1288 lines
54 KiB
Python
1288 lines
54 KiB
Python
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
|