from direct.directnotify import DirectNotifyGlobal from direct.directutil import Mopath from direct.distributed.ClockDelta import * from direct.fsm import ClassicFSM, State from direct.fsm import FSM from direct.gui.DirectGui import * from direct.interval.IntervalGlobal import * from direct.showbase.PythonUtil import Functor from direct.showutil import Rope from direct.task import Task import math from panda3d.core import * import random import DistributedBossCog import SuitDNA from toontown.battle import BattleBase from toontown.battle import MovieToonVictory from toontown.battle import RewardPanel from toontown.battle import SuitBattleGlobals from toontown.battle.BattleProps import * from toontown.coghq import CogDisguiseGlobals from toontown.distributed import DelayDelete from toontown.suit import SellbotBossGlobals from toontown.toon import NPCToons from toontown.toonbase import TTLocalizer from toontown.toonbase import ToontownBattleGlobals from toontown.toonbase import ToontownGlobals from otp.nametag.NametagConstants import * from otp.nametag import NametagGlobals OneBossCog = None class DistributedSellbotBoss(DistributedBossCog.DistributedBossCog, FSM.FSM): notify = DirectNotifyGlobal.directNotify.newCategory('DistributedSellbotBoss') cageHeights = [100, 81, 63, 44, 25, 18] def __init__(self, cr): DistributedBossCog.DistributedBossCog.__init__(self, cr) FSM.FSM.__init__(self, 'DistributedSellbotBoss') self.cagedToonNpcId = None self.doobers = [] self.dooberRequest = None self.bossDamage = 0 self.attackCode = None self.attackAvId = 0 self.recoverRate = 0 self.recoverStartTime = 0 self.bossDamageMovie = None self.cagedToon = None self.cageShadow = None self.cageIndex = 0 self.everThrownPie = 0 self.battleThreeMusicTime = 0 self.insidesANodePath = None self.insidesBNodePath = None self.rampA = None self.rampB = None self.rampC = None self.strafeInterval = None self.onscreenMessage = None self.toonMopathInterval = [] self.nerfed = base.cr.newsManager.isHolidayRunning(ToontownGlobals.SELLBOT_NERF_HOLIDAY) self.localToonPromoted = True self.resetMaxDamage() def announceGenerate(self): global OneBossCog DistributedBossCog.DistributedBossCog.announceGenerate(self) self.setName(TTLocalizer.SellbotBossName) nameInfo = TTLocalizer.BossCogNameWithDept % {'name': self.name, 'dept': SuitDNA.getDeptFullname(self.style.dept)} self.setDisplayName(nameInfo) self.cageDoorSfx = loader.loadSfx('phase_5/audio/sfx/CHQ_SOS_cage_door.ogg') self.cageLandSfx = loader.loadSfx('phase_9/audio/sfx/CHQ_SOS_cage_land.ogg') self.cageLowerSfx = loader.loadSfx('phase_5/audio/sfx/CHQ_SOS_cage_lower.ogg') self.piesRestockSfx = loader.loadSfx('phase_9/audio/sfx/CHQ_SOS_pies_restock.ogg') self.rampSlideSfx = loader.loadSfx('phase_9/audio/sfx/CHQ_VP_ramp_slide.ogg') self.strafeSfx = [] for i in xrange(10): self.strafeSfx.append(loader.loadSfx('phase_3.5/audio/sfx/SA_shred.ogg')) render.setTag('pieCode', str(ToontownGlobals.PieCodeNotBossCog)) insidesA = CollisionPolygon(Point3(4.0, -2.0, 5.0), Point3(-4.0, -2.0, 5.0), Point3(-4.0, -2.0, 0.5), Point3(4.0, -2.0, 0.5)) insidesANode = CollisionNode('BossZap') insidesANode.addSolid(insidesA) insidesANode.setCollideMask(ToontownGlobals.PieBitmask | ToontownGlobals.WallBitmask) self.insidesANodePath = self.axle.attachNewNode(insidesANode) self.insidesANodePath.setTag('pieCode', str(ToontownGlobals.PieCodeBossInsides)) self.insidesANodePath.stash() insidesB = CollisionPolygon(Point3(-4.0, 2.0, 5.0), Point3(4.0, 2.0, 5.0), Point3(4.0, 2.0, 0.5), Point3(-4.0, 2.0, 0.5)) insidesBNode = CollisionNode('BossZap') insidesBNode.addSolid(insidesB) insidesBNode.setCollideMask(ToontownGlobals.PieBitmask | ToontownGlobals.WallBitmask) self.insidesBNodePath = self.axle.attachNewNode(insidesBNode) self.insidesBNodePath.setTag('pieCode', str(ToontownGlobals.PieCodeBossInsides)) self.insidesBNodePath.stash() target = CollisionTube(0, -1, 4, 0, -1, 9, 3.5) targetNode = CollisionNode('BossZap') targetNode.addSolid(target) targetNode.setCollideMask(ToontownGlobals.PieBitmask) self.targetNodePath = self.pelvis.attachNewNode(targetNode) self.targetNodePath.setTag('pieCode', str(ToontownGlobals.PieCodeBossCog)) shield = CollisionTube(0, 1, 4, 0, 1, 7, 3.5) shieldNode = CollisionNode('BossZap') shieldNode.addSolid(shield) shieldNode.setCollideMask(ToontownGlobals.PieBitmask | ToontownGlobals.CameraBitmask) shieldNodePath = self.pelvis.attachNewNode(shieldNode) disk = loader.loadModel('phase_9/models/char/bossCog-gearCollide') disk.find('**/+CollisionNode').setName('BossZap') disk.reparentTo(self.pelvis) disk.setZ(0.8) self.loadEnvironment() self.__makeCagedToon() self.__loadMopaths() if OneBossCog is not None: self.notify.warning('Multiple BossCogs visible.') OneBossCog = self def disable(self): global OneBossCog DistributedBossCog.DistributedBossCog.disable(self) self.request('Off') self.unloadEnvironment() self.__unloadMopaths() self.__cleanupCagedToon() self.__clearOnscreenMessage() taskMgr.remove(self.uniqueName('PieAdvice')) self.__cleanupStrafe() render.clearTag('pieCode') self.targetNodePath.detachNode() self.cr.relatedObjectMgr.abortRequest(self.dooberRequest) self.dooberRequest = None self.betweenBattleMusic.stop() self.promotionMusic.stop() self.stingMusic.stop() self.battleTwoMusic.stop() self.battleThreeMusic.stop() self.epilogueMusic.stop() while len(self.toonMopathInterval): toonMopath = self.toonMopathInterval[0] toonMopath.finish() toonMopath.destroy() self.toonMopathInterval.remove(toonMopath) if OneBossCog == self: OneBossCog = None def resetMaxDamage(self): if self.nerfed: self.bossMaxDamage = ToontownGlobals.SellbotBossMaxDamageNerfed else: self.bossMaxDamage = ToontownGlobals.SellbotBossMaxDamage def d_hitBoss(self, bossDamage): self.sendUpdate('hitBoss', [bossDamage]) def d_hitBossInsides(self): self.sendUpdate('hitBossInsides', []) def d_hitToon(self, toonId): self.sendUpdate('hitToon', [toonId]) def setCagedToonNpcId(self, npcId): self.cagedToonNpcId = npcId def gotToon(self, toon): stateName = self.state if stateName == 'Elevator': self.placeToonInElevator(toon) def setDooberIds(self, dooberIds): self.doobers = [] self.cr.relatedObjectMgr.abortRequest(self.dooberRequest) self.dooberRequest = self.cr.relatedObjectMgr.requestObjects(dooberIds, allCallback=self.__gotDoobers) def __gotDoobers(self, doobers): self.dooberRequest = None self.doobers = doobers def setBossDamage(self, bossDamage, recoverRate, timestamp): recoverStartTime = globalClockDelta.networkToLocalTime(timestamp) self.bossDamage = bossDamage self.recoverRate = recoverRate self.recoverStartTime = recoverStartTime taskName = 'RecoverBossDamage' taskMgr.remove(taskName) if self.bossDamageMovie: if self.bossDamage >= self.bossMaxDamage: self.bossDamageMovie.resumeUntil(self.bossDamageMovie.getDuration()) else: self.bossDamageMovie.resumeUntil(self.bossDamage * self.bossDamageToMovie) if self.recoverRate: taskMgr.add(self.__recoverBossDamage, taskName) def getBossDamage(self): now = globalClock.getFrameTime() elapsed = now - self.recoverStartTime return max(self.bossDamage - self.recoverRate * elapsed / 60.0, 0) def __recoverBossDamage(self, task): self.bossDamageMovie.setT(self.getBossDamage() * self.bossDamageToMovie) return Task.cont def __makeCagedToon(self): if self.cagedToon: return self.cagedToon = NPCToons.createLocalNPC(self.cagedToonNpcId) self.cagedToon.addActive() self.cagedToon.reparentTo(self.cage) self.cagedToon.setPosHpr(0, -2, 0, 180, 0, 0) self.cagedToon.loop('neutral') self.cagedToon.setActiveShadow(0) touch = CollisionPolygon( Point3(-3.0382, 3.0382, -1), Point3(3.0382, 3.0382, -1), Point3(3.0382, -3.0382, -1), Point3(-3.0382, -3.0382, -1)) touch.setTangible(0) touchNode = CollisionNode('Cage') touchNode.setCollideMask(ToontownGlobals.WallBitmask) touchNode.addSolid(touch) self.cage.attachNewNode(touchNode) def __cleanupCagedToon(self): if self.cagedToon: self.cagedToon.removeActive() self.cagedToon.delete() self.cagedToon = None def __walkToonToPromotion(self, toonId, delay, mopath, track, delayDeletes): toon = base.cr.doId2do.get(toonId) if toon: destPos = toon.getPos() self.placeToonInElevator(toon) toon.wrtReparentTo(render) walkMopath = MopathInterval(mopath, toon) ival = Sequence(Wait(delay), Func(toon.suit.setPlayRate, 1, 'walk'), Func(toon.suit.loop, 'walk'), toon.posInterval(1, Point3(0, 90, 20)), ParallelEndTogether(walkMopath, toon.posInterval(2, destPos, blendType='noBlend')), Func(toon.suit.loop, 'neutral')) self.toonMopathInterval.append(walkMopath) track.append(ival) delayDeletes.append(DelayDelete.DelayDelete(toon, 'SellbotBoss.__walkToonToPromotion')) def __walkDoober(self, suit, delay, turnPos, track, delayDeletes): turnPos = Point3(*turnPos) turnPosDown = Point3(*ToontownGlobals.SellbotBossDooberTurnPosDown) flyPos = Point3(*ToontownGlobals.SellbotBossDooberFlyPos) seq = Sequence(Func(suit.headsUp, turnPos), Wait(delay), Func(suit.loop, 'walk', 0), self.__walkSuitToPoint(suit, suit.getPos(), turnPos), self.__walkSuitToPoint(suit, turnPos, turnPosDown), self.__walkSuitToPoint(suit, turnPosDown, flyPos), suit.beginSupaFlyMove(flyPos, 0, 'flyAway'), Func(suit.fsm.request, 'Off')) track.append(seq) delayDeletes.append(DelayDelete.DelayDelete(suit, 'SellbotBoss.__walkDoober')) def __walkSuitToPoint(self, node, fromPos, toPos): vector = Vec3(toPos - fromPos) distance = vector.length() time = distance / (ToontownGlobals.SuitWalkSpeed * 1.8) return Sequence(Func(node.setPos, fromPos), Func(node.headsUp, toPos), node.posInterval(time, toPos)) def makeIntroductionMovie(self, delayDeletes): track = Parallel() camera.reparentTo(render) localAvatar.setCameraFov(ToontownGlobals.CogHQCameraFov) dooberTrack = Parallel() if self.doobers: self.__doobersToPromotionPosition(self.doobers[:4], self.battleANode) self.__doobersToPromotionPosition(self.doobers[4:], self.battleBNode) turnPosA = ToontownGlobals.SellbotBossDooberTurnPosA turnPosB = ToontownGlobals.SellbotBossDooberTurnPosB self.__walkDoober(self.doobers[0], 0, turnPosA, dooberTrack, delayDeletes) self.__walkDoober(self.doobers[1], 4, turnPosA, dooberTrack, delayDeletes) self.__walkDoober(self.doobers[2], 8, turnPosA, dooberTrack, delayDeletes) self.__walkDoober(self.doobers[3], 12, turnPosA, dooberTrack, delayDeletes) self.__walkDoober(self.doobers[7], 2, turnPosB, dooberTrack, delayDeletes) self.__walkDoober(self.doobers[6], 6, turnPosB, dooberTrack, delayDeletes) self.__walkDoober(self.doobers[5], 10, turnPosB, dooberTrack, delayDeletes) self.__walkDoober(self.doobers[4], 14, turnPosB, dooberTrack, delayDeletes) toonTrack = Parallel() self.__toonsToPromotionPosition(self.toonsA, self.battleANode) self.__toonsToPromotionPosition(self.toonsB, self.battleBNode) delay = 0 for toonId in self.toonsA: self.__walkToonToPromotion(toonId, delay, self.toonsEnterA, toonTrack, delayDeletes) delay += 1 for toonId in self.toonsB: self.__walkToonToPromotion(toonId, delay, self.toonsEnterB, toonTrack, delayDeletes) delay += 1 toonTrack.append(Sequence(Wait(delay), self.closeDoors)) self.rampA.request('extended') self.rampB.request('extended') self.rampC.request('retracted') self.clearChat() self.cagedToon.clearChat() promoteDoobers = TTLocalizer.BossCogPromoteDoobers % SuitDNA.getDeptFullnameP(self.style.dept) doobersAway = TTLocalizer.BossCogDoobersAway[self.style.dept] welcomeToons = TTLocalizer.BossCogWelcomeToons promoteToons = TTLocalizer.BossCogPromoteToons % SuitDNA.getDeptFullnameP(self.style.dept) discoverToons = TTLocalizer.BossCogDiscoverToons attackToons = TTLocalizer.BossCogAttackToons interruptBoss = TTLocalizer.CagedToonInterruptBoss rescueQuery = TTLocalizer.CagedToonRescueQuery bossAnimTrack = Sequence( ActorInterval(self, 'Ff_speech', startTime=2, duration=10, loop=1), ActorInterval(self, 'ltTurn2Wave', duration=2), ActorInterval(self, 'wave', duration=4, loop=1), ActorInterval(self, 'ltTurn2Wave', startTime=2, endTime=0), ActorInterval(self, 'Ff_speech', duration=7, loop=1)) track.append(bossAnimTrack) dialogTrack = Track( (0, Parallel( camera.posHprInterval(8, Point3(-22, -100, 35), Point3(-10, -13, 0), blendType='easeInOut'), IndirectInterval(toonTrack, 0, 18))), (5.6, Func(self.setChatAbsolute, promoteDoobers, CFSpeech)), (9, IndirectInterval(dooberTrack, 0, 9)), (10, Sequence( Func(self.clearChat), camera.posHprInterval(5, (-0.3, -105.1, 5.4), (0, 0, 0), blendType='easeInOut'))), (12, Func(self.setChatAbsolute, doobersAway, CFSpeech)), (16, Parallel( Func(self.clearChat), camera.posHprInterval(4, (-25, -99, 10), (-14, 10, 0), blendType='easeInOut'), IndirectInterval(dooberTrack, 14), IndirectInterval(toonTrack, 30))), (18, Func(self.setChatAbsolute, welcomeToons, CFSpeech)), (22, Func(self.setChatAbsolute, promoteToons, CFSpeech)), (22.2, Sequence( Func(self.cagedToon.nametag3d.setScale, 2), Func(self.cagedToon.setChatAbsolute, interruptBoss, CFSpeech), ActorInterval(self.cagedToon, 'wave'), Func(self.cagedToon.loop, 'neutral'))), (25, Sequence( Func(self.clearChat), Func(self.cagedToon.clearChat), Func(camera.setPosHpr, -12, -15, 27, -151, -15, 0), ActorInterval(self, 'Ff_lookRt'))), (27, Sequence( Func(self.cagedToon.setChatAbsolute, rescueQuery, CFSpeech), Func(camera.setPosHpr, -12, 48, 94, -26, 20, 0), ActorInterval(self.cagedToon, 'wave'), Func(self.cagedToon.loop, 'neutral'))), (31, Sequence( camera.posHprInterval(1, (-20, -35, 10), (-88, 25, 0), blendType='easeOut'), Func(self.setChatAbsolute, discoverToons, CFSpeech), Func(self.cagedToon.nametag3d.setScale, 1), Func(self.cagedToon.clearChat), ActorInterval(self, 'turn2Fb'))), (35, Sequence( Func(self.clearChat), self.loseCogSuits(self.toonsA, self.battleANode, (0, 18, 5, -180, 0, 0)), self.loseCogSuits(self.toonsB, self.battleBNode, (0, 18, 5, -180, 0, 0)))), (38, Sequence( self.toonNormalEyes(self.involvedToons), camera.posHprInterval(1, (-23.4, -145.6, 44.0), (-10.0, -12.5, 0), blendType='easeInOut'), Func(self.loop, 'Fb_neutral'), Func(self.rampA.request, 'retract'), Func(self.rampB.request, 'retract'), Parallel(self.backupToonsToBattlePosition(self.toonsA, self.battleANode), self.backupToonsToBattlePosition(self.toonsB, self.battleBNode), Sequence( Wait(3), camera.posHprInterval(1, (-25, -35, 20.5), (-90, 0, 0), blendType='easeOut'), Func(self.setChatAbsolute, attackToons, CFSpeech), Wait(3)))))) track.append(dialogTrack) return Sequence(Func(self.stickToonsToFloor), track, Func(self.unstickToons), name=self.uniqueName('Introduction')) def __makeRollToBattleTwoMovie(self): startPos = Point3(ToontownGlobals.SellbotBossBattleOnePosHpr[0], ToontownGlobals.SellbotBossBattleOnePosHpr[1], ToontownGlobals.SellbotBossBattleOnePosHpr[2]) if self.arenaSide: topRampPos = Point3(*ToontownGlobals.SellbotBossTopRampPosB) topRampTurnPos = Point3(*ToontownGlobals.SellbotBossTopRampTurnPosB) p3Pos = Point3(*ToontownGlobals.SellbotBossP3PosB) else: topRampPos = Point3(*ToontownGlobals.SellbotBossTopRampPosA) topRampTurnPos = Point3(*ToontownGlobals.SellbotBossTopRampTurnPosA) p3Pos = Point3(*ToontownGlobals.SellbotBossP3PosA) battlePos = Point3(ToontownGlobals.SellbotBossBattleTwoPosHpr[0], ToontownGlobals.SellbotBossBattleTwoPosHpr[1], ToontownGlobals.SellbotBossBattleTwoPosHpr[2]) battleHpr = VBase3(ToontownGlobals.SellbotBossBattleTwoPosHpr[3], ToontownGlobals.SellbotBossBattleTwoPosHpr[4], ToontownGlobals.SellbotBossBattleTwoPosHpr[5]) bossTrack = Sequence() bossTrack.append(Func(self.setChatAbsolute, TTLocalizer.VPRampMessage, CFSpeech | CFTimeout)) bossTrack.append(Func(self.getGeomNode().setH, 180)) bossTrack.append(Func(self.loop, 'Fb_neutral')) track, hpr = self.rollBossToPoint(startPos, None, topRampPos, None, 0) bossTrack.append(track) track, hpr = self.rollBossToPoint(topRampPos, hpr, topRampTurnPos, None, 0) bossTrack.append(track) track, hpr = self.rollBossToPoint(topRampTurnPos, hpr, p3Pos, None, 0) bossTrack.append(track) track, hpr = self.rollBossToPoint(p3Pos, hpr, battlePos, None, 0) bossTrack.append(track) return Sequence(bossTrack, Func(self.getGeomNode().setH, 0), name=self.uniqueName('BattleTwo')) def cagedToonMovieFunction(self, instruct, cageIndex): self.notify.debug('cagedToonMovieFunction()') if not (hasattr(self, 'cagedToon') and hasattr(self.cagedToon, 'nametag') and hasattr(self.cagedToon, 'nametag3d')): return if instruct == 1: self.cagedToon.nametag3d.setScale(2) elif instruct == 2: self.cagedToon.setChatAbsolute(TTLocalizer.CagedToonDrop[cageIndex], CFSpeech) elif instruct == 3: self.cagedToon.nametag3d.setScale(1) elif instruct == 4: self.cagedToon.clearChat() def makeEndOfBattleMovie(self, hasLocalToon): name = self.uniqueName('CageDrop') seq = Sequence(name=name) seq.append(Func(self.cage.setPos, self.cagePos[self.cageIndex])) if hasLocalToon: seq += [Func(camera.reparentTo, render), Func(camera.setPosHpr, self.cage, 0, -50, 0, 0, 0, 0), Func(localAvatar.setCameraFov, ToontownGlobals.CogHQCameraFov), Func(self.hide)] seq += [Wait(0.5), Parallel(self.cage.posInterval(1, self.cagePos[self.cageIndex + 1], blendType='easeInOut'), SoundInterval(self.cageLowerSfx, duration=1)), Func(self.cagedToonMovieFunction, 1, self.cageIndex), Func(self.cagedToonMovieFunction, 2, self.cageIndex), Wait(3), Func(self.cagedToonMovieFunction, 3, self.cageIndex), Func(self.cagedToonMovieFunction, 4, self.cageIndex)] if hasLocalToon: seq += [Func(self.show), Func(camera.reparentTo, localAvatar), Func(camera.setPos, localAvatar.cameraPositions[0][0]), Func(camera.setHpr, 0, 0, 0)] self.cageIndex += 1 return seq def __makeBossDamageMovie(self): startPos = Point3(ToontownGlobals.SellbotBossBattleTwoPosHpr[0], ToontownGlobals.SellbotBossBattleTwoPosHpr[1], ToontownGlobals.SellbotBossBattleTwoPosHpr[2]) startHpr = Point3(*ToontownGlobals.SellbotBossBattleThreeHpr) bottomPos = Point3(*ToontownGlobals.SellbotBossBottomPos) deathPos = Point3(*ToontownGlobals.SellbotBossDeathPos) self.setPosHpr(startPos, startHpr) bossTrack = Sequence() bossTrack.append(Func(self.loop, 'Fb_neutral')) track, hpr = self.rollBossToPoint(startPos, startHpr, bottomPos, None, 1) bossTrack.append(track) track, hpr = self.rollBossToPoint(bottomPos, startHpr, deathPos, None, 1) bossTrack.append(track) duration = bossTrack.getDuration() return bossTrack def __talkAboutPromotion(self, speech): if not self.localToonPromoted: pass elif self.prevCogSuitLevel < ToontownGlobals.MaxCogSuitLevel: speech += TTLocalizer.CagedToonPromotion newCogSuitLevel = localAvatar.getCogLevels()[CogDisguiseGlobals.dept2deptIndex(self.style.dept)] if newCogSuitLevel == ToontownGlobals.MaxCogSuitLevel: speech += TTLocalizer.CagedToonLastPromotion % (ToontownGlobals.MaxCogSuitLevel + 1) if newCogSuitLevel in ToontownGlobals.CogSuitHPLevels: speech += TTLocalizer.CagedToonHPBoost else: speech += TTLocalizer.CagedToonMaxed % (ToontownGlobals.MaxCogSuitLevel + 1) if self.keyReward: speech += TTLocalizer.BossRTKeyReward return speech return speech def __makeCageOpenMovie(self): speech = TTLocalizer.CagedToonThankYou speech = self.__talkAboutPromotion(speech) name = self.uniqueName('CageOpen') seq = Sequence( Func(self.cage.setPos, self.cagePos[4]), Func(self.cageDoor.setHpr, VBase3(0, 0, 0)), Func(self.cagedToon.setPos, Point3(0, -2, 0)), Parallel( self.cage.posInterval(0.5, self.cagePos[5], blendType='easeOut'), SoundInterval(self.cageLowerSfx, duration=0.5)), Parallel( self.cageDoor.hprInterval(0.5, VBase3(0, 90, 0), blendType='easeOut'), Sequence(SoundInterval(self.cageDoorSfx), duration=0)), Wait(0.2), Func(self.cagedToon.loop, 'walk'), self.cagedToon.posInterval(0.8, Point3(0, -6, 0)), Func(self.cagedToon.setChatAbsolute, TTLocalizer.CagedToonYippee, CFSpeech), ActorInterval(self.cagedToon, 'jump'), Func(self.cagedToon.loop, 'neutral'), Func(self.cagedToon.headsUp, localAvatar), Func(self.cagedToon.setLocalPageChat, speech, 0), Func(camera.reparentTo, localAvatar), Func(camera.setPos, 0, -9, 9), Func(camera.lookAt, self.cagedToon, Point3(0, 0, 2)), name=name) return seq def __showOnscreenMessage(self, text): if self.onscreenMessage: self.onscreenMessage.destroy() self.onscreenMessage = None self.onscreenMessage = DirectLabel(text=text, text_fg=VBase4(1, 1, 1, 1), text_align=TextNode.ACenter, relief=None, pos=(0, 0, 0.35), scale=0.1) def __clearOnscreenMessage(self): if self.onscreenMessage: self.onscreenMessage.destroy() self.onscreenMessage = None def __showWaitingMessage(self, task): self.__showOnscreenMessage(TTLocalizer.WaitingForOtherToons) def __placeCageShadow(self): if self.cageShadow == None: self.cageShadow = loader.loadModel('phase_3/models/props/drop_shadow') self.cageShadow.setPos(0, 77.9, 18) self.cageShadow.setColorScale(1, 1, 1, 0.6) self.cageShadow.reparentTo(render) def __removeCageShadow(self): if self.cageShadow != None: self.cageShadow.detachNode() def setCageIndex(self, cageIndex): self.cageIndex = cageIndex self.cage.setPos(self.cagePos[self.cageIndex]) if self.cageIndex >= 4: self.__placeCageShadow() else: self.__removeCageShadow() def loadEnvironment(self): DistributedBossCog.DistributedBossCog.loadEnvironment(self) self.geom = loader.loadModel('phase_9/models/cogHQ/BossRoomHQ') self.rampA = self.__findRamp('rampA', '**/west_ramp2') self.rampB = self.__findRamp('rampB', '**/west_ramp') self.rampC = self.__findRamp('rampC', '**/west_ramp1') self.cage = self.geom.find('**/cage') elevatorEntrance = self.geom.find('**/elevatorEntrance') elevatorEntrance.getChildren().detach() elevatorEntrance.setScale(1) elevatorModel = loader.loadModel('phase_9/models/cogHQ/cogHQ_elevator') elevatorModel.reparentTo(elevatorEntrance) self.setupElevator(elevatorModel) pos = self.cage.getPos() self.cagePos = [] for height in self.cageHeights: self.cagePos.append(Point3(pos[0], pos[1], height)) self.cageDoor = self.geom.find('**/cage_door') self.cage.setScale(1) self.rope = Rope.Rope(name='supportChain') self.rope.reparentTo(self.cage) self.rope.setup(2, ((self.cage, (0.15, 0.13, 16)), (self.geom, (0.23, 78, 120)))) self.rope.ropeNode.setRenderMode(RopeNode.RMBillboard) self.rope.ropeNode.setUvMode(RopeNode.UVDistance) self.rope.ropeNode.setUvDirection(0) self.rope.ropeNode.setUvScale(0.8) self.rope.setTexture(self.cage.findTexture('hq_chain')) self.rope.setTransparency(1) self.promotionMusic = base.loadMusic('phase_7/audio/bgm/encntr_suit_winning_indoor.ogg') self.betweenBattleMusic = base.loadMusic('phase_9/audio/bgm/encntr_toon_winning.ogg') self.battleTwoMusic = base.loadMusic('phase_7/audio/bgm/encntr_suit_winning_indoor.ogg') self.battleThreeMusic = base.loadMusic('phase_7/audio/bgm/encntr_suit_winning_indoor.ogg') self.geom.reparentTo(render) def unloadEnvironment(self): DistributedBossCog.DistributedBossCog.unloadEnvironment(self) self.geom.removeNode() del self.geom del self.cage self.rampA.requestFinalState() self.rampB.requestFinalState() self.rampC.requestFinalState() del self.rampA del self.rampB del self.rampC def __loadMopaths(self): self.toonsEnterA = Mopath.Mopath() self.toonsEnterA.loadFile('phase_9/paths/bossBattle-toonsEnterA') self.toonsEnterA.fFaceForward = 1 self.toonsEnterA.timeScale = 35 self.toonsEnterB = Mopath.Mopath() self.toonsEnterB.loadFile('phase_9/paths/bossBattle-toonsEnterB') self.toonsEnterB.fFaceForward = 1 self.toonsEnterB.timeScale = 35 def __unloadMopaths(self): self.toonsEnterA.reset() self.toonsEnterB.reset() def __findRamp(self, name, path): ramp = self.geom.find(path) children = ramp.getChildren() animate = ramp.attachNewNode(name) children.reparentTo(animate) fsm = ClassicFSM.ClassicFSM(name, [ State.State('extend', Functor(self.enterRampExtend, animate), Functor(self.exitRampExtend, animate), [ 'extended', 'retract', 'retracted']), State.State('extended', Functor(self.enterRampExtended, animate), Functor(self.exitRampExtended, animate), [ 'retract', 'retracted']), State.State('retract', Functor(self.enterRampRetract, animate), Functor(self.exitRampRetract, animate), [ 'extend', 'extended', 'retracted']), State.State('retracted', Functor(self.enterRampRetracted, animate), Functor(self.exitRampRetracted, animate), [ 'extend', 'extended']), State.State('off', Functor(self.enterRampOff, animate), Functor(self.exitRampOff, animate))], 'off', 'off', onUndefTransition=ClassicFSM.ClassicFSM.DISALLOW) fsm.enterInitialState() return fsm def enterRampExtend(self, animate): intervalName = self.uniqueName('extend-%s' % animate.getName()) adjustTime = 2.0 * animate.getX() / 18.0 ival = Parallel(SoundInterval(self.rampSlideSfx, node=animate), animate.posInterval(adjustTime, Point3(0, 0, 0), blendType='easeInOut', name=intervalName)) ival.start() self.storeInterval(ival, intervalName) def exitRampExtend(self, animate): intervalName = self.uniqueName('extend-%s' % animate.getName()) self.clearInterval(intervalName) def enterRampExtended(self, animate): animate.setPos(0, 0, 0) def exitRampExtended(self, animate): pass def enterRampRetract(self, animate): intervalName = self.uniqueName('retract-%s' % animate.getName()) adjustTime = 2.0 * (18 - animate.getX()) / 18.0 ival = Parallel(SoundInterval(self.rampSlideSfx, node=animate), animate.posInterval(adjustTime, Point3(18, 0, 0), blendType='easeInOut', name=intervalName)) ival.start() self.storeInterval(ival, intervalName) def exitRampRetract(self, animate): intervalName = self.uniqueName('retract-%s' % animate.getName()) self.clearInterval(intervalName) def enterRampRetracted(self, animate): animate.setPos(18, 0, 0) def exitRampRetracted(self, animate): pass def enterRampOff(self, animate): pass def exitRampOff(self, animate): pass def enterOff(self): DistributedBossCog.DistributedBossCog.enterOff(self) if self.cagedToon: self.cagedToon.clearChat() if self.rampA: self.rampA.request('off') if self.rampB: self.rampB.request('off') if self.rampC: self.rampC.request('off') def enterWaitForToons(self): DistributedBossCog.DistributedBossCog.enterWaitForToons(self) self.geom.hide() self.cagedToon.removeActive() def exitWaitForToons(self): DistributedBossCog.DistributedBossCog.exitWaitForToons(self) self.geom.show() self.cagedToon.addActive() def enterElevator(self): DistributedBossCog.DistributedBossCog.enterElevator(self) self.rampA.request('extended') self.rampB.request('extended') self.rampC.request('retracted') self.setCageIndex(0) self.reparentTo(render) self.setPosHpr(*ToontownGlobals.SellbotBossBattleOnePosHpr) self.happy = 1 self.raised = 1 self.forward = 1 self.doAnimate() self.cagedToon.removeActive() base.camLens.setMinFov(ToontownGlobals.VPElevatorFov/(4./3.)) def exitElevator(self): DistributedBossCog.DistributedBossCog.exitElevator(self) self.cagedToon.addActive() def enterIntroduction(self): self.reparentTo(render) self.setPosHpr(*ToontownGlobals.SellbotBossBattleOnePosHpr) self.stopAnimate() DistributedBossCog.DistributedBossCog.enterIntroduction(self) self.rampA.request('extended') self.rampB.request('extended') self.rampC.request('retracted') self.setCageIndex(0) base.playMusic(self.promotionMusic, looping=1, volume=0.9) def exitIntroduction(self): DistributedBossCog.DistributedBossCog.exitIntroduction(self) self.promotionMusic.stop() def enterBattleOne(self): DistributedBossCog.DistributedBossCog.enterBattleOne(self) self.reparentTo(render) self.setPosHpr(*ToontownGlobals.SellbotBossBattleOnePosHpr) self.clearChat() self.cagedToon.clearChat() self.rampA.request('retract') self.rampB.request('retract') self.rampC.request('retract') if self.battleA == None or self.battleB == None: cageIndex = 1 else: cageIndex = 0 self.setCageIndex(cageIndex) def exitBattleOne(self): DistributedBossCog.DistributedBossCog.exitBattleOne(self) def enterRollToBattleTwo(self): self.disableToonCollision() self.releaseToons() if self.arenaSide: self.rampA.request('retract') self.rampB.request('extend') else: self.rampA.request('extend') self.rampB.request('retract') self.rampC.request('retract') self.reparentTo(render) self.setCageIndex(2) self.stickBossToFloor() intervalName = 'RollToBattleTwo' seq = Sequence(self.__makeRollToBattleTwoMovie(), Func(self.__onToPrepareBattleTwo), name=intervalName) seq.start() self.storeInterval(seq, intervalName) base.playMusic(self.betweenBattleMusic, looping=1, volume=0.9) self.__showEasyBarrels() taskMgr.doMethodLater(0.5, self.enableToonCollision, 'enableToonCollision') def __onToPrepareBattleTwo(self): self.disableToonCollision() self.unstickBoss() self.setPosHpr(*ToontownGlobals.SellbotBossBattleTwoPosHpr) self.doneBarrier('RollToBattleTwo') def exitRollToBattleTwo(self): self.unstickBoss() intervalName = 'RollToBattleTwo' self.clearInterval(intervalName) self.betweenBattleMusic.stop() def disableToonCollision(self): base.localAvatar.collisionsOff() def enableToonCollision(self, task): base.localAvatar.collisionsOn() def enterPrepareBattleTwo(self): self.cleanupIntervals() self.__hideEasyBarrels() self.controlToons() self.clearChat() self.cagedToon.clearChat() self.reparentTo(render) if self.arenaSide: self.rampA.request('retract') self.rampB.request('extend') else: self.rampA.request('extend') self.rampB.request('retract') self.rampC.request('retract') self.reparentTo(render) self.setCageIndex(2) camera.reparentTo(render) camera.setPosHpr(self.cage, 0, -17, 3.3, 0, 0, 0) (localAvatar.setCameraFov(ToontownGlobals.CogHQCameraFov),) self.hide() self.acceptOnce('doneChatPage', self.__onToBattleTwo) self.cagedToon.setLocalPageChat(TTLocalizer.CagedToonPrepareBattleTwo, 1) base.playMusic(self.stingMusic, looping=0, volume=1.0) taskMgr.doMethodLater(0.5, self.enableToonCollision, 'enableToonCollision') def __onToBattleTwo(self, elapsed): self.doneBarrier('PrepareBattleTwo') taskMgr.doMethodLater(1, self.__showWaitingMessage, self.uniqueName('WaitingMessage')) def exitPrepareBattleTwo(self): self.show() taskMgr.remove(self.uniqueName('WaitingMessage')) self.ignore('doneChatPage') self.__clearOnscreenMessage() self.stingMusic.stop() def enterBattleTwo(self): self.cleanupIntervals() mult = ToontownBattleGlobals.getBossBattleCreditMultiplier(2) localAvatar.inventory.setBattleCreditMultiplier(mult) self.reparentTo(render) self.setPosHpr(*ToontownGlobals.SellbotBossBattleTwoPosHpr) self.clearChat() self.cagedToon.clearChat() self.rampA.request('retract') self.rampB.request('retract') self.rampC.request('retract') self.releaseToons() self.toonsToBattlePosition(self.toonsA, self.battleANode) self.toonsToBattlePosition(self.toonsB, self.battleBNode) if self.battleA == None or self.battleB == None: cageIndex = 3 else: cageIndex = 2 self.setCageIndex(cageIndex) base.playMusic(self.battleTwoMusic, looping=1, volume=0.9) def exitBattleTwo(self): intervalName = self.uniqueName('cageDrop') self.clearInterval(intervalName) self.cleanupBattles() self.battleTwoMusic.stop() localAvatar.inventory.setBattleCreditMultiplier(1) def enterPrepareBattleThree(self): self.cleanupIntervals() self.controlToons() self.clearChat() self.cagedToon.clearChat() self.reparentTo(render) self.rampA.request('retract') self.rampB.request('retract') self.rampC.request('extend') self.setCageIndex(4) camera.reparentTo(render) camera.setPosHpr(self.cage, 0, -17, 3.3, 0, 0, 0) (localAvatar.setCameraFov(ToontownGlobals.CogHQCameraFov),) self.hide() self.acceptOnce('doneChatPage', self.__onToBattleThree) self.cagedToon.setLocalPageChat(TTLocalizer.CagedToonPrepareBattleThree, 1) base.playMusic(self.betweenBattleMusic, looping=1, volume=0.9) def __onToBattleThree(self, elapsed): self.doneBarrier('PrepareBattleThree') taskMgr.doMethodLater(1, self.__showWaitingMessage, self.uniqueName('WaitingMessage')) def exitPrepareBattleThree(self): self.show() taskMgr.remove(self.uniqueName('WaitingMessage')) self.ignore('doneChatPage') intervalName = 'PrepareBattleThree' self.clearInterval(intervalName) self.__clearOnscreenMessage() self.betweenBattleMusic.stop() def enterBattleThree(self): DistributedBossCog.DistributedBossCog.enterBattleThree(self) self.clearChat() self.cagedToon.clearChat() self.reparentTo(render) self.rampA.request('retract') self.rampB.request('retract') self.rampC.request('extend') self.setCageIndex(4) self.happy = 0 self.raised = 1 self.forward = 1 self.doAnimate() self.accept('enterCage', self.__touchedCage) self.accept('pieSplat', self.__pieSplat) self.accept('localPieSplat', self.__localPieSplat) self.accept('outOfPies', self.__outOfPies) self.accept('begin-pie', self.__foundPieButton) localAvatar.setCameraFov(ToontownGlobals.BossBattleCameraFov) taskMgr.doMethodLater(30, self.__howToGetPies, self.uniqueName('PieAdvice')) self.stickBossToFloor() self.bossDamageMovie = self.__makeBossDamageMovie() bossDoneEventName = self.uniqueName('DestroyedBoss') self.bossDamageMovie.setDoneEvent(bossDoneEventName) self.acceptOnce(bossDoneEventName, self.__doneBattleThree) self.resetMaxDamage() self.bossDamageToMovie = self.bossDamageMovie.getDuration() / self.bossMaxDamage self.bossDamageMovie.setT(self.bossDamage * self.bossDamageToMovie) base.playMusic(self.battleThreeMusic, looping=1, volume=0.9) def __doneBattleThree(self): self.setState('NearVictory') self.unstickBoss() def exitBattleThree(self): DistributedBossCog.DistributedBossCog.exitBattleThree(self) bossDoneEventName = self.uniqueName('DestroyedBoss') self.ignore(bossDoneEventName) taskMgr.remove(self.uniqueName('StandUp')) self.ignore('enterCage') self.ignore('pieSplat') self.ignore('localPieSplat') self.ignore('outOfPies') self.ignore('begin-pie') self.__clearOnscreenMessage() taskMgr.remove(self.uniqueName('PieAdvice')) localAvatar.setCameraFov(ToontownGlobals.CogHQCameraFov) self.__removeCageShadow() self.bossDamageMovie.finish() self.bossDamageMovie = None self.unstickBoss() taskName = 'RecoverBossDamage' taskMgr.remove(taskName) self.battleThreeMusicTime = self.battleThreeMusic.getTime() self.battleThreeMusic.stop() def enterNearVictory(self): self.cleanupIntervals() self.reparentTo(render) self.setPos(*ToontownGlobals.SellbotBossDeathPos) self.setHpr(*ToontownGlobals.SellbotBossBattleThreeHpr) self.clearChat() self.cagedToon.clearChat() self.setCageIndex(4) self.releaseToons(finalBattle=1) self.rampA.request('retract') self.rampB.request('retract') self.rampC.request('extend') self.accept('enterCage', self.__touchedCage) self.accept('pieSplat', self.__finalPieSplat) self.accept('localPieSplat', self.__localPieSplat) self.accept('outOfPies', self.__outOfPies) localAvatar.setCameraFov(ToontownGlobals.BossBattleCameraFov) self.happy = 0 self.raised = 0 self.forward = 1 self.doAnimate() self.setDizzy(1) base.playMusic(self.battleThreeMusic, looping=1, volume=0.9, time=self.battleThreeMusicTime) def exitNearVictory(self): self.ignore('enterCage') self.ignore('pieSplat') self.ignore('localPieSplat') self.ignore('outOfPies') self.__clearOnscreenMessage() taskMgr.remove(self.uniqueName('PieAdvice')) localAvatar.setCameraFov(ToontownGlobals.CogHQCameraFov) self.__removeCageShadow() self.setDizzy(0) self.battleThreeMusicTime = self.battleThreeMusic.getTime() self.battleThreeMusic.stop() def enterVictory(self): self.cleanupIntervals() localAvatar.setCameraFov(ToontownGlobals.BossBattleCameraFov) self.reparentTo(render) self.setPos(*ToontownGlobals.SellbotBossDeathPos) self.setHpr(*ToontownGlobals.SellbotBossBattleThreeHpr) self.clearChat() self.cagedToon.clearChat() self.setCageIndex(4) self.releaseToons(finalBattle=1) self.rampA.request('retract') self.rampB.request('retract') self.rampC.request('extend') self.happy = 0 self.raised = 0 self.forward = 1 self.setChatAbsolute(TTLocalizer.VPDeathTaunt, CFSpeech | CFTimeout) self.doAnimate('Fb_fall', now=1) self.acceptOnce(self.animDoneEvent, self.__continueVictory) base.playMusic(self.battleThreeMusic, looping=1, volume=0.9, time=self.battleThreeMusicTime) def __continueVictory(self): self.stopAnimate() self.stash() self.doneBarrier('Victory') def exitVictory(self): self.stopAnimate() self.unstash() self.__removeCageShadow() localAvatar.setCameraFov(ToontownGlobals.CogHQCameraFov) self.battleThreeMusicTime = self.battleThreeMusic.getTime() self.battleThreeMusic.stop() def enterReward(self): self.cleanupIntervals() self.clearChat() self.cagedToon.clearChat() self.stash() self.stopAnimate() self.setCageIndex(4) self.releaseToons(finalBattle=1) self.toMovieMode() self.rampA.request('retract') self.rampB.request('retract') self.rampC.request('extend') 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, 'SellbotBoss.enterReward')) ival.delayDeletes = delayDeletes ival.start() self.storeInterval(ival, intervalName) base.playMusic(self.battleThreeMusic, looping=1, volume=0.9, time=self.battleThreeMusicTime) def __doneReward(self): self.doneBarrier('Reward') self.toWalkMode() def exitReward(self): intervalName = 'RewardMovie' self.clearInterval(intervalName) self.unstash() self.rewardPanel.destroy() del self.rewardPanel self.__removeCageShadow() self.battleThreeMusicTime = 0 self.battleThreeMusic.stop() def enterEpilogue(self): self.cleanupIntervals() self.clearChat() self.cagedToon.clearChat() self.stash() self.stopAnimate() self.setCageIndex(4) self.controlToons() self.rampA.request('retract') self.rampB.request('retract') self.rampC.request('extend') self.__arrangeToonsAroundCage() camera.reparentTo(render) camera.setPosHpr(-24, 52, 27.5, -53, -13, 0) intervalName = 'EpilogueMovie' seq = Sequence(self.__makeCageOpenMovie(), name=intervalName) seq.start() self.storeInterval(seq, intervalName) 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 == 2: if self.cagedToon.style.torso[1] == 'd': track = ActorInterval(self.cagedToon, 'curtsy') else: track = ActorInterval(self.cagedToon, 'bow') track = Sequence(track, Func(self.cagedToon.loop, 'neutral')) intervalName = 'EpilogueMovieToonAnim' self.storeInterval(track, intervalName) track.start() def __epilogueChatDone(self, elapsed): self.cagedToon.setChatAbsolute(TTLocalizer.CagedToonGoodbye, CFSpeech) self.ignore('nextChatPage') self.ignore('doneChatPage') intervalName = 'EpilogueMovieToonAnim' self.clearInterval(intervalName) track = Parallel(Sequence(ActorInterval(self.cagedToon, 'wave'), Func(self.cagedToon.loop, 'neutral')), Sequence(Wait(0.5), Func(self.localToonToSafeZone))) self.storeInterval(track, intervalName) track.start() def exitEpilogue(self): self.clearInterval('EpilogueMovieToonAnim') self.unstash() self.__removeCageShadow() self.epilogueMusic.stop() def __arrangeToonsAroundCage(self): radius = 15 numToons = len(self.involvedToons) center = (numToons - 1) / 2.0 for i in xrange(numToons): toon = base.cr.doId2do.get(self.involvedToons[i]) if toon: angle = 270 - 15 * (i - center) radians = angle * math.pi / 180.0 x = math.cos(radians) * radius y = math.sin(radians) * radius toon.setPos(self.cage, x, y, 0) toon.setZ(18.0) toon.headsUp(self.cage) def enterFrolic(self): DistributedBossCog.DistributedBossCog.enterFrolic(self) self.setPosHpr(*ToontownGlobals.SellbotBossBattleOnePosHpr) def doorACallback(self, isOpen): if self.insidesANodePath: if isOpen: self.insidesANodePath.unstash() else: self.insidesANodePath.stash() def doorBCallback(self, isOpen): if self.insidesBNodePath: if isOpen: self.insidesBNodePath.unstash() else: self.insidesBNodePath.stash() def __toonsToPromotionPosition(self, toonIds, battleNode): points = BattleBase.BattleBase.toonPoints[len(toonIds) - 1] for i in xrange(len(toonIds)): toon = base.cr.doId2do.get(toonIds[i]) if toon: toon.reparentTo(render) pos, h = points[i] toon.setPosHpr(battleNode, pos[0], pos[1] + 10, pos[2], h, 0, 0) def __doobersToPromotionPosition(self, doobers, battleNode): points = BattleBase.BattleBase.toonPoints[len(doobers) - 1] for i in xrange(len(doobers)): suit = doobers[i] suit.fsm.request('neutral') suit.loop('neutral') pos, h = points[i] suit.setPosHpr(battleNode, pos[0], pos[1] + 10, pos[2], h, 0, 0) def __touchedCage(self, entry): self.sendUpdate('touchCage', []) self.__clearOnscreenMessage() taskMgr.remove(self.uniqueName('PieAdvice')) base.playSfx(self.piesRestockSfx) if not self.everThrownPie: taskMgr.doMethodLater(30, self.__howToThrowPies, self.uniqueName('PieAdvice')) def __outOfPies(self): self.__showOnscreenMessage(TTLocalizer.BossBattleNeedMorePies) taskMgr.doMethodLater(20, self.__howToGetPies, self.uniqueName('PieAdvice')) def __howToGetPies(self, task): self.__showOnscreenMessage(TTLocalizer.BossBattleHowToGetPies) def __howToThrowPies(self, task): self.__showOnscreenMessage(TTLocalizer.BossBattleHowToThrowPies) def __foundPieButton(self): self.everThrownPie = 1 self.__clearOnscreenMessage() taskMgr.remove(self.uniqueName('PieAdvice')) def __pieSplat(self, toon, pieCode): if base.config.GetBool('easy-vp', 0): if not self.dizzy: pieCode = ToontownGlobals.PieCodeBossInsides if pieCode == ToontownGlobals.PieCodeBossInsides: if toon == localAvatar: self.d_hitBossInsides() self.flashRed() elif pieCode == ToontownGlobals.PieCodeBossCog: if toon == localAvatar: self.d_hitBoss(1) if self.dizzy: self.flashRed() self.doAnimate('hit', now=1) def __localPieSplat(self, pieCode, entry): if pieCode != ToontownGlobals.PieCodeToon: return avatarDoId = entry.getIntoNodePath().getNetTag('avatarDoId') if avatarDoId == '': self.notify.warning('Toon %s has no avatarDoId tag.' % repr(entry.getIntoNodePath())) return doId = int(avatarDoId) if doId != localAvatar.doId: self.d_hitToon(doId) def __finalPieSplat(self, toon, pieCode): if pieCode != ToontownGlobals.PieCodeBossCog: return self.sendUpdate('finalPieSplat', []) self.ignore('pieSplat') def cagedToonBattleThree(self, index, avId): str = TTLocalizer.CagedToonBattleThree.get(index) if str: toonName = '' if avId: toon = self.cr.doId2do.get(avId) if not toon: self.cagedToon.clearChat() return toonName = toon.getName() text = str % {'toon': toonName} self.cagedToon.setChatAbsolute(text, CFSpeech | CFTimeout) else: self.cagedToon.clearChat() def cleanupAttacks(self): self.__cleanupStrafe() def __cleanupStrafe(self): if self.strafeInterval: self.strafeInterval.finish() self.strafeInterval = None def doStrafe(self, side, direction): gearRoot = self.rotateNode.attachNewNode('gearRoot') if side == 0: gearRoot.setPos(0, -7, 3) gearRoot.setHpr(180, 0, 0) door = self.doorA else: gearRoot.setPos(0, 7, 3) door = self.doorB gearRoot.setTag('attackCode', str(ToontownGlobals.BossCogStrafeAttack)) gearModel = self.getGearFrisbee() gearModel.setScale(0.1) t = self.getBossDamage() / 100.0 gearTrack = Parallel() numGears = int(4 + 6 * t + 0.5) time = 5.0 - 4.0 * t spread = 60 * math.pi / 180.0 if direction == 1: spread = -spread dist = 50 rate = time / numGears for i in xrange(numGears): node = gearRoot.attachNewNode(str(i)) node.hide() node.setPos(0, 0, 0) gear = gearModel.instanceTo(node) angle = (float(i) / (numGears - 1) - 0.5) * spread x = dist * math.sin(angle) y = dist * math.cos(angle) h = random.uniform(-720, 720) gearTrack.append(Sequence(Wait(i * rate), Func(node.show), Parallel(node.posInterval(1, Point3(x, y, 0), fluid=1), node.hprInterval(1, VBase3(h, 0, 0), fluid=1), Sequence(SoundInterval(self.strafeSfx[i], volume=0.2, node=self), duration=0)), Func(node.detachNode))) seq = Sequence(Func(door.request, 'open'), Wait(0.7), gearTrack, Func(door.request, 'close')) self.__cleanupStrafe() self.strafeInterval = seq seq.start() def __showEasyBarrels(self): barrelNodes = hidden.findAllMatches('**/Distributed*Barrel-*') if not barrelNodes or barrelNodes.isEmpty(): return if render.find('barrelsRootNode'): self.notify.warning('__showEasyBarrels(): barrelsRootNode already exists') return self.barrelsRootNode = render.attachNewNode('barrelsRootNode') self.barrelsRootNode.setPos(*SellbotBossGlobals.BarrelsStartPos) if self.arenaSide == 0: self.barrelsRootNode.setHpr(180, 0, 0) else: self.barrelsRootNode.setHpr(0, 0, 0) for i, barrelNode in enumerate(barrelNodes): barrel = base.cr.doId2do.get(int(barrelNode.getNetTag('doId'))) SellbotBossGlobals.setBarrelAttr(barrel, barrel.entId) if hasattr(barrel, 'applyLabel'): barrel.applyLabel() barrel.setPosHpr(barrel.pos, barrel.hpr) barrel.reparentTo(self.barrelsRootNode) intervalName = 'MakeBarrelsAppear' seq = Sequence(LerpPosInterval(self.barrelsRootNode, 0.5, Vec3(*SellbotBossGlobals.BarrelsFinalPos), blendType='easeInOut'), name=intervalName) seq.start() self.storeInterval(seq, intervalName) def __hideEasyBarrels(self): if hasattr(self, 'barrelsRootNode'): self.barrelsRootNode.removeNode() intervalName = 'MakeBarrelsAppear' self.clearInterval(intervalName) def toonPromoted(self, promoted): self.localToonPromoted = promoted