def loadAttack(self): self.phone = loader.loadModel('phase_3.5/models/props/phone.bam') self.phone.setHpr(0, 0, 180) if self.suit.type == 'B': self.phone.setPos(0.7, 0.15, 0) else: if self.suit.type == 'C': self.phone.setPos(0.25, 0, 0) self.receiver = loader.loadModel('phase_3.5/models/props/receiver.bam') self.receiver.reparentTo(self.phone) self.cord = Rope() self.cord.ropeNode.setUseVertexColor(1) self.cord.ropeNode.setUseVertexThickness(1) self.cord.setup(3, ({'node': self.phone, 'point': (0.8, 0, 0.2), 'color': (0, 0, 0, 1), 'thickness': 1000}, {'node': self.phone, 'point': (2, 0, 0), 'color': (0, 0, 0, 1), 'thickness': 1000}, {'node': self.receiver, 'point': (1.1, 0.25, 0.5), 'color': (0, 0, 0, 1), 'thickness': 1000}), []) self.cord.setH(180) self.phoneSfx = base.audio3d.loadSfx('phase_3.5/audio/sfx/SA_hangup.ogg') base.audio3d.attachSoundToObject(self.phoneSfx, self.phone) self.hangupSfx = base.audio3d.loadSfx('phase_3.5/audio/sfx/SA_hangup_place_down.ogg') base.audio3d.attachSoundToObject(self.hangupSfx, self.phone) collSphere = CollisionSphere(0, 0, 0, 2) collSphere.setTangible(0) collNode = CollisionNode('phone_shootout') collNode.addSolid(collSphere) collNode.setCollideMask(CIGlobals.WallBitmask) self.collNP = self.phone.attachNewNode(collNode)
def loadAttack(self): self.phone = loader.loadModel('phase_3.5/models/props/phone.bam') self.phone.setHpr(0, 0, 180) if self.suit.type == 'B': self.phone.setPos(0.7, 0.15, 0) elif self.suit.type == 'C': self.phone.setPos(0.25, 0, 0) self.receiver = loader.loadModel('phase_3.5/models/props/receiver.bam') self.receiver.reparentTo(self.phone) self.cord = Rope() self.cord.ropeNode.setUseVertexColor(1) self.cord.ropeNode.setUseVertexThickness(1) self.cord.setup(3, ({'node': self.phone, 'point': (0.8, 0, 0.2), 'color': (0, 0, 0, 1), 'thickness': 1000}, {'node': self.phone, 'point': (2, 0, 0), 'color': (0, 0, 0, 1), 'thickness': 1000}, {'node': self.receiver, 'point': (1.1, 0.25, 0.5), 'color': (0, 0, 0, 1), 'thickness': 1000}), []) self.cord.setH(180) self.phoneSfx = base.audio3d.loadSfx('phase_3.5/audio/sfx/SA_hangup.mp3') base.audio3d.attachSoundToObject(self.phoneSfx, self.phone) self.hangupSfx = base.audio3d.loadSfx('phase_3.5/audio/sfx/SA_hangup_place_down.mp3') base.audio3d.attachSoundToObject(self.hangupSfx, self.phone) collSphere = CollisionSphere(0, 0, 0, 2) collSphere.setTangible(0) collNode = CollisionNode('phone_shootout') collNode.addSolid(collSphere) collNode.setCollideMask(CIGlobals.WallBitmask) self.collNP = self.phone.attachNewNode(collNode)
def announceGenerate(self): DistributedNode.announceGenerate(self) self.kart = loader.loadModel('phase_6/models/karting/Kart3_Final.bam') self.kart.find('**/decals').removeNode() self.kart.reparentTo(self) self.pod = loader.loadModel('phase_4/models/minigames/pods_truck.egg') self.pod.reparentTo(self) self.pod.setScale(0.2) self.pod.setY(8.5) self.pod.setH(180) self.rope = Rope() self.rope.ropeNode.setUseVertexColor(1) self.rope.setup(3, ({'node': self.kart, 'point': (0, 1.5, 0.7), 'color': (0, 0, 0, 1), 'thickness': 1000}, {'node': self.kart, 'point': (0, 1.5, 0.7), 'color': (0, 0, 0, 1), 'thickness': 1000}, {'node': self.pod, 'point': (0, 31, 5), 'color': (0, 0, 0, 1), 'thickness': 1000}), []) self.rope.setH(180) self.rope.reparentTo(self) sphere = CollisionSphere(0, 0, 0, 2) sphere.setTangible(0) node = CollisionNode(self.uniqueName('truck_trigger')) node.addSolid(sphere) node.setCollideMask(CIGlobals.WallBitmask) self.triggerNP = self.attachNewNode(node) self.triggerNP.setPos(0, 8.0, 2.0) self.setScale(2.0) self.accept('enter' + self.triggerNP.node().getName(), self.__handleTruckTrigger)
def loadToonup(self, toonupIndex): self.toonupNum += 1 if toonupIndex in self.toonupModelDict: toonupModel = self.toonupModelDict[toonupIndex] toonupModel.reparentTo(self.foodNodes[toonupIndex]) colNp = toonupModel.find('**/ToonupCol*') colNp.setTag('toonupNum', str(self.toonupNum)) else: toonupModelScale = self.ToonupScales[toonupIndex] modelName = self.ToonupModels[toonupIndex] toonupModel = loader.loadModel(modelName) self.foodNodes[toonupIndex].setZ(self.beltHeight - 0.1) toonupModel.setZ(self.ToonupZOffsets[toonupIndex]) toonupModel.setScale(toonupModelScale) toonupModel.reparentTo(self.foodNodes[toonupIndex]) target = CollisionTube(4, 0, 0, -4, 0, 0, 2) target.setTangible(0) colName = 'ToonupCol-%d-%d' % (self.index, toonupIndex) targetNode = CollisionNode(colName) targetNode.addSolid(target) targetNode.setCollideMask(ToontownGlobals.WallBitmask) targetNodePath = toonupModel.attachNewNode(targetNode) targetNodePath.setScale(1.0 / toonupModelScale) targetNodePath.setTag('toonupIndex', str(toonupIndex)) targetNodePath.setTag('beltIndex', str(self.index)) targetNodePath.setTag('toonupNum', str(self.toonupNum)) targetNodePath.setZ(targetNodePath.getZ() - 1.5 / toonupModelScale) self.accept('enter' + colName, self.touchedToonup) self.toonupModelDict[toonupIndex] = toonupModel
def doAttack(self, particlePaths, track_name, particleCollId, animation_name, delayUntilRelease, animationSpeed=1, handObjPath=None, handObjParent=None, startRightAway=True, ts=0): for path in particlePaths: particle = ParticleLoader.loadParticleEffect(path) self.particles.append(particle) sphere = CollisionSphere(0, 0, 0, 1) sphere.setTangible(0) node = CollisionNode(particleCollId) node.addSolid(sphere) node.setCollideMask(CIGlobals.WallBitmask) self.targetX = self.attacksClass.target.getX(render) self.targetY = self.attacksClass.target.getY(render) self.targetZ = self.attacksClass.target.getZ(render) if len(self.particles) == 1: self.shootOutCollNP = self.particles[0].attachNewNode(node) else: self.shootOutCollNP = self.suit.attachNewNode(node) if handObjPath and handObjParent: self.handObj = loader.loadModel(handObjPath) self.handObj.reparentTo(handObjParent) self.suit.setPlayRate(animationSpeed, animation_name) self.suit.play(animation_name) if hasattr(self.suit, 'uniqueName'): track_name = self.suit.uniqueName(track_name) particleCollId = self.suit.uniqueName(particleCollId) self.suitTrack = Sequence(name=track_name) self.suitTrack.append(Wait(delayUntilRelease)) self.suitTrack.append(Func(self.releaseAttack)) self.suitTrack.append(Wait(self.particleIvalDur)) self.suitTrack.setDoneEvent(self.suitTrack.getName()) self.acceptOnce(self.suitTrack.getDoneEvent(), self.finishedAttack) if startRightAway: self.suitTrack.start(ts)
def loadFood(self, foodIndex): self.foodNum += 1 if foodIndex in self.foodModelDict: foodModel = self.foodModelDict[foodIndex] foodModel.reparentTo(self.foodNodes[foodIndex]) colNp = foodModel.find('**/FoodCol*') colNp.setTag('foodNum', str(self.foodNum)) else: foodModelScale = ToontownGlobals.BossbotFoodModelScale foodModel = loader.loadModel('phase_12/models/bossbotHQ/canoffood') foodModel.setScale(foodModelScale) foodModel.reparentTo(self.foodNodes[foodIndex]) target = CollisionTube(4, 0, 0, -4, 0, 0, 2) target.setTangible(0) colName = 'FoodCol-%d-%d' % (self.index, foodIndex) targetNode = CollisionNode(colName) targetNode.addSolid(target) targetNode.setCollideMask(ToontownGlobals.WallBitmask) targetNodePath = foodModel.attachNewNode(targetNode) targetNodePath.setScale(1.0 / foodModelScale) targetNodePath.setTag('foodIndex', str(foodIndex)) targetNodePath.setTag('beltIndex', str(self.index)) targetNodePath.setTag('foodNum', str(self.foodNum)) targetNodePath.setZ(targetNodePath.getZ() - 1.5) self.accept('enter' + colName, self.touchedFood) self.foodModelDict[foodIndex] = foodModel
def setupCollisions(self): sphere = CollisionSphere(0, 0, 0, 2) sphere.setTangible(0) node = CollisionNode(self.collisionName) node.addSolid(sphere) node.setCollideMask(CIGlobals.WallBitmask) self.collisionNode = self.attachNewNode(node)
def start(self): base.camLens.setNear(0.1) self.shooterTrav = CollisionTraverser('ToonFPS.shooterTrav') ray = CollisionRay() rayNode = CollisionNode('ToonFPS.rayNode') rayNode.addSolid(ray) rayNode.setCollideMask(BitMask32(0)) rayNode.setFromCollideMask(CIGlobals.WallBitmask | CIGlobals.FloorBitmask) self.shooterRay = ray self.shooterRayNode = base.camera.attachNewNode(rayNode) self.shooterHandler = CollisionHandlerQueue() self.shooterTrav.addCollider(self.shooterRayNode, self.shooterHandler) self.firstPerson.start() self.v_model_root.reparentTo(base.camera) self.v_model.reparentTo(self.v_model_root) if self.weaponName == "pistol": self.v_model_root.setZ(-1.8) self.v_model_root.setY(0.3) self.v_model_root.setX(-0.1) self.v_model_root.setH(2) elif self.weaponName == "sniper": self.v_model_root.setPos(-0.42, -0.81, -1.7) self.v_model_root.setHpr(359, 352.87, 0.00) elif self.weaponName == "shotgun": self.v_model_root.setPos(-0.42, -0.81, -1.7) self.v_model_root.setHpr(359, 352.87, 0.00) self.gui.start() self.firstPerson.disableMouse() self.aliveFSM.request('draw')
def doAttack(self, particlePaths, track_name, particleCollId, animation_name, delayUntilRelease, animationSpeed = 1, handObjPath = None, handObjParent = None, startRightAway = True, ts = 0): for path in particlePaths: particle = ParticleLoader.loadParticleEffect(path) self.particles.append(particle) sphere = CollisionSphere(0, 0, 0, 1) sphere.setTangible(0) node = CollisionNode(particleCollId) node.addSolid(sphere) node.setCollideMask(CIGlobals.WallBitmask) self.targetX = self.attacksClass.target.getX(render) self.targetY = self.attacksClass.target.getY(render) self.targetZ = self.attacksClass.target.getZ(render) if len(self.particles) == 1: self.shootOutCollNP = self.particles[0].attachNewNode(node) else: self.shootOutCollNP = self.suit.attachNewNode(node) if handObjPath and handObjParent: self.handObj = loader.loadModel(handObjPath) self.handObj.reparentTo(handObjParent) self.suit.setPlayRate(animationSpeed, animation_name) self.suit.play(animation_name) if hasattr(self.suit, 'uniqueName'): track_name = self.suit.uniqueName(track_name) particleCollId = self.suit.uniqueName(particleCollId) self.suitTrack = Sequence(name=track_name) self.suitTrack.append(Wait(delayUntilRelease)) self.suitTrack.append(Func(self.releaseAttack)) self.suitTrack.append(Wait(self.particleIvalDur)) self.suitTrack.setDoneEvent(self.suitTrack.getName()) self.acceptOnce(self.suitTrack.getDoneEvent(), self.finishedAttack) if startRightAway: self.suitTrack.start(ts)
def announceGenerate(self): self.reparentTo(render) base.minigame.flags.append(self) self.flagMdl = loader.loadModel( 'phase_4/models/minigames/flag_new.egg') self.flagMdl.reparentTo(render) self.flagMdl.find('**/flag').setTwoSided(1) self.flagMdl.find('**/flag_pole').setColor(self.pole_color) self.flagMdl.find('**/flag').setColor(self.colors[self.team]) hideNodes = ['icon2', 'icon3'] if self.team == GGG.Teams.BLUE: hideNodes = ['icon', 'icon1'] for node in hideNodes: part = self.flagMdl.find('**/%s' % node) if part: part.removeNode() sphere = CollisionSphere(0, 0, 0, 4) sphere.setTangible(0) node = CollisionNode(self.uniqueName('flagpoint_colnode')) node.addSolid(sphere) node.setCollideMask(CIGlobals.WallBitmask) self.collNP = self.attachNewNode(node) sphere = CollisionSphere(0, 0, 0, 2) sphere.setTangible(0) node = CollisionNode(self.uniqueName('flag_colnode')) node.addSolid(sphere) node.setCollideMask(CIGlobals.WallBitmask) self.flagCollNP = self.flagMdl.attachNewNode(node) pos, hpr = base.minigame.loader.getFlagPoint_Point(self.team) self.setPos(pos) self.setHpr(hpr)
def __setupCollisions(self): sphere = CollisionSphere(0, 0, 0, 4) sphere.setTangible(0) collisionNode = CollisionNode(self.uniqueName('NPCToonSphere')) collisionNode.addSolid(sphere) collisionNode.setCollideMask(CIGlobals.WallBitmask) self.collisionNodePath = self.attachNewNode(collisionNode) self.collisionNodePath.setY(1.5)
def setupWallSphere(self): sphere = CollisionSphere(0.0, 0.0, 0.0, 3.0) node = CollisionNode('DistributedPieTurret.WallSphere') node.addSolid(sphere) node.setCollideMask(CIGlobals.WallBitmask) self.wallCollNode = self.cannon.attachNewNode(node) self.wallCollNode.setZ(2) self.wallCollNode.setY(1.0)
def getSprayTrack(self, origin, target, scaleUp, hold, scaleDown, horizScale = 1.0, vertScale = 1.0): base.localAvatar.stop(self.toonAnim) self.lastFrame = self.avatar.getCurrentFrame(self.toonAnim) track = Sequence() sprayProp = loader.loadModel(GagGlobals.SPRAY_MDL) sprayProp.setTwoSided(1) sprayScale = hidden.attachNewNode('spray-parent') sprayRot = hidden.attachNewNode('spray-rotate') sprayRot.setColor(GagGlobals.WATER_SPRAY_COLOR) sprayRot.setTransparency(1) collNode = CollisionNode('Collision') spraySphere = CollisionSphere(0, 0, 0, 1) spraySphere.setTangible(0) collNode.addSolid(spraySphere) collNode.setCollideMask(CIGlobals.WallBitmask) sprayNP = sprayRot.attachNewNode(collNode) sprayNP.setY(1) self.sprayNP = sprayNP event = CollisionHandlerEvent() event.set_in_pattern('%fn-into') event.set_out_pattern('%fn-out') base.cTrav.add_collider(sprayNP, event) self.avatar.acceptOnce(sprayNP.node().getName() + '-into', self.onCollision) def showSpray(sprayScale, sprayProp, origin, target): objects = [sprayRot, sprayScale, sprayProp] for item in objects: index = objects.index(item) if index == 0: item.reparentTo(self.sprayJoint) item.setPos(self.sprayJoint.getPos(render)) item.setHpr(self.sprayJoint.getHpr(render)) item.setP(0) else: item.reparentTo(objects[index - 1]) item.clearMat() track.append(Func(showSpray, sprayScale, sprayProp, origin, target)) self.spray = sprayRot def calcTargetScale(): distance = Vec3(target - origin).length() yScale = distance / GagGlobals.SPRAY_LEN targetScale = Point3(yScale * horizScale, yScale, yScale * vertScale) return targetScale track.append(Parallel(LerpScaleInterval(sprayScale, scaleUp, calcTargetScale, startScale=GagGlobals.PNT3NEAR0), sprayNP.posInterval(0.25, self.spray.getPos(render) + Point3(0, 50, 0), startPos=self.spray.getPos(render) + Point3(0, 5, 0)))) track.append(Wait(hold)) track.append(Func(self.handleMiss)) track.append(LerpScaleInterval(sprayScale, 0.75, GagGlobals.PNT3NEAR0)) def hideSpray(): (lambda prop: prop.removeNode(), [sprayProp, sprayRot, sprayScale]) track.append(Func(hideSpray)) track.append(Func(self.completeSquirt)) return track
def __initShopCollisions(self, colName): self.notify.debug('Setting up shop collisions') shopSphere = CollisionSphere(0, 0, 0, 5) shopSphere.setTangible(0) shopNode = CollisionNode(colName) shopNode.addSolid(shopSphere) shopNode.setCollideMask(CIGlobals.WallBitmask) self.shopNP = self.attachNewNode(shopNode) self.shopNP.setZ(3) self.acceptOnce('enter' + self.shopNP.node().getName(), self.__handleShopCollision)
def setupPicker(self): self.pickerTrav = CollisionTraverser('LT.pickerTrav') self.pickerRay = CollisionRay() rayNode = CollisionNode('LT.pickerNode') rayNode.addSolid(self.pickerRay) rayNode.setCollideMask(BitMask32(0)) rayNode.setFromCollideMask(CIGlobals.WallBitmask) self.pickerRayNode = base.camera.attachNewNode(rayNode) self.pickerHandler = CollisionHandlerQueue() self.pickerTrav.addCollider(self.pickerRayNode, self.pickerHandler)
def __initializeEventSphere(self): sphere = CollisionSphere(0, 0, 0, 2) sphere.setTangible(0) node = CollisionNode(self.uniqueName('DEagleSuit-eventSphere')) node.addSolid(sphere) node.setCollideMask(CIGlobals.WallBitmask) np = self.attachNewNode(node) np.setSz(2.5) np.setZ(5.5) self.eventSphereNodePath = np
def __initInteractCollisions(self, colName): self.notify.debug('Setting up Coach collisions') collSphere = CollisionSphere(0, 0, 0, 5) collSphere.setTangible(0) collNode = CollisionNode(colName) collNode.addSolid(collSphere) collNode.setCollideMask(CIGlobals.WallBitmask) self.coachNP = self.attachNewNode(collNode) self.coachNP.setZ(3) self.acceptOnce('enter' + self.coachNP.node().getName(), self.__handleCollision)
def loadCollisions(self): sphere = CollisionSphere(0, 0, 0, 1) sphere.setTangible(0) node = CollisionNode(self.uniqueName('collectableCollNode')) node.addSolid(sphere) node.setCollideMask(CIGlobals.WallBitmask) self.collSensorNodePath = self.attachNewNode(node) ray = CollisionRay(0.0, 0.0, CollisionHandlerRayStart, 0.0, 0.0, -1.0) rayNode = CollisionNode(self.uniqueName('collectableRayNode')) rayNode.addSolid(ray) rayNode.setFromCollideMask(CIGlobals.FloorBitmask) rayNode.setIntoCollideMask(BitMask32.allOff()) self.collRayNodePath = self.attachNewNode(rayNode) lifter = CollisionHandlerFloor() lifter.addCollider(self.collRayNodePath, self) base.cTrav.addCollider(self.collRayNodePath, lifter)
def doAttack(self, weapon_path, weapon_scale, track_name, animation_name, collsphere_radius, weapon_coll_id, weapon_h = 0, weapon_p = 0, weapon_r = 0, weapon_x = 0, weapon_y = 0, weapon_z = 0, ts = 0): self.weapon_state = 'start' if hasattr(self.suit, 'uniqueName'): track_name = self.suit.uniqueName(track_name) weapon_coll_id = self.suit.uniqueName(weapon_coll_id) self.weapon = loader.loadModel(weapon_path) self.weapon.setScale(weapon_scale) self.weapon.setHpr(weapon_h, weapon_p, weapon_r) self.weapon.setPos(weapon_x, weapon_y, weapon_z) self.wss = CollisionSphere(0, 0, 0, collsphere_radius) self.wss.setTangible(0) self.targetX = self.attacksClass.target.getX(render) self.targetY = self.attacksClass.target.getY(render) self.targetZ = self.attacksClass.target.getZ(render) if self.attack not in ('glowerpower',): actorIval = ActorInterval(self.suit, animation_name, playRate=2.0, duration=1.2) actorIval2 = ActorInterval(self.suit, animation_name, startTime=2.4) else: actorIval = ActorInterval(self.suit, animation_name) seq = Sequence() if self.attack not in ('glowerpower',): self.suitTrack = Parallel(Sequence(actorIval, actorIval2), name=track_name) self.weapon.reparentTo(self.suit.find('**/joint_Rhold')) seq.append(Wait(1.2)) if self.suit.suitPlan.getSuitType() == 'C': seq.append(Wait(0)) else: seq.append(Wait(0.7)) seq.append(Func(self.throwObject)) seq.append(Wait(1.0)) seq.append(Func(self.delWeapon)) else: self.suitTrack = Parallel(actorIval, name=track_name) seq.append(Wait(1)) seq.append(Func(self.throwObject)) seq.append(Wait(0.5)) seq.append(Func(self.delWeapon)) self.suitTrack.append(seq) wsnode = CollisionNode(weapon_coll_id) wsnode.addSolid(self.wss) wsnode.setCollideMask(CIGlobals.WallBitmask) self.wsnp = self.weapon.attachNewNode(wsnode) self.suitTrack.setDoneEvent(self.suitTrack.getName()) self.acceptOnce(self.suitTrack.getDoneEvent(), self.finishedAttack) self.suitTrack.delayDelete = DelayDelete.DelayDelete(self.suit, track_name) self.suitTrack.start(ts)
def announceGenerate(self): DistributedNode.announceGenerate(self) self.kart = loader.loadModel('phase_6/models/karting/Kart3_Final.bam') self.kart.find('**/decals').removeNode() self.kart.reparentTo(self) self.pod = loader.loadModel('phase_4/models/minigames/pods_truck.egg') self.pod.reparentTo(self) self.pod.setScale(0.2) self.pod.setY(8.5) self.pod.setH(180) self.pod.find('**/metal_ramp').setBin('ground', 18) self.pod.find('**/metal_ramp_coll').setCollideMask( CIGlobals.FloorBitmask) self.rope = Rope() self.rope.ropeNode.setUseVertexColor(1) self.rope.setup(3, ({ 'node': self.kart, 'point': (0, 1.5, 0.7), 'color': (0, 0, 0, 1), 'thickness': 1000 }, { 'node': self.kart, 'point': (0, 1.5, 0.7), 'color': (0, 0, 0, 1), 'thickness': 1000 }, { 'node': self.pod, 'point': (0, 31, 5), 'color': (0, 0, 0, 1), 'thickness': 1000 }), []) self.rope.setH(180) self.rope.reparentTo(self) sphere = CollisionSphere(0, 0, 0, 2) sphere.setTangible(0) node = CollisionNode(self.uniqueName('truck_trigger')) node.addSolid(sphere) node.setCollideMask(CIGlobals.WallBitmask) self.triggerNP = self.attachNewNode(node) self.triggerNP.setPos(0, 8.0, 2.0) self.setScale(2.0) self.accept('enter' + self.triggerNP.node().getName(), self.__handleTruckTrigger)
def __init__(self, base, n, x, y, z): self.base = base self.n = n self.health = 4 self.np = base.loader.loadModel("./mdl/enemy.egg") self.np.setColor(1, 1, 0, 1) self.np.reparentTo(base.render) self.np.setPos(x, y, z) self.np.setAlphaScale(0.) base.target = self self.radar = OnscreenImage(image="./png/radar.png", pos=Vec3(0), scale=0.01) self.radar.setTransparency(TransparencyAttrib.MAlpha) # collisions cn = CollisionNode("enemy" + str(n)) cn.addSolid(CollisionBox(0, 2.5, 2, 0.5)) cn.setCollideMask(BitMask32(0x1) | BitMask32(0x2)) # cc = self.np.attachNewNode(cn) self.np.attachNewNode(cn) base.accept("fighter-into-enemy" + str(n), self.ship_collision) base.accept("bullet-into-enemy" + str(n), self.bullet_collision) base.accept("missile-into-enemy" + str(n), self.missile_collision) # sound self.snd_crash = base.loader.loadSfx("./snd/crash.flac") self.snd_blip = base.audio3d.loadSfx("./snd/blip.flac") self.snd_hit = base.loader.loadSfx("./snd/hit.flac") self.snd_explode = base.loader.loadSfx("./snd/explosion.flac") base.audio3d.attachSoundToObject(self.snd_blip, self.np) base.audio3d.setSoundVelocityAuto(self.snd_blip) base.audio3d.attachSoundToObject(self.snd_crash, self.np) base.audio3d.setSoundVelocityAuto(self.snd_crash) base.audio3d.attachSoundToObject(self.snd_hit, self.np) base.audio3d.setSoundVelocityAuto(self.snd_hit) base.audio3d.attachSoundToObject(self.snd_explode, self.np) base.audio3d.setSoundVelocityAuto(self.snd_explode) self.snd_blip.setLoop(True) self.snd_blip.play() self.setAI()
def __init__(self, size): DirectFrame.__init__(self, parent=aspect2d, pos=(0, -1.0, 0), relief=None) image = loader.loadModel( "phase_4/models/minigames/photo_game_viewfinder.bam") self['image'] = image self['image_scale'] = (size, 1.0, size) self.screenSizeMult = size * Viewfinder.Ratio self.setTransparency(True) self.setDepthWrite(1) self.setDepthTest(1) self.initialiseoptions(Viewfinder) self.captureCam = NodePath(Camera("CaptureCamera")) self.captureCam.reparentTo(base.camera) self.captureLens = PerspectiveLens() self.captureCam.node().setLens(self.captureLens) self.focusTrav = CollisionTraverser('focusTrav') ray = CollisionRay() rayNode = CollisionNode('rayNode') rayNode.addSolid(ray) rayNode.setCollideMask(BitMask32(0)) rayNode.setFromCollideMask(CIGlobals.WallBitmask) self.focusRay = ray self.focusRayNode = self.captureCam.attachNewNode(rayNode) self.focusHandler = CollisionHandlerQueue() self.focusTrav.addCollider(self.focusRayNode, self.focusHandler) self.textureBuffer = base.win.makeTextureBuffer( "ViewFinderCapture", int(128 * 1.33), 128) self.displayRegion = self.textureBuffer.makeDisplayRegion() self.displayRegion.setCamera(self.captureCam) self.__updateRegions() taskMgr.add(self.__update, "viewfinderUpdate")
def loadAttack(self): self.pen = loader.loadModel('phase_5/models/props/pen.bam') self.pen.reparentTo(self.suit.find('**/joint_Rhold')) self.sprayParticle = ParticleLoader.loadParticleEffect('phase_5/etc/penSpill.ptf') self.spray = loader.loadModel('phase_3.5/models/props/spray.bam') self.spray.setColor(VBase4(0, 0, 0, 1)) self.splat = Actor('phase_3.5/models/props/splat-mod.bam', {'chan': 'phase_3.5/models/props/splat-chan.bam'}) self.splat.setColor(VBase4(0, 0, 0, 1)) self.sprayScaleIval = LerpScaleInterval(self.spray, duration=0.3, scale=(1, 20, 1), startScale=(1, 1, 1)) sphere = CollisionSphere(0, 0, 0, 0.5) sphere.setTangible(0) if hasattr(self.suit, 'uniqueName'): collName = self.suit.uniqueName('fountainPenCollNode') else: collName = 'fountainPenCollNode' collNode = CollisionNode(collName) collNode.addSolid(sphere) collNode.setCollideMask(CIGlobals.WallBitmask) self.wsnp = self.spray.attachNewNode(collNode) self.wsnp.setY(1)
def doAttack(self, weapon_path, weapon_scale, track_name, animation_name, collsphere_radius, weapon_coll_id, weapon_h=0, weapon_p=0, weapon_r=0, weapon_x=0, weapon_y=0, weapon_z=0, ts=0): self.weapon_state = 'start' if hasattr(self.suit, 'uniqueName'): track_name = self.suit.uniqueName(track_name) weapon_coll_id = self.suit.uniqueName(weapon_coll_id) self.weapon = loader.loadModel(weapon_path) self.weapon.setScale(weapon_scale) self.weapon.setHpr(weapon_h, weapon_p, weapon_r) self.weapon.setPos(weapon_x, weapon_y, weapon_z) self.wss = CollisionSphere(0, 0, 0, collsphere_radius) self.wss.setTangible(0) self.targetX = self.attacksClass.target.getX(render) self.targetY = self.attacksClass.target.getY(render) self.targetZ = self.attacksClass.target.getZ(render) self.suitTrack = Sequence(name=track_name) if self.attack not in ('glowerpower', ): self.weapon.reparentTo(self.suit.find('**/joint_Rhold')) self.suitTrack.append(Wait(1.2)) self.suitTrack.append(Func(self.suit.setPlayRate, 1.0, animation_name)) if self.suit.type == 'C': self.suitTrack.append(Wait(0)) else: self.suitTrack.append(Wait(0.7)) self.suit.setPlayRate(2.0, animation_name) self.suitTrack.append(Func(self.throwObject)) self.suitTrack.append(Wait(1.0)) self.suitTrack.append(Func(self.delWeapon)) else: self.suitTrack.append(Wait(1)) self.suitTrack.append(Func(self.throwObject)) self.suitTrack.append(Wait(0.5)) self.suitTrack.append(Func(self.delWeapon)) self.suit.play(animation_name) wsnode = CollisionNode(weapon_coll_id) wsnode.addSolid(self.wss) wsnode.setCollideMask(CIGlobals.WallBitmask) self.wsnp = self.weapon.attachNewNode(wsnode) self.suitTrack.setDoneEvent(self.suitTrack.getName()) self.acceptOnce(self.suitTrack.getDoneEvent(), self.finishedAttack) self.suitTrack.delayDelete = DelayDelete.DelayDelete(self.suit, track_name) self.suitTrack.start(ts)
def start(self): self.fullyChargedSound = base.loadSfx( 'phase_4/audio/sfx/MG_pairing_match.ogg') self.rechargeSound = base.loadSfx( 'phase_4/audio/sfx/MG_sfx_travel_game_blue_arrow.ogg') self.batteryFrame = DirectFrame(parent=base.a2dBottomRight, pos=(-0.2, 0, 0.1), scale=(0.8, 0, 1)) self.batteryBg = OnscreenImage( image='phase_4/maps/battery_charge_frame.png', parent=self.batteryFrame) self.batteryBg.setTransparency(1) self.batteryBg.setX(0.03) self.batteryBg.setScale(0.17, 0, 0.05) self.batteryBar = DirectWaitBar(value=0, range=5, barColor=(1, 1, 1, 1), relief=None, scale=(0.12, 0.0, 0.3), parent=self.batteryFrame) self.cameraFocus = loader.loadModel( "phase_4/models/minigames/photo_game_viewfinder.bam") self.cameraFocus.reparentTo(base.aspect2d) self.focusTrav = CollisionTraverser('CSFP.focusTrav') ray = CollisionRay() rayNode = CollisionNode('CSFP.rayNode') rayNode.addSolid(ray) rayNode.setCollideMask(BitMask32(0)) rayNode.setFromCollideMask(CIGlobals.WallBitmask) self.focusRay = ray self.focusRayNode = base.camera.attachNewNode(rayNode) self.focusHandler = CollisionHandlerQueue() self.focusTrav.addCollider(self.focusRayNode, self.focusHandler) base.localAvatar.walkControls.setWalkSpeed(CIGlobals.ToonForwardSpeed, 0.0, CIGlobals.ToonReverseSpeed, CIGlobals.ToonRotateSpeed) FirstPerson.start(self)
def __init__(self, base, n, x, y, z): self.base = base self.n = n self.health = 4 self.np = base.loader.loadModel("./mdl/enemy.egg") self.np.setColor(1, 1, 0, 1) self.np.reparentTo(base.render) self.np.setPos(x, y, z) self.np.setAlphaScale(0.) base.target = self self.radar = OnscreenImage(image="./png/radar.png", pos=Vec3(0), scale=0.01) self.radar.setTransparency(TransparencyAttrib.MAlpha) # collisions cn = CollisionNode("enemy"+str(n)) cn.addSolid(CollisionBox(0, 2.5, 2, 0.5)) cn.setCollideMask(BitMask32(0x1) | BitMask32(0x2)) # cc = self.np.attachNewNode(cn) self.np.attachNewNode(cn) base.accept("fighter-into-enemy"+str(n), self.ship_collision) base.accept("bullet-into-enemy"+str(n), self.bullet_collision) base.accept("missile-into-enemy"+str(n), self.missile_collision) # sound self.snd_crash = base.loader.loadSfx("./snd/crash.flac") self.snd_blip = base.audio3d.loadSfx("./snd/blip.flac") self.snd_hit = base.loader.loadSfx("./snd/hit.flac") self.snd_explode = base.loader.loadSfx("./snd/explosion.flac") base.audio3d.attachSoundToObject(self.snd_blip, self.np) base.audio3d.setSoundVelocityAuto(self.snd_blip) base.audio3d.attachSoundToObject(self.snd_crash, self.np) base.audio3d.setSoundVelocityAuto(self.snd_crash) base.audio3d.attachSoundToObject(self.snd_hit, self.np) base.audio3d.setSoundVelocityAuto(self.snd_hit) base.audio3d.attachSoundToObject(self.snd_explode, self.np) base.audio3d.setSoundVelocityAuto(self.snd_explode) self.snd_blip.setLoop(True) self.snd_blip.play() self.setAI()
def generate(self): DistributedNode.generate(self) self.cart = loader.loadModel(self.cartModelPath) self.cart.reparentTo(self) self.cart.setH(180) heads = [] for head in CIGlobals.SuitBodyData.keys(): if CIGlobals.SuitBodyData[head][0] != 'B': heads.append(head) head = random.choice(heads) suitType = CIGlobals.SuitBodyData[head][0] suitDept = CIGlobals.SuitBodyData[head][1] self.suitInCar = Suit() self.suitInCar.generateSuit(suitType, head, suitDept, 137, 0, False) self.suitInCar.loop('sit') self.suitInCar.disableRay() self.suitInCar.setScale(0.7) self.suitInCar.setH(180) self.suitInCar.setPos(0, -1, -1.5) self.suitInCar.reparentTo(self.cart.find('**/seat1')) self.soundEngineLoop = base.audio3d.loadSfx('phase_6/audio/sfx/KART_Engine_loop_0.wav') base.audio3d.attachSoundToObject(self.soundEngineLoop, self) base.playSfx(self.soundEngineLoop, looping=1) self.soundDriveByHorn = base.audio3d.loadSfx(self.honkSfxPath) base.audio3d.attachSoundToObject(self.soundDriveByHorn, self) self.soundDriveBy = base.audio3d.loadSfx('phase_14/audio/sfx/cogtropolis_citycar_driveby.mp3') base.audio3d.attachSoundToObject(self.soundDriveBy, self) sphere = CollisionSphere(0, 0, 0, 2.5) sphere.setTangible(0) node = CollisionNode(self.uniqueName('cartSphere')) node.setCollideMask(CIGlobals.WallBitmask) node.addSolid(sphere) self.collNodePath = self.attachNewNode(node) self.collNodePath.setZ(1.5) self.collNodePath.setSy(2.0) self.collNodePath.setSx(1.75)
def generate(self): DistributedNode.generate(self) self.cart = loader.loadModel(self.cartModelPath) self.cart.reparentTo(self) self.cart.setH(180) heads = [] for head in CIGlobals.SuitBodyData.keys(): if CIGlobals.SuitBodyData[head][0] != 'B': heads.append(head) head = random.choice(heads) suitType = CIGlobals.SuitBodyData[head][0] suitDept = CIGlobals.SuitBodyData[head][1] self.suitInCar = Suit() self.suitInCar.generateSuit(suitType, head, suitDept, 137, 0, False) self.suitInCar.loop('sit') self.suitInCar.disableRay() self.suitInCar.setScale(0.7) self.suitInCar.setH(180) self.suitInCar.setPos(0, -1, -1.5) self.suitInCar.reparentTo(self.cart.find('**/seat1')) self.soundEngineLoop = base.audio3d.loadSfx('phase_6/audio/sfx/KART_Engine_loop_0.ogg') base.audio3d.attachSoundToObject(self.soundEngineLoop, self) base.playSfx(self.soundEngineLoop, looping = 1) self.soundDriveByHorn = base.audio3d.loadSfx(self.honkSfxPath) base.audio3d.attachSoundToObject(self.soundDriveByHorn, self) self.soundDriveBy = base.audio3d.loadSfx('phase_14/audio/sfx/cogtropolis_citycar_driveby.ogg') base.audio3d.attachSoundToObject(self.soundDriveBy, self) sphere = CollisionSphere(0, 0, 0, 2.5) sphere.setTangible(0) node = CollisionNode(self.uniqueName('cartSphere')) node.setCollideMask(CIGlobals.WallBitmask) node.addSolid(sphere) self.collNodePath = self.attachNewNode(node) self.collNodePath.setZ(1.5) self.collNodePath.setSy(2.0) self.collNodePath.setSx(1.75)
def generate(self): DistributedNode.generate(self) self.cart = loader.loadModel(self.cartModelPath) self.cart.reparentTo(self) self.cart.setH(180) plans = [] for plan in SuitBank.getSuits(): if plan.getSuitType() != SuitType.B: plans.append(plan) plan = random.choice(plans) self.suitInCar = Suit() self.suitInCar.level = 0 self.suitInCar.generate(plan, Variant.NORMAL) self.suitInCar.loop('sit') self.suitInCar.disableRay() self.suitInCar.setScale(0.7) self.suitInCar.setH(180) self.suitInCar.setPos(0, -1, -1.5) self.suitInCar.reparentTo(self.cart.find('**/seat1')) self.suitInCar.show() self.soundEngineLoop = base.audio3d.loadSfx('phase_6/audio/sfx/KART_Engine_loop_0.ogg') base.audio3d.attachSoundToObject(self.soundEngineLoop, self) base.playSfx(self.soundEngineLoop, looping = 1) self.soundDriveByHorn = base.audio3d.loadSfx(self.honkSfxPath) base.audio3d.attachSoundToObject(self.soundDriveByHorn, self) self.soundDriveBy = base.audio3d.loadSfx('phase_14/audio/sfx/cogtropolis_citycar_driveby.ogg') base.audio3d.attachSoundToObject(self.soundDriveBy, self) sphere = CollisionSphere(0, 0, 0, 2.5) sphere.setTangible(0) node = CollisionNode(self.uniqueName('cartSphere')) node.setCollideMask(CIGlobals.WallBitmask) node.addSolid(sphere) self.collNodePath = self.attachNewNode(node) self.collNodePath.setZ(1.5) self.collNodePath.setSy(2.0) self.collNodePath.setSx(1.75)
class DistributedLawbotCannon(DistributedObject.DistributedObject): notify = DirectNotifyGlobal.directNotify.newCategory( 'DistributedLawbotCannon') LOCAL_CANNON_MOVE_TASK = 'localCannonMoveTask' FIRE_KEY = 'control' UP_KEY = 'arrow_up' DOWN_KEY = 'arrow_down' LEFT_KEY = 'arrow_left' RIGHT_KEY = 'arrow_right' HIT_GROUND = 0 def __init__(self, cr): DistributedObject.DistributedObject.__init__(self, cr) self.index = None self.avId = 0 self.av = None self.localToonShooting = 0 self.cannonsActive = 0 self.cannonLocation = None self.cannonPostion = None self.cannon = None self.madeGui = 0 self.jurorToon = None self.toonModel = None self.toonHead = None self.toonScale = None self.dustCloud = None self.hitBumper = 0 self.hitTarget = 0 self.lastPos = Vec3(0, 0, 0) self.lastVel = Vec3(0, 0, 0) self.vel = Vec3(0, 0, 0) self.landingPos = Vec3(0, 0, 0) self.t = 0 self.lastT = 0 self.deltaT = 0 self.hitTrack = None self.flyColNode = None self.flyColNodePath = None self.localAvId = base.localAvatar.doId self.model_Created = 0 return def disable(self): taskMgr.remove(self.uniqueName('fireCannon')) taskMgr.remove(self.uniqueName('shootTask')) self.__stopFlyTask(self.avId) taskMgr.remove(self.uniqueName('flyTask')) self.ignoreAll() self.setMovie(CannonGlobals.CANNON_MOVIE_CLEAR, 0, 0) self.nodePath.detachNode() self.__unmakeGui() if self.hitTrack: self.hitTrack.finish() del self.hitTrack self.hitTrack = None DistributedObject.DistributedObject.disable(self) return def delete(self): self.offstage() self.unload() DistributedObject.DistributedObject.delete(self) def announceGenerate(self): DistributedObject.DistributedObject.announceGenerate(self) self.boss.cannons[self.index] = self def generateInit(self): DistributedObject.DistributedObject.generateInit(self) self.nodePath = NodePath(self.uniqueName('Cannon')) self.load() self.activateCannons() def setPosHpr(self, x, y, z, h, p, r): self.nodePath.setPosHpr(x, y, z, h, p, r) def setBossCogId(self, bossCogId): self.bossCogId = bossCogId self.boss = base.cr.doId2do[bossCogId] def getSphereRadius(self): return 1.5 def getParentNodePath(self): return render def setIndex(self, index): self.index = index def load(self): self.cannon = loader.loadModel('phase_4/models/minigames/toon_cannon') self.collSphere = CollisionSphere(0, 0, 0, self.getSphereRadius()) self.dustCloud = DustCloud.DustCloud(render) self.dustCloud.setBillboardPointEye() self.collSphere.setTangible(1) self.collNode = CollisionNode(self.uniqueName('CannonSphere')) self.collNode.setCollideMask(ToontownGlobals.WallBitmask) self.collNode.addSolid(self.collSphere) self.collNodePath = self.nodePath.attachNewNode(self.collNode) self.cannon.reparentTo(self.nodePath) self.kartColNode = CollisionNode(self.uniqueName('KartColNode')) self.kartNode = self.nodePath.attachNewNode(self.kartColNode) self.sndCannonMove = base.loader.loadSfx( 'phase_4/audio/sfx/MG_cannon_adjust.ogg') self.sndCannonFire = base.loader.loadSfx( 'phase_4/audio/sfx/MG_cannon_fire_alt.ogg') self.sndHitGround = base.loader.loadSfx( 'phase_4/audio/sfx/MG_cannon_hit_dirt.ogg') self.sndHitChair = base.loader.loadSfx( 'phase_11/audio/sfx/LB_toon_jury.ogg') self.cannon.hide() self.flashingLabel = None return def unload(self): if self.cannon: self.cannon.removeNode() del self.cannon if self.dustCloud != None: self.dustCloud.destroy() del self.dustCloud del self.sndCannonMove del self.sndCannonFire del self.sndHitGround del self.sndHitChair if self.av: self.__resetToon(self.av) self.av.loop('neutral') self.av.setPlayRate(1.0, 'run') if self.toonHead != None: self.toonHead.stopBlink() self.toonHead.stopLookAroundNow() self.toonHead.delete() del self.toonHead if self.toonModel != None: self.toonModel.removeNode() del self.toonModel if self.jurorToon != None: self.jurorToon.delete() del self.jurorToon del self.toonScale return def activateCannons(self): if not self.cannonsActive: self.cannonsActive = 1 self.onstage() self.nodePath.reparentTo(self.getParentNodePath()) self.accept(self.uniqueName('enterCannonSphere'), self.__handleEnterSphere) def onstage(self): self.__createCannon() self.cannon.reparentTo(self.nodePath) self.dustCloud.reparentTo(render) def offstage(self): if self.cannon: self.cannon.reparentTo(hidden) if self.dustCloud: self.dustCloud.reparentTo(hidden) self.dustCloud.stop() def __createCannon(self): self.barrel = self.cannon.find('**/cannon') self.cannonLocation = Point3(0, 0, 0.025) self.cannonPosition = [0, CANNON_ANGLE_MIN] self.cannon.setPos(self.cannonLocation) self.__updateCannonPosition(self.avId) def updateCannonPosition(self, avId, zRot, angle): if avId != self.localAvId: self.cannonPosition = [zRot, angle] self.__updateCannonPosition(avId) def __updateCannonPosition(self, avId): self.cannon.setHpr(self.cannonPosition[0], 0.0, 0.0) self.barrel.setHpr(0.0, self.cannonPosition[1], 0.0) maxP = 90 newP = self.barrel.getP() yScale = 1 - 0.5 * float(newP) / maxP shadow = self.cannon.find('**/square_drop_shadow') shadow.setScale(1, yScale, 1) def __handleEnterSphere(self, collEntry): self.d_requestEnter() def d_requestEnter(self): self.sendUpdate('requestEnter', []) def setMovie(self, mode, avId, extraInfo): wasLocalToon = self.localToonShooting self.avId = avId if mode == CannonGlobals.CANNON_MOVIE_CLEAR: self.setLanded() else: if mode == CannonGlobals.CANNON_MOVIE_LANDED: self.setLanded() else: if mode == CannonGlobals.CANNON_MOVIE_FORCE_EXIT: self.exitCannon(self.avId) self.setLanded() else: if mode == CannonGlobals.CANNON_MOVIE_LOAD: if self.avId == base.localAvatar.doId: self.cannonBallsLeft = extraInfo base.cr.playGame.getPlace().setState('crane') base.localAvatar.setTeleportAvailable(0) self.localToonShooting = 1 self.__makeGui() camera.reparentTo(self.barrel) camera.setPos(0.5, -2, 2.5) camera.setHpr(0, 0, 0) self.boss.toonEnteredCannon(self.avId, self.index) if self.avId in self.cr.doId2do: self.av = self.cr.doId2do[self.avId] self.acceptOnce(self.av.uniqueName('disable'), self.__avatarGone) self.av.loop('neutral') self.av.stopSmooth() self.__destroyToonModels() self.__createToonModels() self.av.setPosHpr(3, 0, 0, 90, 0, 0) self.av.reparentTo(self.cannon) else: self.notify.warning( 'Unknown avatar %d in cannon %d' % (self.avId, self.doId)) else: self.notify.warning('unhandled case, mode = %d' % mode) def __avatarGone(self): self.setMovie(CannonGlobals.CANNON_MOVIE_CLEAR, 0, 0) def __makeGui(self): if self.madeGui: return NametagGlobals.setMasterArrowsOn(0) guiModel = 'phase_4/models/gui/cannon_game_gui' cannonGui = loader.loadModel(guiModel) self.aimPad = DirectFrame(image=cannonGui.find('**/CannonFire_PAD'), relief=None, pos=(0.7, 0, -0.553333), scale=0.8) cannonGui.removeNode() self.fireButton = DirectButton(parent=self.aimPad, image=((guiModel, '**/Fire_Btn_UP'), (guiModel, '**/Fire_Btn_DN'), (guiModel, '**/Fire_Btn_RLVR')), relief=None, pos=(0.0115741, 0, 0.00505051), scale=1.0, command=self.__firePressed) self.upButton = DirectButton(parent=self.aimPad, image=((guiModel, '**/Cannon_Arrow_UP'), (guiModel, '**/Cannon_Arrow_DN'), (guiModel, '**/Cannon_Arrow_RLVR')), relief=None, pos=(0.0115741, 0, 0.221717)) self.downButton = DirectButton(parent=self.aimPad, image=((guiModel, '**/Cannon_Arrow_UP'), (guiModel, '**/Cannon_Arrow_DN'), (guiModel, '**/Cannon_Arrow_RLVR')), relief=None, pos=(0.0136112, 0, -0.210101), image_hpr=(0, 0, 180)) self.leftButton = DirectButton(parent=self.aimPad, image=((guiModel, '**/Cannon_Arrow_UP'), (guiModel, '**/Cannon_Arrow_DN'), (guiModel, '**/Cannon_Arrow_RLVR')), relief=None, pos=(-0.199352, 0, -0.000505269), image_hpr=(0, 0, -90)) self.rightButton = DirectButton( parent=self.aimPad, image=((guiModel, '**/Cannon_Arrow_UP'), (guiModel, '**/Cannon_Arrow_DN'), (guiModel, '**/Cannon_Arrow_RLVR')), relief=None, pos=(0.219167, 0, -0.00101024), image_hpr=(0, 0, 90)) guiClose = loader.loadModel('phase_3.5/models/gui/avatar_panel_gui') cannonBallText = '%d/%d' % (self.cannonBallsLeft, ToontownGlobals.LawbotBossCannonBallMax) self.cannonBallLabel = DirectLabel(parent=self.aimPad, text=cannonBallText, text_fg=VBase4(1, 1, 1, 1), text_align=TextNode.ACenter, relief=None, pos=(0.475, 0.0, -0.35), scale=0.25) if self.cannonBallsLeft < 5: if self.flashingLabel: self.flashingLabel.stop() flashingTrack = Sequence() for i in range(10): flashingTrack.append( LerpColorScaleInterval(self.cannonBallLabel, 0.5, VBase4(1, 0, 0, 1))) flashingTrack.append( LerpColorScaleInterval(self.cannonBallLabel, 0.5, VBase4(1, 1, 1, 1))) self.flashingLabel = flashingTrack self.flashingLabel.start() self.aimPad.setColor(1, 1, 1, 0.9) def bindButton(button, upHandler, downHandler): button.bind(DGG.B1PRESS, lambda x, handler=upHandler: handler()) button.bind(DGG.B1RELEASE, lambda x, handler=downHandler: handler()) bindButton(self.upButton, self.__upPressed, self.__upReleased) bindButton(self.downButton, self.__downPressed, self.__downReleased) bindButton(self.leftButton, self.__leftPressed, self.__leftReleased) bindButton(self.rightButton, self.__rightPressed, self.__rightReleased) self.__enableAimInterface() self.madeGui = 1 return def __unmakeGui(self): self.notify.debug('__unmakeGui') if not self.madeGui: return if self.flashingLabel: self.flashingLabel.finish() self.flashingLabel = None NametagGlobals.setMasterArrowsOn(1) self.__disableAimInterface() self.upButton.unbind(DGG.B1PRESS) self.upButton.unbind(DGG.B1RELEASE) self.downButton.unbind(DGG.B1PRESS) self.downButton.unbind(DGG.B1RELEASE) self.leftButton.unbind(DGG.B1PRESS) self.leftButton.unbind(DGG.B1RELEASE) self.rightButton.unbind(DGG.B1PRESS) self.rightButton.unbind(DGG.B1RELEASE) self.aimPad.destroy() del self.aimPad del self.fireButton del self.upButton del self.downButton del self.leftButton del self.rightButton self.madeGui = 0 return def __enableAimInterface(self): self.aimPad.show() self.accept(self.FIRE_KEY, self.__fireKeyPressed) self.accept(self.UP_KEY, self.__upKeyPressed) self.accept(self.DOWN_KEY, self.__downKeyPressed) self.accept(self.LEFT_KEY, self.__leftKeyPressed) self.accept(self.RIGHT_KEY, self.__rightKeyPressed) self.__spawnLocalCannonMoveTask() def __disableAimInterface(self): self.aimPad.hide() self.ignore(self.FIRE_KEY) self.ignore(self.UP_KEY) self.ignore(self.DOWN_KEY) self.ignore(self.LEFT_KEY) self.ignore(self.RIGHT_KEY) self.ignore(self.FIRE_KEY + '-up') self.ignore(self.UP_KEY + '-up') self.ignore(self.DOWN_KEY + '-up') self.ignore(self.LEFT_KEY + '-up') self.ignore(self.RIGHT_KEY + '-up') self.__killLocalCannonMoveTask() def __fireKeyPressed(self): self.ignore(self.FIRE_KEY) self.accept(self.FIRE_KEY + '-up', self.__fireKeyReleased) self.__firePressed() def __upKeyPressed(self): self.ignore(self.UP_KEY) self.accept(self.UP_KEY + '-up', self.__upKeyReleased) self.__upPressed() def __downKeyPressed(self): self.ignore(self.DOWN_KEY) self.accept(self.DOWN_KEY + '-up', self.__downKeyReleased) self.__downPressed() def __leftKeyPressed(self): self.ignore(self.LEFT_KEY) self.accept(self.LEFT_KEY + '-up', self.__leftKeyReleased) self.__leftPressed() def __rightKeyPressed(self): self.ignore(self.RIGHT_KEY) self.accept(self.RIGHT_KEY + '-up', self.__rightKeyReleased) self.__rightPressed() def __fireKeyReleased(self): self.ignore(self.FIRE_KEY + '-up') self.accept(self.FIRE_KEY, self.__fireKeyPressed) def __leftKeyReleased(self): self.ignore(self.LEFT_KEY + '-up') self.accept(self.LEFT_KEY, self.__leftKeyPressed) self.__leftReleased() def __rightKeyReleased(self): self.ignore(self.RIGHT_KEY + '-up') self.accept(self.RIGHT_KEY, self.__rightKeyPressed) self.__rightReleased() def __upKeyReleased(self): self.ignore(self.UP_KEY + '-up') self.accept(self.UP_KEY, self.__upKeyPressed) self.__upReleased() def __downKeyReleased(self): self.ignore(self.DOWN_KEY + '-up') self.accept(self.DOWN_KEY, self.__downKeyPressed) self.__downReleased() def __leaveCannon(self): self.notify.debug('__leaveCannon') self.sendUpdate('requestLeave') def __firePressed(self): self.notify.debug('fire pressed') if not self.boss.state == 'BattleTwo': self.notify.debug('boss is in state=%s, not firing' % self.boss.state) return self.__broadcastLocalCannonPosition() self.__unmakeGui() self.sendUpdate('setCannonLit', [self.cannonPosition[0], self.cannonPosition[1]]) def __upPressed(self): self.notify.debug('up pressed') self.upPressed = self.__enterControlActive(self.upPressed) def __downPressed(self): self.notify.debug('down pressed') self.downPressed = self.__enterControlActive(self.downPressed) def __leftPressed(self): self.notify.debug('left pressed') self.leftPressed = self.__enterControlActive(self.leftPressed) def __rightPressed(self): self.notify.debug('right pressed') self.rightPressed = self.__enterControlActive(self.rightPressed) def __upReleased(self): self.notify.debug('up released') self.upPressed = self.__exitControlActive(self.upPressed) def __downReleased(self): self.notify.debug('down released') self.downPressed = self.__exitControlActive(self.downPressed) def __leftReleased(self): self.notify.debug('left released') self.leftPressed = self.__exitControlActive(self.leftPressed) def __rightReleased(self): self.notify.debug('right released') self.rightPressed = self.__exitControlActive(self.rightPressed) def __enterControlActive(self, control): return control + 1 def __exitControlActive(self, control): return max(0, control - 1) def __spawnLocalCannonMoveTask(self): self.leftPressed = 0 self.rightPressed = 0 self.upPressed = 0 self.downPressed = 0 self.cannonMoving = 0 task = Task(self.__localCannonMoveTask) task.lastPositionBroadcastTime = 0.0 taskMgr.add(task, self.LOCAL_CANNON_MOVE_TASK) def __killLocalCannonMoveTask(self): taskMgr.remove(self.LOCAL_CANNON_MOVE_TASK) if self.cannonMoving: self.sndCannonMove.stop() def __localCannonMoveTask(self, task): pos = self.cannonPosition oldRot = pos[0] oldAng = pos[1] rotVel = 0 if self.leftPressed: rotVel += CANNON_ROTATION_VEL if self.rightPressed: rotVel -= CANNON_ROTATION_VEL pos[0] += rotVel * globalClock.getDt() if pos[0] < CANNON_ROTATION_MIN: pos[0] = CANNON_ROTATION_MIN else: if pos[0] > CANNON_ROTATION_MAX: pos[0] = CANNON_ROTATION_MAX angVel = 0 if self.upPressed: angVel += CANNON_ANGLE_VEL if self.downPressed: angVel -= CANNON_ANGLE_VEL pos[1] += angVel * globalClock.getDt() if pos[1] < CANNON_ANGLE_MIN: pos[1] = CANNON_ANGLE_MIN else: if pos[1] > CANNON_ANGLE_MAX: pos[1] = CANNON_ANGLE_MAX if oldRot != pos[0] or oldAng != pos[1]: if self.cannonMoving == 0: self.cannonMoving = 1 base.playSfx(self.sndCannonMove, looping=1) self.__updateCannonPosition(self.localAvId) if task.time - task.lastPositionBroadcastTime > CANNON_MOVE_UPDATE_FREQ: task.lastPositionBroadcastTime = task.time self.__broadcastLocalCannonPosition() else: if self.cannonMoving: self.cannonMoving = 0 self.sndCannonMove.stop() self.__broadcastLocalCannonPosition() return Task.cont def __broadcastLocalCannonPosition(self): self.sendUpdate('setCannonPosition', [self.cannonPosition[0], self.cannonPosition[1]]) def __updateCannonPosition(self, avId): self.cannon.setHpr(self.cannonPosition[0], 0.0, 0.0) self.barrel.setHpr(0.0, self.cannonPosition[1], 0.0) maxP = 90 newP = self.barrel.getP() yScale = 1 - 0.5 * float(newP) / maxP shadow = self.cannon.find('**/square_drop_shadow') shadow.setScale(1, yScale, 1) def __createToonModels(self): self.model_Created = 1 self.jurorToon = NPCToons.createLocalNPC( ToontownGlobals.LawbotBossBaseJurorNpcId + self.index) self.toonScale = self.jurorToon.getScale() jurorToonParent = render.attachNewNode('toonOriginChange') self.jurorToon.wrtReparentTo(jurorToonParent) self.jurorToon.setPosHpr(0, 0, -(self.jurorToon.getHeight() / 2.0), 0, -90, 0) self.toonModel = jurorToonParent self.toonHead = ToonHead.ToonHead() self.toonHead.setupHead(self.jurorToon.style) self.toonHead.reparentTo(hidden) self.__loadToonInCannon() def __destroyToonModels(self): if self.toonHead != None: self.toonHead.reparentTo(hidden) self.toonHead.stopBlink() self.toonHead.stopLookAroundNow() self.toonHead = None if self.toonModel != None: self.toonModel.removeNode() self.toonModel = None if self.jurorToon != None: self.jurorToon.delete() self.jurorToon = None self.model_Created = 0 return def __loadToonInCannon(self): self.toonModel.reparentTo(hidden) self.toonHead.startBlink() self.toonHead.startLookAround() self.toonHead.reparentTo(self.barrel) self.toonHead.setPosHpr(0, 6, 0, 0, -45, 0) sc = self.toonScale self.toonHead.setScale(render, sc[0], sc[1], sc[2]) def exitCannon(self, avId): self.__unmakeGui() if self.avId == avId: self.av.reparentTo(render) self.__resetToonToCannon(self.av) def __resetToonToCannon(self, avatar): pos = None if not avatar: if self.avId: avatar = base.cr.doId2do.get(self.avId, None) if avatar: if hasattr(self, 'cannon') and self.cannon: avatar.reparentTo(self.cannon) avatar.setPosHpr(3, 0, 0, 90, 0, 0) avatar.wrtReparentTo(render) self.__resetToon(avatar) return def __resetToon(self, avatar, pos=None): if avatar: self.__stopCollisionHandler(avatar) self.__setToonUpright(avatar, pos) if self.localToonShooting: self.notify.debug('toon setting position to %s' % pos) if pos: base.localAvatar.setPos(pos) camera.reparentTo(avatar) camera.setPos(self.av.cameraPositions[0][0]) place = base.cr.playGame.getPlace() if place: place.setState('finalBattle') self.b_setLanded() def __stopCollisionHandler(self, avatar): if avatar: avatar.loop('neutral') if self.flyColNode: self.flyColNode = None if avatar == base.localAvatar: avatar.collisionsOn() self.flyColSphere = None if self.flyColNodePath: base.cTrav.removeCollider(self.flyColNodePath) self.flyColNodePath.removeNode() self.flyColNodePath = None self.handler = None return def __setToonUpright(self, avatar, pos=None): if avatar: if not pos: pos = avatar.getPos(render) avatar.setPos(render, pos) avatar.loop('neutral') def b_setLanded(self): self.d_setLanded() def d_setLanded(self): if self.localToonShooting: self.sendUpdate('setLanded', []) def setLanded(self): self.removeAvFromCannon() def removeAvFromCannon(self): if self.av != None: self.__stopCollisionHandler(self.av) self.av.resetLOD() place = base.cr.playGame.getPlace() if self.av == base.localAvatar: if place: place.setState('finalBattle') self.av.loop('neutral') self.av.setPlayRate(1.0, 'run') if self.av.getParent().getName() == 'toonOriginChange': self.av.wrtReparentTo(render) self.__setToonUpright(self.av) if self.av == base.localAvatar: self.av.startPosHprBroadcast() self.av.startSmooth() self.av.setScale(1, 1, 1) self.ignore(self.av.uniqueName('disable')) self.__destroyToonModels() return def setCannonWillFire(self, avId, fireTime, zRot, angle, timestamp): self.notify.debug('setCannonWillFire: ' + str(avId) + ': zRot=' + str(zRot) + ', angle=' + str(angle) + ', time=' + str(fireTime)) if not self.model_Created: self.notify.warning( "We walked into the zone mid-flight, so we won't see it") return self.cannonPosition[0] = zRot self.cannonPosition[1] = angle self.__updateCannonPosition(avId) task = Task(self.__fireCannonTask) task.avId = avId ts = globalClockDelta.localElapsedTime(timestamp) task.fireTime = fireTime - ts if task.fireTime < 0.0: task.fireTime = 0.0 taskMgr.add(task, self.taskName('fireCannon')) def __fireCannonTask(self, task): launchTime = task.fireTime avId = task.avId if self.toonHead == None or not self.boss.state == 'BattleTwo': return Task.done startPos, startHpr, startVel, trajectory, timeOfImpact, hitWhat = self.__calcFlightResults( avId, launchTime) self.notify.debug('start position: ' + str(startPos)) self.notify.debug('start velocity: ' + str(startVel)) self.notify.debug('time of launch: ' + str(launchTime)) self.notify.debug('time of impact: ' + str(timeOfImpact)) self.notify.debug('location of impact: ' + str(trajectory.getPos(timeOfImpact))) head = self.toonHead head.stopBlink() head.stopLookAroundNow() head.reparentTo(hidden) juror = self.toonModel juror.reparentTo(render) juror.setPos(startPos) barrelHpr = self.barrel.getHpr(render) juror.setHpr(startHpr) self.jurorToon.loop('swim') self.jurorToon.setPosHpr(0, 0, -(self.jurorToon.getHeight() / 2.0), 0, 0, 0) info = {} info['avId'] = avId info['trajectory'] = trajectory info['launchTime'] = launchTime info['timeOfImpact'] = timeOfImpact info['hitWhat'] = hitWhat info['toon'] = self.toonModel info['hRot'] = self.cannonPosition[0] info['haveWhistled'] = 0 info['maxCamPullback'] = CAMERA_PULLBACK_MIN if self.localToonShooting: camera.reparentTo(juror) camera.setP(45.0) camera.setZ(-10.0) self.flyColSphere = CollisionSphere(0, 0, self.av.getHeight() / 2.0, 1.0) self.flyColNode = CollisionNode(self.uniqueName('flySphere')) self.flyColNode.setCollideMask(ToontownGlobals.WallBitmask | ToontownGlobals.FloorBitmask | ToontownGlobals.PieBitmask) self.flyColNode.addSolid(self.flyColSphere) self.flyColNodePath = self.jurorToon.attachNewNode(self.flyColNode) self.flyColNodePath.setColor(1, 0, 0, 1) self.handler = CollisionHandlerEvent() self.handler.setInPattern(self.uniqueName('cannonHit')) base.cTrav.addCollider(self.flyColNodePath, self.handler) self.accept(self.uniqueName('cannonHit'), self.__handleCannonHit) shootTask = Task(self.__shootTask, self.taskName('shootTask')) flyTask = Task(self.__flyTask, self.taskName('flyTask')) shootTask.info = info flyTask.info = info seqTask = Task.sequence(shootTask, flyTask) taskMgr.add(seqTask, self.taskName('flyingToon') + '-' + str(avId)) self.acceptOnce(self.uniqueName('stopFlyTask'), self.__stopFlyTask) return Task.done def __toRadians(self, angle): return angle * 2.0 * math.pi / 360.0 def __toDegrees(self, angle): return angle * 360.0 / (2.0 * math.pi) def __calcFlightResults(self, avId, launchTime): head = self.toonHead startPos = head.getPos(render) startHpr = head.getHpr(render) hpr = self.barrel.getHpr(render) rotation = self.__toRadians(hpr[0]) angle = self.__toRadians(hpr[1]) horizVel = INITIAL_VELOCITY * math.cos(angle) xVel = horizVel * -math.sin(rotation) yVel = horizVel * math.cos(rotation) zVel = INITIAL_VELOCITY * math.sin(angle) startVel = Vec3(xVel, yVel, zVel) trajectory = Trajectory.Trajectory(launchTime, startPos, startVel) self.trajectory = trajectory timeOfImpact, hitWhat = self.__calcToonImpact(trajectory) return (startPos, startHpr, startVel, trajectory, 3 * timeOfImpact, hitWhat) def __calcToonImpact(self, trajectory): t_groundImpact = trajectory.checkCollisionWithGround(GROUND_PLANE_MIN) if t_groundImpact >= trajectory.getStartTime(): return (t_groundImpact, self.HIT_GROUND) self.notify.error('__calcToonImpact: toon never impacts ground?') return (0.0, self.HIT_GROUND) def __handleCannonHit(self, collisionEntry): if self.av == None or self.flyColNode == None: return interPt = collisionEntry.getSurfacePoint(render) hitNode = collisionEntry.getIntoNode().getName() fromNodePath = collisionEntry.getFromNodePath() intoNodePath = collisionEntry.getIntoNodePath() ignoredHits = ['NearBoss'] for nodeName in ignoredHits: if hitNode == nodeName: return self.__stopFlyTask(self.avId) self.__stopCollisionHandler(self.jurorToon) if self.localToonShooting: camera.wrtReparentTo(render) pos = interPt hpr = self.jurorToon.getHpr() track = Sequence() if self.localToonShooting: pass chairlist = ['trigger-chair'] for index in range(len(ToontownGlobals.LawbotBossChairPosHprs)): chairlist.append('Chair-%s' % index) if hitNode in chairlist: track.append(Func(self.__hitChair, self.jurorToon, pos)) track.append(Wait(1.0)) track.append(Func(self.__setToonUpright, self.av)) if self.av == base.localAvatar: strs = hitNode.split('-') chairNum = int(strs[1]) self.boss.sendUpdate('hitChair', [chairNum, self.index]) else: track.append(Func(self.__hitGround, self.jurorToon, pos)) track.append(Wait(1.0)) track.append(Func(self.__setToonUpright, self.av)) track.append(Func(self.b_setLanded)) if self.localToonShooting: pass if self.hitTrack: self.hitTrack.finish() self.hitTrack = track self.hitTrack.start() return def enterCannonHit(self, collisionEntry): pass def __shootTask(self, task): base.playSfx(self.sndCannonFire) return Task.done def __flyTask(self, task): toon = task.info['toon'] if toon.isEmpty(): self.__resetToonToCannon(self.av) return Task.done curTime = task.time + task.info['launchTime'] t = min(curTime, task.info['timeOfImpact']) self.lastT = self.t self.t = t deltaT = self.t - self.lastT self.deltaT = deltaT if t >= task.info['timeOfImpact']: self.__resetToonToCannon(self.av) return Task.done pos = task.info['trajectory'].getPos(t) toon.setFluidPos(pos) vel = task.info['trajectory'].getVel(t) run = math.sqrt(vel[0] * vel[0] + vel[1] * vel[1]) rise = vel[2] theta = self.__toDegrees(math.atan(rise / run)) toon.setHpr(self.cannon.getH(render), -90 + theta, 0) view = 2 lookAt = task.info['toon'].getPos(render) hpr = task.info['toon'].getHpr(render) if self.localToonShooting: if view == 0: camera.wrtReparentTo(render) camera.lookAt(lookAt) elif view == 1: camera.reparentTo(render) camera.setPos(render, 100, 100, 35.25) camera.lookAt(render, lookAt) elif view == 2: if hpr[1] > -90: camera.setPos(0, 0, -30) if camera.getZ() < lookAt[2]: camera.setZ(render, lookAt[2] + 10) camera.lookAt(Point3(0, 0, 0)) return Task.cont def __stopFlyTask(self, avId): taskMgr.remove(self.taskName('flyingToon') + '-' + str(avId)) def __hitGround(self, avatar, pos, extraArgs=[]): hitP = avatar.getPos(render) h = self.barrel.getH(render) avatar.setPos(pos[0], pos[1], pos[2] + avatar.getHeight() / 3.0) avatar.setHpr(h, -135, 0) self.dustCloud.setPos(render, pos[0], pos[1], pos[2] + avatar.getHeight() / 3.0) self.dustCloud.setScale(0.35) self.dustCloud.play() base.playSfx(self.sndHitGround) avatar.hide() def __hitChair(self, avatar, pos, extraArgs=[]): hitP = avatar.getPos(render) h = self.barrel.getH(render) avatar.setPos(pos[0], pos[1], pos[2] + avatar.getHeight() / 3.0) avatar.setHpr(h, -135, 0) self.dustCloud.setPos(render, pos[0], pos[1], pos[2] + avatar.getHeight() / 3.0) self.dustCloud.setScale(0.35) self.dustCloud.play() base.playSfx(self.sndHitGround) base.playSfx(self.sndHitChair) avatar.hide() def generateCannonAppearTrack(self, avatar): self.cannon.setScale(0.1) self.cannon.show() kartTrack = Parallel( Sequence(ActorInterval(avatar, 'feedPet'), Func(avatar.loop, 'neutral')), Sequence( Func(self.cannon.reparentTo, avatar.rightHand), Wait(2.1), Func(self.cannon.wrtReparentTo, render), Func(self.cannon.setShear, 0, 0, 0), Parallel( LerpHprInterval(self.cannon, hpr=self.nodePath.getHpr(render), duration=1.2), ProjectileInterval(self.cannon, endPos=self.nodePath.getPos(render), duration=1.2, gravityMult=0.45)), Wait(0.2), Sequence( LerpScaleInterval(self.cannon, scale=Point3(1.1, 1.1, 0.1), duration=0.2), LerpScaleInterval(self.cannon, scale=Point3(0.9, 0.9, 0.1), duration=0.1), LerpScaleInterval(self.cannon, scale=Point3(1.0, 1.0, 0.1), duration=0.1), LerpScaleInterval(self.cannon, scale=Point3(1.0, 1.0, 1.1), duration=0.2), LerpScaleInterval(self.cannon, scale=Point3(1.0, 1.0, 0.9), duration=0.1), LerpScaleInterval(self.cannon, scale=Point3(1.0, 1.0, 1.0), duration=0.1), Func(self.cannon.wrtReparentTo, self.nodePath)))) return kartTrack
class CameraShyFirstPerson(FirstPerson): toonInFocusColor = VBase4(0.25, 1.0, 0.25, 1.0) toonOutOfFocusColor = VBase4(1.0, 1.0, 1.0, 1.0) fullyChargedState = 5 def __init__(self, mg): self.mg = mg self.cameraFocus = None self.batteryFrame = None self.batteryBg = None self.batteryBar = None self.rechargeSound = None self.fullyChargedSound = None self.hasToonInFocus = False self.toonToTakePicOf = None self.cameraRechargeState = None self.cameraRechargingLabel = None self.cameraFlashSeq = None self.camFSM = ClassicFSM('CameraFSM', [State('off', self.enterOff, self.exitOff), State('ready', self.enterCameraReady, self.exitCameraReady), State('recharge', self.enterCameraRecharge, self.exitCameraRecharge)], 'off', 'off') self.camFSM.enterInitialState() FirstPerson.__init__(self) return def movementTask(self, task): if not inputState.isSet('jump') and not base.localAvatar.walkControls.isAirborne and inputState.isSet('forward') or inputState.isSet('reverse') or inputState.isSet('slideLeft') or inputState.isSet('slideRight'): if base.localAvatar.getAnimState() != 'run': base.localAvatar.setAnimState('run') base.localAvatar.playMovementSfx('run') self.mg.sendUpdate('runningAvatar', [base.localAvatar.doId]) elif inputState.isSet('jump') or base.localAvatar.walkControls.isAirborne: if base.localAvatar.getAnimState() != 'jump': base.localAvatar.setAnimState('jump') base.localAvatar.playMovementSfx(None) self.mg.sendUpdate('jumpingAvatar', [base.localAvatar.doId]) elif base.localAvatar.getAnimState() != 'neutral': base.localAvatar.setAnimState('neutral') base.localAvatar.playMovementSfx(None) self.mg.sendUpdate('standingAvatar', [base.localAvatar.doId]) return task.cont def enterOff(self): pass def exitOff(self): pass def enterCameraReady(self): self.acceptOnce('mouse1', self.__mouse1Pressed) def stopCameraFlash(self): if self.cameraFlashSeq: self.cameraFlashSeq.finish() self.cameraFlashSeq = None return def __mouse1Pressed(self): self.cameraFlashSeq = Sequence(Func(base.transitions.setFadeColor, 1, 1, 1), Func(base.transitions.fadeOut, 0.1), Wait(0.1), Func(base.transitions.fadeIn, 0.1), Wait(0.1), Func(base.transitions.setFadeColor, 0, 0, 0)) self.cameraFlashSeq.start() self.mg.sendUpdate('remoteAvatarTakePicture', [base.localAvatar.doId]) self.mg.myRemoteAvatar.takePicture() if self.hasToonInFocus and self.toonToTakePicOf: self.mg.sendUpdate('tookPictureOfToon', [self.toonToTakePicOf.doId]) self.camFSM.request('recharge') def exitCameraReady(self): self.ignore('mouse1') def enterCameraRecharge(self): self.batteryBar.update(0) taskMgr.add(self.__rechargeNextState, 'rechargeCamera') def __rechargeNextState(self, task): if self.cameraRechargeState == None: self.cameraRechargeState = -1 self.cameraRechargeState += 1 if self.cameraRechargeState > 0: base.playSfx(self.rechargeSound) self.batteryBar.update(self.cameraRechargeState) if self.cameraRechargeState == self.fullyChargedState: base.playSfx(self.fullyChargedSound) self.camFSM.request('ready') return task.done else: task.delayTime = 1.0 return task.again def exitCameraRecharge(self): taskMgr.remove('rechargeCamera') self.cameraRechargeState = None return def __handleRayInto(self, entry): intoNP = entry.getIntoNodePath() toonNP = intoNP.getParent() for key in base.cr.doId2do.keys(): obj = base.cr.doId2do[key] if obj.__class__.__name__ == 'DistributedToon': if obj.getKey() == toonNP.getKey(): self.__handleToonInFocus(obj) def __handleRayOut(self, entry): intoNP = entry.getIntoNodePath() toonNP = intoNP.getParent() for key in base.cr.doId2do.keys(): obj = base.cr.doId2do[key] if obj.__class__.__name__ == 'DistributedToon': if obj.getKey() == toonNP.getKey(): self.toonToTakePicOf = None self.hasToonInFocus = False if self.cameraFocus.getColorScale() == self.toonInFocusColor: self.cameraFocus.setColorScale(self.toonOutOfFocusColor) return def __handleToonInFocus(self, toon): if not self.hasToonInFocus or self.toonToTakePicOf is not None or self.toonToTakePicOf.doId != toon.doId: self.toonToTakePicOf = toon self.hasToonInFocus = True self.cameraFocus.setColorScale(self.toonInFocusColor) return def start(self): self.fullyChargedSound = base.loadSfx('phase_4/audio/sfx/MG_pairing_match.mp3') self.rechargeSound = base.loadSfx('phase_4/audio/sfx/MG_sfx_travel_game_blue_arrow.mp3') self.batteryFrame = DirectFrame(parent=base.a2dBottomRight, pos=(-0.2, 0, 0.1), scale=(0.8, 0, 1)) self.batteryBg = OnscreenImage(image='phase_4/maps/battery_charge_frame.png', parent=self.batteryFrame) self.batteryBg.setTransparency(1) self.batteryBg.setX(0.03) self.batteryBg.setScale(0.17, 0, 0.05) self.batteryBar = DirectWaitBar(value=0, range=5, barColor=(1, 1, 1, 1), relief=None, scale=(0.12, 0.0, 0.3), parent=self.batteryFrame) self.cameraFocus = loader.loadModel('phase_4/models/minigames/photo_game_viewfinder.bam') self.cameraFocus.reparentTo(base.aspect2d) self.focusCollHandler = CollisionHandlerEvent() self.focusCollHandler.setInPattern('%fn-into') self.focusCollHandler.setOutPattern('%fn-out') self.focusCollNode = CollisionNode('mouseRay') self.focusCollNP = base.camera.attachNewNode(self.focusCollNode) self.focusCollNode.setCollideMask(BitMask32(0)) self.focusCollNode.setFromCollideMask(CIGlobals.WallBitmask) self.focusRay = CollisionRay() self.focusRay.setFromLens(base.camNode, 0.0, 0.0) self.focusCollNode.addSolid(self.focusRay) base.cTrav.addCollider(self.focusCollNP, self.focusCollHandler) base.localAvatar.walkControls.setWalkSpeed(CIGlobals.ToonForwardSpeed, 0.0, CIGlobals.ToonReverseSpeed, CIGlobals.ToonRotateSpeed) FirstPerson.start(self) return def reallyStart(self): self.accept('mouseRay-into', self.__handleRayInto) self.accept('mouseRay-out', self.__handleRayOut) self.camFSM.request('recharge') taskMgr.add(self.movementTask, 'movementTask') FirstPerson.reallyStart(self) def end(self): self.camFSM.request('off') taskMgr.remove('movementTask') self.ignore('mouseRay-into') self.ignore('mouseRay-out') FirstPerson.end(self) def reallyEnd(self): self.batteryBar.destroy() self.batteryBar = None self.batteryBg.destroy() self.batteryBg = None self.batteryFrame.destroy() self.batteryFrame = None self.cameraFocus.removeNode() self.cameraFocus = None self.focusCollHandler = None self.focusCollNode = None self.focusCollNP.removeNode() self.focusCollNP = None self.focusRay = None self.hasToonInFocus = None self.toonToTakePicOf = None self.fullyChargedSound = None self.rechargeSound = None self.stopCameraFlash() FirstPerson.reallyEnd(self) base.localAvatar.walkControls.setWalkSpeed(CIGlobals.ToonForwardSpeed, CIGlobals.ToonJumpForce, CIGlobals.ToonReverseSpeed, CIGlobals.ToonRotateSpeed) return def cleanup(self): self.camFSM.requestFinalState() self.camFSM = None FirstPerson.cleanup(self) return
class MyApp(ShowBase, DirectObject.DirectObject): def __init__(self): ShowBase.__init__(self) # generate a new game game = Game() game.create_player('Player One') game.create_player('Player Two') game.create_player('Player Three') game.initialize_board() # place some random cities for player in game.players.values(): # give the player some random resources for resource in player.resources: player.resources[resource] = random.randint(0,8) while True: n = random.choice(game.board.network.nodes()) if game.board.node_available(n): game.board.update_building(n, player, 'city') # place a random road m = random.choice(game.board.network.neighbors(n)) game.board.network.edge[n][m]['road'] = True game.board.network.edge[n][m]['player'] = player break self.board_renderer = BoardRenderer(self, game.board) self.hand_renderer = HandRenderer(self, game.players.values()[0]) # setup some 3-point lighting for the whole board lKey = DirectionalLight('lKey') lKey.setColor(VBase4(0.9,0.9,0.9,1)) lKeyNode = render.attachNewNode(lKey) lKeyNode.setH(-63) lKeyNode.setP(-60) lKeyNode.setR(-30) render.setLight(lKeyNode) lFill = DirectionalLight('lFill') lFill.setColor(VBase4(0.4,0.4,0.4,1)) lFillNode = render.attachNewNode(lFill) lFillNode.setH(27) lFillNode.setP(-15) lFillNode.setR(-30) render.setLight(lFillNode) lBack = DirectionalLight('lBack') lBack.setColor(VBase4(0.3,0.3,0.3,1)) lBackNode = render.attachNewNode(lBack) lBackNode.setH(177) lBackNode.setP(-20) lBackNode.setR(0) render.setLight(lBackNode) lBelow = DirectionalLight('lBelow') lBelow.setColor(VBase4(0.4,0.4,0.4,1)) lBelowNode = render.attachNewNode(lBelow) lBelowNode.setH(0) lBelowNode.setP(90) lBelowNode.setR(0) render.setLight(lBelowNode) self.accept('a', self.on_toggle_anti_alias) self.mouse_controlled = True self.on_toggle_mouse_control() self.accept('m', self.on_toggle_mouse_control) self.accept('q', self.on_quit) # onto-board selection collision test select_mask = BitMask32(0x100) self.select_ray = CollisionRay() select_node = CollisionNode('mouseToSurfaceRay') select_node.setFromCollideMask(select_mask) select_node.addSolid(self.select_ray) select_np = self.camera.attachNewNode(select_node) self.select_queue = CollisionHandlerQueue() self.select_traverser = CollisionTraverser() self.select_traverser.addCollider(select_np, self.select_queue) # create a plane that only collides with the mouse ray select_plane = CollisionPlane(Plane(Vec3(0,0,1), Point3(0,0,0))) # add plane to render self.select_node = CollisionNode('boardCollisionPlane') self.select_node.setCollideMask(select_mask) self.select_node.addSolid(select_plane) self.select_plane_np = self.render.attachNewNode(self.select_node) self.debug_select = draw_debugging_arrow(self, Vec3(0,0,0), Vec3(0,1,0)) self.taskMgr.add(self.update_mouse_target, "mouseTarget") self.taskMgr.add(self.update_debug_arrow, "updateDebugArrow") def on_toggle_anti_alias(self): if AntialiasAttrib.MNone != render.getAntialias(): render.setAntialias(AntialiasAttrib.MNone) print "anti-aliasing disabled" else: render.setAntialias(AntialiasAttrib.MAuto) print "anti-aliasing enabled" def on_toggle_mouse_control(self): if self.mouse_controlled: self.disableMouse() self.taskMgr.add(self.spin_camera_task, "spinCameraTask") else: self.enableMouse() self.mouse_controlled = not self.mouse_controlled def spin_camera_task(self, task): height = 9 distance = 15 speed = 1./16 angle = (task.time*speed) * 2 * pi self.camera.setPos(distance*cos(angle), distance*-sin(angle), height) self.camera.lookAt(0,0,0) if self.mouse_controlled: return Task.done return Task.cont def update_mouse_target(self, task): if not base.mouseWatcherNode.hasMouse(): self.mouse_target = None return Task.cont # setup ray through camera position and mouse position (on camera plane) mouse_pos = base.mouseWatcherNode.getMouse() self.select_ray.setFromLens(self.board_renderer.base.camNode, mouse_pos.getX(), mouse_pos.getY()) self.select_traverser.traverse(self.board_renderer.base.render) # abort if there's no collision if not self.select_queue.getNumEntries(): return Task.cont collision = self.select_queue.getEntry(0) self.mouse_board_collision = collision.getSurfacePoint(collision.getIntoNodePath()) self.mouse_target = 'board' return Task.cont def update_debug_arrow(self, task): if self.mouse_target: self.debug_select.setPos(self.mouse_board_collision) return Task.cont def on_pick(self): if not self._update_pick_ray(): return # traverse scene graph and determine nearest selection (if pickable) self.pick_traverser.traverse(self.board_renderer.base.render) self.pick_queue.sortEntries() if not self.pick_queue.getNumEntries(): return node = self.pick_queue.getEntry(0).getIntoNodePath().findNetTag('pickable') if node.isEmpty() or node.getTag('pickable') == 'False': return # add some color ts = TextureStage('ts') ts.setMode(TextureStage.MModulate) colors = list(Game.player_colors) colors.remove('white') node.setTexture(ts, self.board_renderer.tileset.load_texture('textures/player%s.png' % random.choice(colors).capitalize())) def on_quit(self): sys.exit(0)
class DistributedPartyGate(DistributedObject.DistributedObject): notify = DirectNotifyGlobal.directNotify.newCategory( 'DistributedPartyGate') def __init__(self, cr): DistributedObject.DistributedObject.__init__(self, cr) self.publicPartyChooseGuiDoneEvent = 'doneChoosingPublicParty' self.publicPartyGui = PublicPartyGui( self.publicPartyChooseGuiDoneEvent) self.publicPartyGui.stash() self.loadClockSounds() self.hourSoundInterval = Sequence() self.accept('stoppedAsleep', self.handleSleep) def loadClockSounds(self): self.clockSounds = [] for i in range(1, 13): if i < 10: si = '0%d' % i else: si = '%d' % i self.clockSounds.append( base.loadSfx('phase_4/audio/sfx/clock%s.mp3' % si)) def generate(self): DistributedObject.DistributedObject.generate(self) loader = self.cr.playGame.hood.loader partyGate = loader.geom.find('**/partyGate_grp') if partyGate.isEmpty(): self.notify.warning('Could not find partyGate_grp in loader.geom') return self.clockFlat = partyGate.find('**/clock_flat') collSphere = CollisionSphere(0, 0, 0, 6.9) collSphere.setTangible(1) self.partyGateSphere = CollisionNode('PartyGateSphere') self.partyGateSphere.addSolid(collSphere) self.partyGateCollNodePath = partyGate.find( '**/partyGate_stepsLocator').attachNewNode(self.partyGateSphere) self.__enableCollisions() self.toontownTimeGui = ServerTimeGui(partyGate, hourCallback=self.hourChange) self.toontownTimeGui.setPos( partyGate.find('**/clockText_locator').getPos() + Point3(0.0, 0.0, -0.2)) self.toontownTimeGui.setHpr( partyGate.find('**/clockText_locator').getHpr()) self.toontownTimeGui.setScale(12.0, 1.0, 26.0) self.toontownTimeGui.amLabel.setPos(-0.035, 0, -0.032) self.toontownTimeGui.amLabel.setScale(0.5) self.toontownTimeGui.updateTime() self.setupSignText() def setupSignText(self): loader = self.cr.playGame.hood.loader partyGate = loader.geom.find('**/partyGateSignGroup') if partyGate.isEmpty(): self.notify.warning('Could not find partyGate_grp in loader.geom') return gateFont = ToontownGlobals.getMinnieFont() leftSign = partyGate.find('**/signTextL_locatorBack') signScale = 0.35 wordWrap = 8 leftText = DirectLabel.DirectLabel(parent=leftSign, pos=(0, 0.0, 0.0), relief=None, text=TTLocalizer.PartyGateLeftSign, text_align=TextNode.ACenter, text_font=gateFont, text_wordwrap=wordWrap, text_fg=Vec4(0.7, 0.3, 0.3, 1.0), scale=signScale) rightSign = partyGate.find('**/signTextR_locatorFront') rightText = DirectLabel.DirectLabel( parent=rightSign, pos=(0, 0.0, 0.0), relief=None, text=TTLocalizer.PartyGateRightSign, text_align=TextNode.ACenter, text_font=gateFont, text_wordwrap=wordWrap, text_fg=Vec4(0.7, 0.3, 0.3, 1.0), scale=signScale) return def announceGenerate(self): DistributedObject.DistributedObject.announceGenerate(self) if ToontownGlobals.dnaMap.has_key(self.zoneId): playground = ToontownGlobals.dnaMap[self.zoneId] else: playground = ToontownGlobals.dnaMap[2000] self.toontownTimeGui.hourLabel[ 'text_fg'] = PartyGlobals.PlayGroundToPartyClockColors[playground] self.toontownTimeGui.colonLabel[ 'text_fg'] = PartyGlobals.PlayGroundToPartyClockColors[playground] self.toontownTimeGui.minutesLabel[ 'text_fg'] = PartyGlobals.PlayGroundToPartyClockColors[playground] self.toontownTimeGui.amLabel[ 'text_fg'] = PartyGlobals.PlayGroundToPartyClockColors[playground] def disable(self): DistributedObject.DistributedObject.disable(self) self.__disableCollisions() self.toontownTimeGui.ival.finish() self.hourSoundInterval.finish() if self.publicPartyGui: self.publicPartyGui.stash() self.publicPartyGui.destroy() self.publicPartyGui = None return def delete(self): DistributedObject.DistributedObject.delete(self) self.toontownTimeGui.destroy() del self.toontownTimeGui self.hourSoundInterval.finish() del self.hourSoundInterval del self.clockFlat if self.publicPartyGui: self.publicPartyGui.destroy() del self.publicPartyGui self.partyGateCollNodePath.removeNode() del self.partyGateCollNodePath self.ignoreAll() def showMessage(self, message): self.messageDoneEvent = self.uniqueName('messageDoneEvent') self.acceptOnce(self.messageDoneEvent, self.__handleMessageDone) self.messageGui = TTDialog.TTGlobalDialog( doneEvent=self.messageDoneEvent, message=message, style=TTDialog.Acknowledge) def __handleMessageDone(self): self.ignore(self.messageDoneEvent) self.freeAvatar() self.messageGui.cleanup() self.messageGui = None return def __handleAskDone(self): DistributedPartyGate.notify.debug('__handleAskDone') self.ignore(self.publicPartyChooseGuiDoneEvent) doneStatus = self.publicPartyGui.doneStatus self.publicPartyGui.stash() if doneStatus is None: self.freeAvatar() return self.sendUpdate('partyChoiceRequest', [base.localAvatar.doId, doneStatus[0], doneStatus[1]]) return def partyRequestDenied(self, reason): DistributedPartyGate.notify.debug( 'partyRequestDenied( reason=%s )' % PartyGlobals.PartyGateDenialReasons.getString(reason)) if reason == PartyGlobals.PartyGateDenialReasons.Unavailable: self.showMessage(TTLocalizer.PartyGatePartyUnavailable) elif reason == PartyGlobals.PartyGateDenialReasons.Full: self.showMessage(TTLocalizer.PartyGatePartyFull) def setParty(self, partyInfoTuple): DistributedPartyGate.notify.debug('setParty') self.freeAvatar() if partyInfoTuple[0] == 0: DistributedPartyGate.notify.debug( 'Public Party closed before toon could get to it.') return shardId, zoneId, numberOfGuests, hostName, activityIds, lane = partyInfoTuple if base.localAvatar.defaultShard == shardId: shardId = None base.cr.playGame.getPlace().requestLeave({ 'loader': 'safeZoneLoader', 'where': 'party', 'how': 'teleportIn', 'hoodId': ToontownGlobals.PartyHood, 'zoneId': zoneId, 'shardId': shardId, 'avId': -1 }) return def freeAvatar(self): base.localAvatar.posCamera(0, 0) base.cr.playGame.getPlace().setState('walk') def hourChange(self, currentHour): currentHour = currentHour % 12 if currentHour == 0: currentHour = 12 self.hourSoundInterval = Parallel() seq1 = Sequence() for i in range(currentHour): seq1.append(SoundInterval(self.clockSounds[i])) seq1.append(Wait(0.2)) timeForEachDeformation = seq1.getDuration() / currentHour seq2 = Sequence() for i in range(currentHour): seq2.append( self.clockFlat.scaleInterval(timeForEachDeformation / 2.0, Vec3(0.9, 1.0, 1.2), blendType='easeInOut')) seq2.append( self.clockFlat.scaleInterval(timeForEachDeformation / 2.0, Vec3(1.2, 1.0, 0.9), blendType='easeInOut')) seq2.append( self.clockFlat.scaleInterval(timeForEachDeformation / 2.0, Vec3(1.0, 1.0, 1.0), blendType='easeInOut')) self.hourSoundInterval.append(seq1) self.hourSoundInterval.append(seq2) self.hourSoundInterval.start() def handleEnterGateSphere(self, collEntry): self.notify.debug('Entering steps Sphere....') base.cr.playGame.getPlace().fsm.request('stopped') self.sendUpdate('getPartyList', [base.localAvatar.doId]) def listAllPublicParties(self, publicPartyInfo): self.notify.debug('listAllPublicParties : publicPartyInfo = %s' % publicPartyInfo) self.acceptOnce(self.publicPartyChooseGuiDoneEvent, self.__handleAskDone) self.publicPartyGui.refresh(publicPartyInfo) self.publicPartyGui.unstash() def __enableCollisions(self): self.accept('enterPartyGateSphere', self.handleEnterGateSphere) self.partyGateSphere.setCollideMask(OTPGlobals.WallBitmask) def __disableCollisions(self): self.ignore('enterPartyGateSphere') self.partyGateSphere.setCollideMask(BitMask32(0)) def handleSleep(self): if hasattr(self, 'messageGui') and self.messageGui: self.__handleMessageDone()
class Avatar(Actor, ShadowCaster): notify = DirectNotifyGlobal.directNotify.newCategory('Avatar') def __init__(self, other=None): Actor.__init__(self, None, None, other, flattenable=0, setFinal=1) ShadowCaster.__init__(self) self.collTube = None self.scale = 1.0 self.height = 0.0 self.style = None self.hpText = None self.hpTextGenerator = TextNode('HpTextGenerator') def delete(self): try: self.Avatar_deleted except: Actor.cleanup(self) self.Avatar_deleted = 1 self.style = None self.collTube = None self.hpText = None self.hpTextGenerator = None ShadowCaster.delete(self) Actor.delete(self) def uniqueName(self, name): return 'Avatar-{0}-{1}'.format(id(self), name) def getCollisionId(self): return self.uniqueName('bodyColl') def getAvatarScale(self): return self.scale def setAvatarScale(self, scale): if self.scale != scale: self.scale = scale self.getGeomNode().setScale(scale) self.setHeight(self.height) def getHeight(self): return self.height def setHeight(self, height): self.height = height if not self.collTube: self.initializeBodyCollisions() self.collTube.setPointB(0, 0, height - self.getRadius()) if self.collNodePath: self.collNodePath.forceRecomputeBounds() def getRadius(self): return GameGlobals.AvatarDefaultRadius def getStyle(self): return self.style def setStyle(self, style): self.style = style def getAirborneHeight(self): height = self.getPos(self.shadowPlacer.shadowNodePath) return height.getZ() + 0.025 def initializeBodyCollisions(self): self.collTube = CollisionTube(0, 0, 0.5, 0, 0, self.height - self.getRadius(), self.getRadius()) self.collNode = CollisionNode(self.getCollisionId()) self.collNode.addSolid(self.collTube) self.collNodePath = self.attachNewNode(self.collNode) self.collNode.setCollideMask(BitmaskGlobals.WallBitmask) def showNodePathColl(self): self.collNodePath.show() def stashBodyCollisions(self): if hasattr(self, 'collNodePath'): self.collNodePath.stash() def unstashBodyCollisions(self): if hasattr(self, 'collNodePath'): self.collNodePath.unstash() def disableBodyCollisions(self): if hasattr(self, 'collNodePath'): self.collNodePath.removeNode() del self.collNodePath self.collTube = None def showHpText(self, number, bonus=0, scale=1.75): if number == 0: return if self.hpText: self.hideHpText() self.hpTextGenerator.setFont(GameGlobals.getSignFont()) if number < 0: text = str(number) if random.randrange(0, 100) < SILLY_SURGE_CHANCE: text += '\n' text += random.choice(GameLocalizer.SillySurgeTerms) else: text = '+' + str(number) self.hpTextGenerator.setText(text) self.hpTextGenerator.clearShadow() self.hpTextGenerator.setAlign(TextNode.ACenter) if bonus == 1: color = [1, 1, 0, 1] elif bonus == 2: color = [1, 0.5, 0, 1] elif number < 0: color = [0.9, 0, 0, 1] else: color = [0, 0.9, 0, 1] self.hpTextGenerator.setTextColor(*color) self.hpTextNode = self.hpTextGenerator.generate() self.hpText = self.attachNewNode(self.hpTextNode) self.hpText.setScale(scale) self.hpText.setBillboardPointEye() self.hpText.setBin('fixed', 100) self.hpText.setPos(0, 0, self.height / 2) color[3] = 0 Sequence( self.hpText.posInterval(1.0, (0, 0, self.height + 0.75), blendType='easeOut'), Wait(0.85), self.hpText.colorInterval(0.1, Vec4(*color), 0.1), Func(self.hideHpText)).start() def hideHpText(self): if self.hpText: taskMgr.remove(self.uniqueName('hpText')) self.hpText.removeNode() self.hpText = None
class DistributedPartyTrampolineActivity(DistributedPartyActivity): notify = DirectNotifyGlobal.directNotify.newCategory('DistributedPartyTrampolineActivity') def __init__(self, cr, doJellyBeans = True, doTricks = False, texture = None): DistributedPartyTrampolineActivity.notify.debug('__init__') DistributedPartyActivity.__init__(self, cr, PartyGlobals.ActivityIds.PartyTrampoline, PartyGlobals.ActivityTypes.GuestInitiated, wantLever=False, wantRewardGui=True) self.doJellyBeans = doJellyBeans self.doTricks = doTricks self.texture = texture self.toon = None self.trampHeight = 3.6 self.trampK = 400.0 self.normalTrampB = 2.5 self.leavingTrampB = 8.0 self.trampB = self.normalTrampB self.g = -32.0 self.jumpBoost = 330.0 self.beginningBoost = 500.0 self.beginningBoostThreshold = self.trampHeight + 1.5 self.earlyJumpThreshold = 75.0 self.boingThreshold = 300.0 self.turnFactor = 120.0 self.stepDT = 0.001 self.targetCameraPos = Point3(0.0, 40.0, 10.0) self.cameraSpeed = 2.0 self.hopOffPos = Point3(16.0, 0.0, 0.0) self.indicatorFactor = 0.0095 self.dropShadowCutoff = 15.0 self.minHeightForText = 15.0 self.heightTextOffset = -0.065 self.beanOffset = 0.5 self.guiBeanOffset = -0.02 self.jumpTextShown = False self.toonJumped = False self.turnLeft = False self.turnRight = False self.leavingTrampoline = False self.toonVelocity = 0.0 self.topHeight = 0.0 self.lastPeak = 0.0 self.beginRoundInterval = None self.hopOnAnim = None self.hopOffAnim = None self.flashTextInterval = None self.numJellyBeans = PartyGlobals.TrampolineNumJellyBeans self.jellyBeanBonus = PartyGlobals.TrampolineJellyBeanBonus self.jellyBeanStartHeight = 20.0 self.jellyBeanStopHeight = 90.0 self.jellyBeanColors = [VBase4(1.0, 0.5, 0.5, 1.0), VBase4(0.5, 1.0, 0.5, 1.0), VBase4(0.5, 1.0, 1.0, 1.0), VBase4(1.0, 1.0, 0.4, 1.0), VBase4(0.4, 0.4, 1.0, 1.0), VBase4(1.0, 0.5, 1.0, 1.0)] delta = (self.jellyBeanStopHeight - self.jellyBeanStartHeight) / (self.numJellyBeans - 1) self.jellyBeanPositions = [ self.jellyBeanStartHeight + n * delta for n in xrange(self.numJellyBeans) ] self.doSimulateStep = False return def load(self): DistributedPartyTrampolineActivity.notify.debug('load') DistributedPartyActivity.load(self) self.loadModels() self.loadCollision() self.loadGUI() self.loadSounds() self.loadIntervals() self.activityFSM = TrampolineActivityFSM(self) self.activityFSM.request('Idle') self.animFSM = TrampolineAnimFSM(self) self.setBestHeightInfo('', 0) def loadModels(self): self.tramp = self.root.attachNewNode(self.uniqueName('tramp')) self.trampActor = Actor('phase_13/models/parties/trampoline_model', {'emptyAnim': 'phase_13/models/parties/trampoline_anim'}) self.trampActor.reparentTo(self.tramp) if self.texture: reskinNode = self.tramp.find('**/trampoline/__Actor_modelRoot/-GeomNode') reskinNode.setTexture(loader.loadTexture(self.texture), 100) self.surface = NodePath(self.uniqueName('trampSurface')) self.surface.reparentTo(self.tramp) self.surface.setZ(self.trampHeight) self.trampActor.controlJoint(self.surface, 'modelRoot', 'trampoline_joint1') self.sign.setPos(PartyGlobals.TrampolineSignOffset) self.beans = [ loader.loadModelCopy('phase_4/models/props/jellybean4') for i in xrange(self.numJellyBeans) ] for bean in self.beans: bean.find('**/jellybean').setP(-35.0) bean.setScale(3.0) bean.setTransparency(True) bean.reparentTo(self.tramp) bean.stash() self.beans[-1].setScale(8.0) def loadCollision(self): collTube = CollisionTube(0.0, 0.0, 0.0, 0.0, 0.0, 6.0, 5.4) collTube.setTangible(True) self.trampolineCollision = CollisionNode(self.uniqueName('TrampolineCollision')) self.trampolineCollision.addSolid(collTube) self.trampolineCollision.setCollideMask(OTPGlobals.CameraBitmask | OTPGlobals.WallBitmask) self.trampolineCollisionNP = self.tramp.attachNewNode(self.trampolineCollision) collSphere = CollisionSphere(0.0, 0.0, 0.0, 7.0) collSphere.setTangible(False) self.trampolineTrigger = CollisionNode(self.uniqueName('TrampolineTrigger')) self.trampolineTrigger.addSolid(collSphere) self.trampolineTrigger.setIntoCollideMask(OTPGlobals.WallBitmask) self.trampolineTriggerNP = self.tramp.attachNewNode(self.trampolineTrigger) self.accept('enter%s' % self.uniqueName('TrampolineTrigger'), self.onTrampolineTrigger) def loadGUI(self): self.gui = loader.loadModel('phase_13/models/parties/trampolineGUI') self.gui.reparentTo(base.a2dTopLeft) self.gui.setPos(0.115, 0, -1) self.gui.hide() self.toonIndicator = self.gui.find('**/trampolineGUI_MovingBar') jumpLineLocator = self.gui.find('**/jumpLine_locator') guiBean = self.gui.find('**/trampolineGUI_GreenJellyBean') self.gui.find('**/trampolineGUI_GreenJellyBean').stash() self.guiBeans = [ guiBean.instanceUnderNode(jumpLineLocator, self.uniqueName('guiBean%d' % i)) for i in xrange(self.numJellyBeans) ] self.guiBeans[-1].setScale(1.5) heightTextNode = TextNode(self.uniqueName('TrampolineActivity.heightTextNode')) heightTextNode.setFont(ToontownGlobals.getSignFont()) heightTextNode.setAlign(TextNode.ALeft) heightTextNode.setText('0.0') heightTextNode.setShadow(0.05, 0.05) heightTextNode.setShadowColor(0.0, 0.0, 0.0, 1.0) heightTextNode.setTextColor(1.0, 1.0, 1.0, 1.0) self.heightText = jumpLineLocator.attachNewNode(heightTextNode) self.heightText.setX(0.15) self.heightText.setScale(0.1) self.heightText.setAlphaScale(0.0) self.quitEarlyButtonModels = loader.loadModel('phase_3.5/models/gui/inventory_gui') quitEarlyUp = self.quitEarlyButtonModels.find('**//InventoryButtonUp') quitEarlyDown = self.quitEarlyButtonModels.find('**/InventoryButtonDown') quitEarlyRollover = self.quitEarlyButtonModels.find('**/InventoryButtonRollover') self.quitEarlyButton = DirectButton(parent=base.a2dTopRight, relief=None, text=TTLocalizer.PartyTrampolineQuitEarlyButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -0.23), text_scale=0.7, image=(quitEarlyUp, quitEarlyDown, quitEarlyRollover), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(-0.183, 0, -0.4), scale=0.09, command=self.leaveTrampoline) self.quitEarlyButton.stash() self.flashText = OnscreenText(text='', pos=(0.0, -0.45), scale=0.2, fg=(1.0, 1.0, 0.65, 1.0), align=TextNode.ACenter, font=ToontownGlobals.getSignFont(), mayChange=True) self.timer = PartyUtils.getNewToontownTimer() self.timer.posInTopRightCorner() return def loadSounds(self): self.jellyBeanSound = base.loader.loadSfx('phase_4/audio/sfx/sparkly.ogg') self.boingSound = base.loader.loadSfx('phase_4/audio/sfx/target_trampoline_2.ogg') self.whistleSound = base.loader.loadSfx('phase_4/audio/sfx/AA_sound_whistle.ogg') def loadIntervals(self): def prepareHeightText(): self.heightText.node().setText(TTLocalizer.PartyTrampolineGetHeight % int(self.toon.getZ())) self.heightText.setZ(self.indicatorFactor * self.toon.getZ() + self.heightTextOffset) self.heightTextInterval = Sequence(Func(prepareHeightText), LerpFunc(self.heightText.setAlphaScale, fromData=1.0, toData=0.0, duration=1.0)) def unload(self): DistributedPartyTrampolineActivity.notify.debug('unload') if self.hopOnAnim and self.hopOnAnim.isPlaying(): self.hopOnAnim.finish() if self.hopOffAnim and self.hopOffAnim.isPlaying(): self.hopOffAnim.finish() if self.beginRoundInterval and self.beginRoundInterval.isPlaying(): self.beginRoundInterval.finish() if self.flashTextInterval and self.flashTextInterval.isPlaying(): self.flashTextInterval.finish() if self.heightTextInterval and self.heightTextInterval.isPlaying(): self.heightTextInterval.finish() self.timer.stop() DistributedPartyActivity.unload(self) taskMgr.remove(self.uniqueName('TrampolineActivity.updateTask')) taskMgr.remove(self.uniqueName('TrampolineActivity.remoteUpdateTask')) self.ignoreAll() del self.heightTextInterval del self.beginRoundInterval del self.hopOnAnim del self.hopOffAnim del self.flashTextInterval if hasattr(self, 'beanAnims'): self.cleanupJellyBeans() self.quitEarlyButton.destroy() del self.quitEarlyButton del self.gui del self.activityFSM del self.animFSM return def setBestHeightInfo(self, toonName, height): self.bestHeightInfo = (toonName, height) DistributedPartyTrampolineActivity.notify.debug('%s has the best height of %d' % (toonName, height)) if height > 0: self.setSignNote(TTLocalizer.PartyTrampolineBestHeight % self.bestHeightInfo) else: self.setSignNote(TTLocalizer.PartyTrampolineNoHeightYet) def leaveTrampoline(self): if self.toon != None and self.toon.doId == base.localAvatar.doId: self._showFlashMessage(TTLocalizer.PartyTrampolineTimesUp) self.leavingTrampoline = True self.timer.reset() self.trampB = self.leavingTrampB self.ignore('control') self.quitEarlyButton.stash() self.gui.hide() return def requestAnim(self, request): self.animFSM.request(request) def b_requestAnim(self, request): self.requestAnim(request) self.sendUpdate('requestAnim', [request]) def requestAnimEcho(self, request): if self.toon != None and self.toon.doId != base.localAvatar.doId: self.requestAnim(request) return def removeBeans(self, beansToRemove): for i in beansToRemove: height, bean, guiBean, beanAnim = self.beanDetails[i] guiBean.stash() if i in self.beansToCollect: self.beansToCollect.remove(i) else: self.notify.warning('removeBeans avoided a crash, %d not in self.beansToCollect' % i) self.poofBean(bean, beanAnim) def b_removeBeans(self, beansToRemove): self.removeBeans(beansToRemove) self.sendUpdate('removeBeans', [beansToRemove]) def removeBeansEcho(self, beansToRemove): if self.toon != None and self.toon.doId != base.localAvatar.doId: self.removeBeans(beansToRemove) return def joinRequestDenied(self, reason): DistributedPartyActivity.joinRequestDenied(self, reason) self.showMessage(TTLocalizer.PartyActivityDefaultJoinDeny) base.cr.playGame.getPlace().fsm.request('walk') def exitRequestDenied(self, reason): DistributedPartyActivity.exitRequestDenied(self, reason) self.showMessage(TTLocalizer.PartyActivityDefaultExitDeny) def setState(self, newState, timestamp): DistributedPartyTrampolineActivity.notify.debug('setState( newState=%s, ... )' % newState) DistributedPartyActivity.setState(self, newState, timestamp) self.activityFSM.request(newState) def startIdle(self): DistributedPartyTrampolineActivity.notify.debug('startIdle') def finishIdle(self): DistributedPartyTrampolineActivity.notify.debug('finishIdle') def startRules(self): DistributedPartyTrampolineActivity.notify.debug('startRules') if self.doJellyBeans: self.setupJellyBeans() if self.toon != None and self.toon.doId == base.localAvatar.doId: self.acquireToon() return def startActive(self): DistributedPartyTrampolineActivity.notify.debug('startActive') if self.toon != None and self.toon.doId == base.localAvatar.doId: base.setCellsActive(base.bottomCells, True) self.accept('arrow_left', self.onLeft) self.accept('arrow_left-up', self.onLeftUp) self.accept('arrow_right', self.onRight) self.accept('arrow_right-up', self.onRightUp) self.beginRoundInterval = Sequence(Func(self._showFlashMessage, TTLocalizer.PartyTrampolineReady), Wait(1.2), Func(self.flashMessage, TTLocalizer.PartyTrampolineGo), Func(self.beginRound)) self.beginRoundInterval.start() return def finishActive(self): DistributedPartyTrampolineActivity.notify.debug('finishActive') if self.doJellyBeans: self.cleanupJellyBeans() def setupJellyBeans(self): self.beanAnims = [] self.beansToCollect = [] self.beanDetails = [] self.numBeansCollected = 0 for i in xrange(self.numJellyBeans): bean = self.beans[i] guiBean = self.guiBeans[i] height = self.jellyBeanPositions[i] color = random.choice(self.jellyBeanColors) bean.find('**/jellybean').setColor(color) if self.toon.doId == base.localAvatar.doId: bean.setAlphaScale(1.0) else: bean.setAlphaScale(0.5) guiBean.setColor(color) bean.setZ(height + self.toon.getHeight() + self.beanOffset) guiBean.setZ(height * self.indicatorFactor + self.guiBeanOffset) bean.setH(0.0) bean.unstash() guiBean.unstash() beanAnim = bean.hprInterval(1.5, VBase3((i % 2 * 2 - 1) * 360.0, 0.0, 0.0)) beanAnim.loop() self.beanAnims.append(beanAnim) self.beanDetails.append((height, bean, guiBean, beanAnim)) self.beansToCollect = range(self.numJellyBeans) def cleanupJellyBeans(self): for bean in self.beans: bean.stash() for guiBean in self.guiBeans: guiBean.stash() if hasattr(self, 'beanAnims'): for beanAnim in self.beanAnims: beanAnim.finish() del self.beanAnims del self.beansToCollect def beginRound(self): base.playSfx(self.whistleSound) self.timer.setTime(PartyGlobals.TrampolineDuration) self.timer.countdown(PartyGlobals.TrampolineDuration) self.timer.show() self.gui.show() self.quitEarlyButton.unstash() self.notify.debug('Accepting contorl') self.accept('control', self.onJump) self.notify.debug('setting simulate step to true') self.doSimulateStep = True def acquireToon(self): self.toon.disableSmartCameraViews() self.toon.stopUpdateSmartCamera() camera.wrtReparentTo(render) self.toon.dropShadow.reparentTo(hidden) self.toon.startPosHprBroadcast(period=0.2) self.toonAcceleration = 0.0 self.toonVelocity = 0.0 self.topHeight = 0.0 self.trampB = self.normalTrampB self.leavingTrampoline = False self.hopOnAnim = Sequence(Func(self.toon.b_setAnimState, 'jump', 1.0), Wait(0.4), PartyUtils.arcPosInterval(0.75, self.toon, Point3(0.0, 0.0, self.trampHeight), 5.0, self.tramp), Func(self.postHopOn)) self.hopOnAnim.start() def postHopOn(self): self.toon.setH(self.toon.getH() + 90.0) self.toon.dropShadow.reparentTo(self.surface) self.timeLeftToSimulate = 0.0 self.doSimulateStep = False taskMgr.add(self.updateTask, self.uniqueName('TrampolineActivity.updateTask')) base.setCellsActive(base.leftCells, False) base.setCellsActive(base.bottomCells, False) DistributedPartyActivity.startRules(self) def releaseToon(self): self._hideFlashMessage() self.ignore('arrow_left') self.ignore('arrow_left-up') self.ignore('arrow_right') self.ignore('arrow_right-up') taskMgr.remove(self.uniqueName('TrampolineActivity.updateTask')) self.hopOffAnim = Sequence(self.toon.hprInterval(0.5, VBase3(-90.0, 0.0, 0.0), other=self.tramp), Func(self.toon.b_setAnimState, 'jump', 1.0), Func(self.toon.dropShadow.reparentTo, hidden), Wait(0.4), PartyUtils.arcPosInterval(0.75, self.toon, self.hopOffPos, 5.0, self.tramp), Func(self.postHopOff)) self.hopOffAnim.start() def postHopOff(self): base.setCellsActive(base.leftCells, True) self.timer.stop() self.timer.hide() self.toon.dropShadow.reparentTo(self.toon.getShadowJoint()) self.toon.dropShadow.setAlphaScale(1.0) self.toon.dropShadow.setScale(1.0) self.b_requestAnim('Off') camera.reparentTo(base.localAvatar) base.localAvatar.startUpdateSmartCamera() base.localAvatar.enableSmartCameraViews() base.localAvatar.setCameraPositionByIndex(base.localAvatar.cameraIndex) place = base.cr.playGame.getPlace() if self.doJellyBeans: self.sendUpdate('awardBeans', [self.numBeansCollected, int(self.topHeight)]) if int(self.topHeight) > self.bestHeightInfo[1]: self.sendUpdate('reportHeightInformation', [int(self.topHeight)]) self.d_toonExitDemand() def onTrampolineTrigger(self, collEntry): if self.activityFSM.state_ == 'Idle' and self.toon == None and base.cr.playGame.getPlace().fsm.getCurrentState().getName() == 'walk': base.cr.playGame.getPlace().fsm.request('activity') self.d_toonJoinRequest() else: self.flashMessage(TTLocalizer.PartyTrampolineActivityOccupied, duration=2.0) return def onJump(self): self.notify.debug('got onJump') if self.toon != None and self.toon.getZ() < self.trampHeight: self.toonJumped = True self.b_requestAnim('Jump') else: self.notify.debug('z is less than tramp height') return def onLeft(self): self.turnLeft = True def onLeftUp(self): self.turnLeft = False def onRight(self): self.turnRight = True def onRightUp(self): self.turnRight = False def handleToonJoined(self, toonId): DistributedPartyTrampolineActivity.notify.debug('handleToonJoined') self.toon = self.getAvatar(toonId) if self.toon != None and not self.toon.isEmpty(): self.oldJumpSquatPlayRate = self.toon.getPlayRate('jump-squat') self.oldJumpLandPlayRate = self.toon.getPlayRate('jump-land') self.toon.setPlayRate(2.5, 'jump-squat') self.toon.setPlayRate(2.0, 'jump-land') self.turnLeft = False self.turnRight = False self.activityFSM.request('Rules') if self.toon.doId != base.localAvatar.doId: taskMgr.add(self.remoteUpdateTask, self.uniqueName('TrampolineActivity.remoteUpdateTask')) else: self.notify.warning('handleToonJoined could not get toon %d' % toonId) return def handleToonExited(self, toonId): DistributedPartyTrampolineActivity.notify.debug('handleToonExited') if self.toon != None: if self.toon.doId != base.localAvatar.doId: taskMgr.remove(self.uniqueName('TrampolineActivity.remoteUpdateTask')) self.surface.setZ(self.trampHeight) self.toon.setPlayRate(self.oldJumpSquatPlayRate, 'jump-squat') self.toon.setPlayRate(self.oldJumpLandPlayRate, 'jump-land') self.toon = None return def handleToonDisabled(self, toonId): DistributedPartyTrampolineActivity.notify.debug('handleToonDisabled') DistributedPartyTrampolineActivity.notify.debug('avatar ' + str(toonId) + ' disabled') if base.localAvatar.doId == toonId: self.releaseToon() def handleRulesDone(self): self.sendUpdate('toonReady') self.finishRules() def getTitle(self): if self.doJellyBeans: return TTLocalizer.PartyTrampolineJellyBeanTitle elif self.doTricks: return TTLocalizer.PartyTrampolineTricksTitle else: return DistributedPartyActivity.getTitle(self) def getInstructions(self): return TTLocalizer.PartyTrampolineActivityInstructions def updateTask(self, task): z = self.toon.getZ() dt = globalClock.getDt() if self.doSimulateStep: self.timeLeftToSimulate += dt while self.timeLeftToSimulate >= self.stepDT: z, a = self.simulateStep(z) self.timeLeftToSimulate -= self.stepDT self.toon.setZ(z) if z <= self.trampHeight: self.surface.setZ(z) else: self.surface.setZ(self.trampHeight) self.toonIndicator.setZ((z - self.trampHeight) * self.indicatorFactor) if self.turnLeft: self.toon.setH(self.toon.getH() + self.turnFactor * dt) if self.turnRight: self.toon.setH(self.toon.getH() - self.turnFactor * dt) currentPos = base.camera.getPos(self.toon) vec = self.targetCameraPos - currentPos newPos = currentPos + vec * (dt * self.cameraSpeed) base.camera.setPos(self.toon, newPos) base.camera.lookAt(self.toon) #if z > self.trampHeight: # heightFactor = 1.0 - min(1.0, (z - self.trampHeight) / self.dropShadowCutoff) # self.toon.dropShadow.setAlphaScale(heightFactor) # self.toon.dropShadow.setScale(max(0.1, heightFactor)) #else: # self.toon.dropShadow.setAlphaScale(1.0) # self.toon.dropShadow.setScale(1.0) if self.leavingTrampoline and z < self.trampHeight and abs(a) < 0.1: self.releaseToon() return Task.cont def simulateStep(self, z): if z >= self.trampHeight: a = self.g self.toonJumped = False else: a = self.g + self.trampK * (self.trampHeight - z) - self.trampB * self.toonVelocity if self.toonJumped: if self.lastPeak > self.earlyJumpThreshold or self.toonVelocity >= -300000.0: a += self.jumpBoost if self.lastPeak < self.beginningBoostThreshold: a += self.beginningBoost lastVelocity = self.toonVelocity self.toonVelocity += a * self.stepDT if lastVelocity > 0.0 and self.toonVelocity <= 0.0: topOfJump = True bottomOfJump = False elif lastVelocity < 0.0 and self.toonVelocity >= 0.0: topOfJump = False bottomOfJump = True else: topOfJump = False bottomOfJump = False newZ = z + self.toonVelocity * self.stepDT if newZ > self.topHeight: self.topHeight = newZ if self.doJellyBeans: self.collectJellyBeans(newZ) if topOfJump: self.lastPeak = newZ if newZ >= self.minHeightForText: self.heightTextInterval.start() if topOfJump: if newZ > self.trampHeight + 20.0: self.b_requestAnim('Falling') elif self.animFSM.state_ == 'Jump': self.b_requestAnim('Falling') if newZ <= self.trampHeight and z > self.trampHeight: if self.animFSM.state_ == 'Falling': self.b_requestAnim('Land') elif self.animFSM.state_ != 'Neutral': self.b_requestAnim('Neutral') if bottomOfJump and a > self.boingThreshold: base.playSfx(self.boingSound) return (newZ, a) def collectJellyBeans(self, z): beansToRemove = [] for i in self.beansToCollect: height = self.beanDetails[i][0] if height <= z: beansToRemove.append(i) if len(beansToRemove) > 0: base.playSfx(self.jellyBeanSound) self.numBeansCollected += len(beansToRemove) self.b_removeBeans(beansToRemove) def remoteUpdateTask(self, task): if self.toon != None and not self.toon.isEmpty(): z = self.toon.getZ() if z <= self.trampHeight: self.surface.setZ(z) else: self.surface.setZ(self.trampHeight) return Task.cont def poofBean(self, bean, beanAnim): if bean == None: self.notify.warning('poofBean, returning immediately as bean is None') return if bean.isEmpty(): self.notify.warning('poofBean, returning immediately as bean is empty') return currentAlpha = bean.getColorScale()[3] currentScale = bean.getScale() poofAnim = Sequence(Parallel(LerpFunc(bean.setAlphaScale, fromData=currentAlpha, toData=0.0, duration=0.25), LerpFunc(bean.setScale, fromData=currentScale, toData=currentScale * 5.0, duration=0.25)), Func(bean.stash), Func(beanAnim.finish), Func(bean.setAlphaScale, currentAlpha), Func(bean.setScale, currentScale)) poofAnim.start() return def _showFlashMessage(self, message): if self.isDisabled(): return if self.flashTextInterval is not None and self.flashTextInterval.isPlaying(): self.flashTextInterval.finish() self.flashText.setText(message) self.flashText.setAlphaScale(1.0) self.flashText.unstash() return def _hideFlashMessage(self, duration = 0.0): if self.isDisabled(): pass self.flashTextInterval = Sequence(Wait(duration), LerpFunc(self.flashText.setAlphaScale, fromData=1.0, toData=0.0, duration=1.0), Func(self.flashText.stash)) self.flashTextInterval.start() def flashMessage(self, message, duration = 0.5): self._showFlashMessage(message) self._hideFlashMessage(duration)
class DistributedLawbotCannon(DistributedObject.DistributedObject): notify = DirectNotifyGlobal.directNotify.newCategory('DistributedLawbotCannon') LOCAL_CANNON_MOVE_TASK = 'localCannonMoveTask' FIRE_KEY = 'control' UP_KEY = 'arrow_up' DOWN_KEY = 'arrow_down' LEFT_KEY = 'arrow_left' RIGHT_KEY = 'arrow_right' HIT_GROUND = 0 def __init__(self, cr): DistributedObject.DistributedObject.__init__(self, cr) self.index = None self.avId = 0 self.av = None self.localToonShooting = 0 self.cannonsActive = 0 self.cannonLocation = None self.cannonPostion = None self.cannon = None self.madeGui = 0 self.jurorToon = None self.toonModel = None self.toonHead = None self.toonScale = None self.dustCloud = None self.hitBumper = 0 self.hitTarget = 0 self.lastPos = Vec3(0, 0, 0) self.lastVel = Vec3(0, 0, 0) self.vel = Vec3(0, 0, 0) self.landingPos = Vec3(0, 0, 0) self.t = 0 self.lastT = 0 self.deltaT = 0 self.hitTrack = None self.flyColNode = None self.flyColNodePath = None self.localAvId = base.localAvatar.doId self.model_Created = 0 return def disable(self): taskMgr.remove(self.uniqueName('fireCannon')) taskMgr.remove(self.uniqueName('shootTask')) self.__stopFlyTask(self.avId) taskMgr.remove(self.uniqueName('flyTask')) self.ignoreAll() self.setMovie(CannonGlobals.CANNON_MOVIE_CLEAR, 0, 0) self.nodePath.detachNode() self.__unmakeGui() if self.hitTrack: self.hitTrack.finish() del self.hitTrack self.hitTrack = None DistributedObject.DistributedObject.disable(self) return def delete(self): self.offstage() self.unload() DistributedObject.DistributedObject.delete(self) def announceGenerate(self): DistributedObject.DistributedObject.announceGenerate(self) self.boss.cannons[self.index] = self def generateInit(self): DistributedObject.DistributedObject.generateInit(self) self.nodePath = NodePath(self.uniqueName('Cannon')) self.load() self.activateCannons() def setPosHpr(self, x, y, z, h, p, r): self.nodePath.setPosHpr(x, y, z, h, p, r) def setBossCogId(self, bossCogId): self.bossCogId = bossCogId self.boss = base.cr.doId2do[bossCogId] def getSphereRadius(self): return 1.5 def getParentNodePath(self): return render def setIndex(self, index): self.index = index def load(self): self.cannon = loader.loadModel('phase_4/models/minigames/toon_cannon') self.collSphere = CollisionSphere(0, 0, 0, self.getSphereRadius()) self.dustCloud = DustCloud.DustCloud(render) self.dustCloud.setBillboardPointEye() self.collSphere.setTangible(1) self.collNode = CollisionNode(self.uniqueName('CannonSphere')) self.collNode.setCollideMask(ToontownGlobals.WallBitmask) self.collNode.addSolid(self.collSphere) self.collNodePath = self.nodePath.attachNewNode(self.collNode) self.cannon.reparentTo(self.nodePath) self.kartColNode = CollisionNode(self.uniqueName('KartColNode')) self.kartNode = self.nodePath.attachNewNode(self.kartColNode) self.sndCannonMove = base.loader.loadSfx('phase_4/audio/sfx/MG_cannon_adjust.ogg') self.sndCannonFire = base.loader.loadSfx('phase_4/audio/sfx/MG_cannon_fire_alt.ogg') self.sndHitGround = base.loader.loadSfx('phase_4/audio/sfx/MG_cannon_hit_dirt.ogg') self.sndHitChair = base.loader.loadSfx('phase_11/audio/sfx/LB_toon_jury.ogg') self.cannon.hide() self.flashingLabel = None return def unload(self): if self.cannon: self.cannon.removeNode() del self.cannon if self.dustCloud != None: self.dustCloud.destroy() del self.dustCloud del self.sndCannonMove del self.sndCannonFire del self.sndHitGround del self.sndHitChair if self.av: self.__resetToon(self.av) self.av.loop('neutral') self.av.setPlayRate(1.0, 'run') if self.toonHead != None: self.toonHead.stopBlink() self.toonHead.stopLookAroundNow() self.toonHead.delete() del self.toonHead if self.toonModel != None: self.toonModel.removeNode() del self.toonModel if self.jurorToon != None: self.jurorToon.delete() del self.jurorToon del self.toonScale return def activateCannons(self): if not self.cannonsActive: self.cannonsActive = 1 self.onstage() self.nodePath.reparentTo(self.getParentNodePath()) self.accept(self.uniqueName('enterCannonSphere'), self.__handleEnterSphere) def onstage(self): self.__createCannon() self.cannon.reparentTo(self.nodePath) self.dustCloud.reparentTo(render) def offstage(self): if self.cannon: self.cannon.reparentTo(hidden) if self.dustCloud: self.dustCloud.reparentTo(hidden) self.dustCloud.stop() def __createCannon(self): self.barrel = self.cannon.find('**/cannon') self.cannonLocation = Point3(0, 0, 0.025) self.cannonPosition = [0, CANNON_ANGLE_MIN] self.cannon.setPos(self.cannonLocation) self.__updateCannonPosition(self.avId) def updateCannonPosition(self, avId, zRot, angle): if avId != self.localAvId: self.cannonPosition = [zRot, angle] self.__updateCannonPosition(avId) def __updateCannonPosition(self, avId): self.cannon.setHpr(self.cannonPosition[0], 0.0, 0.0) self.barrel.setHpr(0.0, self.cannonPosition[1], 0.0) maxP = 90 newP = self.barrel.getP() yScale = 1 - 0.5 * float(newP) / maxP shadow = self.cannon.find('**/square_drop_shadow') shadow.setScale(1, yScale, 1) def __handleEnterSphere(self, collEntry): self.d_requestEnter() def d_requestEnter(self): self.sendUpdate('requestEnter', []) def setMovie(self, mode, avId, extraInfo): wasLocalToon = self.localToonShooting self.avId = avId if mode == CannonGlobals.CANNON_MOVIE_CLEAR: self.setLanded() elif mode == CannonGlobals.CANNON_MOVIE_LANDED: self.setLanded() elif mode == CannonGlobals.CANNON_MOVIE_FORCE_EXIT: self.exitCannon(self.avId) self.setLanded() elif mode == CannonGlobals.CANNON_MOVIE_LOAD: if self.avId == base.localAvatar.doId: self.cannonBallsLeft = extraInfo base.cr.playGame.getPlace().setState('crane') base.localAvatar.setTeleportAvailable(0) self.localToonShooting = 1 self.__makeGui() camera.reparentTo(self.barrel) camera.setPos(0.5, -2, 2.5) camera.setHpr(0, 0, 0) self.boss.toonEnteredCannon(self.avId, self.index) if self.avId in self.cr.doId2do: self.av = self.cr.doId2do[self.avId] self.acceptOnce(self.av.uniqueName('disable'), self.__avatarGone) self.av.loop('neutral') self.av.stopSmooth() self.__destroyToonModels() self.__createToonModels() self.av.setPosHpr(3, 0, 0, 90, 0, 0) self.av.reparentTo(self.cannon) else: self.notify.warning('Unknown avatar %d in cannon %d' % (self.avId, self.doId)) else: self.notify.warning('unhandled case, mode = %d' % mode) def __avatarGone(self): self.setMovie(CannonGlobals.CANNON_MOVIE_CLEAR, 0, 0) def __makeGui(self): if self.madeGui: return NametagGlobals.setWant2dNametags(False) guiModel = 'phase_4/models/gui/cannon_game_gui' cannonGui = loader.loadModel(guiModel) self.aimPad = DirectFrame(image=cannonGui.find('**/CannonFire_PAD'), relief=None, pos=(0.7, 0, -0.553333), scale=0.8) cannonGui.removeNode() self.fireButton = DirectButton(parent=self.aimPad, image=((guiModel, '**/Fire_Btn_UP'), (guiModel, '**/Fire_Btn_DN'), (guiModel, '**/Fire_Btn_RLVR')), relief=None, pos=(0.0115741, 0, 0.00505051), scale=1.0, command=self.__firePressed) self.upButton = DirectButton(parent=self.aimPad, image=((guiModel, '**/Cannon_Arrow_UP'), (guiModel, '**/Cannon_Arrow_DN'), (guiModel, '**/Cannon_Arrow_RLVR')), relief=None, pos=(0.0115741, 0, 0.221717)) self.downButton = DirectButton(parent=self.aimPad, image=((guiModel, '**/Cannon_Arrow_UP'), (guiModel, '**/Cannon_Arrow_DN'), (guiModel, '**/Cannon_Arrow_RLVR')), relief=None, pos=(0.0136112, 0, -0.210101), image_hpr=(0, 0, 180)) self.leftButton = DirectButton(parent=self.aimPad, image=((guiModel, '**/Cannon_Arrow_UP'), (guiModel, '**/Cannon_Arrow_DN'), (guiModel, '**/Cannon_Arrow_RLVR')), relief=None, pos=(-0.199352, 0, -0.000505269), image_hpr=(0, 0, -90)) self.rightButton = DirectButton(parent=self.aimPad, image=((guiModel, '**/Cannon_Arrow_UP'), (guiModel, '**/Cannon_Arrow_DN'), (guiModel, '**/Cannon_Arrow_RLVR')), relief=None, pos=(0.219167, 0, -0.00101024), image_hpr=(0, 0, 90)) guiClose = loader.loadModel('phase_3.5/models/gui/avatar_panel_gui') cannonBallText = '%d/%d' % (self.cannonBallsLeft, ToontownGlobals.LawbotBossCannonBallMax) self.cannonBallLabel = DirectLabel(parent=self.aimPad, text=cannonBallText, text_fg=VBase4(1, 1, 1, 1), text_align=TextNode.ACenter, relief=None, pos=(0.475, 0.0, -0.35), scale=0.25) if self.cannonBallsLeft < 5: if self.flashingLabel: self.flashingLabel.stop() flashingTrack = Sequence() for i in xrange(10): flashingTrack.append(LerpColorScaleInterval(self.cannonBallLabel, 0.5, VBase4(1, 0, 0, 1))) flashingTrack.append(LerpColorScaleInterval(self.cannonBallLabel, 0.5, VBase4(1, 1, 1, 1))) self.flashingLabel = flashingTrack self.flashingLabel.start() self.aimPad.setColor(1, 1, 1, 0.9) def bindButton(button, upHandler, downHandler): button.bind(DGG.B1PRESS, lambda x, handler = upHandler: handler()) button.bind(DGG.B1RELEASE, lambda x, handler = downHandler: handler()) bindButton(self.upButton, self.__upPressed, self.__upReleased) bindButton(self.downButton, self.__downPressed, self.__downReleased) bindButton(self.leftButton, self.__leftPressed, self.__leftReleased) bindButton(self.rightButton, self.__rightPressed, self.__rightReleased) self.__enableAimInterface() self.madeGui = 1 return def __unmakeGui(self): self.notify.debug('__unmakeGui') if not self.madeGui: return if self.flashingLabel: self.flashingLabel.finish() self.flashingLabel = None NametagGlobals.setWant2dNametags(True) self.__disableAimInterface() self.upButton.unbind(DGG.B1PRESS) self.upButton.unbind(DGG.B1RELEASE) self.downButton.unbind(DGG.B1PRESS) self.downButton.unbind(DGG.B1RELEASE) self.leftButton.unbind(DGG.B1PRESS) self.leftButton.unbind(DGG.B1RELEASE) self.rightButton.unbind(DGG.B1PRESS) self.rightButton.unbind(DGG.B1RELEASE) self.aimPad.destroy() del self.aimPad del self.fireButton del self.upButton del self.downButton del self.leftButton del self.rightButton self.madeGui = 0 return def __enableAimInterface(self): self.aimPad.show() self.accept(self.FIRE_KEY, self.__fireKeyPressed) self.accept(self.UP_KEY, self.__upKeyPressed) self.accept(self.DOWN_KEY, self.__downKeyPressed) self.accept(self.LEFT_KEY, self.__leftKeyPressed) self.accept(self.RIGHT_KEY, self.__rightKeyPressed) self.__spawnLocalCannonMoveTask() def __disableAimInterface(self): self.aimPad.hide() self.ignore(self.FIRE_KEY) self.ignore(self.UP_KEY) self.ignore(self.DOWN_KEY) self.ignore(self.LEFT_KEY) self.ignore(self.RIGHT_KEY) self.ignore(self.FIRE_KEY + '-up') self.ignore(self.UP_KEY + '-up') self.ignore(self.DOWN_KEY + '-up') self.ignore(self.LEFT_KEY + '-up') self.ignore(self.RIGHT_KEY + '-up') self.__killLocalCannonMoveTask() def __fireKeyPressed(self): self.ignore(self.FIRE_KEY) self.accept(self.FIRE_KEY + '-up', self.__fireKeyReleased) self.__firePressed() def __upKeyPressed(self): self.ignore(self.UP_KEY) self.accept(self.UP_KEY + '-up', self.__upKeyReleased) self.__upPressed() def __downKeyPressed(self): self.ignore(self.DOWN_KEY) self.accept(self.DOWN_KEY + '-up', self.__downKeyReleased) self.__downPressed() def __leftKeyPressed(self): self.ignore(self.LEFT_KEY) self.accept(self.LEFT_KEY + '-up', self.__leftKeyReleased) self.__leftPressed() def __rightKeyPressed(self): self.ignore(self.RIGHT_KEY) self.accept(self.RIGHT_KEY + '-up', self.__rightKeyReleased) self.__rightPressed() def __fireKeyReleased(self): self.ignore(self.FIRE_KEY + '-up') self.accept(self.FIRE_KEY, self.__fireKeyPressed) def __leftKeyReleased(self): self.ignore(self.LEFT_KEY + '-up') self.accept(self.LEFT_KEY, self.__leftKeyPressed) self.__leftReleased() def __rightKeyReleased(self): self.ignore(self.RIGHT_KEY + '-up') self.accept(self.RIGHT_KEY, self.__rightKeyPressed) self.__rightReleased() def __upKeyReleased(self): self.ignore(self.UP_KEY + '-up') self.accept(self.UP_KEY, self.__upKeyPressed) self.__upReleased() def __downKeyReleased(self): self.ignore(self.DOWN_KEY + '-up') self.accept(self.DOWN_KEY, self.__downKeyPressed) self.__downReleased() def __leaveCannon(self): self.notify.debug('__leaveCannon') self.sendUpdate('requestLeave') def __firePressed(self): self.notify.debug('fire pressed') if not self.boss.state == 'BattleTwo': self.notify.debug('boss is in state=%s, not firing' % self.boss.state) return self.__broadcastLocalCannonPosition() self.__unmakeGui() self.sendUpdate('setCannonLit', [self.cannonPosition[0], self.cannonPosition[1]]) def __upPressed(self): self.notify.debug('up pressed') self.upPressed = self.__enterControlActive(self.upPressed) def __downPressed(self): self.notify.debug('down pressed') self.downPressed = self.__enterControlActive(self.downPressed) def __leftPressed(self): self.notify.debug('left pressed') self.leftPressed = self.__enterControlActive(self.leftPressed) def __rightPressed(self): self.notify.debug('right pressed') self.rightPressed = self.__enterControlActive(self.rightPressed) def __upReleased(self): self.notify.debug('up released') self.upPressed = self.__exitControlActive(self.upPressed) def __downReleased(self): self.notify.debug('down released') self.downPressed = self.__exitControlActive(self.downPressed) def __leftReleased(self): self.notify.debug('left released') self.leftPressed = self.__exitControlActive(self.leftPressed) def __rightReleased(self): self.notify.debug('right released') self.rightPressed = self.__exitControlActive(self.rightPressed) def __enterControlActive(self, control): return control + 1 def __exitControlActive(self, control): return max(0, control - 1) def __spawnLocalCannonMoveTask(self): self.leftPressed = 0 self.rightPressed = 0 self.upPressed = 0 self.downPressed = 0 self.cannonMoving = 0 task = Task(self.__localCannonMoveTask) task.lastPositionBroadcastTime = 0.0 taskMgr.add(task, self.LOCAL_CANNON_MOVE_TASK) def __killLocalCannonMoveTask(self): taskMgr.remove(self.LOCAL_CANNON_MOVE_TASK) if self.cannonMoving: self.sndCannonMove.stop() def __localCannonMoveTask(self, task): pos = self.cannonPosition oldRot = pos[0] oldAng = pos[1] rotVel = 0 if self.leftPressed: rotVel += CANNON_ROTATION_VEL if self.rightPressed: rotVel -= CANNON_ROTATION_VEL pos[0] += rotVel * globalClock.getDt() if pos[0] < CANNON_ROTATION_MIN: pos[0] = CANNON_ROTATION_MIN elif pos[0] > CANNON_ROTATION_MAX: pos[0] = CANNON_ROTATION_MAX angVel = 0 if self.upPressed: angVel += CANNON_ANGLE_VEL if self.downPressed: angVel -= CANNON_ANGLE_VEL pos[1] += angVel * globalClock.getDt() if pos[1] < CANNON_ANGLE_MIN: pos[1] = CANNON_ANGLE_MIN elif pos[1] > CANNON_ANGLE_MAX: pos[1] = CANNON_ANGLE_MAX if oldRot != pos[0] or oldAng != pos[1]: if self.cannonMoving == 0: self.cannonMoving = 1 base.playSfx(self.sndCannonMove, looping=1) self.__updateCannonPosition(self.localAvId) if task.time - task.lastPositionBroadcastTime > CANNON_MOVE_UPDATE_FREQ: task.lastPositionBroadcastTime = task.time self.__broadcastLocalCannonPosition() elif self.cannonMoving: self.cannonMoving = 0 self.sndCannonMove.stop() self.__broadcastLocalCannonPosition() return Task.cont def __broadcastLocalCannonPosition(self): self.sendUpdate('setCannonPosition', [self.cannonPosition[0], self.cannonPosition[1]]) def __updateCannonPosition(self, avId): self.cannon.setHpr(self.cannonPosition[0], 0.0, 0.0) self.barrel.setHpr(0.0, self.cannonPosition[1], 0.0) maxP = 90 newP = self.barrel.getP() yScale = 1 - 0.5 * float(newP) / maxP shadow = self.cannon.find('**/square_drop_shadow') shadow.setScale(1, yScale, 1) def __createToonModels(self): self.model_Created = 1 self.jurorToon = NPCToons.createLocalNPC(ToontownGlobals.LawbotBossBaseJurorNpcId + self.index) self.toonScale = self.jurorToon.getScale() jurorToonParent = render.attachNewNode('toonOriginChange') self.jurorToon.wrtReparentTo(jurorToonParent) self.jurorToon.setPosHpr(0, 0, -(self.jurorToon.getHeight() / 2.0), 0, -90, 0) self.toonModel = jurorToonParent self.toonHead = ToonHead.ToonHead() self.toonHead.setupHead(self.jurorToon.style) self.toonHead.reparentTo(hidden) self.__loadToonInCannon() def __destroyToonModels(self): if (0): self.av.dropShadow.show() if self.dropShadow != None: self.dropShadow.removeNode() self.dropShadow = None self.hitBumper = 0 self.hitTarget = 0 self.angularVel = 0 self.vel = Vec3(0, 0, 0) self.lastVel = Vec3(0, 0, 0) self.lastPos = Vec3(0, 0, 0) self.landingPos = Vec3(0, 0, 0) self.t = 0 self.lastT = 0 self.deltaT = 0 self.av = None self.lastWakeTime = 0 self.localToonShooting = 0 if self.toonHead != None: self.toonHead.reparentTo(hidden) self.toonHead.stopBlink() self.toonHead.stopLookAroundNow() self.toonHead = None if self.toonModel != None: self.toonModel.removeNode() self.toonModel = None if self.jurorToon != None: self.jurorToon.delete() self.jurorToon = None self.model_Created = 0 return def __loadToonInCannon(self): self.toonModel.reparentTo(hidden) self.toonHead.startBlink() self.toonHead.startLookAround() self.toonHead.reparentTo(self.barrel) self.toonHead.setPosHpr(0, 6, 0, 0, -45, 0) sc = self.toonScale self.toonHead.setScale(render, sc[0], sc[1], sc[2]) def exitCannon(self, avId): self.__unmakeGui() if self.avId == avId: self.av.reparentTo(render) self.__resetToonToCannon(self.av) def __resetToonToCannon(self, avatar): pos = None if not avatar: if self.avId: avatar = base.cr.doId2do.get(self.avId, None) if avatar: if hasattr(self, 'cannon') and self.cannon: avatar.reparentTo(self.cannon) avatar.setPosHpr(3, 0, 0, 90, 0, 0) avatar.wrtReparentTo(render) self.__resetToon(avatar) return def __resetToon(self, avatar, pos = None): if avatar: self.__stopCollisionHandler(avatar) self.__setToonUpright(avatar, pos) if self.localToonShooting: self.notify.debug('toon setting position to %s' % pos) if pos: base.localAvatar.setPos(pos) camera.reparentTo(avatar) camera.setPos(self.av.cameraPositions[0][0]) place = base.cr.playGame.getPlace() if place: place.setState('finalBattle') self.b_setLanded() def __stopCollisionHandler(self, avatar): if avatar: avatar.loop('neutral') if self.flyColNode: self.flyColNode = None if avatar == base.localAvatar: avatar.collisionsOn() self.flyColSphere = None if self.flyColNodePath: base.cTrav.removeCollider(self.flyColNodePath) self.flyColNodePath.removeNode() self.flyColNodePath = None self.handler = None return def __setToonUpright(self, avatar, pos = None): if avatar: if not pos: pos = avatar.getPos(render) avatar.setPos(render, pos) avatar.loop('neutral') def b_setLanded(self): self.d_setLanded() def d_setLanded(self): if self.localToonShooting: self.sendUpdate('setLanded', []) def setLanded(self): self.removeAvFromCannon() def removeAvFromCannon(self): if self.av != None: self.__stopCollisionHandler(self.av) self.av.resetLOD() place = base.cr.playGame.getPlace() if self.av == base.localAvatar: if place: place.setState('finalBattle') self.av.loop('neutral') self.av.setPlayRate(1.0, 'run') if self.av.getParent().getName() == 'toonOriginChange': self.av.wrtReparentTo(render) self.__setToonUpright(self.av) if self.av == base.localAvatar: self.av.startPosHprBroadcast() self.av.startSmooth() self.av.setScale(1, 1, 1) self.ignore(self.av.uniqueName('disable')) self.__destroyToonModels() return def setCannonWillFire(self, avId, fireTime, zRot, angle, timestamp): self.notify.debug('setCannonWillFire: ' + str(avId) + ': zRot=' + str(zRot) + ', angle=' + str(angle) + ', time=' + str(fireTime)) if not self.model_Created: self.notify.warning("We walked into the zone mid-flight, so we won't see it") return self.cannonPosition[0] = zRot self.cannonPosition[1] = angle self.__updateCannonPosition(avId) task = Task(self.__fireCannonTask) task.avId = avId ts = globalClockDelta.localElapsedTime(timestamp) task.fireTime = fireTime - ts if task.fireTime < 0.0: task.fireTime = 0.0 taskMgr.add(task, self.taskName('fireCannon')) def __fireCannonTask(self, task): launchTime = task.fireTime avId = task.avId if self.toonHead == None or not self.boss.state == 'BattleTwo': return Task.done startPos, startHpr, startVel, trajectory, timeOfImpact, hitWhat = self.__calcFlightResults(avId, launchTime) self.notify.debug('start position: ' + str(startPos)) self.notify.debug('start velocity: ' + str(startVel)) self.notify.debug('time of launch: ' + str(launchTime)) self.notify.debug('time of impact: ' + str(timeOfImpact)) self.notify.debug('location of impact: ' + str(trajectory.getPos(timeOfImpact))) head = self.toonHead head.stopBlink() head.stopLookAroundNow() head.reparentTo(hidden) juror = self.toonModel juror.reparentTo(render) juror.setPos(startPos) barrelHpr = self.barrel.getHpr(render) juror.setHpr(startHpr) self.jurorToon.loop('swim') self.jurorToon.setPosHpr(0, 0, -(self.jurorToon.getHeight() / 2.0), 0, 0, 0) info = {} info['avId'] = avId info['trajectory'] = trajectory info['launchTime'] = launchTime info['timeOfImpact'] = timeOfImpact info['hitWhat'] = hitWhat info['toon'] = self.toonModel info['hRot'] = self.cannonPosition[0] info['haveWhistled'] = 0 info['maxCamPullback'] = CAMERA_PULLBACK_MIN if self.localToonShooting: camera.reparentTo(juror) camera.setP(45.0) camera.setZ(-10.0) self.flyColSphere = CollisionSphere(0, 0, self.av.getHeight() / 2.0, 1.0) self.flyColNode = CollisionNode(self.uniqueName('flySphere')) self.flyColNode.setCollideMask(ToontownGlobals.WallBitmask | ToontownGlobals.FloorBitmask | ToontownGlobals.PieBitmask) self.flyColNode.addSolid(self.flyColSphere) self.flyColNodePath = self.jurorToon.attachNewNode(self.flyColNode) self.flyColNodePath.setColor(1, 0, 0, 1) self.handler = CollisionHandlerEvent() self.handler.setInPattern(self.uniqueName('cannonHit')) base.cTrav.addCollider(self.flyColNodePath, self.handler) self.accept(self.uniqueName('cannonHit'), self.__handleCannonHit) shootTask = Task(self.__shootTask, self.taskName('shootTask')) flyTask = Task(self.__flyTask, self.taskName('flyTask')) shootTask.info = info flyTask.info = info seqTask = Task.sequence(shootTask, flyTask) taskMgr.add(seqTask, self.taskName('flyingToon') + '-' + str(avId)) self.acceptOnce(self.uniqueName('stopFlyTask'), self.__stopFlyTask) return Task.done def __toRadians(self, angle): return angle * 2.0 * math.pi / 360.0 def __toDegrees(self, angle): return angle * 360.0 / (2.0 * math.pi) def __calcFlightResults(self, avId, launchTime): head = self.toonHead startPos = head.getPos(render) startHpr = head.getHpr(render) hpr = self.barrel.getHpr(render) rotation = self.__toRadians(hpr[0]) angle = self.__toRadians(hpr[1]) horizVel = INITIAL_VELOCITY * math.cos(angle) xVel = horizVel * -math.sin(rotation) yVel = horizVel * math.cos(rotation) zVel = INITIAL_VELOCITY * math.sin(angle) startVel = Vec3(xVel, yVel, zVel) trajectory = Trajectory.Trajectory(launchTime, startPos, startVel) self.trajectory = trajectory timeOfImpact, hitWhat = self.__calcToonImpact(trajectory) return startPos, startHpr, startVel, trajectory, 3 * timeOfImpact, hitWhat def __calcToonImpact(self, trajectory): t_groundImpact = trajectory.checkCollisionWithGround(GROUND_PLANE_MIN) if t_groundImpact >= trajectory.getStartTime(): return (t_groundImpact, self.HIT_GROUND) else: self.notify.error('__calcToonImpact: toon never impacts ground?') return (0.0, self.HIT_GROUND) def __handleCannonHit(self, collisionEntry): if self.av == None or self.flyColNode == None: return interPt = collisionEntry.getSurfacePoint(render) hitNode = collisionEntry.getIntoNode().getName() fromNodePath = collisionEntry.getFromNodePath() intoNodePath = collisionEntry.getIntoNodePath() ignoredHits = ['NearBoss'] for nodeName in ignoredHits: if hitNode == nodeName: return self.__stopFlyTask(self.avId) self.__stopCollisionHandler(self.jurorToon) if self.localToonShooting: camera.wrtReparentTo(render) pos = interPt hpr = self.jurorToon.getHpr() track = Sequence() if self.localToonShooting: pass chairlist = ['trigger-chair'] for index in xrange(len(ToontownGlobals.LawbotBossChairPosHprs)): chairlist.append('Chair-%s' % index) if hitNode in chairlist: track.append(Func(self.__hitChair, self.jurorToon, pos)) track.append(Wait(1.0)) track.append(Func(self.__setToonUpright, self.av)) if self.av == base.localAvatar: strs = hitNode.split('-') chairNum = int(strs[1]) self.boss.sendUpdate('hitChair', [chairNum, self.index]) else: track.append(Func(self.__hitGround, self.jurorToon, pos)) track.append(Wait(1.0)) track.append(Func(self.__setToonUpright, self.av)) track.append(Func(self.b_setLanded)) if self.localToonShooting: pass if self.hitTrack: self.hitTrack.finish() self.hitTrack = track self.hitTrack.start() return def enterCannonHit(self, collisionEntry): pass def __shootTask(self, task): base.playSfx(self.sndCannonFire) return Task.done def __flyTask(self, task): toon = task.info['toon'] if toon.isEmpty(): self.__resetToonToCannon(self.av) return Task.done curTime = task.time + task.info['launchTime'] t = min(curTime, task.info['timeOfImpact']) self.lastT = self.t self.t = t deltaT = self.t - self.lastT self.deltaT = deltaT if t >= task.info['timeOfImpact']: self.__resetToonToCannon(self.av) return Task.done pos = task.info['trajectory'].getPos(t) toon.setFluidPos(pos) vel = task.info['trajectory'].getVel(t) run = math.sqrt(vel[0] * vel[0] + vel[1] * vel[1]) rise = vel[2] theta = self.__toDegrees(math.atan(rise / run)) toon.setHpr(self.cannon.getH(render), -90 + theta, 0) view = 2 lookAt = task.info['toon'].getPos(render) hpr = task.info['toon'].getHpr(render) if self.localToonShooting: if view == 0: camera.wrtReparentTo(render) camera.lookAt(lookAt) elif view == 1: camera.reparentTo(render) camera.setPos(render, 100, 100, 35.25) camera.lookAt(render, lookAt) elif view == 2: if hpr[1] > -90: camera.setPos(0, 0, -30) if camera.getZ() < lookAt[2]: camera.setZ(render, lookAt[2] + 10) camera.lookAt(Point3(0, 0, 0)) return Task.cont def __stopFlyTask(self, avId): taskMgr.remove(self.taskName('flyingToon') + '-' + str(avId)) def __hitGround(self, avatar, pos, extraArgs = []): hitP = avatar.getPos(render) h = self.barrel.getH(render) avatar.setPos(pos[0], pos[1], pos[2] + avatar.getHeight() / 3.0) avatar.setHpr(h, -135, 0) self.dustCloud.setPos(render, pos[0], pos[1], pos[2] + avatar.getHeight() / 3.0) self.dustCloud.setScale(0.35) self.dustCloud.play() base.playSfx(self.sndHitGround) avatar.hide() def __hitChair(self, avatar, pos, extraArgs = []): hitP = avatar.getPos(render) h = self.barrel.getH(render) avatar.setPos(pos[0], pos[1], pos[2] + avatar.getHeight() / 3.0) avatar.setHpr(h, -135, 0) self.dustCloud.setPos(render, pos[0], pos[1], pos[2] + avatar.getHeight() / 3.0) self.dustCloud.setScale(0.35) self.dustCloud.play() base.playSfx(self.sndHitGround) base.playSfx(self.sndHitChair) avatar.hide() def generateCannonAppearTrack(self, avatar): self.cannon.setScale(0.1) self.cannon.show() kartTrack = Parallel(Sequence(ActorInterval(avatar, 'feedPet'), Func(avatar.loop, 'neutral')), Sequence(Func(self.cannon.reparentTo, avatar.rightHand), Wait(2.1), Func(self.cannon.wrtReparentTo, render), Func(self.cannon.setShear, 0, 0, 0), Parallel(LerpHprInterval(self.cannon, hpr=self.nodePath.getHpr(render), duration=1.2), ProjectileInterval(self.cannon, endPos=self.nodePath.getPos(render), duration=1.2, gravityMult=0.45)), Wait(0.2), Sequence(LerpScaleInterval(self.cannon, scale=Point3(1.1, 1.1, 0.1), duration=0.2), LerpScaleInterval(self.cannon, scale=Point3(0.9, 0.9, 0.1), duration=0.1), LerpScaleInterval(self.cannon, scale=Point3(1.0, 1.0, 0.1), duration=0.1), LerpScaleInterval(self.cannon, scale=Point3(1.0, 1.0, 1.1), duration=0.2), LerpScaleInterval(self.cannon, scale=Point3(1.0, 1.0, 0.9), duration=0.1), LerpScaleInterval(self.cannon, scale=Point3(1.0, 1.0, 1.0), duration=0.1), Func(self.cannon.wrtReparentTo, self.nodePath)))) return kartTrack
class DistributedGunGameCapturePoint(DistributedNode): notify = directNotify.newCategory('DistributedGunGameCapturePoint') def __init__(self, cr): DistributedNode.__init__(self, cr) NodePath.__init__(self, 'capture_point') self.capturePoint = None self.captureCircle = None self.aoogahSfx = None self.circleTrack = None self.circleTrackPlayRate = 1.0 self.circleTrackDirection = 0 self.team = None self.collNP = None self.pointCollNode = None self.neutralCapTexture = None self.redCapTexture = None self.blueCapTexture = None self.defCapTexture = None def delete(self): self.ignoreAll() if self.collNP: self.collNP.removeNode() if self.capturePoint: self.capturePoint.removeNode() if self.captureCircle: self.captureCircle.removeNode() if self.aoogahSfx: self.aoogahSfx.stop() if self.circleTrack: self.circleTrack.pause() del self.collNP del self.pointCollNode del self.capturePoint del self.captureCircle del self.aoogahSfx del self.circleTrack del self.circleTrackPlayRate del self.circleTrackDirection del self.team del self.neutralCapTexture del self.redCapTexture del self.blueCapTexture del self.defCapTexture self.removeNode() DistributedNode.delete(self) def getCircleScaleAnim(self, startScale, scale, duration = 1.5): return Sequence( LerpScaleInterval(self.captureCircle, startScale = startScale, scale = scale, duration = duration), Func(self.captureCircle.setColorScale, 0.976, 0, 0, 0.5), Wait(0.25), Func(self.captureCircle.setColorScale, 1, 1, 1, 0.5)) def startCircleAnim(self, direction, timestamp): timestamp = 0 # Begins the circle track in a certain direction. if self.circleTrack: self.circleTrack.pause() self.circleTrack = None self.circleTrackPlayRate = 1.0 self.circleTrackDirection = direction if self.circleTrackDirection == 3: self.captureCircle.hide() return self.circleTrack = Sequence(Func(self.captureCircle.show)) # Let's do the growing animation. if direction == 0: self.circleTrack = Sequence(Func(self.captureCircle.show), Func(self.captureCircle.setColorScale, 1, 1, 1, 0.5), LerpScaleInterval(self.captureCircle, startScale = 0.75, scale = 3.75, duration = 7.5), Func(self.captureCircle.setColorScale, 0.976, 0, 0, 0.5), Wait(0.25), Func(self.captureCircle.setColorScale, 1, 1, 1, 0.5), Wait(0.25), Func(self.captureCircle.hide)) self.circleTrack.start(timestamp) return elif direction == 1: # Let's do the shrinking animation. self.circleTrack = Sequence( Func(self.captureCircle.show), Func(self.captureCircle.setColorScale, 0.976, 0, 0, 0.5), Wait(0.25), Func(self.captureCircle.setColorScale, 1, 1, 1, 0.5)) self.circleTrack.append(self.getCircleScaleAnim(3.75, 3.25)) self.circleTrack.append(self.getCircleScaleAnim(3.25, 2.75)) self.circleTrack.append(self.getCircleScaleAnim(2.75, 2.25)) self.circleTrack.append(self.getCircleScaleAnim(2.25, 1.75)) self.circleTrack.append(self.getCircleScaleAnim(1.75, 1.25)) self.circleTrack.append(self.getCircleScaleAnim(1.25, 0.75)) elif direction == 2: # Let's do the reset animation when a new toon fails to capture it. self.circleTrack = Sequence() self.circleTrack.append(self.getCircleScaleAnim(self.captureCircle.getScale(), 0.75, 1.0)) self.circleTrack.append(Sequence(Wait(0.25), Func(self.captureCircle.hide))) self.circleTrack.start() return self.circleTrack.append(Sequence(Wait(0.25), Func(self.captureCircle.hide))) self.circleTrack.start() def handleContesters(self, contesters): if self.circleTrack: if self.circleTrackDirection == 1: self.circleTrack.pause() self.circleTrackPlayRate = self.circleTrackPlayRate + contesters self.circleTrack.setPlayRate(self.circleTrackPlayRate) self.circleTrack.resume() else: if contesters > 0 and not self.team: self.circleTrack.pause() else: self.circleTrack.resume() def updateStatus(self, status, avId): if avId != 0: avatar = base.cr.doId2do.get(avId) if status == 0: base.minigame.showAlert('The hill is being contested!') self.aoogahSfx.play() elif status == 1: base.minigame.showAlert('%s has captured the hill!' % avatar.getName()) elif status == 2: base.minigame.showAlert('The hill has been reset!') def announceGenerate(self): DistributedNode.announceGenerate(self) self.capturePoint = loader.loadModel('phase_4/models/props/capture_point.bam') self.capturePoint.setScale(2.5) self.capturePoint.reparentTo(self) self.captureCircle = loader.loadModel('phase_4/models/minigames/ice_game_score_circle.bam') self.captureCircle.setAlphaScale(0.5) self.captureCircle.setTransparency(TransparencyAttrib.MAlpha) self.captureCircle.reparentTo(self) self.captureCircle.setPos(self.capturePoint.getPos(render)) self.captureCircle.setX(self.captureCircle.getX() - 0.03) self.captureCircle.setY(self.captureCircle.getY() - 0.1) self.captureCircle.setZ(self.captureCircle.getZ() + 2.4) self.captureCircle.hide() self.captureCircle.setTextureOff(1) self.aoogahSfx = loader.loadSfx('phase_5/audio/sfx/AA_sound_aoogah.ogg') sphere = CollisionSphere(0, 0, 0, 4) sphere.setTangible(0) self.pointCollNode = CollisionNode(self.uniqueName('coll_node')) self.pointCollNode.addSolid(sphere) self.pointCollNode.setCollideMask(GGG.HILL_BITMASK) self.collNP = self.capturePoint.attachNewNode(self.pointCollNode) self.neutralCapTexture = 'phase_4/maps/neutral_capture_point.mat' self.redCapTexture = 'phase_4/maps/red_capture_point.mat' self.blueCapTexture = 'phase_4/maps/blue_capture_point.mat' self.defCapTexture = 'phase_4/maps/captured_capture_point.mat' self.reparentTo(render) def startListening(self): self.accept('enter' + self.uniqueName('coll_node'), self.requestEnter) self.accept('exit' + self.uniqueName('coll_node'), self.requestExit) def setCaptured(self, teamId): textureSection = self.capturePoint.find('**/capture_point') if (teamId - 2) in GGG.TeamNameById.values(): self.team = (teamId - 2) if self.team == GGG.RED: textureSection.setBSPMaterial(self.redCapTexture, 1) elif self.team == GGG.BLUE: textureSection.setBSPMaterial(self.blueCapTexture, 1) elif (teamId - 2) == -2: self.team = None textureSection.setBSPMaterial(self.neutralCapTexture, 1) elif (teamId - 2) == -1: self.team = None textureSection.setBSPMaterial(self.defCapTexture, 1) self.captureCircle.setTextureOff(1) def getCaptured(self): return self.team def requestEnter(self, entry): if hasattr(self, 'capturePoint') and self.capturePoint: self.sendUpdate('requestEnter') def requestExit(self, entry): if hasattr(self, 'capturePoint') and self.capturePoint: self.sendUpdate('requestExit')
def getSprayTrack(self, origin, target, scaleUp, hold, scaleDown, horizScale=1.0, vertScale=1.0): if self.sprayJoint.isEmpty(): self.build() self.origin = self.getSprayStartPos() base.localAvatar.stop(self.toonAnim) self.lastFrame = self.avatar.getCurrentFrame(self.toonAnim) track = Sequence() sprayProp = loader.loadModel(GagGlobals.SPRAY_MDL) sprayProp.setTwoSided(1) sprayScale = hidden.attachNewNode('spray-parent') sprayRot = hidden.attachNewNode('spray-rotate') sprayRot.setColor(GagGlobals.WATER_SPRAY_COLOR) sprayRot.setTransparency(1) collNode = CollisionNode('Collision') spraySphere = CollisionSphere(0, 0, 0, 1) spraySphere.setTangible(0) collNode.addSolid(spraySphere) collNode.setCollideMask(CIGlobals.WallBitmask) sprayNP = sprayRot.attachNewNode(collNode) sprayNP.setY(1) self.sprayNP = sprayNP event = CollisionHandlerEvent() event.set_in_pattern("%fn-into") event.set_out_pattern("%fn-out") base.cTrav.add_collider(sprayNP, event) self.avatar.acceptOnce(sprayNP.node().getName() + '-into', self.onCollision) def showSpray(sprayScale, sprayProp, origin, target): objects = [sprayRot, sprayScale, sprayProp] for item in objects: index = objects.index(item) if index == 0: item.reparentTo(self.sprayJoint) item.setPos(0, 0, 0) item.setHpr(self.sprayRotation) item.wrtReparentTo(render) else: item.reparentTo(objects[index - 1]) track.append(Func(showSpray, sprayScale, sprayProp, origin, target)) self.spray = sprayRot def calcTargetScale(): distance = Vec3(target - origin).length() yScale = distance / GagGlobals.SPRAY_LEN targetScale = Point3(yScale * horizScale, yScale, yScale * vertScale) return targetScale track.append( Parallel( LerpScaleInterval(sprayScale, scaleUp, calcTargetScale, startScale=GagGlobals.PNT3NEAR0), sprayNP.posInterval( 0.25, self.spray.getPos(render) + Point3(0, 50, 0), startPos=self.spray.getPos(render) + Point3(0, 5, 0)))) track.append(Wait(hold)) track.append(Func(self.handleMiss)) track.append(LerpScaleInterval(sprayScale, 0.75, GagGlobals.PNT3NEAR0)) def hideSpray(): lambda prop: prop.removeNode(), [sprayProp, sprayRot, sprayScale] track.append(Func(hideSpray)) track.append(Func(self.completeSquirt)) return track
class DistributedPartyCatchActivity(DistributedPartyActivity, DistributedPartyCatchActivityBase): notify = DirectNotifyGlobal.directNotify.newCategory( 'DistributedPartyCatchActivity') DropTaskName = 'dropSomething' DropObjectPlurals = { 'apple': TTLocalizer.PartyCatchActivityApples, 'orange': TTLocalizer.PartyCatchActivityOranges, 'pear': TTLocalizer.PartyCatchActivityPears, 'coconut': TTLocalizer.PartyCatchActivityCoconuts, 'watermelon': TTLocalizer.PartyCatchActivityWatermelons, 'pineapple': TTLocalizer.PartyCatchActivityPineapples, 'anvil': TTLocalizer.PartyCatchActivityAnvils } class Generation: def __init__(self, generation, startTime, startNetworkTime, numPlayers): self.generation = generation self.startTime = startTime self.startNetworkTime = startNetworkTime self.numPlayers = numPlayers self.hasBeenScheduled = False self.droppedObjNames = [] self.dropSchedule = [] self.numItemsDropped = 0 self.droppedObjCaught = {} def __init__(self, cr): DistributedPartyActivity.__init__( self, cr, PartyGlobals.ActivityIds.PartyCatch, PartyGlobals.ActivityTypes.HostInitiated, wantRewardGui=True) self.setUsesSmoothing() self.setUsesLookAround() self._sNumGen = SerialNumGen() def getTitle(self): return TTLocalizer.PartyCatchActivityTitle def getInstructions(self): return TTLocalizer.PartyCatchActivityInstructions % { 'badThing': self.DropObjectPlurals['anvil'] } def generate(self): DistributedPartyActivity.generate(self) self.notify.info('localAvatar doId: %s' % base.localAvatar.doId) self.notify.info('generate()') self._generateFrame = globalClock.getFrameCount() self._id2gen = {} self._orderedGenerations = [] self._orderedGenerationIndex = None rng = RandomNumGen(self.doId) self._generationSeedBase = rng.randrange(1000) self._lastDropTime = 0.0 return def getCurGeneration(self): if self._orderedGenerationIndex is None: return return self._orderedGenerations[self._orderedGenerationIndex] def _addGeneration(self, generation, startTime, startNetworkTime, numPlayers): self._id2gen[generation] = self.Generation(generation, startTime, startNetworkTime, numPlayers) i = 0 while 1: if i >= len(self._orderedGenerations): break gen = self._orderedGenerations[i] startNetT = self._id2gen[gen].startTime genId = self._id2gen[gen].generation if startNetT > startNetworkTime: break if startNetT == startNetworkTime and genId > generation: break i += 1 self._orderedGenerations = self._orderedGenerations[:i] + [ generation ] + self._orderedGenerations[i:] if self._orderedGenerationIndex is not None: if self._orderedGenerationIndex >= i: self._orderedGenerationIndex += 1 def _removeGeneration(self, generation): del self._id2gen[generation] i = self._orderedGenerations.index(generation) self._orderedGenerations = self._orderedGenerations[: i] + self._orderedGenerations[ i + 1:] if self._orderedGenerationIndex is not None: if len(self._orderedGenerations): if self._orderedGenerationIndex >= i: self._orderedGenerationIndex -= 1 else: self._orderedGenerationIndex = None return def announceGenerate(self): self.notify.info('announceGenerate()') self.catchTreeZoneEvent = 'fence_floor' DistributedPartyActivity.announceGenerate(self) def load(self, loadModels=1, arenaModel='partyCatchTree'): self.notify.info('load()') DistributedPartyCatchActivity.notify.debug('PartyCatch: load') self.activityFSM = CatchActivityFSM(self) if __dev__: for o in range(3): print({ 0: 'SPOTS PER PLAYER', 1: 'DROPS PER MINUTE PER SPOT DURING NORMAL DROP PERIOD', 2: 'DROPS PER MINUTE PER PLAYER DURING NORMAL DROP PERIOD' }[o]) for i in range(1, self.FallRateCap_Players + 10): self.defineConstants(forceNumPlayers=i) numDropLocations = self.DropRows * self.DropColumns numDropsPerMin = 60.0 / self.DropPeriod if o == 0: spotsPerPlayer = numDropLocations / float(i) print('%2d PLAYERS: %s' % (i, spotsPerPlayer)) elif o == 1: numDropsPerMinPerSpot = numDropsPerMin / numDropLocations print('%2d PLAYERS: %s' % (i, numDropsPerMinPerSpot)) elif i > 0: numDropsPerMinPerPlayer = numDropsPerMin / i print('%2d PLAYERS: %s' % (i, numDropsPerMinPerPlayer)) self.defineConstants() self.treesAndFence = loader.loadModel('phase_13/models/parties/%s' % arenaModel) self.treesAndFence.setScale(0.9) self.treesAndFence.find('**/fence_floor').setPos(0.0, 0.0, 0.1) self.treesAndFence.reparentTo(self.root) ground = self.treesAndFence.find('**/groundPlane') ground.setBin('ground', 1) DistributedPartyActivity.load(self) exitText = TextNode('PartyCatchExitText') exitText.setCardAsMargin(0.1, 0.1, 0.1, 0.1) exitText.setCardDecal(True) exitText.setCardColor(1.0, 1.0, 1.0, 0.0) exitText.setText(TTLocalizer.PartyCatchActivityExit) exitText.setTextColor(0.0, 8.0, 0.0, 0.9) exitText.setAlign(exitText.ACenter) exitText.setFont(ToontownGlobals.getBuildingNametagFont()) exitText.setShadowColor(0, 0, 0, 1) exitText.setBin('fixed') if TTLocalizer.BuildingNametagShadow: exitText.setShadow(*TTLocalizer.BuildingNametagShadow) exitTextLoc = self.treesAndFence.find('**/loc_exitSignText') exitTextNp = exitTextLoc.attachNewNode(exitText) exitTextNp.setDepthWrite(0) exitTextNp.setScale(4) exitTextNp.setZ(-.5) self.sign.reparentTo(self.treesAndFence.find('**/loc_eventSign')) self.sign.wrtReparentTo(self.root) self.avatarNodePath = NodePath('PartyCatchAvatarNodePath') self.avatarNodePath.reparentTo(self.root) self._avatarNodePathParentToken = 3 base.cr.parentMgr.registerParent(self._avatarNodePathParentToken, self.avatarNodePath) self.toonSDs = {} self.dropShadow = loader.loadModelOnce( 'phase_3/models/props/drop_shadow') self.dropObjModels = {} if loadModels: self.__loadDropModels() self.sndGoodCatch = base.loader.loadSfx( 'phase_4/audio/sfx/SZ_DD_treasure.ogg') self.sndOof = base.loader.loadSfx( 'phase_4/audio/sfx/MG_cannon_hit_dirt.ogg') self.sndAnvilLand = base.loader.loadSfx( 'phase_4/audio/sfx/AA_drop_anvil_miss.ogg') self.sndPerfect = base.loader.loadSfx( 'phase_4/audio/sfx/ring_perfect.ogg') self.__textGen = TextNode('partyCatchActivity') self.__textGen.setFont(ToontownGlobals.getSignFont()) self.__textGen.setAlign(TextNode.ACenter) self.activityFSM.request('Idle') def __loadDropModels(self): for objType in PartyGlobals.DropObjectTypes: model = loader.loadModel(objType.modelPath) self.dropObjModels[objType.name] = model modelScales = { 'apple': 0.7, 'orange': 0.7, 'pear': 0.5, 'coconut': 0.7, 'watermelon': 0.6, 'pineapple': 0.45 } if objType.name in modelScales: model.setScale(modelScales[objType.name]) if objType == PartyGlobals.Name2DropObjectType['pear']: model.setZ(-.6) if objType == PartyGlobals.Name2DropObjectType['coconut']: model.setP(180) if objType == PartyGlobals.Name2DropObjectType['watermelon']: model.setH(135) model.setZ(-.5) if objType == PartyGlobals.Name2DropObjectType['pineapple']: model.setZ(-1.7) if objType == PartyGlobals.Name2DropObjectType['anvil']: model.setZ(-self.ObjRadius) model.flattenStrong() def unload(self): DistributedPartyCatchActivity.notify.debug('unload') self.finishAllDropIntervals() self.destroyOrthoWalk() DistributedPartyActivity.unload(self) self.stopDropTask() del self.activityFSM del self.__textGen for avId in list(self.toonSDs.keys()): if avId in self.toonSDs: toonSD = self.toonSDs[avId] toonSD.unload() del self.toonSDs self.treesAndFence.removeNode() del self.treesAndFence self.dropShadow.removeNode() del self.dropShadow base.cr.parentMgr.unregisterParent(self._avatarNodePathParentToken) for model in list(self.dropObjModels.values()): model.removeNode() del self.dropObjModels del self.sndGoodCatch del self.sndOof del self.sndAnvilLand del self.sndPerfect def setStartTimestamp(self, timestamp32): self.notify.info('setStartTimestamp(%s)' % (timestamp32, )) self._startTimestamp = globalClockDelta.networkToLocalTime(timestamp32, bits=32) def getCurrentCatchActivityTime(self): return globalClock.getFrameTime() - self._startTimestamp def getObjModel(self, objName): return self.dropObjModels[objName].copyTo(hidden) def joinRequestDenied(self, reason): DistributedPartyActivity.joinRequestDenied(self, reason) base.cr.playGame.getPlace().fsm.request('walk') def handleToonJoined(self, toonId): if toonId not in self.toonSDs: toonSD = PartyCatchActivityToonSD(toonId, self) self.toonSDs[toonId] = toonSD toonSD.load() self.notify.debug('handleToonJoined : currentState = %s' % self.activityFSM.state) self.cr.doId2do[toonId].useLOD(500) if self.activityFSM.state == 'Active': if toonId in self.toonSDs: self.toonSDs[toonId].enter() if base.localAvatar.doId == toonId: base.localAvatar.b_setParent(self._avatarNodePathParentToken) self.putLocalAvatarInActivity() if toonId in self.toonSDs: self.toonSDs[toonId].fsm.request('rules') def handleToonExited(self, toonId): self.notify.debug('handleToonExited( toonId=%s )' % toonId) if toonId in self.cr.doId2do: self.cr.doId2do[toonId].resetLOD() if toonId in self.toonSDs: self.toonSDs[toonId].fsm.request('notPlaying') self.toonSDs[toonId].exit() self.toonSDs[toonId].unload() del self.toonSDs[toonId] if base.localAvatar.doId == toonId: base.localAvatar.b_setParent(ToontownGlobals.SPRender) def takeLocalAvatarOutOfActivity(self): self.notify.debug('localToon has left the circle') camera.reparentTo(base.localAvatar) base.localAvatar.startUpdateSmartCamera() base.localAvatar.enableSmartCameraViews() base.localAvatar.setCameraPositionByIndex(base.localAvatar.cameraIndex) DistributedSmoothNode.activateSmoothing(1, 0) def _enableCollisions(self): DistributedPartyActivity._enableCollisions(self) self._enteredTree = False self.accept('enter' + self.catchTreeZoneEvent, self._toonMayHaveEnteredTree) self.accept('again' + self.catchTreeZoneEvent, self._toonMayHaveEnteredTree) self.accept('exit' + self.catchTreeZoneEvent, self._toonExitedTree) self.accept(DistributedPartyCannonActivity.LOCAL_TOON_LANDED_EVENT, self._handleCannonLanded) def _disableCollisions(self): self.ignore(DistributedPartyCannonActivity.LOCAL_TOON_LANDED_EVENT) self.ignore('enter' + self.catchTreeZoneEvent) self.ignore('again' + self.catchTreeZoneEvent) self.ignore('exit' + self.catchTreeZoneEvent) DistributedPartyActivity._disableCollisions(self) def _handleCannonLanded(self): x = base.localAvatar.getX() y = base.localAvatar.getY() if x > self.x - self.StageHalfWidth and x < self.x + self.StageHalfWidth and y > self.y - self.StageHalfHeight and y < self.y + self.StageHalfHeight: self._toonEnteredTree(None) return def _toonMayHaveEnteredTree(self, collEntry): if self._enteredTree: return if base.localAvatar.controlManager.currentControls.getIsAirborne(): return self._toonEnteredTree(collEntry) def _toonEnteredTree(self, collEntry): self.notify.debug('_toonEnteredTree : avid = %s' % base.localAvatar.doId) self.notify.debug('_toonEnteredTree : currentState = %s' % self.activityFSM.state) if self.isLocalToonInActivity(): return if self.activityFSM.state == 'Active': base.cr.playGame.getPlace().fsm.request('activity') self.d_toonJoinRequest() elif self.activityFSM.state == 'Idle': base.cr.playGame.getPlace().fsm.request('activity') self.d_toonJoinRequest() self._enteredTree = True def _toonExitedTree(self, collEntry): self.notify.debug('_toonExitedTree : avid = %s' % base.localAvatar.doId) self._enteredTree = False if hasattr( base.cr.playGame.getPlace(), 'fsm' ) and self.activityFSM.state == 'Active' and self.isLocalToonInActivity( ): if base.localAvatar.doId in self.toonSDs: self.takeLocalAvatarOutOfActivity() self.toonSDs[base.localAvatar.doId].fsm.request('notPlaying') self.d_toonExitDemand() def setToonsPlaying(self, toonIds): self.notify.info('setToonsPlaying(%s)' % (toonIds, )) DistributedPartyActivity.setToonsPlaying(self, toonIds) if self.isLocalToonInActivity( ) and base.localAvatar.doId not in toonIds: if base.localAvatar.doId in self.toonSDs: self.takeLocalAvatarOutOfActivity() self.toonSDs[base.localAvatar.doId].fsm.request('notPlaying') def __genText(self, text): self.__textGen.setText(text) return self.__textGen.generate() def getNumPlayers(self): return len(self.toonIds) def defineConstants(self, forceNumPlayers=None): DistributedPartyCatchActivity.notify.debug('defineConstants') self.ShowObjSpheres = 0 self.ShowToonSpheres = 0 self.useGravity = True self.trickShadows = True if forceNumPlayers is None: numPlayers = self.getNumPlayers() else: numPlayers = forceNumPlayers self.calcDifficultyConstants(numPlayers) DistributedPartyCatchActivity.notify.debug('ToonSpeed: %s' % self.ToonSpeed) DistributedPartyCatchActivity.notify.debug('total drops: %s' % self.totalDrops) DistributedPartyCatchActivity.notify.debug('numFruits: %s' % self.numFruits) DistributedPartyCatchActivity.notify.debug('numAnvils: %s' % self.numAnvils) self.ObjRadius = 1.0 dropRegionTable = PartyRegionDropPlacer.getDropRegionTable(numPlayers) self.DropRows, self.DropColumns = len(dropRegionTable), len( dropRegionTable[0]) for objType in PartyGlobals.DropObjectTypes: DistributedPartyCatchActivity.notify.debug('*** Object Type: %s' % objType.name) objType.onscreenDuration = objType.onscreenDurMult * self.BaselineOnscreenDropDuration DistributedPartyCatchActivity.notify.debug( 'onscreenDuration=%s' % objType.onscreenDuration) v_0 = 0.0 t = objType.onscreenDuration x_0 = self.MinOffscreenHeight x = 0.0 g = 2.0 * (x - x_0 - v_0 * t) / (t * t) DistributedPartyCatchActivity.notify.debug('gravity=%s' % g) objType.trajectory = Trajectory(0, Vec3(0, 0, x_0), Vec3(0, 0, v_0), gravMult=abs(g / Trajectory.gravity)) objType.fallDuration = objType.onscreenDuration + self.OffscreenTime return def grid2world(self, column, row): x = column / float(self.DropColumns - 1) y = row / float(self.DropRows - 1) x = x * 2.0 - 1.0 y = y * 2.0 - 1.0 x *= self.StageHalfWidth y *= self.StageHalfHeight return (x, y) def showPosts(self): self.hidePosts() self.posts = [Toon.Toon(), Toon.Toon(), Toon.Toon(), Toon.Toon()] for i in range(len(self.posts)): tree = self.posts[i] tree.reparentTo(render) x = self.StageHalfWidth y = self.StageHalfHeight if i > 1: x = -x if i % 2: y = -y tree.setPos(x + self.x, y + self.y, 0) def hidePosts(self): if hasattr(self, 'posts'): for tree in self.posts: tree.removeNode() del self.posts def showDropGrid(self): self.hideDropGrid() self.dropMarkers = [] for row in range(self.DropRows): self.dropMarkers.append([]) rowList = self.dropMarkers[row] for column in range(self.DropColumns): toon = Toon.Toon() toon.setDNA(base.localAvatar.getStyle()) toon.reparentTo(self.root) toon.setScale(1.0 / 3) x, y = self.grid2world(column, row) toon.setPos(x, y, 0) rowList.append(toon) def hideDropGrid(self): if hasattr(self, 'dropMarkers'): for row in self.dropMarkers: for marker in row: marker.removeNode() del self.dropMarkers def handleToonDisabled(self, avId): DistributedPartyCatchActivity.notify.debug('handleToonDisabled') DistributedPartyCatchActivity.notify.debug('avatar ' + str(avId) + ' disabled') if avId in self.toonSDs: self.toonSDs[avId].exit(unexpectedExit=True) del self.toonSDs[avId] def turnOffSmoothingOnGuests(self): pass def setState(self, newState, timestamp): self.notify.info('setState(%s, %s)' % (newState, timestamp)) DistributedPartyCatchActivity.notify.debug( 'setState( newState=%s, ... )' % newState) DistributedPartyActivity.setState(self, newState, timestamp) self.activityFSM.request(newState) if newState == 'Active': if base.localAvatar.doId != self.party.partyInfo.hostId: if globalClock.getFrameCount() > self._generateFrame: if base.localAvatar.getX( ) > self.x - self.StageHalfWidth and base.localAvatar.getX( ) < self.x + self.StageHalfWidth and base.localAvatar.getY( ) > self.y - self.StageHalfHeight and base.localAvatar.getY( ) < self.y + self.StageHalfHeight: self._toonEnteredTree(None) return def putLocalAvatarInActivity(self): if base.cr.playGame.getPlace() and hasattr(base.cr.playGame.getPlace(), 'fsm'): base.cr.playGame.getPlace().fsm.request('activity', [False]) else: self.notify.info( "Avoided crash: toontown.parties.DistributedPartyCatchActivity:632, toontown.parties.DistributedPartyCatchActivity:1198, toontown.parties.activityFSMMixins:49, direct.fsm.FSM:423, AttributeError: 'NoneType' object has no attribute 'fsm'" ) base.localAvatar.stopUpdateSmartCamera() camera.reparentTo(self.treesAndFence) camera.setPosHpr(0.0, -63.0, 30.0, 0.0, -20.0, 0.0) if not hasattr(self, 'ltLegsCollNode'): self.createCatchCollisions() def createCatchCollisions(self): radius = 0.7 handler = CollisionHandlerEvent() handler.setInPattern('ltCatch%in') self.ltLegsCollNode = CollisionNode('catchLegsCollNode') self.ltLegsCollNode.setCollideMask(PartyGlobals.CatchActivityBitmask) self.ltHeadCollNode = CollisionNode('catchHeadCollNode') self.ltHeadCollNode.setCollideMask(PartyGlobals.CatchActivityBitmask) self.ltLHandCollNode = CollisionNode('catchLHandCollNode') self.ltLHandCollNode.setCollideMask(PartyGlobals.CatchActivityBitmask) self.ltRHandCollNode = CollisionNode('catchRHandCollNode') self.ltRHandCollNode.setCollideMask(PartyGlobals.CatchActivityBitmask) legsCollNodepath = base.localAvatar.attachNewNode(self.ltLegsCollNode) legsCollNodepath.hide() head = base.localAvatar.getHeadParts().getPath(2) headCollNodepath = head.attachNewNode(self.ltHeadCollNode) headCollNodepath.hide() lHand = base.localAvatar.getLeftHands()[0] lHandCollNodepath = lHand.attachNewNode(self.ltLHandCollNode) lHandCollNodepath.hide() rHand = base.localAvatar.getRightHands()[0] rHandCollNodepath = rHand.attachNewNode(self.ltRHandCollNode) rHandCollNodepath.hide() base.localAvatar.cTrav.addCollider(legsCollNodepath, handler) base.localAvatar.cTrav.addCollider(headCollNodepath, handler) base.localAvatar.cTrav.addCollider(lHandCollNodepath, handler) base.localAvatar.cTrav.addCollider(lHandCollNodepath, handler) if self.ShowToonSpheres: legsCollNodepath.show() headCollNodepath.show() lHandCollNodepath.show() rHandCollNodepath.show() self.ltLegsCollNode.addSolid(CollisionSphere(0, 0, radius, radius)) self.ltHeadCollNode.addSolid(CollisionSphere(0, 0, 0, radius)) self.ltLHandCollNode.addSolid( CollisionSphere(0, 0, 0, 2 * radius / 3.0)) self.ltRHandCollNode.addSolid( CollisionSphere(0, 0, 0, 2 * radius / 3.0)) self.toonCollNodes = [ legsCollNodepath, headCollNodepath, lHandCollNodepath, rHandCollNodepath ] def destroyCatchCollisions(self): if not hasattr(self, 'ltLegsCollNode'): return for collNode in self.toonCollNodes: while collNode.node().getNumSolids(): collNode.node().removeSolid(0) base.localAvatar.cTrav.removeCollider(collNode) del self.toonCollNodes del self.ltLegsCollNode del self.ltHeadCollNode del self.ltLHandCollNode del self.ltRHandCollNode def timerExpired(self): pass def __handleCatch(self, generation, objNum): DistributedPartyCatchActivity.notify.debug('catch: %s' % [generation, objNum]) if base.localAvatar.doId not in self.toonIds: return self.showCatch(base.localAvatar.doId, generation, objNum) objName = self._id2gen[generation].droppedObjNames[objNum] objTypeId = PartyGlobals.Name2DOTypeId[objName] self.sendUpdate('claimCatch', [generation, objNum, objTypeId]) self.finishDropInterval(generation, objNum) def showCatch(self, avId, generation, objNum): if avId not in self.toonSDs: return isLocal = avId == base.localAvatar.doId if generation not in self._id2gen: return if not self._id2gen[generation].hasBeenScheduled: return objName = self._id2gen[generation].droppedObjNames[objNum] objType = PartyGlobals.Name2DropObjectType[objName] if objType.good: if objNum not in self._id2gen[generation].droppedObjCaught: if isLocal: base.playSfx(self.sndGoodCatch) fruit = self.getObjModel(objName) toon = self.getAvatar(avId) rHand = toon.getRightHands()[1] self.toonSDs[avId].eatFruit(fruit, rHand) else: self.toonSDs[avId].fsm.request('fallForward') self._id2gen[generation].droppedObjCaught[objNum] = 1 def setObjectCaught(self, avId, generation, objNum): self.notify.info('setObjectCaught(%s, %s, %s)' % (avId, generation, objNum)) if self.activityFSM.state != 'Active': DistributedPartyCatchActivity.notify.warning( 'ignoring msg: object %s caught by %s' % (objNum, avId)) return isLocal = avId == base.localAvatar.doId if not isLocal: DistributedPartyCatchActivity.notify.debug( 'AI: avatar %s caught %s' % (avId, objNum)) self.finishDropInterval(generation, objNum) self.showCatch(avId, generation, objNum) self._scheduleGenerations() gen = self._id2gen[generation] if gen.hasBeenScheduled: objName = gen.droppedObjNames[objNum] if PartyGlobals.Name2DropObjectType[objName].good: if hasattr(self, 'fruitsCaught'): self.fruitsCaught += 1 def finishDropInterval(self, generation, objNum): if hasattr(self, 'dropIntervals'): if (generation, objNum) in self.dropIntervals: self.dropIntervals[generation, objNum].finish() def finishAllDropIntervals(self): if hasattr(self, 'dropIntervals'): for dropInterval in list(self.dropIntervals.values()): dropInterval.finish() def setGenerations(self, generations): self.notify.info('setGenerations(%s)' % (generations, )) gen2t = {} gen2nt = {} gen2np = {} for id, timestamp32, numPlayers in generations: gen2t[id] = globalClockDelta.networkToLocalTime( timestamp32, bits=32) - self._startTimestamp gen2nt[id] = timestamp32 gen2np[id] = numPlayers ids = list(self._id2gen.keys()) for id in ids: if id not in gen2t: self._removeGeneration(id) for id in gen2t: if id not in self._id2gen: self._addGeneration(id, gen2t[id], gen2nt[id], gen2np[id]) def scheduleDrops(self, genId=None): if genId is None: genId = self.getCurGeneration() gen = self._id2gen[genId] if gen.hasBeenScheduled: return fruitIndex = int((gen.startTime + 0.5 * self.DropPeriod) / PartyGlobals.CatchActivityDuration) fruitNames = [ 'apple', 'orange', 'pear', 'coconut', 'watermelon', 'pineapple' ] fruitName = fruitNames[fruitIndex % len(fruitNames)] rng = RandomNumGen(genId + self._generationSeedBase) gen.droppedObjNames = [fruitName ] * self.numFruits + ['anvil'] * self.numAnvils rng.shuffle(gen.droppedObjNames) dropPlacer = PartyRegionDropPlacer(self, gen.numPlayers, genId, gen.droppedObjNames, startTime=gen.startTime) gen.numItemsDropped = 0 tIndex = gen.startTime % PartyGlobals.CatchActivityDuration tPercent = float(tIndex) / PartyGlobals.CatchActivityDuration gen.numItemsDropped += dropPlacer.skipPercent(tPercent) while not dropPlacer.doneDropping(continuous=True): nextDrop = dropPlacer.getNextDrop() gen.dropSchedule.append(nextDrop) gen.hasBeenScheduled = True return def startDropTask(self): taskMgr.add(self.dropTask, self.DropTaskName) def stopDropTask(self): taskMgr.remove(self.DropTaskName) def _scheduleGenerations(self): curT = self.getCurrentCatchActivityTime() genIndex = self._orderedGenerationIndex newGenIndex = genIndex while genIndex is None or genIndex < len(self._orderedGenerations) - 1: if genIndex is None: nextGenIndex = 0 else: nextGenIndex = genIndex + 1 nextGenId = self._orderedGenerations[nextGenIndex] nextGen = self._id2gen[nextGenId] startT = nextGen.startTime if curT >= startT: newGenIndex = nextGenIndex if not nextGen.hasBeenScheduled: self.defineConstants(forceNumPlayers=nextGen.numPlayers) self.scheduleDrops( genId=self._orderedGenerations[nextGenIndex]) genIndex = nextGenIndex self._orderedGenerationIndex = newGenIndex return def dropTask(self, task): self._scheduleGenerations() curT = self.getCurrentCatchActivityTime() if self._orderedGenerationIndex is not None: i = self._orderedGenerationIndex genIndex = self._orderedGenerations[i] gen = self._id2gen[genIndex] while len(gen.dropSchedule) > 0 and gen.dropSchedule[0][0] < curT: drop = gen.dropSchedule[0] gen.dropSchedule = gen.dropSchedule[1:] dropTime, objName, dropCoords = drop objNum = gen.numItemsDropped x, y = self.grid2world(*dropCoords) dropIval = self.getDropIval(x, y, objName, genIndex, objNum) def cleanup(generation, objNum, self=self): del self.dropIntervals[generation, objNum] dropIval.append(Func(Functor(cleanup, genIndex, objNum))) self.dropIntervals[genIndex, objNum] = dropIval gen.numItemsDropped += 1 dropIval.start(curT - dropTime) self._lastDropTime = dropTime return Task.cont def getDropIval(self, x, y, dropObjName, generation, num): objType = PartyGlobals.Name2DropObjectType[dropObjName] id = (generation, num) dropNode = hidden.attachNewNode('catchDropNode%s' % (id, )) dropNode.setPos(x, y, 0) shadow = self.dropShadow.copyTo(dropNode) shadow.setZ(PartyGlobals.CatchDropShadowHeight) shadow.setColor(1, 1, 1, 1) object = self.getObjModel(dropObjName) object.reparentTo(hidden) if dropObjName in ['watermelon', 'anvil']: objH = object.getH() absDelta = {'watermelon': 12, 'anvil': 15}[dropObjName] delta = (self.randomNumGen.random() * 2.0 - 1.0) * absDelta newH = objH + delta else: newH = self.randomNumGen.random() * 360.0 object.setH(newH) sphereName = 'FallObj%s' % (id, ) radius = self.ObjRadius if objType.good: radius *= lerp(1.0, 1.3, 0.5) collSphere = CollisionSphere(0, 0, 0, radius) collSphere.setTangible(0) collNode = CollisionNode(sphereName) collNode.setCollideMask(PartyGlobals.CatchActivityBitmask) collNode.addSolid(collSphere) collNodePath = object.attachNewNode(collNode) collNodePath.hide() if self.ShowObjSpheres: collNodePath.show() catchEventName = 'ltCatch' + sphereName def eatCollEntry(forward, collEntry): forward() self.accept( catchEventName, Functor(eatCollEntry, Functor(self.__handleCatch, id[0], id[1]))) def cleanup(self=self, dropNode=dropNode, id=id, event=catchEventName): self.ignore(event) dropNode.removeNode() duration = objType.fallDuration onscreenDuration = objType.onscreenDuration targetShadowScale = 0.3 if self.trickShadows: intermedScale = targetShadowScale * (self.OffscreenTime / self.BaselineDropDuration) shadowScaleIval = Sequence( LerpScaleInterval(shadow, self.OffscreenTime, intermedScale, startScale=0)) shadowScaleIval.append( LerpScaleInterval(shadow, duration - self.OffscreenTime, targetShadowScale, startScale=intermedScale)) else: shadowScaleIval = LerpScaleInterval(shadow, duration, targetShadowScale, startScale=0) targetShadowAlpha = 0.4 shadowAlphaIval = LerpColorScaleInterval( shadow, self.OffscreenTime, Point4(1, 1, 1, targetShadowAlpha), startColorScale=Point4(1, 1, 1, 0)) shadowIval = Parallel(shadowScaleIval, shadowAlphaIval) if self.useGravity: def setObjPos(t, objType=objType, object=object): z = objType.trajectory.calcZ(t) object.setZ(z) setObjPos(0) dropIval = LerpFunctionInterval(setObjPos, fromData=0, toData=onscreenDuration, duration=onscreenDuration) else: startPos = Point3(0, 0, self.MinOffscreenHeight) object.setPos(startPos) dropIval = LerpPosInterval(object, onscreenDuration, Point3(0, 0, 0), startPos=startPos, blendType='easeIn') ival = Sequence(Func(Functor(dropNode.reparentTo, self.root)), Parallel( Sequence( WaitInterval(self.OffscreenTime), Func(Functor(object.reparentTo, dropNode)), dropIval), shadowIval), Func(cleanup), name='drop%s' % (id, )) if objType == PartyGlobals.Name2DropObjectType['anvil']: ival.append(Func(self.playAnvil)) return ival def playAnvil(self): if base.localAvatar.doId in self.toonIds: base.playSfx(self.sndAnvilLand) def initOrthoWalk(self): DistributedPartyCatchActivity.notify.debug('startOrthoWalk') def doCollisions(oldPos, newPos, self=self): x = bound(newPos[0], self.StageHalfWidth, -self.StageHalfWidth) y = bound(newPos[1], self.StageHalfHeight, -self.StageHalfHeight) newPos.setX(x) newPos.setY(y) return newPos orthoDrive = OrthoDrive(self.ToonSpeed, instantTurn=True) self.orthoWalk = OrthoWalk(orthoDrive, broadcast=True) def destroyOrthoWalk(self): DistributedPartyCatchActivity.notify.debug('destroyOrthoWalk') if hasattr(self, 'orthoWalk'): self.orthoWalk.stop() self.orthoWalk.destroy() del self.orthoWalk def startIdle(self): DistributedPartyCatchActivity.notify.debug('startIdle') def finishIdle(self): DistributedPartyCatchActivity.notify.debug('finishIdle') def startActive(self): DistributedPartyCatchActivity.notify.debug('startActive') for avId in self.toonIds: if avId in self.toonSDs: toonSD = self.toonSDs[avId] toonSD.enter() toonSD.fsm.request('normal') self.fruitsCaught = 0 self.dropIntervals = {} self.startDropTask() if base.localAvatar.doId in self.toonIds: self.putLocalAvatarInActivity() def finishActive(self): DistributedPartyCatchActivity.notify.debug('finishActive') self.stopDropTask() if hasattr(self, 'finishIval'): self.finishIval.pause() del self.finishIval if base.localAvatar.doId in self.toonIds: self.takeLocalAvatarOutOfActivity() for ival in list(self.dropIntervals.values()): ival.finish() del self.dropIntervals def startConclusion(self): DistributedPartyCatchActivity.notify.debug('startConclusion') for avId in self.toonIds: if avId in self.toonSDs: toonSD = self.toonSDs[avId] toonSD.fsm.request('notPlaying') self.destroyCatchCollisions() if base.localAvatar.doId not in self.toonIds: return else: self.localToonExiting() if self.fruitsCaught >= self.numFruits: finishText = TTLocalizer.PartyCatchActivityFinishPerfect else: finishText = TTLocalizer.PartyCatchActivityFinish perfectTextSubnode = hidden.attachNewNode(self.__genText(finishText)) perfectText = hidden.attachNewNode('perfectText') perfectTextSubnode.reparentTo(perfectText) frame = self.__textGen.getCardActual() offsetY = -abs(frame[2] + frame[3]) / 2.0 perfectTextSubnode.setPos(0, 0, offsetY) perfectText.setColor(1, 0.1, 0.1, 1) def fadeFunc(t, text=perfectText): text.setColorScale(1, 1, 1, t) def destroyText(text=perfectText): text.removeNode() textTrack = Sequence( Func(perfectText.reparentTo, aspect2d), Parallel( LerpScaleInterval(perfectText, duration=0.5, scale=0.3, startScale=0.0), LerpFunctionInterval(fadeFunc, fromData=0.0, toData=1.0, duration=0.5)), Wait(2.0), Parallel( LerpScaleInterval(perfectText, duration=0.5, scale=1.0), LerpFunctionInterval(fadeFunc, fromData=1.0, toData=0.0, duration=0.5, blendType='easeIn')), Func(destroyText), WaitInterval(0.5)) soundTrack = SoundInterval(self.sndPerfect) self.finishIval = Parallel(textTrack, soundTrack) self.finishIval.start() def finishConclusion(self): DistributedPartyCatchActivity.notify.debug('finishConclusion') if base.localAvatar.doId in self.toonIds: self.takeLocalAvatarOutOfActivity() base.cr.playGame.getPlace().fsm.request('walk') def showJellybeanReward(self, earnedAmount, jarAmount, message): if earnedAmount > 0: DistributedPartyActivity.showJellybeanReward( self, earnedAmount, jarAmount, message) else: base.cr.playGame.getPlace().fsm.request('walk')
class DistributedToonFestTrampolineActivity(DistributedPartyActivity): notify = DirectNotifyGlobal.directNotify.newCategory( 'DistributedToonFestTrampolineActivity') def __init__(self, cr, doJellyBeans=True, doTricks=False, texture=None): DistributedToonFestTrampolineActivity.notify.debug('__init__') DistributedPartyActivity.__init__( self, cr, PartyGlobals.ActivityIds.PartyTrampoline, PartyGlobals.ActivityTypes.GuestInitiated, wantLever=False, wantRewardGui=True) self.doJellyBeans = doJellyBeans self.doTricks = doTricks self.texture = texture self.toon = None self.trampHeight = 3.6 self.trampK = 400.0 self.normalTrampB = 2.5 self.leavingTrampB = 8.0 self.trampB = self.normalTrampB self.g = -32.0 self.jumpBoost = 330.0 self.beginningBoost = 500.0 self.beginningBoostThreshold = self.trampHeight + 1.5 self.earlyJumpThreshold = 75.0 self.boingThreshold = 300.0 self.turnFactor = 120.0 self.stepDT = 0.001 self.targetCameraPos = Point3(0.0, 40.0, 10.0) self.cameraSpeed = 2.0 self.hopOffPos = Point3(16.0, 0.0, 0.0) self.indicatorFactor = 0.0095 self.dropShadowCutoff = 15.0 self.minHeightForText = 15.0 self.heightTextOffset = -0.065 self.beanOffset = 0.5 self.guiBeanOffset = -0.02 self.jumpTextShown = False self.toonJumped = False self.turnLeft = False self.turnRight = False self.leavingTrampoline = False self.toonVelocity = 0.0 self.topHeight = 0.0 self.lastPeak = 0.0 self.beginRoundInterval = None self.hopOnAnim = None self.hopOffAnim = None self.flashTextInterval = None self.numJellyBeans = PartyGlobals.TrampolineNumJellyBeans self.jellyBeanBonus = PartyGlobals.TrampolineJellyBeanBonus self.jellyBeanStartHeight = 20.0 self.jellyBeanStopHeight = 90.0 self.jellyBeanColors = [ VBase4(1.0, 0.5, 0.5, 1.0), VBase4(0.5, 1.0, 0.5, 1.0), VBase4(0.5, 1.0, 1.0, 1.0), VBase4(1.0, 1.0, 0.4, 1.0), VBase4(0.4, 0.4, 1.0, 1.0), VBase4(1.0, 0.5, 1.0, 1.0) ] delta = (self.jellyBeanStopHeight - self.jellyBeanStartHeight) / (self.numJellyBeans - 1) self.jellyBeanPositions = [ self.jellyBeanStartHeight + n * delta for n in range(self.numJellyBeans) ] self.doSimulateStep = False return def load(self): DistributedToonFestTrampolineActivity.notify.debug('load') DistributedPartyActivity.load(self) self.loadModels() self.loadCollision() self.loadGUI() self.loadSounds() self.loadIntervals() self.activityFSM = TrampolineActivityFSM(self) self.activityFSM.request('Idle') self.animFSM = TrampolineAnimFSM(self) self.setBestHeightInfo('', 0) def loadModels(self): self.tramp = self.root.attachNewNode(self.uniqueName('tramp')) self.trampActor = Actor( 'phase_13/models/parties/trampoline_model', {'emptyAnim': 'phase_13/models/parties/trampoline_anim'}) self.trampActor.reparentTo(self.tramp) if self.texture: reskinNode = self.tramp.find( '**/trampoline/__Actor_modelRoot/-GeomNode') reskinNode.setTexture(loader.loadTexture(self.texture), 100) self.surface = NodePath(self.uniqueName('trampSurface')) self.surface.reparentTo(self.tramp) self.surface.setZ(3.6) self.trampHeight = self.z + 3.6 self.beginningBoostThreshold = self.trampHeight + 1.5 self.trampActor.controlJoint(self.surface, 'modelRoot', 'trampoline_joint1') self.sign.setPos(PartyGlobals.TrampolineSignOffset) self.beans = [ loader.loadModel('phase_6/models/events/ttr_tf_m_token') for i in range(self.numJellyBeans) ] for bean in self.beans: bean.setTransparency(True) bean.reparentTo(self.tramp) bean.stash() self.beans[(-1)].setScale(8.0) def loadCollision(self): collTube = CollisionTube(0.0, 0.0, self.z, 0.0, 0.0, self.z, 5.4) collTube.setTangible(True) self.trampolineCollision = CollisionNode( self.uniqueName('TrampolineCollision')) self.trampolineCollision.addSolid(collTube) self.trampolineCollision.setCollideMask(OTPGlobals.CameraBitmask | OTPGlobals.WallBitmask) self.trampolineCollisionNP = self.tramp.attachNewNode( self.trampolineCollision) collSphere = CollisionSphere(0.0, 0.0, self.z, 7.0) collSphere.setTangible(False) self.trampolineTrigger = CollisionNode( self.uniqueName('TrampolineTrigger')) self.trampolineTrigger.addSolid(collSphere) self.trampolineTrigger.setIntoCollideMask(OTPGlobals.WallBitmask) self.trampolineTriggerNP = self.tramp.attachNewNode( self.trampolineTrigger) self.accept('enter%s' % self.uniqueName('TrampolineTrigger'), self.onTrampolineTrigger) def loadGUI(self): self.gui = loader.loadModel('phase_13/models/parties/trampolineGUI') self.gui.reparentTo(base.a2dTopLeft) self.gui.setPos(0.115, 0, -1) self.gui.hide() self.toonIndicator = self.gui.find('**/trampolineGUI_MovingBar') self.gui.find('**/trampolineGUI_GreenJellyBean').hide() self.token_gui = loader.loadModel( 'phase_6/models/gui/ttr_m_tf_gui_tokens') jumpLineLocator = self.gui.find('**/jumpLine_locator') self.guiBean = self.token_gui.find('**/token') self.token_gui.find('**/token').stash() self.guiBean.setScale(0.1) self.guiBeans = [ self.guiBean.instanceUnderNode(jumpLineLocator, self.uniqueName('guiBean%d' % i)) for i in range(self.numJellyBeans) ] self.guiBeans[(-1)].setScale(1.5) heightTextNode = TextNode( self.uniqueName('TrampolineActivity.heightTextNode')) heightTextNode.setFont(ToontownGlobals.getSignFont()) heightTextNode.setAlign(TextNode.ALeft) heightTextNode.setText('0.0') heightTextNode.setShadow(0.05, 0.05) heightTextNode.setShadowColor(0.0, 0.0, 0.0, 1.0) heightTextNode.setTextColor(1.0, 1.0, 1.0, 1.0) self.heightText = jumpLineLocator.attachNewNode(heightTextNode) self.heightText.setX(0.15) self.heightText.setScale(0.1) self.heightText.setAlphaScale(0.0) self.quitEarlyButtonModels = loader.loadModel( 'phase_3.5/models/gui/inventory_gui') quitEarlyUp = self.quitEarlyButtonModels.find('**//InventoryButtonUp') quitEarlyDown = self.quitEarlyButtonModels.find( '**/InventoryButtonDown') quitEarlyRollover = self.quitEarlyButtonModels.find( '**/InventoryButtonRollover') self.quitEarlyButton = DirectButton( parent=base.a2dTopRight, relief=None, text=TTLocalizer.PartyTrampolineQuitEarlyButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -0.23), text_scale=0.7, image=(quitEarlyUp, quitEarlyDown, quitEarlyRollover), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(-0.183, 0, -0.4), scale=0.09, command=self.leaveTrampoline) self.quitEarlyButton.stash() self.flashText = OnscreenText(text='', pos=(0.0, -0.45), scale=0.2, fg=(1.0, 1.0, 0.65, 1.0), align=TextNode.ACenter, font=ToontownGlobals.getSignFont(), mayChange=True) self.timer = PartyUtils.getNewToontownTimer() self.timer.posInTopRightCorner() return def loadSounds(self): self.jellyBeanSound = base.loader.loadSfx( 'phase_4/audio/sfx/sparkly.ogg') self.boingSound = base.loader.loadSfx( 'phase_4/audio/sfx/target_trampoline_2.ogg') self.whistleSound = base.loader.loadSfx( 'phase_4/audio/sfx/AA_sound_whistle.ogg') def loadIntervals(self): def prepareHeightText(): self.heightText.node().setText( TTLocalizer.PartyTrampolineGetHeight % int(self.toon.getZ())) self.heightText.setZ(self.indicatorFactor * self.toon.getZ() + self.heightTextOffset) self.heightTextInterval = Sequence( Func(prepareHeightText), LerpFunc(self.heightText.setAlphaScale, fromData=1.0, toData=0.0, duration=1.0)) def unload(self): DistributedToonFestTrampolineActivity.notify.debug('unload') if self.hopOnAnim and self.hopOnAnim.isPlaying(): self.hopOnAnim.finish() if self.hopOffAnim and self.hopOffAnim.isPlaying(): self.hopOffAnim.finish() if self.beginRoundInterval and self.beginRoundInterval.isPlaying(): self.beginRoundInterval.finish() if self.flashTextInterval and self.flashTextInterval.isPlaying(): self.flashTextInterval.finish() if self.heightTextInterval and self.heightTextInterval.isPlaying(): self.heightTextInterval.finish() self.timer.stop() DistributedPartyActivity.unload(self) taskMgr.remove(self.uniqueName('TrampolineActivity.updateTask')) taskMgr.remove(self.uniqueName('TrampolineActivity.remoteUpdateTask')) self.ignoreAll() del self.heightTextInterval del self.beginRoundInterval del self.hopOnAnim del self.hopOffAnim del self.flashTextInterval if hasattr(self, 'beanAnims'): self.cleanupJellyBeans() self.quitEarlyButton.destroy() del self.quitEarlyButton del self.gui del self.activityFSM del self.animFSM def setBestHeightInfo(self, toonName, height): self.bestHeightInfo = (toonName, height) DistributedToonFestTrampolineActivity.notify.debug( '%s has the best height of %d' % (toonName, height)) if height > 0: self.setSignNote(TTLocalizer.PartyTrampolineBestHeight % self.bestHeightInfo) else: self.setSignNote(TTLocalizer.PartyTrampolineNoHeightYet) def leaveTrampoline(self): if self.toon != None and self.toon.doId == base.localAvatar.doId: self._showFlashMessage(TTLocalizer.PartyTrampolineTimesUp) self.leavingTrampoline = True self.timer.reset() self.trampB = self.leavingTrampB self.ignore('control') self.quitEarlyButton.stash() self.gui.hide() return def requestAnim(self, request): self.animFSM.request(request) def b_requestAnim(self, request): self.requestAnim(request) self.sendUpdate('requestAnim', [request]) def requestAnimEcho(self, request): if self.toon != None and self.toon.doId != base.localAvatar.doId: self.requestAnim(request) return def removeBeans(self, beansToRemove): for i in beansToRemove: height, bean, guiBean, beanAnim = self.beanDetails[i] guiBean.stash() if i in self.beansToCollect: self.beansToCollect.remove(i) else: self.notify.warning( 'removeBeans avoided a crash, %d not in self.beansToCollect' % i) self.poofBean(bean, beanAnim) def b_removeBeans(self, beansToRemove): self.removeBeans(beansToRemove) self.sendUpdate('removeBeans', [beansToRemove]) def removeBeansEcho(self, beansToRemove): if self.toon != None and self.toon.doId != base.localAvatar.doId: self.removeBeans(beansToRemove) return def joinRequestDenied(self, reason): DistributedPartyActivity.joinRequestDenied(self, reason) self.showMessage(TTLocalizer.PartyActivityDefaultJoinDeny) base.cr.playGame.getPlace().fsm.request('walk') def exitRequestDenied(self, reason): DistributedPartyActivity.exitRequestDenied(self, reason) self.showMessage(TTLocalizer.PartyActivityDefaultExitDeny) def setState(self, newState, timestamp): DistributedToonFestTrampolineActivity.notify.debug( 'setState( newState=%s, ... )' % newState) DistributedPartyActivity.setState(self, newState, timestamp) self.activityFSM.request(newState) def startIdle(self): DistributedToonFestTrampolineActivity.notify.debug('startIdle') def finishIdle(self): DistributedToonFestTrampolineActivity.notify.debug('finishIdle') def startRules(self): DistributedToonFestTrampolineActivity.notify.debug('startRules') if self.doJellyBeans: self.setupJellyBeans() if self.toon != None and self.toon.doId == base.localAvatar.doId: self.acquireToon() return def startActive(self): DistributedToonFestTrampolineActivity.notify.debug('startActive') if self.toon != None and self.toon.doId == base.localAvatar.doId: base.setCellsAvailable(base.bottomCells, True) self.accept('arrow_left', self.onLeft) self.accept('arrow_left-up', self.onLeftUp) self.accept('arrow_right', self.onRight) self.accept('arrow_right-up', self.onRightUp) self.beginRoundInterval = Sequence( Func(self._showFlashMessage, TTLocalizer.PartyTrampolineReady), Wait(1.2), Func(self.flashMessage, TTLocalizer.PartyTrampolineGo), Func(self.beginRound)) self.beginRoundInterval.start() return def finishActive(self): DistributedToonFestTrampolineActivity.notify.debug('finishActive') if self.doJellyBeans: self.cleanupJellyBeans() def setupJellyBeans(self): self.beanAnims = [] self.beansToCollect = [] self.beanDetails = [] self.numBeansCollected = 0 for i in range(self.numJellyBeans): bean = self.beans[i] guiBean = self.guiBeans[i] height = self.jellyBeanPositions[i] if self.toon: avHeight = self.toon.getHeight() else: avHeight = 3 bean.setZ(height + self.toon.getHeight() + self.beanOffset) guiBean.setZ(height * self.indicatorFactor + self.guiBeanOffset) bean.setH(0.0) bean.unstash() guiBean.unstash() beanAnim = bean.hprInterval( 1.5, VBase3((i % 2 * 2 - 1) * 360.0, 0.0, 0.0)) beanAnim.loop() self.beanAnims.append(beanAnim) self.beanDetails.append((height, bean, guiBean, beanAnim)) self.beansToCollect = range(self.numJellyBeans) def cleanupJellyBeans(self): for bean in self.beans: bean.stash() for guiBean in self.guiBeans: guiBean.stash() if hasattr(self, 'beanAnims'): for beanAnim in self.beanAnims: beanAnim.finish() del self.beanAnims del self.beansToCollect def beginRound(self): base.playSfx(self.whistleSound) self.timer.setTime(PartyGlobals.TrampolineDuration) self.timer.countdown(PartyGlobals.TrampolineDuration) self.timer.show() self.gui.show() self.quitEarlyButton.unstash() self.notify.debug('Accepting contorl') self.accept('control', self.onJump) self.notify.debug('setting simulate step to true') self.doSimulateStep = True def acquireToon(self): self.toon.disableSmartCameraViews() self.toon.stopUpdateSmartCamera() camera.wrtReparentTo(render) self.toon.dropShadow.reparentTo(hidden) self.toon.startPosHprBroadcast(period=0.2) self.toonAcceleration = 0.0 self.toonVelocity = 0.0 self.topHeight = 0.0 self.trampB = self.normalTrampB self.leavingTrampoline = False self.hopOnAnim = Sequence( Func(self.toon.b_setAnimState, 'jump', 1.0), Wait(0.4), PartyUtils.arcPosInterval(0.75, self.toon, Point3(0.0, 0.0, 3.6), 5.0, self.tramp), Func(self.postHopOn)) self.hopOnAnim.start() def postHopOn(self): self.toon.setH(self.toon.getH() + 90.0) self.toon.dropShadow.reparentTo(self.surface) self.timeLeftToSimulate = 0.0 self.doSimulateStep = False taskMgr.add(self.updateTask, self.uniqueName('TrampolineActivity.updateTask')) base.setCellsAvailable(base.leftCells, False) base.setCellsAvailable(base.bottomCells, False) DistributedPartyActivity.startRules(self) def releaseToon(self): self._hideFlashMessage() self.ignore('arrow_left') self.ignore('arrow_left-up') self.ignore('arrow_right') self.ignore('arrow_right-up') taskMgr.remove(self.uniqueName('TrampolineActivity.updateTask')) self.hopOffAnim = Sequence( self.toon.hprInterval(0.5, VBase3(-90.0, 0.0, 0.0), other=self.tramp), Func(self.toon.b_setAnimState, 'jump', 1.0), Func(self.toon.dropShadow.reparentTo, hidden), Wait(0.4), PartyUtils.arcPosInterval(0.75, self.toon, self.hopOffPos, 5.0, self.tramp), Func(self.postHopOff)) self.hopOffAnim.start() def postHopOff(self): base.setCellsAvailable(base.leftCells, True) self.timer.stop() self.timer.hide() self.toon.dropShadow.reparentTo(self.toon.getShadowJoint()) self.toon.dropShadow.setAlphaScale(1.0) self.toon.dropShadow.setScale(1.0) self.b_requestAnim('Off') camera.reparentTo(base.localAvatar) base.localAvatar.startUpdateSmartCamera() base.localAvatar.enableSmartCameraViews() base.localAvatar.setCameraPositionByIndex(base.localAvatar.cameraIndex) place = base.cr.playGame.getPlace() if self.doJellyBeans: self.sendUpdate('awardTokens', [self.numBeansCollected, int(self.topHeight)]) if int(self.topHeight) > self.bestHeightInfo[1]: self.sendUpdate('reportHeightInformation', [int(self.topHeight)]) self.d_toonExitDemand() def onTrampolineTrigger(self, collEntry): if self.activityFSM.state == 'Idle' and self.toon == None and base.cr.playGame.getPlace( ).fsm.getCurrentState().getName() == 'walk': base.cr.playGame.getPlace().fsm.request('activity') self.d_toonJoinRequest() else: self.flashMessage(TTLocalizer.PartyTrampolineActivityOccupied, duration=2.0) return def onJump(self): self.notify.debug('got onJump') if self.toon != None and self.toon.getZ() < self.trampHeight: self.toonJumped = True self.b_requestAnim('Jump') else: self.notify.debug('z is less than tramp height') return def onLeft(self): self.turnLeft = True def onLeftUp(self): self.turnLeft = False def onRight(self): self.turnRight = True def onRightUp(self): self.turnRight = False def handleToonJoined(self, toonId): DistributedToonFestTrampolineActivity.notify.debug('handleToonJoined') self.toon = self.getAvatar(toonId) if self.toon != None and not self.toon.isEmpty(): self.oldJumpSquatPlayRate = self.toon.getPlayRate('jump-squat') self.oldJumpLandPlayRate = self.toon.getPlayRate('jump-land') self.toon.setPlayRate(2.5, 'jump-squat') self.toon.setPlayRate(2.0, 'jump-land') self.turnLeft = False self.turnRight = False self.activityFSM.request('Rules') if self.toon.doId != base.localAvatar.doId: taskMgr.add( self.remoteUpdateTask, self.uniqueName('TrampolineActivity.remoteUpdateTask')) else: self.notify.warning('handleToonJoined could not get toon %d' % toonId) return def handleToonExited(self, toonId): DistributedToonFestTrampolineActivity.notify.debug('handleToonExited') if self.toon != None: if self.toon.doId != base.localAvatar.doId: taskMgr.remove( self.uniqueName('TrampolineActivity.remoteUpdateTask')) self.surface.setZ(3.6) self.toon.setPlayRate(self.oldJumpSquatPlayRate, 'jump-squat') self.toon.setPlayRate(self.oldJumpLandPlayRate, 'jump-land') self.toon = None return def handleToonDisabled(self, toonId): DistributedToonFestTrampolineActivity.notify.debug( 'handleToonDisabled') DistributedToonFestTrampolineActivity.notify.debug('avatar ' + str(toonId) + ' disabled') if base.localAvatar.doId == toonId: self.releaseToon() def handleRulesDone(self): self.sendUpdate('toonReady') self.finishRules() def getTitle(self): return TTLocalizer.ToonFestTrampolineTokenTitle def getInstructions(self): return TTLocalizer.ToonFestTrampolineActivityInstructions def updateTask(self, task): z = self.toon.getZ() dt = globalClock.getDt() if self.doSimulateStep: self.timeLeftToSimulate += dt while self.timeLeftToSimulate >= self.stepDT: z, a = self.simulateStep(z) self.timeLeftToSimulate -= self.stepDT self.toon.setZ(z) if z <= self.trampHeight: self.surface.setZ(3.6) else: self.surface.setZ(3.6) self.toonIndicator.setZ((z - self.trampHeight) * self.indicatorFactor) if self.turnLeft: self.toon.setH(self.toon.getH() + self.turnFactor * dt) if self.turnRight: self.toon.setH(self.toon.getH() - self.turnFactor * dt) currentPos = base.camera.getPos(self.toon) vec = self.targetCameraPos - currentPos newPos = currentPos + vec * (dt * self.cameraSpeed) base.camera.setPos(self.toon, newPos) base.camera.lookAt(self.toon) if self.leavingTrampoline and z < self.trampHeight and abs(a) < 0.1: self.releaseToon() return Task.cont def simulateStep(self, z): if z >= self.trampHeight: a = self.g self.toonJumped = False else: a = self.g + self.trampK * (self.trampHeight - z) - self.trampB * self.toonVelocity if self.toonJumped: if self.lastPeak > self.earlyJumpThreshold or self.toonVelocity >= -300000.0: a += self.jumpBoost if self.lastPeak < self.beginningBoostThreshold: a += self.beginningBoost lastVelocity = self.toonVelocity self.toonVelocity += a * self.stepDT if lastVelocity > 0.0 and self.toonVelocity <= 0.0: topOfJump = True bottomOfJump = False else: if lastVelocity < 0.0 and self.toonVelocity >= 0.0: topOfJump = False bottomOfJump = True else: topOfJump = False bottomOfJump = False newZ = z + self.toonVelocity * self.stepDT if newZ > self.topHeight: self.topHeight = newZ if self.doJellyBeans: self.collectJellyBeans(newZ) if topOfJump: self.lastPeak = newZ if newZ >= self.minHeightForText: self.heightTextInterval.start() if topOfJump: if newZ > self.trampHeight + 20.0: self.b_requestAnim('Falling') elif self.animFSM.state == 'Jump': self.b_requestAnim('Falling') if newZ <= self.trampHeight and z > self.trampHeight: if self.animFSM.state == 'Falling': self.b_requestAnim('Land') elif self.animFSM.state != 'Neutral': self.b_requestAnim('Neutral') if bottomOfJump and a > self.boingThreshold: base.playSfx(self.boingSound) return (newZ, a) def collectJellyBeans(self, z): beansToRemove = [] for i in self.beansToCollect: height = self.beanDetails[i][0] if height <= z: beansToRemove.append(i) if len(beansToRemove) > 0: base.playSfx(self.jellyBeanSound) self.numBeansCollected += len(beansToRemove) self.b_removeBeans(beansToRemove) def remoteUpdateTask(self, task): if self.toon != None and not self.toon.isEmpty(): z = self.toon.getZ() if z <= self.trampHeight: self.surface.setZ(3.6) else: self.surface.setZ(3.6) return Task.cont def poofBean(self, bean, beanAnim): if bean == None: self.notify.warning( 'poofBean, returning immediately as bean is None') return if bean.isEmpty(): self.notify.warning( 'poofBean, returning immediately as bean is empty') return currentAlpha = bean.getColorScale()[3] currentScale = bean.getScale() poofAnim = Sequence( Parallel( LerpFunc(bean.setAlphaScale, fromData=currentAlpha, toData=0.0, duration=0.25), LerpFunc(bean.setScale, fromData=currentScale, toData=currentScale * 5.0, duration=0.25)), Func(bean.stash), Func(beanAnim.finish), Func(bean.setAlphaScale, currentAlpha), Func(bean.setScale, currentScale)) poofAnim.start() return def _showFlashMessage(self, message): if self.isDisabled(): return if self.flashTextInterval is not None and self.flashTextInterval.isPlaying( ): self.flashTextInterval.finish() self.flashText.setText(message) self.flashText.setAlphaScale(1.0) self.flashText.unstash() return def _hideFlashMessage(self, duration=0.0): if self.isDisabled(): pass self.flashTextInterval = Sequence( Wait(duration), LerpFunc(self.flashText.setAlphaScale, fromData=1.0, toData=0.0, duration=1.0), Func(self.flashText.stash)) self.flashTextInterval.start() def flashMessage(self, message, duration=0.5): self._showFlashMessage(message) self._hideFlashMessage(duration)
def getDropIval(self, x, y, dropObjName, generation, num): objType = PartyGlobals.Name2DropObjectType[dropObjName] id = (generation, num) dropNode = hidden.attachNewNode('catchDropNode%s' % (id, )) dropNode.setPos(x, y, 0) shadow = self.dropShadow.copyTo(dropNode) shadow.setZ(PartyGlobals.CatchDropShadowHeight) shadow.setColor(1, 1, 1, 1) object = self.getObjModel(dropObjName) object.reparentTo(hidden) if dropObjName in ['watermelon', 'anvil']: objH = object.getH() absDelta = {'watermelon': 12, 'anvil': 15}[dropObjName] delta = (self.randomNumGen.random() * 2.0 - 1.0) * absDelta newH = objH + delta else: newH = self.randomNumGen.random() * 360.0 object.setH(newH) sphereName = 'FallObj%s' % (id, ) radius = self.ObjRadius if objType.good: radius *= lerp(1.0, 1.3, 0.5) collSphere = CollisionSphere(0, 0, 0, radius) collSphere.setTangible(0) collNode = CollisionNode(sphereName) collNode.setCollideMask(PartyGlobals.CatchActivityBitmask) collNode.addSolid(collSphere) collNodePath = object.attachNewNode(collNode) collNodePath.hide() if self.ShowObjSpheres: collNodePath.show() catchEventName = 'ltCatch' + sphereName def eatCollEntry(forward, collEntry): forward() self.accept( catchEventName, Functor(eatCollEntry, Functor(self.__handleCatch, id[0], id[1]))) def cleanup(self=self, dropNode=dropNode, id=id, event=catchEventName): self.ignore(event) dropNode.removeNode() duration = objType.fallDuration onscreenDuration = objType.onscreenDuration targetShadowScale = 0.3 if self.trickShadows: intermedScale = targetShadowScale * (self.OffscreenTime / self.BaselineDropDuration) shadowScaleIval = Sequence( LerpScaleInterval(shadow, self.OffscreenTime, intermedScale, startScale=0)) shadowScaleIval.append( LerpScaleInterval(shadow, duration - self.OffscreenTime, targetShadowScale, startScale=intermedScale)) else: shadowScaleIval = LerpScaleInterval(shadow, duration, targetShadowScale, startScale=0) targetShadowAlpha = 0.4 shadowAlphaIval = LerpColorScaleInterval( shadow, self.OffscreenTime, Point4(1, 1, 1, targetShadowAlpha), startColorScale=Point4(1, 1, 1, 0)) shadowIval = Parallel(shadowScaleIval, shadowAlphaIval) if self.useGravity: def setObjPos(t, objType=objType, object=object): z = objType.trajectory.calcZ(t) object.setZ(z) setObjPos(0) dropIval = LerpFunctionInterval(setObjPos, fromData=0, toData=onscreenDuration, duration=onscreenDuration) else: startPos = Point3(0, 0, self.MinOffscreenHeight) object.setPos(startPos) dropIval = LerpPosInterval(object, onscreenDuration, Point3(0, 0, 0), startPos=startPos, blendType='easeIn') ival = Sequence(Func(Functor(dropNode.reparentTo, self.root)), Parallel( Sequence( WaitInterval(self.OffscreenTime), Func(Functor(object.reparentTo, dropNode)), dropIval), shadowIval), Func(cleanup), name='drop%s' % (id, )) if objType == PartyGlobals.Name2DropObjectType['anvil']: ival.append(Func(self.playAnvil)) return ival
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)