def _loadAndBuildMazeModel(self, flatten = False): self.getMazeData() self._model = NodePath('CogdoMazeModel') levelModel = CogdoUtil.loadMazeModel('level') self.quadrants = [] quadrantUnitSize = int(self.quadrantSize * self.cellWidth) frameActualSize = self.frameWallThickness * self.cellWidth size = quadrantUnitSize + frameActualSize halfWidth = int(self.width / 2) halfHeight = int(self.height / 2) i = 0 for y in range(self.height): for x in range(self.width): ax = (x - halfWidth) * size ay = (y - halfHeight) * size extension = '' if hasattr(getBase(), 'air'): extension = '.bam' filepath = self.quadrantData[i][0] + extension angle = self.quadrantData[i][2] m = self._createQuadrant(filepath, i, angle, quadrantUnitSize) m.setPos(ax, ay, 0) m.reparentTo(self._model) self.quadrants.append(m) i += 1 quadrantHalfUnitSize = quadrantUnitSize * 0.5 barrierModel = CogdoUtil.loadMazeModel('grouping_blockerDivider').find('**/divider') y = 3 for x in range(self.width): if x == (self.width - 1) / 2: continue ax = (x - halfWidth) * size ay = (y - halfHeight) * size - quadrantHalfUnitSize - (self.cellWidth - 0.5) b = NodePath('barrier') barrierModel.instanceTo(b) b.setPos(ax, ay, 0) b.reparentTo(self._model) offset = self.cellWidth - 0.5 for x in (0, 3): for y in range(self.height): ax = (x - halfWidth) * size - quadrantHalfUnitSize - frameActualSize + offset ay = (y - halfHeight) * size b = NodePath('barrier') barrierModel.instanceTo(b) b.setPos(ax, ay, 0) b.setH(90) b.reparentTo(self._model) offset -= 2.0 barrierModel.removeNode() levelModel.getChildren().reparentTo(self._model) for np in self._model.findAllMatches('**/*lightCone*'): CogdoUtil.initializeLightCone(np, 'fixed', 3) if flatten: self._model.flattenStrong() return self._model
def _loadAndBuildMazeModel(self, flatten = False): self.getMazeData() self._model = NodePath('CogdoMazeModel') levelModel = CogdoUtil.loadMazeModel('level') self.quadrants = [] quadrantUnitSize = int(self.quadrantSize * self.cellWidth) frameActualSize = self.frameWallThickness * self.cellWidth size = quadrantUnitSize + frameActualSize halfWidth = int(self.width / 2) halfHeight = int(self.height / 2) i = 0 for y in range(self.height): for x in range(self.width): ax = (x - halfWidth) * size ay = (y - halfHeight) * size extension = '' if hasattr(getBase(), 'air'): extension = '.bam' filepath = self.quadrantData[i][0] + extension angle = self.quadrantData[i][2] m = self._createQuadrant(filepath, i, angle, quadrantUnitSize) m.setPos(ax, ay, 0) m.reparentTo(self._model) self.quadrants.append(m) i += 1 quadrantHalfUnitSize = quadrantUnitSize * 0.5 barrierModel = CogdoUtil.loadMazeModel('grouping_blockerDivider').find('**/divider') y = 3 for x in range(self.width): if x == (self.width - 1) / 2: continue ax = (x - halfWidth) * size ay = (y - halfHeight) * size - quadrantHalfUnitSize - (self.cellWidth - 0.5) b = NodePath('barrier') barrierModel.instanceTo(b) b.setPos(ax, ay, 0) b.reparentTo(self._model) offset = self.cellWidth - 0.5 for x in (0, 3): for y in range(self.height): ax = (x - halfWidth) * size - quadrantHalfUnitSize - frameActualSize + offset ay = (y - halfHeight) * size b = NodePath('barrier') barrierModel.instanceTo(b) b.setPos(ax, ay, 0) b.setH(90) b.reparentTo(self._model) offset -= 2.0 barrierModel.removeNode() levelModel.getChildren().reparentTo(self._model) for np in self._model.findAllMatches('**/*lightCone*'): CogdoUtil.initializeLightCone(np, 'fixed', 3) if flatten: self._model.flattenStrong() return self._model
def test_blocks(self): store = DNAStorage() block1 = ( 4269, # block_number "libpandadna", # title "", # article "", # bldg_type 1337 # zone_id ) block2 = ( 1337, # block_number "Visual Studio 2010", # title "", # article "", # bldg_type 4269 # zone_id ) block3 = ( 1000, # block_number "C++ reader", # title "", # article "", # bldg_type 4269 # zone_id ) store.storeBlock(*block1) store.storeBlock(*block2) store.storeBlock(*block3) door1 = NodePath('block-1000') door1.setPos(5, 5, 10) door1.setH(180) store.storeBlockDoor(1000, door1) self.assertEqual(store.getNumBlockNumbers(), 3) # Test an invalid block number self.assertEqual(store.getZoneFromBlockNumber(100), 0) self.assertEqual(store.getZoneFromBlockNumber(1000), 4269) self.assertEqual(store.getZoneFromBlockNumber(1337), 4269) self.assertEqual(store.getZoneFromBlockNumber(4269), 1337) self.assertEqual(store.getTitleFromBlockNumber(1000), "C++ reader") self.assertEqual(store.getTitleFromBlockNumber(1337), "Visual Studio 2010") self.assertEqual(store.getTitleFromBlockNumber(4269), "libpandadna") self.assertEqual(store.getBlockNumberAt(0), 4269) self.assertEqual(store.getBlockNumberAt(1), 1337) self.assertEqual(store.getBlockNumberAt(2), 1000) self.assertEqual(store.getDoorPosHprFromBlockNumber(1000), door1) self.assertTrue(store.getDoorPosHprFromBlockNumber(1337).isEmpty()) store.resetBlockNumbers() store.resetBlockZones() self.assertEqual(store.getTitleFromBlockNumber(1000), "") self.assertEqual(store.getTitleFromBlockNumber(1337), "") self.assertEqual(store.getTitleFromBlockNumber(4269), "")
def test_blocks(self): store = DNAStorage() block1 = ( 4269, # block_number "libpandadna", # title "", # article "", # bldg_type 1337 # zone_id ) block2 = ( 1337, # block_number "Visual Studio 2010", # title "", # article "", # bldg_type 4269 # zone_id ) block3 = ( 1000, # block_number "C++ reader", # title "", # article "", # bldg_type 4269 # zone_id ) store.storeBlock(*block1) store.storeBlock(*block2) store.storeBlock(*block3) door1 = NodePath('block-1000') door1.setPos(5, 5, 10) door1.setH(180) store.storeBlockDoor(1000, door1) self.assertEqual(store.getNumBlockNumbers(), 3) # Test an invalid block number self.assertEqual(store.getZoneFromBlockNumber(100), 0) self.assertEqual(store.getZoneFromBlockNumber(1000), 4269) self.assertEqual(store.getZoneFromBlockNumber(1337), 4269) self.assertEqual(store.getZoneFromBlockNumber(4269), 1337) self.assertEqual(store.getTitleFromBlockNumber(1000), "C++ reader") self.assertEqual(store.getTitleFromBlockNumber(1337), "Visual Studio 2010") self.assertEqual(store.getTitleFromBlockNumber(4269), "libpandadna") self.assertEqual(store.getBlockNumberAt(0), 4269) self.assertEqual(store.getBlockNumberAt(1), 1337) self.assertEqual(store.getBlockNumberAt(2), 1000) self.assertEqual(store.getDoorPosHprFromBlockNumber(1000), door1) self.assertTrue(store.getDoorPosHprFromBlockNumber(1337).isEmpty()) store.resetBlockNumbers() store.resetBlockZones() self.assertEqual(store.getTitleFromBlockNumber(1000), "") self.assertEqual(store.getTitleFromBlockNumber(1337), "") self.assertEqual(store.getTitleFromBlockNumber(4269), "")
def setupFoodNodes(self): for i in xrange(self.NumFoodNodes): newPosIndex = self.NumFoodNodes - 1 - i yPos = -(self.beltLength / 2.0) + newPosIndex * self.distBetweenFoodNodes newFoodNode = NodePath('foodNode-%d-%d' % (self.index, i)) newFoodNode.reparentTo(self.beltModel) newFoodNode.setPos(0, yPos, self.beltHeight) debugFood = None if debugFood: debugFood.setScale(0.10000000000000001) debugFood.reparentTo(newFoodNode) newFoodNode.setH(180) self.foodNodes.append(newFoodNode)
def setupFoodNodes(self): for i in xrange(self.NumFoodNodes): newPosIndex = self.NumFoodNodes - 1 - i yPos = -(self.beltLength / 2.0) + newPosIndex * self.distBetweenFoodNodes newFoodNode = NodePath('foodNode-%d-%d' % (self.index, i)) newFoodNode.reparentTo(self.beltModel) newFoodNode.setPos(0, yPos, self.beltHeight) debugFood = None if debugFood: debugFood.setScale(0.1) debugFood.reparentTo(newFoodNode) newFoodNode.setH(180) self.foodNodes.append(newFoodNode)
def setupFoodNodes(self): """Create the node paths the food will be parented to.""" assert self.notify.debugStateCall(self) # we may later just load this from the belt model for i in xrange(self.NumFoodNodes): # we want index 0 to be the first one out newPosIndex = self.NumFoodNodes - 1 - i yPos = -(self.beltLength / 2.0) + (newPosIndex * self.distBetweenFoodNodes) newFoodNode = NodePath('foodNode-%d-%d' % (self.index, i)) newFoodNode.reparentTo(self.beltModel) newFoodNode.setPos(0, yPos, self.beltHeight) debugFood = None # loader.loadModel('models/misc/xyzAxis') if debugFood: debugFood.setScale(0.1) debugFood.reparentTo(newFoodNode) # to make the front side of the cans come out of the belt newFoodNode.setH(180) self.foodNodes.append(newFoodNode)
def load(self): self.arena = loader.loadModel(self.arenaModel) self.arena.reparentTo(self.root) ground = self.arena.find('**/ground') ground.setBin('ground', 1) entranceArrows = self.arena.findAllMatches('**/arrowFlat*') for arrow in entranceArrows: arrow.setBin('ground', 5) self.leftEntranceLocator = self.arena.find('**/leftEntrance_locator') self.rightEntranceLocator = self.arena.find('**/rightEntrance_locator') self.leftExitLocator = self.arena.find('**/leftExit_locator') self.rightExitLocator = self.arena.find('**/rightExit_locator') self.teamCamPosLocators = (self.arena.find('**/team0CamPos_locator'), self.arena.find('**/team1CamPos_locator')) self.teamCamAimLocators = (self.arena.find('**/team0CamAim_locator'), self.arena.find('**/team1CamAim_locator')) leftTeamLocator = NodePath('TeamLocator-%d' % PartyGlobals.TeamActivityTeams.LeftTeam) leftTeamLocator.reparentTo(self.root) leftTeamLocator.setH(90) rightTeamLocator = NodePath('TeamLocator-%d' % PartyGlobals.TeamActivityTeams.RightTeam) rightTeamLocator.reparentTo(self.root) rightTeamLocator.setH(-90) self.teamLocators = (leftTeamLocator, rightTeamLocator) self._lengthBetweenEntrances = self.leftEntranceLocator.getY( ) - self.rightExitLocator.getY() self._skyCollisionsCollection = self.arena.findAllMatches( '**/cogPieArena_sky*_collision') if len(self._skyCollisionsCollection) > 0: self._skyCollisionParent = self._skyCollisionsCollection[ 0].getParent() else: self._skyCollisionParent = self.arena self._wallCollisionsCollection = self.arena.findAllMatches( '**/cogPieArena_wall*_collision') self._arenaFlagGroups = (self.arena.find('**/flagsL_grp'), self.arena.find('**/flagsR_grp')) self._initArenaDoors() self.cogManager = PartyCogManager() self.arrows = [] self.distanceLabels = [] self.teamColors = list(PartyGlobals.CogActivityColors) + [ PartyGlobals.TeamActivityStatusColor ] for i in range(3): start = self.arena.find('**/cog%d_start_locator' % (i + 1)) end = self.arena.find('**/cog%d_end_locator' % (i + 1)) cog = self.cogManager.generateCog(self.arena) cog.setEndPoints(start.getPos(), end.getPos()) arrow1 = StretchingArrow(self.arena, useColor='orange') arrow2 = StretchingArrow(self.arena, useColor='blue') arrow1.setZ(0.1) arrow2.setZ(0.1) self.arrows.append([arrow1, arrow2]) distanceLabel = self.createDistanceLabel(0, self.teamColors[1]) distanceLabel[0].stash() distanceLabel2 = self.createDistanceLabel(0, self.teamColors[0]) distanceLabel2[0].stash() self.distanceLabels.append([distanceLabel, distanceLabel2]) self.winText = [] text1 = self.createText(0, Point3(-0.5, 0.0, -0.5), self.teamColors[1]) text2 = self.createText(1, Point3(0.5, 0.0, -0.5), self.teamColors[0]) self.winText.append(text1) self.winText.append(text2) self.winStatus = self.createText(2, Point3(0.0, 0.0, -0.8), self.teamColors[0]) signLocator = self.arena.find('**/eventSign_locator') self.activity.sign.setPos(signLocator.getPos(self.root)) if self.texture: textureAlpha = self.texture[:-4] + '_a.rgb' reskinTexture = loader.loadTexture(self.texture, textureAlpha) self.arena.find('**/center_grp').setTexture(reskinTexture, 100) self.arena.find('**/leftSide_grp').setTexture(reskinTexture, 100) self.arena.find('**/rightSide_grp').setTexture(reskinTexture, 100) self.enable()
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)
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
class PlaneView(FSM, DirectObject): """Give this class a plane as argument and it will create some nodes around it which you can parent the camera to (if there are no such nodes yet). Usage: plane_camera = PlaneCamera(aeroplane, camera) plane_camera.setView("ThirdPerson") plane_camera.setView("Next") """ def __init__(self, camera, parent): """Arguments: camera -- Camera to be used parent -- Aeroplane which the camera should follow """ self.notifier = DirectNotify().newCategory("azure-camera") self.camera = camera self.parent = parent # This gets replaced by a NodePath with all available cameras as # children and plane node as parent in createCamNodes() self.cameras = None #if parent.__class__.__name__ is not "Aeroplane": if not isinstance(self.parent, Aeroplane): raise ParamError, "Parent must be an Aeroplane instance, " + \ "but is %s" % type(self.parent) FSM.__init__(self, "PlaneCamera: %s" % self.parent.name) DirectObject.__init__(self) self.cameras = self.parent.node.find("cameras") if self.cameras.isEmpty(): self.createCamNodes() self.updateCamArray() self.sideview_direction = 0 # Set up the default camera self.setView("ThirdPerson") def createCamNodes(self): """Creates a few empty nodes around a plane which the camera might be parented to. It looks if there are cameras inside the model file and uses those if possible. Where everything named "camera CamType" is considered a camera. At least ThirdPerson, FirstPerson and Cockpit should be defined inside the egg file, otherwise some guessed defaults are taken. """ # Look for cameras inside the model (loaded egg file) self.cameras = NodePath("cameras") found_cams = self.parent.node.findAllMatches("**/camera ?*") found_cams.removeDuplicatePaths() found_cams.reparentTo(self.cameras) if not found_cams.isEmpty(): self.notifier.info("Cameras found under model:\n%s" % found_cams) else: self.notifier.info("No cameras found under model.") # FirstPerson camera is a must-have. Set up a guessed one if none # defined yet. if self.cameras.find("camera FirstPerson").isEmpty(): assert self.notifier.debug("No first person camera found in %s. " "Guessing best position." % self.parent.name) first_person = NodePath("camera FirstPerson") # TODO: Guess best position based on bounding box. first_person.setY(5) first_person.reparentTo(cameras) # ThirdPerson camera is a must-have. Set up a guessed one if none # defined yet. if self.cameras.find("camera ThirdPerson").isEmpty(): assert self.notifier.debug("No third person camera found in %s. " "Guessing best position." % self.parent.name) third_person = NodePath("camera ThirdPerson") # TODO: Guess best position based on bounding box. third_person.setPos(0, -30, 5) #third_person.setP(-80) third_person.reparentTo(cameras) # Cockpit needs to be accurate. Don't try to guess it. if self.cameras.find("camera Cockpit").isEmpty(): assert self.notifier.debug("No cockpit camera found in " "%s. Cockpit camera disabled." % self.parent.name) self.sideview_cam = NodePath("camera Sideview") self.sideview_cam.reparentTo(render) # Store the cams at parent node.. # You can edit the camera nodes from outside as well. # If you attach new camera nodes, though, you'll have to call this # function again. self.cameras.reparentTo(self.parent.node) def updateCamArray(self, cameramodes=None): """Set the cameras which next and previous will switch to. Expects a list or tuple. Defaults to all available cameras.""" a = [] if not cameramodes: for c in self.cameras.getChildren(): if c.getName().startswith("camera "): a.append(c.getName().strip("camera ")) self.setStateArray(a) else: self.setStateArray(cameramodes) def getView(self): """Returns the current view mode.""" return self.getCurrentOrNextState() def setView(self, mode, *args): """Convenience function.""" return self.request(mode, args) def defaultEnter(self, *args): """Executed by the FSM every time an undefined state is entered. Note: this function is called AFTER the responsible filter.""" assert self.notifier.debug("Changing state from %s to %s with args: %s." % (self.oldState, self.newState, args)) request = self.newState target_cam = self.cameras.find("camera " + request) if not target_cam.isEmpty(): try: self.camera.reparentTo(target_cam) self.camera.setPosHpr(0, 0, 0, 0, 0, 0) except: self.notifier.warning( "Ok, now this really shouldn't happen! Filter said the " "camera is there and enter can't find it...") def defaultFilter(self, request, args): """Executed by the FSM every time an undefined state is requested.""" assert self.notifier.debug("Requested %s with args: %s" % (request, args)) self.camera.setPosHpr(0, 0, 0, 0, 0, 0) # Always available. if request == "Off": # implemented in FSM.py return (request,) + args if request == "Next": # implemented in FSM.py return self.requestNext(args) if request == "Prev": # implemented in FSM.py return self.requestPrev(args) if request == "Detached": return (request,) + args if request == "Sideview": return (request,) + args # Depending on airplane. if not self.cameras.find("camera " + request).isEmpty(): return (request,) + args assert self.notifier.info("Sorry, no %s camera found." % request) return None def enterOff(self, *args): """Clean up everything by reparenting the camera to the airplane.""" self.camera.reparentTo(self.parent.node) self.camera.setPosHpr(0, 0, 0, 0, 0, 0) def enterSideview(self, *args): self.sideview_direction += 90 self.camera.reparentTo(self.sideview_cam) self.camera.setY(-30) self.sideview_cam.setH(self.sideview_direction) #self.addTask(self.updateSideview, "sideview camera", taskChain="world") self.task = self.updateSideview def exitSideview(self, *args): #self.removeTask("sideview camera") self.task = lambda x: Task.cont def updateSideview(self, task): self.sideview_cam.setPos(self.parent.node.getPos()) return Task.cont def enterDetached(self, *args): """Lets the camera view the plane from far away.""" self.camera.reparentTo(render) self.camera.setPosHpr(0, 0, 10, 0, 0, 0) #self.addTask(self.updateDetachedCam, "detached camera", # taskChain="world") self.task = self.updateDetachedCam def exitDetached(self, *args): #self.removeTask("detached camera") self.task = lambda x: Task.cont def updateDetachedCam(self, task): """Updates camera position and rotation for Detached camera.""" try: self.camera.lookAt(self.parent.node) except: self.notifier.warning("Error on detached cam task. Exit.") return Task.done return Task.cont def enterThirdPerson(self, *args): """Lets the camera view the plane from far away.""" self._hist = [] self.camera.reparentTo(self.cameras.find("camera ThirdPerson")) self.cameras.find("camera ThirdPerson").setPos(0, -30, 0) #self.addTask(self.updateThirdPersonCam, "third person camera", # taskChain="world") self.task = self.updateThirdPersonCam #print "entering third person" def exitThirdPerson(self, *args): #self.removeTask("third person camera") self.task = lambda x: Task.cont del self._hist def updateThirdPersonCam(self, task): """Updates camera position and rotation for ThirdPerson camera.""" speed = self.parent.physics.speed() velocity = self.parent.physics.velocity() #v = Point3(self.parent.physics.angVelVector()) v = Point3(self.parent.physics.angVelBodyHpr()) print round(v.getX(), 2), round(v.getY(), 2), round(v.getZ(), 2) #self.segs = LineSegs("lines"); #self.segs.setColor(1,1,1,1) #self.segs.drawTo(-1, 0) #self.segsnode = self.segs.create() #render2d.attachNewNode(self.segsnode) vec = Point3(self.parent.physics.angVelBodyHpr()) # Y hiervon ist pitch, Z ist roll #print round(vec.getY(), 2), round(vec.getZ(), 2) self.camera.lookAt(self.parent.node) self.camera.setR(self.camera, vec.getZ()*3) #self.camera.setPos(abs(v.getX()), 0, vec.getY()) #plane = self.parent.node #self._hist.insert(0, [task.time, camera.getPos(plane)]) #while len(self._hist) > 50: # self._hist.pop() # #for snapshot in self._hist: # if snapshot[0] > task.time: # break #time_delta = snapshot[0] - task.time #self.camera.setPos(plane, snapshot[1]) #print snapshot #self.camera.setPos(render, snapshot[1]) #self.camera.lookAt(plane, (0, 20+1*speed, 0)) #self.camera.setY(5+0.1*speed) #self.camera.setZ(5-0.1*speed) return Task.cont def update(self, task): return self.task(task) def destroy(self): self.removeAllTasks() self.demand("Off")
def generateHullCache(modelClass): geom = loader.loadModel('models/shipparts/pir_m_shp_%s' % HullDict[modelClass]) stripPrefix(geom, 'model:') for node in geom.findAllMatches('**/omit'): parent = node.getParent() omit = parent.attachNewNode(ModelNode('omit')) node.reparentTo(omit) node.setName('geom') preFlatten(geom) logic = loader.loadModel('models/shipparts/pir_m_shp_%s_logic' % HullDict[modelClass]) locators = logic.find('**/locators') for side in [ 'left', 'right']: bad = locators.find('**/location_ropeLadder_0_%s' % side) if bad: bad.setName('location_ropeLadder_%s_0' % side) bad = locators.find('**/location_ropeLadder_1_%s' % side) if bad: bad.setName('location_ropeLadder_%s_1' % side) bad = locators.find('**/location_ropeLadder_1_%s1' % side) if bad: bad.setName('location_ropeLadder_%s_2' % side) continue collisions = logic.find('**/collisions') badPanel = collisions.find('**/collision_panel_3') if badPanel: badPanel.setName('collision_panel_2') collisions.find('**/collision_panel_0').setTag('Hull Code', '0') collisions.find('**/collision_panel_1').setTag('Hull Code', '1') collisions.find('**/collision_panel_2').setTag('Hull Code', '2') walls = collisions.find('**/collision_walls') if walls: walls.setTag('Hull Code', '255') else: collisions.attachNewNode('collision_walls') shipToShipCollide = collisions.find('**/collision_shiptoship') shipToShipCollide.setCollideMask(PiratesGlobals.ShipCollideBitmask) deck = collisions.find('**/collision_deck') if not deck: deck = collisions.attachNewNode('deck') mask = deck.getCollideMask() mask ^= PiratesGlobals.FloorBitmask mask |= PiratesGlobals.ShipFloorBitmask deck.setCollideMask(mask) floors = collisions.find('**/collision_floors') if not floors: floors = collisions.find('**/collision_floor') mask = floors.getCollideMask() mask ^= PiratesGlobals.FloorBitmask mask |= PiratesGlobals.ShipFloorBitmask floors.setCollideMask(mask) floors.setTag('Hull Code', str(255)) geomHigh = geom.find('**/lod_high') geomMed = geom.find('**/lod_medium') if not geomMed: geomMed = geom.find('**/low_medium') if not geomMed: geomMed = geomHigh.copyTo(NodePath()) geomLow = geom.find('**/lod_low') if not geomLow: geomLow = geomMed.copyTo(NodePath()) geomSuperLow = geom.find('**/lod_superlow') if not geomSuperLow: geomSuperLow = geomLow.copyTo(NodePath()) geomHigh.setName('high') geomMed.setName('med') geomLow.setName('low') geomSuperLow.setName('superlow') if modelClass in [ 21, 22, 23]: spike = loader.loadModel('models/shipparts/pir_m_shp_ram_spike') spikeTrans = locators.find('**/location_ram').getTransform(locators) spike.setTransform(spikeTrans) spike.flattenLight() spikeHi = spike.find('**/lod_high') spikeMed = spike.find('**/lod_medium') spikeLow = spike.find('**/lod_low') spikeHi.copyTo(geomHigh) spikeMed.copyTo(geomMed) spikeLow.copyTo(geomLow) spikeLow.copyTo(geomSuperLow) flipRoot = NodePath('root') collisions.reparentTo(flipRoot) locators.reparentTo(flipRoot) geomHigh.reparentTo(flipRoot) geomMed.reparentTo(flipRoot) geomLow.reparentTo(flipRoot) geomSuperLow.reparentTo(flipRoot) flipRoot.setH(180) flipRoot.flattenLight() omits = flipRoot.findAllMatches('**/omit') for node in omits: node.flattenStrong() for group in [ 'static', 'transparent', 'ropeLadder_*', 'stripeA', 'stripeB', 'pattern']: for node in flipRoot.findAllMatches('**/%s' % group): name = node.getName() for subNode in node.findAllMatches('**/*'): subNode.setName(name) node.flattenStrong() node.setName(name) geomHigh.detachNode() geomMed.detachNode() geomLow.detachNode() geomSuperLow.detachNode() locators.detachNode() collisions.detachNode() genericGeoms = [ geomHigh, geomMed, geomLow, geomSuperLow] customGeoms = [ x.copyTo(NodePath()) for x in genericGeoms ] for np in genericGeoms: trans = np.find('**/transparent') if trans: trans.stash() np.flattenLight() sails = np.findAllMatches('**/sails') sails.stash() omits = np.findAllMatches('**/omit') omits.stash() for node in omits: node.node().setPreserveTransform(node.node().PTDropNode) generic = NodePath('generic') np.findAllMatches('**/+GeomNode').wrtReparentTo(generic) np.findAllMatches('*').detach() generic.flattenStrong() generic.reparentTo(np) stripAttribs(generic, TextureAttrib) collapse(generic) sails.unstash() sails.reparentTo(np) for node in sails: node.node().setPreserveTransform(node.node().PTDropNode) if trans: trans.unstash() trans.flattenStrong() if trans.node().isOfType(ModelNode.getClassType()): trans.node().setPreserveTransform(ModelNode.PTDropNode) deck = np.find('**/=cam=shground') if deck: deck.setName('deck') omits.unstash() for np in customGeoms: collapse(np.find('**/static')) data = HullCache() data.root = NodePath('hull') data.genericGeoms = genericGeoms data.customGeoms = customGeoms data.collisions = collisions data.locators = locators return data
def load(self): self.arena = loader.loadModel("phase_13/models/parties/cogPieArena_model") self.arena.reparentTo(self.root) ground = self.arena.find("**/ground") # Make the ground plane draw before the shadow! ground.setBin("ground", 1) entranceArrows = self.arena.findAllMatches("**/arrowFlat*") for arrow in entranceArrows: arrow.setBin("ground", 5) # Get Entrance/Exit Locations self.leftEntranceLocator = self.arena.find("**/leftEntrance_locator") self.rightEntranceLocator = self.arena.find("**/rightEntrance_locator") self.leftExitLocator = self.arena.find("**/leftExit_locator") self.rightExitLocator = self.arena.find("**/rightExit_locator") self.teamCamPosLocators = ( self.arena.find("**/team0CamPos_locator"), self.arena.find("**/team1CamPos_locator") ) self.teamCamAimLocators = ( self.arena.find("**/team0CamAim_locator"), self.arena.find("**/team1CamAim_locator"), ) # Setup team locators # Toons are parented to these guys in order to do # Orthowalk properly leftTeamLocator = NodePath("TeamLocator-%d" % PartyGlobals.TeamActivityTeams.LeftTeam) leftTeamLocator.reparentTo(self.root) leftTeamLocator.setH(90) rightTeamLocator = NodePath("TeamLocator-%d" % PartyGlobals.TeamActivityTeams.RightTeam) rightTeamLocator.reparentTo(self.root) rightTeamLocator.setH(-90) self.teamLocators = ( leftTeamLocator, rightTeamLocator ) # Used to place the toons in even spaces self._lengthBetweenEntrances = self.leftEntranceLocator.getY() - self.rightExitLocator.getY() # Setup Sky Collisions. Important for cannons. self._skyCollisionsCollection = self.arena.findAllMatches("**/cogPieArena_sky*_collision") if len(self._skyCollisionsCollection) > 0: self._skyCollisionParent = self._skyCollisionsCollection[0].getParent() else: self._skyCollisionParent = self.arena # Get all the wall collisions: self._wallCollisionsCollection = self.arena.findAllMatches("**/cogPieArena_wall*_collision") # Get a hold of the flags: self._arenaFlagGroups = ( self.arena.find("**/flagsL_grp"), self.arena.find("**/flagsR_grp") ) self._initArenaDoors() # Setup Cogs self.cogManager = PartyCogManager() self.arrows = [] self.distanceLabels = [] self.teamColors = list(PartyGlobals.CogActivityColors) + [PartyGlobals.TeamActivityStatusColor] for i in range(3): start = self.arena.find("**/cog%d_start_locator" % (i+1)) end = self.arena.find("**/cog%d_end_locator" % (i+1)) cog = self.cogManager.generateCog(self.arena) cog.setEndPoints(start.getPos(), end.getPos()) arrow1 = StretchingArrow(self.arena, useColor="orange") arrow2 = StretchingArrow(self.arena, useColor="blue") arrow1.setZ(0.1) arrow2.setZ(0.1) self.arrows.append([arrow1, arrow2]) distanceLabel = self.createDistanceLabel(0, self.teamColors[1]) distanceLabel[0].stash() distanceLabel2 = self.createDistanceLabel(0, self.teamColors[0]) distanceLabel2[0].stash() self.distanceLabels.append([distanceLabel, distanceLabel2]) self.winText = [] text1 = self.createText(0, Point3(-0.5,0.0,-0.5), self.teamColors[1]) text2 = self.createText(1, Point3(0.5,0.0,-0.5), self.teamColors[0]) self.winText.append(text1) self.winText.append(text2) self.winStatus = self.createText(2, Point3(0.0,0.0,-0.8), self.teamColors[0]) signLocator = self.arena.find("**/eventSign_locator") self.activity.sign.setPos(signLocator.getPos(self.root)) self.enable()
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 DistributedIceGame(DistributedMinigame.DistributedMinigame, DistributedIceWorld.DistributedIceWorld): notify = directNotify.newCategory("DistributedIceGame") MaxLocalForce = 100 MaxPhysicsForce = 25000 def __init__(self, cr): DistributedMinigame.DistributedMinigame.__init__(self, cr) DistributedIceWorld.DistributedIceWorld.__init__(self, cr) self.gameFSM = ClassicFSM.ClassicFSM( "DistributedIceGame", [ State.State("off", self.enterOff, self.exitOff, ["inputChoice"]), State.State( "inputChoice", self.enterInputChoice, self.exitInputChoice, ["waitServerChoices", "moveTires", "displayVotes", "cleanup"], ), State.State( "waitServerChoices", self.enterWaitServerChoices, self.exitWaitServerChoices, ["moveTires", "cleanup"], ), State.State("moveTires", self.enterMoveTires, self.exitMoveTires, ["synch", "cleanup"]), State.State("synch", self.enterSynch, self.exitSynch, ["inputChoice", "scoring", "cleanup"]), State.State("scoring", self.enterScoring, self.exitScoring, ["cleanup", "finalResults", "inputChoice"]), State.State("finalResults", self.enterFinalResults, self.exitFinalResults, ["cleanup"]), State.State("cleanup", self.enterCleanup, self.exitCleanup, []), ], "off", "cleanup", ) self.addChildGameFSM(self.gameFSM) self.cameraThreeQuarterView = (0, -22, 45, 0, -62.89, 0) self.tireDict = {} self.forceArrowDict = {} self.canDrive = False self.timer = None self.timerStartTime = None self.curForce = 0 self.curHeading = 0 self.headingMomentum = 0.0 self.forceMomentum = 0.0 self.allTireInputs = None self.curRound = 0 self.curMatch = 0 self.controlKeyWarningLabel = DirectLabel( text=TTLocalizer.IceGameControlKeyWarning, text_fg=VBase4(1, 0, 0, 1), relief=None, pos=(0.0, 0, 0), scale=0.15, ) self.controlKeyWarningLabel.hide() self.waitingMoveLabel = DirectLabel( text=TTLocalizer.IceGameWaitingForPlayersToFinishMove, text_fg=VBase4(1, 1, 1, 1), relief=None, pos=(-0.6, 0, -0.75), scale=0.075, ) self.waitingMoveLabel.hide() self.waitingSyncLabel = DirectLabel( text=TTLocalizer.IceGameWaitingForAISync, text_fg=VBase4(1, 1, 1, 1), relief=None, pos=(-0.6, 0, -0.75), scale=0.075, ) self.waitingSyncLabel.hide() self.infoLabel = DirectLabel(text="", text_fg=VBase4(0, 0, 0, 1), relief=None, pos=(0.0, 0, 0.7), scale=0.075) self.updateInfoLabel() self.lastForceArrowUpdateTime = 0 self.sendForceArrowUpdateAsap = False self.treasures = [] self.penalties = [] self.obstacles = [] self.controlKeyPressed = False self.controlKeyWarningIval = None return def delete(self): DistributedIceWorld.DistributedIceWorld.delete(self) DistributedMinigame.DistributedMinigame.delete(self) if self.controlKeyWarningIval: self.controlKeyWarningIval.finish() self.controlKeyWarningIval = None self.controlKeyWarningLabel.destroy() del self.controlKeyWarningLabel self.waitingMoveLabel.destroy() del self.waitingMoveLabel self.waitingSyncLabel.destroy() del self.waitingSyncLabel self.infoLabel.destroy() del self.infoLabel for treasure in self.treasures: treasure.destroy() del self.treasures for penalty in self.penalties: penalty.destroy() del self.penalties for obstacle in self.obstacles: obstacle.removeNode() del self.obstacles del self.gameFSM return def announceGenerate(self): DistributedMinigame.DistributedMinigame.announceGenerate(self) DistributedIceWorld.DistributedIceWorld.announceGenerate(self) self.debugTaskName = self.uniqueName("debugTask") def getTitle(self): return TTLocalizer.IceGameTitle def getInstructions(self): szId = self.getSafezoneId() numPenalties = IceGameGlobals.NumPenalties[szId] result = TTLocalizer.IceGameInstructions if numPenalties == 0: result = TTLocalizer.IceGameInstructionsNoTnt return result def getMaxDuration(self): return 0 def load(self): self.notify.debug("load") DistributedMinigame.DistributedMinigame.load(self) self.music = base.loadMusic("phase_4/audio/bgm/MG_IceGame.ogg") self.gameBoard = loader.loadModel("phase_4/models/minigames/ice_game_icerink") background = loader.loadModel("phase_4/models/minigames/ice_game_2d") backgroundWide = loader.loadModel("phase_4/models/minigames/iceslide_ground") background.reparentTo(self.gameBoard) backgroundWide.reparentTo(self.gameBoard) backgroundWide.setPos(0, -0.3, -0.5) self.gameBoard.setPosHpr(0, 0, 0, 0, 0, 0) self.gameBoard.setScale(1.0) self.setupSimulation() index = 0 for avId in self.avIdList: self.setupTire(avId, index) self.setupForceArrow(avId) index += 1 for index in xrange(len(self.avIdList), 4): self.setupTire(-index, index) self.setupForceArrow(-index) self.showForceArrows(realPlayersOnly=True) self.westWallModel = NodePath() if not self.westWallModel.isEmpty(): self.westWallModel.reparentTo(self.gameBoard) self.westWallModel.setPos(IceGameGlobals.MinWall[0], IceGameGlobals.MinWall[1], 0) self.westWallModel.setScale(4) self.eastWallModel = NodePath() if not self.eastWallModel.isEmpty(): self.eastWallModel.reparentTo(self.gameBoard) self.eastWallModel.setPos(IceGameGlobals.MaxWall[0], IceGameGlobals.MaxWall[1], 0) self.eastWallModel.setScale(4) self.eastWallModel.setH(180) self.arrowKeys = ArrowKeys.ArrowKeys() self.target = loader.loadModel("phase_3/models/misc/sphere") self.target.setScale(0.01) self.target.reparentTo(self.gameBoard) self.target.setPos(0, 0, 0) self.scoreCircle = loader.loadModel("phase_4/models/minigames/ice_game_score_circle") self.scoreCircle.setScale(0.01) self.scoreCircle.reparentTo(self.gameBoard) self.scoreCircle.setZ(IceGameGlobals.TireRadius / 2.0) self.scoreCircle.setAlphaScale(0.5) self.scoreCircle.setTransparency(1) self.scoreCircle.hide() self.treasureModel = loader.loadModel("phase_4/models/minigames/ice_game_barrel") self.penaltyModel = loader.loadModel("phase_4/models/minigames/ice_game_tnt2") self.penaltyModel.setScale(0.75, 0.75, 0.7) szId = self.getSafezoneId() obstacles = IceGameGlobals.Obstacles[szId] index = 0 cubicObstacle = IceGameGlobals.ObstacleShapes[szId] for pos in obstacles: newPos = Point3(pos[0], pos[1], IceGameGlobals.TireRadius) newObstacle = self.createObstacle(newPos, index, cubicObstacle) self.obstacles.append(newObstacle) index += 1 self.countSound = loader.loadSfx("phase_3.5/audio/sfx/tick_counter.ogg") self.treasureGrabSound = loader.loadSfx("phase_4/audio/sfx/MG_sfx_vine_game_bananas.ogg") self.penaltyGrabSound = loader.loadSfx("phase_4/audio/sfx/MG_cannon_fire_alt.ogg") self.tireSounds = [] for tireIndex in xrange(4): tireHit = loader.loadSfx("phase_4/audio/sfx/Golf_Hit_Barrier_1.ogg") wallHit = loader.loadSfx("phase_4/audio/sfx/MG_maze_pickup.ogg") obstacleHit = loader.loadSfx("phase_4/audio/sfx/Golf_Hit_Barrier_2.ogg") self.tireSounds.append({"tireHit": tireHit, "wallHit": wallHit, "obstacleHit": obstacleHit}) self.arrowRotateSound = loader.loadSfx("phase_4/audio/sfx/MG_sfx_ice_force_rotate.ogg") self.arrowUpSound = loader.loadSfx("phase_4/audio/sfx/MG_sfx_ice_force_increase_3sec.ogg") self.arrowDownSound = loader.loadSfx("phase_4/audio/sfx/MG_sfx_ice_force_decrease_3sec.ogg") self.scoreCircleSound = loader.loadSfx("phase_4/audio/sfx/MG_sfx_ice_scoring_1.ogg") def unload(self): self.notify.debug("unload") DistributedMinigame.DistributedMinigame.unload(self) del self.music self.gameBoard.removeNode() del self.gameBoard for forceArrow in self.forceArrowDict.values(): forceArrow.removeNode() del self.forceArrowDict self.scoreCircle.removeNode() del self.scoreCircle del self.countSound def onstage(self): self.notify.debug("onstage") DistributedMinigame.DistributedMinigame.onstage(self) self.gameBoard.reparentTo(render) self.__placeToon(self.localAvId) self.moveCameraToTop() self.scorePanels = [] base.playMusic(self.music, looping=1, volume=0.8) def offstage(self): self.notify.debug("offstage") self.music.stop() self.gameBoard.hide() self.infoLabel.hide() for avId in self.tireDict: self.tireDict[avId]["tireNodePath"].hide() for panel in self.scorePanels: panel.cleanup() del self.scorePanels for obstacle in self.obstacles: obstacle.hide() for treasure in self.treasures: treasure.nodePath.hide() for penalty in self.penalties: penalty.nodePath.hide() for avId in self.avIdList: av = self.getAvatar(avId) if av: av.dropShadow.show() av.resetLOD() taskMgr.remove(self.uniqueName("aimtask")) self.arrowKeys.destroy() del self.arrowKeys DistributedMinigame.DistributedMinigame.offstage(self) def handleDisabledAvatar(self, avId): self.notify.debug("handleDisabledAvatar") self.notify.debug("avatar " + str(avId) + " disabled") DistributedMinigame.DistributedMinigame.handleDisabledAvatar(self, avId) def setGameReady(self): if not self.hasLocalToon: return self.notify.debug("setGameReady") if DistributedMinigame.DistributedMinigame.setGameReady(self): return for index in xrange(self.numPlayers): avId = self.avIdList[index] toon = self.getAvatar(avId) if toon: toon.reparentTo(render) self.__placeToon(avId) toon.forwardSpeed = 0 toon.rotateSpeed = False toon.dropShadow.hide() toon.setAnimState("Sit") if avId in self.tireDict: tireNp = self.tireDict[avId]["tireNodePath"] toon.reparentTo(tireNp) toon.setY(1.0) toon.setZ(-3) toon.startLookAround() def setGameStart(self, timestamp): if not self.hasLocalToon: return self.notify.debug("setGameStart") DistributedMinigame.DistributedMinigame.setGameStart(self, timestamp) for avId in self.remoteAvIdList: toon = self.getAvatar(avId) if toon: toon.stopLookAround() self.scores = [0] * self.numPlayers spacing = 0.4 for i in xrange(self.numPlayers): avId = self.avIdList[i] avName = self.getAvatarName(avId) scorePanel = MinigameAvatarScorePanel.MinigameAvatarScorePanel(avId, avName) scorePanel.setScale(0.9) scorePanel.setPos(-0.583 - spacing * (self.numPlayers - 1 - i), 0.0, -0.15) scorePanel.reparentTo(base.a2dTopRight) scorePanel.makeTransparent(0.75) self.scorePanels.append(scorePanel) self.arrowKeys.setPressHandlers( [ self.__upArrowPressed, self.__downArrowPressed, self.__leftArrowPressed, self.__rightArrowPressed, self.__controlPressed, ] ) def isInPlayState(self): if not self.gameFSM.getCurrentState(): return False if not self.gameFSM.getCurrentState().getName() == "play": return False return True def enterOff(self): self.notify.debug("enterOff") def exitOff(self): pass def enterInputChoice(self): self.notify.debug("enterInputChoice") self.forceLocalToonToTire() self.controlKeyPressed = False if self.curRound == 0: self.setupStartOfMatch() else: self.notify.debug("self.curRound = %s" % self.curRound) self.timer = ToontownTimer.ToontownTimer() self.timer.hide() if self.timerStartTime != None: self.startTimer() self.showForceArrows(realPlayersOnly=True) self.localForceArrow().setPosHpr(0, 0, -1.0, 0, 0, 0) self.localForceArrow().reparentTo(self.localTireNp()) self.localForceArrow().setY(IceGameGlobals.TireRadius) self.localTireNp().headsUp(self.target) self.notify.debug("self.localForceArrow() heading = %s" % self.localForceArrow().getH()) self.curHeading = self.localTireNp().getH() self.curForce = 25 self.updateLocalForceArrow() for avId in self.forceArrowDict: forceArrow = self.forceArrowDict[avId] forceArrow.setPosHpr(0, 0, -1.0, 0, 0, 0) tireNp = self.tireDict[avId]["tireNodePath"] forceArrow.reparentTo(tireNp) forceArrow.setY(IceGameGlobals.TireRadius) tireNp.headsUp(self.target) self.updateForceArrow(avId, tireNp.getH(), 25) taskMgr.add(self.__aimTask, self.uniqueName("aimtask")) if base.localAvatar.laffMeter: base.localAvatar.laffMeter.stop() self.sendForceArrowUpdateAsap = False return def exitInputChoice(self): if not self.controlKeyPressed: if self.controlKeyWarningIval: self.controlKeyWarningIval.finish() self.controlKeyWarningIval = None self.controlKeyWarningIval = Sequence( Func(self.controlKeyWarningLabel.show), self.controlKeyWarningLabel.colorScaleInterval( 10, VBase4(1, 1, 1, 0), startColorScale=VBase4(1, 1, 1, 1) ), Func(self.controlKeyWarningLabel.hide), ) self.controlKeyWarningIval.start() if self.timer != None: self.timer.destroy() self.timer = None self.timerStartTime = None self.hideForceArrows() self.arrowRotateSound.stop() self.arrowUpSound.stop() self.arrowDownSound.stop() taskMgr.remove(self.uniqueName("aimtask")) return def enterWaitServerChoices(self): self.waitingMoveLabel.show() self.showForceArrows(True) def exitWaitServerChoices(self): self.waitingMoveLabel.hide() self.hideForceArrows() def enterMoveTires(self): for key in self.tireDict: body = self.tireDict[key]["tireBody"] body.setAngularVel(0, 0, 0) body.setLinearVel(0, 0, 0) for index in xrange(len(self.allTireInputs)): input = self.allTireInputs[index] avId = self.avIdList[index] body = self.getTireBody(avId) degs = input[1] + 90 tireNp = self.getTireNp(avId) tireH = tireNp.getH() self.notify.debug("tireH = %s" % tireH) radAngle = deg2Rad(degs) foo = NodePath("foo") dirVector = Vec3(math.cos(radAngle), math.sin(radAngle), 0) self.notify.debug("dirVector is now=%s" % dirVector) inputForce = input[0] inputForce /= self.MaxLocalForce inputForce *= self.MaxPhysicsForce force = dirVector * inputForce self.notify.debug("adding force %s to %d" % (force, avId)) body.addForce(force) self.enableAllTireBodies() self.totalPhysicsSteps = 0 self.startSim() taskMgr.add(self.__moveTiresTask, self.uniqueName("moveTiresTtask")) def exitMoveTires(self): self.forceLocalToonToTire() self.disableAllTireBodies() self.stopSim() self.notify.debug("total Physics steps = %d" % self.totalPhysicsSteps) taskMgr.remove(self.uniqueName("moveTiresTtask")) def enterSynch(self): self.waitingSyncLabel.show() def exitSynch(self): self.waitingSyncLabel.hide() def enterScoring(self): sortedByDistance = [] for avId in self.avIdList: np = self.getTireNp(avId) pos = np.getPos() pos.setZ(0) sortedByDistance.append((avId, pos.length())) def compareDistance(x, y): if x[1] - y[1] > 0: return 1 elif x[1] - y[1] < 0: return -1 else: return 0 sortedByDistance.sort(cmp=compareDistance) self.scoreMovie = Sequence() curScale = 0.01 curTime = 0 self.scoreCircle.setScale(0.01) self.scoreCircle.show() self.notify.debug("newScores = %s" % self.newScores) circleStartTime = 0 for index in xrange(len(sortedByDistance)): distance = sortedByDistance[index][1] avId = sortedByDistance[index][0] scorePanelIndex = self.avIdList.index(avId) time = (distance - curScale) / IceGameGlobals.ExpandFeetPerSec if time < 0: time = 0.01 scaleXY = distance + IceGameGlobals.TireRadius self.notify.debug("circleStartTime = %s" % circleStartTime) self.scoreMovie.append( Parallel( LerpScaleInterval(self.scoreCircle, time, Point3(scaleXY, scaleXY, 1.0)), SoundInterval(self.scoreCircleSound, duration=time, startTime=circleStartTime), ) ) circleStartTime += time startScore = self.scorePanels[scorePanelIndex].getScore() destScore = self.newScores[scorePanelIndex] self.notify.debug("for avId %d, startScore=%d, newScores=%d" % (avId, startScore, destScore)) def increaseScores(t, scorePanelIndex=scorePanelIndex, startScore=startScore, destScore=destScore): oldScore = self.scorePanels[scorePanelIndex].getScore() diff = destScore - startScore newScore = int(startScore + diff * t) if newScore > oldScore: base.playSfx(self.countSound) self.scorePanels[scorePanelIndex].setScore(newScore) self.scores[scorePanelIndex] = newScore duration = (destScore - startScore) * IceGameGlobals.ScoreCountUpRate tireNp = self.tireDict[avId]["tireNodePath"] self.scoreMovie.append( Parallel( LerpFunctionInterval(increaseScores, duration), Sequence( LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 0, 0, 1)), LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 1, 1, 1)), LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 0, 0, 1)), LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 1, 1, 1)), LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 0, 0, 1)), LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 1, 1, 1)), ), ) ) curScale += distance self.scoreMovie.append(Func(self.sendUpdate, "reportScoringMovieDone", [])) self.scoreMovie.start() def exitScoring(self): self.scoreMovie.finish() self.scoreMovie = None self.scoreCircle.hide() return def enterFinalResults(self): lerpTrack = Parallel() lerpDur = 0.5 tY = 0.6 bY = -0.05 lX = -0.5 cX = 0 rX = 0.5 scorePanelLocs = ( ((cX, bY),), ((lX, bY), (rX, bY)), ((cX, tY), (lX, bY), (rX, bY)), ((lX, tY), (rX, tY), (lX, bY), (rX, bY)), ) scorePanelLocs = scorePanelLocs[self.numPlayers - 1] for i in xrange(self.numPlayers): panel = self.scorePanels[i] pos = scorePanelLocs[i] panel.wrtReparentTo(aspect2d) lerpTrack.append( Parallel( LerpPosInterval(panel, lerpDur, Point3(pos[0], 0, pos[1]), blendType="easeInOut"), LerpScaleInterval(panel, lerpDur, Vec3(panel.getScale()) * 2.0, blendType="easeInOut"), ) ) self.showScoreTrack = Parallel( lerpTrack, Sequence(Wait(IceGameGlobals.ShowScoresDuration), Func(self.gameOver)) ) self.showScoreTrack.start() def exitFinalResults(self): self.showScoreTrack.pause() del self.showScoreTrack def enterCleanup(self): self.notify.debug("enterCleanup") if base.localAvatar.laffMeter: base.localAvatar.laffMeter.start() def exitCleanup(self): pass def __placeToon(self, avId): toon = self.getAvatar(avId) if toon: toon.setPos(0, 0, 0) toon.setHpr(0, 0, 0) def moveCameraToTop(self): camera.reparentTo(render) p = self.cameraThreeQuarterView camera.setPosHpr(p[0], p[1], p[2], p[3], p[4], p[5]) def setupTire(self, avId, index): tireNp, tireBody, tireOdeGeom = self.createTire(index) self.tireDict[avId] = {"tireNodePath": tireNp, "tireBody": tireBody, "tireOdeGeom": tireOdeGeom} if avId <= 0: tireBlocker = tireNp.find("**/tireblockermesh") if not tireBlocker.isEmpty(): tireBlocker.hide() if avId == self.localAvId: tireNp = self.tireDict[avId]["tireNodePath"] self.treasureSphereName = "treasureCollider" self.treasureCollSphere = CollisionSphere(0, 0, 0, IceGameGlobals.TireRadius) self.treasureCollSphere.setTangible(0) self.treasureCollNode = CollisionNode(self.treasureSphereName) self.treasureCollNode.setFromCollideMask(ToontownGlobals.PieBitmask) self.treasureCollNode.addSolid(self.treasureCollSphere) self.treasureCollNodePath = tireNp.attachNewNode(self.treasureCollNode) self.treasureHandler = CollisionHandlerEvent() self.treasureHandler.addInPattern("%fn-intoTreasure") base.cTrav.addCollider(self.treasureCollNodePath, self.treasureHandler) eventName = "%s-intoTreasure" % self.treasureCollNodePath.getName() self.notify.debug("eventName = %s" % eventName) self.accept(eventName, self.toonHitSomething) def setupForceArrow(self, avId): arrow = loader.loadModel("phase_4/models/minigames/ice_game_arrow") priority = 0 if avId < 0: priority = -avId else: priority = self.avIdList.index(avId) if avId == self.localAvId: priority = 10 self.forceArrowDict[avId] = arrow def hideForceArrows(self): for forceArrow in self.forceArrowDict.values(): forceArrow.hide() def showForceArrows(self, realPlayersOnly=True): for avId in self.forceArrowDict: if realPlayersOnly: if avId > 0: self.forceArrowDict[avId].show() else: self.forceArrowDict[avId].hide() else: self.forceArrowDict[avId].show() def localForceArrow(self): if self.localAvId in self.forceArrowDict: return self.forceArrowDict[self.localAvId] else: return None return None def setChoices(self, input0, input1, input2, input3): pass def startDebugTask(self): taskMgr.add(self.debugTask, self.debugTaskName) def stopDebugTask(self): taskMgr.remove(self.debugTaskName) def debugTask(self, task): if self.canDrive and self.tireDict.has_key(localAvatar.doId): dt = globalClock.getDt() forceMove = 25000 forceMoveDt = forceMove tireBody = self.tireDict[localAvatar.doId]["tireBody"] if self.arrowKeys.upPressed() and not tireBody.isEnabled(): x = 0 y = 1 tireBody.enable() tireBody.addForce(Vec3(x * forceMoveDt, y * forceMoveDt, 0)) if self.arrowKeys.downPressed() and not tireBody.isEnabled(): x = 0 y = -1 tireBody.enable() tireBody.addForce(Vec3(x * forceMoveDt, y * forceMoveDt, 0)) if self.arrowKeys.leftPressed() and not tireBody.isEnabled(): x = -1 y = 0 tireBody.enable() tireBody.addForce(Vec3(x * forceMoveDt, y * forceMoveDt, 0)) if self.arrowKeys.rightPressed() and not tireBody.isEnabled(): x = 1 y = 0 tireBody.enable() tireBody.addForce(Vec3(x * forceMoveDt, y * forceMoveDt, 0)) return task.cont def __upArrowPressed(self): pass def __downArrowPressed(self): pass def __leftArrowPressed(self): pass def __rightArrowPressed(self): pass def __controlPressed(self): if self.gameFSM.getCurrentState().getName() == "inputChoice": self.sendForceArrowUpdateAsap = True self.updateLocalForceArrow() self.controlKeyPressed = True self.sendUpdate("setAvatarChoice", [self.curForce, self.curHeading]) self.gameFSM.request("waitServerChoices") def startTimer(self): now = globalClock.getFrameTime() elapsed = now - self.timerStartTime self.timer.posInTopRightCorner() self.timer.setTime(IceGameGlobals.InputTimeout) self.timer.countdown(IceGameGlobals.InputTimeout - elapsed, self.handleChoiceTimeout) self.timer.show() def setTimerStartTime(self, timestamp): if not self.hasLocalToon: return self.timerStartTime = globalClockDelta.networkToLocalTime(timestamp) if self.timer != None: self.startTimer() return def handleChoiceTimeout(self): self.sendUpdate("setAvatarChoice", [0, 0]) self.gameFSM.request("waitServerChoices") def localTireNp(self): ret = None if self.localAvId in self.tireDict: ret = self.tireDict[self.localAvId]["tireNodePath"] return ret def localTireBody(self): ret = None if self.localAvId in self.tireDict: ret = self.tireDict[self.localAvId]["tireBody"] return ret def getTireBody(self, avId): ret = None if avId in self.tireDict: ret = self.tireDict[avId]["tireBody"] return ret def getTireNp(self, avId): ret = None if avId in self.tireDict: ret = self.tireDict[avId]["tireNodePath"] return ret def updateForceArrow(self, avId, curHeading, curForce): forceArrow = self.forceArrowDict[avId] tireNp = self.tireDict[avId]["tireNodePath"] tireNp.setH(curHeading) tireBody = self.tireDict[avId]["tireBody"] tireBody.setQuaternion(tireNp.getQuat()) self.notify.debug("curHeading = %s" % curHeading) yScale = curForce / 100.0 yScale *= 1 headY = yScale * 15 xScale = (yScale - 1) / 2.0 + 1.0 shaft = forceArrow.find("**/arrow_shaft") head = forceArrow.find("**/arrow_head") shaft.setScale(xScale, yScale, 1) head.setPos(0, headY, 0) head.setScale(xScale, xScale, 1) def updateLocalForceArrow(self): avId = self.localAvId self.b_setForceArrowInfo(avId, self.curHeading, self.curForce) def __aimTask(self, task): if not hasattr(self, "arrowKeys"): return task.done dt = globalClock.getDt() headingMomentumChange = dt * 60.0 forceMomentumChange = dt * 160.0 arrowUpdate = False arrowRotating = False arrowUp = False arrowDown = False if self.arrowKeys.upPressed() and not self.arrowKeys.downPressed(): self.forceMomentum += forceMomentumChange if self.forceMomentum < 0: self.forceMomentum = 0 if self.forceMomentum > 50: self.forceMomentum = 50 oldForce = self.curForce self.curForce += self.forceMomentum * dt arrowUpdate = True if oldForce < self.MaxLocalForce: arrowUp = True elif self.arrowKeys.downPressed() and not self.arrowKeys.upPressed(): self.forceMomentum += forceMomentumChange if self.forceMomentum < 0: self.forceMomentum = 0 if self.forceMomentum > 50: self.forceMomentum = 50 oldForce = self.curForce self.curForce -= self.forceMomentum * dt arrowUpdate = True if oldForce > 0.01: arrowDown = True else: self.forceMomentum = 0 if self.arrowKeys.leftPressed() and not self.arrowKeys.rightPressed(): self.headingMomentum += headingMomentumChange if self.headingMomentum < 0: self.headingMomentum = 0 if self.headingMomentum > 50: self.headingMomentum = 50 self.curHeading += self.headingMomentum * dt arrowUpdate = True arrowRotating = True elif self.arrowKeys.rightPressed() and not self.arrowKeys.leftPressed(): self.headingMomentum += headingMomentumChange if self.headingMomentum < 0: self.headingMomentum = 0 if self.headingMomentum > 50: self.headingMomentum = 50 self.curHeading -= self.headingMomentum * dt arrowUpdate = True arrowRotating = True else: self.headingMomentum = 0 if arrowUpdate: self.normalizeHeadingAndForce() self.updateLocalForceArrow() if arrowRotating: if not self.arrowRotateSound.status() == self.arrowRotateSound.PLAYING: base.playSfx(self.arrowRotateSound, looping=True) else: self.arrowRotateSound.stop() if arrowUp: if not self.arrowUpSound.status() == self.arrowUpSound.PLAYING: base.playSfx(self.arrowUpSound, looping=False) else: self.arrowUpSound.stop() if arrowDown: if not self.arrowDownSound.status() == self.arrowDownSound.PLAYING: base.playSfx(self.arrowDownSound, looping=False) else: self.arrowDownSound.stop() return task.cont def normalizeHeadingAndForce(self): if self.curForce > self.MaxLocalForce: self.curForce = self.MaxLocalForce if self.curForce < 0.01: self.curForce = 0.01 def setTireInputs(self, tireInputs): if not self.hasLocalToon: return self.allTireInputs = tireInputs self.gameFSM.request("moveTires") def enableAllTireBodies(self): for avId in self.tireDict.keys(): self.tireDict[avId]["tireBody"].enable() def disableAllTireBodies(self): for avId in self.tireDict.keys(): self.tireDict[avId]["tireBody"].disable() def areAllTiresDisabled(self): for avId in self.tireDict.keys(): if self.tireDict[avId]["tireBody"].isEnabled(): return False return True def __moveTiresTask(self, task): if self.areAllTiresDisabled(): self.sendTirePositions() self.gameFSM.request("synch") return task.done return task.cont def sendTirePositions(self): tirePositions = [] for index in xrange(len(self.avIdList)): avId = self.avIdList[index] tire = self.getTireBody(avId) pos = Point3(tire.getPosition()) tirePositions.append([pos[0], pos[1], pos[2]]) for index in xrange(len(self.avIdList), 4): avId = -index tire = self.getTireBody(avId) pos = Point3(tire.getPosition()) tirePositions.append([pos[0], pos[1], pos[2]]) self.sendUpdate("endingPositions", [tirePositions]) def setFinalPositions(self, finalPos): if not self.hasLocalToon: return for index in xrange(len(self.avIdList)): avId = self.avIdList[index] tire = self.getTireBody(avId) np = self.getTireNp(avId) pos = finalPos[index] tire.setPosition(pos[0], pos[1], pos[2]) np.setPos(pos[0], pos[1], pos[2]) for index in xrange(len(self.avIdList), 4): avId = -index tire = self.getTireBody(avId) np = self.getTireNp(avId) pos = finalPos[index] tire.setPosition(pos[0], pos[1], pos[2]) np.setPos(pos[0], pos[1], pos[2]) def updateInfoLabel(self): self.infoLabel["text"] = TTLocalizer.IceGameInfo % { "curMatch": self.curMatch + 1, "numMatch": IceGameGlobals.NumMatches, "curRound": self.curRound + 1, "numRound": IceGameGlobals.NumRounds, } def setMatchAndRound(self, match, round): if not self.hasLocalToon: return self.curMatch = match self.curRound = round self.updateInfoLabel() def setScores(self, match, round, scores): if not self.hasLocalToon: return self.newMatch = match self.newRound = round self.newScores = scores def setNewState(self, state): if not self.hasLocalToon: return self.notify.debug("setNewState gameFSM=%s newState=%s" % (self.gameFSM, state)) self.gameFSM.request(state) def putAllTiresInStartingPositions(self): for index in xrange(len(self.avIdList)): avId = self.avIdList[index] np = self.tireDict[avId]["tireNodePath"] np.setPos(IceGameGlobals.StartingPositions[index]) self.notify.debug("avId=%s newPos=%s" % (avId, np.getPos)) np.setHpr(0, 0, 0) quat = np.getQuat() body = self.tireDict[avId]["tireBody"] body.setPosition(IceGameGlobals.StartingPositions[index]) body.setQuaternion(quat) for index in xrange(len(self.avIdList), 4): avId = -index np = self.tireDict[avId]["tireNodePath"] np.setPos(IceGameGlobals.StartingPositions[index]) self.notify.debug("avId=%s newPos=%s" % (avId, np.getPos)) np.setHpr(0, 0, 0) quat = np.getQuat() body = self.tireDict[avId]["tireBody"] body.setPosition(IceGameGlobals.StartingPositions[index]) body.setQuaternion(quat) def b_setForceArrowInfo(self, avId, force, heading): self.setForceArrowInfo(avId, force, heading) self.d_setForceArrowInfo(avId, force, heading) def d_setForceArrowInfo(self, avId, force, heading): sendIt = False curTime = self.getCurrentGameTime() if self.sendForceArrowUpdateAsap: sendIt = True elif curTime - self.lastForceArrowUpdateTime > 0.2: sendIt = True if sendIt: self.sendUpdate("setForceArrowInfo", [avId, force, heading]) self.sendForceArrowUpdateAsap = False self.lastForceArrowUpdateTime = self.getCurrentGameTime() def setForceArrowInfo(self, avId, force, heading): if not self.hasLocalToon: return self.updateForceArrow(avId, force, heading) def setupStartOfMatch(self): self.putAllTiresInStartingPositions() szId = self.getSafezoneId() self.numTreasures = IceGameGlobals.NumTreasures[szId] if self.treasures: for treasure in self.treasures: treasure.destroy() self.treasures = [] index = 0 treasureMargin = IceGameGlobals.TireRadius + 1.0 while len(self.treasures) < self.numTreasures: xPos = self.randomNumGen.randrange(IceGameGlobals.MinWall[0] + 5, IceGameGlobals.MaxWall[0] - 5) yPos = self.randomNumGen.randrange(IceGameGlobals.MinWall[1] + 5, IceGameGlobals.MaxWall[1] - 5) self.notify.debug("yPos=%s" % yPos) pos = Point3(xPos, yPos, IceGameGlobals.TireRadius) newTreasure = IceTreasure.IceTreasure(self.treasureModel, pos, index, self.doId, penalty=False) goodSpot = True for obstacle in self.obstacles: if newTreasure.nodePath.getDistance(obstacle) < treasureMargin: goodSpot = False break if goodSpot: for treasure in self.treasures: if newTreasure.nodePath.getDistance(treasure.nodePath) < treasureMargin: goodSpot = False break if goodSpot: self.treasures.append(newTreasure) index += 1 else: newTreasure.destroy() self.numPenalties = IceGameGlobals.NumPenalties[szId] if self.penalties: for penalty in self.penalties: penalty.destroy() self.penalties = [] index = 0 while len(self.penalties) < self.numPenalties: xPos = self.randomNumGen.randrange(IceGameGlobals.MinWall[0] + 5, IceGameGlobals.MaxWall[0] - 5) yPos = self.randomNumGen.randrange(IceGameGlobals.MinWall[1] + 5, IceGameGlobals.MaxWall[1] - 5) self.notify.debug("yPos=%s" % yPos) pos = Point3(xPos, yPos, IceGameGlobals.TireRadius) newPenalty = IceTreasure.IceTreasure(self.penaltyModel, pos, index, self.doId, penalty=True) goodSpot = True for obstacle in self.obstacles: if newPenalty.nodePath.getDistance(obstacle) < treasureMargin: goodSpot = False break if goodSpot: for treasure in self.treasures: if newPenalty.nodePath.getDistance(treasure.nodePath) < treasureMargin: goodSpot = False break if goodSpot: for penalty in self.penalties: if newPenalty.nodePath.getDistance(penalty.nodePath) < treasureMargin: goodSpot = False break if goodSpot: self.penalties.append(newPenalty) index += 1 else: newPenalty.destroy() def toonHitSomething(self, entry): self.notify.debug("---- treasure Enter ---- ") self.notify.debug("%s" % entry) name = entry.getIntoNodePath().getName() parts = name.split("-") if len(parts) < 3: self.notify.debug("collided with %s, but returning" % name) return if not int(parts[1]) == self.doId: self.notify.debug("collided with %s, but doId doesn't match" % name) return treasureNum = int(parts[2]) if "penalty" in parts[0]: self.__penaltyGrabbed(treasureNum) else: self.__treasureGrabbed(treasureNum) def __treasureGrabbed(self, treasureNum): self.treasures[treasureNum].showGrab() self.treasureGrabSound.play() self.sendUpdate("claimTreasure", [treasureNum]) def setTreasureGrabbed(self, avId, treasureNum): if not self.hasLocalToon: return self.notify.debug("treasure %s grabbed by %s" % (treasureNum, avId)) if avId != self.localAvId: self.treasures[treasureNum].showGrab() i = self.avIdList.index(avId) self.scores[i] += 1 self.scorePanels[i].setScore(self.scores[i]) def __penaltyGrabbed(self, penaltyNum): self.penalties[penaltyNum].showGrab() self.sendUpdate("claimPenalty", [penaltyNum]) def setPenaltyGrabbed(self, avId, penaltyNum): if not self.hasLocalToon: return self.notify.debug("penalty %s grabbed by %s" % (penaltyNum, avId)) if avId != self.localAvId: self.penalties[penaltyNum].showGrab() i = self.avIdList.index(avId) self.scores[i] -= 1 self.scorePanels[i].setScore(self.scores[i]) def postStep(self): DistributedIceWorld.DistributedIceWorld.postStep(self) if not self.colCount: return for count in xrange(self.colCount): c0, c1 = self.getOrderedContacts(count) if c1 in self.tireCollideIds: tireIndex = self.tireCollideIds.index(c1) if c0 in self.tireCollideIds: self.tireSounds[tireIndex]["tireHit"].play() elif c0 == self.wallCollideId: self.tireSounds[tireIndex]["wallHit"].play() elif c0 == self.obstacleCollideId: self.tireSounds[tireIndex]["obstacleHit"].play() def forceLocalToonToTire(self): toon = localAvatar if toon and self.localAvId in self.tireDict: tireNp = self.tireDict[self.localAvId]["tireNodePath"] toon.reparentTo(tireNp) toon.setPosHpr(0, 0, 0, 0, 0, 0) toon.setY(1.0) toon.setZ(-3)
def _createQuadrant(self, filepath, serialNum, angle, size): root = NodePath('QuadrantRoot-%i' % serialNum) quadrant = loader.loadModel(filepath) quadrant.getChildren().reparentTo(root) root.setH(angle) return root
class GameOverNotification(object): def __init__(self,cameraX,cameraY,cameraZ,cameraAngle): self.ticks=0 self.endOfLife=False self.currentLetterAngle=0.0 self.letterNodes=[] self.distance=200 self.closestDistance=20 self.endOfLifeTicks=400 self.cameraX=cameraX self.reduceSpinning=False self.spinningChange=5.0 self.minimumSpinning=False self.stoppedMoving=False self.gameOverContainerNode=NodePath("GameOverContainer") self.gameOverContainerNode.reparentTo(render) self.gameOverContainerNode.setPos(cameraX,cameraY,cameraZ-0.85) self.gameOverNode=self.getGameOverNode() self.gameOverNode.reparentTo(self.gameOverContainerNode) angle=cameraAngle-90 if angle<0.0: angle=angle+360.0 self.gameOverContainerNode.setH(angle) def advanceTime(self): if self.stoppedMoving: self.ticksUntilDeath=self.ticksUntilDeath-1 if self.ticksUntilDeath==0: self.endOfLife=True else: self.currentLetterAngle=self.currentLetterAngle+self.spinningChange if self.currentLetterAngle>360.0: if self.minimumSpinning: self.stoppedMoving=True self.ticksUntilDeath=120 else: self.currentLetterAngle=self.currentLetterAngle-360.0 if not self.reduceSpinning: self.distance=self.distance-1 if self.distance<=self.closestDistance: self.distance=self.closestDistance self.reduceSpinning=True if self.reduceSpinning: if self.spinningChange>1.75: self.spinningChange=self.spinningChange-0.05 else: self.minimumSpinning=True self.gameOverNode.setY(self.distance) for letterNode in self.letterNodes: letterNode.setH(self.currentLetterAngle) def getGameOverNode(self): gameOverNode=NodePath("GameOver") letterGeometry=LetterGeometry.getCardGeometryByPhrase('game over') for letter in letterGeometry: letterCm=CardMaker('card') letterCm.setFrame(letter['left'],letter['right'],letter['top'],letter['bottom']) letterNode=gameOverNode.attachNewNode(letterCm.generate()) self.letterNodes.append(letterNode) letterNode.setTwoSided(True) letterNode.setTransparency(TransparencyAttrib.MAlpha) letterNode.setBin('unsorted',50) letterNode.setDepthTest(False) letterNode.setDepthWrite(False) tex=loader.loadTexture('textures/letter-'+letter['letter']+'.png') tex.setWrapU(Texture.WMClamp) tex.setWrapV(Texture.WMClamp) letterNode.setTexture(tex) letterNode.setPos(letter['originx'],letter['originy'],0) return gameOverNode def setCompletionEvent(self,completionEvent): self.completionEvent=completionEvent def getCompletionEvent(self): return self.completionEvent def hasDied(self): return self.endOfLife def delete(self): self.gameOverContainerNode.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])
def generateHullCache(modelClass): geom = loader.loadModel("models/shipparts/pir_m_shp_%s" % HullDict[modelClass]) stripPrefix(geom, "model:") for node in geom.findAllMatches("**/omit"): parent = node.getParent() omit = parent.attachNewNode(ModelNode("omit")) node.reparentTo(omit) node.setName("geom") preFlatten(geom) logic = loader.loadModel("models/shipparts/pir_m_shp_%s_logic" % HullDict[modelClass]) locators = logic.find("**/locators") for side in ["left", "right"]: bad = locators.find("**/location_ropeLadder_0_%s" % side) if bad: bad.setName("location_ropeLadder_%s_0" % side) bad = locators.find("**/location_ropeLadder_1_%s" % side) if bad: bad.setName("location_ropeLadder_%s_1" % side) bad = locators.find("**/location_ropeLadder_1_%s1" % side) if bad: bad.setName("location_ropeLadder_%s_2" % side) continue collisions = logic.find("**/collisions") badPanel = collisions.find("**/collision_panel_3") if badPanel: badPanel.setName("collision_panel_2") collisions.find("**/collision_panel_0").setTag("Hull Code", "0") collisions.find("**/collision_panel_1").setTag("Hull Code", "1") collisions.find("**/collision_panel_2").setTag("Hull Code", "2") walls = collisions.find("**/collision_walls") if walls: walls.setTag("Hull Code", "255") else: collisions.attachNewNode("collision_walls") shipToShipCollide = collisions.find("**/collision_shiptoship") shipToShipCollide.setCollideMask(PiratesGlobals.ShipCollideBitmask) deck = collisions.find("**/collision_deck") if not deck: deck = collisions.attachNewNode("deck") mask = deck.getCollideMask() mask ^= PiratesGlobals.FloorBitmask mask |= PiratesGlobals.ShipFloorBitmask deck.setCollideMask(mask) floors = collisions.find("**/collision_floors") if not floors: floors = collisions.find("**/collision_floor") mask = floors.getCollideMask() mask ^= PiratesGlobals.FloorBitmask mask |= PiratesGlobals.ShipFloorBitmask floors.setCollideMask(mask) floors.setTag("Hull Code", str(255)) geomHigh = geom.find("**/lod_high") geomMed = geom.find("**/lod_medium") if not geomMed: geomMed = geom.find("**/low_medium") if not geomMed: geomMed = geomHigh.copyTo(NodePath()) geomLow = geom.find("**/lod_low") if not geomLow: geomLow = geomMed.copyTo(NodePath()) geomSuperLow = geom.find("**/lod_superlow") if not geomSuperLow: geomSuperLow = geomLow.copyTo(NodePath()) geomHigh.setName("high") geomMed.setName("med") geomLow.setName("low") geomSuperLow.setName("superlow") if modelClass in [21, 22, 23]: spike = loader.loadModel("models/shipparts/pir_m_shp_ram_spike") spikeTrans = locators.find("**/location_ram").getTransform(locators) spike.setTransform(spikeTrans) spike.flattenLight() spikeHi = spike.find("**/lod_high") spikeMed = spike.find("**/lod_medium") spikeLow = spike.find("**/lod_low") spikeHi.copyTo(geomHigh) spikeMed.copyTo(geomMed) spikeLow.copyTo(geomLow) spikeLow.copyTo(geomSuperLow) flipRoot = NodePath("root") collisions.reparentTo(flipRoot) locators.reparentTo(flipRoot) geomHigh.reparentTo(flipRoot) geomMed.reparentTo(flipRoot) geomLow.reparentTo(flipRoot) geomSuperLow.reparentTo(flipRoot) flipRoot.setH(180) flipRoot.flattenLight() omits = flipRoot.findAllMatches("**/omit") for node in omits: node.flattenStrong() for group in ["static", "transparent", "ropeLadder_*", "stripeA", "stripeB", "pattern"]: for node in flipRoot.findAllMatches("**/%s" % group): name = node.getName() for subNode in node.findAllMatches("**/*"): subNode.setName(name) node.flattenStrong() node.setName(name) geomHigh.detachNode() geomMed.detachNode() geomLow.detachNode() geomSuperLow.detachNode() locators.detachNode() collisions.detachNode() genericGeoms = [geomHigh, geomMed, geomLow, geomSuperLow] customGeoms = [x.copyTo(NodePath()) for x in genericGeoms] for np in genericGeoms: trans = np.find("**/transparent") if trans: trans.stash() np.flattenLight() sails = np.findAllMatches("**/sails") sails.stash() omits = np.findAllMatches("**/omit") omits.stash() for node in omits: node.node().setPreserveTransform(node.node().PTDropNode) generic = NodePath("generic") np.findAllMatches("**/+GeomNode").wrtReparentTo(generic) np.findAllMatches("*").detach() generic.flattenStrong() generic.reparentTo(np) stripAttribs(generic, TextureAttrib) stripAttribs(generic, TransparencyAttrib) stripAttribs(generic, CullBinAttrib) generic.setBin("ground", 1) collapse(generic) sails.unstash() sails.reparentTo(np) for node in sails: node.node().setPreserveTransform(node.node().PTDropNode) if trans: trans.unstash() trans.flattenStrong() if trans.node().isOfType(ModelNode.getClassType()): trans.node().setPreserveTransform(ModelNode.PTDropNode) deck = np.find("**/=cam=shground") if deck: deck.setName("deck") omits.unstash() for np in customGeoms: collapse(np.find("**/static")) data = HullCache() data.root = NodePath("hull") data.genericGeoms = genericGeoms data.customGeoms = customGeoms data.collisions = collisions data.locators = locators return data
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 GameOverNotification(object): def __init__(self, cameraX, cameraY, cameraZ, cameraAngle): self.ticks = 0 self.endOfLife = False self.currentLetterAngle = 0.0 self.letterNodes = [] self.distance = 200 self.closestDistance = 20 self.endOfLifeTicks = 400 self.cameraX = cameraX self.reduceSpinning = False self.spinningChange = 5.0 self.minimumSpinning = False self.stoppedMoving = False self.gameOverContainerNode = NodePath("GameOverContainer") self.gameOverContainerNode.reparentTo(render) self.gameOverContainerNode.setPos(cameraX, cameraY, cameraZ - 0.85) self.gameOverNode = self.getGameOverNode() self.gameOverNode.reparentTo(self.gameOverContainerNode) angle = cameraAngle - 90 if angle < 0.0: angle = angle + 360.0 self.gameOverContainerNode.setH(angle) def advanceTime(self): if self.stoppedMoving: self.ticksUntilDeath = self.ticksUntilDeath - 1 if self.ticksUntilDeath == 0: self.endOfLife = True else: self.currentLetterAngle = self.currentLetterAngle + self.spinningChange if self.currentLetterAngle > 360.0: if self.minimumSpinning: self.stoppedMoving = True self.ticksUntilDeath = 120 else: self.currentLetterAngle = self.currentLetterAngle - 360.0 if not self.reduceSpinning: self.distance = self.distance - 1 if self.distance <= self.closestDistance: self.distance = self.closestDistance self.reduceSpinning = True if self.reduceSpinning: if self.spinningChange > 1.75: self.spinningChange = self.spinningChange - 0.05 else: self.minimumSpinning = True self.gameOverNode.setY(self.distance) for letterNode in self.letterNodes: letterNode.setH(self.currentLetterAngle) def getGameOverNode(self): gameOverNode = NodePath("GameOver") letterGeometry = LetterGeometry.getCardGeometryByPhrase('game over') for letter in letterGeometry: letterCm = CardMaker('card') letterCm.setFrame(letter['left'], letter['right'], letter['top'], letter['bottom']) letterNode = gameOverNode.attachNewNode(letterCm.generate()) self.letterNodes.append(letterNode) letterNode.setTwoSided(True) letterNode.setTransparency(TransparencyAttrib.MAlpha) letterNode.setBin('unsorted', 50) letterNode.setDepthTest(False) letterNode.setDepthWrite(False) tex = loader.loadTexture('textures/letter-' + letter['letter'] + '.png') tex.setWrapU(Texture.WMClamp) tex.setWrapV(Texture.WMClamp) letterNode.setTexture(tex) letterNode.setPos(letter['originx'], letter['originy'], 0) return gameOverNode def setCompletionEvent(self, completionEvent): self.completionEvent = completionEvent def getCompletionEvent(self): return self.completionEvent def hasDied(self): return self.endOfLife def delete(self): self.gameOverContainerNode.removeNode()
def generateHullCache(modelClass): geom = loader.loadModel('models/shipparts/pir_m_shp_%s' % HullDict[modelClass]) stripPrefix(geom, 'model:') for node in geom.findAllMatches('**/omit'): parent = node.getParent() omit = parent.attachNewNode(ModelNode('omit')) node.reparentTo(omit) node.setName('geom') preFlatten(geom) logic = loader.loadModel('models/shipparts/pir_m_shp_%s_logic' % HullDict[modelClass]) locators = logic.find('**/locators') for side in ['left', 'right']: bad = locators.find('**/location_ropeLadder_0_%s' % side) if bad: bad.setName('location_ropeLadder_%s_0' % side) bad = locators.find('**/location_ropeLadder_1_%s' % side) if bad: bad.setName('location_ropeLadder_%s_1' % side) bad = locators.find('**/location_ropeLadder_1_%s1' % side) if bad: bad.setName('location_ropeLadder_%s_2' % side) collisions = logic.find('**/collisions') badPanel = collisions.find('**/collision_panel_3') if badPanel: badPanel.setName('collision_panel_2') collisions.find('**/collision_panel_0').setTag('Hull Code', '0') collisions.find('**/collision_panel_1').setTag('Hull Code', '1') collisions.find('**/collision_panel_2').setTag('Hull Code', '2') walls = collisions.find('**/collision_walls') if walls: walls.setTag('Hull Code', '255') else: collisions.attachNewNode('collision_walls') shipToShipCollide = collisions.find('**/collision_shiptoship') shipToShipCollide.setCollideMask(PiratesGlobals.ShipCollideBitmask) deck = collisions.find('**/collision_deck') if not deck: deck = collisions.attachNewNode('deck') mask = deck.getCollideMask() mask ^= PiratesGlobals.FloorBitmask mask |= PiratesGlobals.ShipFloorBitmask deck.setCollideMask(mask) floors = collisions.find('**/collision_floors') if not floors: floors = collisions.find('**/collision_floor') mask = floors.getCollideMask() mask ^= PiratesGlobals.FloorBitmask mask |= PiratesGlobals.ShipFloorBitmask floors.setCollideMask(mask) floors.setTag('Hull Code', str(255)) geomHigh = geom.find('**/lod_high') geomMed = geom.find('**/lod_medium') if not geomMed: geomMed = geom.find('**/low_medium') if not geomMed: geomMed = geomHigh.copyTo(NodePath()) geomLow = geom.find('**/lod_low') if not geomLow: geomLow = geomMed.copyTo(NodePath()) geomSuperLow = geom.find('**/lod_superlow') if not geomSuperLow: geomSuperLow = geomLow.copyTo(NodePath()) geomHigh.setName('high') geomMed.setName('med') geomLow.setName('low') geomSuperLow.setName('superlow') if modelClass in [21, 22, 23]: spike = loader.loadModel('models/shipparts/pir_m_shp_ram_spike') spikeTrans = locators.find('**/location_ram').getTransform(locators) spike.setTransform(spikeTrans) spike.flattenLight() spikeHi = spike.find('**/lod_high') spikeMed = spike.find('**/lod_medium') spikeLow = spike.find('**/lod_low') spikeHi.copyTo(geomHigh) spikeMed.copyTo(geomMed) spikeLow.copyTo(geomLow) spikeLow.copyTo(geomSuperLow) flipRoot = NodePath('root') collisions.reparentTo(flipRoot) locators.reparentTo(flipRoot) geomHigh.reparentTo(flipRoot) geomMed.reparentTo(flipRoot) geomLow.reparentTo(flipRoot) geomSuperLow.reparentTo(flipRoot) flipRoot.setH(180) flipRoot.flattenLight() omits = flipRoot.findAllMatches('**/omit') for node in omits: node.flattenStrong() for group in [ 'static', 'transparent', 'ropeLadder_*', 'stripeA', 'stripeB', 'pattern' ]: for node in flipRoot.findAllMatches('**/%s' % group): name = node.getName() for subNode in node.findAllMatches('**/*'): subNode.setName(name) node.flattenStrong() node.setName(name) geomHigh.detachNode() geomMed.detachNode() geomLow.detachNode() geomSuperLow.detachNode() locators.detachNode() collisions.detachNode() genericGeoms = [geomHigh, geomMed, geomLow, geomSuperLow] customGeoms = [x.copyTo(NodePath()) for x in genericGeoms] for np in genericGeoms: trans = np.find('**/transparent') if trans: trans.stash() np.flattenLight() sails = np.findAllMatches('**/sails') sails.stash() omits = np.findAllMatches('**/omit') omits.stash() for node in omits: node.node().setPreserveTransform(node.node().PTDropNode) generic = NodePath('generic') np.findAllMatches('**/+GeomNode').wrtReparentTo(generic) np.findAllMatches('*').detach() generic.flattenStrong() generic.reparentTo(np) stripAttribs(generic, TextureAttrib) stripAttribs(generic, TransparencyAttrib) stripAttribs(generic, CullBinAttrib) generic.setBin('ground', 1) collapse(generic) sails.unstash() sails.reparentTo(np) for node in sails: node.node().setPreserveTransform(node.node().PTDropNode) if trans: trans.unstash() trans.flattenStrong() if trans.node().isOfType(ModelNode.getClassType()): trans.node().setPreserveTransform(ModelNode.PTDropNode) deck = np.find('**/=cam=shground') if deck: deck.setName('deck') omits.unstash() for np in customGeoms: collapse(np.find('**/static')) data = HullCache() data.root = NodePath('hull') data.genericGeoms = genericGeoms data.customGeoms = customGeoms data.collisions = collisions data.locators = locators return data
class PlaneCamera(FSM, DirectObject): """Give this class a plane as argument and it will create some nodes around it which you can parent the camera to (if there are no such nodes yet). Keep in mind, that it only uses base.camera the whole time - no other cams are involved. Usage: plane_camera = PlaneCamera(aeroplane) plane_camera.setView("ThirdPerson") plane_camera.setView("Next") """ def __init__(self, parent): """Arguments: parent -- Aeroplane which the camera should follow """ # Used for debugging. Verbosity is set in config file. # Usually this is called self.notify, but in this case it would # override FSM's own. self.notifier = DirectNotify().newCategory("azure-camera") self.parent = parent # Replaced by a NodePath with all available cameras as children and # plane node as parent. self.cameras = None #if parent.__class__.__name__ is not "Aeroplane": if not isinstance(self.parent, Aeroplane): raise ParamError, "Parent must be an Aeroplane instance, " + \ "but is %s" % type(self.parent) FSM.__init__(self, "PlaneCamera: %s" % self.parent.name) DirectObject.__init__(self) try: self.camera = base.camera except: raise BaseMissing self.cameras = self.parent.node.find("cameras") if self.cameras.isEmpty(): self.createCamNodes() self.updateCamArray() self.sideview_direction = 0 # Set up the default camera self.setView("ThirdPerson") def createCamNodes(self): """Creates a few empty nodes around a plane which the camera might be parented to. It looks if there are cameras inside the model file and uses those if possible. Where everything named "camera CamType" is considered a camera. At least ThirdPerson, FirstPerson and Cockpit should be defined inside the egg file, otherwise some guessed defaults are taken. """ # Look for cameras inside the model (loaded egg file) self.cameras = NodePath("cameras") found_cams = self.parent.node.findAllMatches("**/camera ?*") found_cams.removeDuplicatePaths() found_cams.reparentTo(self.cameras) if not found_cams.isEmpty(): self.notifier.info("Cameras found under model:\n%s" % found_cams) else: self.notifier.info("No cameras found under model.") # FirstPerson camera is a must-have. Set up a guessed one if none # defined yet. if self.cameras.find("camera FirstPerson").isEmpty(): assert self.notifier.debug("No first person camera found in %s. " "Guessing best position." % self.parent.name) first_person = NodePath("camera FirstPerson") # TODO: Guess best position based on bounding box. first_person.setY(5) first_person.reparentTo(cameras) # ThirdPerson camera is a must-have. Set up a guessed one if none # defined yet. if self.cameras.find("camera ThirdPerson").isEmpty(): assert self.notifier.debug("No third person camera found in %s. " "Guessing best position." % self.parent.name) third_person = NodePath("camera ThirdPerson") # TODO: Guess best position based on bounding box. third_person.setPos(0, -30, 5) #third_person.setP(-80) third_person.reparentTo(cameras) # Cockpit needs to be accurate. Don't try to guess it. if self.cameras.find("camera Cockpit").isEmpty(): assert self.notifier.debug("No cockpit camera found in " "%s. Cockpit camera disabled." % self.parent.name) self.sideview_cam = NodePath("camera Sideview") self.sideview_cam.reparentTo(render) # Store the cams at parent node.. # You can edit the camera nodes from outside as well. # If you attach new camera nodes, though, you'll have to call this # function again. self.cameras.reparentTo(self.parent.node) def updateCamArray(self, cameramodes=None): """Set the cameras which next and previous will switch to. Expects a list or tuple. Defaults to all available cameras.""" a = [] if not cameramodes: for c in self.cameras.getChildren(): if c.getName().startswith("camera "): a.append(c.getName().strip("camera ")) self.setStateArray(a) else: self.setStateArray(cameramodes) def getView(self): """Returns the current view mode.""" return self.getCurrentOrNextState() def setView(self, mode, *args): """Convenience function.""" return self.request(mode, args) def defaultEnter(self, *args): """Executed by the FSM every time an undefined state is entered. Note: this function is called AFTER the responsible filter.""" assert self.notifier.debug("Changing state from %s to %s with args: %s." % (self.oldState, self.newState, args)) request = self.newState target_cam = self.cameras.find("camera " + request) if not target_cam.isEmpty(): try: self.camera.reparentTo(target_cam) self.camera.setPosHpr(0, 0, 0, 0, 0, 0) except: self.notifier.warning( "Ok, now this really shouldn't happen! Filter said the " "camera is there and enter can't find it...") def defaultFilter(self, request, args): """Executed by the FSM every time an undefined state is requested.""" assert self.notifier.debug("Requested %s with args: %s" % (request, args)) self.camera.setPosHpr(0, 0, 0, 0, 0, 0) # Always available. if request == "Off": # implemented in FSM.py return (request,) + args if request == "Next": # implemented in FSM.py return self.requestNext(args) if request == "Prev": # implemented in FSM.py return self.requestPrev(args) if request == "Detached": return (request,) + args if request == "Sideview": return (request,) + args # Depending on airplane. if not self.cameras.find("camera " + request).isEmpty(): # TODO(Nemesis13, 26.10.09): add some nice camera transition return (request,) + args assert self.notifier.info("Sorry, no %s camera found." % request) return None def enterOff(self, *args): """Clean up everything by reparenting the camera to the airplane.""" self.camera.reparentTo(self.parent.node) self.camera.setPosHpr(0, 0, 0, 0, 0, 0) def enterSideview(self, *args): self.sideview_direction += 90 self.camera.reparentTo(self.sideview_cam) self.camera.setY(-30) self.sideview_cam.setH(self.sideview_direction) self.addTask(self.updateSideview, "sideview camera", taskChain="world") def exitSideview(self, *args): self.removeTask("sideview camera") def updateSideview(self, task): self.sideview_cam.setPos(self.parent.node.getPos()) return Task.cont def enterDetached(self, *args): """Lets the camera view the plane from far away.""" self.camera.reparentTo(render) self.camera.setPosHpr(0, 0, 10, 0, 0, 0) self.addTask(self.updateDetachedCam, "detached camera", taskChain="world") def exitDetached(self, *args): self.removeTask("detached camera") def updateDetachedCam(self, task): """Updates camera position and rotation for Detached camera.""" try: self.camera.lookAt(self.parent.node) except: self.notifier.warning("Error on detached cam task. Exit.") return Task.done return Task.cont def enterThirdPerson(self, *args): """Lets the camera view the plane from far away.""" self._hist = [] self.camera.reparentTo(self.cameras.find("camera ThirdPerson")) self.addTask(self.updateThirdPersonCam, "third person camera", taskChain="world") #print "entering third person" def exitThirdPerson(self, *args): self.removeTask("third person camera") del self._hist #print "third person exited" def updateThirdPersonCam(self, task): """Updates camera position and rotation for ThirdPerson camera.""" #speed = self.parent.speed() #plane = self.parent.node #self._hist.insert(0, [task.time, camera.getPos(plane)]) #while len(self._hist) > 50: # self._hist.pop() # #for snapshot in self._hist: # if snapshot[0] > task.time: # break #time_delta = snapshot[0] - task.time #self.camera.setPos(plane, snapshot[1]) #print snapshot #self.camera.setPos(render, snapshot[1]) #self.camera.lookAt(plane, (0, 20+1*speed, 0)) #self.camera.setY(5+0.1*speed) #self.camera.setZ(5-0.1*speed) return Task.cont def destroy(self): self.removeAllTasks() self.demand("Off")
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)
def load(self): self.arena = loader.loadModel(self.arenaModel) self.arena.reparentTo(self.root) ground = self.arena.find('**/ground') ground.setBin('ground', 1) entranceArrows = self.arena.findAllMatches('**/arrowFlat*') for arrow in entranceArrows: arrow.setBin('ground', 5) self.leftEntranceLocator = self.arena.find('**/leftEntrance_locator') self.rightEntranceLocator = self.arena.find('**/rightEntrance_locator') self.leftExitLocator = self.arena.find('**/leftExit_locator') self.rightExitLocator = self.arena.find('**/rightExit_locator') self.teamCamPosLocators = (self.arena.find('**/team0CamPos_locator'), self.arena.find('**/team1CamPos_locator')) self.teamCamAimLocators = (self.arena.find('**/team0CamAim_locator'), self.arena.find('**/team1CamAim_locator')) leftTeamLocator = NodePath('TeamLocator-%d' % PartyGlobals.TeamActivityTeams.LeftTeam) leftTeamLocator.reparentTo(self.root) leftTeamLocator.setH(90) rightTeamLocator = NodePath('TeamLocator-%d' % PartyGlobals.TeamActivityTeams.RightTeam) rightTeamLocator.reparentTo(self.root) rightTeamLocator.setH(-90) self.teamLocators = (leftTeamLocator, rightTeamLocator) self._lengthBetweenEntrances = self.leftEntranceLocator.getY() - self.rightExitLocator.getY() self._skyCollisionsCollection = self.arena.findAllMatches('**/cogPieArena_sky*_collision') if len(self._skyCollisionsCollection) > 0: self._skyCollisionParent = self._skyCollisionsCollection[0].getParent() else: self._skyCollisionParent = self.arena self._wallCollisionsCollection = self.arena.findAllMatches('**/cogPieArena_wall*_collision') self._arenaFlagGroups = (self.arena.find('**/flagsL_grp'), self.arena.find('**/flagsR_grp')) self._initArenaDoors() self.cogManager = PartyCogManager() self.arrows = [] self.distanceLabels = [] self.teamColors = list(PartyGlobals.CogActivityColors) + [PartyGlobals.TeamActivityStatusColor] for i in range(3): start = self.arena.find('**/cog%d_start_locator' % (i + 1)) end = self.arena.find('**/cog%d_end_locator' % (i + 1)) cog = self.cogManager.generateCog(self.arena) cog.setEndPoints(start.getPos(), end.getPos()) arrow1 = StretchingArrow(self.arena, useColor='orange') arrow2 = StretchingArrow(self.arena, useColor='blue') arrow1.setZ(0.1) arrow2.setZ(0.1) self.arrows.append([arrow1, arrow2]) distanceLabel = self.createDistanceLabel(0, self.teamColors[1]) distanceLabel[0].stash() distanceLabel2 = self.createDistanceLabel(0, self.teamColors[0]) distanceLabel2[0].stash() self.distanceLabels.append([distanceLabel, distanceLabel2]) self.winText = [] text1 = self.createText(0, Point3(-0.5, 0.0, -0.5), self.teamColors[1]) text2 = self.createText(1, Point3(0.5, 0.0, -0.5), self.teamColors[0]) self.winText.append(text1) self.winText.append(text2) self.winStatus = self.createText(2, Point3(0.0, 0.0, -0.8), self.teamColors[0]) signLocator = self.arena.find('**/eventSign_locator') self.activity.sign.setPos(signLocator.getPos(self.root)) if self.texture: textureAlpha = self.texture[:-4] + '_a.rgb' reskinTexture = loader.loadTexture(self.texture, textureAlpha) self.arena.find('**/center_grp').setTexture(reskinTexture, 100) self.arena.find('**/leftSide_grp').setTexture(reskinTexture, 100) self.arena.find('**/rightSide_grp').setTexture(reskinTexture, 100) self.enable()
def _createQuadrant(self, filepath, serialNum, angle, size): root = NodePath('QuadrantRoot-%i' % serialNum) quadrant = loader.loadModel(filepath) quadrant.getChildren().reparentTo(root) root.setH(angle) return root
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 DistributedIceGame(DistributedMinigame.DistributedMinigame, DistributedIceWorld.DistributedIceWorld): notify = directNotify.newCategory('DistributedIceGame') MaxLocalForce = 100 MaxPhysicsForce = 25000 def __init__(self, cr): DistributedMinigame.DistributedMinigame.__init__(self, cr) DistributedIceWorld.DistributedIceWorld.__init__(self, cr) self.gameFSM = ClassicFSM.ClassicFSM('DistributedIceGame', [ State.State('off', self.enterOff, self.exitOff, ['inputChoice']), State.State( 'inputChoice', self.enterInputChoice, self.exitInputChoice, ['waitServerChoices', 'moveTires', 'displayVotes', 'cleanup']), State.State('waitServerChoices', self.enterWaitServerChoices, self.exitWaitServerChoices, ['moveTires', 'cleanup']), State.State('moveTires', self.enterMoveTires, self.exitMoveTires, ['synch', 'cleanup']), State.State('synch', self.enterSynch, self.exitSynch, ['inputChoice', 'scoring', 'cleanup']), State.State('scoring', self.enterScoring, self.exitScoring, ['cleanup', 'finalResults', 'inputChoice']), State.State('finalResults', self.enterFinalResults, self.exitFinalResults, ['cleanup']), State.State('cleanup', self.enterCleanup, self.exitCleanup, []) ], 'off', 'cleanup') self.addChildGameFSM(self.gameFSM) self.cameraThreeQuarterView = (0, -22, 45, 0, -62.890000000000001, 0) self.tireDict = {} self.forceArrowDict = {} self.canDrive = False self.timer = None self.timerStartTime = None self.curForce = 0 self.curHeading = 0 self.headingMomentum = 0.0 self.forceMomentum = 0.0 self.allTireInputs = None self.curRound = 0 self.curMatch = 0 self.controlKeyWarningLabel = DirectLabel( text=TTLocalizer.IceGameControlKeyWarning, text_fg=VBase4(1, 0, 0, 1), relief=None, pos=(0.0, 0, 0), scale=0.14999999999999999) self.controlKeyWarningLabel.hide() self.waitingMoveLabel = DirectLabel( text=TTLocalizer.IceGameWaitingForPlayersToFinishMove, text_fg=VBase4(1, 1, 1, 1), relief=None, pos=(-0.59999999999999998, 0, -0.75), scale=0.074999999999999997) self.waitingMoveLabel.hide() self.waitingSyncLabel = DirectLabel( text=TTLocalizer.IceGameWaitingForAISync, text_fg=VBase4(1, 1, 1, 1), relief=None, pos=(-0.59999999999999998, 0, -0.75), scale=0.074999999999999997) self.waitingSyncLabel.hide() self.infoLabel = DirectLabel(text='', text_fg=VBase4(0, 0, 0, 1), relief=None, pos=(0.0, 0, 0.69999999999999996), scale=0.074999999999999997) self.updateInfoLabel() self.lastForceArrowUpdateTime = 0 self.sendForceArrowUpdateAsap = False self.treasures = [] self.penalties = [] self.obstacles = [] self.controlKeyPressed = False self.controlKeyWarningIval = None def delete(self): DistributedIceWorld.DistributedIceWorld.delete(self) DistributedMinigame.DistributedMinigame.delete(self) if self.controlKeyWarningIval: self.controlKeyWarningIval.finish() self.controlKeyWarningIval = None self.controlKeyWarningLabel.destroy() del self.controlKeyWarningLabel self.waitingMoveLabel.destroy() del self.waitingMoveLabel self.waitingSyncLabel.destroy() del self.waitingSyncLabel self.infoLabel.destroy() del self.infoLabel for treasure in self.treasures: treasure.destroy() del self.treasures for penalty in self.penalties: penalty.destroy() del self.penalties for obstacle in self.obstacles: obstacle.removeNode() del self.obstacles del self.gameFSM def announceGenerate(self): DistributedMinigame.DistributedMinigame.announceGenerate(self) DistributedIceWorld.DistributedIceWorld.announceGenerate(self) self.debugTaskName = self.uniqueName('debugTask') def getTitle(self): return TTLocalizer.IceGameTitle def getInstructions(self): szId = self.getSafezoneId() numPenalties = IceGameGlobals.NumPenalties[szId] result = TTLocalizer.IceGameInstructions if numPenalties == 0: result = TTLocalizer.IceGameInstructionsNoTnt return result def getMaxDuration(self): return 0 def load(self): self.notify.debug('load') DistributedMinigame.DistributedMinigame.load(self) self.music = base.loadMusic('phase_4/audio/bgm/MG_IceGame.mid') self.gameBoard = loader.loadModel( 'phase_4/models/minigames/ice_game_icerink') background = loader.loadModel('phase_4/models/minigames/ice_game_2d') background.reparentTo(self.gameBoard) self.gameBoard.setPosHpr(0, 0, 0, 0, 0, 0) self.gameBoard.setScale(1.0) self.setupSimulation() index = 0 for avId in self.avIdList: self.setupTire(avId, index) self.setupForceArrow(avId) index += 1 for index in xrange(len(self.avIdList), 4): self.setupTire(-index, index) self.setupForceArrow(-index) self.showForceArrows(realPlayersOnly=True) self.westWallModel = NodePath() if not self.westWallModel.isEmpty(): self.westWallModel.reparentTo(self.gameBoard) self.westWallModel.setPos(IceGameGlobals.MinWall[0], IceGameGlobals.MinWall[1], 0) self.westWallModel.setScale(4) self.eastWallModel = NodePath() if not self.eastWallModel.isEmpty(): self.eastWallModel.reparentTo(self.gameBoard) self.eastWallModel.setPos(IceGameGlobals.MaxWall[0], IceGameGlobals.MaxWall[1], 0) self.eastWallModel.setScale(4) self.eastWallModel.setH(180) self.arrowKeys = ArrowKeys.ArrowKeys() self.target = loader.loadModel('phase_3/models/misc/sphere') self.target.setScale(0.01) self.target.reparentTo(self.gameBoard) self.target.setPos(0, 0, 0) self.scoreCircle = loader.loadModel( 'phase_4/models/minigames/ice_game_score_circle') self.scoreCircle.setScale(0.01) self.scoreCircle.reparentTo(self.gameBoard) self.scoreCircle.setZ(IceGameGlobals.TireRadius / 2.0) self.scoreCircle.setAlphaScale(0.5) self.scoreCircle.setTransparency(1) self.scoreCircle.hide() self.treasureModel = loader.loadModel( 'phase_4/models/minigames/ice_game_barrel') self.penaltyModel = loader.loadModel( 'phase_4/models/minigames/ice_game_tnt2') self.penaltyModel.setScale(0.75, 0.75, 0.69999999999999996) szId = self.getSafezoneId() obstacles = IceGameGlobals.Obstacles[szId] index = 0 cubicObstacle = IceGameGlobals.ObstacleShapes[szId] for pos in obstacles: newPos = Point3(pos[0], pos[1], IceGameGlobals.TireRadius) newObstacle = self.createObstacle(newPos, index, cubicObstacle) self.obstacles.append(newObstacle) index += 1 self.countSound = loader.loadSfx( 'phase_3.5/audio/sfx/tick_counter.mp3') self.treasureGrabSound = loader.loadSfx( 'phase_4/audio/sfx/MG_sfx_vine_game_bananas.mp3') self.penaltyGrabSound = loader.loadSfx( 'phase_4/audio/sfx/MG_cannon_fire_alt.mp3') self.tireSounds = [] for tireIndex in xrange(4): tireHit = loader.loadSfx( 'phase_4/audio/sfx/Golf_Hit_Barrier_1.mp3') wallHit = loader.loadSfx('phase_4/audio/sfx/MG_maze_pickup.mp3') obstacleHit = loader.loadSfx( 'phase_4/audio/sfx/Golf_Hit_Barrier_2.mp3') self.tireSounds.append({ 'tireHit': tireHit, 'wallHit': wallHit, 'obstacleHit': obstacleHit }) self.arrowRotateSound = loader.loadSfx( 'phase_4/audio/sfx/MG_sfx_ice_force_rotate.wav') self.arrowUpSound = loader.loadSfx( 'phase_4/audio/sfx/MG_sfx_ice_force_increase_3sec.mp3') self.arrowDownSound = loader.loadSfx( 'phase_4/audio/sfx/MG_sfx_ice_force_decrease_3sec.mp3') self.scoreCircleSound = loader.loadSfx( 'phase_4/audio/sfx/MG_sfx_ice_scoring_1.mp3') def unload(self): self.notify.debug('unload') DistributedMinigame.DistributedMinigame.unload(self) del self.music self.gameBoard.removeNode() del self.gameBoard for forceArrow in self.forceArrowDict.values(): forceArrow.removeNode() del self.forceArrowDict self.scoreCircle.removeNode() del self.scoreCircle del self.countSound def onstage(self): self.notify.debug('onstage') DistributedMinigame.DistributedMinigame.onstage(self) self.gameBoard.reparentTo(render) self._DistributedIceGame__placeToon(self.localAvId) self.moveCameraToTop() self.scorePanels = [] base.playMusic(self.music, looping=1, volume=0.80000000000000004) def offstage(self): self.notify.debug('offstage') self.music.stop() self.gameBoard.hide() self.infoLabel.hide() for avId in self.tireDict: self.tireDict[avId]['tireNodePath'].hide() for panel in self.scorePanels: panel.cleanup() del self.scorePanels for obstacle in self.obstacles: obstacle.hide() for treasure in self.treasures: treasure.nodePath.hide() for penalty in self.penalties: penalty.nodePath.hide() for avId in self.avIdList: av = self.getAvatar(avId) if av: av.dropShadow.show() av.resetLOD() continue taskMgr.remove(self.uniqueName('aimtask')) self.arrowKeys.destroy() del self.arrowKeys DistributedMinigame.DistributedMinigame.offstage(self) def handleDisabledAvatar(self, avId): self.notify.debug('handleDisabledAvatar') self.notify.debug('avatar ' + str(avId) + ' disabled') DistributedMinigame.DistributedMinigame.handleDisabledAvatar( self, avId) def setGameReady(self): if not self.hasLocalToon: return None self.notify.debug('setGameReady') if DistributedMinigame.DistributedMinigame.setGameReady(self): return None for index in xrange(self.numPlayers): avId = self.avIdList[index] toon = self.getAvatar(avId) if toon: toon.reparentTo(render) self._DistributedIceGame__placeToon(avId) toon.forwardSpeed = 0 toon.rotateSpeed = False toon.dropShadow.hide() toon.setAnimState('Sit') if avId in self.tireDict: tireNp = self.tireDict[avId]['tireNodePath'] toon.reparentTo(tireNp) toon.setY(1.0) toon.setZ(-3) toon.startLookAround() continue def setGameStart(self, timestamp): if not self.hasLocalToon: return None self.notify.debug('setGameStart') DistributedMinigame.DistributedMinigame.setGameStart(self, timestamp) for avId in self.remoteAvIdList: toon = self.getAvatar(avId) if toon: toon.stopLookAround() continue self.scores = [0] * self.numPlayers spacing = 0.40000000000000002 for i in xrange(self.numPlayers): avId = self.avIdList[i] avName = self.getAvatarName(avId) scorePanel = MinigameAvatarScorePanel.MinigameAvatarScorePanel( avId, avName) scorePanel.setScale(0.90000000000000002) scorePanel.setPos(0.75 - spacing * (self.numPlayers - 1 - i), 0.0, 0.875) scorePanel.makeTransparent(0.75) self.scorePanels.append(scorePanel) self.arrowKeys.setPressHandlers([ self._DistributedIceGame__upArrowPressed, self._DistributedIceGame__downArrowPressed, self._DistributedIceGame__leftArrowPressed, self._DistributedIceGame__rightArrowPressed, self._DistributedIceGame__controlPressed ]) def isInPlayState(self): if not self.gameFSM.getCurrentState(): return False if not self.gameFSM.getCurrentState().getName() == 'play': return False return True def enterOff(self): self.notify.debug('enterOff') def exitOff(self): pass def enterInputChoice(self): self.notify.debug('enterInputChoice') self.forceLocalToonToTire() self.controlKeyPressed = False if self.curRound == 0: self.setupStartOfMatch() else: self.notify.debug('self.curRound = %s' % self.curRound) self.timer = ToontownTimer.ToontownTimer() self.timer.hide() if self.timerStartTime != None: self.startTimer() self.showForceArrows(realPlayersOnly=True) self.localForceArrow().setPosHpr(0, 0, -1.0, 0, 0, 0) self.localForceArrow().reparentTo(self.localTireNp()) self.localForceArrow().setY(IceGameGlobals.TireRadius) self.localTireNp().headsUp(self.target) self.notify.debug('self.localForceArrow() heading = %s' % self.localForceArrow().getH()) self.curHeading = self.localTireNp().getH() self.curForce = 25 self.updateLocalForceArrow() for avId in self.forceArrowDict: forceArrow = self.forceArrowDict[avId] forceArrow.setPosHpr(0, 0, -1.0, 0, 0, 0) tireNp = self.tireDict[avId]['tireNodePath'] forceArrow.reparentTo(tireNp) forceArrow.setY(IceGameGlobals.TireRadius) tireNp.headsUp(self.target) self.updateForceArrow(avId, tireNp.getH(), 25) taskMgr.add(self._DistributedIceGame__aimTask, self.uniqueName('aimtask')) if base.localAvatar.laffMeter: base.localAvatar.laffMeter.stop() self.sendForceArrowUpdateAsap = False def exitInputChoice(self): if not self.controlKeyPressed: if self.controlKeyWarningIval: self.controlKeyWarningIval.finish() self.controlKeyWarningIval = None self.controlKeyWarningIval = Sequence( Func(self.controlKeyWarningLabel.show), self.controlKeyWarningLabel.colorScaleInterval( 10, VBase4(1, 1, 1, 0), startColorScale=VBase4(1, 1, 1, 1)), Func(self.controlKeyWarningLabel.hide)) self.controlKeyWarningIval.start() if self.timer != None: self.timer.destroy() self.timer = None self.timerStartTime = None self.hideForceArrows() self.arrowRotateSound.stop() self.arrowUpSound.stop() self.arrowDownSound.stop() taskMgr.remove(self.uniqueName('aimtask')) def enterWaitServerChoices(self): self.waitingMoveLabel.show() self.showForceArrows(True) def exitWaitServerChoices(self): self.waitingMoveLabel.hide() self.hideForceArrows() def enterMoveTires(self): for key in self.tireDict: body = self.tireDict[key]['tireBody'] body.setAngularVel(0, 0, 0) body.setLinearVel(0, 0, 0) for index in xrange(len(self.allTireInputs)): input = self.allTireInputs[index] avId = self.avIdList[index] body = self.getTireBody(avId) degs = input[1] + 90 tireNp = self.getTireNp(avId) tireH = tireNp.getH() self.notify.debug('tireH = %s' % tireH) radAngle = deg2Rad(degs) foo = NodePath('foo') dirVector = Vec3(math.cos(radAngle), math.sin(radAngle), 0) self.notify.debug('dirVector is now=%s' % dirVector) inputForce = input[0] inputForce /= self.MaxLocalForce inputForce *= self.MaxPhysicsForce force = dirVector * inputForce self.notify.debug('adding force %s to %d' % (force, avId)) body.addForce(force) self.enableAllTireBodies() self.totalPhysicsSteps = 0 self.startSim() taskMgr.add(self._DistributedIceGame__moveTiresTask, self.uniqueName('moveTiresTtask')) def exitMoveTires(self): self.forceLocalToonToTire() self.disableAllTireBodies() self.stopSim() self.notify.debug('total Physics steps = %d' % self.totalPhysicsSteps) taskMgr.remove(self.uniqueName('moveTiresTtask')) def enterSynch(self): self.waitingSyncLabel.show() def exitSynch(self): self.waitingSyncLabel.hide() def enterScoring(self): sortedByDistance = [] for avId in self.avIdList: np = self.getTireNp(avId) pos = np.getPos() pos.setZ(0) sortedByDistance.append((avId, pos.length())) def compareDistance(x, y): if x[1] - y[1] > 0: return 1 elif x[1] - y[1] < 0: return -1 else: return 0 sortedByDistance.sort(cmp=compareDistance) self.scoreMovie = Sequence() curScale = 0.01 curTime = 0 self.scoreCircle.setScale(0.01) self.scoreCircle.show() self.notify.debug('newScores = %s' % self.newScores) circleStartTime = 0 for index in xrange(len(sortedByDistance)): distance = sortedByDistance[index][1] avId = sortedByDistance[index][0] scorePanelIndex = self.avIdList.index(avId) time = (distance - curScale) / IceGameGlobals.ExpandFeetPerSec if time < 0: time = 0.01 scaleXY = distance + IceGameGlobals.TireRadius self.notify.debug('circleStartTime = %s' % circleStartTime) self.scoreMovie.append( Parallel( LerpScaleInterval(self.scoreCircle, time, Point3(scaleXY, scaleXY, 1.0)), SoundInterval(self.scoreCircleSound, duration=time, startTime=circleStartTime))) circleStartTime += time startScore = self.scorePanels[scorePanelIndex].getScore() destScore = self.newScores[scorePanelIndex] self.notify.debug('for avId %d, startScore=%d, newScores=%d' % (avId, startScore, destScore)) def increaseScores(t, scorePanelIndex=scorePanelIndex, startScore=startScore, destScore=destScore): oldScore = self.scorePanels[scorePanelIndex].getScore() diff = destScore - startScore newScore = int(startScore + diff * t) if newScore > oldScore: base.playSfx(self.countSound) self.scorePanels[scorePanelIndex].setScore(newScore) self.scores[scorePanelIndex] = newScore duration = (destScore - startScore) * IceGameGlobals.ScoreCountUpRate tireNp = self.tireDict[avId]['tireNodePath'] self.scoreMovie.append( Parallel( LerpFunctionInterval(increaseScores, duration), Sequence( LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 0, 0, 1)), LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 1, 1, 1)), LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 0, 0, 1)), LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 1, 1, 1)), LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 0, 0, 1)), LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 1, 1, 1))))) curScale += distance self.scoreMovie.append( Func(self.sendUpdate, 'reportScoringMovieDone', [])) self.scoreMovie.start() def exitScoring(self): self.scoreMovie.finish() self.scoreMovie = None self.scoreCircle.hide() def enterFinalResults(self): lerpTrack = Parallel() lerpDur = 0.5 tY = 0.59999999999999998 bY = -0.050000000000000003 lX = -0.5 cX = 0 rX = 0.5 scorePanelLocs = (((cX, bY), ), ((lX, bY), (rX, bY)), ((cX, tY), (lX, bY), (rX, bY)), ((lX, tY), (rX, tY), (lX, bY), (rX, bY))) scorePanelLocs = scorePanelLocs[self.numPlayers - 1] for i in xrange(self.numPlayers): panel = self.scorePanels[i] pos = scorePanelLocs[i] lerpTrack.append( Parallel( LerpPosInterval(panel, lerpDur, Point3(pos[0], 0, pos[1]), blendType='easeInOut'), LerpScaleInterval(panel, lerpDur, Vec3(panel.getScale()) * 2.0, blendType='easeInOut'))) self.showScoreTrack = Parallel( lerpTrack, Sequence(Wait(IceGameGlobals.ShowScoresDuration), Func(self.gameOver))) self.showScoreTrack.start() def exitFinalResults(self): self.showScoreTrack.pause() del self.showScoreTrack def enterCleanup(self): self.notify.debug('enterCleanup') if base.localAvatar.laffMeter: base.localAvatar.laffMeter.start() def exitCleanup(self): pass def _DistributedIceGame__placeToon(self, avId): toon = self.getAvatar(avId) if toon: toon.setPos(0, 0, 0) toon.setHpr(0, 0, 0) def moveCameraToTop(self): camera.reparentTo(render) p = self.cameraThreeQuarterView camera.setPosHpr(p[0], p[1], p[2], p[3], p[4], p[5]) def setupTire(self, avId, index): (tireNp, tireBody, tireOdeGeom) = self.createTire(index) self.tireDict[avId] = { 'tireNodePath': tireNp, 'tireBody': tireBody, 'tireOdeGeom': tireOdeGeom } if avId <= 0: tireBlocker = tireNp.find('**/tireblockermesh') if not tireBlocker.isEmpty(): tireBlocker.hide() if avId == self.localAvId: tireNp = self.tireDict[avId]['tireNodePath'] self.treasureSphereName = 'treasureCollider' self.treasureCollSphere = CollisionSphere( 0, 0, 0, IceGameGlobals.TireRadius) self.treasureCollSphere.setTangible(0) self.treasureCollNode = CollisionNode(self.treasureSphereName) self.treasureCollNode.setFromCollideMask( ToontownGlobals.PieBitmask) self.treasureCollNode.addSolid(self.treasureCollSphere) self.treasureCollNodePath = tireNp.attachNewNode( self.treasureCollNode) self.treasureHandler = CollisionHandlerEvent() self.treasureHandler.addInPattern('%fn-intoTreasure') base.cTrav.addCollider(self.treasureCollNodePath, self.treasureHandler) eventName = '%s-intoTreasure' % self.treasureCollNodePath.getName() self.notify.debug('eventName = %s' % eventName) self.accept(eventName, self.toonHitSomething) def setupForceArrow(self, avId): arrow = loader.loadModel('phase_4/models/minigames/ice_game_arrow') priority = 0 if avId < 0: priority = -avId else: priority = self.avIdList.index(avId) if avId == self.localAvId: priority = 10 self.forceArrowDict[avId] = arrow def hideForceArrows(self): for forceArrow in self.forceArrowDict.values(): forceArrow.hide() def showForceArrows(self, realPlayersOnly=True): for avId in self.forceArrowDict: if realPlayersOnly: if avId > 0: self.forceArrowDict[avId].show() else: self.forceArrowDict[avId].hide() avId > 0 self.forceArrowDict[avId].show() def localForceArrow(self): if self.localAvId in self.forceArrowDict: return self.forceArrowDict[self.localAvId] else: return None def setChoices(self, input0, input1, input2, input3): pass def startDebugTask(self): taskMgr.add(self.debugTask, self.debugTaskName) def stopDebugTask(self): taskMgr.remove(self.debugTaskName) def debugTask(self, task): if self.canDrive and self.tireDict.has_key(localAvatar.doId): dt = globalClock.getDt() forceMove = 25000 forceMoveDt = forceMove tireBody = self.tireDict[localAvatar.doId]['tireBody'] if self.arrowKeys.upPressed() and not tireBody.isEnabled(): x = 0 y = 1 tireBody.enable() tireBody.addForce(Vec3(x * forceMoveDt, y * forceMoveDt, 0)) if self.arrowKeys.downPressed() and not tireBody.isEnabled(): x = 0 y = -1 tireBody.enable() tireBody.addForce(Vec3(x * forceMoveDt, y * forceMoveDt, 0)) if self.arrowKeys.leftPressed() and not tireBody.isEnabled(): x = -1 y = 0 tireBody.enable() tireBody.addForce(Vec3(x * forceMoveDt, y * forceMoveDt, 0)) if self.arrowKeys.rightPressed() and not tireBody.isEnabled(): x = 1 y = 0 tireBody.enable() tireBody.addForce(Vec3(x * forceMoveDt, y * forceMoveDt, 0)) return task.cont def _DistributedIceGame__upArrowPressed(self): pass def _DistributedIceGame__downArrowPressed(self): pass def _DistributedIceGame__leftArrowPressed(self): pass def _DistributedIceGame__rightArrowPressed(self): pass def _DistributedIceGame__controlPressed(self): if self.gameFSM.getCurrentState().getName() == 'inputChoice': self.sendForceArrowUpdateAsap = True self.updateLocalForceArrow() self.controlKeyPressed = True self.sendUpdate('setAvatarChoice', [self.curForce, self.curHeading]) self.gameFSM.request('waitServerChoices') def startTimer(self): now = globalClock.getFrameTime() elapsed = now - self.timerStartTime self.timer.posInTopRightCorner() self.timer.setTime(IceGameGlobals.InputTimeout) self.timer.countdown(IceGameGlobals.InputTimeout - elapsed, self.handleChoiceTimeout) self.timer.show() def setTimerStartTime(self, timestamp): if not self.hasLocalToon: return None self.timerStartTime = globalClockDelta.networkToLocalTime(timestamp) if self.timer != None: self.startTimer() def handleChoiceTimeout(self): self.sendUpdate('setAvatarChoice', [0, 0]) self.gameFSM.request('waitServerChoices') def localTireNp(self): ret = None if self.localAvId in self.tireDict: ret = self.tireDict[self.localAvId]['tireNodePath'] return ret def localTireBody(self): ret = None if self.localAvId in self.tireDict: ret = self.tireDict[self.localAvId]['tireBody'] return ret def getTireBody(self, avId): ret = None if avId in self.tireDict: ret = self.tireDict[avId]['tireBody'] return ret def getTireNp(self, avId): ret = None if avId in self.tireDict: ret = self.tireDict[avId]['tireNodePath'] return ret def updateForceArrow(self, avId, curHeading, curForce): forceArrow = self.forceArrowDict[avId] tireNp = self.tireDict[avId]['tireNodePath'] tireNp.setH(curHeading) tireBody = self.tireDict[avId]['tireBody'] tireBody.setQuaternion(tireNp.getQuat()) self.notify.debug('curHeading = %s' % curHeading) yScale = curForce / 100.0 yScale *= 1 headY = yScale * 15 xScale = (yScale - 1) / 2.0 + 1.0 shaft = forceArrow.find('**/arrow_shaft') head = forceArrow.find('**/arrow_head') shaft.setScale(xScale, yScale, 1) head.setPos(0, headY, 0) head.setScale(xScale, xScale, 1) def updateLocalForceArrow(self): avId = self.localAvId self.b_setForceArrowInfo(avId, self.curHeading, self.curForce) def _DistributedIceGame__aimTask(self, task): if not hasattr(self, 'arrowKeys'): return task.done dt = globalClock.getDt() headingMomentumChange = dt * 60.0 forceMomentumChange = dt * 160.0 arrowUpdate = False arrowRotating = False arrowUp = False arrowDown = False if self.arrowKeys.upPressed() and not self.arrowKeys.downPressed(): self.forceMomentum += forceMomentumChange if self.forceMomentum < 0: self.forceMomentum = 0 if self.forceMomentum > 50: self.forceMomentum = 50 oldForce = self.curForce self.curForce += self.forceMomentum * dt arrowUpdate = True if oldForce < self.MaxLocalForce: arrowUp = True elif self.arrowKeys.downPressed() and not self.arrowKeys.upPressed(): self.forceMomentum += forceMomentumChange if self.forceMomentum < 0: self.forceMomentum = 0 if self.forceMomentum > 50: self.forceMomentum = 50 oldForce = self.curForce self.curForce -= self.forceMomentum * dt arrowUpdate = True if oldForce > 0.01: arrowDown = True else: self.forceMomentum = 0 if self.arrowKeys.leftPressed() and not self.arrowKeys.rightPressed(): self.headingMomentum += headingMomentumChange if self.headingMomentum < 0: self.headingMomentum = 0 if self.headingMomentum > 50: self.headingMomentum = 50 self.curHeading += self.headingMomentum * dt arrowUpdate = True arrowRotating = True elif self.arrowKeys.rightPressed( ) and not self.arrowKeys.leftPressed(): self.headingMomentum += headingMomentumChange if self.headingMomentum < 0: self.headingMomentum = 0 if self.headingMomentum > 50: self.headingMomentum = 50 self.curHeading -= self.headingMomentum * dt arrowUpdate = True arrowRotating = True else: self.headingMomentum = 0 if arrowUpdate: self.normalizeHeadingAndForce() self.updateLocalForceArrow() if arrowRotating: if not self.arrowRotateSound.status( ) == self.arrowRotateSound.PLAYING: base.playSfx(self.arrowRotateSound, looping=True) else: self.arrowRotateSound.stop() if arrowUp: if not self.arrowUpSound.status() == self.arrowUpSound.PLAYING: base.playSfx(self.arrowUpSound, looping=False) else: self.arrowUpSound.stop() if arrowDown: if not self.arrowDownSound.status() == self.arrowDownSound.PLAYING: base.playSfx(self.arrowDownSound, looping=False) else: self.arrowDownSound.stop() return task.cont def normalizeHeadingAndForce(self): if self.curForce > self.MaxLocalForce: self.curForce = self.MaxLocalForce if self.curForce < 0.01: self.curForce = 0.01 def setTireInputs(self, tireInputs): if not self.hasLocalToon: return None self.allTireInputs = tireInputs self.gameFSM.request('moveTires') def enableAllTireBodies(self): for avId in self.tireDict.keys(): self.tireDict[avId]['tireBody'].enable() def disableAllTireBodies(self): for avId in self.tireDict.keys(): self.tireDict[avId]['tireBody'].disable() def areAllTiresDisabled(self): for avId in self.tireDict.keys(): if self.tireDict[avId]['tireBody'].isEnabled(): return False continue return True def _DistributedIceGame__moveTiresTask(self, task): if self.areAllTiresDisabled(): self.sendTirePositions() self.gameFSM.request('synch') return task.done return task.cont def sendTirePositions(self): tirePositions = [] for index in xrange(len(self.avIdList)): avId = self.avIdList[index] tire = self.getTireBody(avId) pos = Point3(tire.getPosition()) tirePositions.append([pos[0], pos[1], pos[2]]) for index in xrange(len(self.avIdList), 4): avId = -index tire = self.getTireBody(avId) pos = Point3(tire.getPosition()) tirePositions.append([pos[0], pos[1], pos[2]]) self.sendUpdate('endingPositions', [tirePositions]) def setFinalPositions(self, finalPos): if not self.hasLocalToon: return None for index in xrange(len(self.avIdList)): avId = self.avIdList[index] tire = self.getTireBody(avId) np = self.getTireNp(avId) pos = finalPos[index] tire.setPosition(pos[0], pos[1], pos[2]) np.setPos(pos[0], pos[1], pos[2]) for index in xrange(len(self.avIdList), 4): avId = -index tire = self.getTireBody(avId) np = self.getTireNp(avId) pos = finalPos[index] tire.setPosition(pos[0], pos[1], pos[2]) np.setPos(pos[0], pos[1], pos[2]) def updateInfoLabel(self): self.infoLabel['text'] = TTLocalizer.IceGameInfo % { 'curMatch': self.curMatch + 1, 'numMatch': IceGameGlobals.NumMatches, 'curRound': self.curRound + 1, 'numRound': IceGameGlobals.NumRounds } def setMatchAndRound(self, match, round): if not self.hasLocalToon: return None self.curMatch = match self.curRound = round self.updateInfoLabel() def setScores(self, match, round, scores): if not self.hasLocalToon: return None self.newMatch = match self.newRound = round self.newScores = scores def setNewState(self, state): if not self.hasLocalToon: return None self.notify.debug('setNewState gameFSM=%s newState=%s' % (self.gameFSM, state)) self.gameFSM.request(state) def putAllTiresInStartingPositions(self): for index in xrange(len(self.avIdList)): avId = self.avIdList[index] np = self.tireDict[avId]['tireNodePath'] np.setPos(IceGameGlobals.StartingPositions[index]) self.notify.debug('avId=%s newPos=%s' % (avId, np.getPos)) np.setHpr(0, 0, 0) quat = np.getQuat() body = self.tireDict[avId]['tireBody'] body.setPosition(IceGameGlobals.StartingPositions[index]) body.setQuaternion(quat) for index in xrange(len(self.avIdList), 4): avId = -index np = self.tireDict[avId]['tireNodePath'] np.setPos(IceGameGlobals.StartingPositions[index]) self.notify.debug('avId=%s newPos=%s' % (avId, np.getPos)) np.setHpr(0, 0, 0) quat = np.getQuat() body = self.tireDict[avId]['tireBody'] body.setPosition(IceGameGlobals.StartingPositions[index]) body.setQuaternion(quat) def b_setForceArrowInfo(self, avId, force, heading): self.setForceArrowInfo(avId, force, heading) self.d_setForceArrowInfo(avId, force, heading) def d_setForceArrowInfo(self, avId, force, heading): sendIt = False curTime = self.getCurrentGameTime() if self.sendForceArrowUpdateAsap: sendIt = True elif curTime - self.lastForceArrowUpdateTime > 0.20000000000000001: sendIt = True if sendIt: self.sendUpdate('setForceArrowInfo', [avId, force, heading]) self.sendForceArrowUpdateAsap = False self.lastForceArrowUpdateTime = self.getCurrentGameTime() def setForceArrowInfo(self, avId, force, heading): if not self.hasLocalToon: return None self.updateForceArrow(avId, force, heading) def setupStartOfMatch(self): self.putAllTiresInStartingPositions() szId = self.getSafezoneId() self.numTreasures = IceGameGlobals.NumTreasures[szId] if self.treasures: for treasure in self.treasures: treasure.destroy() self.treasures = [] index = 0 treasureMargin = IceGameGlobals.TireRadius + 1.0 while len(self.treasures) < self.numTreasures: xPos = self.randomNumGen.randrange(IceGameGlobals.MinWall[0] + 5, IceGameGlobals.MaxWall[0] - 5) yPos = self.randomNumGen.randrange(IceGameGlobals.MinWall[1] + 5, IceGameGlobals.MaxWall[1] - 5) self.notify.debug('yPos=%s' % yPos) pos = Point3(xPos, yPos, IceGameGlobals.TireRadius) newTreasure = IceTreasure.IceTreasure(self.treasureModel, pos, index, self.doId, penalty=False) goodSpot = True for obstacle in self.obstacles: if newTreasure.nodePath.getDistance(obstacle) < treasureMargin: goodSpot = False break continue if goodSpot: for treasure in self.treasures: if newTreasure.nodePath.getDistance( treasure.nodePath) < treasureMargin: goodSpot = False break continue if goodSpot: self.treasures.append(newTreasure) index += 1 continue newTreasure.destroy() self.numPenalties = IceGameGlobals.NumPenalties[szId] if self.penalties: for penalty in self.penalties: penalty.destroy() self.penalties = [] index = 0 while len(self.penalties) < self.numPenalties: xPos = self.randomNumGen.randrange(IceGameGlobals.MinWall[0] + 5, IceGameGlobals.MaxWall[0] - 5) yPos = self.randomNumGen.randrange(IceGameGlobals.MinWall[1] + 5, IceGameGlobals.MaxWall[1] - 5) self.notify.debug('yPos=%s' % yPos) pos = Point3(xPos, yPos, IceGameGlobals.TireRadius) newPenalty = IceTreasure.IceTreasure(self.penaltyModel, pos, index, self.doId, penalty=True) goodSpot = True for obstacle in self.obstacles: if newPenalty.nodePath.getDistance(obstacle) < treasureMargin: goodSpot = False break continue if goodSpot: for treasure in self.treasures: if newPenalty.nodePath.getDistance( treasure.nodePath) < treasureMargin: goodSpot = False break continue if goodSpot: for penalty in self.penalties: if newPenalty.nodePath.getDistance( penalty.nodePath) < treasureMargin: goodSpot = False break continue if goodSpot: self.penalties.append(newPenalty) index += 1 continue newPenalty.destroy() def toonHitSomething(self, entry): self.notify.debug('---- treasure Enter ---- ') self.notify.debug('%s' % entry) name = entry.getIntoNodePath().getName() parts = name.split('-') if len(parts) < 3: self.notify.debug('collided with %s, but returning' % name) return None if not int(parts[1]) == self.doId: self.notify.debug("collided with %s, but doId doesn't match" % name) return None treasureNum = int(parts[2]) if 'penalty' in parts[0]: self._DistributedIceGame__penaltyGrabbed(treasureNum) else: self._DistributedIceGame__treasureGrabbed(treasureNum) def _DistributedIceGame__treasureGrabbed(self, treasureNum): self.treasures[treasureNum].showGrab() self.treasureGrabSound.play() self.sendUpdate('claimTreasure', [treasureNum]) def setTreasureGrabbed(self, avId, treasureNum): if not self.hasLocalToon: return None self.notify.debug('treasure %s grabbed by %s' % (treasureNum, avId)) if avId != self.localAvId: self.treasures[treasureNum].showGrab() i = self.avIdList.index(avId) self.scores[i] += 1 self.scorePanels[i].setScore(self.scores[i]) def _DistributedIceGame__penaltyGrabbed(self, penaltyNum): self.penalties[penaltyNum].showGrab() self.sendUpdate('claimPenalty', [penaltyNum]) def setPenaltyGrabbed(self, avId, penaltyNum): if not self.hasLocalToon: return None self.notify.debug('penalty %s grabbed by %s' % (penaltyNum, avId)) if avId != self.localAvId: self.penalties[penaltyNum].showGrab() i = self.avIdList.index(avId) self.scores[i] -= 1 self.scorePanels[i].setScore(self.scores[i]) def postStep(self): DistributedIceWorld.DistributedIceWorld.postStep(self) for count in range(self.colCount): (c0, c1) = self.getOrderedContacts(count) if c1 in self.tireCollideIds: tireIndex = self.tireCollideIds.index(c1) if c0 in self.tireCollideIds: self.tireSounds[tireIndex]['tireHit'].play() elif c0 == self.wallCollideId: self.tireSounds[tireIndex]['wallHit'].play() elif c0 == self.obstacleCollideId: self.tireSounds[tireIndex]['obstacleHit'].play() c0 in self.tireCollideIds def forceLocalToonToTire(self): toon = localAvatar if toon and self.localAvId in self.tireDict: tireNp = self.tireDict[self.localAvId]['tireNodePath'] toon.reparentTo(tireNp) toon.setPosHpr(0, 0, 0, 0, 0, 0) toon.setY(1.0) toon.setZ(-3)
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)