def generateToonMoveTrack(self, toon): node = NodePath('tempNode') displacement = Vec3(toon.getPos(render) - self.getPos(render)) displacement.setZ(0) displacement.normalize() movieDistance = self.movieNode.getDistance(self.rotateNode) displacement *= movieDistance node.reparentTo(render) node.setPos(displacement + self.getPos(render)) node.lookAt(self) heading = PythonUtil.fitDestAngle2Src(toon.getH(render), node.getH(render)) hpr = toon.getHpr(render) hpr.setX(heading) finalX = node.getX(render) finalY = node.getY(render) finalZ = node.getZ(render) node.removeNode() toonTrack = Sequence( Parallel( ActorInterval(toon, 'walk', loop=True, duration=1), Parallel( LerpPosInterval(toon, 1.0, Point3(finalX, finalY, toon.getZ(render)), fluid=True, bakeInStart=False)), LerpHprInterval(toon, 1.0, hpr=hpr)), Func(toon.loop, 'neutral')) return toonTrack
def test_windows_setup(self): self.store.storeNode('files/node.bam', '', 'window_r') self.store.storeNode('files/hood_node.bam', '', 'window_l') windows = DNAWindows('windows') x = .1 y = .4 np = NodePath('window_root') code = 'window_l' scale = 1.25 color = Vec4(.842, .167, .361, 1) windows.makeWindows(x, y, np, code, scale, color, self.store, False) # Check if the nodes attributes are correct model = np.find('**/node') self.assertFalse(model.isEmpty()) self.assertEqual(model.getPos(np), Point3(x, 0, y)) self.assertEqual(model.getScale(np), Vec3(scale)) # Now test with flip = True np.removeNode() np = NodePath('window_root') windows.makeWindows(x, y, np, code, scale, color, self.store, True) # Check if the nodes attributes are correct model = np.find('**/hood_node') self.assertFalse(model.isEmpty()) self.assertEqual(model.getPos(np), Point3(x, 0, y)) self.assertEqual(model.getScale(np), Vec3(scale))
def generateToonMoveTrack(self, toon): node = NodePath("tempNode") displacement = Vec3(toon.getPos(render) - self.getPos(render)) displacement.setZ(0) displacement.normalize() movieDistance = self.movieNode.getDistance(self.rotateNode) displacement *= movieDistance node.reparentTo(render) node.setPos(displacement + self.getPos(render)) node.lookAt(self) heading = PythonUtil.fitDestAngle2Src(toon.getH(render), node.getH(render)) hpr = toon.getHpr(render) hpr.setX(heading) finalX = node.getX(render) finalY = node.getY(render) finalZ = node.getZ(render) node.removeNode() toonTrack = Sequence( Parallel( ActorInterval(toon, "walk", loop=True, duration=1), Parallel( LerpPosInterval(toon, 1.0, Point3(finalX, finalY, toon.getZ(render)), fluid=True, bakeInStart=False) ), LerpHprInterval(toon, 1.0, hpr=hpr), ), Func(toon.loop, "neutral"), ) return toonTrack
def cleanup(self): for page in self.catalogItemPages: page.cleanup() self.tabButton.destroy() NodePath.removeNode(self)
def test_windows_setup(self): self.store.storeNode('files/node.bam', '', 'window_r') self.store.storeNode('files/hood_node.bam', '', 'window_l') windows = DNAWindows('windows') x = .1 y = .4 np = NodePath('window_root') code = 'window_l' scale = 1.25 color = Vec4(.842, .167, .361, 1) windows.makeWindows(x, y, np, code, scale, color, self.store, False) # Check if the nodes attributes are correct model = np.find('**/node') self.assertFalse(model.isEmpty()) self.assertEqual(model.getPos(np), Point3(x, 0, y)) self.assertEqual(model.getScale(np), Vec3(scale)) # Now test with flip = True np.removeNode() np = NodePath('window_root') windows.makeWindows(x, y, np, code, scale, color, self.store, True) # Check if the nodes attributes are correct model = np.find('**/hood_node') self.assertFalse(model.isEmpty()) self.assertEqual(model.getPos(np), Point3(x, 0, y)) self.assertEqual(model.getScale(np), Vec3(scale))
class CogdoMaze(MazeBase, DirectObject): def __init__(self, model, data, cellWidth): MazeBase.__init__(self, model, data, cellWidth) self._initWaterCoolers() self.elevatorPos = self.maze.find('**/elevator_loc').getPos(render) self.exitPos = self.maze.find('**/exit_loc').getPos(render) self.maze.flattenStrong() self._clearColor = VBase4(base.win.getClearColor()) self._clearColor.setW(1.0) base.win.setClearColor(VBase4(0.0, 0.0, 0.0, 1.0)) def _initWaterCoolers(self): self._waterCoolers = [] self._waterCoolerRoot = NodePath('WaterCoolerRoot') self._waterCoolerRoot.reparentTo(render) models = [] for model in self.maze.findAllMatches('**/*waterCooler'): model.wrtReparentTo(render) models.append( (model.getPos(self.maze), model.getHpr(self.maze), model)) models.sort() i = 0 for pos, hpr, model in models: wc = CogdoMazeWaterCooler(i, model) wc.wrtReparentTo(self._waterCoolerRoot) wc.setPos(pos) wc.setHpr(hpr) self._waterCoolers.append(wc) i += 1 self._waterCoolerRoot.stash() def getWaterCoolers(self): return self._waterCoolers def isAccessible(self, tX, tY): if tX < 0 or tY < 0 or tX >= self.width or tY >= self.height: return 0 return self.collisionTable[tY][tX] != 1 def destroy(self): for waterCooler in self._waterCoolers: waterCooler.destroy() del self._waterCoolers self._waterCoolerRoot.removeNode() del self._waterCoolerRoot base.win.setClearColor(self._clearColor) del self._clearColor MazeBase.destroy(self) def onstage(self): MazeBase.onstage(self) self._waterCoolerRoot.unstash() def offstage(self): self._waterCoolerRoot.stash() MazeBase.offstage(self)
class CogdoMaze(MazeBase, DirectObject): def __init__(self, model, data, cellWidth): MazeBase.__init__(self, model, data, cellWidth) self._initWaterCoolers() self.elevatorPos = self.maze.find('**/elevator_loc').getPos(render) self.exitPos = self.maze.find('**/exit_loc').getPos(render) self.maze.flattenStrong() self._clearColor = VBase4(base.win.getClearColor()) self._clearColor.setW(1.0) base.win.setClearColor(VBase4(0.0, 0.0, 0.0, 1.0)) def _initWaterCoolers(self): self._waterCoolers = [] self._waterCoolerRoot = NodePath('WaterCoolerRoot') self._waterCoolerRoot.reparentTo(render) models = [] for model in self.maze.findAllMatches('**/*waterCooler'): model.wrtReparentTo(render) models.append((model.getPos(self.maze), model.getHpr(self.maze), model)) models.sort() i = 0 for pos, hpr, model in models: wc = CogdoMazeWaterCooler(i, model) wc.wrtReparentTo(self._waterCoolerRoot) wc.setPos(pos) wc.setHpr(hpr) self._waterCoolers.append(wc) i += 1 self._waterCoolerRoot.stash() def getWaterCoolers(self): return self._waterCoolers def isAccessible(self, tX, tY): if tX < 0 or tY < 0 or tX >= self.width or tY >= self.height: return 0 return self.collisionTable[tY][tX] != 1 def destroy(self): for waterCooler in self._waterCoolers: waterCooler.destroy() del self._waterCoolers self._waterCoolerRoot.removeNode() del self._waterCoolerRoot base.win.setClearColor(self._clearColor) del self._clearColor MazeBase.destroy(self) def onstage(self): MazeBase.onstage(self) self._waterCoolerRoot.unstash() def offstage(self): self._waterCoolerRoot.stash() MazeBase.offstage(self)
class RepairSawingLine: def __init__(self, parent, thickness, color, lineSpawnDist=0.01): self.points = [] self.parent = parent self.thickness = thickness self.color = color self.lineNode = None self.lineDrawer = LineSegs() self.lineDrawer.setThickness(thickness) self.lineSpawnDist = lineSpawnDist self.currentPoint = None self.startPoint = None self.redraw() def redraw(self): self.clearLine() self.lineDrawer.reset() self.lineDrawer.setThickness(self.thickness) self.lineDrawer.setColor(self.color) if len(self.points) > 0: self.lineDrawer.moveTo(self.points[0]) for i in range(1, len(self.points)): p = self.points[i] self.lineDrawer.drawTo(p) self.currentPoint = p self.lineNode = NodePath(self.lineDrawer.create()) self.lineNode.reparentTo(self.parent) self.lineNode.setBin('fixed', 37) self.lineNode.setTransparency(True) def update(self, point): if self.currentPoint == None or ( point - self.currentPoint).length() >= self.lineSpawnDist: self.addPoint(point) self.redraw() def addPoint(self, p): if len(self.points) == 0: self.startPoint = p self.points.append(p) def clearLine(self): if self.lineNode != None: self.lineNode.removeNode() def reset(self): self.clearLine() self.points = [] self.redraw() self.currentPoint = None self.startPoint = None def show(self): self.lineNode.unstash() def hide(self): self.lineNode.stash()
class CogdoMazeHud(): __module__ = __name__ def __init__(self): self._update = None self._initQuestArrow() return def _initQuestArrow(self): matchingGameGui = loader.loadModel( 'phase_3.5/models/gui/matching_game_gui') arrow = matchingGameGui.find('**/minnieArrow') arrow.setScale(Globals.QuestArrowScale) arrow.setColor(*Globals.QuestArrowColor) arrow.setHpr(90, -90, 0) self._questArrow = NodePath('Arrow') arrow.reparentTo(self._questArrow) self._questArrow.reparentTo(render) self.hideQuestArrow() matchingGameGui.removeNode() def destroy(self): self.__stopUpdateTask() self._questArrow.removeNode() self._questArrow = None return def showQuestArrow(self, parent, nodeToPoint, offset=Point3(0, 0, 0)): self._questArrowNodeToPoint = nodeToPoint self._questArrowParent = parent self._questArrowOffset = offset self._questArrow.unstash() self._questArrowVisible = True self.__startUpdateTask() def hideQuestArrow(self): self._questArrow.stash() self.__stopUpdateTask() self._questArrowVisible = False self._questArrowNodeToPoint = None return def __startUpdateTask(self): self.__stopUpdateTask() self._update = taskMgr.add(self._updateTask, 'CogdoMazeHud_Update', 45) def __stopUpdateTask(self): if self._update is not None: taskMgr.remove(self._update) return def _updateTask(self, task): if self._questArrowVisible: self._questArrow.setPos(self._questArrowParent, self._questArrowOffset) self._questArrow.lookAt(self._questArrowNodeToPoint) return Task.cont
def cleanup(self): for item in self.catalogItems: if hasattr(item, 'destroy'): item.destroy() for itemFrame in self.itemFrames: itemFrame.destroy() NodePath.removeNode(self)
def cleanup(self): for item in self.catalogItems: if hasattr(item, 'destroy'): item.destroy() for itemFrame in self.itemFrames: itemFrame.destroy() NodePath.removeNode(self)
class CogdoMazeHud(): __module__ = __name__ def __init__(self): self._update = None self._initQuestArrow() return def _initQuestArrow(self): matchingGameGui = loader.loadModel('phase_3.5/models/gui/matching_game_gui') arrow = matchingGameGui.find('**/minnieArrow') arrow.setScale(Globals.QuestArrowScale) arrow.setColor(*Globals.QuestArrowColor) arrow.setHpr(90, -90, 0) self._questArrow = NodePath('Arrow') arrow.reparentTo(self._questArrow) self._questArrow.reparentTo(render) self.hideQuestArrow() matchingGameGui.removeNode() def destroy(self): self.__stopUpdateTask() self._questArrow.removeNode() self._questArrow = None return def showQuestArrow(self, parent, nodeToPoint, offset = Point3(0, 0, 0)): self._questArrowNodeToPoint = nodeToPoint self._questArrowParent = parent self._questArrowOffset = offset self._questArrow.unstash() self._questArrowVisible = True self.__startUpdateTask() def hideQuestArrow(self): self._questArrow.stash() self.__stopUpdateTask() self._questArrowVisible = False self._questArrowNodeToPoint = None return def __startUpdateTask(self): self.__stopUpdateTask() self._update = taskMgr.add(self._updateTask, 'CogdoMazeHud_Update', 45) def __stopUpdateTask(self): if self._update is not None: taskMgr.remove(self._update) return def _updateTask(self, task): if self._questArrowVisible: self._questArrow.setPos(self._questArrowParent, self._questArrowOffset) self._questArrow.lookAt(self._questArrowNodeToPoint) return Task.cont
def genCollTree(self): tempNode = NodePath('tempNode') toOctreefy = self.geomRoot.copyTo(tempNode) toOctreefy.flattenLight() print "begin octreefy" collRoot = nodeOctree.octreefy(toOctreefy) print "end octreefy" tempNode.removeNode() self.collRoot.removeNode() self.collRoot = collRoot collRoot.reparentTo(self.terrainRoot)
def __init__(self, cameraPos, heightfield, plantModelDict, numberOfTiles, sizeOfTile, usingLod): # storage for the nodepaths used by the plants self.tileDict = dict() self.plantClassNp = render.attachNewNode("plants-%i-%i" % (numberOfTiles, sizeOfTile)) self.usingLod = usingLod # save camera position to create plants around it self.cameraPos = cameraPos # save a instance of the heightfield to access heightinformations of the ground self.heightfield = heightfield # dictionary with the models self.plantModelDict = plantModelDict # number of tiles around the camera self.numberOfTiles = numberOfTiles # size of one of these tiles self.sizeOfTile = sizeOfTile # sum up all distribution numbers of the plantmodelDict self.plantmodelDistributionSum = reduce( add, [self.plantModelDict[key][0] for key in self.plantModelDict.keys()] ) # a dictionary to store the models which need to be faded in self.fadingNodepaths = dict() # convert the egg's to bam's for name, [c, modelName, minS, maxS, distF] in self.plantModelDict.items(): try: tempModelRoot = loader.loadModel(modelName + ".egg") tempModelRoot.flattenStrong() modelRoot = NodePath("modelRoot-%s" % name) tempModelRoot.getChildren().reparentTo(modelRoot) modelRoot.flattenStrong() modelRoot.writeBamFile(modelName + ".bam") modelRoot.removeNode() # for models with different lod's except: for [maxLodDist, minLodDistance, modelName] in modelName: tempModelRoot = loader.loadModel(modelName + ".egg") tempModelRoot.flattenStrong() modelRoot = NodePath("modelRoot-%s" % name) tempModelRoot.getChildren().reparentTo(modelRoot) modelRoot.flattenStrong() modelRoot.writeBamFile(modelName + ".bam") modelRoot.removeNode() # task to create the plants taskMgr.add(self.updatePlants, "updatePlants")
class CarExplosion(object): def __init__(self,carNode): self.ticks=0 self.endOfLife=False self.subExplosions=[] self.carNode=carNode self.containerNode=NodePath("CarExplosion") self.containerNode.reparentTo(carNode) self.containerNode.setPos(0.0,0.0,0.0) subExplosion=CarSubExplosion( -30, 0.3, 0, 0, self.containerNode ) self.subExplosions.append(subExplosion) for i in range(6): self.addSubExplosion() def addSubExplosion(self): subExplosion=CarSubExplosion( int(random.random()*40.0), (random.random()*0.5+0.5)*0.25, random.random()*0.6-0.3, random.random()*0.6-0.3, self.containerNode ) self.subExplosions.append(subExplosion) def advanceTime(self): for subExplosion in self.subExplosions: subExplosion.advanceTime() self.ticks=self.ticks+1 def isComplete(self): isComplete=True for subExplosion in self.subExplosions: if not subExplosion.isComplete(): isComplete=False return isComplete def delete(self): self.containerNode.removeNode() pass
class MinigameHood: def __init__(self, cr): self.cr = cr self.isLoaded = 0 self.dnaStore = DNAStorage() def createHood(self, loadStorage=1): if loadStorage: loadDNAFile(self.dnaStore, "phase_13/dna/storage_party_sz.dna") self.node = loadDNAFile(self.dnaStore, "phase_13/dna/party_sz.dna") if self.node.getNumParents() == 1: self.geom = NodePath(self.node.getParent(0)) self.geom.reparentTo(hidden) else: self.geom = hidden.attachNewNode(self.node) gsg = base.win.getGsg() if gsg: self.geom.prepareScene(gsg) self.geom.setName('minigames') base.hoodBGM = base.loadMusic( "phase_13/audio/bgm/party_original_theme.ogg") base.hoodBGM.setVolume(0.7) base.hoodBGM.setLoop(True) base.hoodBGM.play() self.sky = loader.loadModel("phase_3.5/models/props/TT_sky.bam") self.sky.reparentTo(self.geom) self.sky.setPos(9.15527e-005, -1.90735e-006, 2.6226e-006) self.sky.setH(-90) self.skyUtil = SkyUtil() self.skyUtil.startSky(self.sky) self.geom.reparentTo(render) self.isLoaded = 1 messenger.send("loadedHood") def unloadHood(self): self.isLoaded = 0 self.skyUtil.stopSky() self.geom.removeNode() base.hoodBGM.stop()
class AttackCursor(object): _EDGES = 40 _color = Vec4(0.8, 0.3, 0.3, 1) def __init__(self, parent, entity, foot=1): self.entity = entity self.pos = entity.pos self.attackRad = entity.attackRad self.footRad = foot self._footCircle = LineSegs() self._footCircleNP = NodePath("Movement Foot Circle Node") self._attackRadCircle = LineSegs() self._attackRadCircleNP = NodePath("Attack Radius Node") self._np = NodePath("Movement Node") self.attackables = Entity.EntityManager().getEntitiesWithin( self.pos, self.attackRad) for e in self.attackables: if isinstance( e, Entity.EntityShip ) and e != self.entity and e.owner != self.entity.owner: e.representation.setAttackable() def draw(self): # Draw attack radius attackRadLine = LineSegs() attackRadLine.setThickness(1) attackRadLine.setColor(self._color) attackRadLine.moveTo(self.attackRad, 0, 0) for i in range(self._EDGES + 1): newX = (self.attackRad * math.cos((2 * math.pi / self._EDGES) * i)) newY = (self.attackRad * math.sin((2 * math.pi / self._EDGES) * i)) attackRadLine.drawTo(newX, newY, 0) attackRadGeom = attackRadLine.create() self._attackRadCircleNP = NodePath(attackRadGeom) self._attackRadCircleNP.reparentTo(self._np) # Draw foot circle self._footCircle.setThickness(1) self._footCircle.setColor(self._color) self._footCircle.moveTo(self.footRad, 0, 0) for i in range(self._EDGES): newX = (self.footRad * math.cos((2 * math.pi / self._EDGES) * i)) newY = (self.footRad * math.sin((2 * math.pi / self._EDGES) * i)) self._footCircle.drawTo(newX, newY, 0) self._footCircle.drawTo(self.footRad, 0, 0) footCircleGeom = self._footCircle.create() self._footCircleNP = NodePath(footCircleGeom) self._footCircleNP.reparentTo(self._np) def removeNode(self): for e in self.attackables: if isinstance(e, Entity.EntityShip): e.representation.unsetAttackable() self._footCircleNP.removeNode() self._attackRadCircleNP.removeNode() self._np.removeNode() def __del__(self): self.removeNode()
class CarExplosion(object): def __init__(self, carNode): self.ticks = 0 self.endOfLife = False self.subExplosions = [] self.carNode = carNode self.containerNode = NodePath("CarExplosion") self.containerNode.reparentTo(carNode) self.containerNode.setPos(0.0, 0.0, 0.0) subExplosion = CarSubExplosion(-30, 0.3, 0, 0, self.containerNode) self.subExplosions.append(subExplosion) for i in range(6): self.addSubExplosion() def addSubExplosion(self): subExplosion = CarSubExplosion(int(random.random() * 40.0), (random.random() * 0.5 + 0.5) * 0.25, random.random() * 0.6 - 0.3, random.random() * 0.6 - 0.3, self.containerNode) self.subExplosions.append(subExplosion) def advanceTime(self): for subExplosion in self.subExplosions: subExplosion.advanceTime() self.ticks = self.ticks + 1 def isComplete(self): isComplete = True for subExplosion in self.subExplosions: if not subExplosion.isComplete(): isComplete = False return isComplete def delete(self): self.containerNode.removeNode() pass
class AttackCursor(object): _EDGES = 40 _color = Vec4(0.8, 0.3, 0.3, 1) def __init__(self, parent, entity, foot=1): self.entity = entity self.pos = entity.pos self.attackRad = entity.attackRad self.footRad = foot self._footCircle = LineSegs() self._footCircleNP = NodePath("Movement Foot Circle Node") self._attackRadCircle = LineSegs() self._attackRadCircleNP= NodePath("Attack Radius Node") self._np = NodePath("Movement Node") self.attackables = Entity.EntityManager().getEntitiesWithin(self.pos, self.attackRad) for e in self.attackables: if isinstance(e, Entity.EntityShip) and e != self.entity and e.owner != self.entity.owner: e.representation.setAttackable() def draw(self): # Draw attack radius attackRadLine = LineSegs() attackRadLine.setThickness(1) attackRadLine.setColor(self._color) attackRadLine.moveTo(self.attackRad, 0, 0) for i in range(self._EDGES + 1): newX = (self.attackRad * math.cos((2*math.pi/self._EDGES)*i)) newY = (self.attackRad * math.sin((2*math.pi/self._EDGES)*i)) attackRadLine.drawTo(newX, newY, 0) attackRadGeom = attackRadLine.create() self._attackRadCircleNP = NodePath(attackRadGeom) self._attackRadCircleNP.reparentTo(self._np) # Draw foot circle self._footCircle.setThickness(1) self._footCircle.setColor(self._color) self._footCircle.moveTo(self.footRad, 0, 0) for i in range(self._EDGES): newX = (self.footRad * math.cos((2*math.pi/self._EDGES)*i)) newY = (self.footRad * math.sin((2*math.pi/self._EDGES)*i)) self._footCircle.drawTo(newX, newY, 0) self._footCircle.drawTo(self.footRad, 0, 0) footCircleGeom = self._footCircle.create() self._footCircleNP = NodePath(footCircleGeom) self._footCircleNP.reparentTo(self._np) def removeNode(self): for e in self.attackables: if isinstance(e, Entity.EntityShip): e.representation.unsetAttackable() self._footCircleNP.removeNode() self._attackRadCircleNP.removeNode() self._np.removeNode() def __del__(self): self.removeNode()
class LegendaryFishingGameGUI: def __init__(self, gameObject=None): base.loadingScreen.beginStep('LegendaryGameGUI', 4, 20) self.gameObject = gameObject self.guiImage = loader.loadModel( 'models/minigames/pir_m_gam_fsh_legendaryGui') self.UICompoments = {} self.uiBaseNode = NodePath('baseNode') self.uiBaseNode.reparentTo(aspect2d) self.uiBaseNode.show() self.leftBaseNode = NodePath('leftBaseNode') self.leftBaseNode.reparentTo(base.a2dLeftCenter) self.leftBaseNode.show() self.fishActor = None self.actorAnim = {} self.scaleSize = { InventoryType.Collection_Set11_Part1: 0.059999999999999998, InventoryType.Collection_Set11_Part2: 0.055, InventoryType.Collection_Set11_Part3: 0.12, InventoryType.Collection_Set11_Part4: 0.086999999999999994, InventoryType.Collection_Set11_Part5: 0.080000000000000002 } self.meterFrame = DirectFrame( parent=self.leftBaseNode, frameSize=(-0.29999999999999999, 0.29999999999999999, -1.0, 0.0), frameColor=(1.0, 1.0, 1.0, 0.0), relief=None, state=DGG.DISABLED, pos=(1.0, 0.0, -0.45000000000000001), hpr=(0, 0, 0), scale=(1.3, 0.0, 1.3), image=self.guiImage.find('**/pir_t_gui_fsh_meter'), image_scale=(0.20000000000000001, 0.0, 0.80000000000000004), image_pos=(0, 0, 0), text='', textMayChange=1, text_scale=PiratesGuiGlobals.TextScaleTitleLarge, text_pos=(-0.55000000000000004, 0.10000000000000001), text_shadow=PiratesGuiGlobals.TextShadow) self.UICompoments['meterFrame'] = self.meterFrame self.fishingRod = DirectFrame( parent=self.meterFrame, frameSize=(-0.29999999999999999, 0.29999999999999999, -1.0, 0.0), relief=None, state=DGG.DISABLED, pos=FishingGlobals.fishingRodScreenPosition, image=self.guiImage.find('**/pir_t_gui_fsh_fullRod'), image_scale=(1.0, 0.0, 0.125), image_pos=(0.20000000000000001, 0, 0)) self.fishingRod.setR(FishingGlobals.fishingRodInitSlope) self.UICompoments['fishingRod'] = self.fishingRod base.loadingScreen.tick() self.fishingHandleBaseFrame = DirectFrame( parent=self.uiBaseNode, frameSize=(-0.29999999999999999, 0.29999999999999999, -1.5, 1.5), frameColor=(1.0, 1.0, 1.0, 0.0), relief=None, state=DGG.DISABLED, pos=(0.0, 0.0, 0.0), hpr=(0, 0, 0), scale=(0.71999999999999997, 0.0, 0.71999999999999997), image=self.guiImage.find('**/pir_t_gui_fsh_partialRod'), image_scale=(3.7999999999999998, 0.0, 1.8999999999999999), image_pos=(0, 0, 0), image_hpr=(0.0, 0.0, 0)) self.fishingHandleBaseFrame.hide() self.UICompoments[ 'fishingHandleBaseFrame'] = self.fishingHandleBaseFrame self.fishingHandle = DirectFrame( parent=self.fishingHandleBaseFrame, frameSize=(-0.080000000000000002, 0.080000000000000002, -0.20000000000000001, 0.20000000000000001), relief=None, state=DGG.DISABLED, pos=(-0.10000000000000001, 0.0, -0.050000000000000003), hpr=(0, 0, 0), image=self.guiImage.find('**/pir_t_gui_fsh_handleArm'), image_scale=(1.0, 0.0, 1.0), image_pos=(-0.042000000000000003, 0, -0.115), image_hpr=(0.0, 0.0, 0)) self.UICompoments['fishingHandle'] = self.fishingHandle self.arrowImage = DirectFrame( parent=self.fishingHandleBaseFrame, frameSize=(-0.40000000000000002, 0.40000000000000002, -0.40000000000000002, 0.40000000000000002), relief=None, state=DGG.DISABLED, pos=(0.0, 0.0, 0.0), hpr=(0, 0, 0), scale=(1.2, 0.0, 1.2), image=self.guiImage.find('**/pir_t_gui_fsh_arrow'), image_scale=(1.0, 0.0, 1.0), image_pos=(0.0, 0, 0.0), image_hpr=(0.0, 0.0, 0.0)) self.arrowImage.hide() self.UICompoments['arrowImage'] = self.arrowImage btnGeom = (self.guiImage.find('**/pir_t_gui_fsh_handle'), self.guiImage.find('**/pir_t_gui_fsh_handle'), self.guiImage.find('**/pir_t_gui_fsh_handleOn')) self.fishingHandleButton = GuiButton(pos=(-0.29999999999999999, 0, -0.55000000000000004), hpr=(0, 0, 0), scale=0.45000000000000001, image=btnGeom, image_pos=(0, 0, 0), image_scale=1.0, sortOrder=2) self.fishingHandleButton.bind(DGG.B1PRESS, self.handleButtonClicked) self.fishingHandleButton.reparentTo(self.fishingHandle) self.UICompoments['fishingHandleButton'] = self.fishingHandleButton self.fishingHandleBaseFrame.setTransparency(TransparencyAttrib.MAlpha) self.meterFrame.setTransparency(TransparencyAttrib.MAlpha) self.lineOneTransitTextNode = TextNode('lineOneTransitText') self.lineOneTransitTextNode.setFont(PiratesGlobals.getPirateFont()) self.lineOneTransitTextNode.setText('') self.lineOneTransitTextNode.setAlign(TextNode.ACenter) self.lineOneTransitTextNode.setTextColor(1.0, 1.0, 1.0, 0.5) self.lineOneTransitTextNodePath = NodePath(self.lineOneTransitTextNode) self.lineOneTransitTextNodePath.setPos(0.0, 0.0, -0.80000000000000004) self.lineOneTransitTextNodePath.setScale(0.34999999999999998, 0.34999999999999998, 0.34999999999999998) self.lineOneTransitTextNodePath.reparentTo(self.uiBaseNode) self.lineOneTransitTextNodePath.hide() self.UICompoments[ 'lineOneTransitText'] = self.lineOneTransitTextNodePath self.lineTwoTransitTextNode = TextNode('lineTwoTransitText') self.lineTwoTransitTextNode.setFont(PiratesGlobals.getPirateFont()) self.lineTwoTransitTextNode.setText('') self.lineTwoTransitTextNode.setAlign(TextNode.ACenter) self.lineTwoTransitTextNode.setTextColor(1.0, 1.0, 1.0, 0.5) self.lineTwoTransitTextNodePath = NodePath(self.lineTwoTransitTextNode) self.lineTwoTransitTextNodePath.setPos(-0.40000000000000002, 0.0, -0.94999999999999996) self.lineTwoTransitTextNodePath.setScale(0.12, 0.12, 0.12) self.lineTwoTransitTextNodePath.reparentTo(self.uiBaseNode) self.lineTwoTransitTextNodePath.hide() self.UICompoments[ 'lineTwoTransitText'] = self.lineTwoTransitTextNodePath base.loadingScreen.tick() self.test_guiImage = loader.loadModel('models/gui/toplevel_gui') self.buttonIcon = ( self.test_guiImage.find('**/treasure_chest_closed'), self.test_guiImage.find('**/treasure_chest_closed'), self.test_guiImage.find('**/treasure_chest_closed_over')) self.winImagePanel = GuiPanel.GuiPanel('', 2.6000000000000001, 1.8999999999999999, True) self.winImagePanel.setPos(-1.3, 0.0, -0.94999999999999996) self.winImagePanel.reparentTo(self.uiBaseNode) self.winImagePanel.background = OnscreenImage( parent=self.winImagePanel, scale=(2.3999999999999999, 0, 1.8), image=self.guiImage.find('**/pir_t_gui_fsh_posterBackground'), hpr=(0, 0, 0), pos=(1.3, 0, 0.94999999999999996)) self.winImagePanel.setBin('gui-popup', -4) self.winTitleTextNode = TextNode('winTitleTextNode') self.winTitleTextNode.setText('Congratulations!') self.winTitleTextNode.setAlign(TextNode.ACenter) self.winTitleTextNode.setFont(PiratesGlobals.getPirateFont()) self.winTitleTextNode.setTextColor(0.23000000000000001, 0.089999999999999997, 0.029999999999999999, 1.0) self.winTitleTextNodePath = NodePath(self.winTitleTextNode) self.winTitleTextNodePath.setPos(1.3500000000000001, 0.0, 1.6699999999999999) self.winTitleTextNodePath.setScale(0.17999999999999999) self.winTitleTextNodePath.reparentTo(self.winImagePanel) self.wholeStoryTextNode = TextNode('storyTextNode') self.wholeStoryTextNode.setText('') self.wholeStoryTextNode.setWordwrap(19.0) self.wholeStoryTextNode.setTextColor(0.23000000000000001, 0.089999999999999997, 0.029999999999999999, 1.0) self.wholeStoryTextNodePath = NodePath(self.wholeStoryTextNode) self.wholeStoryTextNodePath.setPos(0.33000000000000002, 0.0, 1.6399999999999999) self.wholeStoryTextNodePath.setScale(0.050000000000000003) self.wholeStoryTextNodePath.reparentTo(self.winImagePanel) self.winImagePanel.closeButton[ 'command'] = self.closeDialogGotNextState self.winImagePanel.closeButton['extraArgs'] = [ 'winImagePanel', 'FarewellLegendaryFish', False ] self.UICompoments['winImagePanel'] = self.winImagePanel self.winImagePanel.hide() self.luiCloseDialogSequence = Sequence() self.arrowImageRotationInterval = LerpHprInterval( self.arrowImage, 2.2000000000000002, self.arrowImage.getHpr() + Point3(0.0, 0.0, 280.0), self.arrowImage.getHpr()) self.luiArrowRotatingSequence = Sequence( Func(self.showGui, ['arrowImage']), Parallel(Func(self.arrowImageRotationInterval.start), Wait(2.2000000000000002)), Func(self.hideGui, ['arrowImage']), Func(self.arrowImage.setHpr, self.arrowImage.getHpr() + Point3(0.0, 0.0, 5.0)), name=self.gameObject.distributedFishingSpot.uniqueName( 'luiArrowRotatingSequence')) self.lineOneColorChange = LerpColorScaleInterval( self.lineOneTransitTextNodePath, FishingGlobals.legendaryTransitionTextDuration, (1.0, 1.0, 1.0, 0.0), (1.0, 1.0, 1.0, 1.0), blendType='easeOut') self.lineOnePosChange = LerpPosInterval( self.lineOneTransitTextNodePath, FishingGlobals.legendaryTransitionTextDuration, (0.0, 0.0, -0.20000000000000001), (0.0, 0.0, -0.80000000000000004), blendType='easeOut') self.lineTwoCholorChange = LerpColorScaleInterval( self.lineTwoTransitTextNodePath, FishingGlobals.legendaryTransitionTextDuration, (1.0, 1.0, 1.0, 1.0), (1.0, 1.0, 1.0, 1.0), blendType='easeOut') self.lineTwoPosChange = LerpPosInterval( self.lineTwoTransitTextNodePath, FishingGlobals.legendaryTransitionTextDuration, (0.0, 0.0, -0.32000000000000001), (0.0, 0.0, -0.94999999999999996), blendType='easeOut') self.transitionTextMovingSequence = Sequence( Func(self.lineOneTransitTextNodePath.show), Func(self.lineTwoTransitTextNodePath.show), Parallel(self.lineOnePosChange, self.lineTwoPosChange, self.lineOneColorChange, self.lineTwoCholorChange), Func(self.lineOneTransitTextNodePath.hide), Func(self.lineTwoTransitTextNodePath.hide), name=self.gameObject.distributedFishingSpot.uniqueName( 'transitionTextMovingSequence')) self.meterFadeInInterval = Sequence( Func(self.meterFrame.show), LerpColorScaleInterval( self.meterFrame, FishingGlobals.legendaryTransitionTextDuration, colorScale=(1.0, 1.0, 1.0, 1.0), startColorScale=(1.0, 1.0, 1.0, 0.0), blendType='easeOut'), name='FadeInLegendaryMeter') self.meterFadeOutInterval = Sequence(LerpColorScaleInterval( self.meterFrame, FishingGlobals.legendaryTransitionTextDuration, colorScale=(1.0, 1.0, 1.0, 0.0), startColorScale=(1.0, 1.0, 1.0, 1.0), blendType='easeOut'), Func(self.meterFrame.hide), name='FadeOutLegendaryMeter') self.rodFadeInInterval = Sequence( Func(self.fishingHandleBaseFrame.show), LerpColorScaleInterval( self.fishingHandleBaseFrame, FishingGlobals.legendaryTransitionTextDuration, colorScale=(1.0, 1.0, 1.0, 1.0), startColorScale=(1.0, 1.0, 1.0, 0.0), blendType='easeOut'), name='FadeInLegendaryRodInterface') self.rodFadeOutInterval = Sequence( LerpColorScaleInterval( self.fishingHandleBaseFrame, FishingGlobals.legendaryTransitionTextDuration, colorScale=(1.0, 1.0, 1.0, 0.0), startColorScale=(1.0, 1.0, 1.0, 1.0), blendType='easeOut'), Func(self.fishingHandleBaseFrame.hide), name='FadeOutLegendaryRodInterface') base.loadingScreen.tick() smallScale = self.fishingHandleButton['scale'] bigScale = self.fishingHandleButton['scale'] * 1.2 self.buttonGrowUpInterval = LerpScaleInterval(self.fishingHandleButton, 1.0, bigScale, smallScale) self.luiFightTransitSequence = Sequence( Parallel(Func(self.fishingHandleBaseFrame.show), Func(self.meterFadeOutInterval.start), Func(self.rodFadeInInterval.start), Func(self.buttonGrowUpInterval.start)), Wait(1.0), Func(self.meterFrame.hide), name=self.gameObject.distributedFishingSpot.uniqueName( 'luiFightTransitSequence')) self.luiReelTransitSequence = Sequence( Parallel(Func(self.fishingHandleBaseFrame.show), Func(self.meterFadeOutInterval.start), Func(self.rodFadeInInterval.start)), Wait(1.0), Func(self.meterFrame.hide), name=self.gameObject.distributedFishingSpot.uniqueName( 'luiReelTransitSequence')) self.luiStruggleTransitSequence = Sequence( Parallel(Func(self.meterFrame.show), Func(self.resetFishingRod), self.meterFadeInInterval, self.rodFadeOutInterval), Wait(1.0), Func(self.fishingHandleBaseFrame.hide), name=self.gameObject.distributedFishingSpot.uniqueName( 'luiStruggleTransitSequence')) self.meterFadeOutInterval.start() self.rodFadeOutInterval.start() self.hideAllGUI() base.loadingScreen.endStep('LegendaryGameGUI') def hideAllGUI(self): self.uiBaseNode.reparentTo(hidden) self.leftBaseNode.reparentTo(hidden) def showAllGUI(self): self.uiBaseNode.reparentTo(aspect2d) self.leftBaseNode.reparentTo(base.a2dLeftCenter) def hideGui(self, nameList): for ui in nameList: self.UICompoments[ui].hide() def showGui(self, nameList): for ui in nameList: self.UICompoments[ui].show() def destroy(self): self.arrowImageRotationInterval.pause() self.arrowImageRotationInterval.clearToInitial() self.luiArrowRotatingSequence.pause() self.luiArrowRotatingSequence.clearToInitial() self.luiCloseDialogSequence.pause() self.luiCloseDialogSequence.clearToInitial() totalKey = self.UICompoments.keys() for iKey in totalKey: del self.UICompoments[iKey] self.fishingHandle = None self.fishingHandleButton = None self.fishingRod.removeNode() self.leftBaseNode.removeNode() self.uiBaseNode.removeNode() if self.fishActor: self.fishActor.destroy() self.fishActor = None def handleButtonClicked(self, mouseKey): if self.gameObject.lfgFsm.getCurrentOrNextState() in ['CatchIt']: self.gameObject.lfgFsm.request('Transition', 'Struggle') self.gameObject.sfx['legendaryGreen'].play() def setTransitionText(self, state): self.lineOneTransitTextNode.setText( PLocalizer.LegendaryFishingGui[state][0]) self.lineTwoTransitTextNode.setText( PLocalizer.LegendaryFishingGui[state][1]) def resetInterval(self): self.transitionTextMovingSequence.pause() self.transitionTextMovingSequence.clearToInitial() self.lineOneColorChange.pause() self.lineOneColorChange.clearToInitial() self.lineOnePosChange.pause() self.lineOnePosChange.clearToInitial() self.lineTwoCholorChange.pause() self.lineTwoCholorChange.clearToInitial() self.lineTwoPosChange.pause() self.lineTwoPosChange.clearToInitial() self.luiReelTransitSequence.pause() self.luiReelTransitSequence.clearToInitial() self.luiStruggleTransitSequence.pause() self.luiStruggleTransitSequence.clearToInitial() self.luiFightTransitSequence.pause() self.luiFightTransitSequence.clearToInitial() self.buttonGrowUpInterval.pause() self.buttonGrowUpInterval.clearToInitial() self.meterFadeOutInterval.pause() self.meterFadeOutInterval.clearToInitial() self.rodFadeInInterval.pause() self.rodFadeInInterval.clearToInitial() self.meterFadeInInterval.pause() self.meterFadeInInterval.clearToInitial() self.rodFadeOutInterval.pause() self.rodFadeOutInterval.clearToInitial() def fightingTransit(self): self.luiFightTransitSequence.start() def reelTransit(self): self.luiReelTransitSequence.start() def struggleTransit(self): self.luiStruggleTransitSequence.start() def resetFishingRod(self): self.fishingRod.setR(FishingGlobals.fishingRodInitSlope) def showWinImage(self, fish): self.hideGui(['meterFrame', 'fishingHandleBaseFrame']) result = fish.myData['name'].split(' ') fileName = str(result[0]).capitalize() imgName = 'pir_t_gui_fsh_render%s' % fileName self.actorAnim[ 'swimIdleOpposite'] = 'models/char/pir_a_gam_fsh_%s_%s.bam' % ( fish.myData['model'], 'swimIdleOpposite') self.fishActor = BlendActor( 'models/char/pir_r_gam_fsh_%s.bam' % fish.myData['model'], self.actorAnim, FishingGlobals.defaultFishBlendTime, FishingGlobals.fishBlendTimeDict) self.fishActor.setPlayRate( fish.myData['speed'] * fish.myData['swimAnimationMultiplier'], 'swimIdleOpposite') self.fishActor.changeAnimationTo('swimIdleOpposite') self.fishActor.reparentTo(self.winImagePanel) self.fishActor.setScale(self.scaleSize[fish.myData['id']]) self.fishActor.setPos(1.7, 0, 1.0) self.fishActor.setHpr(0, 0, 35) self.fishActor.setDepthWrite(True) self.fishActor.setDepthTest(True) self.wholeStoryTextNode.setText( PLocalizer.LegendSelectionGui['wholeStory'][fish.myData['id']]) self.winImagePanel.show() def closeDialogGotNextState(self, object, targetState, ifFadeInAgain): if self.fishActor: self.fishActor.destroy() self.fishActor = None self.luiCloseDialogSequence = Sequence( Func(self.gameObject.distributedFishingSpot.fadeOut), Wait(0.40000000000000002), Func(self.UICompoments[object].hide), Func(self.gameObject.lfgFsm.request, targetState), name=self.gameObject.distributedFishingSpot.uniqueName( 'luiCloseDialogSequence')) self.luiCloseDialogSequence.start() def updateStruggleTimerText(self, time, percent): self.meterFrame['text'] = str(time) self.meterFrame['text_fg'] = (1.0 - percent, percent, 0.0, 1.0)
class FishLure(NodePath): def __init__(self, gameObject, type): NodePath.__init__(self, "FishingLure_%s" % type) self.gameObject = gameObject self.type = type self.initLureModel() if FishingGlobals.wantDebugCollisionVisuals: self.initCollision() self.initLureHelpText() self.setLightOff() def initLureModel(self): self.lureModel = NodePath("lure") self.currentLureType = "regular" self.lureAttractRadius = FishingGlobals.lureTypeToAttractRadius[self.currentLureType] self.lureModel = loader.loadModel(FishingGlobals.lureTypeToModel[self.currentLureType]) self.lureModel.setScale(2.0) self.lureModel.reparentTo(self) self.lureModel.setDepthWrite(False) self.lureModel.setDepthTest(True) self.lureModel.setBin("ground", 25) self.mainGui = loader.loadModel("models/gui/gui_main") def initCollision(self): self.lureCollisionVisual = loader.loadModel("models/ammunition/cannonball") self.lureCollisionVisual.setTransparency(1) self.lureCollisionVisual.setColor(0.0, 0.0, 1.0, 0.29999999999999999) self.lureCollisionVisual.setScale(self.lureAttractRadius) self.lureCollisionVisual.reparentTo(self) self.lureCollisionVisual.hide() def initLureHelpText(self): self.helpTextNode = TextNode("fishBitingIcon") self.helpTextNodePath = NodePath(self.helpTextNode) self.helpTextNodePath.setPos(0.0, 0.0, 0.69999999999999996) self.helpTextNode.setText(" ") self.helpTextNode.setAlign(TextNode.ACenter) self.helpTextNode.setFont(PiratesGlobals.getPirateFont()) self.helpTextNode.setTextColor(1.0, 1.0, 1.0, 1.0) self.helpTextNodePath.reparentTo(self) self.helpTextNodePath.setBillboardPointEye() self.helpTextNodePath.setBin("fishingGame", 10) self.helpTextNodePath.hide() def enableLureGlow(self, glowType): self.lureGlow = LureGlow.getEffect() if self.lureGlow: if self.gameObject.fishManager.activeFish is not None: self.lureGlow.reparentTo(self.gameObject.fishManager.activeFish.mouthJoint) else: self.lureGlow.reparentTo(self) self.lureGlow.effectColor = _glowColors[glowType] self.lureGlow.setShaderOff() self.lureGlow.setBin("fishingGame", 5) self.lureGlow.play() def showHelpText(self, textToShow): taskMgr.remove(self.gameObject.distributedFishingSpot.uniqueName("ClearLureText")) if textToShow is None: self.helpTextNode.setText(" ") self.helpTextNodePath.hide() elif self.gameObject.fishManager.activeFish is not None: self.helpTextNodePath.setScale( FishingGlobals.fishSizeToHelpTextScale[self.gameObject.fishManager.activeFish.myData["size"]] ) else: self.helpTextNodePath.setScale(1.0) self.helpTextNode.setText(textToShow) self.helpTextNodePath.show() taskMgr.doMethodLater( FishingGlobals.lureHelpTextDuration, self.showHelpText, name=self.gameObject.distributedFishingSpot.uniqueName("ClearLureText"), extraArgs=[None], ) def setLureType(self, type): self.currentLureType = type if type == None: self.lureModel.hide() self.gameObject.gui.setTackleBoxPulse(True) elif type == "regular": self.gameObject.gui.setTackleBoxPulse(False) self.currentLureType = type self.lureModel.removeNode() self.lureAttractRadius = FishingGlobals.lureTypeToAttractRadius[type] self.lureModel = loader.loadModel(FishingGlobals.lureTypeToModel[type]) self.lureModel.setScale(2.0) self.lureModel.reparentTo(self) self.lureModel.setDepthWrite(False) self.lureModel.setDepthTest(True) self.lureModel.setBin("ground", 25) elif type == "legendary": self.gameObject.gui.setTackleBoxPulse(False) self.currentLureType = type self.lureModel.removeNode() self.lureAttractRadius = FishingGlobals.lureTypeToAttractRadius[type] self.lureModel = loader.loadModel(FishingGlobals.lureTypeToModel[type]) self.lureModel.setScale(2.0) self.lureModel.reparentTo(self) self.lureModel.setDepthWrite(False) self.lureModel.setDepthTest(True) self.lureModel.setBin("ground", 25) def showCollisionVisuals(self): if FishingGlobals.wantDebugCollisionVisuals: self.lureCollisionVisual.show() def hideCollisionVisuals(self): if FishingGlobals.wantDebugCollisionVisuals: self.lureCollisionVisual.hide() def requestPitch(self, fish): offset = fish.getPos() - self.getPos() if fish.getX() < self.getX(): return math.degrees(math.atan2(offset.getZ(), -offset.getX())) else: return math.degrees(math.atan2(-offset.getZ(), offset.getX())) def resetLureModel(self): self.lureModel.reparentTo(self) self.lureModel.show() self.lureModel.setPosHpr(0, 0, 0, 0, 0, 0.0) if self.currentLureType == None: self.lureModel.hide() self.gameObject.gui.setTackleBoxPulse(True) else: self.gameObject.gui.setTackleBoxPulse(False) def destroy(self): self.lureModel.removeNode() self.removeNode()
class Entity(DirectObject, object): def __init__(self, model = None): self.prime = None if model != None: self.set_model(model) def get_model(self): return self.prime def set_model(self, model): if model != None: if isinstance(model, PandaNode): self.prime = NodePath(model) elif isinstance(model, NodePath): self.prime = model else: if Filename(model).exists(): self.model = Filename(model).getBasenameWoExtension() path = model else: if isinstance(model, Filename): self.model = model.getBasenameWoExtension() path = model.getFullpath() else: path = APP_PATH + model print "path: ", path if Filename(path).exists(): pass elif Filename(path + ".bam").exists(): path += ".bam" elif Filename(path + ".bam.pz").exists(): path += ".bam.pz" elif Filename(path + ".egg").exists(): path += ".egg" elif Filename(path + ".egg.pz").exists(): path += ".egg.pz" elif Filename(path + ".x").exists(): path += ".x" else: print ":object(error): can't find model", model, "!" # Probably shouldn't exit because of this sys.exit(1) self.model = model self.prime = base.loader.loadModel(path) if self.prime == None: print ":object(error): can't load model", model, "!" # Probably shouldn't exit because of this sys.exit(1) def getX(self): return self.prime.getX(base.render) def getY(self): return self.prime.getY(base.render) def getZ(self): return self.prime.getZ(base.render) def getH(self): return self.prime.getH(base.render) def getP(self): return self.prime.getP(base.render) def getR(self): return self.prime.getR(base.render) def getSx(self): return self.prime.getSx(base.render) def getSy(self): return self.prime.getSy(base.render) def getSz(self): return self.prime.getSz(base.render) def getPos(self): return self.prime.getPos(base.render) def getHpr(self): return self.prime.getHpr(base.render) def getScale(self): return self.prime.getScale(base.render) def getCollideMask(self): return self.prime.getCollideMask() def getTransparency(self): return self.prime.getTransparency() def getTwoSided(self): return self.prime.getTwoSided() def getParent(self): return self.prime.getParent() def setX(self, *v): self.prime.setX(*v) def setY(self, *v): self.prime.setY(*v) def setZ(self, *v): self.prime.setZ(*v) def setH(self, *v): self.prime.setH(*v) def setP(self, *v): self.prime.setP(*v) def setR(self, *v): self.prime.setR(*v) def setSx(self, *v): self.prime.setSx(*v) def setSy(self, *v): self.prime.setSy(*v) def setSz(self, *v): self.prime.setSz(*v) def setPos(self, *v): self.prime.setPos(*v) def setHpr(self, *v): self.prime.setHpr(*v) def setScale(self, *v): self.prime.setScale(*v) def setCollideMask(self, *v): self.prime.setCollideMask(*v) def setTransparency(self, *v): self.prime.setTransparency(*v) def setTwoSided(self, *v): self.prime.setTwoSided(*v) def removeNode(self): self.prime.removeNode() def reparentTo(self, parent): if isinstance(parent, Entity): parent = parent.prime if isinstance(parent, str): if parent.startswith("render/"): parent = parent[7:] tv = parent parent = base.render.find(tv) if parent == NodePath(): parent = base.render.find("**/" + tv) if parent != NodePath() and parent != None: self.prime.reparentTo(parent) def wrtReparentTo(self, parent): if isinstance(parent, Entity): parent = parent.prime if isinstance(parent, str): if parent.startswith("render/"): parent = parent[7:] tv = parent parent = base.render.find(tv) if parent == NodePath(): parent = base.render.find("**/" + tv) if parent != NodePath(): self.prime.reparentTo(parent) def attachTo(self, parent): """This attaches the object to another object/nodepath. The caller object stays at the same place, with the same scale and rotation, but they become relative to the other object/nodepath. This is useful with for example a character that steps onto a moving ship or so.""" if isinstance(parent, Entity): parent = parent.prime if isinstance(parent, str): if(parent.startswith("render/")): parent = parent[7:] tv = parent parent = base.render.find(tv) if(parent == NodePath()): parent = base.render.find("**/" + tv) if(parent != NodePath()): self.prime.setPos(self.prime.getPos(parent)) self.prime.setHpr(self.prime.getHpr(parent)) self.prime.setScale(self.prime.getScale(parent)) self.prime.reparentTo(parent) def hide(self): self.prime.hide() def show(self): self.prime.show() def __del__(self): try: if isinstance(self.prime, NodePath): self.prime.removeNode() except AttributeError: pass def __getstate__(self): return [self.model, self.getX(), self.getY(), self.getZ(), self.getH(), self.getP(), self.getR(), self.getSx(), self.getSy(), self.getSz(), self.getCollideMask().getWord(), self.getTransparency(), self.getTwoSided(), str(self.getParent())] def __setstate__(self, p): if len(p) < 14: print ":object(error): This state is not compatible with this version!" sys.exit(1) self.setModel(p[0]) self.setX(p[1]) self.setY(p[2]) self.setZ(p[3]) self.setH(p[4]) self.setP(p[5]) self.setR(p[6]) self.setSx(p[7]) self.setSy(p[8]) self.setSz(p[9]) self.setCollideMask(BitMask32(p[10])) self.setTransparency(p[11]) self.setTwoSided(p[12]) self.reparentTo(p[13])
class CameraManager: nextID = 0 def __init__(self, cameraNP): self.cameraNP = cameraNP self.id = CameraManager.nextID CameraManager.nextID += 1 self.otherNP = render self.lookAtNP = NodePath('CameraManager%d.lookAtNP' % self.id) self.lookAtEnabled = False self.targetPos = Point3(0.0, 0.0, 0.0) self.targetLookAtPos = Point3(0.0, 1.0, 0.0) self.enabled = False self.rate = 10.0 def destroy(self): if self.enabled: self.setEnabled(False) self.lookAtNP.removeNode() del self.lookAtNP del self.targetPos del self.targetLookAtPos del self.otherNP def setEnabled(self, enabled): if enabled != self.enabled: if enabled: taskMgr.add(self.updateTask, 'CameraManager%d.update' % self.id) else: taskMgr.remove('CameraManager%d.update' % self.id) self.enabled = enabled def setTargetPos(self, p): self.targetPos = p def setPos(self, p): self.targetPos = p self.cameraNP.setPos(self.otherNP, p) def setTargetLookAtPos(self, p): self.lookAtEnabled = True self.targetLookAtPos = p def setLookAtPos(self, p): self.lookAtEnabled = True self.targetLookAtPos = p self.lookAtNP.setPos(p) def setHpr(self, hpr): self.lookAtEnabled = False self.cameraNP.setHpr(self.otherNP, hpr) def updateTask(self, task): newCameraPos = self.rateInterpolate(self.cameraNP.getPos(self.otherNP), self.targetPos) self.cameraNP.setPos(self.otherNP, newCameraPos) if self.lookAtEnabled: newLookAtPos = self.rateInterpolate(self.lookAtNP.getPos(self.otherNP), self.targetLookAtPos) self.lookAtNP.setPos(self.otherNP, newLookAtPos) self.cameraNP.lookAt(self.lookAtNP) return task.cont def rateInterpolate(self, currentPos, targetPos): dt = globalClock.getDt() vec = currentPos - targetPos return targetPos + vec * inverse_e ** (dt * self.rate)
def createSector(self, sectorId): (sectorX, sectorY) = sectorId # print "creating sector %s" % str(sectorId) # init seed depending on quadrant we are currently in random.seed(sectorId) if self.usingLod: plantLodNpChilds = [NodePath("lod-0-%s" % str(sectorId)), NodePath("lod-1-%s" % str(sectorId))] else: tileNode = self.plantClassNp.attachNewNode("tileNode-%s" % str(sectorId)) tempTileNode = NodePath("tempTileNode-%s" % str(sectorId)) # create each plant with the given chance in the sector for ( plantName, [plantChance, plantModel, plantMinScale, plantScaleVariance, [noiseFunc, distFunc, distParams]], ) in self.plantModelDict.items(): # maximum number of plants of this type averagePlantCount = (plantChance / 100.0) * self.sizeOfTile ** 2 # well use ceil, if not some plants may never be generated plantCount = math.ceil(averagePlantCount) distFuncResultAccumulated = 0.0 # print "planning to create %i plants" % plantCount [commented by Finn] # creating plantCount number of plants placedPlantCounter = 0 for plantId in xrange(int(plantCount)): # select position the plant will have posX = random.randint(0, self.sizeOfTile) + (sectorX * self.sizeOfTile) posY = random.randint(0, self.sizeOfTile) + (sectorY * self.sizeOfTile) # get z position of ground posZ = self.heightfield.get_elevation([posX, posY]) # the absolue world position of the plant absoluteWorldPosition = Vec3(posX, posY, posZ) # decide if we want to place this plant based on the noise function noiseFuncResult = noiseFunc(posX, posY) distFuncResult = distFunc(noiseFuncResult, *distParams) # make sure the plants are placed evenly distFuncResultAccumulated += distFuncResult if distFuncResultAccumulated > 1.0: placedPlantCounter += 1 # print "plant" # place a plant distFuncResultAccumulated -= 1.0 # select scale & rotation of plant scale = random.random() rotation = random.randint(0, 360) # load model if self.usingLod: # save that we are using lod, we cant flatten if we are # usingLod = True # setup lod nodepath # plantLodNp = NodePath(FadeLODNode('lod')) # plantLodNp.reparentTo(self.plantClassNp) i = 0 for [maxLodDist, minLodDistance, lodModelName] in plantModel: # print "creating lod %i of plant %s" % (i, plantName) [commented by Finn] tempPlantNp = loader.loadModel(lodModelName + ".egg") plantNp = NodePath("model-%s" % str(absoluteWorldPosition)) tempPlantNp.getChildren().reparentTo(plantNp) # flatten the nodepath # plantNp.flattenStrong() # set position of plant plantNp.setPos(absoluteWorldPosition) plantNp.setHpr(rotation, 0, 0) finalScale = plantMinScale + scale * plantScaleVariance plantNp.setScale(finalScale) # add plant to tile plantNp.reparentTo(plantLodNpChilds[i]) # i += 1 else: # plantNp = loader.loadModelCopy( plantModel+".egg" ) # plantNp.reparentTo( tileNode ) tempPlantNp = loader.loadModelCopy(plantModel + ".egg") plantNp = NodePath("model-%s" % str(absoluteWorldPosition)) tempPlantNp.getChildren().reparentTo(plantNp) tempPlantNp.removeNode() # flatten the nodepath # plantNp.flattenStrong() # add plant to tile plantNp.reparentTo(tempTileNode) # set position of plant plantNp.setPos(absoluteWorldPosition) plantNp.setHpr(rotation, 0, 0) finalScale = plantMinScale + scale * plantScaleVariance plantNp.setScale(finalScale) # print "planted %i plants" % placedPlantCounter # flatten the tile if not using lod if self.usingLod: plantLodNpChilds[0].flattenStrong() plantLodNpChilds[1].flattenStrong() fadeLodNode = FadeLODNode("lod-%s" % str(sectorId)) absolutePosX = (sectorX * self.sizeOfTile) + self.sizeOfTile / 2.0 absolutePosY = (sectorY * self.sizeOfTile) + self.sizeOfTile / 2.0 absolutePosZ = self.heightfield.get_elevation([absolutePosX, absolutePosY]) fadeLodNode.setCenter(Point3(absolutePosX, absolutePosY, absolutePosZ)) plantLodNp = NodePath(fadeLodNode) # plantLodNp = NodePath('lod-%s' % str(sectorId)) plantLodNpChilds[0].reparentTo(plantLodNp) plantLodNp.node().addSwitch(9999, self.sizeOfTile * 2.0) plantLodNpChilds[1].reparentTo(plantLodNp) plantLodNp.node().addSwitch(self.sizeOfTile * 2.0, 0) self.tileDict[sectorId] = plantLodNp plantLodNp.reparentTo(self.plantClassNp) if FADEIN: self.makeFadeIn(plantLodNp) else: # reassign plants to sectorNode tempTileNode.getChildren().reparentTo(tileNode) tempTileNode.removeNode() tempTileNode = None # tileNode.flattenMedium() tileNode.flattenStrong() tileNode.reparentTo(self.plantClassNp) self.tileDict[sectorId] = tileNode if FADEIN: self.makeFadeIn(tileNode)
class CogdoExecutiveSuiteIntro(CogdoGameMovie): notify = DirectNotifyGlobal.directNotify.newCategory('CogdoExecutiveSuiteIntro') introDuration = 7 cameraMoveDuration = 3 def __init__(self, shopOwner): CogdoGameMovie.__init__(self) self._shopOwner = shopOwner self._lookAtCamTarget = False self._camTarget = None self._camHelperNode = None self._toonDialogueSfx = None self.toonHead = None self.frame = None return def displayLine(self, text): self.notify.debug('displayLine') self._dialogueLabel.node().setText(text) self.toonHead.reparentTo(aspect2d) self._toonDialogueSfx.play() self.toonHead.setClipPlane(self.clipPlane) def makeSuit(self, suitType): self.notify.debug('makeSuit()') suit = Suit.Suit() dna = SuitDNA.SuitDNA() dna.newSuit(suitType) suit.setStyle(dna) suit.isDisguised = 1 suit.generateSuit() suit.setScale(1.05, 1.05, 2.05) suit.setPos(0, 0, -4.4) suit.reparentTo(self.toonHead) for part in suit.getHeadParts(): part.hide() suit.loop('neutral') def load(self): self.notify.debug('load()') CogdoGameMovie.load(self) backgroundGui = loader.loadModel('phase_5/models/cogdominium/tt_m_gui_csa_flyThru') self.bg = backgroundGui.find('**/background') self.chatBubble = backgroundGui.find('**/chatBubble') self.chatBubble.setScale(6.5, 6.5, 7.3) self.chatBubble.setPos(0.32, 0, -0.78) self.bg.setScale(5.2) self.bg.setPos(0.14, 0, -0.6667) self.bg.reparentTo(aspect2d) self.chatBubble.reparentTo(aspect2d) self.frame = DirectFrame(geom=self.bg, relief=None, pos=(0.2, 0, -0.6667)) self.bg.wrtReparentTo(self.frame) self.gameTitleText = DirectLabel(parent=self.frame, text=TTLocalizer.CogdoExecutiveSuiteTitle, scale=TTLocalizer.MRPgameTitleText * 0.8, text_align=TextNode.ACenter, text_font=getSignFont(), text_fg=(1.0, 0.33, 0.33, 1.0), pos=TTLocalizer.MRgameTitleTextPos, relief=None) self.chatBubble.wrtReparentTo(self.frame) self.frame.hide() backgroundGui.removeNode() self.toonDNA = ToonDNA.ToonDNA() self.toonDNA.newToonFromProperties('dss', 'ss', 'm', 'm', 2, 0, 2, 2, 1, 8, 1, 8, 1, 14, 0) self.toonHead = Toon.Toon() self.toonHead.setDNA(self.toonDNA) self.makeSuit('sc') self.toonHead.getGeomNode().setDepthWrite(1) self.toonHead.getGeomNode().setDepthTest(1) self.toonHead.loop('neutral') self.toonHead.setPosHprScale(-0.73, 0, -1.27, 180, 0, 0, 0.18, 0.18, 0.18) self.toonHead.reparentTo(hidden) self.toonHead.startBlink() self.clipPlane = self.toonHead.attachNewNode(PlaneNode('clip')) self.clipPlane.node().setPlane(Plane(0, 0, 1, 0)) self.clipPlane.setPos(0, 0, 2.45) self._toonDialogueSfx = loader.loadSfx('phase_3.5/audio/dial/AV_dog_long.ogg') self._camHelperNode = NodePath('CamHelperNode') self._camHelperNode.reparentTo(render) dialogue = TTLocalizer.CogdoExecutiveSuiteIntroMessage def start(): self.frame.show() base.setCellsActive(base.bottomCells + base.leftCells + base.rightCells, 0) def showShopOwner(): self._setCamTarget(self._shopOwner, -10, offset=Point3(0, 0, 5)) def end(): self._dialogueLabel.reparentTo(hidden) self.toonHead.reparentTo(hidden) self.frame.hide() base.setCellsActive(base.bottomCells + base.leftCells + base.rightCells, 1) self._stopUpdateTask() self._ival = Sequence(Func(start), Func(self.displayLine, dialogue), Func(showShopOwner), ParallelEndTogether(camera.posInterval(self.cameraMoveDuration, Point3(8, 0, 13), blendType='easeInOut'), camera.hprInterval(0.5, self._camHelperNode.getHpr(), blendType='easeInOut')), Wait(self.introDuration), Func(end)) self._startUpdateTask() return def _setCamTarget(self, targetNP, distance, offset = Point3(0, 0, 0), angle = Point3(0, 0, 0)): camera.wrtReparentTo(render) self._camTarget = targetNP self._camOffset = offset self._camAngle = angle self._camDistance = distance self._camHelperNode.setPos(self._camTarget, self._camOffset) self._camHelperNode.setHpr(self._camTarget, 180 + self._camAngle[0], self._camAngle[1], self._camAngle[2]) self._camHelperNode.setPos(self._camHelperNode, 0, self._camDistance, 0) def _updateTask(self, task): dt = globalClock.getDt() return task.cont def unload(self): self._shopOwner = None self._camTarget = None if hasattr(self, '_camHelperNode') and self._camHelperNode: self._camHelperNode.removeNode() del self._camHelperNode self.frame.destroy() del self.frame self.bg.removeNode() del self.bg self.chatBubble.removeNode() del self.chatBubble self.toonHead.stopBlink() self.toonHead.stop() self.toonHead.removeNode() self.toonHead.delete() del self.toonHead CogdoGameMovie.unload(self) return
class DistributedParty(DistributedObject.DistributedObject): notify = directNotify.newCategory('DistributedParty') generatedEvent = 'distributedPartyGenerated' def __init__(self, cr): DistributedObject.DistributedObject.__init__(self, cr) self.partyDoneEvent = 'partyDone' self.load() self.avIdsAtParty = [] base.distributedParty = self self.titleText = '' self.isPartyEnding = False def setPartyState(self, partyState): self.isPartyEnding = partyState messenger.send('partyStateChanged', [partyState]) def getPartyState(self): return self.isPartyEnding def setPartyClockInfo(self, x, y, h): x = PartyUtils.convertDistanceFromPartyGrid(x, 0) y = PartyUtils.convertDistanceFromPartyGrid(y, 1) h = PartyUtils.convertDegreesFromPartyGrid(h) self.partyClockInfo = (x, y, h) self.loadPartyCountdownTimer() def setInviteeIds(self, inviteeIds): self.inviteeIds = inviteeIds def setPartyInfoTuple(self, partyInfoTuple): self.partyInfo = PartyInfo(*partyInfoTuple) self.loadDecorations() allActIds = [ x.activityId for x in self.partyInfo.activityList ] base.partyHasJukebox = PartyGlobals.ActivityIds.PartyJukebox in allActIds or PartyGlobals.ActivityIds.PartyJukebox40 in allActIds self.grid = [[False, False, False, False, False, True, True, True, True, True, True, True, True, True, True, False, False, False], [False, False, False, False, True, True, True, True, True, True, True, True, True, True, True, False, False, False], [False, False, False, True, True, True, True, True, True, True, True, True, True, True, True, True, False, False], [False, False, False, True, True, True, True, True, True, True, True, True, True, True, True, True, False, False], [False, False, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, False], [False, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True], [True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True], [True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True], [True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True], [True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True], [False, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True], [False, True, True, True, True, True, True, True, True, True, True, True, True, True, False, False, False, False], [False, False, False, False, True, True, True, True, True, True, True, True, True, False, False, False, False, False], [False, False, False, False, False, True, True, True, True, True, True, True, False, False, False, False, False, False], [False, False, False, False, False, False, True, True, True, True, True, False, False, False, False, False, False, False]] def fillGrid(x, y, size): for i in xrange(-size[1] / 2 + 1, size[1] / 2 + 1): for j in xrange(-size[0] / 2 + 1, size[0] / 2 + 1): self.grid[i + y][j + x] = False for activityBase in self.partyInfo.activityList: fillGrid(activityBase.x, activityBase.y, PartyGlobals.ActivityInformationDict[activityBase.activityId]['gridsize']) for decorBase in self.partyInfo.decors: fillGrid(decorBase.x, decorBase.y, PartyGlobals.DecorationInformationDict[decorBase.decorId]['gridsize']) self.loadGrass() def setPartyStartedTime(self, startedTime): stime = time.strptime(startedTime, '%Y-%m-%d %H:%M:%S') self.partyStartedTime = datetime.datetime(year=stime.tm_year, month=stime.tm_mon, day=stime.tm_mday, hour=stime.tm_hour, minute=stime.tm_min, second=stime.tm_sec, tzinfo=base.cr.toontownTimeManager.getCurServerDateTime().tzinfo) def disable(self): self.notify.debug('disable') DistributedObject.DistributedObject.disable(self) base.localAvatar.chatMgr.chatInputSpeedChat.removeInsidePartiesMenu() def delete(self): self.notify.debug('delete') self.unload() if hasattr(base, 'distributedParty'): del base.distributedParty DistributedObject.DistributedObject.delete(self) def load(self): Toon.loadMinigameAnims() self.defaultSignModel = loader.loadModel('phase_13/models/parties/eventSign') self.activityIconsModel = loader.loadModel('phase_4/models/parties/eventSignIcons') model = loader.loadModel('phase_4/models/parties/partyStickerbook') self.partyHat = model.find('**/Stickerbook_PartyIcon') self.partyHat.setPos(0.0, 0.1, 2.5) self.partyHat.setHpr(0.0, 0.0, -50.0) self.partyHat.setScale(4.0) self.partyHat.setBillboardAxis() self.partyHat.reparentTo(hidden) model.removeNode() self.defaultLeverModel = loader.loadModel('phase_13/models/parties/partyLeverBase') self.defaultStickModel = loader.loadModel('phase_13/models/parties/partyLeverStick') def loadGrass(self): self.grassRoot = NodePath('GrassRoot') self.grassRoot.reparentTo(base.cr.playGame.hood.loader.geom) grass = loader.loadModel('phase_13/models/parties/grass') clearPositions = self.getClearSquarePositions() numTufts = min(len(clearPositions) * 3, PartyGlobals.TuftsOfGrass) for i in xrange(numTufts): g = grass.copyTo(self.grassRoot) pos = random.choice(clearPositions) g.setPos(pos[0] + random.randint(-8, 8), pos[1] + random.randint(-8, 8), 0.0) def loadDecorations(self): self.decorationsList = [] for decorBase in self.partyInfo.decors: self.decorationsList.append(Decoration(PartyGlobals.DecorationIds.getString(decorBase.decorId), PartyUtils.convertDistanceFromPartyGrid(decorBase.x, 0), PartyUtils.convertDistanceFromPartyGrid(decorBase.y, 1), PartyUtils.convertDegreesFromPartyGrid(decorBase.h))) def unload(self): if hasattr(self, 'decorationsList') and self.decorationsList: for decor in self.decorationsList: decor.unload() del self.decorationsList self.stopPartyClock() self.grassRoot.removeNode() del self.grassRoot if hasattr(self, 'testGrid'): self.testGrid.removeNode() del self.testGrid self.ignoreAll() Toon.unloadMinigameAnims() self.partyHat.removeNode() del self.partyHat if hasattr(base, 'partyHasJukebox'): del base.partyHasJukebox def announceGenerate(self): #TODO - for some reason this is getting called hundreds of times when there are multiple districts DistributedObject.DistributedObject.announceGenerate(self) self.sendUpdate('enteredParty', []) globalClock.syncFrameTime() self.startPartyClock() base.localAvatar.chatMgr.chatInputSpeedChat.addInsidePartiesMenu() self.spawnTitleText() messenger.send(self.generatedEvent) if config.GetBool('show-debug-party-grid', 0): self.testGrid = NodePath('test_grid') self.testGrid.reparentTo(base.cr.playGame.hood.loader.geom) for i in xrange(len(self.grid)): for j in xrange(len(self.grid[i])): cm = CardMaker('gridsquare') np = NodePath(cm.generate()) np.setScale(12) np.setP(-90.0) np.setPos(PartyUtils.convertDistanceFromPartyGrid(j, 0) - 6.0, PartyUtils.convertDistanceFromPartyGrid(i, 1) - 6.0, 0.1) np.reparentTo(self.testGrid) if self.grid[i][j]: np.setColorScale(0.0, 1.0, 0.0, 1.0) else: np.setColorScale(1.0, 0.0, 0.0, 1.0) def getClearSquarePos(self): clearPositions = self.getClearSquarePositions() if len(clearPositions) == 0: raise StandardError, 'Party %s has no empty grid squares.' % self.doId return random.choice(clearPositions) def getClearSquarePositions(self): clearPositions = [] for y in xrange(len(self.grid)): for x in xrange(len(self.grid[0])): if self.grid[y][x]: pos = (PartyUtils.convertDistanceFromPartyGrid(x, 0), PartyUtils.convertDistanceFromPartyGrid(y, 1), 0.1) clearPositions.append(pos) return clearPositions def startPartyClock(self): self.partyClockModel.reparentTo(base.cr.playGame.hood.loader.geom) curServerTime = base.cr.toontownTimeManager.getCurServerDateTime() timePartyWillEnd = self.partyStartedTime + datetime.timedelta(hours=PartyGlobals.DefaultPartyDuration) timeLeftInParty = timePartyWillEnd - curServerTime if curServerTime < timePartyWillEnd: self.secondsLeftInParty = timeLeftInParty.seconds else: self.secondsLeftInParty = 0 taskMgr.doMethodLater(0.5, self.partyClockTask, 'UpdatePartyClock') self.partyClockSignFront = self.partyClockModel.find('**/signFrontText_locator') self.partyClockSignBack = self.partyClockModel.find('**/signBackText_locator') self.attachHostNameToSign(self.partyClockSignFront) self.attachHostNameToSign(self.partyClockSignBack) def attachHostNameToSign(self, locator): if self.hostName == '': return nameText = TextNode('nameText') nameText.setCardAsMargin(0.1, 0.1, 0.1, 0.1) nameText.setCardDecal(True) nameText.setCardColor(1.0, 1.0, 1.0, 0.0) r = 232.0 / 255.0 g = 169.0 / 255.0 b = 23.0 / 255.0 nameText.setTextColor(r, g, b, 1) nameText.setAlign(nameText.ACenter) nameText.setFont(ToontownGlobals.getBuildingNametagFont()) nameText.setShadowColor(0, 0, 0, 1) nameText.setBin('fixed') if TTLocalizer.BuildingNametagShadow: nameText.setShadow(*TTLocalizer.BuildingNametagShadow) nameWordWrap = 11.0 nameText.setWordwrap(nameWordWrap) scaleMult = 0.48 houseName = self.hostName nameText.setText(houseName) textWidth = nameText.getWidth() xScale = 1.0 * scaleMult if textWidth > nameWordWrap: xScale = nameWordWrap / textWidth * scaleMult sign_origin = locator namePlate = sign_origin.attachNewNode(nameText) namePlate.setDepthWrite(0) namePlate.setPos(0, 0, 0) namePlate.setScale(xScale) def stopPartyClock(self): self.partyClockModel.removeNode() taskMgr.remove('UpdatePartyClock') def partyClockTask(self, task): self.secondsLeftInParty -= 0.5 if self.secondsLeftInParty < 0: self.frontTimer['minute']['text'] = '--' self.backTimer['minute']['text'] = '--' self.frontTimer['second']['text'] = '--' self.backTimer['second']['text'] = '--' return if self.frontTimer['colon'].isStashed(): self.frontTimer['colon'].unstash() self.backTimer['colon'].unstash() else: self.frontTimer['colon'].stash() self.backTimer['colon'].stash() minutesLeft = int(int(self.secondsLeftInParty / 60) % 60) if minutesLeft < 10: minutesLeft = '0%d' % minutesLeft else: minutesLeft = '%d' % minutesLeft secondsLeft = int(self.secondsLeftInParty % 60) if secondsLeft < 10: secondsLeft = '0%d' % secondsLeft else: secondsLeft = '%d' % secondsLeft self.frontTimer['minute']['text'] = minutesLeft self.backTimer['minute']['text'] = minutesLeft self.frontTimer['second']['text'] = secondsLeft self.backTimer['second']['text'] = secondsLeft taskMgr.doMethodLater(0.5, self.partyClockTask, 'UpdatePartyClock') if self.secondsLeftInParty != int(self.secondsLeftInParty): self.partyClockModel.find('**/middleRotateFront_grp').setR(-6.0 * (self.secondsLeftInParty % 60)) self.partyClockModel.find('**/middleRotateBack_grp').setR(6.0 * (self.secondsLeftInParty % 60)) def getAvIdsAtParty(self): return self.avIdsAtParty def setAvIdsAtParty(self, avIdsAtParty): self.avIdsAtParty = avIdsAtParty def loadPartyCountdownTimer(self): self.partyClockModel = loader.loadModel('phase_13/models/parties/partyClock') self.partyClockModel.setPos(self.partyClockInfo[0], self.partyClockInfo[1], 0.0) self.partyClockModel.setH(self.partyClockInfo[2]) self.partyClockModel.reparentTo(base.cr.playGame.hood.loader.geom) self.partyClockModel.find('**/frontText_locator').setY(-1.1) self.partyClockModel.find('**/backText_locator').setY(0.633) self.frontTimer = self.getTimer(self.partyClockModel.find('**/frontText_locator')) base.frontTimerLoc = self.partyClockModel.find('**/frontText_locator') base.backTimerLoc = self.partyClockModel.find('**/backText_locator') self.backTimer = self.getTimer(self.partyClockModel.find('**/backText_locator')) self.partyClockModel.stash() def getTimer(self, parent): timeFont = ToontownGlobals.getMinnieFont() timer = {} timer['minute'] = DirectLabel(parent=parent, pos=TTLocalizer.DPtimerMinutePos, relief=None, text='59', text_align=TextNode.ACenter, text_font=timeFont, text_fg=(0.7, 0.3, 0.3, 1.0), scale=TTLocalizer.DPtimerMinute) timer['colon'] = DirectLabel(parent=parent, pos=TTLocalizer.DPtimerColonPos, relief=None, text=':', text_align=TextNode.ACenter, text_font=timeFont, text_fg=(0.7, 0.3, 0.3, 1.0), scale=TTLocalizer.DPtimerColon) timer['second'] = DirectLabel(parent=parent, relief=None, pos=TTLocalizer.DPtimerSecondPos, text='14', text_align=TextNode.ACenter, text_font=timeFont, text_fg=(0.7, 0.3, 0.3, 1.0), scale=TTLocalizer.DPtimerSecond) timer['textLabel'] = DirectLabel(parent=parent, relief=None, pos=(0.0, 0.0, 1.15), text=TTLocalizer.PartyCountdownClockText, text_font=timeFont, text_fg=(0.7, 0.3, 0.3, 1.0), scale=TTLocalizer.DPtimerTextLabel) return timer def setHostName(self, hostName): self.hostName = hostName if hasattr(self, 'partyClockSignFront'): self.attachHostNameToSign(self.partyClockSignFront) if hasattr(self, 'partyClockSignBack'): self.attachHostNameToSign(self.partyClockSignBack) def spawnTitleText(self): if not self.hostName: return partyText = TTLocalizer.PartyTitleText % TTLocalizer.GetPossesive(self.hostName) self.doSpawnTitleText(partyText) def doSpawnTitleText(self, text): return self.titleColor = (1.0, 0.5, 0.4, 1.0) self.titleText = OnscreenText.OnscreenText(text, fg=self.titleColor, font=ToontownGlobals.getSignFont(), pos=(0, -0.5), scale=0.16, drawOrder=0, mayChange=1, wordwrap=16) self.titleText.setText(text) self.titleText.show() self.titleText.setColor(Vec4(*self.titleColor)) self.titleText.clearColorScale() self.titleText.setFg(self.titleColor) seq = Sequence(Wait(0.1), Wait(6.0), self.titleText.colorScaleInterval(0.5, Vec4(1.0, 1.0, 1.0, 0.0)), Task(self.hideTitleText)) seq.start() def hideTitleText(self): if self.titleText: self.titleText.hide()
def destroy(self): NodePath.removeNode(self)
class DistributedPartyActivity(DistributedObject.DistributedObject): deferFor = 1 def __init__(self, cr, activityId, activityType, wantLever=False, wantRewardGui=False): DistributedObject.DistributedObject.__init__(self, cr) self.activityId = activityId self.activityName = PartyGlobals.ActivityIds.getString(self.activityId) self.activityType = activityType self.wantLever = wantLever self.wantRewardGui = wantRewardGui self.messageGui = None self.rewardGui = None self.toonIds = [] self._toonId2ror = {} childName = '%s' % self childName = childName[childName.rfind('.DistributedParty') + len('.DistributedParty'):childName. rfind('Activity instance')] if not hasattr(base, 'partyActivityDict'): base.partyActivityDict = {} base.partyActivityDict[childName] = self self.root = NodePath('root') self.rulesDoneEvent = 'rulesDone' self.modelCount = 500 self.cleanupActions = [] self.usesSmoothing = 0 self.usesLookAround = 0 self.difficultyOverride = None self.trolleyZoneOverride = None self._localToonRequestStatus = None #self.root.setPos(self.x, self.y, self.z) return def localToonExiting(self): self._localToonRequestStatus = PartyGlobals.ActivityRequestStatus.Exiting def localToonJoining(self): self._localToonRequestStatus = PartyGlobals.ActivityRequestStatus.Joining def d_toonJoinRequest(self): if self._localToonRequestStatus is None: self.localToonJoining() self.sendUpdate('toonJoinRequest') return def d_toonExitRequest(self): if self._localToonRequestStatus is None: self.localToonExiting() self.sendUpdate('toonExitRequest') return def d_toonExitDemand(self): self.localToonExiting() self.sendUpdate('toonExitDemand') def joinRequestDenied(self, reason): self._localToonRequestStatus = None return def exitRequestDenied(self, reason): self._localToonRequestStatus = None return def handleToonJoined(self, toonId): self.notify.error('BASE: handleToonJoined should be overridden %s' % self.activityName) def handleToonExited(self, toonId): self.notify.error('BASE: handleToonExited should be overridden %s' % self.activityName) def handleToonDisabled(self, toonId): self.notify.error('BASE: handleToonDisabled should be overridden %s' % self.activityName) def setToonsPlaying(self, toonIds): exitedToons, joinedToons = self.getToonsPlayingChanges( self.toonIds, toonIds) self.setToonIds(toonIds) self._processExitedToons(exitedToons) self._processJoinedToons(joinedToons) def _processExitedToons(self, exitedToons): for toonId in exitedToons: if toonId != base.localAvatar.doId or toonId == base.localAvatar.doId and self.isLocalToonRequestStatus( PartyGlobals.ActivityRequestStatus.Exiting): toon = self.getAvatar(toonId) if toon is not None: self.ignore(toon.uniqueName('disable')) self.handleToonExited(toonId) if toonId == base.localAvatar.doId: self._localToonRequestStatus = None if toonId in self._toonId2ror: self.cr.relatedObjectMgr.abortRequest( self._toonId2ror[toonId]) del self._toonId2ror[toonId] return def _processJoinedToons(self, joinedToons): for toonId in joinedToons: if toonId != base.localAvatar.doId or toonId == base.localAvatar.doId and self.isLocalToonRequestStatus( PartyGlobals.ActivityRequestStatus.Joining): if toonId not in self._toonId2ror: request = self.cr.relatedObjectMgr.requestObjects( [toonId], allCallback=self._handlePlayerPresent) if toonId in self._toonId2ror: del self._toonId2ror[toonId] else: self._toonId2ror[toonId] = request def _handlePlayerPresent(self, toons): toon = toons[0] toonId = toon.doId if toonId in self._toonId2ror: del self._toonId2ror[toonId] else: self._toonId2ror[toonId] = None self._enableHandleToonDisabled(toonId) self.handleToonJoined(toonId) if toonId == base.localAvatar.doId: self._localToonRequestStatus = None return def _enableHandleToonDisabled(self, toonId): toon = self.getAvatar(toonId) if toon is not None: self.acceptOnce(toon.uniqueName('disable'), self.handleToonDisabled, [toonId]) else: self.notify.warning( 'BASE: unable to get handle to toon with toonId:%d. Hook for handleToonDisabled not set.' % toonId) return def isLocalToonRequestStatus(self, requestStatus): return self._localToonRequestStatus == requestStatus def setToonIds(self, toonIds): self.toonIds = toonIds def getToonsPlayingChanges(self, oldToonIds, newToonIds): oldToons = set(oldToonIds) newToons = set(newToonIds) exitedToons = oldToons.difference(newToons) joinedToons = newToons.difference(oldToons) return (list(exitedToons), list(joinedToons)) def setUsesSmoothing(self): self.usesSmoothing = True def setUsesLookAround(self): self.usesLookAround = True def getInstructions(self): return TTLocalizer.DefaultPartyActivityInstructions def getParentNodePath(self): if hasattr(base.cr.playGame, 'hood') and base.cr.playGame.hood and hasattr( base.cr.playGame.hood, 'loader') and base.cr.playGame.hood.loader and hasattr( base.cr.playGame.hood.loader, 'geom') and base.cr.playGame.hood.loader.geom: return base.cr.playGame.hood.loader.geom else: self.notify.warning( 'Hood or loader not created, defaulting to render') return render def __createRandomNumGen(self): self.notify.debug('BASE: self.doId=0x%08X' % self.doId) self.randomNumGen = RandomNumGen.RandomNumGen(self.doId) def destroy(self=self): self.notify.debug('BASE: destroying random num gen') del self.randomNumGen self.cleanupActions.append(destroy) def generate(self): DistributedObject.DistributedObject.generate(self) self.notify.debug('BASE: generate, %s' % self.getTitle()) self.__createRandomNumGen() def announceGenerate(self): DistributedObject.DistributedObject.announceGenerate(self) self.notify.debug('BASE: announceGenerate %s' % self.activityName) self.root.setName(self.activityName + 'Root') centeredX, centeredY = getCenterPosFromGridSize( self.x, self.y, PartyGlobals.ActivityInformationDict[self.activityId]['gridsize']) self.root.setPos(centeredX, centeredY, 0.0) self.root.setH(self.h) self.root.setZ(self.z) self.normalExit = True if self.wantLever: self.leverTriggerEvent = self.uniqueName('leverTriggerEvent') self.load() def cleanup(self=self): self.notify.debug('BASE: cleanup: normalExit=%s' % self.normalExit) base.cr.renderFrame() if self.normalExit: self.sendUpdate('toonExitRequest') self.cleanupActions.append(cleanup) def disable(self): self.notify.debug('BASE: disable') DistributedObject.DistributedObject.disable(self) rorToonIds = self._toonId2ror.keys() for toonId in rorToonIds: self.cr.relatedObjectMgr.abortRequest(self._toonId2ror[toonId]) del self._toonId2ror[toonId] self.ignore(self.messageDoneEvent) if self.messageGui is not None and not self.messageGui.isEmpty(): self.messageGui.cleanup() self.messageGui = None return def delete(self): self.notify.debug('BASE: delete') self.unload() self.ignoreAll() DistributedObject.DistributedObject.delete(self) def load(self): self.notify.debug('BASE: load') self.loadSign() if self.wantLever: self.loadLever() if self.wantRewardGui: self.showRewardDoneEvent = self.uniqueName('showRewardDoneEvent') self.rewardGui = JellybeanRewardGui(self.showRewardDoneEvent) self.messageDoneEvent = self.uniqueName('messageDoneEvent') self.root.reparentTo(self.getParentNodePath()) self._enableCollisions() def loadSign(self): actNameForSign = self.activityName if self.activityId == PartyGlobals.ActivityIds.PartyJukebox40: actNameForSign = PartyGlobals.ActivityIds.getString( PartyGlobals.ActivityIds.PartyJukebox) elif self.activityId == PartyGlobals.ActivityIds.PartyDance20: actNameForSign = PartyGlobals.ActivityIds.getString( PartyGlobals.ActivityIds.PartyDance) self.sign = self.root.attachNewNode('%sSign' % self.activityName) self.signModel = self.party.defaultSignModel.copyTo(self.sign) self.signFlat = self.signModel.find('**/sign_flat') self.signFlatWithNote = self.signModel.find('**/sign_withNote') self.signTextLocator = self.signModel.find('**/signText_locator') textureNodePath = getPartyActivityIcon(self.party.activityIconsModel, actNameForSign) textureNodePath.setPos(0.0, -0.02, 2.2) textureNodePath.setScale(2.35) textureNodePath.copyTo(self.signFlat) textureNodePath.copyTo(self.signFlatWithNote) text = TextNode('noteText') text.setTextColor(0.2, 0.1, 0.7, 1.0) text.setAlign(TextNode.ACenter) text.setFont(OTPGlobals.getInterfaceFont()) text.setWordwrap(10.0) text.setText('') self.noteText = self.signFlatWithNote.attachNewNode(text) self.noteText.setPosHpr(self.signTextLocator, 0.0, 0.0, 0.2, 0.0, 0.0, 0.0) self.noteText.setScale(0.2) self.signFlatWithNote.stash() self.signTextLocator.stash() def loadLever(self): self.lever = self.root.attachNewNode('%sLever' % self.activityName) self.leverModel = self.party.defaultLeverModel.copyTo(self.lever) self.controlColumn = NodePath('cc') column = self.leverModel.find('**/column') column.getChildren().reparentTo(self.controlColumn) self.controlColumn.reparentTo(column) self.stickHinge = self.controlColumn.attachNewNode('stickHinge') self.stick = self.party.defaultStickModel.copyTo(self.stickHinge) self.stickHinge.setHpr(0.0, 90.0, 0.0) self.stick.setHpr(0, -90.0, 0) self.stick.flattenLight() self.bottom = self.leverModel.find('**/bottom') self.bottom.wrtReparentTo(self.controlColumn) self.bottomPos = self.bottom.getPos() cs = CollisionSphere(0.0, 1.35, 2.0, 1.0) cs.setTangible(False) cn = CollisionNode(self.leverTriggerEvent) cn.addSolid(cs) cn.setIntoCollideMask(OTPGlobals.WallBitmask) self.leverTrigger = self.root.attachNewNode(cn) self.leverTrigger.reparentTo(self.lever) self.leverTrigger.stash() cs = CollisionTube(0.0, 2.7, 0.0, 0.0, 2.7, 3.0, 1.2) cn = CollisionNode('levertube') cn.addSolid(cs) cn.setIntoCollideMask(OTPGlobals.WallBitmask) self.leverTube = self.leverModel.attachNewNode(cn) host = base.cr.doId2do.get(self.party.partyInfo.hostId) if host is None: self.notify.debug( '%s loadLever : Host has left the game before lever could be created.' % self.activityName) return scale = host.getGeomNode().getChild(0).getSz(render) self.leverModel.setScale(scale) self.controlColumn.setPos(0, 0, 0) host.setPosHpr(self.lever, 0, 0, 0, 0, 0, 0) host.pose('leverNeutral', 0) host.update() pos = host.rightHand.getPos(self.controlColumn) self.controlColumn.setPos(pos[0], pos[1], pos[2] - 1) self.bottom.setZ(host, 0.0) self.bottom.setPos(self.bottomPos[0], self.bottomPos[1], self.bottom.getZ()) lookAtPoint = Point3(0.3, 0, 0.1) lookAtUp = Vec3(0, -1, 0) self.stickHinge.lookAt(host.rightHand, lookAtPoint, lookAtUp) host.play('walk') host.update() return def unloadLever(self): self.lever.removeNode() self.leverModel.removeNode() self.controlColumn.removeNode() self.stickHinge.removeNode() self.stick.removeNode() self.bottom.removeNode() self.leverTrigger.removeNode() self.leverTube.removeNode() del self.bottomPos del self.lever del self.leverModel del self.controlColumn del self.stickHinge del self.stick del self.bottom del self.leverTrigger del self.leverTube def _enableCollisions(self): if self.wantLever: self.leverTrigger.unstash() self.accept('enter%s' % self.leverTriggerEvent, self._leverPulled) def _disableCollisions(self): if self.wantLever: self.leverTrigger.stash() self.ignore('enter%s' % self.leverTriggerEvent) def _leverPulled(self, collEntry): self.notify.debug('_leverPulled : Someone pulled the lever!!! ') if self.activityType == PartyGlobals.ActivityTypes.HostInitiated and base.localAvatar.doId != self.party.partyInfo.hostId: return False return True def getToonPullingLeverInterval(self, toon): walkTime = 0.2 reach = ActorInterval(toon, 'leverReach', playRate=2.0) pull = ActorInterval(toon, 'leverPull', startFrame=6) origPos = toon.getPos(render) origHpr = toon.getHpr(render) newPos = self.lever.getPos(render) newHpr = self.lever.getHpr(render) origHpr.setX(PythonUtil.fitSrcAngle2Dest(origHpr[0], newHpr[0])) toon.setPosHpr(origPos, origHpr) reachAndPull = Sequence( ActorInterval(toon, 'walk', loop=True, duration=walkTime - reach.getDuration()), reach, pull) leverSeq = Sequence( Wait(walkTime + reach.getDuration() - 0.1), self.stick.hprInterval(0.55, Point3(0.0, 25.0, 0.0), Point3(0.0, 0.0, 0.0)), Wait(0.3), self.stick.hprInterval(0.4, Point3(0.0, 0.0, 0.0), Point3(0.0, 25.0, 0.0))) returnSeq = Sequence( Parallel(toon.posInterval(walkTime, newPos, origPos), toon.hprInterval(walkTime, newHpr, origHpr), leverSeq, reachAndPull)) return returnSeq def showMessage(self, message, endState='walk'): base.cr.playGame.getPlace().fsm.request('activity') self.acceptOnce(self.messageDoneEvent, self.__handleMessageDone) self.messageGui = TTDialog.TTGlobalDialog( doneEvent=self.messageDoneEvent, message=message, style=TTDialog.Acknowledge) self.messageGui.endState = endState def __handleMessageDone(self): self.ignore(self.messageDoneEvent) if hasattr(base.cr.playGame.getPlace(), 'fsm'): if self.messageGui and hasattr(self.messageGui, 'endState'): self.notify.info('__handleMessageDone (endState=%s)' % self.messageGui.endState) base.cr.playGame.getPlace().fsm.request( self.messageGui.endState) else: self.notify.warning( "messageGui has no endState, defaulting to 'walk'") base.cr.playGame.getPlace().fsm.request('walk') if self.messageGui is not None and not self.messageGui.isEmpty(): self.messageGui.cleanup() self.messageGui = None return def showJellybeanReward(self, earnedAmount, jarAmount, message): if not self.isLocalToonInActivity( ) or base.localAvatar.doId in self.getToonIdsAsList(): messenger.send('DistributedPartyActivity-showJellybeanReward') base.cr.playGame.getPlace().fsm.request('activity') self.acceptOnce(self.showRewardDoneEvent, self.__handleJellybeanRewardDone) self.rewardGui.showReward(earnedAmount, jarAmount, message) def __handleJellybeanRewardDone(self): self.ignore(self.showRewardDoneEvent) self.handleRewardDone() def handleRewardDone(self): if base.cr.playGame.getPlace() and hasattr(base.cr.playGame.getPlace(), 'fsm'): base.cr.playGame.getPlace().fsm.request('walk') def setSignNote(self, note): self.noteText.node().setText(note) if len(note.strip()) > 0: self.signFlat.stash() self.signFlatWithNote.unstash() self.signTextLocator.unstash() else: self.signFlat.unstash() self.signFlatWithNote.stash() self.signTextLocator.stash() def unload(self): self.notify.debug('BASE: unload') self.finishRules() self._disableCollisions() self.signModel.removeNode() del self.signModel self.sign.removeNode() del self.sign self.ignoreAll() if self.wantLever: self.unloadLever() self.root.removeNode() del self.root del self.activityId del self.activityName del self.activityType del self.wantLever del self.messageGui if self.rewardGui is not None: self.rewardGui.destroy() del self.rewardGui if hasattr(self, 'toonIds'): del self.toonIds del self.rulesDoneEvent del self.modelCount del self.cleanupActions del self.usesSmoothing del self.usesLookAround del self.difficultyOverride del self.trolleyZoneOverride if hasattr(base, 'partyActivityDict'): del base.partyActivityDict return def setPartyDoId(self, partyDoId): #print base.cr.doId2do self.party = base.cr.doId2do[partyDoId] def setX(self, x): self.x = x def setY(self, y): self.y = y def setZ(self, z): self.z = z def setH(self, h): self.h = h def setState(self, newState, timestamp): if newState == 'Active': self.activityStartTime = globalClockDelta.networkToLocalTime( timestamp) def turnOffSmoothingOnGuests(self): for toonId in self.toonIds: avatar = self.getAvatar(toonId) if avatar: if not self.usesSmoothing: avatar.stopSmooth() if not self.usesLookAround: avatar.stopLookAround() def getAvatar(self, toonId): if self.cr.doId2do.has_key(toonId): return self.cr.doId2do[toonId] else: self.notify.warning( 'BASE: getAvatar: No avatar in doId2do with id: ' + str(toonId)) return None return None def getAvatarName(self, toonId): avatar = self.getAvatar(toonId) if avatar: return avatar.getName() else: return 'Unknown' def isLocalToonInActivity(self): result = False place = base.cr.playGame.getPlace() if place and place.__class__.__name__ == 'Party' and hasattr( place, 'fsm') and place.fsm: result = place.fsm.getCurrentState().getName() == 'activity' return result def getToonIdsAsList(self): return self.toonIds def startRules(self, timeout=PartyGlobals.DefaultRulesTimeout): self.notify.debug('BASE: startRules') self.accept(self.rulesDoneEvent, self.handleRulesDone) self.rulesPanel = MinigameRulesPanel('PartyRulesPanel', self.getTitle(), self.getInstructions(), self.rulesDoneEvent, timeout) base.setCellsAvailable( base.bottomCells + [base.leftCells[0], base.rightCells[1]], False) self.rulesPanel.load() self.rulesPanel.enter() def finishRules(self): self.notify.debug('BASE: finishRules') self.ignore(self.rulesDoneEvent) if hasattr(self, 'rulesPanel'): self.rulesPanel.exit() self.rulesPanel.unload() del self.rulesPanel base.setCellsAvailable( base.bottomCells + [base.leftCells[0], base.rightCells[1]], True) def handleRulesDone(self): self.notify.error('BASE: handleRulesDone should be overridden') def getTitle(self): return TTLocalizer.PartyActivityNameDict[self.activityId]['generic'] def local2ActivityTime(self, timestamp): return timestamp - self.activityStartTime def activity2LocalTime(self, timestamp): return timestamp + self.activityStartTime def getCurrentActivityTime(self): return self.local2ActivityTime(globalClock.getFrameTime()) def disableEmotes(self): Emote.globalEmote.disableAll(base.localAvatar) def enableEmotes(self): Emote.globalEmote.releaseAll(base.localAvatar)
class CogdoFlyingGuiManager: ClearMessageDisplayEventName = 'ClearMessageDisplayEvent' EagleTargetingLocalPlayerEventName = 'EagleTargetingLocalPlayerEvent' EagleAttackingLocalPlayerEventName = 'EagleAttackingLocalPlayerEvent' FirstPressOfCtrlEventName = 'FirstPressOfCtrlEvent' PickedUpFirstPropellerEventName = 'PickedUpFirstPropellerEvent' InvulnerableEventName = 'InvulnerableEvent' StartRunningOutOfTimeMusicEventName = 'StartRunningOutOfTimeEvent' def __init__(self, level): self._level = level self.root = NodePath('CogdoFlyingGui') self.root.reparentTo(aspect2d) self.root.stash() self._initTimer() self._initHud() self._initMessageDisplay() self.sentTimeRunningOutMessage = False self._refuelGui = CogdoFlyingFuelGui(self.root) self._progressGui = CogdoFlyingProgressGui(self.root, self._level) def _initHud(self): self._memoGui = CogdoMemoGui(self.root) self._memoGui.posNextToLaffMeter() def _initTimer(self): self._timer = ToontownTimer() self._timer.reparentTo(self.root) self._timer.posInTopRightCorner() def _initMessageDisplay(self): audioMgr = base.cogdoGameAudioMgr sound = audioMgr.createSfx('popupHelpText') self._messageDisplay = CogdoGameMessageDisplay( 'CogdoFlyingMessageDisplay', self.root, sfx=sound) def destroyTimer(self): if self._timer is not None: self._timer.stop() self._timer.destroy() self._timer = None return def onstage(self): self.root.unstash() self._refuelGui.hide() self._progressGui.hide() def presentProgressGui(self): ToontownIntervals.start( ToontownIntervals.getPresentGuiIval(self._progressGui, 'present_progress_gui')) def presentRefuelGui(self): ToontownIntervals.start( ToontownIntervals.getPresentGuiIval(self._refuelGui, 'present_fuel_gui')) def presentTimerGui(self): ToontownIntervals.start( ToontownIntervals.getPresentGuiIval(self._timer, 'present_timer_gui')) def presentMemoGui(self): ToontownIntervals.start( ToontownIntervals.getPresentGuiIval(self._memoGui, 'present_memo_gui')) def offstage(self): self.root.stash() self._refuelGui.hide() self._progressGui.hide() self.hideTimer() def getTimeLeft(self): return Globals.Gameplay.SecondsUntilGameOver - self._timer.getElapsedTime( ) def isTimeRunningOut(self): return self.getTimeLeft() < Globals.Gameplay.TimeRunningOutSeconds def startTimer(self, duration, timerExpiredCallback=None, keepHidden=False): if self._timer is None: self._initTimer() self._timer.setTime(duration) self._timer.countdown(duration, timerExpiredCallback) if keepHidden: self.hideTimer() else: self.showTimer() return def stopTimer(self): if hasattr(self, '_timer') and self._timer is not None: self.hideTimer() self._timer.stop() return def showTimer(self): self._timer.show() def hideTimer(self): self._timer.hide() def forceTimerDone(self): if self._timer.countdownTask != None: self._timer.countdownTask.duration = 0 return def showRefuelGui(self): self._refuelGui.show() def hideRefuelGui(self): self._refuelGui.hide() def setMessage(self, text, color=None, transition='fade'): self._messageDisplay.updateMessage(text, color, transition) def setTemporaryMessage(self, text, duration=3.0, color=None): self._messageDisplay.showMessageTemporarily(text, duration, color) def setFuel(self, fuel): self._refuelGui.setFuel(fuel) def resetBlades(self): self._refuelGui.resetBlades() def setBlades(self, fuelState): self._refuelGui.setBlades(fuelState) def bladeLost(self): self._refuelGui.bladeLost() def setPropellerSpinRate(self, newRate): self._refuelGui.setPropellerSpinRate(newRate) def setMemoCount(self, score): self._memoGui.setCount(score) def addToonToProgressMeter(self, toon): self._progressGui.addToon(toon) def removeToonFromProgressMeter(self, toon): self._progressGui.removeToon(toon) def update(self): if self.isTimeRunningOut() and not self.sentTimeRunningOutMessage: messenger.send( CogdoFlyingGuiManager.StartRunningOutOfTimeMusicEventName) self.sentTimeRunningOutMessage = True self._refuelGui.update() self._progressGui.update() def destroy(self): ToontownIntervals.cleanup('present_fuel_gui') ToontownIntervals.cleanup('present_timer_gui') ToontownIntervals.cleanup('present_memo_gui') ToontownIntervals.cleanup('present_progress_gui') self._refuelGui.destroy() self._refuelGui = None self._memoGui.destroy() self._memoGui = None self._progressGui.destroy() self._progressGui = None self.destroyTimer() self._messageDisplay.destroy() self._messageDisplay = None self.root.removeNode() self.root = None return
class CogdoFlyingCameraManager: def __init__(self, cam, parent, player, level): self._toon = player.toon self._camera = cam self._parent = parent self._player = player self._level = level self._enabled = False def enable(self): if self._enabled: return self._toon.detachCamera() self._prevToonY = 0.0 levelBounds = self._level.getBounds() l = Globals.Camera.LevelBoundsFactor self._bounds = ( (levelBounds[0][0] * l[0], levelBounds[0][1] * l[0]), (levelBounds[1][0] * l[1], levelBounds[1][1] * l[1]), (levelBounds[2][0] * l[2], levelBounds[2][1] * l[2]), ) self._lookAtZ = self._toon.getHeight() + Globals.Camera.LookAtToonHeightOffset self._camParent = NodePath("CamParent") self._camParent.reparentTo(self._parent) self._camParent.setPos(self._toon, 0, 0, 0) self._camParent.setHpr(180, Globals.Camera.Angle, 0) self._camera.reparentTo(self._camParent) self._camera.setPos(0, Globals.Camera.Distance, 0) self._camera.lookAt(self._toon, 0, 0, self._lookAtZ) self._cameraLookAtNP = NodePath("CameraLookAt") self._cameraLookAtNP.reparentTo(self._camera.getParent()) self._cameraLookAtNP.setPosHpr(self._camera.getPos(), self._camera.getHpr()) self._levelBounds = self._level.getBounds() self._enabled = True self._frozen = False self._initCollisions() def _initCollisions(self): self._camCollRay = CollisionRay() camCollNode = CollisionNode("CameraToonRay") camCollNode.addSolid(self._camCollRay) camCollNode.setFromCollideMask( OTPGlobals.WallBitmask | OTPGlobals.CameraBitmask | ToontownGlobals.FloorEventBitmask | ToontownGlobals.CeilingBitmask ) camCollNode.setIntoCollideMask(0) self._camCollNP = self._camera.attachNewNode(camCollNode) self._camCollNP.show() self._collOffset = Vec3(0, 0, 0.5) self._collHandler = CollisionHandlerQueue() self._collTrav = CollisionTraverser() self._collTrav.addCollider(self._camCollNP, self._collHandler) self._betweenCamAndToon = {} self._transNP = NodePath("trans") self._transNP.reparentTo(render) self._transNP.setTransparency(True) self._transNP.setAlphaScale(Globals.Camera.AlphaBetweenToon) self._transNP.setBin("fixed", 10000) def _destroyCollisions(self): self._collTrav.removeCollider(self._camCollNP) self._camCollNP.removeNode() del self._camCollNP del self._camCollRay del self._collHandler del self._collOffset del self._betweenCamAndToon self._transNP.removeNode() del self._transNP def freeze(self): self._frozen = True def unfreeze(self): self._frozen = False def disable(self): if not self._enabled: return self._destroyCollisions() self._camera.wrtReparentTo(render) self._cameraLookAtNP.removeNode() del self._cameraLookAtNP self._camParent.removeNode() del self._camParent del self._prevToonY del self._lookAtZ del self._bounds del self._frozen self._enabled = False def update(self, dt=0.0): self._updateCam(dt) self._updateCollisions() def _updateCam(self, dt): toonPos = self._toon.getPos() camPos = self._camParent.getPos() x = camPos[0] z = camPos[2] toonWorldX = self._toon.getX(render) maxX = Globals.Camera.MaxSpinX toonWorldX = clamp(toonWorldX, -1.0 * maxX, maxX) spinAngle = Globals.Camera.MaxSpinAngle * toonWorldX * toonWorldX / (maxX * maxX) newH = 180.0 + spinAngle self._camParent.setH(newH) spinAngle = spinAngle * (pi / 180.0) distBehindToon = Globals.Camera.SpinRadius * cos(spinAngle) distToRightOfToon = Globals.Camera.SpinRadius * sin(spinAngle) d = self._camParent.getX() - clamp(toonPos[0], *self._bounds[0]) if abs(d) > Globals.Camera.LeewayX: if d > Globals.Camera.LeewayX: x = toonPos[0] + Globals.Camera.LeewayX else: x = toonPos[0] - Globals.Camera.LeewayX x = self._toon.getX(render) + distToRightOfToon boundToonZ = min(toonPos[2], self._bounds[2][1]) d = z - boundToonZ if d > Globals.Camera.MinLeewayZ: if self._player.velocity[2] >= 0 and toonPos[1] != self._prevToonY or self._player.velocity[2] > 0: z = boundToonZ + d * INVERSE_E ** (dt * Globals.Camera.CatchUpRateZ) elif d > Globals.Camera.MaxLeewayZ: z = boundToonZ + Globals.Camera.MaxLeewayZ elif d < -Globals.Camera.MinLeewayZ: z = boundToonZ - Globals.Camera.MinLeewayZ if self._frozen: y = camPos[1] else: y = self._toon.getY(render) - distBehindToon self._camParent.setPos(x, smooth(camPos[1], y), smooth(camPos[2], z)) if toonPos[2] < self._bounds[2][1]: h = self._cameraLookAtNP.getH() if d >= Globals.Camera.MinLeewayZ: self._cameraLookAtNP.lookAt(self._toon, 0, 0, self._lookAtZ) elif d <= -Globals.Camera.MinLeewayZ: self._cameraLookAtNP.lookAt(self._camParent, 0, 0, self._lookAtZ) self._cameraLookAtNP.setHpr(h, self._cameraLookAtNP.getP(), 0) self._camera.setHpr(smooth(self._camera.getHpr(), self._cameraLookAtNP.getHpr())) self._prevToonY = toonPos[1] def _updateCollisions(self): pos = self._toon.getPos(self._camera) + self._collOffset self._camCollRay.setOrigin(pos) direction = -Vec3(pos) direction.normalize() self._camCollRay.setDirection(direction) self._collTrav.traverse(render) nodesInBetween = {} if self._collHandler.getNumEntries() > 0: self._collHandler.sortEntries() for entry in self._collHandler.getEntries(): name = entry.getIntoNode().getName() if name.find("col_") >= 0: np = entry.getIntoNodePath().getParent() if not nodesInBetween.has_key(np): nodesInBetween[np] = np.getParent() for np in nodesInBetween.keys(): if self._betweenCamAndToon.has_key(np): del self._betweenCamAndToon[np] else: np.setTransparency(True) np.wrtReparentTo(self._transNP) if np.getName().find("lightFixture") >= 0: if not np.find("**/*floor_mesh").isEmpty(): np.find("**/*floor_mesh").hide() elif np.getName().find("platform") >= 0: if not np.find("**/*Floor").isEmpty(): np.find("**/*Floor").hide() for np, parent in self._betweenCamAndToon.items(): np.wrtReparentTo(parent) np.setTransparency(False) if np.getName().find("lightFixture") >= 0: if not np.find("**/*floor_mesh").isEmpty(): np.find("**/*floor_mesh").show() elif np.getName().find("platform") >= 0: if not np.find("**/*Floor").isEmpty(): np.find("**/*Floor").show() self._betweenCamAndToon = nodesInBetween
class CogdoFlyingLevelQuadrant: notify = directNotify.newCategory('CogdoFlyingLevelQuadrant') def __init__(self, serialNum, model, level, parent): self.serialNum = serialNum self._model = model self._level = level self._root = NodePath('Quadrant' + `serialNum`) self._model.reparentTo(self._root) self._root.reparentTo(parent) self._visible = True self.platforms = {} self.gatherables = [] self.obstacles = [] self._playing = False self._obstaclesRoot = NodePath('obstacles') self._obstaclesRoot.reparentTo(self._root) self._initObstacles(self._obstaclesRoot) self._gatherablesRoot = NodePath('gatherables') self._gatherablesRoot.reparentTo(self._root) self._initGatherables(self._gatherablesRoot) self._platformsRoot = NodePath('platforms') self._platformsRoot.reparentTo(self._model) self._initPlatforms(self._platformsRoot) self._optimize() self.place() def _optimize(self): lightCones = NodePath('lightCones') for np in self._platformsRoot.findAllMatches('**/*lightCone*'): np.wrtReparentTo(lightCones) lightCones.reparentTo(self._model) node = self._model.find('**/ducts') if not node.isEmpty(): node.flattenStrong() for np in node.getChildren(): np.wrtReparentTo(self._model) node = self._model.find('**/nests') if not node.isEmpty(): for np in node.getChildren(): np.flattenStrong() np.wrtReparentTo(self._model) for np in self._model.findAllMatches('**/*LayerStack*'): np.wrtReparentTo(self._model) if not self._model.find('**/static').isEmpty(): for np in self._model.find('**/static').getChildren(): np.wrtReparentTo(self._model) self._model.flattenMedium() def _initPlatforms(self, parent): platformModels = self._model.findAllMatches('**/%s' % Globals.Level.PlatformName) for platformModel in platformModels: platform = CogdoFlyingPlatform(platformModel, parent=parent) self.platforms[platform.getName()] = platform def _destroyPlatforms(self): for platform in self.platforms.values(): platform.destroy() del self.platforms def _initGatherables(self, parent): self.generateGatherables(self._model, parent=parent) if Globals.Level.SpawnLaffPowerupsInNests: self.generateNestPowerups(self._model, parent=parent) def generateNestPowerups(self, gatherableModel, parent): nests = gatherableModel.findAllMatches('**/%s;+s' % Globals.Level.LegalEagleNestName) for nest in nests: offset = Globals.Level.LaffPowerupNestOffset pickup = self._level.gatherableFactory.createPowerup(Globals.Level.GatherableTypes.LaffPowerup) pickup.reparentTo(parent) pickup.setPos(parent, nest.getPos(parent) + offset) if Globals.Level.AddSparkleToPowerups: sparkles = self._level.gatherableFactory.createSparkles(Vec4(1, 1, 1, 1), Vec4(1, 1, 0, 1), 10.0) sparkles.reparentTo(pickup) sparkles.setPos(0, 0, 1) sparkles.start() self.gatherables.append(pickup) def generateGatherables(self, gatherableModel, parent = None, spread = Globals.Level.GatherablesDefaultSpread): parent = parent or self._root mopath = Mopath.Mopath(name='gatherables') def generateMemos(): gatherPaths = gatherableModel.findAllMatches('**/%s' % Globals.Level.GatherablesPathName) for gatherPath in gatherPaths: mopath.loadNodePath(gatherPath) t = 0.0 while t < mopath.getMaxT(): pickup = self._level.gatherableFactory.createMemo() pickup.reparentTo(parent) mopath.goTo(pickup, t) self.gatherables.append(pickup) t += spread gatherPath.removeNode() angleSpread = 360.0 / Globals.Level.NumMemosInRing gatherPaths = gatherableModel.findAllMatches('**/%s' % Globals.Level.GatherablesRingName) for gatherPath in gatherPaths: mopath.loadNodePath(gatherPath) t = 0.0 while t < mopath.getMaxT(): angle = 0 r = 3 while angle < 360.0: pickup = self._level.gatherableFactory.createMemo() pickup.reparentTo(parent) mopath.goTo(pickup, t) pickup.setX(parent, pickup.getX() + r * math.cos(math.radians(angle))) pickup.setZ(parent, pickup.getZ() + r * math.sin(math.radians(angle))) self.gatherables.append(pickup) angle += angleSpread t += spread + 0.5 gatherPath.removeNode() def generatePropellers(): gatherables = gatherableModel.findAllMatches('**/%s' % Globals.Level.PropellerName) for gatherable in gatherables: pickup = self._level.gatherableFactory.createPropeller() pickup.reparentTo(gatherable.getParent()) pickup.setPos(parent, gatherable.getPos(parent)) self.gatherables.append(pickup) gatherable.removeNode() def generatePowerUps(): for powerupType, locName in Globals.Level.PowerupType2Loc.iteritems(): gatherables = gatherableModel.findAllMatches('**/%s' % locName) for gatherable in gatherables: pickup = self._level.gatherableFactory.createPowerup(powerupType) pickup.reparentTo(parent) pickup.setPos(parent, gatherable.getPos(parent)) if Globals.Level.AddSparkleToPowerups: sparkles = self._level.gatherableFactory.createSparkles(Vec4(1, 1, 1, 1), Vec4(1, 1, 0, 1), 10.0) sparkles.reparentTo(pickup) sparkles.setPos(0, 0, 1) sparkles.start() self.gatherables.append(pickup) gatherable.removeNode() generateMemos() generatePropellers() generatePowerUps() def _initObstacles(self, parent): def initWhirlwinds(): obstacles = self._root.findAllMatches('**/%s' % Globals.Level.WhirlwindName) for obstacleLoc in obstacles: motionPath = self._model.find('**/%s%s' % (obstacleLoc.getName(), Globals.Level.WhirlwindPathName)) if motionPath.isEmpty(): motionPath = None obstacle = self._level.obstacleFactory.createWhirlwind(motionPath=motionPath) obstacle.model.reparentTo(parent) obstacle.model.setPos(parent, obstacleLoc.getPos(parent)) self.obstacles.append(obstacle) obstacleLoc.removeNode() def initStreamers(): obstacles = self._model.findAllMatches('**/%s' % Globals.Level.StreamerName) for obstacleLoc in obstacles: obstacle = self._level.obstacleFactory.createFan() obstacle.model.reparentTo(parent) obstacle.model.setPos(parent, obstacleLoc.getPos(parent)) obstacle.model.setHpr(parent, obstacleLoc.getHpr(parent)) obstacle.model.setScale(parent, obstacleLoc.getScale(parent)) obstacle.setBlowDirection() if Globals.Level.AddParticlesToStreamers: particles = self._level.obstacleFactory.createStreamerParticles(Vec4(1, 1, 1, 1), Vec4(1, 1, 1, 1), 10.0) particles.reparentTo(obstacle.model) particles.start() self.obstacles.append(obstacle) obstacleLoc.removeNode() def initWalkingMinions(): motionPaths = self._model.findAllMatches('**/%s' % Globals.Level.MinionWalkingPathName) for motionPath in motionPaths: obstacle = self._level.obstacleFactory.createWalkingMinion(motionPath=motionPath) obstacle.model.reparentTo(parent) obstacle.model.setPos(parent, motionPath.getPos(parent)) self.obstacles.append(obstacle) def initFlyingMinions(): motionPaths = self._model.findAllMatches('**/%s' % Globals.Level.MinionFlyingPathName) for motionPath in motionPaths: obstacle = self._level.obstacleFactory.createFlyingMinion(motionPath=motionPath) obstacle.model.reparentTo(parent) obstacle.model.setPos(parent, motionPath.getPos(parent)) self.obstacles.append(obstacle) initWhirlwinds() initStreamers() initWalkingMinions() initFlyingMinions() def place(self): self._root.setPos(0, self._level.convertQuadNumToY(self.serialNum), 0) def destroy(self): if self._visible: self.offstage() self._destroyPlatforms() for obstacle in self.obstacles: obstacle.destroy() for gatherable in self.gatherables: gatherable.destroy() self._root.removeNode() del self._root del self._gatherablesRoot del self._obstaclesRoot del self._platformsRoot del self._level def onstage(self, elapsedTime = 0.0): if self._visible: return self._root.unstash() for obstacle in self.obstacles: obstacle.startMoving(elapsedTime) for gatherable in self.gatherables: gatherable.show() self._visible = True def offstage(self): if not self._visible: return self._root.stash() for obstacle in self.obstacles: obstacle.stopMoving() for gatherable in self.gatherables: gatherable.hide() self._visible = False def update(self, dt): if self._visible: for gatherable in self.gatherables: gatherable.update(dt) for obstacle in self.obstacles: obstacle.update(dt) def getModel(self): return self._root
class CogdoFlyingGuiManager: ClearMessageDisplayEventName = 'ClearMessageDisplayEvent' EagleTargetingLocalPlayerEventName = 'EagleTargetingLocalPlayerEvent' EagleAttackingLocalPlayerEventName = 'EagleAttackingLocalPlayerEvent' FirstPressOfCtrlEventName = 'FirstPressOfCtrlEvent' PickedUpFirstPropellerEventName = 'PickedUpFirstPropellerEvent' InvulnerableEventName = 'InvulnerableEvent' StartRunningOutOfTimeMusicEventName = 'StartRunningOutOfTimeEvent' def __init__(self, level): self._level = level self.root = NodePath('CogdoFlyingGui') self.root.reparentTo(aspect2d) self.root.stash() self._initTimer() self._initHud() self._initMessageDisplay() self.sentTimeRunningOutMessage = False self._refuelGui = CogdoFlyingFuelGui(self.root) self._progressGui = CogdoFlyingProgressGui(self.root, self._level) def _initHud(self): self._memoGui = CogdoMemoGui(self.root) self._memoGui.posNextToLaffMeter() def _initTimer(self): self._timer = ToontownTimer() self._timer.reparentTo(self.root) self._timer.posInTopRightCorner() def _initMessageDisplay(self): audioMgr = base.cogdoGameAudioMgr sound = audioMgr.createSfx('popupHelpText') self._messageDisplay = CogdoGameMessageDisplay('CogdoFlyingMessageDisplay', self.root, sfx=sound) def destroyTimer(self): if self._timer is not None: self._timer.stop() self._timer.destroy() self._timer = None return def onstage(self): self.root.unstash() self._refuelGui.hide() self._progressGui.hide() def presentProgressGui(self): ToontownIntervals.start(ToontownIntervals.getPresentGuiIval(self._progressGui, 'present_progress_gui')) def presentRefuelGui(self): ToontownIntervals.start(ToontownIntervals.getPresentGuiIval(self._refuelGui, 'present_fuel_gui')) def presentTimerGui(self): ToontownIntervals.start(ToontownIntervals.getPresentGuiIval(self._timer, 'present_timer_gui')) def presentMemoGui(self): ToontownIntervals.start(ToontownIntervals.getPresentGuiIval(self._memoGui, 'present_memo_gui')) def offstage(self): self.root.stash() self._refuelGui.hide() self._progressGui.hide() self.hideTimer() def getTimeLeft(self): return Globals.Gameplay.SecondsUntilGameOver - self._timer.getElapsedTime() def isTimeRunningOut(self): return self.getTimeLeft() < Globals.Gameplay.TimeRunningOutSeconds def startTimer(self, duration, timerExpiredCallback = None, keepHidden = False): if self._timer is None: self._initTimer() self._timer.setTime(duration) self._timer.countdown(duration, timerExpiredCallback) if keepHidden: self.hideTimer() else: self.showTimer() return def stopTimer(self): if hasattr(self, '_timer') and self._timer is not None: self.hideTimer() self._timer.stop() return def showTimer(self): self._timer.show() def hideTimer(self): self._timer.hide() def forceTimerDone(self): if self._timer.countdownTask != None: self._timer.countdownTask.duration = 0 return def showRefuelGui(self): self._refuelGui.show() def hideRefuelGui(self): self._refuelGui.hide() def setMessage(self, text, color = None, transition = 'fade'): self._messageDisplay.updateMessage(text, color, transition) def setTemporaryMessage(self, text, duration = 3.0, color = None): self._messageDisplay.showMessageTemporarily(text, duration, color) def setFuel(self, fuel): self._refuelGui.setFuel(fuel) def resetBlades(self): self._refuelGui.resetBlades() def setBlades(self, fuelState): self._refuelGui.setBlades(fuelState) def bladeLost(self): self._refuelGui.bladeLost() def setPropellerSpinRate(self, newRate): self._refuelGui.setPropellerSpinRate(newRate) def setMemoCount(self, score): self._memoGui.setCount(score) def addToonToProgressMeter(self, toon): self._progressGui.addToon(toon) def removeToonFromProgressMeter(self, toon): self._progressGui.removeToon(toon) def update(self): if self.isTimeRunningOut() and not self.sentTimeRunningOutMessage: messenger.send(CogdoFlyingGuiManager.StartRunningOutOfTimeMusicEventName) self.sentTimeRunningOutMessage = True self._refuelGui.update() self._progressGui.update() def destroy(self): ToontownIntervals.cleanup('present_fuel_gui') ToontownIntervals.cleanup('present_timer_gui') ToontownIntervals.cleanup('present_memo_gui') ToontownIntervals.cleanup('present_progress_gui') self._refuelGui.destroy() self._refuelGui = None self._memoGui.destroy() self._memoGui = None self._progressGui.destroy() self._progressGui = None self.destroyTimer() self._messageDisplay.destroy() self._messageDisplay = None self.root.removeNode() self.root = None return
class RepairPitchingGame(RepairMincroGame): __module__ = __name__ def __init__(self, repairGame): self.config = RepairGlobals.Pitching RepairMincroGame.__init__(self, repairGame, 'pitching', PLocalizer.Minigame_Repair_Pitching_Start) def _initVars(self): RepairMincroGame._initVars(self) self.nextSpawnTime = 0.0 self.inactiveLeaks = set() self.activeLeaks = set() self.patchedLeaks = set() self.locators = [] self.leakCount = 0 self.maxLeaks = 0 self.bucketPouring = False def _initAudio(self): RepairMincroGame._initAudio(self) self.pitchSounds = (loadSfx( SoundGlobals.SFX_MINIGAME_REPAIR_PITCH_PLUG01), loadSfx( SoundGlobals.SFX_MINIGAME_REPAIR_PITCH_PLUG02), loadSfx( SoundGlobals.SFX_MINIGAME_REPAIR_PITCH_PLUG03)) self.leakSounds = (loadSfx( SoundGlobals.SFX_MINIGAME_REPAIR_PITCH_LEAK01), loadSfx( SoundGlobals.SFX_MINIGAME_REPAIR_PITCH_LEAK02), loadSfx( SoundGlobals.SFX_MINIGAME_REPAIR_PITCH_LEAK03), loadSfx( SoundGlobals.SFX_MINIGAME_REPAIR_PITCH_LEAK04)) def _initVisuals(self): RepairMincroGame._initVisuals(self) self.model = loader.loadModel('models/gui/pir_m_gui_srp_pitching_main') self.board = self.model.find('**/piece_hull') self.board.reparentTo(self) self.board.setPos(0.0, 0.0, 0.19) self.crossHair = self.model.find('**/crosshair') self.crossHair.reparentTo(base.a2dBackground) self.crossHair.setBin('fixed', 45) self.crossHair.setScale(1.0) self.crossHair.setColorScale(0.0, 1.0, 0.0, 1.0) self.crossHair.stash() self.bucketIdle = self.model.find('**/pitchCursor/idle') self.bucketIdle.reparentTo(base.a2dBackground) self.bucketIdle.setBin('fixed', 45) self.bucketIdle.setScale(1.35) self.bucketIdle.stash() self.bucket = self.bucketIdle.copyTo(NodePath()) self.bucket.reparentTo(base.a2dBackground) self.bucket.setHpr(0, 0, 90) self.bucket.setBin('fixed', 45) self.bucket.setScale(1.35) self.bucket.stash() self.missPatch = NodePath('dummy') self.missPatchAsset = self.model.find('**/miss') self.missPatchAsset.reparentTo(self.missPatch) self.missPatch.reparentTo(self) self.missPatch.setScale(1.1) self.missPatch.stash() self.missSeq = None index = 1 while True: locator = self.model.find('**/locator_%i' % index) if locator.isEmpty(): break self.locators.append(locator) index += 1 return def onMouseUp(self): self.bucketPouring = False def onMouseDown(self): self.bucketPouring = True if base.mouseWatcherNode.hasMouse(): mpos = base.mouseWatcherNode.getMouse() mpos = Point3(mpos.getX(), mpos.getY(), 0.0) mpos = aspect2d.getRelativePoint(render2d, mpos) if self.missSeq is not None: self.missSeq.finish() self.missPatch.unstash() self.missPatch.setPos(mpos.getX(), 0.0, mpos.getY() + 0.2) self.missPatchAsset.setPos(0.0, 0.0, 0.0) self.missSeq = Sequence( Parallel( LerpPosInterval(self.missPatch, duration=1.5, blendType='easeIn', pos=(mpos.getX(), 0.0, mpos.getY() - 0.15)), LerpPosInterval(self.missPatchAsset, duration=1.5, blendType='easeOut', pos=(0.2, 0.0, 0.0)), LerpColorScaleInterval(self.missPatch, duration=1.5, blendType='easeIn', startColorScale=(1.0, 1.0, 1.0, 1.0), colorScale=(1.0, 1.0, 1.0, 0.0))), Func(self.missPatch.stash)) self.missSeq.start() return def reset(self): if self.missSeq is not None: self.missSeq.finish() self.clearLeaks() for i in range(self.leakCount): self.createLeak('leak%i' % i) self.repairGame.gui.setTutorial(self.name) self.repairGame.gui.setTitle(self.name) self.bucketPouring = False return def destroy(self): RepairMincroGame.destroy(self) for leakSet in (self.activeLeaks, self.inactiveLeaks, self.patchedLeaks): for i in range(len(leakSet)): leak = leakSet.pop() del self.activeLeaks del self.inactiveLeaks del self.patchedLeaks for locator in self.locators: locator.removeNode() del self.locators self.board.removeNode() del self.board self.crossHair.removeNode() del self.crossHair self.bucket.removeNode() del self.bucket self.bucketIdle.removeNode() del self.bucketIdle if self.missSeq is not None: self.missSeq.finish() del self.missSeq self.missPatch.removeNode() del self.missPatch return def setDifficulty(self, difficulty): RepairMincroGame.setDifficulty(self, difficulty) percent = difficulty / self.repairGame.difficultyMax dif = self.config.leakCountRange[1] - self.config.leakCountRange[0] self.leakCount = int( math.floor(self.config.leakCountRange[0] + dif * percent)) dif = self.config.maxLeaksRange[1] - self.config.maxLeaksRange[0] self.maxLeaks = int( math.floor(self.config.maxLeaksRange[0] + dif * percent)) dif = self.config.spawnDelayRange[1] - self.config.spawnDelayRange[0] self.minSpawnTime = self.config.spawnDelayRange[0] + dif * percent dif = self.config.spawnDelayRange[3] - self.config.spawnDelayRange[2] self.maxSpawnTime = self.config.spawnDelayRange[2] + dif * percent def clearLeaks(self): for leakSet in (self.activeLeaks, self.inactiveLeaks, self.patchedLeaks): for i in range(len(leakSet)): leak = leakSet.pop() leak.destroy() _MIN_DIST = 0.2 _MAX_TRIES = 10 def placeLeak(self, leak): tooClose = True attempts = 0 while tooClose and attempts < self._MAX_TRIES: attempts += 1 locator = self.locators[random.randint(0, len(self.locators) - 1)] relative = self.getRelativePoint( self.board, Point3(locator.getX(), 0, locator.getZ())) x = relative.getX() z = relative.getZ() tooClose = False for otherLeak in self.activeLeaks: dist = math.hypot(otherLeak.getX() - x, otherLeak.getZ() - z) if dist < self._MIN_DIST: tooClose = True for otherLeak in self.patchedLeaks: dist = math.hypot(otherLeak.getX() - x, otherLeak.getZ() - z) if dist < self._MIN_DIST: tooClose = True leak.repositionTo(x, z) def createLeak(self, name): scale = random.uniform(self.config.leakScaleRange[0], self.config.leakScaleRange[1]) leak = RepairLeak(name=name, parent=self, leakscale=scale, command=self.onLeakPressed) leak['extraArgs'] = [leak] leak.onCleanup = self.cleanupLeak self.inactiveLeaks.add(leak) leak.request('Idle') def cleanupLeak(self, leak): if leak in self.patchedLeaks: self.patchedLeaks.remove(leak) def onLeakPressed(self, leak): self.bucketPouring = True if leak in self.activeLeaks: self.activeLeaks.remove(leak) self.patchedLeaks.add(leak) leak.request('Patched') numLeaks = len(self.activeLeaks) remainingLeaks = len(self.inactiveLeaks) + numLeaks percent = 100 - int((remainingLeaks + 0.0) / self.leakCount * 100) random.choice(self.pitchSounds).play() self.repairGame.d_reportMincroGameProgress( percent, max(0, min(4, 4 + self.config.ratingGive - numLeaks))) self.checkWin() def springLeak(self): leakSound = random.choice(self.leakSounds) if not leakSound.status() == AudioSound.PLAYING: leakSound.play() newLeak = self.inactiveLeaks.pop() self.placeLeak(newLeak) self.activeLeaks.add(newLeak) newLeak.request('Active') def checkWin(self): if len(self.inactiveLeaks) == 0: if len(self.activeLeaks) == 0: self.request('Outro') def updateTask(self, task): elapsedTime = self.repairGame.repairClock.getTime() if len(self.activeLeaks) == 0: if len(self.inactiveLeaks) > 0: self.springLeak() if elapsedTime >= self.nextSpawnTime: if len(self.inactiveLeaks) > 0: self.nextSpawnTime = elapsedTime + random.uniform( self.minSpawnTime, self.maxSpawnTime) if len(self.activeLeaks) < self.maxLeaks: self.springLeak() if base.mouseWatcherNode.hasMouse(): mpos = base.mouseWatcherNode.getMouse() mpos = Point3(mpos.getX(), mpos.getY(), 0.0) mpos = aspect2d.getRelativePoint(render2d, mpos) if self.config.useReticle: activeXOffset = -0.14 activeYOffset = 0.02 idleXOffset = -0.17 idleYOffset = -0.08 self.crossHair.unstash() self.crossHair.setPos(mpos.getX(), 0.0, mpos.getY()) else: activeXOffset = -0.06 activeYOffset = 0.07 idleXOffset = -0.08 idleYOffset = -0.03 self.crossHair.stash() self.bucketPouring and self.bucketIdle.stash() self.bucket.unstash() self.bucket.setPos(mpos.getX() + activeXOffset, 0.0, mpos.getY() + activeYOffset) else: self.bucketIdle.unstash() self.bucket.stash() self.bucketIdle.setPos(mpos.getX() + idleXOffset, 0.0, mpos.getY() + idleYOffset) return Task.cont def enterGame(self): RepairMincroGame.enterGame(self) taskMgr.add(self.updateTask, 'RepairPitchingGame.updateTask') self.bucketPouring = False self.accept('mouse1', self.onMouseDown) self.accept('mouse1-up', self.onMouseUp) self.nextSpawnTime = 0.0 def exitGame(self): self.bucket.stash() self.bucketIdle.stash() self.crossHair.stash() RepairMincroGame.exitGame(self) self.ignore('mouse1') self.ignore('mouse1-up') taskMgr.remove('RepairPitchingGame.updateTask') self.clearLeaks() self.bucket.stash() self.bucketIdle.stash() def enterOutro(self): RepairMincroGame.enterOutro(self) self.repairGame.d_reportMincroGameScore(150)
class CogdoExecutiveSuiteIntro(CogdoGameMovie): notify = DirectNotifyGlobal.directNotify.newCategory( 'CogdoExecutiveSuiteIntro') introDuration = 7 cameraMoveDuration = 3 def __init__(self, shopOwner): CogdoGameMovie.__init__(self) self._shopOwner = shopOwner self._lookAtCamTarget = False self._camTarget = None self._camHelperNode = None self._toonDialogueSfx = None self.toonHead = None self.frame = None return def displayLine(self, text): self.notify.debug('displayLine') self._dialogueLabel.node().setText(text) self.toonHead.reparentTo(aspect2d) self._toonDialogueSfx.play() self.toonHead.setClipPlane(self.clipPlane) def makeSuit(self, suitType): self.notify.debug('makeSuit()') suit = Suit.Suit() dna = SuitDNA.SuitDNA() dna.newSuit(suitType) suit.setStyle(dna) suit.isDisguised = 1 suit.generateSuit() suit.setScale(1, 1, 2) suit.setPos(0, 0, -4.4) suit.reparentTo(self.toonHead) for part in suit.getHeadParts(): part.hide() def load(self): self.notify.debug('load()') CogdoGameMovie.load(self) backgroundGui = loader.loadModel( 'phase_5/models/cogdominium/tt_m_gui_csa_flyThru') self.bg = backgroundGui.find('**/background') self.chatBubble = backgroundGui.find('**/chatBubble') self.chatBubble.setScale(6.5, 6.5, 7.3) self.chatBubble.setPos(0.32, 0, -0.78) self.bg.setScale(5.2) self.bg.setPos(0.14, 0, -0.6667) self.bg.reparentTo(aspect2d) self.chatBubble.reparentTo(aspect2d) self.frame = DirectFrame(geom=self.bg, relief=None, pos=(0.2, 0, -0.6667)) self.bg.wrtReparentTo(self.frame) self.gameTitleText = DirectLabel( parent=self.frame, text=TTLocalizer.CogdoExecutiveSuiteTitle, scale=TTLocalizer.MRPgameTitleText * 0.8, text_align=TextNode.ACenter, text_font=getSignFont(), text_fg=(1.0, 0.33, 0.33, 1.0), pos=TTLocalizer.MRgameTitleTextPos, relief=None) self.chatBubble.wrtReparentTo(self.frame) self.frame.hide() backgroundGui.removeNode() self.toonDNA = ToonDNA.ToonDNA() self.toonDNA.newToonFromProperties('dss', 'ss', 'm', 'm', 2, 0, 2, 2, 1, 8, 1, 8, 1, 14) self.toonHead = Toon.Toon() self.toonHead.setDNA(self.toonDNA) self.makeSuit('sc') self.toonHead.getGeomNode().setDepthWrite(1) self.toonHead.getGeomNode().setDepthTest(1) self.toonHead.loop('neutral') self.toonHead.setPosHprScale(-0.73, 0, -1.27, 180, 0, 0, 0.18, 0.18, 0.18) self.toonHead.reparentTo(hidden) self.toonHead.startBlink() self.clipPlane = self.toonHead.attachNewNode(PlaneNode('clip')) self.clipPlane.node().setPlane(Plane(0, 0, 1, 0)) self.clipPlane.setPos(0, 0, 2.45) self._toonDialogueSfx = loader.loadSfx( 'phase_3.5/audio/dial/AV_dog_long.ogg') self._camHelperNode = NodePath('CamHelperNode') self._camHelperNode.reparentTo(render) dialogue = TTLocalizer.CogdoExecutiveSuiteIntroMessage def start(): self.frame.show() base.setCellsAvailable( base.bottomCells + base.leftCells + base.rightCells, 0) def showShopOwner(): self._setCamTarget(self._shopOwner, -10, offset=Point3(0, 0, 5)) def end(): self._dialogueLabel.reparentTo(hidden) self.toonHead.reparentTo(hidden) self.frame.hide() base.setCellsAvailable( base.bottomCells + base.leftCells + base.rightCells, 1) self._stopUpdateTask() self._ival = Sequence( Func(start), Func(self.displayLine, dialogue), Func(showShopOwner), ParallelEndTogether( camera.posInterval(self.cameraMoveDuration, Point3(8, 0, 13), blendType='easeInOut'), camera.hprInterval(0.5, self._camHelperNode.getHpr(), blendType='easeInOut')), Wait(self.introDuration), Func(end)) self._startUpdateTask() return def _setCamTarget(self, targetNP, distance, offset=Point3(0, 0, 0), angle=Point3(0, 0, 0)): camera.wrtReparentTo(render) self._camTarget = targetNP self._camOffset = offset self._camAngle = angle self._camDistance = distance self._camHelperNode.setPos(self._camTarget, self._camOffset) self._camHelperNode.setHpr(self._camTarget, 180 + self._camAngle[0], self._camAngle[1], self._camAngle[2]) self._camHelperNode.setPos(self._camHelperNode, 0, self._camDistance, 0) def _updateTask(self, task): dt = globalClock.getDt() return task.cont def unload(self): self._shopOwner = None self._camTarget = None if hasattr(self, '_camHelperNode') and self._camHelperNode: self._camHelperNode.removeNode() del self._camHelperNode self.frame.destroy() del self.frame self.bg.removeNode() del self.bg self.chatBubble.removeNode() del self.chatBubble self.toonHead.stopBlink() self.toonHead.stop() self.toonHead.removeNode() self.toonHead.delete() del self.toonHead CogdoGameMovie.unload(self) return
class DistributedButterfly(DistributedObject.DistributedObject): notify = DirectNotifyGlobal.directNotify.newCategory('DistributedButterfly') id = 0 wingTypes = ('wings_1', 'wings_2', 'wings_3', 'wings_4', 'wings_5', 'wings_6') yellowColors = (Vec4(1, 1, 1, 1), Vec4(0.2, 0, 1, 1), Vec4(0.8, 0, 1, 1)) whiteColors = (Vec4(0.8, 0, 0.8, 1), Vec4(0, 0.8, 0.8, 1), Vec4(0.9, 0.4, 0.6, 1), Vec4(0.9, 0.4, 0.4, 1), Vec4(0.8, 0.5, 0.9, 1), Vec4(0.4, 0.1, 0.7, 1)) paleYellowColors = (Vec4(0.8, 0, 0.8, 1), Vec4(0.6, 0.6, 0.9, 1), Vec4(0.7, 0.6, 0.9, 1), Vec4(0.8, 0.6, 0.9, 1), Vec4(0.9, 0.6, 0.9, 1), Vec4(1, 0.6, 0.9, 1)) shadowScaleBig = Point3(0.07, 0.07, 0.07) shadowScaleSmall = Point3(0.01, 0.01, 0.01) def __init__(self, cr): DistributedObject.DistributedObject.__init__(self, cr) self.fsm = ClassicFSM.ClassicFSM('DistributedButterfly', [State.State('off', self.enterOff, self.exitOff, ['Flying', 'Landed']), State.State('Flying', self.enterFlying, self.exitFlying, ['Landed']), State.State('Landed', self.enterLanded, self.exitLanded, ['Flying'])], 'off', 'off') self.butterfly = None self.butterflyNode = None self.curIndex = 0 self.destIndex = 0 self.time = 0.0 self.ival = None self.fsm.enterInitialState() return def generate(self): DistributedObject.DistributedObject.generate(self) if self.butterfly: return self.butterfly = Actor.Actor() self.butterfly.loadModel('phase_4/models/props/SZ_butterfly-mod') self.butterfly.loadAnims({'flutter': 'phase_4/models/props/SZ_butterfly-flutter', 'glide': 'phase_4/models/props/SZ_butterfly-glide', 'land': 'phase_4/models/props/SZ_butterfly-land'}) index = self.doId % len(self.wingTypes) chosenType = self.wingTypes[index] node = self.butterfly.getGeomNode() for type in self.wingTypes: wing = node.find('**/' + type) if type != chosenType: wing.removeNode() else: if index == 0 or index == 1: color = self.yellowColors[self.doId % len(self.yellowColors)] elif index == 2 or index == 3: color = self.whiteColors[self.doId % len(self.whiteColors)] elif index == 4: color = self.paleYellowColors[self.doId % len(self.paleYellowColors)] else: color = Vec4(1, 1, 1, 1) wing.setColor(color) self.butterfly2 = Actor.Actor(other=self.butterfly) self.butterfly.enableBlend(blendType=PartBundle.BTLinear) self.butterfly.loop('flutter') self.butterfly.loop('land') self.butterfly.loop('glide') rng = RandomNumGen.RandomNumGen(self.doId) playRate = 0.6 + 0.8 * rng.random() self.butterfly.setPlayRate(playRate, 'flutter') self.butterfly.setPlayRate(playRate, 'land') self.butterfly.setPlayRate(playRate, 'glide') self.butterfly2.setPlayRate(playRate, 'flutter') self.butterfly2.setPlayRate(playRate, 'land') self.butterfly2.setPlayRate(playRate, 'glide') self.glideWeight = rng.random() * 2 lodNode = LODNode('butterfly-node') lodNode.addSwitch(100, 40) lodNode.addSwitch(40, 0) self.butterflyNode = NodePath(lodNode) self.butterfly2.setH(180.0) self.butterfly2.reparentTo(self.butterflyNode) self.butterfly.setH(180.0) self.butterfly.reparentTo(self.butterflyNode) self.__initCollisions() self.dropShadow = loader.loadModel('phase_3/models/props/drop_shadow') self.dropShadow.setColor(0, 0, 0, 0.3) self.dropShadow.setPos(0, 0.1, -0.05) self.dropShadow.setScale(self.shadowScaleBig) self.dropShadow.reparentTo(self.butterfly) def disable(self): self.butterflyNode.reparentTo(hidden) if self.ival != None: self.ival.finish() self.__ignoreAvatars() DistributedObject.DistributedObject.disable(self) return def delete(self): self.butterfly.cleanup() self.butterfly = None self.butterfly2.cleanup() self.butterfly2 = None self.butterflyNode.removeNode() self.__deleteCollisions() self.ival = None del self.fsm DistributedObject.DistributedObject.delete(self) return def uniqueButterflyName(self, name): DistributedButterfly.id += 1 return name + '-%d' % DistributedButterfly.id def __detectAvatars(self): self.accept('enter' + self.cSphereNode.getName(), self.__handleCollisionSphereEnter) def __ignoreAvatars(self): self.ignore('enter' + self.cSphereNode.getName()) def __initCollisions(self): self.cSphere = CollisionSphere(0.0, 1.0, 0.0, 3.0) self.cSphere.setTangible(0) self.cSphereNode = CollisionNode(self.uniqueButterflyName('cSphereNode')) self.cSphereNode.addSolid(self.cSphere) self.cSphereNodePath = self.butterflyNode.attachNewNode(self.cSphereNode) self.cSphereNodePath.hide() self.cSphereNode.setCollideMask(ToontownGlobals.WallBitmask) def __deleteCollisions(self): del self.cSphere del self.cSphereNode self.cSphereNodePath.removeNode() del self.cSphereNodePath def __handleCollisionSphereEnter(self, collEntry): self.sendUpdate('avatarEnter', []) def setArea(self, playground, area): self.playground = playground self.area = area def setState(self, stateIndex, curIndex, destIndex, time, timestamp): self.curIndex = curIndex self.destIndex = destIndex self.time = time self.fsm.request(ButterflyGlobals.states[stateIndex], [globalClockDelta.localElapsedTime(timestamp)]) def enterOff(self, ts = 0.0): if self.butterflyNode != None: self.butterflyNode.reparentTo(hidden) return def exitOff(self): if self.butterflyNode != None: self.butterflyNode.reparentTo(render) return def enterFlying(self, ts): self.__detectAvatars() curPos = ButterflyGlobals.ButterflyPoints[self.playground][self.area][self.curIndex] destPos = ButterflyGlobals.ButterflyPoints[self.playground][self.area][self.destIndex] flyHeight = max(curPos[2], destPos[2]) + ButterflyGlobals.BUTTERFLY_HEIGHT[self.playground] curPosHigh = Point3(curPos[0], curPos[1], flyHeight) destPosHigh = Point3(destPos[0], destPos[1], flyHeight) if ts <= self.time: flyTime = self.time - (ButterflyGlobals.BUTTERFLY_TAKEOFF[self.playground] + ButterflyGlobals.BUTTERFLY_LANDING[self.playground]) self.butterflyNode.setPos(curPos) self.dropShadow.show() self.dropShadow.setScale(self.shadowScaleBig) oldHpr = self.butterflyNode.getHpr() self.butterflyNode.headsUp(destPos) newHpr = self.butterflyNode.getHpr() self.butterflyNode.setHpr(oldHpr) takeoffShadowT = 0.2 * ButterflyGlobals.BUTTERFLY_TAKEOFF[self.playground] landShadowT = 0.2 * ButterflyGlobals.BUTTERFLY_LANDING[self.playground] self.butterfly2.loop('flutter') self.ival = Sequence(Parallel(LerpPosHprInterval(self.butterflyNode, ButterflyGlobals.BUTTERFLY_TAKEOFF[self.playground], curPosHigh, newHpr), LerpAnimInterval(self.butterfly, ButterflyGlobals.BUTTERFLY_TAKEOFF[self.playground], 'land', 'flutter'), LerpAnimInterval(self.butterfly, ButterflyGlobals.BUTTERFLY_TAKEOFF[self.playground], None, 'glide', startWeight=0, endWeight=self.glideWeight), Sequence(LerpScaleInterval(self.dropShadow, takeoffShadowT, self.shadowScaleSmall, startScale=self.shadowScaleBig), HideInterval(self.dropShadow))), LerpPosInterval(self.butterflyNode, flyTime, destPosHigh), Parallel(LerpPosInterval(self.butterflyNode, ButterflyGlobals.BUTTERFLY_LANDING[self.playground], destPos), LerpAnimInterval(self.butterfly, ButterflyGlobals.BUTTERFLY_LANDING[self.playground], 'flutter', 'land'), LerpAnimInterval(self.butterfly, ButterflyGlobals.BUTTERFLY_LANDING[self.playground], None, 'glide', startWeight=self.glideWeight, endWeight=0), Sequence(Wait(ButterflyGlobals.BUTTERFLY_LANDING[self.playground] - landShadowT), ShowInterval(self.dropShadow), LerpScaleInterval(self.dropShadow, landShadowT, self.shadowScaleBig, startScale=self.shadowScaleSmall))), name=self.uniqueName('Butterfly')) self.ival.start(ts) else: self.ival = None self.butterflyNode.setPos(destPos) self.butterfly.setControlEffect('land', 1.0) self.butterfly.setControlEffect('flutter', 0.0) self.butterfly.setControlEffect('glide', 0.0) self.butterfly2.loop('land') return def exitFlying(self): self.__ignoreAvatars() if self.ival != None: self.ival.finish() self.ival = None return def enterLanded(self, ts): self.__detectAvatars() curPos = ButterflyGlobals.ButterflyPoints[self.playground][self.area][self.curIndex] self.butterflyNode.setPos(curPos) self.dropShadow.show() self.dropShadow.setScale(self.shadowScaleBig) self.butterfly.setControlEffect('land', 1.0) self.butterfly.setControlEffect('flutter', 0.0) self.butterfly.setControlEffect('glide', 0.0) self.butterfly2.pose('land', random.randrange(self.butterfly2.getNumFrames('land'))) return None def exitLanded(self): self.__ignoreAvatars() return None
class CogdoFlyingLevel(DirectObject): notify = directNotify.newCategory('CogdoFlyingLevel') def __init__(self, parent, frameModel, startPlatformModel, endPlatformModel, quadLengthUnits, quadVisibilityAhead, quadVisibiltyBehind): self.parent = parent self.quadLengthUnits = quadLengthUnits self._halfQuadLengthUnits = quadLengthUnits / 2.0 self.quadVisibiltyAhead = quadVisibilityAhead self.quadVisibiltyBehind = quadVisibiltyBehind self._frameModel = frameModel self.root = NodePath('CogdoFlyingLevel') self.quadrantRoot = NodePath('QuadrantsRoot') self.quadrantRoot.reparentTo(self.root) self._startPlatformModel = startPlatformModel self._startPlatformModel.reparentTo(self.root) self._startPlatformModel.setZ(Globals.Level.StartPlatformHeight) self._endPlatformModel = endPlatformModel self._endPlatformModel.reparentTo(self.root) self._endPlatformModel.setZ(Globals.Level.EndPlatformHeight) self.wallR = self._frameModel.find('**/wallR') self.wallL = self._frameModel.find('**/wallL') self._exit = CogdoGameExit() self._exit.reparentTo(self._endPlatformModel) loc = self._endPlatformModel.find('**/exit_loc') offset = loc.getPos(render) self._exit.setPos(render, offset) self.quadrants = [] self.visibleQuadIndices = [] self._numQuads = 0 self._currentQuadNum = -1 self._camera = None self._initCollisions() self.upLimit = self._frameModel.find('**/limit_up').getZ(render) self.downLimit = self._frameModel.find('**/limit_down').getZ(render) self.leftLimit = self._frameModel.find('**/limit_left').getX( render) - 30.0 self.rightLimit = self._frameModel.find('**/limit_right').getX( render) + 30.0 self.backLimit = -self.quadLengthUnits self.forwardLimit = self.quadLengthUnits * 20 self._frameModel.flattenStrong() self.gatherableFactory = CogdoFlyingGatherableFactory() self.obstacleFactory = CogdoFlyingObtacleFactory() return def getExit(self): return self._exit def getBounds(self): return ((self.leftLimit, self.rightLimit), (self.backLimit, self.forwardLimit), (self.downLimit, self.upLimit)) def getGatherable(self, serialNum): for quadrant in self.quadrants: for gatherable in quadrant.gatherables: if gatherable.serialNum == serialNum: return gatherable return None def ready(self): self.gatherableFactory.destroy() del self.gatherableFactory self.obstacleFactory.destroy() del self.obstacleFactory self._initStartEndPlatforms() self._frameModel.reparentTo(self.root) self.root.reparentTo(self.parent) self.root.stash() def _initStartEndPlatforms(self): self.startPlatform = CogdoFlyingPlatform( self._startPlatformModel, Globals.Level.PlatformTypes.StartPlatform) self.endPlatform = CogdoFlyingPlatform( self._endPlatformModel, Globals.Level.PlatformTypes.EndPlatform) self._endPlatformModel.setY(self.convertQuadNumToY(self._numQuads)) self.backLimit = self._startPlatformModel.getY( render) - Globals.Level.StartPlatformLength * 0.7 self.forwardLimit = self._endPlatformModel.getY( render) + Globals.Level.EndPlatformLength * 0.7 def _initCollisions(self): self.collPlane = CollisionPlane( Plane(Vec3(0, 0, 1.0), Point3(0, 0, 10))) self.collPlane.setTangible(0) self.collNode = CollisionNode('fogPlane') self.collNode.setIntoCollideMask(OTPGlobals.FloorBitmask) self.collNode.addSolid(self.collPlane) self.collNodePath = self.root.attachNewNode(self.collNode) self.collNodePath.hide() def destroy(self): del self.collPlane self.collNodePath.removeNode() del self.collNodePath del self.collNode for quadrant in self.quadrants: quadrant.destroy() self._exit.destroy() del self._exit self.root.removeNode() del self.root def onstage(self): self.root.unstash() self.update(0.0) def offstage(self): self.root.stash() def start(self, startTime=0.0): self._startTime = startTime def stop(self): pass def getLength(self): return self.quadLengthUnits * self.getNumQuadrants() def appendQuadrant(self, model): quadrant = CogdoFlyingLevelQuadrant(self._numQuads, model, self, self.root) if self._numQuads == 0: quadrant.generateGatherables(self._startPlatformModel) quadrant.offstage() self.quadrants.append(quadrant) self._numQuads = len(self.quadrants) def getNumQuadrants(self): return self._numQuads def setCamera(self, camera): self._camera = camera def getCameraActualQuadrant(self): camY = self._camera.getY(render) y = self.root.getY(render) return self.convertYToQuadNum(camY - y) def update(self, dt=0.0): if self._camera is None: return quadNum = clamp(self.getCameraActualQuadrant(), 0, self._numQuads - 1) if quadNum < self._numQuads: self.quadrants[quadNum].update(dt) if quadNum + 1 < self._numQuads: self.quadrants[quadNum + 1].update(dt) if quadNum != self._currentQuadNum: self._switchToQuadrant(quadNum) return def _switchToQuadrant(self, quadNum): self.visibleQuadIndices = [] if quadNum >= 0: if quadNum > 0: self.quadrants[max(quadNum - self.quadVisibiltyBehind, 0)].onstage() for i in range( quadNum, min(quadNum + self.quadVisibiltyAhead + 1, self._numQuads)): self.quadrants[i].onstage() self.visibleQuadIndices.append(i) if i == 0: self.startPlatform.onstage() elif i == self._numQuads - 1: self.endPlatform.onstage() self._currentQuadNum = quadNum for i in range( 0, max( self._currentQuadNum - self.quadVisibiltyBehind, 0)) + range( min(self._currentQuadNum + self.quadVisibiltyAhead + 1, self._numQuads), self._numQuads): self.quadrants[i].offstage() if i == 0: self.startPlatform.offstage() elif i == self._numQuads - 1: self.endPlatform.offstage() def convertQuadNumToY(self, quadNum): return quadNum * self.quadLengthUnits def convertYToQuadNum(self, y): return int(y / self.quadLengthUnits) def convertCenterYToQuadNum(self, y): return self.convertYToQuadNum(y + self._halfQuadLengthUnits)
class CogdoMazeGameIntro(CogdoGameMovie): def __init__(self, maze, exit, rng): CogdoGameMovie.__init__(self) self._maze = maze self._exit = exit self._rng = RandomNumGen(rng) self._camTarget = None self._state = 0 self._suits = [] return def _getRandomLine(self, lineList): return CogdoUtil.getRandomDialogueLine(lineList, self._rng) def displayLine(self, who, text): self._dialogueLabel.node().setText(text) if who == 'toon': self.toonHead.reparentTo(aspect2d) self.cogHead.reparentTo(hidden) self._toonDialogueSfx.play() self.toonHead.setClipPlane(self.clipPlane) else: self.toonHead.reparentTo(hidden) self.cogHead.reparentTo(aspect2d) self._cogDialogueSfx.play() self.cogHead.setClipPlane(self.clipPlane) def makeSuit(self, suitType): suit = Suit.Suit() dna = SuitDNA.SuitDNA() dna.newSuit(suitType) suit.setStyle(dna) suit.isDisguised = 1 suit.generateSuit() suit.setScale(1, 1, 2) suit.setPos(0, 0, -4.4) suit.reparentTo(self.toonHead) for part in suit.getHeadParts(): part.hide() suit.loop('neutral') def load(self): CogdoGameMovie.load(self) self.toonDNA = ToonDNA.ToonDNA() self.toonDNA.newToonFromProperties('dss', 'ss', 'm', 'm', 2, 0, 2, 2, 1, 8, 1, 8, 1, 14) self.toonHead = Toon.Toon() self.toonHead.setDNA(self.toonDNA) self.makeSuit('sc') self.toonHead.getGeomNode().setDepthWrite(1) self.toonHead.getGeomNode().setDepthTest(1) self.toonHead.loop('neutral') self.toonHead.setPosHprScale(-0.73, 0, -1.27, 180, 0, 0, 0.18, 0.18, 0.18) self.toonHead.reparentTo(hidden) self.toonHead.startBlink() self.cogHead = Suit.Suit() self.cogDNA = SuitDNA.SuitDNA() self.cogDNA.newSuit('ms') self.cogHead.setDNA(self.cogDNA) self.cogHead.getGeomNode().setDepthWrite(1) self.cogHead.getGeomNode().setDepthTest(1) self.cogHead.loop('neutral') self.cogHead.setPosHprScale(-0.73, 0, -1.46, 180, 0, 0, 0.14, 0.14, 0.14) self.cogHead.reparentTo(hidden) self.clipPlane = self.toonHead.attachNewNode(PlaneNode('clip')) self.clipPlane.node().setPlane(Plane(0, 0, 1, 0)) self.clipPlane.setPos(0, 0, 2.45) audioMgr = base.cogdoGameAudioMgr self._cogDialogueSfx = audioMgr.createSfx('cogDialogue') self._toonDialogueSfx = audioMgr.createSfx('toonDialogue') suitData = Globals.SuitData[Globals.SuitTypes.Boss] bossSuit = Suit.Suit() d = SuitDNA.SuitDNA() d.newSuit(suitData['dnaName']) bossSuit.setDNA(d) bossSuit.setScale(suitData['scale']) bossSuit.loop('neutral') bossSuit.reparentTo(render) bossSuit.setPos(self._exit, -5, -5, 0) bossSuit.lookAt(self._exit) self._suits.append(bossSuit) self._camHelperNode = NodePath('CamHelperNode') self._camHelperNode.reparentTo(render) dialogue = TTLocalizer.CogdoMazeIntroMovieDialogue introDuration = Globals.IntroDurationSeconds waitDuration = introDuration / len(dialogue) def start(): base.camera.wrtReparentTo(render) self._exit.open(animate=False) def showBoss(): self._setCamTarget(bossSuit, 20, offset=Point3(0, 0, 7), angle=Point3(0, 15, 0)) bossSuit.loop('victory') self._state = 1 def showExit(): self._setCamTarget(self._exit, 10, offset=Point3(0, 0, 0), angle=Point3(0, 60, 0)) self._exit.close() self._state = 2 showExitIval = Parallel(base.camera.posInterval(waitDuration * 0.5, (10, -25, 20), other=self._exit, blendType='easeInOut'), Sequence(Wait(waitDuration * 0.25), Func(bossSuit.play, 'effort'), base.camera.hprInterval(waitDuration * 0.25, (30, -30, 0), blendType='easeInOut'), Func(self._exit.close), Wait(waitDuration * 0.5))) def showWaterCooler(): wc = self._maze.getWaterCoolers()[0] self._setCamTarget(wc, 25, angle=Point3(-30, 60, 0)) base.camera.wrtReparentTo(self._camHelperNode) self._state = 3 def end(): self._stopUpdateTask() self._ival = Sequence(Func(start), Func(self.displayLine, 'toon', self._getRandomLine(dialogue[0])), showExitIval, Func(showWaterCooler), Func(self.displayLine, 'toon', self._getRandomLine(dialogue[1])), Wait(waitDuration), Func(showBoss), bossSuit.hprInterval(1.0, bossSuit.getHpr() + Point3(180, 0, 0), blendType='easeInOut'), Func(self.displayLine, 'toon', self._getRandomLine(dialogue[2])), Wait(waitDuration - 1.0), Func(end)) self._startUpdateTask() def _setCamTarget(self, targetNP, distance, offset = Point3(0, 0, 0), angle = Point3(0, 0, 0)): base.camera.wrtReparentTo(render) self._camTarget = targetNP self._camOffset = offset self._camAngle = angle self._camDistance = distance self._camHelperNode.setPos(self._camTarget, self._camOffset) self._camHelperNode.setHpr(self._camTarget, 180 + self._camAngle[0], self._camAngle[1], self._camAngle[2]) base.camera.setPos(self._camHelperNode, 0, self._camDistance, 0) def _updateTask(self, task): dt = globalClock.getDt() if self._state == 1: self._camHelperNode.setPos(self._camTarget.getPos() + self._camOffset) base.camera.setPos(self._camHelperNode, 0, self._camDistance, 0) base.camera.lookAt(self._camTarget, 0, 0, 4) elif self._state == 2: base.camera.lookAt(self._camTarget, 0, 0, 5) elif self._state == 3: self._camHelperNode.setHpr(self._camHelperNode, dt, dt, 0) base.camera.setY(camera, 0.8 * dt) base.camera.lookAt(self._camTarget, 0, 0, 3) return task.cont def unload(self): self._exit = None self._camTarget = None self._camHelperNode.removeNode() del self._camHelperNode for suit in self._suits: suit.cleanup() suit.removeNode() suit.delete() self._suits = [] CogdoGameMovie.unload(self) del self._cogDialogueSfx del self._toonDialogueSfx self.toonHead.stopBlink() self.toonHead.stop() self.toonHead.removeNode() self.toonHead.delete() del self.toonHead self.cogHead.stop() self.cogHead.removeNode() self.cogHead.delete() del self.cogHead return
class LegendaryFishingGameGUI: def __init__(self, gameObject = None): base.loadingScreen.beginStep('LegendaryGameGUI', 4, 20) self.gameObject = gameObject self.guiImage = loader.loadModel('models/minigames/pir_m_gam_fsh_legendaryGui') self.UICompoments = { } self.uiBaseNode = NodePath('baseNode') self.uiBaseNode.reparentTo(aspect2d) self.uiBaseNode.show() self.leftBaseNode = NodePath('leftBaseNode') self.leftBaseNode.reparentTo(base.a2dLeftCenter) self.leftBaseNode.show() self.fishActor = None self.actorAnim = { } self.scaleSize = { InventoryType.Collection_Set11_Part1: 0.059999999999999998, InventoryType.Collection_Set11_Part2: 0.055, InventoryType.Collection_Set11_Part3: 0.12, InventoryType.Collection_Set11_Part4: 0.086999999999999994, InventoryType.Collection_Set11_Part5: 0.080000000000000002 } self.meterFrame = DirectFrame(parent = self.leftBaseNode, frameSize = (-0.29999999999999999, 0.29999999999999999, -1.0, 0.0), frameColor = (1.0, 1.0, 1.0, 0.0), relief = None, state = DGG.DISABLED, pos = (1.0, 0.0, -0.45000000000000001), hpr = (0, 0, 0), scale = (1.3, 0.0, 1.3), image = self.guiImage.find('**/pir_t_gui_fsh_meter'), image_scale = (0.20000000000000001, 0.0, 0.80000000000000004), image_pos = (0, 0, 0), text = '', textMayChange = 1, text_scale = PiratesGuiGlobals.TextScaleTitleLarge, text_pos = (-0.55000000000000004, 0.10000000000000001), text_shadow = PiratesGuiGlobals.TextShadow) self.UICompoments['meterFrame'] = self.meterFrame self.fishingRod = DirectFrame(parent = self.meterFrame, frameSize = (-0.29999999999999999, 0.29999999999999999, -1.0, 0.0), relief = None, state = DGG.DISABLED, pos = FishingGlobals.fishingRodScreenPosition, image = self.guiImage.find('**/pir_t_gui_fsh_fullRod'), image_scale = (1.0, 0.0, 0.125), image_pos = (0.20000000000000001, 0, 0)) self.fishingRod.setR(FishingGlobals.fishingRodInitSlope) self.UICompoments['fishingRod'] = self.fishingRod base.loadingScreen.tick() self.fishingHandleBaseFrame = DirectFrame(parent = self.uiBaseNode, frameSize = (-0.29999999999999999, 0.29999999999999999, -1.5, 1.5), frameColor = (1.0, 1.0, 1.0, 0.0), relief = None, state = DGG.DISABLED, pos = (0.0, 0.0, 0.0), hpr = (0, 0, 0), scale = (0.71999999999999997, 0.0, 0.71999999999999997), image = self.guiImage.find('**/pir_t_gui_fsh_partialRod'), image_scale = (3.7999999999999998, 0.0, 1.8999999999999999), image_pos = (0, 0, 0), image_hpr = (0.0, 0.0, 0)) self.fishingHandleBaseFrame.hide() self.UICompoments['fishingHandleBaseFrame'] = self.fishingHandleBaseFrame self.fishingHandle = DirectFrame(parent = self.fishingHandleBaseFrame, frameSize = (-0.080000000000000002, 0.080000000000000002, -0.20000000000000001, 0.20000000000000001), relief = None, state = DGG.DISABLED, pos = (-0.10000000000000001, 0.0, -0.050000000000000003), hpr = (0, 0, 0), image = self.guiImage.find('**/pir_t_gui_fsh_handleArm'), image_scale = (1.0, 0.0, 1.0), image_pos = (-0.042000000000000003, 0, -0.115), image_hpr = (0.0, 0.0, 0)) self.UICompoments['fishingHandle'] = self.fishingHandle self.arrowImage = DirectFrame(parent = self.fishingHandleBaseFrame, frameSize = (-0.40000000000000002, 0.40000000000000002, -0.40000000000000002, 0.40000000000000002), relief = None, state = DGG.DISABLED, pos = (0.0, 0.0, 0.0), hpr = (0, 0, 0), scale = (1.2, 0.0, 1.2), image = self.guiImage.find('**/pir_t_gui_fsh_arrow'), image_scale = (1.0, 0.0, 1.0), image_pos = (0.0, 0, 0.0), image_hpr = (0.0, 0.0, 0.0)) self.arrowImage.hide() self.UICompoments['arrowImage'] = self.arrowImage btnGeom = (self.guiImage.find('**/pir_t_gui_fsh_handle'), self.guiImage.find('**/pir_t_gui_fsh_handle'), self.guiImage.find('**/pir_t_gui_fsh_handleOn')) self.fishingHandleButton = GuiButton(pos = (-0.29999999999999999, 0, -0.55000000000000004), hpr = (0, 0, 0), scale = 0.45000000000000001, image = btnGeom, image_pos = (0, 0, 0), image_scale = 1.0, sortOrder = 2) self.fishingHandleButton.bind(DGG.B1PRESS, self.handleButtonClicked) self.fishingHandleButton.reparentTo(self.fishingHandle) self.UICompoments['fishingHandleButton'] = self.fishingHandleButton self.fishingHandleBaseFrame.setTransparency(TransparencyAttrib.MAlpha) self.meterFrame.setTransparency(TransparencyAttrib.MAlpha) self.lineOneTransitTextNode = TextNode('lineOneTransitText') self.lineOneTransitTextNode.setFont(PiratesGlobals.getPirateFont()) self.lineOneTransitTextNode.setText('') self.lineOneTransitTextNode.setAlign(TextNode.ACenter) self.lineOneTransitTextNode.setTextColor(1.0, 1.0, 1.0, 0.5) self.lineOneTransitTextNodePath = NodePath(self.lineOneTransitTextNode) self.lineOneTransitTextNodePath.setPos(0.0, 0.0, -0.80000000000000004) self.lineOneTransitTextNodePath.setScale(0.34999999999999998, 0.34999999999999998, 0.34999999999999998) self.lineOneTransitTextNodePath.reparentTo(self.uiBaseNode) self.lineOneTransitTextNodePath.hide() self.UICompoments['lineOneTransitText'] = self.lineOneTransitTextNodePath self.lineTwoTransitTextNode = TextNode('lineTwoTransitText') self.lineTwoTransitTextNode.setFont(PiratesGlobals.getPirateFont()) self.lineTwoTransitTextNode.setText('') self.lineTwoTransitTextNode.setAlign(TextNode.ACenter) self.lineTwoTransitTextNode.setTextColor(1.0, 1.0, 1.0, 0.5) self.lineTwoTransitTextNodePath = NodePath(self.lineTwoTransitTextNode) self.lineTwoTransitTextNodePath.setPos(-0.40000000000000002, 0.0, -0.94999999999999996) self.lineTwoTransitTextNodePath.setScale(0.12, 0.12, 0.12) self.lineTwoTransitTextNodePath.reparentTo(self.uiBaseNode) self.lineTwoTransitTextNodePath.hide() self.UICompoments['lineTwoTransitText'] = self.lineTwoTransitTextNodePath base.loadingScreen.tick() self.test_guiImage = loader.loadModel('models/gui/toplevel_gui') self.buttonIcon = (self.test_guiImage.find('**/treasure_chest_closed'), self.test_guiImage.find('**/treasure_chest_closed'), self.test_guiImage.find('**/treasure_chest_closed_over')) self.winImagePanel = GuiPanel.GuiPanel('', 2.6000000000000001, 1.8999999999999999, True) self.winImagePanel.setPos(-1.3, 0.0, -0.94999999999999996) self.winImagePanel.reparentTo(self.uiBaseNode) self.winImagePanel.background = OnscreenImage(parent = self.winImagePanel, scale = (2.3999999999999999, 0, 1.8), image = self.guiImage.find('**/pir_t_gui_fsh_posterBackground'), hpr = (0, 0, 0), pos = (1.3, 0, 0.94999999999999996)) self.winImagePanel.setBin('gui-popup', -4) self.winTitleTextNode = TextNode('winTitleTextNode') self.winTitleTextNode.setText('Congratulations!') self.winTitleTextNode.setAlign(TextNode.ACenter) self.winTitleTextNode.setFont(PiratesGlobals.getPirateFont()) self.winTitleTextNode.setTextColor(0.23000000000000001, 0.089999999999999997, 0.029999999999999999, 1.0) self.winTitleTextNodePath = NodePath(self.winTitleTextNode) self.winTitleTextNodePath.setPos(1.3500000000000001, 0.0, 1.6699999999999999) self.winTitleTextNodePath.setScale(0.17999999999999999) self.winTitleTextNodePath.reparentTo(self.winImagePanel) self.wholeStoryTextNode = TextNode('storyTextNode') self.wholeStoryTextNode.setText('') self.wholeStoryTextNode.setWordwrap(19.0) self.wholeStoryTextNode.setTextColor(0.23000000000000001, 0.089999999999999997, 0.029999999999999999, 1.0) self.wholeStoryTextNodePath = NodePath(self.wholeStoryTextNode) self.wholeStoryTextNodePath.setPos(0.33000000000000002, 0.0, 1.6399999999999999) self.wholeStoryTextNodePath.setScale(0.050000000000000003) self.wholeStoryTextNodePath.reparentTo(self.winImagePanel) self.winImagePanel.closeButton['command'] = self.closeDialogGotNextState self.winImagePanel.closeButton['extraArgs'] = [ 'winImagePanel', 'FarewellLegendaryFish', False] self.UICompoments['winImagePanel'] = self.winImagePanel self.winImagePanel.hide() self.luiCloseDialogSequence = Sequence() self.arrowImageRotationInterval = LerpHprInterval(self.arrowImage, 2.2000000000000002, self.arrowImage.getHpr() + Point3(0.0, 0.0, 280.0), self.arrowImage.getHpr()) self.luiArrowRotatingSequence = Sequence(Func(self.showGui, [ 'arrowImage']), Parallel(Func(self.arrowImageRotationInterval.start), Wait(2.2000000000000002)), Func(self.hideGui, [ 'arrowImage']), Func(self.arrowImage.setHpr, self.arrowImage.getHpr() + Point3(0.0, 0.0, 5.0)), name = self.gameObject.distributedFishingSpot.uniqueName('luiArrowRotatingSequence')) self.lineOneColorChange = LerpColorScaleInterval(self.lineOneTransitTextNodePath, FishingGlobals.legendaryTransitionTextDuration, (1.0, 1.0, 1.0, 0.0), (1.0, 1.0, 1.0, 1.0), blendType = 'easeOut') self.lineOnePosChange = LerpPosInterval(self.lineOneTransitTextNodePath, FishingGlobals.legendaryTransitionTextDuration, (0.0, 0.0, -0.20000000000000001), (0.0, 0.0, -0.80000000000000004), blendType = 'easeOut') self.lineTwoCholorChange = LerpColorScaleInterval(self.lineTwoTransitTextNodePath, FishingGlobals.legendaryTransitionTextDuration, (1.0, 1.0, 1.0, 1.0), (1.0, 1.0, 1.0, 1.0), blendType = 'easeOut') self.lineTwoPosChange = LerpPosInterval(self.lineTwoTransitTextNodePath, FishingGlobals.legendaryTransitionTextDuration, (0.0, 0.0, -0.32000000000000001), (0.0, 0.0, -0.94999999999999996), blendType = 'easeOut') self.transitionTextMovingSequence = Sequence(Func(self.lineOneTransitTextNodePath.show), Func(self.lineTwoTransitTextNodePath.show), Parallel(self.lineOnePosChange, self.lineTwoPosChange, self.lineOneColorChange, self.lineTwoCholorChange), Func(self.lineOneTransitTextNodePath.hide), Func(self.lineTwoTransitTextNodePath.hide), name = self.gameObject.distributedFishingSpot.uniqueName('transitionTextMovingSequence')) self.meterFadeInInterval = Sequence(Func(self.meterFrame.show), LerpColorScaleInterval(self.meterFrame, FishingGlobals.legendaryTransitionTextDuration, colorScale = (1.0, 1.0, 1.0, 1.0), startColorScale = (1.0, 1.0, 1.0, 0.0), blendType = 'easeOut'), name = 'FadeInLegendaryMeter') self.meterFadeOutInterval = Sequence(LerpColorScaleInterval(self.meterFrame, FishingGlobals.legendaryTransitionTextDuration, colorScale = (1.0, 1.0, 1.0, 0.0), startColorScale = (1.0, 1.0, 1.0, 1.0), blendType = 'easeOut'), Func(self.meterFrame.hide), name = 'FadeOutLegendaryMeter') self.rodFadeInInterval = Sequence(Func(self.fishingHandleBaseFrame.show), LerpColorScaleInterval(self.fishingHandleBaseFrame, FishingGlobals.legendaryTransitionTextDuration, colorScale = (1.0, 1.0, 1.0, 1.0), startColorScale = (1.0, 1.0, 1.0, 0.0), blendType = 'easeOut'), name = 'FadeInLegendaryRodInterface') self.rodFadeOutInterval = Sequence(LerpColorScaleInterval(self.fishingHandleBaseFrame, FishingGlobals.legendaryTransitionTextDuration, colorScale = (1.0, 1.0, 1.0, 0.0), startColorScale = (1.0, 1.0, 1.0, 1.0), blendType = 'easeOut'), Func(self.fishingHandleBaseFrame.hide), name = 'FadeOutLegendaryRodInterface') base.loadingScreen.tick() smallScale = self.fishingHandleButton['scale'] bigScale = self.fishingHandleButton['scale'] * 1.2 self.buttonGrowUpInterval = LerpScaleInterval(self.fishingHandleButton, 1.0, bigScale, smallScale) self.luiFightTransitSequence = Sequence(Parallel(Func(self.fishingHandleBaseFrame.show), Func(self.meterFadeOutInterval.start), Func(self.rodFadeInInterval.start), Func(self.buttonGrowUpInterval.start)), Wait(1.0), Func(self.meterFrame.hide), name = self.gameObject.distributedFishingSpot.uniqueName('luiFightTransitSequence')) self.luiReelTransitSequence = Sequence(Parallel(Func(self.fishingHandleBaseFrame.show), Func(self.meterFadeOutInterval.start), Func(self.rodFadeInInterval.start)), Wait(1.0), Func(self.meterFrame.hide), name = self.gameObject.distributedFishingSpot.uniqueName('luiReelTransitSequence')) self.luiStruggleTransitSequence = Sequence(Parallel(Func(self.meterFrame.show), Func(self.resetFishingRod), self.meterFadeInInterval, self.rodFadeOutInterval), Wait(1.0), Func(self.fishingHandleBaseFrame.hide), name = self.gameObject.distributedFishingSpot.uniqueName('luiStruggleTransitSequence')) self.meterFadeOutInterval.start() self.rodFadeOutInterval.start() self.hideAllGUI() base.loadingScreen.endStep('LegendaryGameGUI') def hideAllGUI(self): self.uiBaseNode.reparentTo(hidden) self.leftBaseNode.reparentTo(hidden) def showAllGUI(self): self.uiBaseNode.reparentTo(aspect2d) self.leftBaseNode.reparentTo(base.a2dLeftCenter) def hideGui(self, nameList): for ui in nameList: self.UICompoments[ui].hide() def showGui(self, nameList): for ui in nameList: self.UICompoments[ui].show() def destroy(self): self.arrowImageRotationInterval.pause() self.arrowImageRotationInterval.clearToInitial() self.luiArrowRotatingSequence.pause() self.luiArrowRotatingSequence.clearToInitial() self.luiCloseDialogSequence.pause() self.luiCloseDialogSequence.clearToInitial() totalKey = self.UICompoments.keys() for iKey in totalKey: del self.UICompoments[iKey] self.fishingHandle = None self.fishingHandleButton = None self.fishingRod.removeNode() self.leftBaseNode.removeNode() self.uiBaseNode.removeNode() if self.fishActor: self.fishActor.destroy() self.fishActor = None def handleButtonClicked(self, mouseKey): if self.gameObject.lfgFsm.getCurrentOrNextState() in [ 'CatchIt']: self.gameObject.lfgFsm.request('Transition', 'Struggle') self.gameObject.sfx['legendaryGreen'].play() def setTransitionText(self, state): self.lineOneTransitTextNode.setText(PLocalizer.LegendaryFishingGui[state][0]) self.lineTwoTransitTextNode.setText(PLocalizer.LegendaryFishingGui[state][1]) def resetInterval(self): self.transitionTextMovingSequence.pause() self.transitionTextMovingSequence.clearToInitial() self.lineOneColorChange.pause() self.lineOneColorChange.clearToInitial() self.lineOnePosChange.pause() self.lineOnePosChange.clearToInitial() self.lineTwoCholorChange.pause() self.lineTwoCholorChange.clearToInitial() self.lineTwoPosChange.pause() self.lineTwoPosChange.clearToInitial() self.luiReelTransitSequence.pause() self.luiReelTransitSequence.clearToInitial() self.luiStruggleTransitSequence.pause() self.luiStruggleTransitSequence.clearToInitial() self.luiFightTransitSequence.pause() self.luiFightTransitSequence.clearToInitial() self.buttonGrowUpInterval.pause() self.buttonGrowUpInterval.clearToInitial() self.meterFadeOutInterval.pause() self.meterFadeOutInterval.clearToInitial() self.rodFadeInInterval.pause() self.rodFadeInInterval.clearToInitial() self.meterFadeInInterval.pause() self.meterFadeInInterval.clearToInitial() self.rodFadeOutInterval.pause() self.rodFadeOutInterval.clearToInitial() def fightingTransit(self): self.luiFightTransitSequence.start() def reelTransit(self): self.luiReelTransitSequence.start() def struggleTransit(self): self.luiStruggleTransitSequence.start() def resetFishingRod(self): self.fishingRod.setR(FishingGlobals.fishingRodInitSlope) def showWinImage(self, fish): self.hideGui([ 'meterFrame', 'fishingHandleBaseFrame']) result = fish.myData['name'].split(' ') fileName = str(result[0]).capitalize() imgName = 'pir_t_gui_fsh_render%s' % fileName self.actorAnim['swimIdleOpposite'] = 'models/char/pir_a_gam_fsh_%s_%s.bam' % (fish.myData['model'], 'swimIdleOpposite') self.fishActor = BlendActor('models/char/pir_r_gam_fsh_%s.bam' % fish.myData['model'], self.actorAnim, FishingGlobals.defaultFishBlendTime, FishingGlobals.fishBlendTimeDict) self.fishActor.setPlayRate(fish.myData['speed'] * fish.myData['swimAnimationMultiplier'], 'swimIdleOpposite') self.fishActor.changeAnimationTo('swimIdleOpposite') self.fishActor.reparentTo(self.winImagePanel) self.fishActor.setScale(self.scaleSize[fish.myData['id']]) self.fishActor.setPos(1.7, 0, 1.0) self.fishActor.setHpr(0, 0, 35) self.fishActor.setDepthWrite(True) self.fishActor.setDepthTest(True) self.wholeStoryTextNode.setText(PLocalizer.LegendSelectionGui['wholeStory'][fish.myData['id']]) self.winImagePanel.show() def closeDialogGotNextState(self, object, targetState, ifFadeInAgain): if self.fishActor: self.fishActor.destroy() self.fishActor = None self.luiCloseDialogSequence = Sequence(Func(self.gameObject.distributedFishingSpot.fadeOut), Wait(0.40000000000000002), Func(self.UICompoments[object].hide), Func(self.gameObject.lfgFsm.request, targetState), name = self.gameObject.distributedFishingSpot.uniqueName('luiCloseDialogSequence')) self.luiCloseDialogSequence.start() def updateStruggleTimerText(self, time, percent): self.meterFrame['text'] = str(time) self.meterFrame['text_fg'] = (1.0 - percent, percent, 0.0, 1.0)
class DistributedPartyActivity(DistributedObject.DistributedObject): deferFor = 1 def __init__(self, cr, activityId, activityType, wantLever = False, wantRewardGui = False): DistributedObject.DistributedObject.__init__(self, cr) self.activityId = activityId self.activityName = PartyGlobals.ActivityIds.getString(self.activityId) self.activityType = activityType self.wantLever = wantLever self.wantRewardGui = wantRewardGui self.messageGui = None self.rewardGui = None self.toonIds = [] self._toonId2ror = {} childName = '%s' % self childName = childName[childName.rfind('.DistributedParty') + len('.DistributedParty'):childName.rfind('Activity instance')] if not hasattr(base, 'partyActivityDict'): base.partyActivityDict = {} base.partyActivityDict[childName] = self self.root = NodePath('root') self.rulesDoneEvent = 'rulesDone' self.modelCount = 500 self.cleanupActions = [] self.usesSmoothing = 0 self.usesLookAround = 0 self.difficultyOverride = None self.trolleyZoneOverride = None self._localToonRequestStatus = None return def localToonExiting(self): self._localToonRequestStatus = PartyGlobals.ActivityRequestStatus.Exiting def localToonJoining(self): self._localToonRequestStatus = PartyGlobals.ActivityRequestStatus.Joining def d_toonJoinRequest(self): if self._localToonRequestStatus is None: self.localToonJoining() self.sendUpdate('toonJoinRequest') return def d_toonExitRequest(self): if self._localToonRequestStatus is None: self.localToonExiting() self.sendUpdate('toonExitRequest') return def d_toonExitDemand(self): self.localToonExiting() self.sendUpdate('toonExitDemand') def joinRequestDenied(self, reason): self._localToonRequestStatus = None return def exitRequestDenied(self, reason): self._localToonRequestStatus = None return def handleToonJoined(self, toonId): self.notify.error('BASE: handleToonJoined should be overridden %s' % self.activityName) def handleToonExited(self, toonId): self.notify.error('BASE: handleToonExited should be overridden %s' % self.activityName) def handleToonDisabled(self, toonId): self.notify.error('BASE: handleToonDisabled should be overridden %s' % self.activityName) def setToonsPlaying(self, toonIds): exitedToons, joinedToons = self.getToonsPlayingChanges(self.toonIds, toonIds) self.setToonIds(toonIds) self._processExitedToons(exitedToons) self._processJoinedToons(joinedToons) def _processExitedToons(self, exitedToons): for toonId in exitedToons: if toonId != base.localAvatar.doId or toonId == base.localAvatar.doId and self.isLocalToonRequestStatus(PartyGlobals.ActivityRequestStatus.Exiting): toon = self.getAvatar(toonId) if toon is not None: self.ignore(toon.uniqueName('disable')) self.handleToonExited(toonId) if toonId == base.localAvatar.doId: self._localToonRequestStatus = None if toonId in self._toonId2ror: self.cr.relatedObjectMgr.abortRequest(self._toonId2ror[toonId]) del self._toonId2ror[toonId] return def _processJoinedToons(self, joinedToons): for toonId in joinedToons: if toonId != base.localAvatar.doId or toonId == base.localAvatar.doId and self.isLocalToonRequestStatus(PartyGlobals.ActivityRequestStatus.Joining): if toonId not in self._toonId2ror: request = self.cr.relatedObjectMgr.requestObjects([toonId], allCallback=self._handlePlayerPresent) if toonId in self._toonId2ror: del self._toonId2ror[toonId] else: self._toonId2ror[toonId] = request def _handlePlayerPresent(self, toons): toon = toons[0] toonId = toon.doId if toonId in self._toonId2ror: del self._toonId2ror[toonId] else: self._toonId2ror[toonId] = None self._enableHandleToonDisabled(toonId) self.handleToonJoined(toonId) if toonId == base.localAvatar.doId: self._localToonRequestStatus = None return def _enableHandleToonDisabled(self, toonId): toon = self.getAvatar(toonId) if toon is not None: self.acceptOnce(toon.uniqueName('disable'), self.handleToonDisabled, [toonId]) else: self.notify.warning('BASE: unable to get handle to toon with toonId:%d. Hook for handleToonDisabled not set.' % toonId) return def isLocalToonRequestStatus(self, requestStatus): return self._localToonRequestStatus == requestStatus def setToonIds(self, toonIds): self.toonIds = toonIds def getToonsPlayingChanges(self, oldToonIds, newToonIds): oldToons = set(oldToonIds) newToons = set(newToonIds) exitedToons = oldToons.difference(newToons) joinedToons = newToons.difference(oldToons) return (list(exitedToons), list(joinedToons)) def setUsesSmoothing(self): self.usesSmoothing = True def setUsesLookAround(self): self.usesLookAround = True def getInstructions(self): return TTLocalizer.DefaultPartyActivityInstructions def getParentNodePath(self): if hasattr(base.cr.playGame, 'hood') and base.cr.playGame.hood and hasattr(base.cr.playGame.hood, 'loader') and base.cr.playGame.hood.loader and hasattr(base.cr.playGame.hood.loader, 'geom') and base.cr.playGame.hood.loader.geom: return base.cr.playGame.hood.loader.geom else: self.notify.warning('Hood or loader not created, defaulting to render') return render def __createRandomNumGen(self): self.notify.debug('BASE: self.doId=0x%08X' % self.doId) self.randomNumGen = RandomNumGen.RandomNumGen(self.doId) def destroy(self = self): self.notify.debug('BASE: destroying random num gen') del self.randomNumGen self.cleanupActions.append(destroy) def generate(self): DistributedObject.DistributedObject.generate(self) self.notify.debug('BASE: generate, %s' % self.getTitle()) self.__createRandomNumGen() def announceGenerate(self): DistributedObject.DistributedObject.announceGenerate(self) self.notify.debug('BASE: announceGenerate %s' % self.activityName) self.root.setName(self.activityName + 'Root') centeredX, centeredY = getCenterPosFromGridSize(self.x, self.y, PartyGlobals.ActivityInformationDict[self.activityId]['gridsize']) self.root.setPos(centeredX, centeredY, 0.0) self.root.setH(self.h) self.normalExit = True if self.wantLever: self.leverTriggerEvent = self.uniqueName('leverTriggerEvent') self.load() def cleanup(self = self): self.notify.debug('BASE: cleanup: normalExit=%s' % self.normalExit) base.cr.renderFrame() if self.normalExit: self.sendUpdate('toonExitRequest') self.cleanupActions.append(cleanup) def disable(self): self.notify.debug('BASE: disable') DistributedObject.DistributedObject.disable(self) rorToonIds = self._toonId2ror.keys() for toonId in rorToonIds: self.cr.relatedObjectMgr.abortRequest(self._toonId2ror[toonId]) del self._toonId2ror[toonId] self.ignore(self.messageDoneEvent) if self.messageGui is not None and not self.messageGui.isEmpty(): self.messageGui.cleanup() self.messageGui = None return def delete(self): self.notify.debug('BASE: delete') self.unload() self.ignoreAll() DistributedObject.DistributedObject.delete(self) def load(self): self.notify.debug('BASE: load') self.loadSign() if self.wantLever: self.loadLever() if self.wantRewardGui: self.showRewardDoneEvent = self.uniqueName('showRewardDoneEvent') self.rewardGui = JellybeanRewardGui(self.showRewardDoneEvent) self.messageDoneEvent = self.uniqueName('messageDoneEvent') self.root.reparentTo(self.getParentNodePath()) self._enableCollisions() def loadSign(self): actNameForSign = self.activityName if self.activityId == PartyGlobals.ActivityIds.PartyJukebox40: actNameForSign = PartyGlobals.ActivityIds.getString(PartyGlobals.ActivityIds.PartyJukebox) elif self.activityId == PartyGlobals.ActivityIds.PartyDance20: actNameForSign = PartyGlobals.ActivityIds.getString(PartyGlobals.ActivityIds.PartyDance) self.sign = self.root.attachNewNode('%sSign' % self.activityName) self.signModel = self.party.defaultSignModel.copyTo(self.sign) self.signFlat = self.signModel.find('**/sign_flat') self.signFlatWithNote = self.signModel.find('**/sign_withNote') self.signTextLocator = self.signModel.find('**/signText_locator') textureNodePath = getPartyActivityIcon(self.party.activityIconsModel, actNameForSign) textureNodePath.setPos(0.0, -0.02, 2.2) textureNodePath.setScale(2.35) textureNodePath.copyTo(self.signFlat) textureNodePath.copyTo(self.signFlatWithNote) text = TextNode('noteText') text.setTextColor(0.2, 0.1, 0.7, 1.0) text.setAlign(TextNode.ACenter) text.setFont(OTPGlobals.getInterfaceFont()) text.setWordwrap(10.0) text.setText('') self.noteText = self.signFlatWithNote.attachNewNode(text) self.noteText.setPosHpr(self.signTextLocator, 0.0, 0.0, 0.2, 0.0, 0.0, 0.0) self.noteText.setScale(0.2) self.signFlatWithNote.stash() self.signTextLocator.stash() def loadLever(self): self.lever = self.root.attachNewNode('%sLever' % self.activityName) self.leverModel = self.party.defaultLeverModel.copyTo(self.lever) self.controlColumn = NodePath('cc') column = self.leverModel.find('**/column') column.getChildren().reparentTo(self.controlColumn) self.controlColumn.reparentTo(column) self.stickHinge = self.controlColumn.attachNewNode('stickHinge') self.stick = self.party.defaultStickModel.copyTo(self.stickHinge) self.stickHinge.setHpr(0.0, 90.0, 0.0) self.stick.setHpr(0, -90.0, 0) self.stick.flattenLight() self.bottom = self.leverModel.find('**/bottom') self.bottom.wrtReparentTo(self.controlColumn) self.bottomPos = self.bottom.getPos() cs = CollisionSphere(0.0, 1.35, 2.0, 1.0) cs.setTangible(False) cn = CollisionNode(self.leverTriggerEvent) cn.addSolid(cs) cn.setIntoCollideMask(OTPGlobals.WallBitmask) self.leverTrigger = self.root.attachNewNode(cn) self.leverTrigger.reparentTo(self.lever) self.leverTrigger.stash() cs = CollisionTube(0.0, 2.7, 0.0, 0.0, 2.7, 3.0, 1.2) cn = CollisionNode('levertube') cn.addSolid(cs) cn.setIntoCollideMask(OTPGlobals.WallBitmask) self.leverTube = self.leverModel.attachNewNode(cn) host = base.cr.doId2do.get(self.party.partyInfo.hostId) if host is None: self.notify.debug('%s loadLever : Host has left the game before lever could be created.' % self.activityName) return scale = host.getGeomNode().getChild(0).getSz(render) self.leverModel.setScale(scale) self.controlColumn.setPos(0, 0, 0) host.setPosHpr(self.lever, 0, 0, 0, 0, 0, 0) host.pose('leverNeutral', 0) host.update() pos = host.rightHand.getPos(self.controlColumn) self.controlColumn.setPos(pos[0], pos[1], pos[2] - 1) self.bottom.setZ(host, 0.0) self.bottom.setPos(self.bottomPos[0], self.bottomPos[1], self.bottom.getZ()) lookAtPoint = Point3(0.3, 0, 0.1) lookAtUp = Vec3(0, -1, 0) self.stickHinge.lookAt(host.rightHand, lookAtPoint, lookAtUp) host.play('walk') host.update() return def unloadLever(self): self.lever.removeNode() self.leverModel.removeNode() self.controlColumn.removeNode() self.stickHinge.removeNode() self.stick.removeNode() self.bottom.removeNode() self.leverTrigger.removeNode() self.leverTube.removeNode() del self.bottomPos del self.lever del self.leverModel del self.controlColumn del self.stickHinge del self.stick del self.bottom del self.leverTrigger del self.leverTube def _enableCollisions(self): if self.wantLever: self.leverTrigger.unstash() self.accept('enter%s' % self.leverTriggerEvent, self._leverPulled) def _disableCollisions(self): if self.wantLever: self.leverTrigger.stash() self.ignore('enter%s' % self.leverTriggerEvent) def _leverPulled(self, collEntry): self.notify.debug('_leverPulled : Someone pulled the lever!!! ') if self.activityType == PartyGlobals.ActivityTypes.HostInitiated and base.localAvatar.doId != self.party.partyInfo.hostId: return False return True def getToonPullingLeverInterval(self, toon): walkTime = 0.2 reach = ActorInterval(toon, 'leverReach', playRate=2.0) pull = ActorInterval(toon, 'leverPull', startFrame=6) origPos = toon.getPos(render) origHpr = toon.getHpr(render) newPos = self.lever.getPos(render) newHpr = self.lever.getHpr(render) origHpr.setX(PythonUtil.fitSrcAngle2Dest(origHpr[0], newHpr[0])) toon.setPosHpr(origPos, origHpr) reachAndPull = Sequence(ActorInterval(toon, 'walk', loop=True, duration=walkTime - reach.getDuration()), reach, pull) leverSeq = Sequence(Wait(walkTime + reach.getDuration() - 0.1), self.stick.hprInterval(0.55, Point3(0.0, 25.0, 0.0), Point3(0.0, 0.0, 0.0)), Wait(0.3), self.stick.hprInterval(0.4, Point3(0.0, 0.0, 0.0), Point3(0.0, 25.0, 0.0))) returnSeq = Sequence(Parallel(toon.posInterval(walkTime, newPos, origPos), toon.hprInterval(walkTime, newHpr, origHpr), leverSeq, reachAndPull)) return returnSeq def showMessage(self, message, endState = 'walk'): base.cr.playGame.getPlace().fsm.request('activity') self.acceptOnce(self.messageDoneEvent, self.__handleMessageDone) self.messageGui = TTDialog.TTGlobalDialog(doneEvent=self.messageDoneEvent, message=message, style=TTDialog.Acknowledge) self.messageGui.endState = endState def __handleMessageDone(self): self.ignore(self.messageDoneEvent) if hasattr(base.cr.playGame.getPlace(), 'fsm'): if self.messageGui and hasattr(self.messageGui, 'endState'): self.notify.info('__handleMessageDone (endState=%s)' % self.messageGui.endState) base.cr.playGame.getPlace().fsm.request(self.messageGui.endState) else: self.notify.warning("messageGui has no endState, defaulting to 'walk'") base.cr.playGame.getPlace().fsm.request('walk') if self.messageGui is not None and not self.messageGui.isEmpty(): self.messageGui.cleanup() self.messageGui = None return def showJellybeanReward(self, earnedAmount, jarAmount, message): if not self.isLocalToonInActivity() or base.localAvatar.doId in self.getToonIdsAsList(): messenger.send('DistributedPartyActivity-showJellybeanReward') base.cr.playGame.getPlace().fsm.request('activity') self.acceptOnce(self.showRewardDoneEvent, self.__handleJellybeanRewardDone) self.rewardGui.showReward(earnedAmount, jarAmount, message) def __handleJellybeanRewardDone(self): self.ignore(self.showRewardDoneEvent) self.handleRewardDone() def handleRewardDone(self): if base.cr.playGame.getPlace() and hasattr(base.cr.playGame.getPlace(), 'fsm'): base.cr.playGame.getPlace().fsm.request('walk') def setSignNote(self, note): self.noteText.node().setText(note) if len(note.strip()) > 0: self.signFlat.stash() self.signFlatWithNote.unstash() self.signTextLocator.unstash() else: self.signFlat.unstash() self.signFlatWithNote.stash() self.signTextLocator.stash() def unload(self): self.notify.debug('BASE: unload') self.finishRules() self._disableCollisions() self.signModel.removeNode() del self.signModel self.sign.removeNode() del self.sign self.ignoreAll() if self.wantLever: self.unloadLever() self.root.removeNode() del self.root del self.activityId del self.activityName del self.activityType del self.wantLever del self.messageGui if self.rewardGui is not None: self.rewardGui.destroy() del self.rewardGui if hasattr(self, 'toonIds'): del self.toonIds del self.rulesDoneEvent del self.modelCount del self.cleanupActions del self.usesSmoothing del self.usesLookAround del self.difficultyOverride del self.trolleyZoneOverride if hasattr(base, 'partyActivityDict'): del base.partyActivityDict return def setPartyDoId(self, partyDoId): self.party = base.cr.doId2do[partyDoId] def setX(self, x): self.x = x def setY(self, y): self.y = y def setH(self, h): self.h = h def setState(self, newState, timestamp): if newState == 'Active': self.activityStartTime = globalClockDelta.networkToLocalTime(timestamp) def turnOffSmoothingOnGuests(self): for toonId in self.toonIds: avatar = self.getAvatar(toonId) if avatar: if not self.usesSmoothing: avatar.stopSmooth() if not self.usesLookAround: avatar.stopLookAround() def getAvatar(self, toonId): if self.cr.doId2do.has_key(toonId): return self.cr.doId2do[toonId] else: self.notify.warning('BASE: getAvatar: No avatar in doId2do with id: ' + str(toonId)) return None return None def getAvatarName(self, toonId): avatar = self.getAvatar(toonId) if avatar: return avatar.getName() else: return 'Unknown' def isLocalToonInActivity(self): result = False place = base.cr.playGame.getPlace() if place and place.__class__.__name__ == 'Party' and hasattr(place, 'fsm') and place.fsm: result = place.fsm.getCurrentState().getName() == 'activity' return result def getToonIdsAsList(self): return self.toonIds def startRules(self, timeout = PartyGlobals.DefaultRulesTimeout): self.notify.debug('BASE: startRules') self.accept(self.rulesDoneEvent, self.handleRulesDone) self.rulesPanel = MinigameRulesPanel('PartyRulesPanel', self.getTitle(), self.getInstructions(), self.rulesDoneEvent, timeout) base.setCellsAvailable(base.bottomCells + [base.leftCells[0], base.rightCells[1]], False) self.rulesPanel.load() self.rulesPanel.enter() def finishRules(self): self.notify.debug('BASE: finishRules') self.ignore(self.rulesDoneEvent) if hasattr(self, 'rulesPanel'): self.rulesPanel.exit() self.rulesPanel.unload() del self.rulesPanel base.setCellsAvailable(base.bottomCells + [base.leftCells[0], base.rightCells[1]], True) def handleRulesDone(self): self.notify.error('BASE: handleRulesDone should be overridden') def getTitle(self): return TTLocalizer.PartyActivityNameDict[self.activityId]['generic'] def local2ActivityTime(self, timestamp): return timestamp - self.activityStartTime def activity2LocalTime(self, timestamp): return timestamp + self.activityStartTime def getCurrentActivityTime(self): return self.local2ActivityTime(globalClock.getFrameTime()) def disableEmotes(self): Emote.globalEmote.disableAll(base.localAvatar) def enableEmotes(self): Emote.globalEmote.releaseAll(base.localAvatar)
class Sprite2d: class Cell: def __init__(self, col, row): self.col = col self.row = row def __str__(self): return "Cell - Col %d, Row %d" % (self.col, self.row) class Animation: def __init__(self, cells, fps): self.cells = cells self.fps = fps self.playhead = 0 ALIGN_CENTER = "Center" ALIGN_LEFT = "Left" ALIGN_RIGHT = "Right" ALIGN_BOTTOM = "Bottom" ALIGN_TOP = "Top" TRANS_ALPHA = TransparencyAttrib.MAlpha TRANS_DUAL = TransparencyAttrib.MDual # One pixel is divided by this much. If you load a 100x50 image with PIXEL_SCALE of 10.0 # you get a card that is 1 unit wide, 0.5 units high PIXEL_SCALE = 20.0 def __init__(self, image_path, rowPerFace, name=None,\ rows=1, cols=1, scale=1.0,\ twoSided=False, alpha=TRANS_ALPHA,\ repeatX=1, repeatY=1,\ anchorX=ALIGN_CENTER, anchorY=ALIGN_BOTTOM): """ Create a card textured with an image. The card is sized so that the ratio between the card and image is the same. """ global SpriteId self.spriteNum = str(SpriteId) SpriteId += 1 scale *= self.PIXEL_SCALE self.animations = {} self.scale = scale self.repeatX = repeatX self.repeatY = repeatY self.flip = {'x':False,'y':False} self.rows = rows self.cols = cols self.currentFrame = 0 self.currentAnim = None self.loopAnim = False self.frameInterrupt = True # Create the NodePath if name: self.node = NodePath("Sprite2d:%s" % name) else: self.node = NodePath("Sprite2d:%s" % image_path) # Set the attribute for transparency/twosided self.node.node().setAttrib(TransparencyAttrib.make(alpha)) if twoSided: self.node.setTwoSided(True) # Make a filepath self.imgFile = Filename(image_path) if self.imgFile.empty(): raise IOError, "File not found" # Instead of loading it outright, check with the PNMImageHeader if we can open # the file. imgHead = PNMImageHeader() if not imgHead.readHeader(self.imgFile): raise IOError, "PNMImageHeader could not read file. Try using absolute filepaths" # Load the image with a PNMImage image = PNMImage() image.read(self.imgFile) self.sizeX = image.getXSize() self.sizeY = image.getYSize() # We need to find the power of two size for the another PNMImage # so that the texture thats loaded on the geometry won't have artifacts textureSizeX = self.nextsize(self.sizeX) textureSizeY = self.nextsize(self.sizeY) # The actual size of the texture in memory self.realSizeX = textureSizeX self.realSizeY = textureSizeY self.paddedImg = PNMImage(textureSizeX, textureSizeY) if image.hasAlpha(): self.paddedImg.alphaFill(0) # Copy the source image to the image we're actually using self.paddedImg.blendSubImage(image, 0, 0) # We're done with source image, clear it image.clear() # The pixel sizes for each cell self.colSize = self.sizeX/self.cols self.rowSize = self.sizeY/self.rows # How much padding the texture has self.paddingX = textureSizeX - self.sizeX self.paddingY = textureSizeY - self.sizeY # Set UV padding self.uPad = float(self.paddingX)/textureSizeX self.vPad = float(self.paddingY)/textureSizeY # The UV dimensions for each cell self.uSize = (1.0 - self.uPad) / self.cols self.vSize = (1.0 - self.vPad) / self.rows self.cards = [] self.rowPerFace = rowPerFace for i in range(len(rowPerFace)): card = CardMaker("Sprite2d-Geom") # The positions to create the card at if anchorX == self.ALIGN_LEFT: posLeft = 0 posRight = (self.colSize/scale)*repeatX elif anchorX == self.ALIGN_CENTER: posLeft = -(self.colSize/2.0/scale)*repeatX posRight = (self.colSize/2.0/scale)*repeatX elif anchorX == self.ALIGN_RIGHT: posLeft = -(self.colSize/scale)*repeatX posRight = 0 if anchorY == self.ALIGN_BOTTOM: posTop = 0 posBottom = (self.rowSize/scale)*repeatY elif anchorY == self.ALIGN_CENTER: posTop = -(self.rowSize/2.0/scale)*repeatY posBottom = (self.rowSize/2.0/scale)*repeatY elif anchorY == self.ALIGN_TOP: posTop = -(self.rowSize/scale)*repeatY posBottom = 0 card.setFrame(posLeft, posRight, posTop, posBottom) card.setHasUvs(True) self.cards.append(self.node.attachNewNode(card.generate())) self.cards[-1].setH(i * 360/len(rowPerFace)) # Since the texture is padded, we need to set up offsets and scales to make # the texture fit the whole card self.offsetX = (float(self.colSize)/textureSizeX) self.offsetY = (float(self.rowSize)/textureSizeY) # self.node.setTexScale(TextureStage.getDefault(), self.offsetX * repeatX, self.offsetY * repeatY) # self.node.setTexOffset(TextureStage.getDefault(), 0, 1-self.offsetY) self.texture = Texture() self.texture.setXSize(textureSizeX) self.texture.setYSize(textureSizeY) self.texture.setZSize(1) # Load the padded PNMImage to the texture self.texture.load(self.paddedImg) self.texture.setMagfilter(Texture.FTNearest) self.texture.setMinfilter(Texture.FTNearest) #Set up texture clamps according to repeats if repeatX > 1: self.texture.setWrapU(Texture.WMRepeat) else: self.texture.setWrapU(Texture.WMClamp) if repeatY > 1: self.texture.setWrapV(Texture.WMRepeat) else: self.texture.setWrapV(Texture.WMClamp) self.node.setTexture(self.texture) self.setFrame(0) def nextsize(self, num): """ Finds the next power of two size for the given integer. """ p2x=max(1,log(num,2)) notP2X=modf(p2x)[0]>0 return 2**int(notP2X+p2x) def setFrame(self, frame=0): """ Sets the current sprite to the given frame """ self.frameInterrupt = True # A flag to tell the animation task to shut it up ur face self.currentFrame = frame self.flipTexture() def playAnim(self, animName, loop=False): """ Sets the sprite to animate the given named animation. Booleon to loop animation""" if not taskMgr.hasTaskNamed("Animate sprite" + self.spriteNum): if hasattr(self, "task"): taskMgr.remove("Animate sprite" + self.spriteNum) del self.task self.frameInterrupt = False # Clear any previous interrupt flags self.loopAnim = loop self.currentAnim = self.animations[animName] self.currentAnim.playhead = 0 self.task = taskMgr.doMethodLater(1.0/self.currentAnim.fps,self.animPlayer, "Animate sprite" + self.spriteNum) def createAnim(self, animName, frameCols, fps=12): """ Create a named animation. Takes the animation name and a tuple of frame numbers """ self.animations[animName] = Sprite2d.Animation(frameCols, fps) return self.animations[animName] def flipX(self, val=None): """ Flip the sprite on X. If no value given, it will invert the current flipping.""" if val: self.flip['x'] = val else: if self.flip['x']: self.flip['x'] = False else: self.flip['x'] = True self.flipTexture() return self.flip['x'] def flipY(self, val=None): """ See flipX """ if val: self.flip['y'] = val else: if self.flip['y']: self.flip['y'] = False else: self.flip['y'] = True self.flipTexture() return self.flip['y'] def updateCameraAngle(self, cameraNode): baseH = cameraNode.getH(render) - self.node.getH(render) degreesBetweenCards = 360/len(self.cards) bestCard = int(((baseH)+degreesBetweenCards/2)%360 / degreesBetweenCards) #print baseH, bestCard for i in range(len(self.cards)): if i == bestCard: self.cards[i].show() else: self.cards[i].hide() def flipTexture(self): """ Sets the texture coordinates of the texture to the current frame""" for i in range(len(self.cards)): currentRow = self.rowPerFace[i] sU = self.offsetX * self.repeatX sV = self.offsetY * self.repeatY oU = 0 + self.currentFrame * self.uSize #oU = 0 + self.frames[self.currentFrame].col * self.uSize #oV = 1 - self.frames[self.currentFrame].row * self.vSize - self.offsetY oV = 1 - currentRow * self.vSize - self.offsetY if self.flip['x'] ^ i==1: ##hack to fix side view #print "flipping, i = ",i sU *= -1 #oU = self.uSize + self.frames[self.currentFrame].col * self.uSize oU = self.uSize + self.currentFrame * self.uSize if self.flip['y']: sV *= -1 #oV = 1 - self.frames[self.currentFrame].row * self.vSize oV = 1 - currentRow * self.vSize self.cards[i].setTexScale(TextureStage.getDefault(), sU, sV) self.cards[i].setTexOffset(TextureStage.getDefault(), oU, oV) def clear(self): """ Free up the texture memory being used """ self.texture.clear() self.paddedImg.clear() self.node.removeNode() def animPlayer(self, task): if self.frameInterrupt: return task.done #print "Playing",self.currentAnim.cells[self.currentAnim.playhead] self.currentFrame = self.currentAnim.cells[self.currentAnim.playhead] self.flipTexture() if self.currentAnim.playhead+1 < len(self.currentAnim.cells): self.currentAnim.playhead += 1 return task.again if self.loopAnim: self.currentAnim.playhead = 0 return task.again
class PartyCogActivityLocalPlayer(PartyCogActivityPlayer): def __init__(self, activity, position, team, exitActivityCallback = None): PartyCogActivityPlayer.__init__(self, activity, base.localAvatar, position, team) self.input = PartyCogActivityInput(exitActivityCallback) self.gui = PartyCogActivityGui() self.throwPiePrevTime = 0 self.lastMoved = 0 if base.localAvatar: self.prevPos = base.localAvatar.getPos() self.cameraManager = None self.control = None self.consecutiveShortThrows = 0 return def destroy(self): if self.enabled: self.disable() if self.cameraManager is not None: self.cameraManager.setEnabled(False) self.cameraManager.destroy() del self.cameraManager del self.gui del self.input if self.control is not None: self.control.destroy() del self.control PartyCogActivityPlayer.destroy(self) return def _initOrthoWalk(self): orthoDrive = OrthoDrive(9.778, customCollisionCallback=self.activity.view.checkOrthoDriveCollision) self.orthoWalk = OrthoWalk(orthoDrive, broadcast=True) def _destroyOrthoWalk(self): self.orthoWalk.stop() self.orthoWalk.destroy() del self.orthoWalk def getPieThrowingPower(self, time): elapsed = max(time - self.input.throwPiePressedStartTime, 0.0) w = 1.0 / PartyGlobals.CogActivityPowerMeterTime * 2.0 * math.pi power = int(round(-math.cos(w * elapsed) * 50.0 + 50.0)) return power def isShortThrow(self, time): elapsed = max(time - self.input.throwPiePressedStartTime, 0.0) return elapsed <= PartyGlobals.CogActivityShortThrowTime def checkForThrowSpam(self, time): if self.isShortThrow(time): self.consecutiveShortThrows += 1 else: self.consecutiveShortThrows = 0 return self.consecutiveShortThrows >= PartyGlobals.CogActivityShortThrowSpam def _startUpdateTask(self): task = Task(self._updateTask) task.lastPositionBroadcastTime = 0.0 self.throwPiePrevTime = 0 taskMgr.add(task, UPDATE_TASK_NAME) def _stopUpdateTask(self): taskMgr.remove(UPDATE_TASK_NAME) def _updateTask(self, task): self._update() if base.localAvatar.getPos() != self.prevPos: self.prevPos = base.localAvatar.getPos() self.lastMoved = self.activity.getCurrentActivityTime() if max(self.activity.getCurrentActivityTime() - self.lastMoved, 0) > PartyGlobals.ToonMoveIdleThreshold: self.gui.showMoveControls() if max(self.activity.getCurrentActivityTime() - self.throwPiePrevTime, 0) > PartyGlobals.ToonAttackIdleThreshold: self.gui.showAttackControls() if self.input.throwPieWasReleased: if self.checkForThrowSpam(globalClock.getFrameTime()): self.gui.showSpamWarning() self.input.throwPieWasReleased = False self.throwPie(self.getPieThrowingPower(globalClock.getFrameTime())) return Task.cont def throwPie(self, piePower): if not self.activity.isState('Active'): return if self.activity.getCurrentActivityTime() - self.throwPiePrevTime > THROW_PIE_LIMIT_TIME: self.throwPiePrevTime = self.activity.getCurrentActivityTime() self.activity.b_pieThrow(self.toon, piePower) def _update(self): self.control.update() def getLookat(self, whosLooking, refNode = None): if refNode is None: refNode = render dist = 5.0 oldParent = self.tempNP.getParent() self.tempNP.reparentTo(whosLooking) self.tempNP.setPos(0.0, dist, 0.0) pos = self.tempNP.getPos(refNode) self.tempNP.reparentTo(oldParent) return pos def entersActivity(self): base.cr.playGame.getPlace().setState('activity') PartyCogActivityPlayer.entersActivity(self) self.gui.disableToontownHUD() self.cameraManager = CameraManager(camera) self.tempNP = NodePath('temp') self.lookAtMyTeam() self.control = StrafingControl(self) def exitsActivity(self): PartyCogActivityPlayer.exitsActivity(self) self.gui.enableToontownHUD() self.cameraManager.setEnabled(False) self.tempNP.removeNode() self.tempNP = None if not aspect2d.find('**/JellybeanRewardGui*'): base.cr.playGame.getPlace().setState('walk') else: self.toon.startPosHprBroadcast() return def getRunToStartPositionIval(self): targetH = self.locator.getH() travelVec = self.position - self.toon.getPos(self.activity.root) duration = travelVec.length() / 9.778 startH = 0.0 if travelVec.getY() < 0.0: startH = 180.0 return Sequence(Func(self.toon.startPosHprBroadcast, 0.1), Func(self.toon.b_setAnimState, 'run'), Parallel(self.toon.hprInterval(0.5, VBase3(startH, 0.0, 0.0), other=self.activity.root), self.toon.posInterval(duration, self.position, other=self.activity.root)), Func(self.toon.b_setAnimState, 'neutral'), self.toon.hprInterval(0.25, VBase3(targetH, 0.0, 0.0), other=self.activity.root), Func(self.toon.stopPosHprBroadcast)) def enable(self): if self.enabled: return PartyCogActivityPlayer.enable(self) self.toon.b_setAnimState('Happy') self._initOrthoWalk() self.orthoWalk.start() self.orthoWalking = True self.input.enable() self.gui.disableToontownHUD() self.gui.load() self.gui.setScore(0) self.gui.showScore() self.gui.setTeam(self.team) self.gui.startTrackingCogs(self.activity.view.cogManager.cogs) self.control.enable() self._startUpdateTask() def disable(self): if not self.enabled: return self._stopUpdateTask() self.toon.b_setAnimState('neutral') PartyCogActivityPlayer.disable(self) self.orthoWalking = False self.orthoWalk.stop() self._destroyOrthoWalk() self.input.disable() self._aimMode = False self.cameraManager.setEnabled(False) self.gui.hide() self.gui.stopTrackingCogs() self.gui.unload() def updateScore(self): self.gui.setScore(self.score) def b_updateToonPosition(self): self.updateToonPosition() self.d_updateToonPosition() def d_updateToonPosition(self): self.toon.d_setPos(self.toon.getX(), self.toon.getY(), self.toon.getZ()) self.toon.d_setH(self.toon.getH()) def lookAtArena(self): self.cameraManager.setEnabled(True) self.cameraManager.setTargetPos(self.activity.view.arena.find('**/conclusionCamPos_locator').getPos(render)) self.cameraManager.setTargetLookAtPos(self.activity.view.arena.find('**/conclusionCamAim_locator').getPos(render)) def lookAtMyTeam(self): activityView = self.activity.view arena = activityView.arena pos = activityView.teamCamPosLocators[self.team].getPos() aim = activityView.teamCamAimLocators[self.team].getPos() camera.wrtReparentTo(arena) self.cameraManager.setPos(camera.getPos(render)) self.tempNP.reparentTo(arena) self.tempNP.setPos(arena, pos) self.cameraManager.setTargetPos(self.tempNP.getPos(render)) self.cameraManager.setLookAtPos(self.getLookat(camera)) self.tempNP.reparentTo(arena) self.tempNP.setPos(arena, aim) self.cameraManager.setTargetLookAtPos(self.tempNP.getPos(render)) self.cameraManager.setEnabled(True) camera.setP(0.0) camera.setR(0.0)
class CogdoMazeGameIntro(CogdoGameMovie): def __init__(self, maze, exit, rng): CogdoGameMovie.__init__(self) self._maze = maze self._exit = exit self._rng = RandomNumGen(rng) self._camTarget = None self._state = 0 self._suits = [] def _getRandomLine(self, lineList): return CogdoUtil.getRandomDialogueLine(lineList, self._rng) def displayLine(self, who, text): self._dialogueLabel.node().setText(text) if who == 'toon': self.toonHead.reparentTo(aspect2d) self.cogHead.reparentTo(hidden) self._toonDialogueSfx.play() self.toonHead.setClipPlane(self.clipPlane) else: self.toonHead.reparentTo(hidden) self.cogHead.reparentTo(aspect2d) self._cogDialogueSfx.play() self.cogHead.setClipPlane(self.clipPlane) def makeSuit(self, suitType): suit = Suit.Suit() dna = SuitDNA.SuitDNA() dna.newSuit(suitType) suit.setStyle(dna) suit.isDisguised = 1 suit.generateSuit() suit.setScale(1, 1, 2) suit.setPos(0, 0, -4.4) suit.reparentTo(self.toonHead) for part in suit.getHeadParts(): part.hide() def load(self): CogdoGameMovie.load(self) self.toonDNA = ToonDNA.ToonDNA() self.toonDNA.newToonFromProperties('dss', 'ss', 'm', 'm', 2, 0, 2, 2, 1, 8, 1, 8, 1, 14) self.toonHead = Toon.Toon() self.toonHead.setDNA(self.toonDNA) self.makeSuit('sc') self.toonHead.getGeomNode().setDepthWrite(1) self.toonHead.getGeomNode().setDepthTest(1) self.toonHead.loop('neutral') self.toonHead.setPosHprScale(-0.73, 0, -1.27, 180, 0, 0, 0.18, 0.18, 0.18) self.toonHead.reparentTo(hidden) self.toonHead.startBlink() self.cogHead = Suit.Suit() self.cogDNA = SuitDNA.SuitDNA() self.cogDNA.newSuit('ms') self.cogHead.setDNA(self.cogDNA) self.cogHead.getGeomNode().setDepthWrite(1) self.cogHead.getGeomNode().setDepthTest(1) self.cogHead.loop('neutral') self.cogHead.setPosHprScale(-0.73, 0, -1.46, 180, 0, 0, 0.14, 0.14, 0.14) self.cogHead.reparentTo(hidden) self.clipPlane = self.toonHead.attachNewNode(PlaneNode('clip')) self.clipPlane.node().setPlane(Plane(0, 0, 1, 0)) self.clipPlane.setPos(0, 0, 2.45) audioMgr = base.cogdoGameAudioMgr self._cogDialogueSfx = audioMgr.createSfx('cogDialogue') self._toonDialogueSfx = audioMgr.createSfx('toonDialogue') suitData = Globals.SuitData[Globals.SuitTypes.Boss] bossSuit = Suit.Suit() bossSuit.nametag3d.stash() bossSuit.nametag.destroy() d = SuitDNA.SuitDNA() d.newSuit(suitData['dnaName']) bossSuit.setDNA(d) bossSuit.setScale(suitData['scale']) bossSuit.loop('neutral') bossSuit.reparentTo(render) bossSuit.setPos(self._exit, -5, -5, 0) bossSuit.lookAt(self._exit) self._suits.append(bossSuit) self._camHelperNode = NodePath('CamHelperNode') self._camHelperNode.reparentTo(render) dialogue = TTLocalizer.CogdoMazeIntroMovieDialogue introDuration = Globals.IntroDurationSeconds waitDuration = introDuration / len(dialogue) def start(): camera.wrtReparentTo(render) self._exit.open(animate=False) def showBoss(): self._setCamTarget(bossSuit, 20, offset=Point3(0, 0, 7), angle=Point3(0, 15, 0)) bossSuit.loop('victory') self._state = 1 def showExit(): self._setCamTarget(self._exit, 10, offset=Point3(0, 0, 0), angle=Point3(0, 60, 0)) self._exit.close() self._state = 2 showExitIval = Parallel(camera.posInterval(waitDuration * 0.5, (10, -25, 20), other=self._exit, blendType='easeInOut'), Sequence(Wait(waitDuration * 0.25), Func(bossSuit.play, 'effort'), camera.hprInterval(waitDuration * 0.25, (30, -30, 0), blendType='easeInOut'), Func(self._exit.close), Wait(waitDuration * 0.5))) def showWaterCooler(): wc = self._maze.getWaterCoolers()[0] self._setCamTarget(wc, 25, angle=Point3(-30, 60, 0)) camera.wrtReparentTo(self._camHelperNode) self._state = 3 def end(): self._stopUpdateTask() self._ival = Sequence(Func(start), Func(self.displayLine, 'toon', self._getRandomLine(dialogue[0])), showExitIval, Func(showWaterCooler), Func(self.displayLine, 'toon', self._getRandomLine(dialogue[1])), Wait(waitDuration), Func(showBoss), bossSuit.hprInterval(1.0, bossSuit.getHpr() + Point3(180, 0, 0), blendType='easeInOut'), Func(self.displayLine, 'toon', self._getRandomLine(dialogue[2])), Wait(waitDuration - 1.0), Func(end)) self._startUpdateTask() def _setCamTarget(self, targetNP, distance, offset = Point3(0, 0, 0), angle = Point3(0, 0, 0)): camera.wrtReparentTo(render) self._camTarget = targetNP self._camOffset = offset self._camAngle = angle self._camDistance = distance self._camHelperNode.setPos(self._camTarget, self._camOffset) self._camHelperNode.setHpr(self._camTarget, 180 + self._camAngle[0], self._camAngle[1], self._camAngle[2]) camera.setPos(self._camHelperNode, 0, self._camDistance, 0) def _updateTask(self, task): dt = globalClock.getDt() if self._state == 1: self._camHelperNode.setPos(self._camTarget.getPos() + self._camOffset) camera.setPos(self._camHelperNode, 0, self._camDistance, 0) camera.lookAt(self._camTarget, 0, 0, 4) elif self._state == 2: camera.lookAt(self._camTarget, 0, 0, 5) elif self._state == 3: self._camHelperNode.setHpr(self._camHelperNode, dt, dt, 0) camera.setY(camera, 0.8 * dt) camera.lookAt(self._camTarget, 0, 0, 3) return task.cont def unload(self): self._exit = None self._camTarget = None self._camHelperNode.removeNode() del self._camHelperNode for suit in self._suits: suit.cleanup() suit.removeNode() suit.delete() self._suits = [] CogdoGameMovie.unload(self) del self._cogDialogueSfx del self._toonDialogueSfx self.toonHead.stopBlink() self.toonHead.stop() self.toonHead.removeNode() self.toonHead.delete() del self.toonHead self.cogHead.stop() self.cogHead.removeNode() self.cogHead.delete() del self.cogHead
class Sprite2d: class Cell: def __init__(self, col, row): self.col = col self.row = row def __str__(self): return "Cell - Col %d, Row %d" % (self.col, self.row) class Animation: def __init__(self, cells, fps): self.cells = cells self.fps = fps self.playhead = 0 ALIGN_CENTER = "Center" ALIGN_LEFT = "Left" ALIGN_RIGHT = "Right" ALIGN_BOTTOM = "Bottom" ALIGN_TOP = "Top" TRANS_ALPHA = TransparencyAttrib.MAlpha TRANS_DUAL = TransparencyAttrib.MDual # One pixel is divided by this much. If you load a 100x50 image with PIXEL_SCALE of 10.0 # you get a card that is 1 unit wide, 0.5 units high PIXEL_SCALE = 20.0 def __init__(self, image_path, rowPerFace, name=None,\ rows=1, cols=1, scale=1.0,\ twoSided=False, alpha=TRANS_ALPHA,\ repeatX=1, repeatY=1,\ anchorX=ALIGN_CENTER, anchorY=ALIGN_BOTTOM): """ Create a card textured with an image. The card is sized so that the ratio between the card and image is the same. """ global SpriteId self.spriteNum = str(SpriteId) SpriteId += 1 scale *= self.PIXEL_SCALE self.animations = {} self.scale = scale self.repeatX = repeatX self.repeatY = repeatY self.flip = {'x': False, 'y': False} self.rows = rows self.cols = cols self.currentFrame = 0 self.currentAnim = None self.loopAnim = False self.frameInterrupt = True # Create the NodePath if name: self.node = NodePath("Sprite2d:%s" % name) else: self.node = NodePath("Sprite2d:%s" % image_path) # Set the attribute for transparency/twosided self.node.node().setAttrib(TransparencyAttrib.make(alpha)) if twoSided: self.node.setTwoSided(True) # Make a filepath self.imgFile = Filename(image_path) if self.imgFile.empty(): raise IOError, "File not found" # Instead of loading it outright, check with the PNMImageHeader if we can open # the file. imgHead = PNMImageHeader() if not imgHead.readHeader(self.imgFile): raise IOError, "PNMImageHeader could not read file. Try using absolute filepaths" # Load the image with a PNMImage image = PNMImage() image.read(self.imgFile) self.sizeX = image.getXSize() self.sizeY = image.getYSize() # We need to find the power of two size for the another PNMImage # so that the texture thats loaded on the geometry won't have artifacts textureSizeX = self.nextsize(self.sizeX) textureSizeY = self.nextsize(self.sizeY) # The actual size of the texture in memory self.realSizeX = textureSizeX self.realSizeY = textureSizeY self.paddedImg = PNMImage(textureSizeX, textureSizeY) if image.hasAlpha(): self.paddedImg.alphaFill(0) # Copy the source image to the image we're actually using self.paddedImg.blendSubImage(image, 0, 0) # We're done with source image, clear it image.clear() # The pixel sizes for each cell self.colSize = self.sizeX / self.cols self.rowSize = self.sizeY / self.rows # How much padding the texture has self.paddingX = textureSizeX - self.sizeX self.paddingY = textureSizeY - self.sizeY # Set UV padding self.uPad = float(self.paddingX) / textureSizeX self.vPad = float(self.paddingY) / textureSizeY # The UV dimensions for each cell self.uSize = (1.0 - self.uPad) / self.cols self.vSize = (1.0 - self.vPad) / self.rows self.cards = [] self.rowPerFace = rowPerFace for i in range(len(rowPerFace)): card = CardMaker("Sprite2d-Geom") # The positions to create the card at if anchorX == self.ALIGN_LEFT: posLeft = 0 posRight = (self.colSize / scale) * repeatX elif anchorX == self.ALIGN_CENTER: posLeft = -(self.colSize / 2.0 / scale) * repeatX posRight = (self.colSize / 2.0 / scale) * repeatX elif anchorX == self.ALIGN_RIGHT: posLeft = -(self.colSize / scale) * repeatX posRight = 0 if anchorY == self.ALIGN_BOTTOM: posTop = 0 posBottom = (self.rowSize / scale) * repeatY elif anchorY == self.ALIGN_CENTER: posTop = -(self.rowSize / 2.0 / scale) * repeatY posBottom = (self.rowSize / 2.0 / scale) * repeatY elif anchorY == self.ALIGN_TOP: posTop = -(self.rowSize / scale) * repeatY posBottom = 0 card.setFrame(posLeft, posRight, posTop, posBottom) card.setHasUvs(True) self.cards.append(self.node.attachNewNode(card.generate())) self.cards[-1].setH(i * 360 / len(rowPerFace)) # Since the texture is padded, we need to set up offsets and scales to make # the texture fit the whole card self.offsetX = (float(self.colSize) / textureSizeX) self.offsetY = (float(self.rowSize) / textureSizeY) # self.node.setTexScale(TextureStage.getDefault(), self.offsetX * repeatX, self.offsetY * repeatY) # self.node.setTexOffset(TextureStage.getDefault(), 0, 1-self.offsetY) self.texture = Texture() self.texture.setXSize(textureSizeX) self.texture.setYSize(textureSizeY) self.texture.setZSize(1) # Load the padded PNMImage to the texture self.texture.load(self.paddedImg) self.texture.setMagfilter(Texture.FTNearest) self.texture.setMinfilter(Texture.FTNearest) #Set up texture clamps according to repeats if repeatX > 1: self.texture.setWrapU(Texture.WMRepeat) else: self.texture.setWrapU(Texture.WMClamp) if repeatY > 1: self.texture.setWrapV(Texture.WMRepeat) else: self.texture.setWrapV(Texture.WMClamp) self.node.setTexture(self.texture) self.setFrame(0) def nextsize(self, num): """ Finds the next power of two size for the given integer. """ p2x = max(1, log(num, 2)) notP2X = modf(p2x)[0] > 0 return 2**int(notP2X + p2x) def setFrame(self, frame=0): """ Sets the current sprite to the given frame """ self.frameInterrupt = True # A flag to tell the animation task to shut it up ur face self.currentFrame = frame self.flipTexture() def playAnim(self, animName, loop=False): """ Sets the sprite to animate the given named animation. Booleon to loop animation""" if not taskMgr.hasTaskNamed("Animate sprite" + self.spriteNum): if hasattr(self, "task"): taskMgr.remove("Animate sprite" + self.spriteNum) del self.task self.frameInterrupt = False # Clear any previous interrupt flags self.loopAnim = loop self.currentAnim = self.animations[animName] self.currentAnim.playhead = 0 self.task = taskMgr.doMethodLater( 1.0 / self.currentAnim.fps, self.animPlayer, "Animate sprite" + self.spriteNum) def createAnim(self, animName, frameCols, fps=12): """ Create a named animation. Takes the animation name and a tuple of frame numbers """ self.animations[animName] = Sprite2d.Animation(frameCols, fps) return self.animations[animName] def flipX(self, val=None): """ Flip the sprite on X. If no value given, it will invert the current flipping.""" if val: self.flip['x'] = val else: if self.flip['x']: self.flip['x'] = False else: self.flip['x'] = True self.flipTexture() return self.flip['x'] def flipY(self, val=None): """ See flipX """ if val: self.flip['y'] = val else: if self.flip['y']: self.flip['y'] = False else: self.flip['y'] = True self.flipTexture() return self.flip['y'] def updateCameraAngle(self, cameraNode): baseH = cameraNode.getH(render) - self.node.getH(render) degreesBetweenCards = 360 / len(self.cards) bestCard = int( ((baseH) + degreesBetweenCards / 2) % 360 / degreesBetweenCards) #print baseH, bestCard for i in range(len(self.cards)): if i == bestCard: self.cards[i].show() else: self.cards[i].hide() def flipTexture(self): """ Sets the texture coordinates of the texture to the current frame""" for i in range(len(self.cards)): currentRow = self.rowPerFace[i] sU = self.offsetX * self.repeatX sV = self.offsetY * self.repeatY oU = 0 + self.currentFrame * self.uSize #oU = 0 + self.frames[self.currentFrame].col * self.uSize #oV = 1 - self.frames[self.currentFrame].row * self.vSize - self.offsetY oV = 1 - currentRow * self.vSize - self.offsetY if self.flip['x'] ^ i == 1: ##hack to fix side view #print "flipping, i = ",i sU *= -1 #oU = self.uSize + self.frames[self.currentFrame].col * self.uSize oU = self.uSize + self.currentFrame * self.uSize if self.flip['y']: sV *= -1 #oV = 1 - self.frames[self.currentFrame].row * self.vSize oV = 1 - currentRow * self.vSize self.cards[i].setTexScale(TextureStage.getDefault(), sU, sV) self.cards[i].setTexOffset(TextureStage.getDefault(), oU, oV) def clear(self): """ Free up the texture memory being used """ self.texture.clear() self.paddedImg.clear() self.node.removeNode() def animPlayer(self, task): if self.frameInterrupt: return task.done #print "Playing",self.currentAnim.cells[self.currentAnim.playhead] self.currentFrame = self.currentAnim.cells[self.currentAnim.playhead] self.flipTexture() if self.currentAnim.playhead + 1 < len(self.currentAnim.cells): self.currentAnim.playhead += 1 return task.again if self.loopAnim: self.currentAnim.playhead = 0 return task.again
class PartyCog(FSM): notify = directNotify.newCategory("PartyCog") HpTextGenerator = TextNode("HpTextGenerator") hpText = None height = 7 def __init__(self, parentNode, id, bounceSpeed=3, bounceHeight=1, rotateSpeed=1, heightShift=1, xMoveSpeed=0, xMoveDistance=0, bounceOffset=0): self.id = id FSM.__init__(self, "PartyCogFSM-%d" % self.id) self.showFacingStatus = False self.xMoveSpeed = xMoveSpeed self.xMoveDistance = xMoveDistance self.heightShift = heightShift self.bounceSpeed = bounceSpeed self.bounceHeight = bounceHeight self.rotateSpeed = rotateSpeed self.parentNode = parentNode self.bounceOffset = bounceOffset self.hitInterval = None self.kaboomTrack = None self.resetRollIval = None self.netTimeSentToStartByHit = 0 self.load() self.request("Down") def load(self): self.root = NodePath("PartyCog-%d" % self.id) self.root.reparentTo(self.parentNode) path = "phase_13/models/parties/cogPinata_" self.actor = Actor( path + "actor", { "idle": path + "idle_anim", "down": path + "down_anim", "up": path + "up_anim", "bodyHitBack": path + "bodyHitBack_anim", "bodyHitFront": path + "bodyHitFront_anim", "headHitBack": path + "headHitBack_anim", "headHitFront": path + "headHitFront_anim", }) self.actor.reparentTo(self.root) self.temp_transform = Mat4() self.head_locator = self.actor.attachNewNode("temphead") self.bodyColl = CollisionTube(0, 0, 1, 0, 0, 5.75, 0.75) self.bodyColl.setTangible(1) self.bodyCollNode = CollisionNode("PartyCog-%d-Body-Collision" % self.id) self.bodyCollNode.setCollideMask(ToontownGlobals.PieBitmask) self.bodyCollNode.addSolid(self.bodyColl) self.bodyCollNodePath = self.root.attachNewNode(self.bodyCollNode) self.headColl = CollisionTube(0, 0, 3, 0, 0, 3.0, 1.5) self.headColl.setTangible(1) self.headCollNode = CollisionNode("PartyCog-%d-Head-Collision" % self.id) self.headCollNode.setCollideMask(ToontownGlobals.PieBitmask) self.headCollNode.addSolid(self.headColl) self.headCollNodePath = self.root.attachNewNode(self.headCollNode) # Cog's Left Arm self.arm1Coll = CollisionSphere(1.65, 0, 3.95, 1.0) self.arm1Coll.setTangible(1) self.arm1CollNode = CollisionNode("PartyCog-%d-Arm1-Collision" % self.id) self.arm1CollNode.setCollideMask(ToontownGlobals.PieBitmask) self.arm1CollNode.addSolid(self.arm1Coll) self.arm1CollNodePath = self.root.attachNewNode(self.arm1CollNode) # Cog's Right Arm self.arm2Coll = CollisionSphere(-1.65, 0, 3.45, 1.0) self.arm2Coll.setTangible(1) self.arm2CollNode = CollisionNode("PartyCog-%d-Arm2-Collision" % self.id) self.arm2CollNode.setCollideMask(ToontownGlobals.PieBitmask) self.arm2CollNode.addSolid(self.arm2Coll) self.arm2CollNodePath = self.root.attachNewNode(self.arm2CollNode) splatName = 'splat-creampie' self.splat = globalPropPool.getProp(splatName) self.splat.setBillboardPointEye() self.splatType = globalPropPool.getPropType(splatName) self.pieHitSound = globalBattleSoundCache.getSound( 'AA_wholepie_only.mp3') self.upSound = globalBattleSoundCache.getSound('AV_jump_to_side.mp3') self.hole = loader.loadModel("phase_13/models/parties/cogPinataHole") self.hole.setTransparency(True) self.hole.setP(-90.0) self.hole.setScale(3) self.hole.setBin("ground", 3) self.hole.reparentTo(self.parentNode) def unload(self): self.request("Off") self.clearHitInterval() if self.hole is not None: self.hole.removeNode() self.hole = None if self.actor is not None: self.actor.cleanup() self.actor.removeNode() self.actor = None if self.root is not None: self.root.removeNode() self.root = None if self.kaboomTrack is not None and self.kaboomTrack.isPlaying(): self.kaboomTrack.finish() self.kaboomTrack = None if self.resetRollIval is not None and self.resetRollIval.isPlaying(): self.resetRollIval.finish() self.resetRollIval = None if self.hitInterval is not None and self.hitInterval.isPlaying(): self.hitInterval.finish() self.hitInterval = None del self.upSound del self.pieHitSound #=============================================================================== # FSM States #=============================================================================== def enterStatic(self): pass def exitStatic(self): pass def enterActive(self, startTime): self.root.setR(0.0) updateTask = Task.Task(self.updateTask) updateTask.startTime = startTime taskMgr.add(updateTask, "PartyCog.update-%d" % self.id) def exitActive(self): taskMgr.remove("PartyCog.update-%d" % self.id) taskMgr.remove("PartyCog.bounceTask-%d" % self.id) self.clearHitInterval() self.resetRollIval = self.root.hprInterval(0.5, Point3( self.root.getH(), 0.0, 0.0), blendType="easeInOut") self.resetRollIval.start() self.actor.stop() def enterDown(self): if self.oldState == "Off": downAnimControl = self.actor.getAnimControl("down") self.actor.pose("down", downAnimControl.getNumFrames() - 1) return self.clearHitInterval() startScale = self.hole.getScale() endScale = Point3(5, 5, 5) self.hitInterval = Sequence( LerpFunc(self.setAlongSpline, duration=1.0, fromData=self.currentT, toData=0.0), LerpScaleInterval(self.hole, duration=0.175, scale=endScale, startScale=startScale, blendType="easeIn"), Parallel( SoundInterval(self.upSound, volume=0.6, node=self.actor, cutOff=PartyGlobals.PARTY_COG_CUTOFF), ActorInterval(self.actor, "down", loop=0), ), LerpScaleInterval(self.hole, duration=0.175, scale=Point3(3, 3, 3), startScale=endScale, blendType="easeOut"), ) self.hitInterval.start() def exitDown(self): self.root.setR(0.0) self.root.setH(0.0) self.targetDistance = 0.0 self.targetFacing = 0.0 self.currentT = 0.0 self.setAlongSpline(0.0) self.clearHitInterval() startScale = self.hole.getScale() endScale = Point3(5, 5, 5) self.hitInterval = Sequence( LerpScaleInterval(self.hole, duration=0.175, scale=endScale, startScale=startScale, blendType="easeIn"), Parallel( SoundInterval(self.upSound, volume=0.6, node=self.actor, cutOff=PartyGlobals.PARTY_COG_CUTOFF), ActorInterval(self.actor, "up", loop=0), ), Func(self.actor.loop, "idle"), LerpScaleInterval(self.hole, duration=0.175, scale=Point3(3, 3, 3), startScale=endScale, blendType="easeOut"), ) self.hitInterval.start() def filterDown(self, request, args): if request == "Down": return None else: return self.defaultFilter(request, args) #------------------------------------------------------------------------------ def setEndPoints(self, start, end, amplitude=1.7): self.sinAmplitude = amplitude self.sinPeriod = (end.getX() - start.getX()) / 2 self.sinDisplacement = start.getY() self.startPoint = start self.endPoint = end self.currentT = 0.0 self.targetDistance = 0.0 self.currentFacing = 0.0 self.targetFacing = 0.0 self.setAlongSpline(self.currentT) self.hole.setPos(self.root.getPos()) self.hole.setZ(0.02) def rockBackAndForth(self, task): t = task.startTime + task.time angle = math.sin(t) * 20.0 self.root.setR(angle) # if self.id == 0: # print angle return task.cont def updateDistance(self, distance): self.targetDistance = clamp(distance, -1.0, 1.0) def updateTask(self, task): self.rockBackAndForth(task) if self.targetDistance > self.currentT: self.currentT += min(0.01, self.targetDistance - self.currentT) self.setAlongSpline(self.currentT) elif self.targetDistance < self.currentT: self.currentT += max(-0.01, self.targetDistance - self.currentT) self.setAlongSpline(self.currentT) if self.currentT < 0.0: self.targetFacing = -90.0 elif self.currentT > 0.0: self.targetFacing = 90.0 else: self.targetFacing = 0.0 if self.targetFacing > self.currentFacing: self.currentFacing += min(10, self.targetFacing - self.currentFacing) elif self.targetFacing < self.currentFacing: self.currentFacing += max(-10, self.targetFacing - self.currentFacing) self.root.setH(self.currentFacing) return task.cont def setAlongSpline(self, t): t = t + 1.0 dist = (self.endPoint.getX() - self.startPoint.getX()) / 2.0 x = self.startPoint.getX() + t * dist y = self.startPoint.getY() - math.sin( t * 2 * math.pi) * self.sinAmplitude self.root.setPos(x, y, 0) def startBounce(self): taskMgr.add(self.bounce, "PartyCog.bounceTask-%d" % self.id) def bounce(self, task): #self.root.setH(self.root.getH() - self.rotateSpeed) self.root.setZ((math.sin((self.bounceOffset + task.time) * self.bounceSpeed) * self.bounceHeight) + self.heightShift) return task.cont def setPos(self, position): self.root.setPos(position) def respondToPieHit(self, timestamp, position, hot=False, direction=1.0): """The toon hit us, react appropriately.""" assert (self.notify.debugStateCall(self)) if self.netTimeSentToStartByHit < timestamp: self.__showSplat(position, direction, hot) if self.netTimeSentToStartByHit < timestamp: self.netTimeSentToStartByHit = timestamp else: #self.notify.debug('localStamp = %s, lastLocalTimeStampFromAI=%s, ignoring respondToPieHit' % (localStamp, self.lastLocalTimeStampFromAI)) self.notify.debug( 'respondToPieHit self.netTimeSentToStartByHit = %s' % self.netTimeSentToStartByHit) def clearHitInterval(self): if self.hitInterval is not None and self.hitInterval.isPlaying(): self.hitInterval.clearToInitial() def __showSplat(self, position, direction, hot=False): """Show the splat graphic and sound.""" if self.kaboomTrack is not None and self.kaboomTrack.isPlaying(): self.kaboomTrack.finish() self.clearHitInterval() splatName = 'splat-creampie' self.splat = globalPropPool.getProp(splatName) self.splat.setBillboardPointEye() self.splat.reparentTo(render) self.splat.setPos(self.root, position) self.splat.setAlphaScale(1.0) if not direction == 1.0: #self.splat.setColorScale(Vec4(0.0, 0.0, 50.0, 1.0)) self.splat.setColorScale(PartyGlobals.CogActivitySplatColors[0]) if self.currentFacing > 0.0: facing = "HitFront" else: facing = "HitBack" else: self.splat.setColorScale(PartyGlobals.CogActivitySplatColors[1]) #self.splat.setColorScale(Vec4(1.0, 0.6, 0.08, 1.0)) if self.currentFacing > 0.0: facing = "HitBack" else: facing = "HitFront" if hot: targetscale = 0.75 part = "head" else: targetscale = 0.5 part = "body" def setSplatAlpha(amount): self.splat.setAlphaScale(amount) self.hitInterval = Sequence( ActorInterval(self.actor, part + facing, loop=0), Func(self.actor.loop, "idle"), ) self.hitInterval.start() self.kaboomTrack = Parallel( SoundInterval(self.pieHitSound, volume=1.0, node=self.actor, cutOff=PartyGlobals.PARTY_COG_CUTOFF), Sequence( Func(self.splat.showThrough), Parallel( Sequence( LerpScaleInterval(self.splat, duration=0.175, scale=targetscale, startScale=Point3(0.1, 0.1, 0.1), blendType="easeOut"), Wait(0.175), ), Sequence( Wait(0.1), LerpFunc( setSplatAlpha, duration=1.0, #0.4, fromData=1.0, toData=0.0, blendType="easeOut"))), Func(self.splat.cleanup), Func(self.splat.removeNode), )) self.kaboomTrack.start() def showHitScore(self, number, scale=1): """ Shows the hit score. Borrowed from otp.avatar.DistributedAvatar.showHpText """ if number <= 0: return # Get rid of the number if it is already there. if self.hpText: self.hideHitScore() # Set the font self.HpTextGenerator.setFont(ToontownGlobals.getSignFont()) # Show both negative and positive signs if number < 0: self.HpTextGenerator.setText(str(number)) else: self.HpTextGenerator.setText("+" + str(number)) # No shadow self.HpTextGenerator.clearShadow() # Center the number self.HpTextGenerator.setAlign(TextNode.ACenter) # Red, always #if number < 0: r = 1 #0.9 g = 1 #0 b = 0 a = 1 self.HpTextGenerator.setTextColor(r, g, b, a) self.hpTextNode = self.HpTextGenerator.generate() # Put the hpText over the head of the avatar self.hpText = render.attachNewNode(self.hpTextNode) self.hpText.setScale(scale) # Make sure it is a billboard self.hpText.setBillboardPointEye() # Render it after other things in the scene. self.hpText.setBin('fixed', 100) # Initial position ... Center of the body... the "tan tien" self.hpText.setPos(self.root, 0, 0, self.height / 2) # Black magic from the early days of Panda3D, later replaced by a Sequence seq = Task.sequence( # Fly the number out of the character self.hpText.lerpPos(Point3( self.root.getX(render), self.root.getY(render), self.root.getZ(render) + self.height + 1.0), 0.25, blendType='easeOut'), Task.pause(0.25), # Fade the number self.hpText.lerpColor(Vec4(r, g, b, a), Vec4(r, g, b, 0), 0.1), # Get rid of the number Task.Task(self.__hideHitScoreTask)) taskMgr.add(seq, "PartyCogHpText" + str(self.id)) def __hideHitScoreTask(self, task): self.hideHitScore() return Task.done def hideHitScore(self): if self.hpText: taskMgr.remove("PartyCogHpText" + str(self.id)) self.hpText.removeNode() self.hpText = None def getHeadLocation(self): (self.actor.getJoints(jointName="head")[0]).getNetTransform( self.temp_transform) self.head_locator.setMat(self.temp_transform) #print self.head_locator.getZ() return self.head_locator.getZ(self.root)
def destroy(self): NodePath.removeNode(self)
class CogdoFlyingCameraManager: def __init__(self, cam, parent, player, level): self._toon = player.toon self._camera = cam self._parent = parent self._player = player self._level = level self._enabled = False def enable(self): if self._enabled: return self._toon.detachCamera() self._prevToonY = 0.0 levelBounds = self._level.getBounds() l = Globals.Camera.LevelBoundsFactor self._bounds = ((levelBounds[0][0] * l[0], levelBounds[0][1] * l[0]), (levelBounds[1][0] * l[1], levelBounds[1][1] * l[1]), (levelBounds[2][0] * l[2], levelBounds[2][1] * l[2])) self._lookAtZ = self._toon.getHeight( ) + Globals.Camera.LookAtToonHeightOffset self._camParent = NodePath('CamParent') self._camParent.reparentTo(self._parent) self._camParent.setPos(self._toon, 0, 0, 0) self._camParent.setHpr(180, Globals.Camera.Angle, 0) self._camera.reparentTo(self._camParent) self._camera.setPos(0, Globals.Camera.Distance, 0) self._camera.lookAt(self._toon, 0, 0, self._lookAtZ) self._cameraLookAtNP = NodePath('CameraLookAt') self._cameraLookAtNP.reparentTo(self._camera.getParent()) self._cameraLookAtNP.setPosHpr(self._camera.getPos(), self._camera.getHpr()) self._levelBounds = self._level.getBounds() self._enabled = True self._frozen = False self._initCollisions() def _initCollisions(self): self._camCollRay = CollisionRay() camCollNode = CollisionNode('CameraToonRay') camCollNode.addSolid(self._camCollRay) camCollNode.setFromCollideMask(OTPGlobals.WallBitmask | OTPGlobals.CameraBitmask | ToontownGlobals.FloorEventBitmask | ToontownGlobals.CeilingBitmask) camCollNode.setIntoCollideMask(0) self._camCollNP = self._camera.attachNewNode(camCollNode) self._camCollNP.show() self._collOffset = Vec3(0, 0, 0.5) self._collHandler = CollisionHandlerQueue() self._collTrav = CollisionTraverser() self._collTrav.addCollider(self._camCollNP, self._collHandler) self._betweenCamAndToon = {} self._transNP = NodePath('trans') self._transNP.reparentTo(render) self._transNP.setTransparency(True) self._transNP.setAlphaScale(Globals.Camera.AlphaBetweenToon) self._transNP.setBin('fixed', 10000) def _destroyCollisions(self): self._collTrav.removeCollider(self._camCollNP) self._camCollNP.removeNode() del self._camCollNP del self._camCollRay del self._collHandler del self._collOffset del self._betweenCamAndToon self._transNP.removeNode() del self._transNP def freeze(self): self._frozen = True def unfreeze(self): self._frozen = False def disable(self): if not self._enabled: return self._destroyCollisions() self._camera.wrtReparentTo(render) self._cameraLookAtNP.removeNode() del self._cameraLookAtNP self._camParent.removeNode() del self._camParent del self._prevToonY del self._lookAtZ del self._bounds del self._frozen self._enabled = False def update(self, dt=0.0): self._updateCam(dt) self._updateCollisions() def _updateCam(self, dt): toonPos = self._toon.getPos() camPos = self._camParent.getPos() x = camPos[0] z = camPos[2] toonWorldX = self._toon.getX(render) maxX = Globals.Camera.MaxSpinX toonWorldX = clamp(toonWorldX, -1.0 * maxX, maxX) spinAngle = Globals.Camera.MaxSpinAngle * toonWorldX * toonWorldX / ( maxX * maxX) newH = 180.0 + spinAngle self._camParent.setH(newH) spinAngle = spinAngle * (pi / 180.0) distBehindToon = Globals.Camera.SpinRadius * cos(spinAngle) distToRightOfToon = Globals.Camera.SpinRadius * sin(spinAngle) d = self._camParent.getX() - clamp(toonPos[0], *self._bounds[0]) if abs(d) > Globals.Camera.LeewayX: if d > Globals.Camera.LeewayX: x = toonPos[0] + Globals.Camera.LeewayX else: x = toonPos[0] - Globals.Camera.LeewayX x = self._toon.getX(render) + distToRightOfToon boundToonZ = min(toonPos[2], self._bounds[2][1]) d = z - boundToonZ if d > Globals.Camera.MinLeewayZ: if self._player.velocity[2] >= 0 and toonPos[ 1] != self._prevToonY or self._player.velocity[2] > 0: z = boundToonZ + d * INVERSE_E**(dt * Globals.Camera.CatchUpRateZ) elif d > Globals.Camera.MaxLeewayZ: z = boundToonZ + Globals.Camera.MaxLeewayZ elif d < -Globals.Camera.MinLeewayZ: z = boundToonZ - Globals.Camera.MinLeewayZ if self._frozen: y = camPos[1] else: y = self._toon.getY(render) - distBehindToon self._camParent.setPos(x, smooth(camPos[1], y), smooth(camPos[2], z)) if toonPos[2] < self._bounds[2][1]: h = self._cameraLookAtNP.getH() if d >= Globals.Camera.MinLeewayZ: self._cameraLookAtNP.lookAt(self._toon, 0, 0, self._lookAtZ) elif d <= -Globals.Camera.MinLeewayZ: self._cameraLookAtNP.lookAt(self._camParent, 0, 0, self._lookAtZ) self._cameraLookAtNP.setHpr(h, self._cameraLookAtNP.getP(), 0) self._camera.setHpr( smooth(self._camera.getHpr(), self._cameraLookAtNP.getHpr())) self._prevToonY = toonPos[1] def _updateCollisions(self): pos = self._toon.getPos(self._camera) + self._collOffset self._camCollRay.setOrigin(pos) direction = -Vec3(pos) direction.normalize() self._camCollRay.setDirection(direction) self._collTrav.traverse(render) nodesInBetween = {} if self._collHandler.getNumEntries() > 0: self._collHandler.sortEntries() for entry in self._collHandler.getEntries(): name = entry.getIntoNode().getName() if name.find('col_') >= 0: np = entry.getIntoNodePath().getParent() if not np in nodesInBetween: nodesInBetween[np] = np.getParent() for np in nodesInBetween.keys(): if np in self._betweenCamAndToon: del self._betweenCamAndToon[np] else: np.setTransparency(True) np.wrtReparentTo(self._transNP) if np.getName().find('lightFixture') >= 0: if not np.find('**/*floor_mesh').isEmpty(): np.find('**/*floor_mesh').hide() elif np.getName().find('platform') >= 0: if not np.find('**/*Floor').isEmpty(): np.find('**/*Floor').hide() for np, parent in self._betweenCamAndToon.items(): np.wrtReparentTo(parent) np.setTransparency(False) if np.getName().find('lightFixture') >= 0: if not np.find('**/*floor_mesh').isEmpty(): np.find('**/*floor_mesh').show() elif np.getName().find('platform') >= 0: if not np.find('**/*Floor').isEmpty(): np.find('**/*Floor').show() self._betweenCamAndToon = nodesInBetween
def cleanup(self): self.arrowButton.destroy() NodePath.removeNode(self)
class LegendaryFish(Fish): def __init__(self, fishManager, myData, index): Fish.__init__(self, fishManager, myData, index) self.fsm = LegendaryFishFSM(self) self.actor.setScale(self.myData['scaleRange'][0]) self.staminaValue = self.myData['stamina'] self.aboutToBitingInterval = None self.fishChaseLureSequence = Sequence() self.lfStruggleSequence = Sequence() self.initFishStaminaBar() self.lurePosition = None def initFishStaminaBar(self): self.legendaryGui = loader.loadModel('models/minigames/pir_m_gam_fsh_legendaryGui') self.iconBaseFrame = DirectFrame(relief = None, state = DGG.DISABLED, pos = (0, 0, 0), sortOrder = 30, image = self.legendaryGui.find('**/pir_t_gui_fsh_fishPortraitFrame'), image_scale = 0.17999999999999999, image_pos = (0, 0, 0)) self.iconBaseFrame.setTransparency(TransparencyAttrib.MAlpha) self.fishUINodePath = NodePath(self.iconBaseFrame) self.fishUINodePath.setPos(-0.29999999999999999, 0.0, 0.82999999999999996) self.fishUINodePath.reparentTo(hidden) self.iconCard = loader.loadModel('models/gui/treasure_gui') self.iconBaseFrame.iconImage = OnscreenImage(parent = self.iconBaseFrame, image = self.iconCard.find('**/%s*' % CollectionMap.Assets[self.myData['id']]), scale = 0.34999999999999998, hpr = (0, 0, 0), pos = (0.0, 0, 0.0)) self.fishNameLabel = TextNode('fishNameLabel') name = self.getName().split('_') self.fishNameLabel.setText(name[0]) self.fishNameLabel.setTextColor(1.0, 1.0, 1.0, 1.0) self.fishNameLabelNodePath = NodePath(self.fishNameLabel) self.fishNameLabelNodePath.setPos(0.29999999999999999, 0, 0.040000000000000001) self.fishNameLabelNodePath.setScale(0.044999999999999998) self.fishNameLabelNodePath.reparentTo(self.iconBaseFrame) self.fishStaminaBar = DirectWaitBar(parent = self.iconBaseFrame, relief = DGG.FLAT, state = DGG.DISABLED, range = 100, value = 0, sortOrder = 20, frameColor = (0, 0, 0, 1.0), pos = (0.070000000000000007, 0.0, -0.014999999999999999), hpr = (0, 0, 0), frameSize = (0, 0.71999999999999997, 0, 0.028000000000000001)) self.fishStaminaBar['value'] = self.staminaValue self.fishStaminaBar['barColor'] = FishingGlobals.fishingStaminaBarColor[int((self.staminaValue / 100.0) * (len(FishingGlobals.fishingStaminaBarColor) - 1))] self.fishStaminaValueLabel = TextNode('fishStaminaValueLabel') self.fishStaminaValueLabel.setText(str(self.staminaValue) + '//' + str(self.staminaValue)) self.fishStaminaValueLabel.setTextColor(1.0, 1.0, 1.0, 1.0) self.fishStaminaValueLabelNodePath = NodePath(self.fishStaminaValueLabel) self.fishStaminaValueLabelNodePath.setPos(0.66000000000000003, 0, -0.059999999999999998) self.fishStaminaValueLabelNodePath.setScale(0.044999999999999998) self.fishStaminaValueLabelNodePath.reparentTo(self.iconBaseFrame) self.fishStaminaBarFrame = DirectLabel(parent = self.iconBaseFrame, relief = None, state = DGG.DISABLED, frameColor = (1, 1, 1, 0.10000000000000001), pos = (0.44, 0.0, 0.0), hpr = (0, 0, 0), sortOrder = 25, image = self.legendaryGui.find('**/pir_t_gui_fsh_staminaBarForeground'), image_scale = (1.0, 0.0, 0.050000000000000003), image_pos = (0.0, 0.0, 0.0), image_hpr = (0.0, 0.0, 0.0)) self.fishStaminaBarFrame.setTransparency(TransparencyAttrib.MAlpha) self.fishStaminaBarFrame.setDepthTest(True) self.fishStaminaBarFrame.setDepthWrite(True) def cleanFishData(self): self.staminaValue = self.myData['stamina'] self.fishStaminaBar['value'] = self.staminaValue self.fishStaminaValueLabel.setText(str(int(self.staminaValue)) + ' / ' + str(100)) self.fishStaminaBar['barColor'] = FishingGlobals.fishingStaminaBarColor[int((self.staminaValue / 100.0) * (len(FishingGlobals.fishingStaminaBarColor) - 1))] self.hideStaminaBar() taskMgr.remove('updateFishStaminaTask') self.lurePosition = None self.fishChaseLureSequence.pause() self.fishChaseLureSequence.clearToInitial() self.lfStruggleSequence.pause() self.lfStruggleSequence.clearToInitial() if self.aboutToBitingInterval is None: return None self.aboutToBitingInterval.pause() def destroy(self): self.fishUINodePath.removeNode() Fish.destroy(self) def updateFishStaminaTask(self, task = None): if self.staminaValue <= 1: return Task.done self.staminaValue = max(1, self.staminaValue - FishingGlobals.staminaReduceValue) self.fishStaminaValueLabel.setText(str(int(self.staminaValue)) + ' / ' + str(100)) self.fishStaminaBar['value'] = self.staminaValue self.fishStaminaBar['barColor'] = FishingGlobals.fishingStaminaBarColor[int((self.staminaValue / 100.0) * (len(FishingGlobals.fishingStaminaBarColor) - 1))] return Task.cont def updateFishStaminaBar(self): self.fishStaminaBar['value'] = self.staminaValue def fishStaminaConsume(self): taskMgr.add(self.updateFishStaminaTask, 'updateFishStaminaTask') def staminaPercentage(self): return self.staminaValue / self.myData['stamina'] def showStaminaBar(self): self.fishUINodePath.reparentTo(aspect2d) def hideStaminaBar(self): self.fishUINodePath.reparentTo(hidden) def performStraightBehavior(self, lurePos, dt): newX = self.getX() + self.velocity[0] * dt + self.accel[0] * dt * dt newZ = self.getZ() + self.velocity[2] * dt + self.accel[2] * dt * dt return (newX, newZ)
def removeNode(self): self.visual.removeNode() del self.visual self.resultLabel.destroy() NodePath.removeNode(self)
def removeNode(self): self.visual.removeNode() del self.visual self.resultLabel.destroy() NodePath.removeNode(self)
class DistributedParty(DistributedObject.DistributedObject): notify = directNotify.newCategory("DistributedParty") generatedEvent = "distributedPartyGenerated" def __init__(self, cr): DistributedObject.DistributedObject.__init__(self, cr) self.partyDoneEvent = "partyDone" self.load() self.avIdsAtParty = [] base.distributedParty = self self.titleText = "" self.isPartyEnding = False def setPartyState(self, partyState): self.isPartyEnding = partyState messenger.send("partyStateChanged", [partyState]) def getPartyState(self): return self.isPartyEnding def setPartyClockInfo(self, x, y, h): x = PartyUtils.convertDistanceFromPartyGrid(x, 0) y = PartyUtils.convertDistanceFromPartyGrid(y, 1) h = PartyUtils.convertDegreesFromPartyGrid(h) self.partyClockInfo = (x, y, h) self.loadPartyCountdownTimer() def setInviteeIds(self, inviteeIds): self.inviteeIds = inviteeIds def setPartyInfoTuple(self, partyInfoTuple): self.partyInfo = PartyInfo(*partyInfoTuple) self.loadDecorations() allActIds = [x.activityId for x in self.partyInfo.activityList] base.partyHasJukebox = ( PartyGlobals.ActivityIds.PartyJukebox in allActIds or PartyGlobals.ActivityIds.PartyJukebox40 in allActIds ) self.grid = [ [ False, False, False, False, False, True, True, True, True, True, True, True, True, True, True, False, False, False, ], [ False, False, False, False, True, True, True, True, True, True, True, True, True, True, True, False, False, False, ], [ False, False, False, True, True, True, True, True, True, True, True, True, True, True, True, True, False, False, ], [ False, False, False, True, True, True, True, True, True, True, True, True, True, True, True, True, False, False, ], [ False, False, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, False, ], [ False, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, ], [ True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, ], [ True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, ], [ True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, ], [ True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, ], [ False, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, ], [ False, True, True, True, True, True, True, True, True, True, True, True, True, True, False, False, False, False, ], [ False, False, False, False, True, True, True, True, True, True, True, True, True, False, False, False, False, False, ], [ False, False, False, False, False, True, True, True, True, True, True, True, False, False, False, False, False, False, ], [ False, False, False, False, False, False, True, True, True, True, True, False, False, False, False, False, False, False, ], ] def fillGrid(x, y, size): for i in xrange(-size[1] / 2 + 1, size[1] / 2 + 1): for j in xrange(-size[0] / 2 + 1, size[0] / 2 + 1): self.grid[i + y][j + x] = False for activityBase in self.partyInfo.activityList: fillGrid( activityBase.x, activityBase.y, PartyGlobals.ActivityInformationDict[activityBase.activityId]["gridsize"], ) for decorBase in self.partyInfo.decors: fillGrid(decorBase.x, decorBase.y, PartyGlobals.DecorationInformationDict[decorBase.decorId]["gridsize"]) self.loadGrass() def setPartyStartedTime(self, startedTime): stime = time.strptime(startedTime, "%Y-%m-%d %H:%M:%S") self.partyStartedTime = datetime.datetime( year=stime.tm_year, month=stime.tm_mon, day=stime.tm_mday, hour=stime.tm_hour, minute=stime.tm_min, second=stime.tm_sec, tzinfo=base.cr.toontownTimeManager.getCurServerDateTime().tzinfo, ) def disable(self): self.notify.debug("disable") DistributedObject.DistributedObject.disable(self) base.localAvatar.chatMgr.chatInputSpeedChat.removeInsidePartiesMenu() def delete(self): self.notify.debug("delete") self.unload() if hasattr(base, "distributedParty"): del base.distributedParty DistributedObject.DistributedObject.delete(self) def load(self): Toon.loadMinigameAnims() self.defaultSignModel = loader.loadModel("phase_13/models/parties/eventSign") self.activityIconsModel = loader.loadModel("phase_4/models/parties/eventSignIcons") model = loader.loadModel("phase_4/models/parties/partyStickerbook") self.partyHat = model.find("**/Stickerbook_PartyIcon") self.partyHat.setPos(0.0, 0.1, 2.5) self.partyHat.setHpr(0.0, 0.0, -50.0) self.partyHat.setScale(4.0) self.partyHat.setBillboardAxis() self.partyHat.reparentTo(hidden) model.removeNode() self.defaultLeverModel = loader.loadModel("phase_13/models/parties/partyLeverBase") self.defaultStickModel = loader.loadModel("phase_13/models/parties/partyLeverStick") def loadGrass(self): self.grassRoot = NodePath("GrassRoot") self.grassRoot.reparentTo(base.cr.playGame.hood.loader.geom) grass = loader.loadModel("phase_13/models/parties/grass") clearPositions = self.getClearSquarePositions() numTufts = min(len(clearPositions) * 3, PartyGlobals.TuftsOfGrass) for i in xrange(numTufts): g = grass.copyTo(self.grassRoot) pos = random.choice(clearPositions) g.setPos(pos[0] + random.randint(-8, 8), pos[1] + random.randint(-8, 8), 0.0) def loadDecorations(self): self.decorationsList = [] for decorBase in self.partyInfo.decors: self.decorationsList.append( Decoration( PartyGlobals.DecorationIds.getString(decorBase.decorId), PartyUtils.convertDistanceFromPartyGrid(decorBase.x, 0), PartyUtils.convertDistanceFromPartyGrid(decorBase.y, 1), PartyUtils.convertDegreesFromPartyGrid(decorBase.h), ) ) def unload(self): if hasattr(self, "decorationsList") and self.decorationsList: for decor in self.decorationsList: decor.unload() del self.decorationsList self.stopPartyClock() self.grassRoot.removeNode() del self.grassRoot if hasattr(self, "testGrid"): self.testGrid.removeNode() del self.testGrid self.ignoreAll() Toon.unloadMinigameAnims() self.partyHat.removeNode() del self.partyHat if hasattr(base, "partyHasJukebox"): del base.partyHasJukebox def announceGenerate(self): # TODO - for some reason this is getting called hundreds of times when there are multiple districts DistributedObject.DistributedObject.announceGenerate(self) self.sendUpdate("enteredParty", []) globalClock.syncFrameTime() self.startPartyClock() base.localAvatar.chatMgr.chatInputSpeedChat.addInsidePartiesMenu() self.spawnTitleText() messenger.send(self.generatedEvent) if config.GetBool("show-debug-party-grid", 0): self.testGrid = NodePath("test_grid") self.testGrid.reparentTo(base.cr.playGame.hood.loader.geom) for i in xrange(len(self.grid)): for j in xrange(len(self.grid[i])): cm = CardMaker("gridsquare") np = NodePath(cm.generate()) np.setScale(12) np.setP(-90.0) np.setPos( PartyUtils.convertDistanceFromPartyGrid(j, 0) - 6.0, PartyUtils.convertDistanceFromPartyGrid(i, 1) - 6.0, 0.1, ) np.reparentTo(self.testGrid) if self.grid[i][j]: np.setColorScale(0.0, 1.0, 0.0, 1.0) else: np.setColorScale(1.0, 0.0, 0.0, 1.0) def getClearSquarePos(self): clearPositions = self.getClearSquarePositions() if len(clearPositions) == 0: raise StandardError, "Party %s has no empty grid squares." % self.doId return random.choice(clearPositions) def getClearSquarePositions(self): clearPositions = [] for y in xrange(len(self.grid)): for x in xrange(len(self.grid[0])): if self.grid[y][x]: pos = ( PartyUtils.convertDistanceFromPartyGrid(x, 0), PartyUtils.convertDistanceFromPartyGrid(y, 1), 0.1, ) clearPositions.append(pos) return clearPositions def startPartyClock(self): self.partyClockModel.reparentTo(base.cr.playGame.hood.loader.geom) curServerTime = base.cr.toontownTimeManager.getCurServerDateTime() timePartyWillEnd = self.partyStartedTime + datetime.timedelta(hours=PartyGlobals.DefaultPartyDuration) timeLeftInParty = timePartyWillEnd - curServerTime if curServerTime < timePartyWillEnd: self.secondsLeftInParty = timeLeftInParty.seconds else: self.secondsLeftInParty = 0 taskMgr.doMethodLater(0.5, self.partyClockTask, "UpdatePartyClock") self.partyClockSignFront = self.partyClockModel.find("**/signFrontText_locator") self.partyClockSignBack = self.partyClockModel.find("**/signBackText_locator") self.attachHostNameToSign(self.partyClockSignFront) self.attachHostNameToSign(self.partyClockSignBack) def attachHostNameToSign(self, locator): if self.hostName == "": return nameText = TextNode("nameText") nameText.setCardAsMargin(0.1, 0.1, 0.1, 0.1) nameText.setCardDecal(True) nameText.setCardColor(1.0, 1.0, 1.0, 0.0) r = 232.0 / 255.0 g = 169.0 / 255.0 b = 23.0 / 255.0 nameText.setTextColor(r, g, b, 1) nameText.setAlign(nameText.ACenter) nameText.setFont(ToontownGlobals.getBuildingNametagFont()) nameText.setShadowColor(0, 0, 0, 1) nameText.setBin("fixed") if TTLocalizer.BuildingNametagShadow: nameText.setShadow(*TTLocalizer.BuildingNametagShadow) nameWordWrap = 11.0 nameText.setWordwrap(nameWordWrap) scaleMult = 0.48 houseName = self.hostName nameText.setText(houseName) textWidth = nameText.getWidth() xScale = 1.0 * scaleMult if textWidth > nameWordWrap: xScale = nameWordWrap / textWidth * scaleMult sign_origin = locator namePlate = sign_origin.attachNewNode(nameText) namePlate.setDepthWrite(0) namePlate.setPos(0, 0, 0) namePlate.setScale(xScale) def stopPartyClock(self): self.partyClockModel.removeNode() taskMgr.remove("UpdatePartyClock") def partyClockTask(self, task): self.secondsLeftInParty -= 0.5 if self.secondsLeftInParty < 0: self.frontTimer["minute"]["text"] = "--" self.backTimer["minute"]["text"] = "--" self.frontTimer["second"]["text"] = "--" self.backTimer["second"]["text"] = "--" return if self.frontTimer["colon"].isStashed(): self.frontTimer["colon"].unstash() self.backTimer["colon"].unstash() else: self.frontTimer["colon"].stash() self.backTimer["colon"].stash() minutesLeft = int(int(self.secondsLeftInParty / 60) % 60) if minutesLeft < 10: minutesLeft = "0%d" % minutesLeft else: minutesLeft = "%d" % minutesLeft secondsLeft = int(self.secondsLeftInParty % 60) if secondsLeft < 10: secondsLeft = "0%d" % secondsLeft else: secondsLeft = "%d" % secondsLeft self.frontTimer["minute"]["text"] = minutesLeft self.backTimer["minute"]["text"] = minutesLeft self.frontTimer["second"]["text"] = secondsLeft self.backTimer["second"]["text"] = secondsLeft taskMgr.doMethodLater(0.5, self.partyClockTask, "UpdatePartyClock") if self.secondsLeftInParty != int(self.secondsLeftInParty): self.partyClockModel.find("**/middleRotateFront_grp").setR(-6.0 * (self.secondsLeftInParty % 60)) self.partyClockModel.find("**/middleRotateBack_grp").setR(6.0 * (self.secondsLeftInParty % 60)) def getAvIdsAtParty(self): return self.avIdsAtParty def setAvIdsAtParty(self, avIdsAtParty): self.avIdsAtParty = avIdsAtParty def loadPartyCountdownTimer(self): self.partyClockModel = loader.loadModel("phase_13/models/parties/partyClock") self.partyClockModel.setPos(self.partyClockInfo[0], self.partyClockInfo[1], 0.0) self.partyClockModel.setH(self.partyClockInfo[2]) self.partyClockModel.reparentTo(base.cr.playGame.hood.loader.geom) self.partyClockModel.find("**/frontText_locator").setY(-1.1) self.partyClockModel.find("**/backText_locator").setY(0.633) self.frontTimer = self.getTimer(self.partyClockModel.find("**/frontText_locator")) base.frontTimerLoc = self.partyClockModel.find("**/frontText_locator") base.backTimerLoc = self.partyClockModel.find("**/backText_locator") self.backTimer = self.getTimer(self.partyClockModel.find("**/backText_locator")) self.partyClockModel.stash() def getTimer(self, parent): timeFont = ToontownGlobals.getMinnieFont() timer = {} timer["minute"] = DirectLabel( parent=parent, pos=TTLocalizer.DPtimerMinutePos, relief=None, text="59", text_align=TextNode.ACenter, text_font=timeFont, text_fg=(0.7, 0.3, 0.3, 1.0), scale=TTLocalizer.DPtimerMinute, ) timer["colon"] = DirectLabel( parent=parent, pos=TTLocalizer.DPtimerColonPos, relief=None, text=":", text_align=TextNode.ACenter, text_font=timeFont, text_fg=(0.7, 0.3, 0.3, 1.0), scale=TTLocalizer.DPtimerColon, ) timer["second"] = DirectLabel( parent=parent, relief=None, pos=TTLocalizer.DPtimerSecondPos, text="14", text_align=TextNode.ACenter, text_font=timeFont, text_fg=(0.7, 0.3, 0.3, 1.0), scale=TTLocalizer.DPtimerSecond, ) timer["textLabel"] = DirectLabel( parent=parent, relief=None, pos=(0.0, 0.0, 1.15), text=TTLocalizer.PartyCountdownClockText, text_font=timeFont, text_fg=(0.7, 0.3, 0.3, 1.0), scale=TTLocalizer.DPtimerTextLabel, ) return timer def setHostName(self, hostName): self.hostName = hostName if hasattr(self, "partyClockSignFront"): self.attachHostNameToSign(self.partyClockSignFront) if hasattr(self, "partyClockSignBack"): self.attachHostNameToSign(self.partyClockSignBack) def spawnTitleText(self): if not self.hostName: return partyText = TTLocalizer.PartyTitleText % TTLocalizer.GetPossesive(self.hostName) self.doSpawnTitleText(partyText) def doSpawnTitleText(self, text): return self.titleColor = (1.0, 0.5, 0.4, 1.0) self.titleText = OnscreenText.OnscreenText( text, fg=self.titleColor, font=ToontownGlobals.getSignFont(), pos=(0, -0.5), scale=0.16, drawOrder=0, mayChange=1, wordwrap=16, ) self.titleText.setText(text) self.titleText.show() self.titleText.setColor(Vec4(*self.titleColor)) self.titleText.clearColorScale() self.titleText.setFg(self.titleColor) seq = Sequence( Wait(0.1), Wait(6.0), self.titleText.colorScaleInterval(0.5, Vec4(1.0, 1.0, 1.0, 0.0)), Task(self.hideTitleText), ) seq.start() def hideTitleText(self): if self.titleText: self.titleText.hide()
class PartyCog(FSM): notify = directNotify.newCategory('PartyCog') HpTextGenerator = TextNode('HpTextGenerator') hpText = None height = 7 def __init__(self, parentNode, id, bounceSpeed = 3, bounceHeight = 1, rotateSpeed = 1, heightShift = 1, xMoveSpeed = 0, xMoveDistance = 0, bounceOffset = 0): self.id = id FSM.__init__(self, 'PartyCogFSM-%d' % self.id) self.showFacingStatus = False self.xMoveSpeed = xMoveSpeed self.xMoveDistance = xMoveDistance self.heightShift = heightShift self.bounceSpeed = bounceSpeed self.bounceHeight = bounceHeight self.rotateSpeed = rotateSpeed self.parentNode = parentNode self.bounceOffset = bounceOffset self.hitInterval = None self.kaboomTrack = None self.resetRollIval = None self.netTimeSentToStartByHit = 0 self.load() self.request('Down') return def load(self): self.root = NodePath('PartyCog-%d' % self.id) self.root.reparentTo(self.parentNode) path = 'phase_13/models/parties/cogPinata_' self.actor = Actor(path + 'actor', {'idle': path + 'idle_anim', 'down': path + 'down_anim', 'up': path + 'up_anim', 'bodyHitBack': path + 'bodyHitBack_anim', 'bodyHitFront': path + 'bodyHitFront_anim', 'headHitBack': path + 'headHitBack_anim', 'headHitFront': path + 'headHitFront_anim'}) self.actor.reparentTo(self.root) self.temp_transform = Mat4() self.head_locator = self.actor.attachNewNode('temphead') self.bodyColl = CollisionTube(0, 0, 1, 0, 0, 5.75, 0.75) self.bodyColl.setTangible(1) self.bodyCollNode = CollisionNode('PartyCog-%d-Body-Collision' % self.id) self.bodyCollNode.setCollideMask(ToontownGlobals.PieBitmask) self.bodyCollNode.addSolid(self.bodyColl) self.bodyCollNodePath = self.root.attachNewNode(self.bodyCollNode) self.headColl = CollisionTube(0, 0, 3, 0, 0, 3.0, 1.5) self.headColl.setTangible(1) self.headCollNode = CollisionNode('PartyCog-%d-Head-Collision' % self.id) self.headCollNode.setCollideMask(ToontownGlobals.PieBitmask) self.headCollNode.addSolid(self.headColl) self.headCollNodePath = self.root.attachNewNode(self.headCollNode) self.arm1Coll = CollisionSphere(1.65, 0, 3.95, 1.0) self.arm1Coll.setTangible(1) self.arm1CollNode = CollisionNode('PartyCog-%d-Arm1-Collision' % self.id) self.arm1CollNode.setCollideMask(ToontownGlobals.PieBitmask) self.arm1CollNode.addSolid(self.arm1Coll) self.arm1CollNodePath = self.root.attachNewNode(self.arm1CollNode) self.arm2Coll = CollisionSphere(-1.65, 0, 3.45, 1.0) self.arm2Coll.setTangible(1) self.arm2CollNode = CollisionNode('PartyCog-%d-Arm2-Collision' % self.id) self.arm2CollNode.setCollideMask(ToontownGlobals.PieBitmask) self.arm2CollNode.addSolid(self.arm2Coll) self.arm2CollNodePath = self.root.attachNewNode(self.arm2CollNode) splatName = 'splat-creampie' self.splat = globalPropPool.getProp(splatName) self.splat.setBillboardPointEye() self.splatType = globalPropPool.getPropType(splatName) self.pieHitSound = globalBattleSoundCache.getSound('AA_wholepie_only.ogg') self.upSound = globalBattleSoundCache.getSound('AV_jump_to_side.ogg') self.hole = loader.loadModel('phase_13/models/parties/cogPinataHole') self.hole.setTransparency(True) self.hole.setP(-90.0) self.hole.setScale(3) self.hole.setBin('ground', 3) self.hole.reparentTo(self.parentNode) def unload(self): self.request('Off') self.clearHitInterval() if self.hole is not None: self.hole.removeNode() self.hole = None if self.actor is not None: self.actor.cleanup() self.actor.removeNode() self.actor = None if self.root is not None: self.root.removeNode() self.root = None if self.kaboomTrack is not None and self.kaboomTrack.isPlaying(): self.kaboomTrack.finish() self.kaboomTrack = None if self.resetRollIval is not None and self.resetRollIval.isPlaying(): self.resetRollIval.finish() self.resetRollIval = None if self.hitInterval is not None and self.hitInterval.isPlaying(): self.hitInterval.finish() self.hitInterval = None del self.upSound del self.pieHitSound return def enterStatic(self): pass def exitStatic(self): pass def enterActive(self, startTime): self.root.setR(0.0) updateTask = Task.Task(self.updateTask) updateTask.startTime = startTime taskMgr.add(updateTask, 'PartyCog.update-%d' % self.id) def exitActive(self): taskMgr.remove('PartyCog.update-%d' % self.id) taskMgr.remove('PartyCog.bounceTask-%d' % self.id) self.clearHitInterval() self.resetRollIval = self.root.hprInterval(0.5, Point3(self.root.getH(), 0.0, 0.0), blendType='easeInOut') self.resetRollIval.start() self.actor.stop() def enterDown(self): if self.oldState == 'Off': downAnimControl = self.actor.getAnimControl('down') self.actor.pose('down', downAnimControl.getNumFrames() - 1) return self.clearHitInterval() startScale = self.hole.getScale() endScale = Point3(5, 5, 5) self.hitInterval = Sequence(LerpFunc(self.setAlongSpline, duration=1.0, fromData=self.currentT, toData=0.0), LerpScaleInterval(self.hole, duration=0.175, scale=endScale, startScale=startScale, blendType='easeIn'), Parallel(SoundInterval(self.upSound, volume=0.6, node=self.actor, cutOff=PartyGlobals.PARTY_COG_CUTOFF), ActorInterval(self.actor, 'down', loop=0)), LerpScaleInterval(self.hole, duration=0.175, scale=Point3(3, 3, 3), startScale=endScale, blendType='easeOut')) self.hitInterval.start() def exitDown(self): self.root.setR(0.0) self.root.setH(0.0) self.targetDistance = 0.0 self.targetFacing = 0.0 self.currentT = 0.0 self.setAlongSpline(0.0) self.clearHitInterval() startScale = self.hole.getScale() endScale = Point3(5, 5, 5) self.hitInterval = Sequence(LerpScaleInterval(self.hole, duration=0.175, scale=endScale, startScale=startScale, blendType='easeIn'), Parallel(SoundInterval(self.upSound, volume=0.6, node=self.actor, cutOff=PartyGlobals.PARTY_COG_CUTOFF), ActorInterval(self.actor, 'up', loop=0)), Func(self.actor.loop, 'idle'), LerpScaleInterval(self.hole, duration=0.175, scale=Point3(3, 3, 3), startScale=endScale, blendType='easeOut')) self.hitInterval.start() def filterDown(self, request, args): if request == 'Down': return None else: return self.defaultFilter(request, args) return None def setEndPoints(self, start, end, amplitude = 1.7): self.sinAmplitude = amplitude self.sinPeriod = (end.getX() - start.getX()) / 2 self.sinDisplacement = start.getY() self.startPoint = start self.endPoint = end self.currentT = 0.0 self.targetDistance = 0.0 self.currentFacing = 0.0 self.targetFacing = 0.0 self.setAlongSpline(self.currentT) self.hole.setPos(self.root.getPos()) self.hole.setZ(0.02) def rockBackAndForth(self, task): t = task.startTime + task.time angle = math.sin(t) * 20.0 self.root.setR(angle) return task.cont def updateDistance(self, distance): self.targetDistance = clamp(distance, -1.0, 1.0) def updateTask(self, task): self.rockBackAndForth(task) if self.targetDistance > self.currentT: self.currentT += min(0.01, self.targetDistance - self.currentT) self.setAlongSpline(self.currentT) elif self.targetDistance < self.currentT: self.currentT += max(-0.01, self.targetDistance - self.currentT) self.setAlongSpline(self.currentT) if self.currentT < 0.0: self.targetFacing = -90.0 elif self.currentT > 0.0: self.targetFacing = 90.0 else: self.targetFacing = 0.0 if self.targetFacing > self.currentFacing: self.currentFacing += min(10, self.targetFacing - self.currentFacing) elif self.targetFacing < self.currentFacing: self.currentFacing += max(-10, self.targetFacing - self.currentFacing) self.root.setH(self.currentFacing) return task.cont def setAlongSpline(self, t): t = t + 1.0 dist = (self.endPoint.getX() - self.startPoint.getX()) / 2.0 x = self.startPoint.getX() + t * dist y = self.startPoint.getY() - math.sin(t * 2 * math.pi) * self.sinAmplitude self.root.setPos(x, y, 0) def startBounce(self): taskMgr.add(self.bounce, 'PartyCog.bounceTask-%d' % self.id) def bounce(self, task): self.root.setZ(math.sin((self.bounceOffset + task.time) * self.bounceSpeed) * self.bounceHeight + self.heightShift) return task.cont def setPos(self, position): self.root.setPos(position) def respondToPieHit(self, timestamp, position, hot = False, direction = 1.0): if self.netTimeSentToStartByHit < timestamp: self.__showSplat(position, direction, hot) if self.netTimeSentToStartByHit < timestamp: self.netTimeSentToStartByHit = timestamp else: self.notify.debug('respondToPieHit self.netTimeSentToStartByHit = %s' % self.netTimeSentToStartByHit) def clearHitInterval(self): if self.hitInterval is not None and self.hitInterval.isPlaying(): self.hitInterval.clearToInitial() return def __showSplat(self, position, direction, hot = False): if self.kaboomTrack is not None and self.kaboomTrack.isPlaying(): self.kaboomTrack.finish() self.clearHitInterval() splatName = 'splat-creampie' self.splat = globalPropPool.getProp(splatName) self.splat.setBillboardPointEye() self.splat.reparentTo(render) self.splat.setPos(self.root, position) self.splat.setAlphaScale(1.0) if not direction == 1.0: self.splat.setColorScale(PartyGlobals.CogActivitySplatColors[0]) if self.currentFacing > 0.0: facing = 'HitFront' else: facing = 'HitBack' else: self.splat.setColorScale(PartyGlobals.CogActivitySplatColors[1]) if self.currentFacing > 0.0: facing = 'HitBack' else: facing = 'HitFront' if hot: targetscale = 0.75 part = 'head' else: targetscale = 0.5 part = 'body' def setSplatAlpha(amount): self.splat.setAlphaScale(amount) self.hitInterval = Sequence(ActorInterval(self.actor, part + facing, loop=0), Func(self.actor.loop, 'idle')) self.hitInterval.start() self.kaboomTrack = Parallel(SoundInterval(self.pieHitSound, volume=1.0, node=self.actor, cutOff=PartyGlobals.PARTY_COG_CUTOFF), Sequence(Func(self.splat.showThrough), Parallel(Sequence(LerpScaleInterval(self.splat, duration=0.175, scale=targetscale, startScale=Point3(0.1, 0.1, 0.1), blendType='easeOut'), Wait(0.175)), Sequence(Wait(0.1), LerpFunc(setSplatAlpha, duration=1.0, fromData=1.0, toData=0.0, blendType='easeOut'))), Func(self.splat.cleanup), Func(self.splat.removeNode))) self.kaboomTrack.start() return def showHitScore(self, number, scale = 1): if number <= 0: return if self.hpText: self.hideHitScore() self.HpTextGenerator.setFont(ToontownGlobals.getSignFont()) if number < 0: self.HpTextGenerator.setText(str(number)) else: self.HpTextGenerator.setText('+' + str(number)) self.HpTextGenerator.clearShadow() self.HpTextGenerator.setAlign(TextNode.ACenter) r = 1 g = 1 b = 0 a = 1 self.HpTextGenerator.setTextColor(r, g, b, a) self.hpTextNode = self.HpTextGenerator.generate() self.hpText = render.attachNewNode(self.hpTextNode) self.hpText.setScale(scale) self.hpText.setBillboardPointEye() self.hpText.setBin('fixed', 100) self.hpText.setPos(self.root, 0, 0, self.height / 2) seq = Sequence(self.hpText.posInterval(0.25, Point3(self.root.getX(render), self.root.getY(render), self.root.getZ(render) + self.height + 1.0), blendType='easeOut'), Wait(0.25), self.hpText.colorInterval(0.1, Vec4(r, g, b, 0)), Func(self.__hideHitScore)) seq.start() def hideHitScore(self): if self.hpText: taskMgr.remove('PartyCogHpText' + str(self.id)) self.hpText.removeNode() self.hpText = None return def getHeadLocation(self): self.actor.getJoints(jointName='head')[0].getNetTransform(self.temp_transform) self.head_locator.setMat(self.temp_transform) return self.head_locator.getZ(self.root)
class PartyCog(FSM): notify = directNotify.newCategory('PartyCog') HpTextGenerator = TextNode('HpTextGenerator') hpText = None height = 7 def __init__(self, parentNode, id, bounceSpeed=3, bounceHeight=1, rotateSpeed=1, heightShift=1, xMoveSpeed=0, xMoveDistance=0, bounceOffset=0): self.id = id FSM.__init__(self, 'PartyCogFSM-%d' % self.id) self.showFacingStatus = False self.xMoveSpeed = xMoveSpeed self.xMoveDistance = xMoveDistance self.heightShift = heightShift self.bounceSpeed = bounceSpeed self.bounceHeight = bounceHeight self.rotateSpeed = rotateSpeed self.parentNode = parentNode self.bounceOffset = bounceOffset self.hitInterval = None self.kaboomTrack = None self.resetRollIval = None self.netTimeSentToStartByHit = 0 self.load() self.request('Down') return def load(self): self.root = NodePath('PartyCog-%d' % self.id) self.root.reparentTo(self.parentNode) path = 'phase_13/models/parties/cogPinata_' self.actor = Actor( path + 'actor', { 'idle': path + 'idle_anim', 'down': path + 'down_anim', 'up': path + 'up_anim', 'bodyHitBack': path + 'bodyHitBack_anim', 'bodyHitFront': path + 'bodyHitFront_anim', 'headHitBack': path + 'headHitBack_anim', 'headHitFront': path + 'headHitFront_anim' }) self.actor.reparentTo(self.root) self.temp_transform = Mat4() self.head_locator = self.actor.attachNewNode('temphead') self.bodyColl = CollisionTube(0, 0, 1, 0, 0, 5.75, 0.75) self.bodyColl.setTangible(1) self.bodyCollNode = CollisionNode('PartyCog-%d-Body-Collision' % self.id) self.bodyCollNode.setCollideMask(ToontownGlobals.PieBitmask) self.bodyCollNode.addSolid(self.bodyColl) self.bodyCollNodePath = self.root.attachNewNode(self.bodyCollNode) self.headColl = CollisionTube(0, 0, 3, 0, 0, 3.0, 1.5) self.headColl.setTangible(1) self.headCollNode = CollisionNode('PartyCog-%d-Head-Collision' % self.id) self.headCollNode.setCollideMask(ToontownGlobals.PieBitmask) self.headCollNode.addSolid(self.headColl) self.headCollNodePath = self.root.attachNewNode(self.headCollNode) self.arm1Coll = CollisionSphere(1.65, 0, 3.95, 1.0) self.arm1Coll.setTangible(1) self.arm1CollNode = CollisionNode('PartyCog-%d-Arm1-Collision' % self.id) self.arm1CollNode.setCollideMask(ToontownGlobals.PieBitmask) self.arm1CollNode.addSolid(self.arm1Coll) self.arm1CollNodePath = self.root.attachNewNode(self.arm1CollNode) self.arm2Coll = CollisionSphere(-1.65, 0, 3.45, 1.0) self.arm2Coll.setTangible(1) self.arm2CollNode = CollisionNode('PartyCog-%d-Arm2-Collision' % self.id) self.arm2CollNode.setCollideMask(ToontownGlobals.PieBitmask) self.arm2CollNode.addSolid(self.arm2Coll) self.arm2CollNodePath = self.root.attachNewNode(self.arm2CollNode) splatName = 'splat-creampie' self.splat = globalPropPool.getProp(splatName) self.splat.setBillboardPointEye() self.splatType = globalPropPool.getPropType(splatName) self.pieHitSound = globalBattleSoundCache.getSound( 'AA_wholepie_only.ogg') self.upSound = globalBattleSoundCache.getSound('AV_jump_to_side.ogg') self.hole = loader.loadModel('phase_13/models/parties/cogPinataHole') self.hole.setTransparency(True) self.hole.setP(-90.0) self.hole.setScale(3) self.hole.setBin('ground', 3) self.hole.reparentTo(self.parentNode) def unload(self): self.request('Off') self.clearHitInterval() if self.hole is not None: self.hole.removeNode() self.hole = None if self.actor is not None: self.actor.cleanup() self.actor.removeNode() self.actor = None if self.root is not None: self.root.removeNode() self.root = None if self.kaboomTrack is not None and self.kaboomTrack.isPlaying(): self.kaboomTrack.finish() self.kaboomTrack = None if self.resetRollIval is not None and self.resetRollIval.isPlaying(): self.resetRollIval.finish() self.resetRollIval = None if self.hitInterval is not None and self.hitInterval.isPlaying(): self.hitInterval.finish() self.hitInterval = None del self.upSound del self.pieHitSound return def enterStatic(self): pass def exitStatic(self): pass def enterActive(self, startTime): self.root.setR(0.0) updateTask = Task.Task(self.updateTask) updateTask.startTime = startTime taskMgr.add(updateTask, 'PartyCog.update-%d' % self.id) def exitActive(self): taskMgr.remove('PartyCog.update-%d' % self.id) taskMgr.remove('PartyCog.bounceTask-%d' % self.id) self.clearHitInterval() self.resetRollIval = self.root.hprInterval(0.5, Point3( self.root.getH(), 0.0, 0.0), blendType='easeInOut') self.resetRollIval.start() self.actor.stop() def enterDown(self): if self.oldState == 'Off': downAnimControl = self.actor.getAnimControl('down') self.actor.pose('down', downAnimControl.getNumFrames() - 1) return self.clearHitInterval() startScale = self.hole.getScale() endScale = Point3(5, 5, 5) self.hitInterval = Sequence( LerpFunc(self.setAlongSpline, duration=1.0, fromData=self.currentT, toData=0.0), LerpScaleInterval(self.hole, duration=0.175, scale=endScale, startScale=startScale, blendType='easeIn'), Parallel( SoundInterval(self.upSound, volume=0.6, node=self.actor, cutOff=PartyGlobals.PARTY_COG_CUTOFF), ActorInterval(self.actor, 'down', loop=0)), LerpScaleInterval(self.hole, duration=0.175, scale=Point3(3, 3, 3), startScale=endScale, blendType='easeOut')) self.hitInterval.start() def exitDown(self): self.root.setR(0.0) self.root.setH(0.0) self.targetDistance = 0.0 self.targetFacing = 0.0 self.currentT = 0.0 self.setAlongSpline(0.0) self.clearHitInterval() startScale = self.hole.getScale() endScale = Point3(5, 5, 5) self.hitInterval = Sequence( LerpScaleInterval(self.hole, duration=0.175, scale=endScale, startScale=startScale, blendType='easeIn'), Parallel( SoundInterval(self.upSound, volume=0.6, node=self.actor, cutOff=PartyGlobals.PARTY_COG_CUTOFF), ActorInterval(self.actor, 'up', loop=0)), Func(self.actor.loop, 'idle'), LerpScaleInterval(self.hole, duration=0.175, scale=Point3(3, 3, 3), startScale=endScale, blendType='easeOut')) self.hitInterval.start() def filterDown(self, request, args): if request == 'Down': return None else: return self.defaultFilter(request, args) return None def setEndPoints(self, start, end, amplitude=1.7): self.sinAmplitude = amplitude self.sinPeriod = (end.getX() - start.getX()) / 2 self.sinDisplacement = start.getY() self.startPoint = start self.endPoint = end self.currentT = 0.0 self.targetDistance = 0.0 self.currentFacing = 0.0 self.targetFacing = 0.0 self.setAlongSpline(self.currentT) self.hole.setPos(self.root.getPos()) self.hole.setZ(0.02) def rockBackAndForth(self, task): t = task.startTime + task.time angle = math.sin(t) * 20.0 self.root.setR(angle) return task.cont def updateDistance(self, distance): self.targetDistance = clamp(distance, -1.0, 1.0) def updateTask(self, task): self.rockBackAndForth(task) if self.targetDistance > self.currentT: self.currentT += min(0.01, self.targetDistance - self.currentT) self.setAlongSpline(self.currentT) elif self.targetDistance < self.currentT: self.currentT += max(-0.01, self.targetDistance - self.currentT) self.setAlongSpline(self.currentT) if self.currentT < 0.0: self.targetFacing = -90.0 elif self.currentT > 0.0: self.targetFacing = 90.0 else: self.targetFacing = 0.0 if self.targetFacing > self.currentFacing: self.currentFacing += min(10, self.targetFacing - self.currentFacing) elif self.targetFacing < self.currentFacing: self.currentFacing += max(-10, self.targetFacing - self.currentFacing) self.root.setH(self.currentFacing) return task.cont def setAlongSpline(self, t): t = t + 1.0 dist = (self.endPoint.getX() - self.startPoint.getX()) / 2.0 x = self.startPoint.getX() + t * dist y = self.startPoint.getY() - math.sin( t * 2 * math.pi) * self.sinAmplitude self.root.setPos(x, y, 0) def startBounce(self): taskMgr.add(self.bounce, 'PartyCog.bounceTask-%d' % self.id) def bounce(self, task): self.root.setZ( math.sin((self.bounceOffset + task.time) * self.bounceSpeed) * self.bounceHeight + self.heightShift) return task.cont def setPos(self, position): self.root.setPos(position) def respondToPieHit(self, timestamp, position, hot=False, direction=1.0): if self.netTimeSentToStartByHit < timestamp: self.__showSplat(position, direction, hot) if self.netTimeSentToStartByHit < timestamp: self.netTimeSentToStartByHit = timestamp else: self.notify.debug( 'respondToPieHit self.netTimeSentToStartByHit = %s' % self.netTimeSentToStartByHit) def clearHitInterval(self): if self.hitInterval is not None and self.hitInterval.isPlaying(): self.hitInterval.clearToInitial() return def __showSplat(self, position, direction, hot=False): if self.kaboomTrack is not None and self.kaboomTrack.isPlaying(): self.kaboomTrack.finish() self.clearHitInterval() splatName = 'splat-creampie' self.splat = globalPropPool.getProp(splatName) self.splat.setBillboardPointEye() self.splat.reparentTo(render) self.splat.setPos(self.root, position) self.splat.setAlphaScale(1.0) if not direction == 1.0: self.splat.setColorScale(PartyGlobals.CogActivitySplatColors[0]) if self.currentFacing > 0.0: facing = 'HitFront' else: facing = 'HitBack' else: self.splat.setColorScale(PartyGlobals.CogActivitySplatColors[1]) if self.currentFacing > 0.0: facing = 'HitBack' else: facing = 'HitFront' if hot: targetscale = 0.75 part = 'head' else: targetscale = 0.5 part = 'body' def setSplatAlpha(amount): self.splat.setAlphaScale(amount) self.hitInterval = Sequence( ActorInterval(self.actor, part + facing, loop=0), Func(self.actor.loop, 'idle')) self.hitInterval.start() self.kaboomTrack = Parallel( SoundInterval(self.pieHitSound, volume=1.0, node=self.actor, cutOff=PartyGlobals.PARTY_COG_CUTOFF), Sequence( Func(self.splat.showThrough), Parallel( Sequence( LerpScaleInterval(self.splat, duration=0.175, scale=targetscale, startScale=Point3(0.1, 0.1, 0.1), blendType='easeOut'), Wait(0.175)), Sequence( Wait(0.1), LerpFunc(setSplatAlpha, duration=1.0, fromData=1.0, toData=0.0, blendType='easeOut'))), Func(self.splat.cleanup), Func(self.splat.removeNode))) self.kaboomTrack.start() return def showHitScore(self, number, scale=1): if number <= 0: return if self.hpText: self.hideHitScore() self.HpTextGenerator.setFont(ToontownGlobals.getSignFont()) if number < 0: self.HpTextGenerator.setText(str(number)) else: self.HpTextGenerator.setText('+' + str(number)) self.HpTextGenerator.clearShadow() self.HpTextGenerator.setAlign(TextNode.ACenter) r = 1 g = 1 b = 0 a = 1 self.HpTextGenerator.setTextColor(r, g, b, a) self.hpTextNode = self.HpTextGenerator.generate() self.hpText = render.attachNewNode(self.hpTextNode) self.hpText.setScale(scale) self.hpText.setBillboardPointEye() self.hpText.setBin('fixed', 100) self.hpText.setPos(self.root, 0, 0, self.height / 2) seq = Task.sequence( self.hpText.lerpPos(Point3( self.root.getX(render), self.root.getY(render), self.root.getZ(render) + self.height + 1.0), 0.25, blendType='easeOut'), Task.pause(0.25), self.hpText.lerpColor(Vec4(r, g, b, a), Vec4(r, g, b, 0), 0.1), Task.Task(self.__hideHitScoreTask)) taskMgr.add(seq, 'PartyCogHpText' + str(self.id)) def __hideHitScoreTask(self, task): self.hideHitScore() return Task.done def hideHitScore(self): if self.hpText: taskMgr.remove('PartyCogHpText' + str(self.id)) self.hpText.removeNode() self.hpText = None return def getHeadLocation(self): self.actor.getJoints(jointName='head')[0].getNetTransform( self.temp_transform) self.head_locator.setMat(self.temp_transform) return self.head_locator.getZ(self.root)
class CogdoMazeDoor: def __init__(self, closedDoorModel, openDoorModel): self.model = NodePath("CogdoMazeDoor") self.model.setPos(0, 0, 0) self.model.reparentTo(render) self.closedDoorModel = closedDoorModel self.closedDoorModel.reparentTo(self.model) self.openDoorModel = openDoorModel self.openDoorModel.reparentTo(self.model) self.openDoorModel.stash() self.lockId2lock = {} self._open = False self.revealed = False self.players = [] self._initCollisions() def setPosition(self, x, y): self.model.setPos(x, y, 2.5) def _initCollisions(self): name = "CogdoMazeDoor" collSphere = CollisionSphere(0, 0, 0.0, 0.25) collSphere.setTangible(0) collNode = CollisionNode(name) collNode.setFromCollideMask(ToontownGlobals.CatchGameBitmask) collNode.addSolid(collSphere) self.collNP = self.model.attachNewNode(collNode) self.enterCollisionEventName = "enter" + name def destroy(self): self.model.removeNode() del self.model del self.openDoorModel del self.closedDoorModel for lock in self.lockId2lock.values(): lock.destroy() del self.lockId2lock def onstage(self): self.model.unstash() def offstage(self): self.model.stash() def open(self): self._open = True self.closedDoorModel.stash() self.openDoorModel.unstash() def close(self): self._open = False self.closedDoorModel.unstash() self.openDoorModel.stash() def addLock(self, lock): self.lockId2lock[lock.id] = lock def unlock(self, lockId): lock = self.lockId2lock.get(lockId) if lock is not None and lock.isLocked(): lock.unlock() return True return False def getLocks(self): return self.lockId2lock.values() def getLock(self, lockId): return self.lockId2lock.get(lockId) def isLocked(self): return True in [lock.isLocked() for lock in self.lockId2lock.values()] def playerEntersDoor(self, player): self.players.append(player) def getPlayerCount(self): return len(self.players)
class DistributedButterfly(DistributedObject.DistributedObject): notify = DirectNotifyGlobal.directNotify.newCategory( 'DistributedButterfly') id = 0 wingTypes = ('wings_1', 'wings_2', 'wings_3', 'wings_4', 'wings_5', 'wings_6') yellowColors = (Vec4(1, 1, 1, 1), Vec4(0.2, 0, 1, 1), Vec4(0.8, 0, 1, 1)) whiteColors = (Vec4(0.8, 0, 0.8, 1), Vec4(0, 0.8, 0.8, 1), Vec4(0.9, 0.4, 0.6, 1), Vec4(0.9, 0.4, 0.4, 1), Vec4(0.8, 0.5, 0.9, 1), Vec4(0.4, 0.1, 0.7, 1)) paleYellowColors = (Vec4(0.8, 0, 0.8, 1), Vec4(0.6, 0.6, 0.9, 1), Vec4(0.7, 0.6, 0.9, 1), Vec4(0.8, 0.6, 0.9, 1), Vec4(0.9, 0.6, 0.9, 1), Vec4(1, 0.6, 0.9, 1)) shadowScaleBig = Point3(0.07, 0.07, 0.07) shadowScaleSmall = Point3(0.01, 0.01, 0.01) def __init__(self, cr): DistributedObject.DistributedObject.__init__(self, cr) self.fsm = ClassicFSM.ClassicFSM('DistributedButterfly', [ State.State('off', self.enterOff, self.exitOff, ['Flying', 'Landed']), State.State('Flying', self.enterFlying, self.exitFlying, ['Landed']), State.State('Landed', self.enterLanded, self.exitLanded, ['Flying']) ], 'off', 'off') self.butterfly = None self.butterflyNode = None self.curIndex = 0 self.destIndex = 0 self.time = 0.0 self.ival = None self.fsm.enterInitialState() return def generate(self): DistributedObject.DistributedObject.generate(self) if self.butterfly: return self.butterfly = Actor.Actor() self.butterfly.loadModel('phase_4/models/props/SZ_butterfly-mod') self.butterfly.loadAnims({ 'flutter': 'phase_4/models/props/SZ_butterfly-flutter', 'glide': 'phase_4/models/props/SZ_butterfly-glide', 'land': 'phase_4/models/props/SZ_butterfly-land' }) index = self.doId % len(self.wingTypes) chosenType = self.wingTypes[index] node = self.butterfly.getGeomNode() for type in self.wingTypes: wing = node.find('**/' + type) if type != chosenType: wing.removeNode() else: if index == 0 or index == 1: color = self.yellowColors[self.doId % len(self.yellowColors)] elif index == 2 or index == 3: color = self.whiteColors[self.doId % len(self.whiteColors)] elif index == 4: color = self.paleYellowColors[self.doId % len(self.paleYellowColors)] else: color = Vec4(1, 1, 1, 1) wing.setColor(color) self.butterfly2 = Actor.Actor(other=self.butterfly) self.butterfly.enableBlend(blendType=PartBundle.BTLinear) self.butterfly.loop('flutter') self.butterfly.loop('land') self.butterfly.loop('glide') rng = RandomNumGen.RandomNumGen(self.doId) playRate = 0.6 + 0.8 * rng.random() self.butterfly.setPlayRate(playRate, 'flutter') self.butterfly.setPlayRate(playRate, 'land') self.butterfly.setPlayRate(playRate, 'glide') self.butterfly2.setPlayRate(playRate, 'flutter') self.butterfly2.setPlayRate(playRate, 'land') self.butterfly2.setPlayRate(playRate, 'glide') self.glideWeight = rng.random() * 2 lodNode = LODNode('butterfly-node') lodNode.addSwitch(100, 40) lodNode.addSwitch(40, 0) self.butterflyNode = NodePath(lodNode) self.butterfly2.setH(180.0) self.butterfly2.reparentTo(self.butterflyNode) self.butterfly.setH(180.0) self.butterfly.reparentTo(self.butterflyNode) self.__initCollisions() self.dropShadow = loader.loadModel('phase_3/models/props/drop_shadow') self.dropShadow.setColor(0, 0, 0, 0.3) self.dropShadow.setPos(0, 0.1, -0.05) self.dropShadow.setScale(self.shadowScaleBig) self.dropShadow.reparentTo(self.butterfly) def disable(self): self.butterflyNode.reparentTo(hidden) if self.ival != None: self.ival.finish() self.__ignoreAvatars() DistributedObject.DistributedObject.disable(self) return def delete(self): self.butterfly.cleanup() self.butterfly = None self.butterfly2.cleanup() self.butterfly2 = None self.butterflyNode.removeNode() self.__deleteCollisions() self.ival = None del self.fsm DistributedObject.DistributedObject.delete(self) return def uniqueButterflyName(self, name): DistributedButterfly.id += 1 return name + '-%d' % DistributedButterfly.id def __detectAvatars(self): self.accept('enter' + self.cSphereNode.getName(), self.__handleCollisionSphereEnter) def __ignoreAvatars(self): self.ignore('enter' + self.cSphereNode.getName()) def __initCollisions(self): self.cSphere = CollisionSphere(0.0, 1.0, 0.0, 3.0) self.cSphere.setTangible(0) self.cSphereNode = CollisionNode( self.uniqueButterflyName('cSphereNode')) self.cSphereNode.addSolid(self.cSphere) self.cSphereNodePath = self.butterflyNode.attachNewNode( self.cSphereNode) self.cSphereNodePath.hide() self.cSphereNode.setCollideMask(ToontownGlobals.WallBitmask) def __deleteCollisions(self): del self.cSphere del self.cSphereNode self.cSphereNodePath.removeNode() del self.cSphereNodePath def __handleCollisionSphereEnter(self, collEntry): self.sendUpdate('avatarEnter', []) def setArea(self, playground, area): self.playground = playground self.area = area def setState(self, stateIndex, curIndex, destIndex, time, timestamp): self.curIndex = curIndex self.destIndex = destIndex self.time = time self.fsm.request(ButterflyGlobals.states[stateIndex], [globalClockDelta.localElapsedTime(timestamp)]) def enterOff(self, ts=0.0): if self.butterflyNode != None: self.butterflyNode.reparentTo(hidden) return def exitOff(self): if self.butterflyNode != None: self.butterflyNode.reparentTo(render) return def enterFlying(self, ts): self.__detectAvatars() curPos = ButterflyGlobals.ButterflyPoints[self.playground][self.area][ self.curIndex] destPos = ButterflyGlobals.ButterflyPoints[self.playground][self.area][ self.destIndex] flyHeight = max( curPos[2], destPos[2]) + ButterflyGlobals.BUTTERFLY_HEIGHT[self.playground] curPosHigh = Point3(curPos[0], curPos[1], flyHeight) destPosHigh = Point3(destPos[0], destPos[1], flyHeight) if ts <= self.time: flyTime = self.time - ( ButterflyGlobals.BUTTERFLY_TAKEOFF[self.playground] + ButterflyGlobals.BUTTERFLY_LANDING[self.playground]) self.butterflyNode.setPos(curPos) self.dropShadow.show() self.dropShadow.setScale(self.shadowScaleBig) oldHpr = self.butterflyNode.getHpr() self.butterflyNode.headsUp(destPos) newHpr = self.butterflyNode.getHpr() self.butterflyNode.setHpr(oldHpr) takeoffShadowT = 0.2 * ButterflyGlobals.BUTTERFLY_TAKEOFF[ self.playground] landShadowT = 0.2 * ButterflyGlobals.BUTTERFLY_LANDING[ self.playground] self.butterfly2.loop('flutter') self.ival = Sequence( Parallel( LerpPosHprInterval( self.butterflyNode, ButterflyGlobals.BUTTERFLY_TAKEOFF[self.playground], curPosHigh, newHpr), LerpAnimInterval( self.butterfly, ButterflyGlobals.BUTTERFLY_TAKEOFF[self.playground], 'land', 'flutter'), LerpAnimInterval( self.butterfly, ButterflyGlobals.BUTTERFLY_TAKEOFF[self.playground], None, 'glide', startWeight=0, endWeight=self.glideWeight), Sequence( LerpScaleInterval(self.dropShadow, takeoffShadowT, self.shadowScaleSmall, startScale=self.shadowScaleBig), HideInterval(self.dropShadow))), LerpPosInterval(self.butterflyNode, flyTime, destPosHigh), Parallel( LerpPosInterval( self.butterflyNode, ButterflyGlobals.BUTTERFLY_LANDING[self.playground], destPos), LerpAnimInterval( self.butterfly, ButterflyGlobals.BUTTERFLY_LANDING[self.playground], 'flutter', 'land'), LerpAnimInterval( self.butterfly, ButterflyGlobals.BUTTERFLY_LANDING[self.playground], None, 'glide', startWeight=self.glideWeight, endWeight=0), Sequence( Wait(ButterflyGlobals.BUTTERFLY_LANDING[ self.playground] - landShadowT), ShowInterval(self.dropShadow), LerpScaleInterval(self.dropShadow, landShadowT, self.shadowScaleBig, startScale=self.shadowScaleSmall))), name=self.uniqueName('Butterfly')) self.ival.start(ts) else: self.ival = None self.butterflyNode.setPos(destPos) self.butterfly.setControlEffect('land', 1.0) self.butterfly.setControlEffect('flutter', 0.0) self.butterfly.setControlEffect('glide', 0.0) self.butterfly2.loop('land') return def exitFlying(self): self.__ignoreAvatars() if self.ival != None: self.ival.finish() self.ival = None return def enterLanded(self, ts): self.__detectAvatars() curPos = ButterflyGlobals.ButterflyPoints[self.playground][self.area][ self.curIndex] self.butterflyNode.setPos(curPos) self.dropShadow.show() self.dropShadow.setScale(self.shadowScaleBig) self.butterfly.setControlEffect('land', 1.0) self.butterfly.setControlEffect('flutter', 0.0) self.butterfly.setControlEffect('glide', 0.0) self.butterfly2.pose( 'land', random.randrange(self.butterfly2.getNumFrames('land'))) return None def exitLanded(self): self.__ignoreAvatars() return None
class CogdoFlyingLevel(DirectObject): notify = directNotify.newCategory('CogdoFlyingLevel') def __init__(self, parent, frameModel, startPlatformModel, endPlatformModel, quadLengthUnits, quadVisibilityAhead, quadVisibiltyBehind): self.parent = parent self.quadLengthUnits = quadLengthUnits self._halfQuadLengthUnits = quadLengthUnits / 2.0 self.quadVisibiltyAhead = quadVisibilityAhead self.quadVisibiltyBehind = quadVisibiltyBehind self._frameModel = frameModel self.root = NodePath('CogdoFlyingLevel') self.quadrantRoot = NodePath('QuadrantsRoot') self.quadrantRoot.reparentTo(self.root) self._startPlatformModel = startPlatformModel self._startPlatformModel.reparentTo(self.root) self._startPlatformModel.setZ(Globals.Level.StartPlatformHeight) self._endPlatformModel = endPlatformModel self._endPlatformModel.reparentTo(self.root) self._endPlatformModel.setZ(Globals.Level.EndPlatformHeight) self.wallR = self._frameModel.find('**/wallR') self.wallL = self._frameModel.find('**/wallL') self._exit = CogdoGameExit() self._exit.reparentTo(self._endPlatformModel) loc = self._endPlatformModel.find('**/exit_loc') offset = loc.getPos(render) self._exit.setPos(render, offset) self.quadrants = [] self.visibleQuadIndices = [] self._numQuads = 0 self._currentQuadNum = -1 self._camera = None self._initCollisions() self.upLimit = self._frameModel.find('**/limit_up').getZ(render) self.downLimit = self._frameModel.find('**/limit_down').getZ(render) self.leftLimit = self._frameModel.find('**/limit_left').getX(render) - 30.0 self.rightLimit = self._frameModel.find('**/limit_right').getX(render) + 30.0 self.backLimit = -self.quadLengthUnits self.forwardLimit = self.quadLengthUnits * 20 self._frameModel.flattenStrong() self.gatherableFactory = CogdoFlyingGatherableFactory() self.obstacleFactory = CogdoFlyingObstacleFactory() return def getExit(self): return self._exit def getBounds(self): return ((self.leftLimit, self.rightLimit), (self.backLimit, self.forwardLimit), (self.downLimit, self.upLimit)) def getGatherable(self, serialNum): for quadrant in self.quadrants: for gatherable in quadrant.gatherables: if gatherable.serialNum == serialNum: return gatherable return None def ready(self): self.gatherableFactory.destroy() del self.gatherableFactory self.obstacleFactory.destroy() del self.obstacleFactory self._initStartEndPlatforms() self._frameModel.reparentTo(self.root) self.root.reparentTo(self.parent) self.root.stash() def _initStartEndPlatforms(self): self.startPlatform = CogdoFlyingPlatform(self._startPlatformModel, Globals.Level.PlatformTypes.StartPlatform) self.endPlatform = CogdoFlyingPlatform(self._endPlatformModel, Globals.Level.PlatformTypes.EndPlatform) self._endPlatformModel.setY(self.convertQuadNumToY(self._numQuads)) self.backLimit = self._startPlatformModel.getY(render) - Globals.Level.StartPlatformLength * 0.7 self.forwardLimit = self._endPlatformModel.getY(render) + Globals.Level.EndPlatformLength * 0.7 def _initCollisions(self): self.collPlane = CollisionPlane(Plane(Vec3(0, 0, 1.0), Point3(0, 0, 10))) self.collPlane.setTangible(0) self.collNode = CollisionNode('fogPlane') self.collNode.setIntoCollideMask(OTPGlobals.FloorBitmask) self.collNode.addSolid(self.collPlane) self.collNodePath = self.root.attachNewNode(self.collNode) self.collNodePath.hide() def destroy(self): del self.collPlane self.collNodePath.removeNode() del self.collNodePath del self.collNode for quadrant in self.quadrants: quadrant.destroy() self._exit.destroy() del self._exit self.root.removeNode() del self.root def onstage(self): self.root.unstash() self.update(0.0) def offstage(self): self.root.stash() def start(self, startTime = 0.0): self._startTime = startTime def stop(self): pass def getLength(self): return self.quadLengthUnits * self.getNumQuadrants() def appendQuadrant(self, model): quadrant = CogdoFlyingLevelQuadrant(self._numQuads, model, self, self.root) if self._numQuads == 0: quadrant.generateGatherables(self._startPlatformModel) quadrant.offstage() self.quadrants.append(quadrant) self._numQuads = len(self.quadrants) def getNumQuadrants(self): return self._numQuads def setCamera(self, camera): self._camera = camera def getCameraActualQuadrant(self): camY = self._camera.getY(render) y = self.root.getY(render) return self.convertYToQuadNum(camY - y) def update(self, dt = 0.0): if self._camera is None: return else: quadNum = clamp(self.getCameraActualQuadrant(), 0, self._numQuads - 1) if quadNum < self._numQuads: self.quadrants[quadNum].update(dt) if quadNum + 1 < self._numQuads: self.quadrants[quadNum + 1].update(dt) if quadNum != self._currentQuadNum: self._switchToQuadrant(quadNum) return def _switchToQuadrant(self, quadNum): self.visibleQuadIndices = [] if quadNum >= 0: if quadNum > 0: self.quadrants[max(quadNum - self.quadVisibiltyBehind, 0)].onstage() for i in xrange(quadNum, min(quadNum + self.quadVisibiltyAhead + 1, self._numQuads)): self.quadrants[i].onstage() self.visibleQuadIndices.append(i) if i == 0: self.startPlatform.onstage() elif i == self._numQuads - 1: self.endPlatform.onstage() self._currentQuadNum = quadNum for i in range(0, max(self._currentQuadNum - self.quadVisibiltyBehind, 0)) + range(min(self._currentQuadNum + self.quadVisibiltyAhead + 1, self._numQuads), self._numQuads): self.quadrants[i].offstage() if i == 0: self.startPlatform.offstage() elif i == self._numQuads - 1: self.endPlatform.offstage() def convertQuadNumToY(self, quadNum): return quadNum * self.quadLengthUnits def convertYToQuadNum(self, y): return int(y / self.quadLengthUnits) def convertCenterYToQuadNum(self, y): return self.convertYToQuadNum(y + self._halfQuadLengthUnits)
class PartyCogActivityLocalPlayer(PartyCogActivityPlayer): def __init__(self, activity, position, team, exitActivityCallback=None): PartyCogActivityPlayer.__init__(self, activity, base.localAvatar, position, team) self.input = PartyCogActivityInput(exitActivityCallback) self.gui = PartyCogActivityGui() self.throwPiePrevTime = 0 self.lastMoved = 0 if base.localAvatar: self.prevPos = base.localAvatar.getPos() self.cameraManager = None self.control = None self.consecutiveShortThrows = 0 return def destroy(self): if self.enabled: self.disable() if self.cameraManager is not None: self.cameraManager.setEnabled(False) self.cameraManager.destroy() del self.cameraManager del self.gui del self.input if self.control is not None: self.control.destroy() del self.control PartyCogActivityPlayer.destroy(self) return def _initOrthoWalk(self): orthoDrive = OrthoDrive(9.778, customCollisionCallback=self.activity.view. checkOrthoDriveCollision) self.orthoWalk = OrthoWalk(orthoDrive, broadcast=True) def _destroyOrthoWalk(self): self.orthoWalk.stop() self.orthoWalk.destroy() del self.orthoWalk def getPieThrowingPower(self, time): elapsed = max(time - self.input.throwPiePressedStartTime, 0.0) w = 1.0 / PartyGlobals.CogActivityPowerMeterTime * 2.0 * math.pi power = int(round(-math.cos(w * elapsed) * 50.0 + 50.0)) return power def isShortThrow(self, time): elapsed = max(time - self.input.throwPiePressedStartTime, 0.0) return elapsed <= PartyGlobals.CogActivityShortThrowTime def checkForThrowSpam(self, time): if self.isShortThrow(time): self.consecutiveShortThrows += 1 else: self.consecutiveShortThrows = 0 return self.consecutiveShortThrows >= PartyGlobals.CogActivityShortThrowSpam def _startUpdateTask(self): task = Task(self._updateTask) task.lastPositionBroadcastTime = 0.0 self.throwPiePrevTime = 0 taskMgr.add(task, UPDATE_TASK_NAME) def _stopUpdateTask(self): taskMgr.remove(UPDATE_TASK_NAME) def _updateTask(self, task): self._update() if base.localAvatar.getPos() != self.prevPos: self.prevPos = base.localAvatar.getPos() self.lastMoved = self.activity.getCurrentActivityTime() if max(self.activity.getCurrentActivityTime() - self.lastMoved, 0) > PartyGlobals.ToonMoveIdleThreshold: self.gui.showMoveControls() if max(self.activity.getCurrentActivityTime() - self.throwPiePrevTime, 0) > PartyGlobals.ToonAttackIdleThreshold: self.gui.showAttackControls() if self.input.throwPieWasReleased: if self.checkForThrowSpam(globalClock.getFrameTime()): self.gui.showSpamWarning() self.input.throwPieWasReleased = False self.throwPie(self.getPieThrowingPower(globalClock.getFrameTime())) return Task.cont def throwPie(self, piePower): if not self.activity.isState('Active'): return if self.activity.getCurrentActivityTime( ) - self.throwPiePrevTime > THROW_PIE_LIMIT_TIME: self.throwPiePrevTime = self.activity.getCurrentActivityTime() self.activity.b_pieThrow(self.toon, piePower) def _update(self): self.control.update() def getLookat(self, whosLooking, refNode=None): if refNode is None: refNode = render dist = 5.0 oldParent = self.tempNP.getParent() self.tempNP.reparentTo(whosLooking) self.tempNP.setPos(0.0, dist, 0.0) pos = self.tempNP.getPos(refNode) self.tempNP.reparentTo(oldParent) return pos def entersActivity(self): base.cr.playGame.getPlace().setState('activity') PartyCogActivityPlayer.entersActivity(self) self.gui.disableToontownHUD() self.cameraManager = CameraManager(camera) self.tempNP = NodePath('temp') self.lookAtMyTeam() self.control = StrafingControl(self) def exitsActivity(self): PartyCogActivityPlayer.exitsActivity(self) self.gui.enableToontownHUD() self.cameraManager.setEnabled(False) self.tempNP.removeNode() self.tempNP = None if not aspect2d.find('**/JellybeanRewardGui*'): base.cr.playGame.getPlace().setState('walk') else: self.toon.startPosHprBroadcast() return def getRunToStartPositionIval(self): targetH = self.locator.getH() travelVec = self.position - self.toon.getPos(self.activity.root) duration = travelVec.length() / 9.778 startH = 0.0 if travelVec.getY() < 0.0: startH = 180.0 return Sequence( Func(self.toon.startPosHprBroadcast, 0.1), Func(self.toon.b_setAnimState, 'run'), Parallel( self.toon.hprInterval(0.5, VBase3(startH, 0.0, 0.0), other=self.activity.root), self.toon.posInterval(duration, self.position, other=self.activity.root)), Func(self.toon.b_setAnimState, 'neutral'), self.toon.hprInterval(0.25, VBase3(targetH, 0.0, 0.0), other=self.activity.root), Func(self.toon.stopPosHprBroadcast)) def enable(self): if self.enabled: return PartyCogActivityPlayer.enable(self) self.toon.b_setAnimState('Happy') self._initOrthoWalk() self.orthoWalk.start() self.orthoWalking = True self.input.enable() self.gui.disableToontownHUD() self.gui.load() self.gui.setScore(0) self.gui.showScore() self.gui.setTeam(self.team) self.gui.startTrackingCogs(self.activity.view.cogManager.cogs) self.control.enable() self._startUpdateTask() def disable(self): if not self.enabled: return self._stopUpdateTask() self.toon.b_setAnimState('neutral') PartyCogActivityPlayer.disable(self) self.orthoWalking = False self.orthoWalk.stop() self._destroyOrthoWalk() self.input.disable() self._aimMode = False self.cameraManager.setEnabled(False) self.gui.hide() self.gui.stopTrackingCogs() self.gui.unload() def updateScore(self): self.gui.setScore(self.score) def b_updateToonPosition(self): self.updateToonPosition() self.d_updateToonPosition() def d_updateToonPosition(self): self.toon.d_setPos(self.toon.getX(), self.toon.getY(), self.toon.getZ()) self.toon.d_setH(self.toon.getH()) def lookAtArena(self): self.cameraManager.setEnabled(True) self.cameraManager.setTargetPos( self.activity.view.arena.find( '**/conclusionCamPos_locator').getPos(render)) self.cameraManager.setTargetLookAtPos( self.activity.view.arena.find( '**/conclusionCamAim_locator').getPos(render)) def lookAtMyTeam(self): activityView = self.activity.view arena = activityView.arena pos = activityView.teamCamPosLocators[self.team].getPos() aim = activityView.teamCamAimLocators[self.team].getPos() camera.wrtReparentTo(arena) self.cameraManager.setPos(camera.getPos(render)) self.tempNP.reparentTo(arena) self.tempNP.setPos(arena, pos) self.cameraManager.setTargetPos(self.tempNP.getPos(render)) self.cameraManager.setLookAtPos(self.getLookat(camera)) self.tempNP.reparentTo(arena) self.tempNP.setPos(arena, aim) self.cameraManager.setTargetLookAtPos(self.tempNP.getPos(render)) self.cameraManager.setEnabled(True) camera.setP(0.0) camera.setR(0.0)
class DistributedPartyTrampolineActivity(DistributedPartyActivity): notify = DirectNotifyGlobal.directNotify.newCategory('DistributedPartyTrampolineActivity') def __init__(self, cr, doJellyBeans = True, doTricks = False, texture = None): DistributedPartyTrampolineActivity.notify.debug('__init__') DistributedPartyActivity.__init__(self, cr, PartyGlobals.ActivityIds.PartyTrampoline, PartyGlobals.ActivityTypes.GuestInitiated, wantLever=False, wantRewardGui=True) self.doJellyBeans = doJellyBeans self.doTricks = doTricks self.texture = texture self.toon = None self.trampHeight = 3.6 self.trampK = 400.0 self.normalTrampB = 2.5 self.leavingTrampB = 8.0 self.trampB = self.normalTrampB self.g = -32.0 self.jumpBoost = 330.0 self.beginningBoost = 500.0 self.beginningBoostThreshold = self.trampHeight + 1.5 self.earlyJumpThreshold = 75.0 self.boingThreshold = 300.0 self.turnFactor = 120.0 self.stepDT = 0.001 self.targetCameraPos = Point3(0.0, 40.0, 10.0) self.cameraSpeed = 2.0 self.hopOffPos = Point3(16.0, 0.0, 0.0) self.indicatorFactor = 0.0095 self.dropShadowCutoff = 15.0 self.minHeightForText = 15.0 self.heightTextOffset = -0.065 self.beanOffset = 0.5 self.guiBeanOffset = -0.02 self.jumpTextShown = False self.toonJumped = False self.turnLeft = False self.turnRight = False self.leavingTrampoline = False self.toonVelocity = 0.0 self.topHeight = 0.0 self.lastPeak = 0.0 self.beginRoundInterval = None self.hopOnAnim = None self.hopOffAnim = None self.flashTextInterval = None self.numJellyBeans = PartyGlobals.TrampolineNumJellyBeans self.jellyBeanBonus = PartyGlobals.TrampolineJellyBeanBonus self.jellyBeanStartHeight = 20.0 self.jellyBeanStopHeight = 90.0 self.jellyBeanColors = [VBase4(1.0, 0.5, 0.5, 1.0), VBase4(0.5, 1.0, 0.5, 1.0), VBase4(0.5, 1.0, 1.0, 1.0), VBase4(1.0, 1.0, 0.4, 1.0), VBase4(0.4, 0.4, 1.0, 1.0), VBase4(1.0, 0.5, 1.0, 1.0)] delta = (self.jellyBeanStopHeight - self.jellyBeanStartHeight) / (self.numJellyBeans - 1) self.jellyBeanPositions = [ self.jellyBeanStartHeight + n * delta for n in range(self.numJellyBeans) ] self.doSimulateStep = False return def load(self): DistributedPartyTrampolineActivity.notify.debug('load') DistributedPartyActivity.load(self) self.loadModels() self.loadCollision() self.loadGUI() self.loadSounds() self.loadIntervals() self.activityFSM = TrampolineActivityFSM(self) self.activityFSM.request('Idle') self.animFSM = TrampolineAnimFSM(self) self.setBestHeightInfo('', 0) def loadModels(self): self.tramp = self.root.attachNewNode(self.uniqueName('tramp')) self.screenPlaneElements = NodePath(self.uniqueName('screenPlane')) self.trampActor = Actor('phase_13/models/parties/trampoline_model', {'emptyAnim': 'phase_13/models/parties/trampoline_anim'}) self.trampActor.reparentTo(self.tramp) if self.texture: reskinNode = self.tramp.find('**/trampoline/__Actor_modelRoot/-GeomNode') reskinNode.setTexture(loader.loadTexture(self.texture), 100) self.surface = NodePath(self.uniqueName('trampSurface')) self.surface.reparentTo(self.tramp) self.surface.setZ(self.trampHeight) self.trampActor.controlJoint(self.surface, 'modelRoot', 'trampoline_joint1') self.sign.setPos(PartyGlobals.TrampolineSignOffset) self.beans = [ loader.loadModelCopy('phase_4/models/props/jellybean4') for i in range(self.numJellyBeans) ] for bean in self.beans: bean.find('**/jellybean').setP(-35.0) bean.setScale(3.0) bean.setTransparency(True) bean.reparentTo(self.tramp) bean.stash() self.beans[-1].setScale(8.0) def loadCollision(self): collTube = CollisionTube(0.0, 0.0, 0.0, 0.0, 0.0, 6.0, 5.4) collTube.setTangible(True) self.trampolineCollision = CollisionNode(self.uniqueName('TrampolineCollision')) self.trampolineCollision.addSolid(collTube) self.trampolineCollision.setCollideMask(OTPGlobals.CameraBitmask | OTPGlobals.WallBitmask) self.trampolineCollisionNP = self.tramp.attachNewNode(self.trampolineCollision) collSphere = CollisionSphere(0.0, 0.0, 0.0, 7.0) collSphere.setTangible(False) self.trampolineTrigger = CollisionNode(self.uniqueName('TrampolineTrigger')) self.trampolineTrigger.addSolid(collSphere) self.trampolineTrigger.setIntoCollideMask(OTPGlobals.WallBitmask) self.trampolineTriggerNP = self.tramp.attachNewNode(self.trampolineTrigger) self.accept('enter%s' % self.uniqueName('TrampolineTrigger'), self.onTrampolineTrigger) def loadGUI(self): self.gui = loader.loadModel('phase_13/models/parties/trampolineGUI') self.gui.setX(-1.15) self.gui.reparentTo(self.screenPlaneElements) self.toonIndicator = self.gui.find('**/trampolineGUI_MovingBar') jumpLineLocator = self.gui.find('**/jumpLine_locator') guiBean = self.gui.find('**/trampolineGUI_GreenJellyBean') self.gui.find('**/trampolineGUI_GreenJellyBean').stash() self.guiBeans = [ guiBean.instanceUnderNode(jumpLineLocator, self.uniqueName('guiBean%d' % i)) for i in range(self.numJellyBeans) ] self.guiBeans[-1].setScale(1.5) heightTextNode = TextNode(self.uniqueName('TrampolineActivity.heightTextNode')) heightTextNode.setFont(ToontownGlobals.getSignFont()) heightTextNode.setAlign(TextNode.ALeft) heightTextNode.setText('0.0') heightTextNode.setShadow(0.05, 0.05) heightTextNode.setShadowColor(0.0, 0.0, 0.0, 1.0) heightTextNode.setTextColor(1.0, 1.0, 1.0, 1.0) self.heightText = jumpLineLocator.attachNewNode(heightTextNode) self.heightText.setX(0.15) self.heightText.setScale(0.1) self.heightText.setAlphaScale(0.0) self.quitEarlyButtonModels = loader.loadModel('phase_3.5/models/gui/inventory_gui') quitEarlyUp = self.quitEarlyButtonModels.find('**//InventoryButtonUp') quitEarlyDown = self.quitEarlyButtonModels.find('**/InventoryButtonDown') quitEarlyRollover = self.quitEarlyButtonModels.find('**/InventoryButtonRollover') self.quitEarlyButton = DirectButton(parent=self.screenPlaneElements, relief=None, text=TTLocalizer.PartyTrampolineQuitEarlyButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -0.23), text_scale=0.7, image=(quitEarlyUp, quitEarlyDown, quitEarlyRollover), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(1.15, 0, 0.6), scale=0.09, command=self.leaveTrampoline) self.quitEarlyButton.stash() self.flashText = OnscreenText(text='', pos=(0.0, -0.45), scale=0.2, fg=(1.0, 1.0, 0.65, 1.0), align=TextNode.ACenter, font=ToontownGlobals.getSignFont(), mayChange=True) self.timer = PartyUtils.getNewToontownTimer() self.timer.reparentTo(self.screenPlaneElements) return def loadSounds(self): self.jellyBeanSound = base.loader.loadSfx('phase_4/audio/sfx/sparkly.ogg') self.boingSound = base.loader.loadSfx('phase_4/audio/sfx/target_trampoline_2.ogg') self.whistleSound = base.loader.loadSfx('phase_4/audio/sfx/AA_sound_whistle.ogg') def loadIntervals(self): def prepareHeightText(): self.heightText.node().setText(TTLocalizer.PartyTrampolineGetHeight % int(self.toon.getZ())) self.heightText.setZ(self.indicatorFactor * self.toon.getZ() + self.heightTextOffset) self.heightTextInterval = Sequence(Func(prepareHeightText), LerpFunc(self.heightText.setAlphaScale, fromData=1.0, toData=0.0, duration=1.0)) def unload(self): DistributedPartyTrampolineActivity.notify.debug('unload') if self.hopOnAnim and self.hopOnAnim.isPlaying(): self.hopOnAnim.finish() if self.hopOffAnim and self.hopOffAnim.isPlaying(): self.hopOffAnim.finish() if self.beginRoundInterval and self.beginRoundInterval.isPlaying(): self.beginRoundInterval.finish() if self.flashTextInterval and self.flashTextInterval.isPlaying(): self.flashTextInterval.finish() if self.heightTextInterval and self.heightTextInterval.isPlaying(): self.heightTextInterval.finish() self.timer.stop() DistributedPartyActivity.unload(self) taskMgr.remove(self.uniqueName('TrampolineActivity.updateTask')) taskMgr.remove(self.uniqueName('TrampolineActivity.remoteUpdateTask')) self.ignoreAll() del self.heightTextInterval del self.beginRoundInterval del self.hopOnAnim del self.hopOffAnim del self.flashTextInterval if hasattr(self, 'beanAnims'): self.cleanupJellyBeans() self.quitEarlyButton.destroy() del self.quitEarlyButton if self.screenPlaneElements: self.screenPlaneElements.removeNode() self.screenPlaneElements = None del self.activityFSM del self.animFSM return def setBestHeightInfo(self, toonName, height): self.bestHeightInfo = (toonName, height) DistributedPartyTrampolineActivity.notify.debug('%s has the best height of %d' % (toonName, height)) if height > 0: self.setSignNote(TTLocalizer.PartyTrampolineBestHeight % self.bestHeightInfo) else: self.setSignNote(TTLocalizer.PartyTrampolineNoHeightYet) def leaveTrampoline(self): if self.toon != None and self.toon.doId == base.localAvatar.doId: self._showFlashMessage(TTLocalizer.PartyTrampolineTimesUp) self.leavingTrampoline = True self.timer.reset() self.trampB = self.leavingTrampB self.ignore('control') self.quitEarlyButton.stash() return def requestAnim(self, request): self.animFSM.request(request) def b_requestAnim(self, request): self.requestAnim(request) self.sendUpdate('requestAnim', [request]) def requestAnimEcho(self, request): if self.toon != None and self.toon.doId != base.localAvatar.doId: self.requestAnim(request) return def removeBeans(self, beansToRemove): for i in beansToRemove: height, bean, guiBean, beanAnim = self.beanDetails[i] guiBean.stash() if i in self.beansToCollect: self.beansToCollect.remove(i) else: self.notify.warning('removeBeans avoided a crash, %d not in self.beansToCollect' % i) self.poofBean(bean, beanAnim) def b_removeBeans(self, beansToRemove): self.removeBeans(beansToRemove) self.sendUpdate('removeBeans', [beansToRemove]) def removeBeansEcho(self, beansToRemove): if self.toon != None and self.toon.doId != base.localAvatar.doId: self.removeBeans(beansToRemove) return def joinRequestDenied(self, reason): DistributedPartyActivity.joinRequestDenied(self, reason) self.showMessage(TTLocalizer.PartyActivityDefaultJoinDeny) base.cr.playGame.getPlace().fsm.request('walk') def exitRequestDenied(self, reason): DistributedPartyActivity.exitRequestDenied(self, reason) self.showMessage(TTLocalizer.PartyActivityDefaultExitDeny) def setState(self, newState, timestamp): DistributedPartyTrampolineActivity.notify.debug('setState( newState=%s, ... )' % newState) DistributedPartyActivity.setState(self, newState, timestamp) self.activityFSM.request(newState) def startIdle(self): DistributedPartyTrampolineActivity.notify.debug('startIdle') def finishIdle(self): DistributedPartyTrampolineActivity.notify.debug('finishIdle') def startRules(self): DistributedPartyTrampolineActivity.notify.debug('startRules') if self.doJellyBeans: self.setupJellyBeans() if self.toon != None and self.toon.doId == base.localAvatar.doId: self.acquireToon() return def startActive(self): DistributedPartyTrampolineActivity.notify.debug('startActive') if self.toon != None and self.toon.doId == base.localAvatar.doId: base.setCellsAvailable(base.bottomCells, True) self.accept('arrow_left', self.onLeft) self.accept('arrow_left-up', self.onLeftUp) self.accept('arrow_right', self.onRight) self.accept('arrow_right-up', self.onRightUp) self.beginRoundInterval = Sequence(Func(self._showFlashMessage, TTLocalizer.PartyTrampolineReady), Wait(1.2), Func(self.flashMessage, TTLocalizer.PartyTrampolineGo), Func(self.beginRound)) self.beginRoundInterval.start() return def finishActive(self): DistributedPartyTrampolineActivity.notify.debug('finishActive') if self.doJellyBeans: self.cleanupJellyBeans() def setupJellyBeans(self): self.beanAnims = [] self.beansToCollect = [] self.beanDetails = [] self.numBeansCollected = 0 for i in range(self.numJellyBeans): bean = self.beans[i] guiBean = self.guiBeans[i] height = self.jellyBeanPositions[i] color = random.choice(self.jellyBeanColors) bean.find('**/jellybean').setColor(color) if self.toon.doId == base.localAvatar.doId: bean.setAlphaScale(1.0) else: bean.setAlphaScale(0.5) guiBean.setColor(color) bean.setZ(height + self.toon.getHeight() + self.beanOffset) guiBean.setZ(height * self.indicatorFactor + self.guiBeanOffset) bean.setH(0.0) bean.unstash() guiBean.unstash() beanAnim = bean.hprInterval(1.5, VBase3((i % 2 * 2 - 1) * 360.0, 0.0, 0.0)) beanAnim.loop() self.beanAnims.append(beanAnim) self.beanDetails.append((height, bean, guiBean, beanAnim)) self.beansToCollect = list(range(self.numJellyBeans)) def cleanupJellyBeans(self): for bean in self.beans: bean.stash() for guiBean in self.guiBeans: guiBean.stash() if hasattr(self, 'beanAnims'): for beanAnim in self.beanAnims: beanAnim.finish() del self.beanAnims del self.beansToCollect def beginRound(self): base.playSfx(self.whistleSound) self.timer.setTime(PartyGlobals.TrampolineDuration) self.timer.countdown(PartyGlobals.TrampolineDuration) self.timer.show() self.quitEarlyButton.unstash() self.notify.debug('Accepting contorl') self.accept('control', self.onJump) self.notify.debug('setting simulate step to true') self.doSimulateStep = True def acquireToon(self): self.toon.disableSmartCameraViews() self.toon.stopUpdateSmartCamera() camera.wrtReparentTo(render) self.toon.dropShadow.reparentTo(hidden) self.toon.startPosHprBroadcast(period=0.2) self.toonAcceleration = 0.0 self.toonVelocity = 0.0 self.topHeight = 0.0 self.trampB = self.normalTrampB self.leavingTrampoline = False self.hopOnAnim = Sequence(Func(self.toon.b_setAnimState, 'jump', 1.0), Wait(0.4), PartyUtils.arcPosInterval(0.75, self.toon, Point3(0.0, 0.0, self.trampHeight), 5.0, self.tramp), Func(self.postHopOn)) self.hopOnAnim.start() def postHopOn(self): self.toon.setH(self.toon.getH() + 90.0) self.toon.dropShadow.reparentTo(self.surface) self.screenPlaneElements.reparentTo(aspect2d) self.timeLeftToSimulate = 0.0 self.doSimulateStep = False taskMgr.add(self.updateTask, self.uniqueName('TrampolineActivity.updateTask')) base.setCellsAvailable(base.leftCells, False) base.setCellsAvailable(base.bottomCells, False) DistributedPartyActivity.startRules(self) def releaseToon(self): self._hideFlashMessage() self.ignore('arrow_left') self.ignore('arrow_left-up') self.ignore('arrow_right') self.ignore('arrow_right-up') taskMgr.remove(self.uniqueName('TrampolineActivity.updateTask')) self.hopOffAnim = Sequence(self.toon.hprInterval(0.5, VBase3(-90.0, 0.0, 0.0), other=self.tramp), Func(self.toon.b_setAnimState, 'jump', 1.0), Func(self.toon.dropShadow.reparentTo, hidden), Wait(0.4), PartyUtils.arcPosInterval(0.75, self.toon, self.hopOffPos, 5.0, self.tramp), Func(self.postHopOff)) self.hopOffAnim.start() def postHopOff(self): self.screenPlaneElements.reparentTo(hidden) base.setCellsAvailable(base.leftCells, True) self.timer.stop() self.timer.hide() self.toon.dropShadow.reparentTo(self.toon.getShadowJoint()) self.toon.dropShadow.setAlphaScale(1.0) self.toon.dropShadow.setScale(1.0) self.b_requestAnim('Off') camera.reparentTo(base.localAvatar) base.localAvatar.startUpdateSmartCamera() base.localAvatar.enableSmartCameraViews() base.localAvatar.setCameraPositionByIndex(base.localAvatar.cameraIndex) place = base.cr.playGame.getPlace() if self.doJellyBeans: self.sendUpdate('awardBeans', [self.numBeansCollected, int(self.topHeight)]) if int(self.topHeight) > self.bestHeightInfo[1]: self.sendUpdate('reportHeightInformation', [int(self.topHeight)]) self.d_toonExitDemand() def onTrampolineTrigger(self, collEntry): if self.activityFSM.state == 'Idle' and self.toon == None and base.cr.playGame.getPlace().fsm.getCurrentState().getName() == 'walk': base.cr.playGame.getPlace().fsm.request('activity') self.d_toonJoinRequest() else: self.flashMessage(TTLocalizer.PartyTrampolineActivityOccupied, duration=2.0) return def onJump(self): self.notify.debug('got onJump') if self.toon != None and self.toon.getZ() < self.trampHeight: self.toonJumped = True self.b_requestAnim('Jump') else: self.notify.debug('z is less than tramp height') return def onLeft(self): self.turnLeft = True def onLeftUp(self): self.turnLeft = False def onRight(self): self.turnRight = True def onRightUp(self): self.turnRight = False def handleToonJoined(self, toonId): DistributedPartyTrampolineActivity.notify.debug('handleToonJoined') self.toon = self.getAvatar(toonId) if self.toon != None and not self.toon.isEmpty(): self.oldJumpSquatPlayRate = self.toon.getPlayRate('jump-squat') self.oldJumpLandPlayRate = self.toon.getPlayRate('jump-land') self.toon.setPlayRate(2.5, 'jump-squat') self.toon.setPlayRate(2.0, 'jump-land') self.turnLeft = False self.turnRight = False self.activityFSM.request('Rules') if self.toon.doId != base.localAvatar.doId: taskMgr.add(self.remoteUpdateTask, self.uniqueName('TrampolineActivity.remoteUpdateTask')) else: self.notify.warning('handleToonJoined could not get toon %d' % toonId) return def handleToonExited(self, toonId): DistributedPartyTrampolineActivity.notify.debug('handleToonExited') if self.toon != None: if self.toon.doId != base.localAvatar.doId: taskMgr.remove(self.uniqueName('TrampolineActivity.remoteUpdateTask')) self.surface.setZ(self.trampHeight) self.toon.setPlayRate(self.oldJumpSquatPlayRate, 'jump-squat') self.toon.setPlayRate(self.oldJumpLandPlayRate, 'jump-land') self.toon = None return def handleToonDisabled(self, toonId): DistributedPartyTrampolineActivity.notify.debug('handleToonDisabled') DistributedPartyTrampolineActivity.notify.debug('avatar ' + str(toonId) + ' disabled') if base.localAvatar.doId == toonId: self.releaseToon() def handleRulesDone(self): self.sendUpdate('toonReady') self.finishRules() def getTitle(self): if self.doJellyBeans: return TTLocalizer.PartyTrampolineJellyBeanTitle elif self.doTricks: return TTLocalizer.PartyTrampolineTricksTitle else: return DistributedPartyActivity.getTitle(self) def getInstructions(self): return TTLocalizer.PartyTrampolineActivityInstructions def updateTask(self, task): z = self.toon.getZ() dt = globalClock.getDt() if self.doSimulateStep: self.timeLeftToSimulate += dt while self.timeLeftToSimulate >= self.stepDT: z, a = self.simulateStep(z) self.timeLeftToSimulate -= self.stepDT self.toon.setZ(z) if z <= self.trampHeight: self.surface.setZ(z) else: self.surface.setZ(self.trampHeight) self.toonIndicator.setZ((z - self.trampHeight) * self.indicatorFactor) if self.turnLeft: self.toon.setH(self.toon.getH() + self.turnFactor * dt) if self.turnRight: self.toon.setH(self.toon.getH() - self.turnFactor * dt) currentPos = base.camera.getPos(self.toon) vec = self.targetCameraPos - currentPos newPos = currentPos + vec * (dt * self.cameraSpeed) base.camera.setPos(self.toon, newPos) base.camera.lookAt(self.toon) if z > self.trampHeight: heightFactor = 1.0 - min(1.0, (z - self.trampHeight) / self.dropShadowCutoff) self.toon.dropShadow.setAlphaScale(heightFactor) self.toon.dropShadow.setScale(max(0.1, heightFactor)) else: self.toon.dropShadow.setAlphaScale(1.0) self.toon.dropShadow.setScale(1.0) if self.leavingTrampoline and z < self.trampHeight and abs(a) < 0.1: self.releaseToon() return Task.cont def simulateStep(self, z): if z >= self.trampHeight: a = self.g self.toonJumped = False else: a = self.g + self.trampK * (self.trampHeight - z) - self.trampB * self.toonVelocity if self.toonJumped: if self.lastPeak > self.earlyJumpThreshold or self.toonVelocity >= -300000.0: a += self.jumpBoost if self.lastPeak < self.beginningBoostThreshold: a += self.beginningBoost lastVelocity = self.toonVelocity self.toonVelocity += a * self.stepDT if lastVelocity > 0.0 and self.toonVelocity <= 0.0: topOfJump = True bottomOfJump = False elif lastVelocity < 0.0 and self.toonVelocity >= 0.0: topOfJump = False bottomOfJump = True else: topOfJump = False bottomOfJump = False newZ = z + self.toonVelocity * self.stepDT if newZ > self.topHeight: self.topHeight = newZ if self.doJellyBeans: self.collectJellyBeans(newZ) if topOfJump: self.lastPeak = newZ if newZ >= self.minHeightForText: self.heightTextInterval.start() if topOfJump: if newZ > self.trampHeight + 20.0: self.b_requestAnim('Falling') elif self.animFSM.state == 'Jump': self.b_requestAnim('Falling') if newZ <= self.trampHeight and z > self.trampHeight: if self.animFSM.state == 'Falling': self.b_requestAnim('Land') elif self.animFSM.state != 'Neutral': self.b_requestAnim('Neutral') if bottomOfJump and a > self.boingThreshold: base.playSfx(self.boingSound) return (newZ, a) def collectJellyBeans(self, z): beansToRemove = [] for i in self.beansToCollect: height = self.beanDetails[i][0] if height <= z: beansToRemove.append(i) if len(beansToRemove) > 0: base.playSfx(self.jellyBeanSound) self.numBeansCollected += len(beansToRemove) self.b_removeBeans(beansToRemove) def remoteUpdateTask(self, task): if self.toon != None and not self.toon.isEmpty(): z = self.toon.getZ() if z <= self.trampHeight: self.surface.setZ(z) else: self.surface.setZ(self.trampHeight) return Task.cont def poofBean(self, bean, beanAnim): if bean == None: self.notify.warning('poofBean, returning immediately as bean is None') return if bean.isEmpty(): self.notify.warning('poofBean, returning immediately as bean is empty') return currentAlpha = bean.getColorScale()[3] currentScale = bean.getScale() poofAnim = Sequence(Parallel(LerpFunc(bean.setAlphaScale, fromData=currentAlpha, toData=0.0, duration=0.25), LerpFunc(bean.setScale, fromData=currentScale, toData=currentScale * 5.0, duration=0.25)), Func(bean.stash), Func(beanAnim.finish), Func(bean.setAlphaScale, currentAlpha), Func(bean.setScale, currentScale)) poofAnim.start() return def _showFlashMessage(self, message): if self.isDisabled(): return if self.flashTextInterval is not None and self.flashTextInterval.isPlaying(): self.flashTextInterval.finish() self.flashText.setText(message) self.flashText.setAlphaScale(1.0) self.flashText.unstash() return def _hideFlashMessage(self, duration = 0.0): if self.isDisabled(): pass self.flashTextInterval = Sequence(Wait(duration), LerpFunc(self.flashText.setAlphaScale, fromData=1.0, toData=0.0, duration=1.0), Func(self.flashText.stash)) self.flashTextInterval.start() def flashMessage(self, message, duration = 0.5): self._showFlashMessage(message) self._hideFlashMessage(duration)