class HangUpAttack(Attack): notify = directNotify.newCategory('HangUpAttack') attack = 'hangup' def __init__(self, attacksClass, suit): Attack.__init__(self, attacksClass, suit) self.phone = None self.receiver = None self.collNP = None self.phoneSfx = None self.hangupSfx = None self.shootIval = None self.cord = None self.receiverOutCord = None self.phoneOutCord = None return 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 doAttack(self, ts = 0): self.loadAttack() if hasattr(self.suit, 'uniqueName'): name = self.suit.uniqueName('doHangupAttack') else: name = 'doHangupAttack' if self.suit.type == 'A': delay2playSound = 1.0 delayAfterSoundToPlaceDownReceiver = 0.2 delayAfterShootToIgnoreCollisions = 1.0 delay2PickUpReceiver = 1.0 receiverInHandPos = Point3(-0.5, 0.5, -1) elif self.suit.type == 'B': delay2playSound = 1.5 delayAfterSoundToPlaceDownReceiver = 0.7 delayAfterShootToIgnoreCollisions = 1.0 delay2PickUpReceiver = 1.5 receiverInHandPos = Point3(-0.3, 0.5, -0.8) elif self.suit.type == 'C': delay2playSound = 1.0 delayAfterSoundToPlaceDownReceiver = 1.15 delayAfterShootToIgnoreCollisions = 1.0 delay2PickUpReceiver = 1.5 receiverInHandPos = Point3(-0.3, 0.5, -0.8) self.suitTrack = Parallel(name=name) self.suitTrack.append(ActorInterval(self.suit, 'phone')) self.suitTrack.append(Sequence(Wait(delay2playSound), SoundInterval(self.phoneSfx, duration=2.1), Wait(delayAfterSoundToPlaceDownReceiver), Func(self.receiver.setPos, 0, 0, 0), Func(self.receiver.setH, 0.0), Func(self.receiver.reparentTo, self.phone), Func(self.acceptOnce, 'enter' + self.collNP.node().getName(), self.handleCollision), Func(self.shootOut), Parallel(SoundInterval(self.hangupSfx), Sequence(Wait(delayAfterShootToIgnoreCollisions), Func(self.ignore, 'enter' + self.collNP.node().getName()))))) self.suitTrack.append(Sequence(Func(self.phone.reparentTo, self.suit.find('**/joint_Lhold')), Func(self.cord.reparentTo, render), Wait(delay2PickUpReceiver), Func(self.receiver.reparentTo, self.suit.find('**/joint_Rhold')), Func(self.receiver.setPos, receiverInHandPos), Func(self.receiver.setH, 270.0))) self.suitTrack.setDoneEvent(self.suitTrack.getName()) self.acceptOnce(self.suitTrack.getDoneEvent(), self.finishedAttack) self.suitTrack.delayDelete = DelayDelete.DelayDelete(self.suit, name) self.suitTrack.start(ts) def handleCollision(self, entry): if self.suit: self.suit.sendUpdate('toonHitByWeapon', [self.getAttackId(self.attack), base.localAvatar.doId]) base.localAvatar.b_handleSuitAttack(self.getAttackId(self.attack), self.suit.doId) def shootOut(self): pathNode = NodePath('path') pathNode.reparentTo(self.suit) pathNode.setPos(0, 50, self.phone.getZ(self.suit)) self.collNP.reparentTo(render) self.shootIval = LerpPosInterval(self.collNP, duration=1.0, pos=pathNode.getPos(render), startPos=self.phone.getPos(render)) self.shootIval.start() pathNode.removeNode() del pathNode def cleanup(self): Attack.cleanup(self) if self.shootIval: self.shootIval.pause() self.shootIval = None if self.cord: self.cord.removeNode() self.cord = None if self.phone: self.phone.removeNode() self.phone = None if self.receiver: self.receiver.removeNode() self.receiver = None if self.collNP: self.collNP.node().clearSolids() self.collNP.removeNode() self.collNP = None if self.phoneSfx: self.phoneSfx.stop() self.phoneSfx = None return
class ParticleAttack(Attack): notify = directNotify.newCategory('ParticleAttack') attack = 'particleattack' particleIvalDur = 1 shooterDistance = 50 def __init__(self, attacksClass, suit): Attack.__init__(self, attacksClass, suit) self.particles = [] self.handObj = None self.shootOutCollNP = None self.particleSound = None self.particleMoveIval = None self.targetX = None self.targetY = None self.targetZ = None return def handleWeaponTouch(self): pass def handleCollision(self, entry): if self.suit: self.suit.sendUpdate('toonHitByWeapon', [self.getAttackId(self.attack), base.localAvatar.doId]) base.localAvatar.b_handleSuitAttack(self.getAttackId(self.attack), self.suit.doId) 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 releaseAttack(self, releaseFromJoint, onlyMoveColl = True, blendType = 'noBlend'): startNP = releaseFromJoint.attachNewNode('startNP') if None not in [self.targetX, self.targetY, self.targetZ]: startNP.lookAt(render, self.targetX, self.targetY, self.targetZ + 2) pathNP = NodePath('path') pathNP.reparentTo(startNP) pathNP.setScale(render, 1.0) pathNP.setPos(0, self.shooterDistance, 0) for particle in self.particles: if not onlyMoveColl: particle.start(render) else: particle.start(self.suit) particle.lookAt(pathNP) if self.attack == 'razzledazzle': particle.setP(particle, 90) if onlyMoveColl: target = self.shootOutCollNP target.wrtReparentTo(render) else: target = self.particles[0] self.particleMoveIval = LerpPosInterval(target, duration=self.particleIvalDur, pos=pathNP.getPos(render), startPos=startNP.getPos(render), blendType=blendType) self.particleMoveIval.start() self.acceptOnce('enter' + self.shootOutCollNP.node().getName(), self.handleCollision) pathNP.removeNode() startNP.removeNode() del pathNP del startNP self.playParticleSound() return def playParticleSound(self): if self.particleSound: base.audio3d.attachSoundToObject(self.particleSound, self.suit) base.playSfx(self.particleSound) def cleanup(self): Attack.cleanup(self) self.targetX = None self.targetY = None self.targetZ = None if self.particles: for particle in self.particles: particle.cleanup() self.particles = None if self.handObj: self.handObj.removeNode() self.handObj = None if self.shootOutCollNP: self.ignore('enter' + self.shootOutCollNP.node().getName()) self.shootOutCollNP.removeNode() self.shootOutCollNP = None if self.particleMoveIval: self.particleMoveIval.pause() self.particleMoveIval = None self.particleSound = None self.particleIvalDur = None return
class DistributedEagleSuit(DistributedSuit): notify = directNotify.newCategory('DistributedEagleSuit') def __init__(self, cr): DistributedSuit.__init__(self, cr) self.eagleCry = base.audio3d.loadSfx( 'phase_5/audio/sfx/tt_s_ara_cfg_eagleCry.ogg') base.audio3d.attachSoundToObject(self.eagleCry, self) self.fallWhistle = base.audio3d.loadSfx( 'phase_5/audio/sfx/incoming_whistleALT.ogg') base.audio3d.attachSoundToObject(self.fallWhistle, self) self.explode = base.audio3d.loadSfx( 'phase_3.5/audio/sfx/ENC_cogfall_apart.ogg') base.audio3d.attachSoundToObject(self.explode, self) self.eventSphereNodePath = None self.fallingPropeller = None self.fallingPropProjectile = None self.mg = None self.flySpeed = 0.0 return def enterNeutral(self, ts=0): self.show() self.timestampAnimTrack = Sequence(Wait(ts), Func(self.loop, 'flyNeutral')) self.timestampAnimTrack.start() def makeStateDict(self): self.suitFSM.addState( State('eagleFly', self.enterEagleFly, self.exitEagleFly)) self.suitFSM.addState( State('eagleFall', self.enterEagleFall, self.exitEagleFall)) self.stateIndex2suitState = { 0: self.suitFSM.getStateNamed('off'), 1: self.suitFSM.getStateNamed('walking'), 2: self.suitFSM.getStateNamed('flyingDown'), 3: self.suitFSM.getStateNamed('flyingUp'), 4: self.suitFSM.getStateNamed('lured'), 5: self.suitFSM.getStateNamed('eagleFly'), 6: self.suitFSM.getStateNamed('eagleFall') } self.suitState2stateIndex = {} for stateId, state in self.stateIndex2suitState.items(): self.suitState2stateIndex[state.getName()] = stateId def setFlySpeed(self, value): self.flySpeed = value def getFlySpeed(self): return self.flySpeed def enterEagleFly(self, startIndex, endIndex, ts=0.0): durationFactor = self.getFlySpeed() if startIndex > -1: startPos = EGG.EAGLE_FLY_POINTS[startIndex] else: startPos = self.getPos(render) endPos = EGG.EAGLE_FLY_POINTS[endIndex] if self.moveIval: self.moveIval.pause() self.moveIval = None self.moveIval = NPCWalkInterval(self, endPos, durationFactor=durationFactor, startPos=startPos, fluid=1) self.moveIval.start(ts) return def exitEagleFly(self): if self.moveIval: self.moveIval.pause() self.moveIval = None return def enterEagleFall(self, startIndex, endIndex, ts=0.0): self.moveIval = LerpPosInterval(self, duration=4.0, pos=self.getPos(render) - (0, 0, 75), startPos=self.getPos(render), blendType='easeIn') self.moveIval.start(ts) def exitEagleFall(self): if self.moveIval: self.moveIval.finish() self.moveIval = None return def fallAndExplode(self): self.cleanupPropeller() self.fallingPropeller = Actor( 'phase_4/models/props/propeller-mod.bam', {'chan': 'phase_4/models/props/propeller-chan.bam'}) self.fallingPropeller.reparentTo(render) self.fallingPropeller.loop('chan', fromFrame=0, toFrame=3) parentNode = self.attachNewNode('fallingPropParentNode') h = random.randint(0, 359) parentNode.setH(h) dummyNode = parentNode.attachNewNode('dummyNode') dummyNode.setPos(0, 10, -50) self.fallingPropProjectile = FlightProjectileInterval( self.fallingPropeller, startPos=self.find('**/joint_head').getPos(render), endPos=dummyNode.getPos(render), duration=5.0, gravityMult=0.25) self.fallingPropProjectile.start() dummyNode.removeNode() del dummyNode parentNode.removeNode() del parentNode self.updateHealthBar(0) self.ignoreHit() base.playSfx(self.fallWhistle, node=self) taskMgr.doMethodLater(4.0, self.doExplodeSound, self.uniqueName('DEagleSuit-doExplodeSound')) def doExplodeSound(self, task): base.playSfx(self.explode, node=self) return Task.done 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 removeEventSphere(self): if self.eventSphereNodePath: self.eventSphereNodePath.removeNode() self.eventSphereNodePath = None return def acceptHit(self): self.acceptOnce('enter' + self.eventSphereNodePath.node().getName(), self.__handleHit) def ignoreHit(self): self.ignore('enter' + self.eventSphereNodePath.node().getName()) def __handleHit(self, entry): messenger.send(EGG.EAGLE_HIT_EVENT, [self.doId]) def setSuit(self, arg, variant): DistributedSuit.setSuit(self, arg, 3) self.deleteShadow() self.disableBodyCollisions() self.disableRay() self.__initializeEventSphere() self.show() self.setAnimState('flyNeutral') def __doEagleCry(self, task): base.playSfx(self.eagleCry, node=self) task.delayTime = random.uniform(3, 30) return Task.again def announceGenerate(self): DistributedSuit.announceGenerate(self) taskMgr.doMethodLater(random.uniform(5, 25), self.__doEagleCry, self.uniqueName('DEagleSuit-doEagleCry')) self.acceptHit() def disable(self): self.ignoreHit() self.removeEventSphere() taskMgr.remove(self.uniqueName('DEagleSuit-doExplodeSound')) taskMgr.remove(self.uniqueName('DEagleSuit-doEagleCry')) if self.fallingPropProjectile: self.fallingPropProjectile.finish() self.fallingPropProjectile = None if self.fallingPropeller: self.fallingPropeller.cleanup() self.fallingPropeller = None base.audio3d.detachSound(self.fallWhistle) del self.fallWhistle base.audio3d.detachSound(self.explode) del self.explode base.audio3d.detachSound(self.eagleCry) del self.eagleCry self.mg = None DistributedSuit.disable(self) return
class ThrowAttack(Attack): notify = directNotify.newCategory('ThrowAttack') attack = 'throw' def __init__(self, attacksClass, suit): Attack.__init__(self, attacksClass, suit) self.weapon_state = None self.weapon = None self.wss = None self.wsnp = None self.suitTrack = None self.weaponSfx = None self.throwTrajectory = None self.targetX = None self.targetY = None self.targetZ = None self.startNP = None return def handleWeaponCollision(self, entry): if self.suit: self.suit.sendUpdate('toonHitByWeapon', [self.getAttackId(self.attack), base.localAvatar.doId]) base.localAvatar.b_handleSuitAttack(self.getAttackId(self.attack), self.suit.doId) self.suit.b_handleWeaponTouch() 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 playWeaponSound(self): if self.weapon and self.weaponSfx: base.audio3d.attachSoundToObject(self.weaponSfx, self.suit) self.weaponSfx.play() def throwObject(self, projectile = True): if not self.weapon: return self.acceptOnce('enter' + self.wsnp.node().getName(), self.handleWeaponCollision) self.playWeaponSound() if self.weapon: self.weapon.wrtReparentTo(render) self.weapon.setHpr(Vec3(0, 0, 0)) if self.attack not in ('glowerpower',): parent = self.suit.find('**/joint_Rhold') else: parent = self.suit.find('**/joint_head') startNP = parent.attachNewNode('startNp') startNP.lookAt(render, self.targetX, self.targetY, self.targetZ) pathNP = NodePath('throwPath') pathNP.reparentTo(startNP) pathNP.setScale(render, 1.0) pathNP.setPos(0, 50, 0) if self.attack in ('clipontie', 'powertie', 'halfwindsor'): self.weapon.setHpr(pathNP.getHpr(render)) if projectile == True: self.throwTrajectory = ProjectileInterval(self.weapon, startPos=self.suit.find('**/joint_Rhold').getPos(render), endPos=pathNP.getPos(render), gravityMult=0.7, duration=1.0) else: self.weapon.setH(pathNP.getH(render)) self.throwTrajectory = LerpPosInterval(self.weapon, duration=0.5, pos=pathNP.getPos(render), startPos=startNP.getPos(render) + (0, 3, 0)) self.throwTrajectory.start() self.weapon_state = 'released' startNP.removeNode() del startNP pathNP.removeNode() del pathNP def interruptAttack(self): if self.throwTrajectory: if self.throwTrajectory.isStopped(): self.delWeapon() def handleWeaponTouch(self): if self.throwTrajectory: self.throwTrajectory.pause() self.throwTrajectory = None self.delWeapon() return def delWeapon(self): if self.weapon: self.weapon.removeNode() self.weapon = None return def cleanup(self): Attack.cleanup(self) self.targetX = None self.targetY = None self.targetZ = None self.weapon_state = None if self.weaponSfx: self.weaponSfx.stop() self.weaponSfx = None if self.throwTrajectory: self.throwTrajectory.pause() self.throwTrajectory = None self.delWeapon() self.wss = None if self.wsnp: self.wsnp.node().clearSolids() self.wsnp.removeNode() self.wsnp = None return
class DistributedSuit(Suit, DistributedAvatar, DistributedSmoothNode, DelayDeletable): notify = directNotify.newCategory('DistributedSuit') def __init__(self, cr): Suit.__init__(self) DistributedAvatar.__init__(self, cr) DistributedSmoothNode.__init__(self, cr) self.anim = None self._state = SuitState.ALIVE self.dept = None self.variant = None self.suitPlan = None self.level = None self.moveIval = None self.hpFlash = None # For PythonCTMusicManager: # Are we in range of the localAvatar? self.isInRange = False self.chaseTarget = 0 self.suitFSM = ClassicFSM('DistributedSuit', [ State('off', self.enterSuitOff, self.exitSuitOff), State('walking', self.enterWalking, self.exitWalking), State('flyingDown', self.enterFlyingDown, self.exitFlyingDown), State('flyingUp', self.enterFlyingUp, self.exitFlyingUp), State('lured', self.enterLured, self.exitLured) ], 'off', 'off') self.stateIndex2suitState = {} self.suitFSM.enterInitialState() self.makeStateDict() def setChaseTarget(self, avId): if avId != base.localAvatar.doId: if self.chaseTarget == base.localAvatar.doId: messenger.send(PCTMM.getCogLostTargetEvent()) else: messenger.send(PCTMM.getCogChasingEvent()) self.chaseTarget = avId def setWalkPath(self, path, timestamp): elapsedT = globalClockDelta.localElapsedTime(timestamp) self.suitFSM.request('walking', [path, elapsedT]) def showAvId(self): self.setDisplayName(self.getName() + "\n" + str(self.doId)) def showName(self): self.setDisplayName(self.getName()) def setDisplayName(self, name): self.setupNameTag(tempName=name) def enterWalking(self, path, elapsedT): # path: A list of point2s. # # We will make a sequence of NPCWalkIntervals for each point2 in the path. self.clearMoveTrack() self.moveIval = getMoveIvalFromPath(self, path, elapsedT, True, 'suitMoveIval') self.moveIval.start(elapsedT) def clearMoveTrack(self): if self.moveIval: self.ignore(self.moveIval.getDoneEvent()) self.moveIval.pause() self.moveIval = None if not self.isDead(): self.animFSM.request('neutral') def exitWalking(self): self.clearMoveTrack() if not self.isDead(): self.animFSM.request('neutral') def enterFlyingDown(self, startIndex, endIndex, ts=0.0): if self.getHood() != '' and startIndex != -1 and endIndex != -1: duration = 3.5 startPoint = CIGlobals.SuitSpawnPoints[ self.getHood()].keys()[startIndex] startPos = CIGlobals.SuitSpawnPoints[ self.getHood()][startPoint] + (0, 0, 6.5 * 4.8) endPoint = CIGlobals.SuitSpawnPoints[ self.getHood()].keys()[endIndex] endPos = CIGlobals.SuitSpawnPoints[self.getHood()][endPoint] self.stopMoving(finish=1) groundF = 28 dur = self.getDuration('land') fr = self.getFrameRate('land') if fr: animTimeInAir = groundF / fr else: animTimeInAir = groundF impactLength = dur - animTimeInAir timeTillLanding = 6.5 - impactLength self.moveIval = LerpPosInterval(self, duration=timeTillLanding, pos=endPos, startPos=startPos, fluid=1) self.moveIval.start(ts) self.animFSM.request('flyDown', [ts]) def exitFlyingDown(self): self.stopMoving(finish=1) self.animFSM.request('neutral') def enterFlyingUp(self, startIndex, endIndex, ts=0.0): if self.getHood() != '': duration = 3 if startIndex > -1: startPoint = CIGlobals.SuitSpawnPoints[ self.getHood()].keys()[startIndex] startPos = CIGlobals.SuitSpawnPoints[ self.getHood()][startPoint] else: startPos = self.getPos(render) if endIndex > -1: endPoint = CIGlobals.SuitSpawnPoints[ self.getHood()].keys()[endIndex] endPos = CIGlobals.SuitSpawnPoints[ self.getHood()][endPoint] + (0, 0, 6.5 * 4.8) else: endPos = self.getPos(render) + (0, 0, 6.5 * 4.8) self.stopMoving(finish=1) groundF = 28 dur = self.getDuration('land') fr = self.getFrameRate('land') if fr: animTimeInAir = groundF / fr else: animTimeInAir = groundF impactLength = dur - animTimeInAir timeTillLanding = 6.5 - impactLength self.moveIval = Sequence( Wait(impactLength), LerpPosInterval(self, duration=timeTillLanding, pos=endPos, startPos=startPos, fluid=1)) self.moveIval.start(ts) self.animFSM.request('flyAway', [ts, 1]) def exitFlyingUp(self): if self.moveIval: self.moveIval.finish() self.moveIval = None self.animFSM.request('neutral') def enterLured(self, _, __, ___): self.loop('lured') def exitLured(self): self.stop() def enterSuitOff(self, foo1=None, foo2=None, foo3=None): pass def exitSuitOff(self): pass def setName(self, name): Suit.setName(self, name, self.suitPlan.getName()) def setLevel(self, level): self.level = level if self.level == 12: self.maxHealth = 200 elif self.level > 0: self.maxHealth = (self.level + 1) * (self.level + 2) else: self.maxHealth = 1 self.health = self.maxHealth self.updateHealthBar(self.health) def getLevel(self): return self.level def startMoveInterval(self, startX, startY, startZ, endX, endY, endZ, duration): self.stopMoving() endPos = Point3(endX, endY, endZ) self.moveIval = NPCWalkInterval(self, endPos, durationFactor=duration, fluid=1) self.moveIval.start() def stopMoveInterval(self, andTurnAround=0): if self.moveIval: self.moveIval.pause() self.moveIval = None if andTurnAround == 1: if self.health > 0: self.animFSM.request('neutral') self.setH(self.getH() - 180) def toggleRay(self, ray=1): if ray: Suit.initializeRay(self, self.avatarType, 2) else: Suit.disableRay(self) def startProjInterval(self, startX, startY, startZ, endX, endY, endZ, duration, gravityMult, ts=0): if isinstance(ts, int) and ts != 0: ts = globalClockDelta.localElapsedTime(ts) self.disableRay() self.stopMoveInterval() startPos = Point3(startX, startY, startZ) endPos = Point3(endX, endY, endZ) oldHpr = self.getHpr(render) self.headsUp(endPos) newHpr = self.getHpr(render) self.setHpr(oldHpr) self.moveIval = Parallel( LerpHprInterval(self, duration=0.5, hpr=newHpr, startHpr=oldHpr, blendType='easeInOut'), Sequence(Func(self.animFSM.request, 'flyAway', [ts]), Wait(3.5), Func(self.animFSM.request, 'flyDown', [1.0])), Sequence( Wait(2.0), Func(self.headsUp, endPos), ProjectileInterval(self, startPos=startPos, endPos=endPos, gravityMult=gravityMult, duration=duration))) self.moveIval.start(ts) def startPosInterval(self, startX, startY, startZ, endX, endY, endZ, duration, blendType, ts=0.0): if ts != 0.0: ts = globalClockDelta.localElapsedTime(ts) self.stopMoveInterval() startPos = Point3(startX, startY, startZ) endPos = Point3(endX, endY, endZ) self.moveIval = LerpPosInterval(self, duration=duration, pos=endPos, startPos=startPos, blendType=blendType) self.moveIval.start(ts) def stopMoving(self, finish=0): if self.moveIval: if finish: self.moveIval.finish() else: self.moveIval.pause() self.moveIval = None def d_disableMovement(self, wantRay=False): self.sendUpdate('disableMovement', []) self.interruptAttack() self.stopMoving() if not wantRay: Suit.disableRay(self) def d_enableMovement(self): self.sendUpdate('enableMovement', []) Suit.initializeRay(self, self.avatarType, 2) def startRay(self): Suit.initializeRay(self, self.avatarType, 2) def setHealth(self, health): if health > self.health: # We got an hp boost. Flash green. flashColor = VBase4(0, 1, 0, 1) elif health < self.health: # We got an hp loss. Flash red. flashColor = VBase4(1, 0, 0, 1) DistributedAvatar.setHealth(self, health) def doBossFlash(): if not self.isEmpty(): LerpColorScaleInterval(self, 0.2, flashColor).start() def clearBossFlash(): if not self.isEmpty(): self.clearColorScale() if self.isDead(): self.setChaseTarget(0) base.taskMgr.remove(self.uniqueName('monitorLocalAvDistance')) if self.isInRange: messenger.send(PCTMM.getCogOutOfRangeEvent()) self.isInRange = False self.interruptAttack() if self.getLevel() > 12: if self.hpFlash: self.hpFlash.finish() self.hpFlash = None self.hpFlash = Sequence(Func(doBossFlash), Wait(0.2), Func(clearBossFlash)) self.hpFlash.start() self.updateHealthBar(health) def announceHealth(self, level, hp): DistributedAvatar.announceHealth(self, level, hp) if level == 1: healthSfx = base.audio3d.loadSfx(SuitGlobals.healedSfx) base.audio3d.attachSoundToObject(healthSfx, self) SoundInterval(healthSfx, node=self).start() del healthSfx # # 'setSuit' sets the suit type and generates it. # 'arg' is an id for a SuitPlan as defined in SuitBank or # an instance of SuitPlan. # 'variant' is an optional argument that sets the variant. # It takes an id for the variant or an instance of Variant. # Default is Variant.NORMAL. def setSuit(self, arg, variant=0): if isinstance(arg, SuitPlan): plan = arg else: plan = SuitBank.getSuitById(arg) voice = Voice.NORMAL if variant: if isinstance(variant, (int, long, float, complex)): variant = Variant.getVariantById(variant) if plan.getForcedVoice(): voice = plan.getForcedVoice() Suit.generate(self, plan, variant, voice=voice) self.suitPlan = plan self.variant = Variant.getVariantById(variant) def getSuit(self): return tuple((self.suitPlan, self.variant)) def spawn(self, startIndex, endIndex, spawnMode=SpawnMode.FLYDOWN): if spawnMode == SpawnMode.FLYDOWN: startPoint = CIGlobals.SuitSpawnPoints[ self.getHood()].keys()[startIndex] startPos = CIGlobals.SuitSpawnPoints[ self.getHood()][startPoint] + (0, 0, 50) endPoint = CIGlobals.SuitSpawnPoints[ self.getHood()].keys()[endIndex] endPos = CIGlobals.SuitSpawnPoints[self.getHood()][endPoint] if self.moveIval: self.moveIval.finish() self.moveIval = None self.moveIval = LerpPosInterval(self, duration=3, pos=endPos, startPos=startPos, fluid=1) def makeStateDict(self): self.stateIndex2suitState = { 0: self.suitFSM.getStateNamed('off'), 1: self.suitFSM.getStateNamed('walking'), 2: self.suitFSM.getStateNamed('flyingDown'), 3: self.suitFSM.getStateNamed('flyingUp'), 4: self.suitFSM.getStateNamed('lured') } self.suitState2stateIndex = {} for stateId, state in self.stateIndex2suitState.items(): self.suitState2stateIndex[state.getName()] = stateId def setSuitState(self, index, startPoint, endPoint, timestamp=None): if timestamp != None: ts = globalClockDelta.localElapsedTime(timestamp) else: ts = 0.0 self.suitState = self.stateIndex2suitState[index] self.startPoint = startPoint self.endPoint = endPoint self.suitFSM.request(self.suitState, [startPoint, endPoint, ts]) def getSuitState(self): return self.suitState def setAnimState(self, anim, loop=1, timestamp=None): prevAnim = self.anim self.anim = anim if timestamp == None: ts = 0.0 else: ts = globalClockDelta.localElapsedTime(timestamp) if type(anim) == types.IntType: if anim != 44 and anim != 45: anim = SuitGlobals.getAnimById(anim) animName = anim.getName() elif anim == 44: animName = 'die' elif anim == 45: animName = 'flyNeutral' elif type(anim) == types.StringType: animName = anim if self.animFSM.hasStateNamed(animName): self.animFSM.request(animName, [ts]) else: if loop: self.loop(animName) else: self.play(animName) messenger.send(SuitGlobals.animStateChangeEvent % (self.uniqueName), [anim, prevAnim]) def doAttack(self, attackId, avId, timestamp=None): if timestamp == None: ts = 0.0 else: ts = globalClockDelta.localElapsedTime(timestamp) attackName = SuitAttacks.SuitAttackLengths.keys()[attackId] attackTaunt = CIGlobals.SuitAttackTaunts[attackName][random.randint( 0, len(CIGlobals.SuitAttackTaunts[attackName]) - 1)] avatar = self.cr.doId2do.get(avId) shouldChat = 0 if self.suitPlan in [SuitBank.VicePresident, SuitBank.LucyCrossbill]: shouldChat = random.randint(0, 2) if shouldChat == 0: self.setChat(attackTaunt) self.animFSM.request('attack', [attackName, avatar, 0.0]) def throwObject(self): self.acceptOnce('enter' + self.wsnp.node().getName(), self.__handleWeaponCollision) Suit.throwObject(self) def __handleWeaponCollision(self, entry): self.sendUpdate('toonHitByWeapon', [self.attack, base.localAvatar.doId]) base.localAvatar.handleHitByWeapon(self.attack, self) self.b_handleWeaponTouch() def b_handleWeaponTouch(self): self.sendUpdate('handleWeaponTouch', []) self.handleWeaponTouch() def __monitorLocalAvDistance(self, task): if self.getDistance(base.localAvatar) <= PCTMM.getCogInRangeDistance( ) and not self.isInRange: self.isInRange = True messenger.send(PCTMM.getCogInRangeEvent()) elif self.getDistance(base.localAvatar) > PCTMM.getCogInRangeDistance( ) and self.isInRange: self.isInRange = False messenger.send(PCTMM.getCogOutOfRangeEvent()) return task.cont def announceGenerate(self): DistributedAvatar.announceGenerate(self) self.setAnimState('neutral') base.taskMgr.add(self.__monitorLocalAvDistance, self.uniqueName('monitorLocalAvDistance')) def generate(self): DistributedAvatar.generate(self) DistributedSmoothNode.generate(self) def disable(self): base.taskMgr.remove(self.uniqueName('monitorLocalAvDistance')) self.anim = None self._state = None self.dept = None self.variant = None self.suitPlan = None if self.hpFlash: self.hpFlash.finish() self.hpFlash = None if self.moveIval: self.moveIval.pause() self.moveIval = None Suit.disable(self) DistributedAvatar.disable(self) def delete(self): Suit.delete(self) del self.anim del self._state del self.dept del self.variant del self.suitPlan del self.moveIval DistributedAvatar.delete(self) DistributedSmoothNode.delete(self)
class DistributedEagleSuit(DistributedSuit): notify = directNotify.newCategory('DistributedEagleSuit') def __init__(self, cr): DistributedSuit.__init__(self, cr) self.eagleCry = base.audio3d.loadSfx('phase_5/audio/sfx/tt_s_ara_cfg_eagleCry.mp3') base.audio3d.attachSoundToObject(self.eagleCry, self) self.fallWhistle = base.audio3d.loadSfx('phase_5/audio/sfx/incoming_whistleALT.mp3') base.audio3d.attachSoundToObject(self.fallWhistle, self) self.explode = base.audio3d.loadSfx('phase_3.5/audio/sfx/ENC_cogfall_apart.mp3') base.audio3d.attachSoundToObject(self.explode, self) self.eventSphereNodePath = None self.fallingPropeller = None self.fallingPropProjectile = None self.mg = None self.flySpeed = 0.0 return def enterNeutral(self, ts = 0): self.show() self.timestampAnimTrack = Sequence(Wait(ts), Func(self.loop, 'flyNeutral')) self.timestampAnimTrack.start() def makeStateDict(self): self.suitFSM.addState(State('eagleFly', self.enterEagleFly, self.exitEagleFly)) self.suitFSM.addState(State('eagleFall', self.enterEagleFall, self.exitEagleFall)) self.stateIndex2suitState = {0: self.suitFSM.getStateNamed('off'), 1: self.suitFSM.getStateNamed('walking'), 2: self.suitFSM.getStateNamed('flyingDown'), 3: self.suitFSM.getStateNamed('flyingUp'), 4: self.suitFSM.getStateNamed('lured'), 5: self.suitFSM.getStateNamed('eagleFly'), 6: self.suitFSM.getStateNamed('eagleFall')} self.suitState2stateIndex = {} for stateId, state in self.stateIndex2suitState.items(): self.suitState2stateIndex[state.getName()] = stateId def setFlySpeed(self, value): self.flySpeed = value def getFlySpeed(self): return self.flySpeed def enterEagleFly(self, startIndex, endIndex, ts = 0.0): durationFactor = self.getFlySpeed() if startIndex > -1: startPos = EGG.EAGLE_FLY_POINTS[startIndex] else: startPos = self.getPos(render) endPos = EGG.EAGLE_FLY_POINTS[endIndex] if self.moveIval: self.moveIval.pause() self.moveIval = None self.moveIval = NPCWalkInterval(self, endPos, durationFactor=durationFactor, startPos=startPos, fluid=1) self.moveIval.start(ts) return def exitEagleFly(self): if self.moveIval: self.moveIval.pause() self.moveIval = None return def enterEagleFall(self, startIndex, endIndex, ts = 0.0): self.moveIval = LerpPosInterval(self, duration=4.0, pos=self.getPos(render) - (0, 0, 75), startPos=self.getPos(render), blendType='easeIn') self.moveIval.start(ts) def exitEagleFall(self): if self.moveIval: self.moveIval.finish() self.moveIval = None return def fallAndExplode(self): self.cleanupPropeller() self.fallingPropeller = Actor('phase_4/models/props/propeller-mod.bam', {'chan': 'phase_4/models/props/propeller-chan.bam'}) self.fallingPropeller.reparentTo(render) self.fallingPropeller.loop('chan', fromFrame=0, toFrame=3) parentNode = self.attachNewNode('fallingPropParentNode') h = random.randint(0, 359) parentNode.setH(h) dummyNode = parentNode.attachNewNode('dummyNode') dummyNode.setPos(0, 10, -50) self.fallingPropProjectile = FlightProjectileInterval(self.fallingPropeller, startPos=self.find('**/joint_head').getPos(render), endPos=dummyNode.getPos(render), duration=5.0, gravityMult=0.25) self.fallingPropProjectile.start() dummyNode.removeNode() del dummyNode parentNode.removeNode() del parentNode self.updateHealthBar(0) self.ignoreHit() self.fallWhistle.play() taskMgr.doMethodLater(4.0, self.doExplodeSound, self.uniqueName('DEagleSuit-doExplodeSound')) def doExplodeSound(self, task): self.explode.play() return Task.done 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 removeEventSphere(self): if self.eventSphereNodePath: self.eventSphereNodePath.removeNode() self.eventSphereNodePath = None return def acceptHit(self): self.acceptOnce('enter' + self.eventSphereNodePath.node().getName(), self.__handleHit) def ignoreHit(self): self.ignore('enter' + self.eventSphereNodePath.node().getName()) def __handleHit(self, entry): messenger.send(EGG.EAGLE_HIT_EVENT, [self.doId]) def setSuit(self, arg, variant): DistributedSuit.setSuit(self, arg, 3) self.deleteShadow() self.disableBodyCollisions() self.disableRay() self.__initializeEventSphere() self.show() self.setAnimState('flyNeutral') def __doEagleCry(self, task): self.eagleCry.play() task.delayTime = random.uniform(3, 30) return Task.again def announceGenerate(self): DistributedSuit.announceGenerate(self) taskMgr.doMethodLater(random.uniform(5, 25), self.__doEagleCry, self.uniqueName('DEagleSuit-doEagleCry')) self.acceptHit() def disable(self): self.ignoreHit() self.removeEventSphere() taskMgr.remove(self.uniqueName('DEagleSuit-doExplodeSound')) taskMgr.remove(self.uniqueName('DEagleSuit-doEagleCry')) if self.fallingPropProjectile: self.fallingPropProjectile.finish() self.fallingPropProjectile = None if self.fallingPropeller: self.fallingPropeller.cleanup() self.fallingPropeller = None base.audio3d.detachSound(self.fallWhistle) del self.fallWhistle base.audio3d.detachSound(self.explode) del self.explode base.audio3d.detachSound(self.eagleCry) del self.eagleCry self.mg = None DistributedSuit.disable(self) return
class ParticleAttack(Attack): notify = directNotify.newCategory('ParticleAttack') attack = 'particleattack' particleIvalDur = 1 shooterDistance = 50 def __init__(self, attacksClass, suit): Attack.__init__(self, attacksClass, suit) self.particles = [] self.handObj = None self.shootOutCollNP = None self.particleSound = None self.particleMoveIval = None self.targetX = None self.targetY = None self.targetZ = None return def handleWeaponTouch(self): pass def handleCollision(self, entry): if self.suit: self.suit.sendUpdate('toonHitByWeapon', [self.getAttackId(self.attack), base.localAvatar.doId]) base.localAvatar.b_handleSuitAttack(self.getAttackId(self.attack), self.suit.doId) 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 releaseAttack(self, releaseFromJoint, onlyMoveColl=True, blendType='noBlend'): startNP = releaseFromJoint.attachNewNode('startNP') if None not in [self.targetX, self.targetY, self.targetZ]: startNP.lookAt(render, self.targetX, self.targetY, self.targetZ + 2) pathNP = NodePath('path') pathNP.reparentTo(startNP) pathNP.setScale(render, 1.0) pathNP.setPos(0, self.shooterDistance, 0) for particle in self.particles: if not onlyMoveColl: particle.start(render) else: particle.start(self.suit) particle.lookAt(pathNP) if self.attack == 'razzledazzle': particle.setP(particle, 90) if onlyMoveColl: target = self.shootOutCollNP target.wrtReparentTo(render) else: target = self.particles[0] self.particleMoveIval = LerpPosInterval(target, duration=self.particleIvalDur, pos=pathNP.getPos(render), startPos=startNP.getPos(render), blendType=blendType) self.particleMoveIval.start() self.acceptOnce('enter' + self.shootOutCollNP.node().getName(), self.handleCollision) pathNP.removeNode() startNP.removeNode() del pathNP del startNP self.playParticleSound() return def playParticleSound(self): if self.particleSound: base.audio3d.attachSoundToObject(self.particleSound, self.suit) base.playSfx(self.particleSound) def cleanup(self): Attack.cleanup(self) self.targetX = None self.targetY = None self.targetZ = None if self.particles: for particle in self.particles: particle.cleanup() self.particles = None if self.handObj: self.handObj.removeNode() self.handObj = None if self.shootOutCollNP: self.ignore('enter' + self.shootOutCollNP.node().getName()) self.shootOutCollNP.removeNode() self.shootOutCollNP = None if self.particleMoveIval: self.particleMoveIval.pause() self.particleMoveIval = None self.particleSound = None self.particleIvalDur = None return
class HangUpAttack(Attack): notify = directNotify.newCategory('HangUpAttack') attack = 'hangup' def __init__(self, attacksClass, suit): Attack.__init__(self, attacksClass, suit) self.phone = None self.receiver = None self.collNP = None self.phoneSfx = None self.hangupSfx = None self.shootIval = None self.cord = None self.receiverOutCord = None self.phoneOutCord = None return 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 doAttack(self, ts=0): self.loadAttack() if hasattr(self.suit, 'uniqueName'): name = self.suit.uniqueName('doHangupAttack') else: name = 'doHangupAttack' if self.suit.type == 'A': delay2playSound = 1.0 delayAfterSoundToPlaceDownReceiver = 0.2 delayAfterShootToIgnoreCollisions = 1.0 delay2PickUpReceiver = 1.0 receiverInHandPos = Point3(-0.5, 0.5, -1) else: if self.suit.type == 'B': delay2playSound = 1.5 delayAfterSoundToPlaceDownReceiver = 0.7 delayAfterShootToIgnoreCollisions = 1.0 delay2PickUpReceiver = 1.5 receiverInHandPos = Point3(-0.3, 0.5, -0.8) else: if self.suit.type == 'C': delay2playSound = 1.0 delayAfterSoundToPlaceDownReceiver = 1.15 delayAfterShootToIgnoreCollisions = 1.0 delay2PickUpReceiver = 1.5 receiverInHandPos = Point3(-0.3, 0.5, -0.8) self.suitTrack = Parallel(name=name) self.suitTrack.append(ActorInterval(self.suit, 'phone')) self.suitTrack.append(Sequence(Wait(delay2playSound), SoundInterval(self.phoneSfx, duration=2.1), Wait(delayAfterSoundToPlaceDownReceiver), Func(self.receiver.setPos, 0, 0, 0), Func(self.receiver.setH, 0.0), Func(self.receiver.reparentTo, self.phone), Func(self.acceptOnce, 'enter' + self.collNP.node().getName(), self.handleCollision), Func(self.shootOut), Parallel(SoundInterval(self.hangupSfx), Sequence(Wait(delayAfterShootToIgnoreCollisions), Func(self.ignore, 'enter' + self.collNP.node().getName()))))) self.suitTrack.append(Sequence(Func(self.phone.reparentTo, self.suit.find('**/joint_Lhold')), Func(self.cord.reparentTo, render), Wait(delay2PickUpReceiver), Func(self.receiver.reparentTo, self.suit.find('**/joint_Rhold')), Func(self.receiver.setPos, receiverInHandPos), Func(self.receiver.setH, 270.0))) self.suitTrack.setDoneEvent(self.suitTrack.getName()) self.acceptOnce(self.suitTrack.getDoneEvent(), self.finishedAttack) self.suitTrack.delayDelete = DelayDelete.DelayDelete(self.suit, name) self.suitTrack.start(ts) def handleCollision(self, entry): if self.suit: self.suit.sendUpdate('toonHitByWeapon', [self.getAttackId(self.attack), base.localAvatar.doId]) base.localAvatar.b_handleSuitAttack(self.getAttackId(self.attack), self.suit.doId) def shootOut(self): pathNode = NodePath('path') pathNode.reparentTo(self.suit) pathNode.setPos(0, 50, self.phone.getZ(self.suit)) self.collNP.reparentTo(render) self.shootIval = LerpPosInterval(self.collNP, duration=1.0, pos=pathNode.getPos(render), startPos=self.phone.getPos(render)) self.shootIval.start() pathNode.removeNode() del pathNode def cleanup(self): Attack.cleanup(self) if self.shootIval: self.shootIval.pause() self.shootIval = None if self.cord: self.cord.removeNode() self.cord = None if self.phone: self.phone.removeNode() self.phone = None if self.receiver: self.receiver.removeNode() self.receiver = None if self.collNP: self.collNP.node().clearSolids() self.collNP.removeNode() self.collNP = None if self.phoneSfx: self.phoneSfx.stop() self.phoneSfx = None return
class ThrowAttack(Attack): notify = directNotify.newCategory('ThrowAttack') attack = 'throw' def __init__(self, attacksClass, suit): Attack.__init__(self, attacksClass, suit) self.weapon_state = None self.weapon = None self.wss = None self.wsnp = None self.suitTrack = None self.weaponSfx = None self.throwTrajectory = None self.targetX = None self.targetY = None self.targetZ = None self.startNP = None return def handleWeaponCollision(self, entry): if self.suit: self.suit.sendUpdate('toonHitByWeapon', [self.getAttackId(self.attack), base.localAvatar.doId]) base.localAvatar.b_handleSuitAttack(self.getAttackId(self.attack), self.suit.doId) self.suit.b_handleWeaponTouch() 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 playWeaponSound(self): if self.weapon and self.weaponSfx: base.audio3d.attachSoundToObject(self.weaponSfx, self.suit) self.weaponSfx.play() def throwObject(self, projectile=True): if not self.weapon: return self.acceptOnce('enter' + self.wsnp.node().getName(), self.handleWeaponCollision) self.playWeaponSound() if self.weapon: self.weapon.wrtReparentTo(render) self.weapon.setHpr(Vec3(0, 0, 0)) if self.attack not in ('glowerpower', ): parent = self.suit.find('**/joint_Rhold') else: parent = self.suit.find('**/joint_head') startNP = parent.attachNewNode('startNp') startNP.lookAt(render, self.targetX, self.targetY, self.targetZ) pathNP = NodePath('throwPath') pathNP.reparentTo(startNP) pathNP.setScale(render, 1.0) pathNP.setPos(0, 50, 0) if self.attack in ('clipontie', 'powertie', 'halfwindsor'): self.weapon.setHpr(pathNP.getHpr(render)) if projectile == True: self.throwTrajectory = ProjectileInterval(self.weapon, startPos=self.suit.find('**/joint_Rhold').getPos(render), endPos=pathNP.getPos(render), gravityMult=0.7, duration=1.0) else: self.weapon.setH(pathNP.getH(render)) self.throwTrajectory = LerpPosInterval(self.weapon, duration=0.5, pos=pathNP.getPos(render), startPos=startNP.getPos(render) + (0, 3, 0)) self.throwTrajectory.start() self.weapon_state = 'released' startNP.removeNode() del startNP pathNP.removeNode() del pathNP def interruptAttack(self): if self.throwTrajectory: if self.throwTrajectory.isStopped(): self.delWeapon() def handleWeaponTouch(self): if self.throwTrajectory: self.throwTrajectory.pause() self.throwTrajectory = None self.delWeapon() return def delWeapon(self): if self.weapon: self.weapon.removeNode() self.weapon = None return def cleanup(self): Attack.cleanup(self) self.targetX = None self.targetY = None self.targetZ = None self.weapon_state = None if self.weaponSfx: self.weaponSfx.stop() self.weaponSfx = None if self.throwTrajectory: self.throwTrajectory.pause() self.throwTrajectory = None self.delWeapon() self.wss = None if self.wsnp: self.wsnp.node().clearSolids() self.wsnp.removeNode() self.wsnp = None return