from direct.directnotify import DirectNotifyGlobal from direct.fsm import FSM from direct.interval.IntervalGlobal import * from direct.task.Task import Task from direct.task.TaskManagerGlobal import * import math from panda3d.core import * import random import DistributedBossCog import DistributedCashbotBossGoon import SuitDNA from otp.otpbase import OTPGlobals from toontown.battle import MovieToonVictory from toontown.battle import RewardPanel from toontown.battle import SuitBattleGlobals from toontown.building import ElevatorConstants from toontown.building import ElevatorUtils from toontown.chat import ResistanceChat from toontown.coghq import CogDisguiseGlobals from toontown.distributed import DelayDelete from toontown.toon import Toon from toontown.toon import ToonDNA from toontown.toonbase import TTLocalizer from toontown.toonbase import ToontownGlobals from otp.nametag import NametagGroup from otp.nametag.NametagConstants import * from otp.nametag import NametagGlobals OneBossCog = None TTL = TTLocalizer class DistributedCashbotBoss(DistributedBossCog.DistributedBossCog, FSM.FSM): notify = DirectNotifyGlobal.directNotify.newCategory('DistributedCashbotBoss') numFakeGoons = 3 def __init__(self, cr): DistributedBossCog.DistributedBossCog.__init__(self, cr) FSM.FSM.__init__(self, 'DistributedSellbotBoss') self.resistanceToon = None self.resistanceToonOnstage = 0 self.cranes = {} self.safes = {} self.goons = [] self.bossMaxDamage = ToontownGlobals.CashbotBossMaxDamage self.elevatorType = ElevatorConstants.ELEVATOR_CFO base.boss = self return def announceGenerate(self): DistributedBossCog.DistributedBossCog.announceGenerate(self) self.setName(TTLocalizer.CashbotBossName) nameInfo = TTLocalizer.BossCogNameWithDept % {'name': self.name, 'dept': SuitDNA.getDeptFullname(self.style.dept)} self.setDisplayName(nameInfo) target = CollisionSphere(2, 0, 0, 3) targetNode = CollisionNode('headTarget') targetNode.addSolid(target) targetNode.setCollideMask(ToontownGlobals.PieBitmask) self.headTarget = self.neck.attachNewNode(targetNode) shield = CollisionSphere(0, 0, 0.8, 7) shieldNode = CollisionNode('shield') shieldNode.addSolid(shield) shieldNode.setCollideMask(ToontownGlobals.PieBitmask) shieldNodePath = self.pelvis.attachNewNode(shieldNode) self.heldObject = None self.bossDamage = 0 self.intermissionMusic = base.loadMusic('phase_9/audio/bgm/CBHQ_Boss_intermission.ogg') self.loadEnvironment() self.__makeResistanceToon() self.physicsMgr = PhysicsManager() integrator = LinearEulerIntegrator() self.physicsMgr.attachLinearIntegrator(integrator) fn = ForceNode('gravity') self.fnp = self.geom.attachNewNode(fn) gravity = LinearVectorForce(0, 0, -32) fn.addForce(gravity) self.physicsMgr.addLinearForce(gravity) base.localAvatar.chatMgr.chatInputSpeedChat.addCFOMenu() global OneBossCog if OneBossCog != None: self.notify.warning('Multiple BossCogs visible.') OneBossCog = self return def disable(self): global OneBossCog DistributedBossCog.DistributedBossCog.disable(self) self.demand('Off') self.unloadEnvironment() self.__cleanupResistanceToon() self.fnp.removeNode() self.physicsMgr.clearLinearForces() self.battleThreeMusic.stop() self.intermissionMusic.stop() self.epilogueMusic.stop() base.localAvatar.chatMgr.chatInputSpeedChat.removeCFOMenu() if OneBossCog == self: OneBossCog = None return def __makeResistanceToon(self): if self.resistanceToon: return npc = Toon.Toon() npc.setName(TTLocalizer.ResistanceToonName) npc.setPickable(0) npc.setPlayerType(NametagGroup.CCNonPlayer) dna = ToonDNA.ToonDNA() dna.newToonRandom(11237, 'f', 1) dna.head = 'pls' npc.setDNAString(dna.makeNetString()) npc.animFSM.request('neutral') self.resistanceToon = npc self.resistanceToon.setPosHpr(*ToontownGlobals.CashbotRTBattleOneStartPosHpr) state = random.getstate() random.seed(self.doId) self.resistanceToon.suitType = SuitDNA.getRandomSuitByDept('m') random.setstate(state) self.fakeGoons = [] for i in xrange(self.numFakeGoons): goon = DistributedCashbotBossGoon.DistributedCashbotBossGoon(base.cr) goon.doId = -1 - i goon.setBossCogId(self.doId) goon.generate() goon.announceGenerate() self.fakeGoons.append(goon) self.__hideFakeGoons() def __cleanupResistanceToon(self): self.__hideResistanceToon() if self.resistanceToon: self.resistanceToon.removeActive() self.resistanceToon.delete() self.resistanceToon = None for i in xrange(self.numFakeGoons): self.fakeGoons[i].disable() self.fakeGoons[i].delete() self.fakeGoons[i] = None return def __showResistanceToon(self, withSuit): if not self.resistanceToonOnstage: self.resistanceToon.addActive() self.resistanceToon.reparentTo(self.geom) self.resistanceToonOnstage = 1 if withSuit: suit = self.resistanceToon.suitType self.resistanceToon.putOnSuit(suit, False) else: self.resistanceToon.takeOffSuit() def __hideResistanceToon(self): if self.resistanceToonOnstage: self.resistanceToon.removeActive() self.resistanceToon.detachNode() self.resistanceToonOnstage = 0 def __hideFakeGoons(self): if self.fakeGoons: for goon in self.fakeGoons: goon.request('Off') def __showFakeGoons(self, state): if self.fakeGoons: for goon in self.fakeGoons: goon.request(state) def loadEnvironment(self): DistributedBossCog.DistributedBossCog.loadEnvironment(self) self.midVault = loader.loadModel('phase_10/models/cogHQ/MidVault.bam') self.endVault = loader.loadModel('phase_10/models/cogHQ/EndVault.bam') self.lightning = loader.loadModel('phase_10/models/cogHQ/CBLightning.bam') self.magnet = loader.loadModel('phase_10/models/cogHQ/CBMagnet.bam') self.craneArm = loader.loadModel('phase_10/models/cogHQ/CBCraneArm.bam') self.controls = loader.loadModel('phase_10/models/cogHQ/CBCraneControls.bam') self.stick = loader.loadModel('phase_10/models/cogHQ/CBCraneStick.bam') self.safe = loader.loadModel('phase_10/models/cogHQ/CBSafe.bam') self.eyes = loader.loadModel('phase_10/models/cogHQ/CashBotBossEyes.bam') self.cableTex = self.craneArm.findTexture('MagnetControl') self.eyes.setPosHprScale(4.5, 0, -2.5, 90, 90, 0, 0.4, 0.4, 0.4) self.eyes.reparentTo(self.neck) self.eyes.hide() self.midVault.setPos(0, -222, -70.7) self.endVault.setPos(84, -201, -6) self.geom = NodePath('geom') self.midVault.reparentTo(self.geom) self.endVault.reparentTo(self.geom) self.endVault.findAllMatches('**/MagnetArms').detach() self.endVault.findAllMatches('**/Safes').detach() self.endVault.findAllMatches('**/MagnetControlsAll').detach() cn = self.endVault.find('**/wallsCollision').node() cn.setIntoCollideMask(OTPGlobals.WallBitmask | ToontownGlobals.PieBitmask) self.door1 = self.midVault.find('**/SlidingDoor1/') self.door2 = self.midVault.find('**/SlidingDoor/') self.door3 = self.endVault.find('**/SlidingDoor/') elevatorModel = loader.loadModel('phase_10/models/cogHQ/CFOElevator') elevatorOrigin = self.midVault.find('**/elevator_origin') elevatorOrigin.setScale(1) elevatorModel.reparentTo(elevatorOrigin) leftDoor = elevatorModel.find('**/left_door') leftDoor.setName('left-door') rightDoor = elevatorModel.find('**/right_door') rightDoor.setName('right-door') self.setupElevator(elevatorOrigin) ElevatorUtils.closeDoors(leftDoor, rightDoor, ElevatorConstants.ELEVATOR_CFO) walls = self.endVault.find('**/RollUpFrameCillison') walls.detachNode() self.evWalls = self.replaceCollisionPolysWithPlanes(walls) self.evWalls.reparentTo(self.endVault) self.evWalls.stash() floor = self.endVault.find('**/EndVaultFloorCollision') floor.detachNode() self.evFloor = self.replaceCollisionPolysWithPlanes(floor) self.evFloor.reparentTo(self.endVault) self.evFloor.setName('floor') plane = CollisionPlane(Plane(Vec3(0, 0, 1), Point3(0, 0, -50))) planeNode = CollisionNode('dropPlane') planeNode.addSolid(plane) planeNode.setCollideMask(ToontownGlobals.PieBitmask) self.geom.attachNewNode(planeNode) self.geom.reparentTo(render) def unloadEnvironment(self): DistributedBossCog.DistributedBossCog.unloadEnvironment(self) self.geom.removeNode() def replaceCollisionPolysWithPlanes(self, model): newCollisionNode = CollisionNode('collisions') newCollideMask = BitMask32(0) planes = [] collList = model.findAllMatches('**/+CollisionNode') if not collList: collList = [model] for cnp in collList: cn = cnp.node() if not isinstance(cn, CollisionNode): self.notify.warning('Not a collision node: %s' % repr(cnp)) break newCollideMask = newCollideMask | cn.getIntoCollideMask() for i in xrange(cn.getNumSolids()): solid = cn.getSolid(i) if isinstance(solid, CollisionPolygon): plane = Plane(solid.getPlane()) planes.append(plane) else: self.notify.warning('Unexpected collision solid: %s' % repr(solid)) newCollisionNode.addSolid(plane) newCollisionNode.setIntoCollideMask(newCollideMask) threshold = 0.1 planes.sort(lambda p1, p2: p1.compareTo(p2, threshold)) lastPlane = None for plane in planes: if lastPlane == None or plane.compareTo(lastPlane, threshold) != 0: cp = CollisionPlane(plane) newCollisionNode.addSolid(cp) lastPlane = plane return NodePath(newCollisionNode) def __makeGoonMovieForIntro(self): goonTrack = Parallel() goon = self.fakeGoons[0] goonTrack.append(Sequence( goon.posHprInterval(0, Point3(111, -287, 0), VBase3(165, 0, 0)), goon.posHprInterval(9, Point3(101, -323, 0), VBase3(165, 0, 0)), goon.hprInterval(1, VBase3(345, 0, 0)), goon.posHprInterval(9, Point3(111, -287, 0), VBase3(345, 0, 0)), goon.hprInterval(1, VBase3(165, 0, 0)), goon.posHprInterval(9.5, Point3(104, -316, 0), VBase3(165, 0, 0)), Func(goon.request, 'Stunned'), Wait(1))) goon = self.fakeGoons[1] goonTrack.append(Sequence( goon.posHprInterval(0, Point3(119, -315, 0), VBase3(357, 0, 0)), goon.posHprInterval(9, Point3(121, -280, 0), VBase3(357, 0, 0)), goon.hprInterval(1, VBase3(177, 0, 0)), goon.posHprInterval(9, Point3(119, -315, 0), VBase3(177, 0, 0)), goon.hprInterval(1, VBase3(357, 0, 0)), goon.posHprInterval(9, Point3(121, -280, 0), VBase3(357, 0, 0)))) goon = self.fakeGoons[2] goonTrack.append(Sequence( goon.posHprInterval(0, Point3(102, -320, 0), VBase3(231, 0, 0)), goon.posHprInterval(9, Point3(127, -337, 0), VBase3(231, 0, 0)), goon.hprInterval(1, VBase3(51, 0, 0)), goon.posHprInterval(9, Point3(102, -320, 0), VBase3(51, 0, 0)), goon.hprInterval(1, VBase3(231, 0, 0)), goon.posHprInterval(9, Point3(127, -337, 0), VBase3(231, 0, 0)))) return Sequence(Func(self.__showFakeGoons, 'Walk'), goonTrack, Func(self.__hideFakeGoons)) def makeIntroductionMovie(self, delayDeletes): for toonId in self.involvedToons: toon = self.cr.doId2do.get(toonId) if toon: delayDeletes.append(DelayDelete.DelayDelete(toon, 'CashbotBoss.makeIntroductionMovie')) rtTrack = Sequence() startPos = Point3(ToontownGlobals.CashbotBossOffstagePosHpr[0], ToontownGlobals.CashbotBossOffstagePosHpr[1], ToontownGlobals.CashbotBossOffstagePosHpr[2]) battlePos = Point3(ToontownGlobals.CashbotBossBattleOnePosHpr[0], ToontownGlobals.CashbotBossBattleOnePosHpr[1], ToontownGlobals.CashbotBossBattleOnePosHpr[2]) battleHpr = VBase3(ToontownGlobals.CashbotBossBattleOnePosHpr[3], ToontownGlobals.CashbotBossBattleOnePosHpr[4], ToontownGlobals.CashbotBossBattleOnePosHpr[5]) bossTrack = Sequence() bossTrack.append(Func(self.reparentTo, render)) bossTrack.append(Func(self.getGeomNode().setH, 180)) bossTrack.append(Func(self.pelvis.setHpr, self.pelvisForwardHpr)) bossTrack.append(Func(self.loop, 'Ff_neutral')) track, hpr = self.rollBossToPoint(startPos, None, battlePos, None, 0) bossTrack.append(track) track, hpr = self.rollBossToPoint(battlePos, hpr, battlePos, battleHpr, 0) bossTrack.append(track) bossTrack.append(Func(self.getGeomNode().setH, 0)) bossTrack.append(Func(self.pelvis.setHpr, self.pelvisReversedHpr)) goonTrack = self.__makeGoonMovieForIntro() attackToons = TTL.CashbotBossCogAttack rToon = self.resistanceToon rToon.setPosHpr(*ToontownGlobals.CashbotRTBattleOneStartPosHpr) track = Sequence( Func(base.camera.setPosHpr, 82, -219, 5, 267, 0, 0), Func(rToon.setChatAbsolute, TTL.ResistanceToonWelcome, CFSpeech), Wait(3), Sequence(goonTrack, duration=0), Parallel( base.camera.posHprInterval(4, Point3(108, -244, 4), VBase3(211.5, 0, 0)), Sequence( Func(rToon.suit.setPlayRate, 1.4, 'walk'), Func(rToon.suit.loop, 'walk'), Parallel( rToon.hprInterval(1, VBase3(180, 0, 0)), rToon.posInterval(3, VBase3(120, -255, 0)), Sequence( Wait(2), Func(rToon.clearChat))), Func(rToon.suit.loop, 'neutral'), self.door2.posInterval(3, VBase3(0, 0, 30)))), Func(rToon.setHpr, 0, 0, 0), Func(rToon.setChatAbsolute, TTL.ResistanceToonTooLate, CFSpeech), Func(base.camera.reparentTo, render), Func(base.camera.setPosHpr, 61.1, -228.8, 10.2, -90, 0, 0), self.door1.posInterval(2, VBase3(0, 0, 30)), Parallel( bossTrack, Sequence( Wait(3), Func(rToon.clearChat), self.door1.posInterval(3, VBase3(0, 0, 0)))), Func(self.setChatAbsolute, TTL.CashbotBossDiscoverToons1, CFSpeech), base.camera.posHprInterval(1.5, Point3(93.3, -230, 0.7), VBase3(-92.9, 39.7, 8.3)), Func(self.setChatAbsolute, TTL.CashbotBossDiscoverToons2, CFSpeech), Wait(4), Func(self.clearChat), self.loseCogSuits(self.toonsA + self.toonsB, render, (113, -228, 10, 90, 0, 0)), Wait(1), Func(rToon.setHpr, 0, 0, 0), self.loseCogSuits([rToon], render, (133, -243, 5, 143, 0, 0), True), Func(rToon.setChatAbsolute, TTL.ResistanceToonKeepHimBusy, CFSpeech), Wait(1), Func(self.__showResistanceToon, False), Sequence( Func(rToon.animFSM.request, 'run'), rToon.hprInterval(1, VBase3(180, 0, 0)), Parallel( Sequence( rToon.posInterval(1.5, VBase3(109, -294, 0)), Parallel(Func(rToon.animFSM.request, 'jump')), rToon.posInterval(1.5, VBase3(93.935, -341.065, 2))), self.door2.posInterval(3, VBase3(0, 0, 0))), Func(rToon.animFSM.request, 'neutral')), self.toonNormalEyes(self.involvedToons), self.toonNormalEyes([self.resistanceToon], True), Func(rToon.clearChat), Func(base.camera.setPosHpr, 93.3, -230, 0.7, -92.9, 39.7, 8.3), Func(self.setChatAbsolute, attackToons, CFSpeech), Wait(2), Func(self.clearChat)) return Sequence(Func(base.camera.reparentTo, render), track) def __makeGoonMovieForBattleThree(self): goonPosHprs = [[Point3(111, -287, 0), VBase3(165, 0, 0), Point3(101, -323, 0), VBase3(165, 0, 0)], [Point3(119, -315, 0), VBase3(357, 0, 0), Point3(121, -280, 0), VBase3(357, 0, 0)], [Point3(102, -320, 0), VBase3(231, 0, 0), Point3(127, -337, 0), VBase3(231, 0, 0)]] mainGoon = self.fakeGoons[0] goonLoop = Parallel() for i in xrange(1, self.numFakeGoons): goon = self.fakeGoons[i] goonLoop.append(Sequence(goon.posHprInterval(8, goonPosHprs[i][0], goonPosHprs[i][1]), goon.posHprInterval(8, goonPosHprs[i][2], goonPosHprs[i][3]))) goonTrack = Sequence(Func(self.__showFakeGoons, 'Walk'), Func(mainGoon.request, 'Stunned'), Func(goonLoop.loop), Wait(20)) return goonTrack def makePrepareBattleThreeMovie(self, delayDeletes, crane, safe): for toonId in self.involvedToons: toon = self.cr.doId2do.get(toonId) if toon: delayDeletes.append(DelayDelete.DelayDelete(toon, 'CashbotBoss.makePrepareBattleThreeMovie')) startPos = Point3(ToontownGlobals.CashbotBossBattleOnePosHpr[0], ToontownGlobals.CashbotBossBattleOnePosHpr[1], ToontownGlobals.CashbotBossBattleOnePosHpr[2]) battlePos = Point3(ToontownGlobals.CashbotBossBattleThreePosHpr[0], ToontownGlobals.CashbotBossBattleThreePosHpr[1], ToontownGlobals.CashbotBossBattleThreePosHpr[2]) startHpr = Point3(ToontownGlobals.CashbotBossBattleOnePosHpr[3], ToontownGlobals.CashbotBossBattleOnePosHpr[4], ToontownGlobals.CashbotBossBattleOnePosHpr[5]) battleHpr = VBase3(ToontownGlobals.CashbotBossBattleThreePosHpr[3], ToontownGlobals.CashbotBossBattleThreePosHpr[4], ToontownGlobals.CashbotBossBattleThreePosHpr[5]) finalHpr = VBase3(135, 0, 0) bossTrack = Sequence() bossTrack.append(Func(base.playMusic, self.intermissionMusic, 1, 0.9)) bossTrack.append(Func(self.reparentTo, render)) bossTrack.append(Func(self.getGeomNode().setH, 180)) bossTrack.append(Func(self.pelvis.setHpr, self.pelvisForwardHpr)) bossTrack.append(Func(self.loop, 'Ff_neutral')) track, hpr = self.rollBossToPoint(startPos, startHpr, startPos, battleHpr, 0) bossTrack.append(track) track, hpr = self.rollBossToPoint(startPos, None, battlePos, None, 0) bossTrack.append(track) track, hpr = self.rollBossToPoint(battlePos, battleHpr, battlePos, finalHpr, 0) bossTrack.append(track) rToon = self.resistanceToon rToon.setPosHpr(93.935, -341.065, 0, -45, 0, 0) goon = self.fakeGoons[0] crane = self.cranes[0] track = Sequence( Func(self.__hideToons), Func(crane.request, 'Movie'), Func(crane.accomodateToon, rToon), Func(goon.request, 'Stunned'), Func(goon.setPosHpr, 104, -316, 0, 165, 0, 0), Parallel( self.door2.posInterval(4.5, VBase3(0, 0, 30)), self.door3.posInterval(4.5, VBase3(0, 0, 30)), bossTrack), Func(rToon.loop, 'leverNeutral'), Func(base.camera.reparentTo, self.geom), Func(base.camera.setPosHpr, 105, -326, 5, 136.3, 0, 0), Func(rToon.setChatAbsolute, TTL.ResistanceToonWatchThis, CFSpeech), Wait(2), Func(rToon.clearChat), Func(base.camera.setPosHpr, 105, -326, 20, -45.3, 11, 0), Func(self.setChatAbsolute, TTL.CashbotBossGetAwayFromThat, CFSpeech), Wait(2), Func(self.clearChat), base.camera.posHprInterval(1.5, Point3(105, -326, 5), Point3(136.3, 0, 0), blendType='easeInOut'), Func(rToon.setChatAbsolute, TTL.ResistanceToonCraneInstructions1, CFSpeech), Wait(4), Func(rToon.setChatAbsolute, TTL.ResistanceToonCraneInstructions2, CFSpeech), Wait(4), Func(rToon.setChatAbsolute, TTL.ResistanceToonCraneInstructions3, CFSpeech), Wait(4), Func(rToon.setChatAbsolute, TTL.ResistanceToonCraneInstructions4, CFSpeech), Wait(4), Func(rToon.clearChat), Func(base.camera.setPosHpr, 102, -323.6, 0.9, -10.6, 14, 0), Func(goon.request, 'Recovery'), Wait(2), Func(base.camera.setPosHpr, 95.4, -332.6, 4.2, 167.1, -13.2, 0), Func(rToon.setChatAbsolute, TTL.ResistanceToonGetaway, CFSpeech), Func(rToon.animFSM.request, 'jump'), Wait(1.8), Func(rToon.clearChat), Func(base.camera.setPosHpr, 109.1, -300.7, 13.9, -15.6, -13.6, 0), Func(rToon.animFSM.request, 'run'), Func(goon.request, 'Walk'), Parallel( self.door3.posInterval(3, VBase3(0, 0, 0)), rToon.posHprInterval(3, Point3(136, -212.9, 0), VBase3(-14, 0, 0), startPos=Point3(110.8, -292.7, 0), startHpr=VBase3(-14, 0, 0)), goon.posHprInterval(3, Point3(125.2, -243.5, 0), VBase3(-14, 0, 0), startPos=Point3(104.8, -309.5, 0), startHpr=VBase3(-14, 0, 0))), Func(self.__hideFakeGoons), Func(self.intermissionMusic.stop), Func(crane.request, 'Free'), Func(self.getGeomNode().setH, 0), self.moveToonsToBattleThreePos(self.involvedToons), Func(self.__showToons)) return Sequence(Func(base.camera.reparentTo, self), Func(base.camera.setPosHpr, 0, -27, 25, 0, -18, 0), track) def moveToonsToBattleThreePos(self, toons): track = Parallel() for i in xrange(len(toons)): toon = base.cr.doId2do.get(toons[i]) if toon: posHpr = ToontownGlobals.CashbotToonsBattleThreeStartPosHpr[i] pos = Point3(*posHpr[0:3]) hpr = VBase3(*posHpr[3:6]) track.append(toon.posHprInterval(0.2, pos, hpr)) return track def makeBossFleeMovie(self): hadEnough = TTLocalizer.CashbotBossHadEnough outtaHere = TTLocalizer.CashbotBossOuttaHere loco = loader.loadModel('phase_10/models/cogHQ/CashBotLocomotive') car1 = loader.loadModel('phase_10/models/cogHQ/CashBotBoxCar') car2 = loader.loadModel('phase_10/models/cogHQ/CashBotTankCar') trainPassingSfx = base.loadSfx('phase_10/audio/sfx/CBHQ_TRAIN_pass.ogg') boomSfx = loader.loadSfx('phase_3.5/audio/sfx/ENC_cogfall_apart.ogg') rollThroughDoor = self.rollBossToPoint(fromPos=Point3(120, -280, 0), fromHpr=None, toPos=Point3(120, -250, 0), toHpr=None, reverse=0) rollTrack = Sequence(Func(self.getGeomNode().setH, 180), rollThroughDoor[0], Func(self.getGeomNode().setH, 0)) g = 80.0 / 300.0 trainTrack = Track( (0 * g, loco.posInterval(0.5, Point3(0, -242, 0), startPos=Point3(150, -242, 0))), (1 * g, car2.posInterval(0.5, Point3(0, -242, 0), startPos=Point3(150, -242, 0))), (2 * g, car1.posInterval(0.5, Point3(0, -242, 0), startPos=Point3(150, -242, 0))), (3 * g, car2.posInterval(0.5, Point3(0, -242, 0), startPos=Point3(150, -242, 0))), (4 * g, car1.posInterval(0.5, Point3(0, -242, 0), startPos=Point3(150, -242, 0))), (5 * g, car2.posInterval(0.5, Point3(0, -242, 0), startPos=Point3(150, -242, 0))), (6 * g, car1.posInterval(0.5, Point3(0, -242, 0), startPos=Point3(150, -242, 0))), (7 * g, car2.posInterval(0.5, Point3(0, -242, 0), startPos=Point3(150, -242, 0))), (8 * g, car1.posInterval(0.5, Point3(0, -242, 0), startPos=Point3(150, -242, 0))), (9 * g, car2.posInterval(0.5, Point3(0, -242, 0), startPos=Point3(150, -242, 0))), (10 * g, car1.posInterval(0.5, Point3(0, -242, 0), startPos=Point3(150, -242, 0))), (11 * g, car2.posInterval(0.5, Point3(0, -242, 0), startPos=Point3(150, -242, 0))), (12 * g, car1.posInterval(0.5, Point3(0, -242, 0), startPos=Point3(150, -242, 0))), (13 * g, car2.posInterval(0.5, Point3(0, -242, 0), startPos=Point3(150, -242, 0))), (14 * g, car1.posInterval(0.5, Point3(0, -242, 0), startPos=Point3(150, -242, 0)))) bossTrack = Track( (0.0, Sequence( Func(base.camera.reparentTo, render), Func(base.camera.setPosHpr, 105, -280, 20, -158, -3, 0), Func(self.reparentTo, render), Func(self.show), Func(self.clearChat), Func(self.setPosHpr, *ToontownGlobals.CashbotBossBattleThreePosHpr), Func(self.reverseHead), ActorInterval(self, 'Fb_firstHit'), ActorInterval(self, 'Fb_down2Up'))), (1.0, Func(self.setChatAbsolute, hadEnough, CFSpeech)), (5.5, Parallel( Func(base.camera.setPosHpr, 100, -315, 16, -20, 0, 0), Func(self.hideBattleThreeObjects), Func(self.forwardHead), Func(self.loop, 'Ff_neutral'), rollTrack, self.door3.posInterval(2.5, Point3(0, 0, 25), startPos=Point3(0, 0, 18)))), (5.5, Func(self.setChatAbsolute, outtaHere, CFSpeech)), (5.5, SoundInterval(trainPassingSfx)), (8.1, Func(self.clearChat)), (9.4, Sequence( Func(loco.reparentTo, render), Func(car1.reparentTo, render), Func(car2.reparentTo, render), trainTrack, Func(loco.detachNode), Func(car1.detachNode), Func(car2.detachNode), Wait(2))), (9.5, SoundInterval(boomSfx)), (9.5, Sequence( self.posInterval(0.4, Point3(0, -250, 0)), Func(self.stash)))) return bossTrack def grabObject(self, obj): obj.wrtReparentTo(self.neck) obj.hideShadows() obj.stashCollisions() if obj.lerpInterval: obj.lerpInterval.finish() obj.lerpInterval = Parallel(obj.posInterval(ToontownGlobals.CashbotBossToMagnetTime, Point3(-1, 0, 0.2)), obj.quatInterval(ToontownGlobals.CashbotBossToMagnetTime, VBase3(0, -90, 90)), Sequence(Wait(ToontownGlobals.CashbotBossToMagnetTime), ShowInterval(self.eyes)), obj.toMagnetSoundInterval) obj.lerpInterval.start() self.heldObject = obj def dropObject(self, obj): if obj.lerpInterval: obj.lerpInterval.finish() obj.lerpInterval = None obj = self.heldObject obj.wrtReparentTo(render) obj.setHpr(obj.getH(), 0, 0) self.eyes.hide() obj.showShadows() obj.unstashCollisions() self.heldObject = None return def setBossDamage(self, bossDamage): if bossDamage > self.bossDamage: delta = bossDamage - self.bossDamage self.flashRed() self.doAnimate('hit', now=1) self.showHpText(-delta, scale=5) self.bossDamage = bossDamage self.updateHealthBar() def setRewardId(self, rewardId): self.rewardId = rewardId def d_applyReward(self): self.sendUpdate('applyReward', []) def stunAllGoons(self): for goon in self.goons: if goon.state == 'Walk' or goon.state == 'Battle': goon.demand('Stunned') goon.sendUpdate('requestStunned', [0]) def destroyAllGoons(self): for goon in self.goons: if goon.state != 'Off' and not goon.isDead: goon.b_destroyGoon() def deactivateCranes(self): for crane in self.cranes.values(): crane.demand('Free') def hideBattleThreeObjects(self): for goon in self.goons: goon.demand('Off') for safe in self.safes.values(): safe.demand('Off') for crane in self.cranes.values(): crane.demand('Off') def __doPhysics(self, task): dt = globalClock.getDt() self.physicsMgr.doPhysics(dt) return Task.cont def __hideToons(self): for toonId in self.involvedToons: toon = self.cr.doId2do.get(toonId) if toon: toon.hide() def __showToons(self): for toonId in self.involvedToons: toon = self.cr.doId2do.get(toonId) if toon: toon.show() def __arrangeToonsAroundResistanceToon(self): radius = 7 numToons = len(self.involvedToons) center = (numToons - 1) / 2.0 for i in xrange(numToons): toon = self.cr.doId2do.get(self.involvedToons[i]) if toon: angle = 90 - 15 * (i - center) radians = angle * math.pi / 180.0 x = math.cos(radians) * radius y = math.sin(radians) * radius toon.setPos(self.resistanceToon, x, y, 0) toon.headsUp(self.resistanceToon) toon.loop('neutral') toon.show() def __talkAboutPromotion(self, speech): if self.prevCogSuitLevel < ToontownGlobals.MaxCogSuitLevel: newCogSuitLevel = localAvatar.getCogLevels()[CogDisguiseGlobals.dept2deptIndex(self.style.dept)] if newCogSuitLevel == ToontownGlobals.MaxCogSuitLevel: speech += TTLocalizer.ResistanceToonLastPromotion % (ToontownGlobals.MaxCogSuitLevel + 1) if newCogSuitLevel in ToontownGlobals.CogSuitHPLevels: speech += TTLocalizer.ResistanceToonHPBoost else: speech += TTLocalizer.ResistanceToonMaxed % (ToontownGlobals.MaxCogSuitLevel + 1) return speech def enterOff(self): DistributedBossCog.DistributedBossCog.enterOff(self) if self.resistanceToon: self.resistanceToon.clearChat() def enterWaitForToons(self): DistributedBossCog.DistributedBossCog.enterWaitForToons(self) self.detachNode() self.geom.hide() self.resistanceToon.removeActive() def exitWaitForToons(self): DistributedBossCog.DistributedBossCog.exitWaitForToons(self) self.geom.show() self.resistanceToon.addActive() def enterElevator(self): DistributedBossCog.DistributedBossCog.enterElevator(self) self.detachNode() self.resistanceToon.removeActive() self.endVault.stash() self.midVault.unstash() self.__showResistanceToon(True) base.camLens.setMinFov(ToontownGlobals.CFOElevatorFov/(4./3.)) def exitElevator(self): DistributedBossCog.DistributedBossCog.exitElevator(self) self.resistanceToon.addActive() def enterIntroduction(self): self.detachNode() self.stopAnimate() self.endVault.unstash() self.evWalls.stash() self.midVault.unstash() self.__showResistanceToon(True) base.playMusic(self.stingMusic, looping=1, volume=0.9) DistributedBossCog.DistributedBossCog.enterIntroduction(self) def exitIntroduction(self): DistributedBossCog.DistributedBossCog.exitIntroduction(self) self.stingMusic.stop() def enterBattleOne(self): DistributedBossCog.DistributedBossCog.enterBattleOne(self) self.reparentTo(render) self.setPosHpr(*ToontownGlobals.CashbotBossBattleOnePosHpr) self.show() self.pelvis.setHpr(self.pelvisReversedHpr) self.doAnimate() self.endVault.stash() self.midVault.unstash() self.__hideResistanceToon() def exitBattleOne(self): DistributedBossCog.DistributedBossCog.exitBattleOne(self) def enterPrepareBattleThree(self): self.controlToons() NametagGlobals.setMasterArrowsOn(0) intervalName = 'PrepareBattleThreeMovie' delayDeletes = [] self.movieCrane = self.cranes[0] self.movieSafe = self.safes[1] self.movieCrane.request('Movie') seq = Sequence(self.makePrepareBattleThreeMovie(delayDeletes, self.movieCrane, self.movieSafe), Func(self.__beginBattleThree), name=intervalName) seq.delayDeletes = delayDeletes seq.start() self.storeInterval(seq, intervalName) self.endVault.unstash() self.evWalls.stash() self.midVault.unstash() self.__showResistanceToon(False) taskMgr.add(self.__doPhysics, self.uniqueName('physics'), priority=25) def __beginBattleThree(self): intervalName = 'PrepareBattleThreeMovie' self.clearInterval(intervalName) self.doneBarrier('PrepareBattleThree') def exitPrepareBattleThree(self): intervalName = 'PrepareBattleThreeMovie' self.clearInterval(intervalName) self.unstickToons() self.releaseToons() if self.newState == 'BattleThree': self.movieCrane.request('Free') self.movieSafe.request('Initial') NametagGlobals.setMasterArrowsOn(1) ElevatorUtils.closeDoors(self.leftDoor, self.rightDoor, ElevatorConstants.ELEVATOR_CFO) taskMgr.remove(self.uniqueName('physics')) def enterBattleThree(self): DistributedBossCog.DistributedBossCog.enterBattleThree(self) self.clearChat() self.resistanceToon.clearChat() self.reparentTo(render) self.setPosHpr(*ToontownGlobals.CashbotBossBattleThreePosHpr) self.happy = 1 self.raised = 1 self.forward = 1 self.doAnimate() self.endVault.unstash() self.evWalls.unstash() self.midVault.stash() self.__hideResistanceToon() localAvatar.setCameraFov(ToontownGlobals.BossBattleCameraFov) self.generateHealthBar() self.updateHealthBar() base.playMusic(self.battleThreeMusic, looping=1, volume=0.9) taskMgr.add(self.__doPhysics, self.uniqueName('physics'), priority=25) def exitBattleThree(self): DistributedBossCog.DistributedBossCog.exitBattleThree(self) bossDoneEventName = self.uniqueName('DestroyedBoss') self.ignore(bossDoneEventName) self.stopAnimate() self.cleanupAttacks() self.setDizzy(0) self.removeHealthBar() localAvatar.setCameraFov(ToontownGlobals.CogHQCameraFov) if self.newState != 'Victory': self.battleThreeMusic.stop() taskMgr.remove(self.uniqueName('physics')) def enterVictory(self): self.cleanupIntervals() self.reparentTo(render) self.setPosHpr(*ToontownGlobals.CashbotBossBattleThreePosHpr) self.stopAnimate() self.endVault.unstash() self.evWalls.unstash() self.midVault.unstash() self.__hideResistanceToon() self.__hideToons() self.clearChat() self.resistanceToon.clearChat() self.deactivateCranes() if self.cranes: self.cranes[1].demand('Off') self.releaseToons(finalBattle=1) if self.hasLocalToon(): self.toMovieMode() intervalName = 'VictoryMovie' seq = Sequence(self.makeBossFleeMovie(), Func(self.__continueVictory), name=intervalName) seq.start() self.storeInterval(seq, intervalName) if self.oldState != 'BattleThree': base.playMusic(self.battleThreeMusic, looping=1, volume=0.9) def __continueVictory(self): self.doneBarrier('Victory') def exitVictory(self): self.cleanupIntervals() if self.newState != 'Reward': if self.hasLocalToon(): self.toWalkMode() self.__showToons() self.door3.setPos(0, 0, 0) if self.newState != 'Reward': self.battleThreeMusic.stop() def enterReward(self): self.cleanupIntervals() self.clearChat() self.resistanceToon.clearChat() self.stash() self.stopAnimate() self.controlToons() panelName = self.uniqueName('reward') self.rewardPanel = RewardPanel.RewardPanel(panelName) victory, camVictory, skipper = MovieToonVictory.doToonVictory(1, self.involvedToons, self.toonRewardIds, self.toonRewardDicts, self.deathList, self.rewardPanel, allowGroupShot=0, uberList=self.uberList, noSkip=True) ival = Sequence(Parallel(victory, camVictory), Func(self.__doneReward)) intervalName = 'RewardMovie' delayDeletes = [] for toonId in self.involvedToons: toon = self.cr.doId2do.get(toonId) if toon: delayDeletes.append(DelayDelete.DelayDelete(toon, 'CashbotBoss.enterReward')) ival.delayDeletes = delayDeletes ival.start() self.storeInterval(ival, intervalName) if self.oldState != 'Victory': base.playMusic(self.battleThreeMusic, looping=1, volume=0.9) def __doneReward(self): self.doneBarrier('Reward') self.toWalkMode() def exitReward(self): intervalName = 'RewardMovie' self.clearInterval(intervalName) if self.newState != 'Epilogue': self.releaseToons() self.unstash() self.rewardPanel.destroy() del self.rewardPanel self.battleThreeMusic.stop() def enterEpilogue(self): self.cleanupIntervals() self.clearChat() self.resistanceToon.clearChat() self.stash() self.stopAnimate() self.controlToons() self.__showResistanceToon(False) self.resistanceToon.setPosHpr(*ToontownGlobals.CashbotBossBattleThreePosHpr) self.resistanceToon.loop('neutral') self.__arrangeToonsAroundResistanceToon() base.camera.reparentTo(render) base.camera.setPos(self.resistanceToon, -9, 12, 6) base.camera.lookAt(self.resistanceToon, 0, 0, 3) intervalName = 'EpilogueMovie' text = ResistanceChat.getChatText(self.rewardId) menuIndex, itemIndex = ResistanceChat.decodeId(self.rewardId) value = ResistanceChat.getItemValue(self.rewardId) if menuIndex == ResistanceChat.RESISTANCE_TOONUP: if value == -1: instructions = TTLocalizer.ResistanceToonToonupAllInstructions else: instructions = TTLocalizer.ResistanceToonToonupInstructions % value elif menuIndex == ResistanceChat.RESISTANCE_MONEY: if value == -1: instructions = TTLocalizer.ResistanceToonMoneyAllInstructions else: instructions = TTLocalizer.ResistanceToonMoneyInstructions % value elif menuIndex == ResistanceChat.RESISTANCE_RESTOCK: if value == -1: instructions = TTLocalizer.ResistanceToonRestockAllInstructions else: trackName = TTLocalizer.BattleGlobalTracks[value] instructions = TTLocalizer.ResistanceToonRestockInstructions % trackName elif menuIndex == ResistanceChat.RESISTANCE_MERITS: if value == -1: instructions = TTLocalizer.ResistanceToonMeritsAllInstructions else: instructions = TTLocalizer.ResistanceToonMeritsInstructions % TTLocalizer.RewardPanelMeritBarLabels[value] elif menuIndex == ResistanceChat.RESISTANCE_TICKETS: instructions = TTLocalizer.ResistanceToonTicketsInstructions % value speech = TTLocalizer.ResistanceToonCongratulations % (text, instructions) speech = self.__talkAboutPromotion(speech) self.resistanceToon.setLocalPageChat(speech, 0) self.accept('nextChatPage', self.__epilogueChatNext) self.accept('doneChatPage', self.__epilogueChatDone) base.playMusic(self.epilogueMusic, looping=1, volume=0.9) def __epilogueChatNext(self, pageNumber, elapsed): if pageNumber == 1: toon = self.resistanceToon playRate = 0.75 track = Sequence(ActorInterval(toon, 'victory', playRate=playRate, startFrame=0, endFrame=9), ActorInterval(toon, 'victory', playRate=playRate, startFrame=9, endFrame=0), Func(self.resistanceToon.loop, 'neutral')) intervalName = 'EpilogueMovieToonAnim' self.storeInterval(track, intervalName) track.start() elif pageNumber == 3: self.d_applyReward() ResistanceChat.doEffect(self.rewardId, self.resistanceToon, self.involvedToons) def __epilogueChatDone(self, elapsed): self.resistanceToon.setChatAbsolute(TTLocalizer.CagedToonGoodbye, CFSpeech) self.ignore('nextChatPage') self.ignore('doneChatPage') intervalName = 'EpilogueMovieToonAnim' self.clearInterval(intervalName) track = Parallel(Sequence(ActorInterval(self.resistanceToon, 'wave'), Func(self.resistanceToon.loop, 'neutral')), Sequence(Wait(0.5), Func(self.localToonToSafeZone))) self.storeInterval(track, intervalName) track.start() def exitEpilogue(self): self.clearInterval('EpilogueMovieToonAnim') self.unstash() self.epilogueMusic.stop() def enterFrolic(self): DistributedBossCog.DistributedBossCog.enterFrolic(self) self.setPosHpr(*ToontownGlobals.CashbotBossBattleOnePosHpr) self.releaseToons() if self.hasLocalToon(): self.toWalkMode() self.door3.setZ(25) self.door2.setZ(25) self.endVault.unstash() self.evWalls.stash() self.midVault.unstash() self.__hideResistanceToon() def exitFrolic(self): self.door3.setZ(0) self.door2.setZ(0)