toontown-just-works/toontown/suit/DistributedBossbotBoss.py
2024-07-07 18:08:39 -05:00

1529 lines
65 KiB
Python

from direct.directnotify import DirectNotifyGlobal
from direct.distributed.ClockDelta import globalClockDelta
from direct.fsm import FSM
from direct.interval.IntervalGlobal import Sequence, Wait, Func, LerpHprInterval, Parallel, LerpPosInterval, Track, ActorInterval, ParallelEndTogether, LerpFunctionInterval, LerpScaleInterval, LerpPosHprInterval, SoundInterval
from direct.showbase import PythonUtil
from direct.task import Task
import math
from pandac.PandaModules import VBase3, CollisionPlane, CollisionNode, CollisionSphere, CollisionTube, NodePath, Plane, Vec3, Vec2, Point3, BitMask32, CollisionHandlerEvent, TextureStage, VBase4, BoundingSphere
import random
from toontown.battle import MovieToonVictory
from toontown.battle import RewardPanel
from toontown.battle import SuitBattleGlobals
from toontown.building import ElevatorConstants
from toontown.coghq import CogDisguiseGlobals
from toontown.distributed import DelayDelete
from toontown.effects import DustCloud
from toontown.suit import DistributedBossCog
from toontown.suit import Suit
from toontown.suit import SuitDNA
from toontown.toon import Toon, NPCToons
from toontown.toonbase import TTLocalizer
from toontown.toonbase import ToontownGlobals
from toontown.toonbase import ToontownTimer
from otp.nametag import NametagGroup
from otp.nametag.NametagConstants import *
from otp.nametag import NametagGlobals
OneBossCog = None
TTL = TTLocalizer
class DistributedBossbotBoss(DistributedBossCog.DistributedBossCog, FSM.FSM):
notify = DirectNotifyGlobal.directNotify.newCategory('DistributedBossbotBoss')
BallLaunchOffset = Point3(10.5, 8.5, -5)
def __init__(self, cr):
self.notify.debug('----- __init___')
DistributedBossCog.DistributedBossCog.__init__(self, cr)
FSM.FSM.__init__(self, 'DistributedBossbotBoss')
self.bossDamage = 0
self.bossMaxDamage = ToontownGlobals.BossbotBossMaxDamage
self.elevatorType = ElevatorConstants.ELEVATOR_BB
self.resistanceToon = None
self.resistanceToonOnstage = 0
self.battleANode.setPosHpr(*ToontownGlobals.WaiterBattleAPosHpr)
self.battleBNode.setPosHpr(*ToontownGlobals.WaiterBattleBPosHpr)
self.toonFoodStatus = {}
self.belts = [None, None]
self.tables = {}
self.golfSpots = {}
self.servingTimer = None
self.notDeadList = None
self.moveTrack = None
self.speedDamage = 0
self.maxSpeedDamage = ToontownGlobals.BossbotMaxSpeedDamage
self.speedRecoverRate = 0
self.speedRecoverStartTime = 0
self.ballLaunch = None
self.moveTrack = None
self.lastZapLocalTime = 0
self.numAttacks = 0
return
def announceGenerate(self):
global OneBossCog
DistributedBossCog.DistributedBossCog.announceGenerate(self)
self.setName(TTLocalizer.BossbotBossName)
nameInfo = TTLocalizer.BossCogNameWithDept % {'name': self.name,
'dept': SuitDNA.getDeptFullname(self.style.dept)}
self.setDisplayName(nameInfo)
self.loadEnvironment()
self.__makeResistanceToon()
base.localAvatar.chatMgr.chatInputSpeedChat.addCEOMenu()
if OneBossCog != None:
self.notify.warning('Multiple BossCogs visible.')
OneBossCog = self
render.setTag('pieCode', str(ToontownGlobals.PieCodeNotBossCog))
self.setTag('attackCode', str(ToontownGlobals.BossCogGolfAttack))
target = CollisionTube(0, -2, -2, 0, -1, 9, 4.0)
targetNode = CollisionNode('BossZap')
targetNode.addSolid(target)
targetNode.setCollideMask(ToontownGlobals.PieBitmask)
self.targetNodePath = self.pelvis.attachNewNode(targetNode)
self.targetNodePath.setTag('pieCode', str(ToontownGlobals.PieCodeBossCog))
self.axle.getParent().setTag('pieCode', str(ToontownGlobals.PieCodeBossCog))
disk = loader.loadModel('phase_9/models/char/bossCog-gearCollide')
disk.find('**/+CollisionNode').setName('BossZap')
disk.reparentTo(self.pelvis)
disk.setZ(0.8)
closeBubble = CollisionSphere(0, 0, 0, 10)
closeBubble.setTangible(0)
closeBubbleNode = CollisionNode('CloseBoss')
closeBubbleNode.setIntoCollideMask(BitMask32(0))
closeBubbleNode.setFromCollideMask(ToontownGlobals.BanquetTableBitmask)
closeBubbleNode.addSolid(closeBubble)
self.closeBubbleNode = closeBubbleNode
self.closeHandler = CollisionHandlerEvent()
self.closeHandler.addInPattern('closeEnter')
self.closeHandler.addOutPattern('closeExit')
self.closeBubbleNodePath = self.attachNewNode(closeBubbleNode)
(base.cTrav.addCollider(self.closeBubbleNodePath, self.closeHandler),)
self.accept('closeEnter', self.closeEnter)
self.accept('closeExit', self.closeExit)
self.treads = self.find('**/treads')
demotedCeo = Suit.Suit()
demotedCeo.dna = SuitDNA.SuitDNA()
demotedCeo.dna.newSuit('f')
demotedCeo.setDNA(demotedCeo.dna)
demotedCeo.reparentTo(self.geom)
demotedCeo.loop('neutral')
demotedCeo.stash()
self.demotedCeo = demotedCeo
self.bossClub = loader.loadModel('phase_12/models/char/bossbotBoss-golfclub')
overtimeOneClubSequence = Sequence(self.bossClub.colorScaleInterval(0.1, colorScale=VBase4(0, 1, 0, 1)), self.bossClub.colorScaleInterval(0.3, colorScale=VBase4(1, 1, 1, 1)))
overtimeTwoClubSequence = Sequence(self.bossClub.colorScaleInterval(0.1, colorScale=VBase4(1, 0, 0, 1)), self.bossClub.colorScaleInterval(0.3, colorScale=VBase4(1, 1, 1, 1)))
self.bossClubIntervals = [overtimeOneClubSequence, overtimeTwoClubSequence]
self.rightHandJoint = self.find('**/joint17')
self.setPosHpr(*ToontownGlobals.BossbotBossBattleOnePosHpr)
self.reparentTo(render)
self.toonUpSfx = loader.loadSfx('phase_11/audio/sfx/LB_toonup.ogg')
self.warningSfx = loader.loadSfx('phase_5/audio/sfx/Skel_COG_VO_grunt.ogg')
self.swingClubSfx = loader.loadSfx('phase_5/audio/sfx/SA_hardball.ogg')
self.moveBossTaskName = 'CEOMoveTask'
return
def disable(self):
global OneBossCog
self.notify.debug('----- disable')
DistributedBossCog.DistributedBossCog.disable(self)
self.demotedCeo.delete()
base.cTrav.removeCollider(self.closeBubbleNodePath)
taskMgr.remove('RecoverSpeedDamage')
self.request('Off')
self.unloadEnvironment()
self.__cleanupResistanceToon()
if self.servingTimer:
self.servingTimer.destroy()
del self.servingTimer
base.localAvatar.chatMgr.chatInputSpeedChat.removeCEOMenu()
if OneBossCog == self:
OneBossCog = None
self.promotionMusic.stop()
self.betweenPhaseMusic.stop()
self.phaseTwoMusic.stop()
self.phaseFourMusic.stop()
self.interruptMove()
for ival in self.bossClubIntervals:
ival.finish()
self.belts = []
self.tables = {}
self.removeAllTasks()
return
def loadEnvironment(self):
self.notify.debug('----- loadEnvironment')
DistributedBossCog.DistributedBossCog.loadEnvironment(self)
self.geom = loader.loadModel('phase_12/models/bossbotHQ/BanquetInterior_1')
self.elevatorEntrance = self.geom.find('**/elevator_origin')
elevatorModel = loader.loadModel('phase_12/models/bossbotHQ/BB_Inside_Elevator')
if not elevatorModel:
elevatorModel = loader.loadModel('phase_12/models/bossbotHQ/BB_Elevator')
elevatorModel.reparentTo(self.elevatorEntrance)
self.setupElevator(elevatorModel)
self.banquetDoor = self.geom.find('**/door3')
plane = CollisionPlane(Plane(Vec3(0, 0, 1), Point3(0, 0, -50)))
planeNode = CollisionNode('dropPlane')
planeNode.addSolid(plane)
planeNode.setCollideMask(ToontownGlobals.PieBitmask)
self.geom.attachNewNode(planeNode)
self.geom.reparentTo(render)
self.promotionMusic = base.loadMusic('phase_7/audio/bgm/encntr_suit_winning_indoor.ogg')
self.betweenPhaseMusic = base.loadMusic('phase_9/audio/bgm/encntr_toon_winning.ogg')
self.phaseTwoMusic = base.loadMusic('phase_12/audio/bgm/BossBot_CEO_v1.ogg')
self.phaseFourMusic = base.loadMusic('phase_12/audio/bgm/BossBot_CEO_v2.ogg')
self.pickupFoodSfx = loader.loadSfx('phase_6/audio/sfx/SZ_MM_gliss.ogg')
self.explodeSfx = loader.loadSfx('phase_4/audio/sfx/firework_distance_02.ogg')
def unloadEnvironment(self):
self.notify.debug('----- unloadEnvironment')
for belt in self.belts:
if belt:
belt.cleanup()
for spot in self.golfSpots.values():
if spot:
spot.cleanup()
self.golfSpots = {}
self.geom.removeNode()
del self.geom
DistributedBossCog.DistributedBossCog.unloadEnvironment(self)
def __makeResistanceToon(self):
if self.resistanceToon:
return
self.resistanceToon = NPCToons.createLocalNPC(10002)
self.resistanceToon.setPosHpr(*ToontownGlobals.BossbotRTIntroStartPosHpr)
state = random.getstate()
random.seed(self.doId)
self.resistanceToon.suitType = SuitDNA.getRandomSuitByDept('c')
random.setstate(state)
def __cleanupResistanceToon(self):
self.__hideResistanceToon()
if self.resistanceToon:
self.resistanceToon.takeOffSuit()
self.resistanceToon.removeActive()
self.resistanceToon.delete()
self.resistanceToon = None
return
def __showResistanceToon(self, withSuit):
if not self.resistanceToonOnstage:
self.resistanceToon.addActive()
self.resistanceToon.reparentTo(self.geom)
self.resistanceToonOnstage = 1
if withSuit:
suit = self.resistanceToon.suitType
self.resistanceToon.putOnSuit(suit, False)
else:
self.resistanceToon.takeOffSuit()
def __hideResistanceToon(self):
if self.resistanceToonOnstage:
self.resistanceToon.removeActive()
self.resistanceToon.detachNode()
self.resistanceToonOnstage = 0
def enterElevator(self):
DistributedBossCog.DistributedBossCog.enterElevator(self)
self.resistanceToon.removeActive()
self.__showResistanceToon(True)
self.resistanceToon.suit.loop('neutral')
base.camera.setPos(0, 21, 7)
self.reparentTo(render)
self.setPosHpr(*ToontownGlobals.BossbotBossBattleOnePosHpr)
self.loop('Ff_neutral')
self.show()
base.camLens.setMinFov(ToontownGlobals.CEOElevatorFov/(4./3.))
def enterIntroduction(self):
if not self.resistanceToonOnstage:
self.__showResistanceToon(True)
DistributedBossCog.DistributedBossCog.enterIntroduction(self)
base.playMusic(self.promotionMusic, looping=1, volume=0.9)
def exitIntroduction(self):
DistributedBossCog.DistributedBossCog.exitIntroduction(self)
self.promotionMusic.stop()
def makeIntroductionMovie(self, delayDeletes):
rToon = self.resistanceToon
rToonStartPos = Point3(ToontownGlobals.BossbotRTIntroStartPosHpr[0], ToontownGlobals.BossbotRTIntroStartPosHpr[1], ToontownGlobals.BossbotRTIntroStartPosHpr[2])
rToonEndPos = rToonStartPos + Point3(40, 0, 0)
elevCamPosHpr = ToontownGlobals.BossbotElevCamPosHpr
closeUpRTCamPos = Point3(elevCamPosHpr[0], elevCamPosHpr[1], elevCamPosHpr[2])
closeUpRTCamHpr = Point3(elevCamPosHpr[3], elevCamPosHpr[4], elevCamPosHpr[5])
closeUpRTCamPos.setY(closeUpRTCamPos.getY() + 20)
closeUpRTCamPos.setZ(closeUpRTCamPos.getZ() + -2)
closeUpRTCamHpr = Point3(0, 5, 0)
loseSuitCamPos = Point3(rToonStartPos)
loseSuitCamPos += Point3(0, -5, 4)
loseSuitCamHpr = Point3(180, 0, 0)
waiterCamPos = Point3(rToonStartPos)
waiterCamPos += Point3(-5, -10, 5)
waiterCamHpr = Point3(-30, 0, 0)
track = Sequence(Func(camera.reparentTo, render), Func(camera.setPosHpr, *elevCamPosHpr), Func(rToon.setChatAbsolute, TTL.BossbotRTWelcome, CFSpeech), LerpPosHprInterval(camera, 3, closeUpRTCamPos, closeUpRTCamHpr), Func(rToon.setChatAbsolute, TTL.BossbotRTRemoveSuit, CFSpeech), Wait(3), Func(self.clearChat), self.loseCogSuits(self.toonsA + self.toonsB, render, (loseSuitCamPos[0],
loseSuitCamPos[1],
loseSuitCamPos[2],
loseSuitCamHpr[0],
loseSuitCamHpr[1],
loseSuitCamHpr[2])), self.toonNormalEyes(self.involvedToons), Wait(2), Func(camera.setPosHpr, closeUpRTCamPos, closeUpRTCamHpr), Func(rToon.setChatAbsolute, TTL.BossbotRTFightWaiter, CFSpeech), Wait(1), LerpHprInterval(camera, 2, Point3(-15, 5, 0)), Sequence(Func(rToon.suit.loop, 'walk'), rToon.hprInterval(1, VBase3(270, 0, 0)), rToon.posInterval(2.5, rToonEndPos), Func(rToon.suit.loop, 'neutral')), Wait(3), Func(rToon.clearChat), Func(self.__hideResistanceToon))
return track
def enterFrolic(self):
self.notify.debug('----- enterFrolic')
self.setPosHpr(*ToontownGlobals.BossbotBossBattleOnePosHpr)
DistributedBossCog.DistributedBossCog.enterFrolic(self)
self.show()
def enterPrepareBattleTwo(self):
self.controlToons()
self.setToonsToNeutral(self.involvedToons)
for toonId in self.involvedToons:
toon = self.cr.doId2do.get(toonId)
if toon:
toon.takeOffSuit()
self.__showResistanceToon(True)
self.resistanceToon.setPosHpr(*ToontownGlobals.BossbotRTPreTwoPosHpr)
self.__arrangeToonsAroundResistanceToon()
intervalName = 'PrepareBattleTwoMovie'
delayDeletes = []
seq = Sequence(self.makePrepareBattleTwoMovie(delayDeletes), Func(self.__onToBattleTwo), name=intervalName)
seq.delayDeletes = delayDeletes
seq.start()
self.storeInterval(seq, intervalName)
base.playMusic(self.betweenPhaseMusic, looping=1, volume=0.9)
def makePrepareBattleTwoMovie(self, delayDeletes):
for toonId in self.involvedToons:
toon = self.cr.doId2do.get(toonId)
if toon:
delayDeletes.append(DelayDelete.DelayDelete(toon, 'BossbotBoss.makePrepareBattleTwoMovie'))
rToon = self.resistanceToon
rToonStartPos = Point3(ToontownGlobals.BossbotRTPreTwoPosHpr[0], ToontownGlobals.BossbotRTPreTwoPosHpr[1], ToontownGlobals.BossbotRTPreTwoPosHpr[2])
rToonEndPos = rToonStartPos + Point3(-40, 0, 0)
bossPos = Point3(ToontownGlobals.BossbotBossPreTwoPosHpr[0], ToontownGlobals.BossbotBossPreTwoPosHpr[1], ToontownGlobals.BossbotBossPreTwoPosHpr[2])
bossEndPos = Point3(ToontownGlobals.BossbotBossBattleOnePosHpr[0], ToontownGlobals.BossbotBossBattleOnePosHpr[1], ToontownGlobals.BossbotBossBattleOnePosHpr[2])
tempNode = self.attachNewNode('temp')
tempNode.setPos(0, -40, 18)
def getCamBossPos(tempNode = tempNode):
return tempNode.getPos(render)
rNode = rToon.attachNewNode('temp2')
rNode.setPos(-5, 25, 12)
def getCamRTPos(rNode = rNode):
return rNode.getPos(render)
track = Sequence(
Func(camera.reparentTo, render),
Func(camera.setPos, rToon, 0, 22, 6),
Func(camera.setHpr, 0, 0, 0),
Func(rToon.setChatAbsolute, TTL.BossbotRTWearWaiter, CFSpeech),
Wait(3.0),
self.wearCogSuits(self.toonsA + self.toonsB, render, None, waiter=True),
Func(rToon.clearChat),
Func(self.setPosHpr, bossPos, Point3(0, 0, 0)),
Parallel(LerpHprInterval(self.banquetDoor, 2, Point3(90, 0, 0)),
LerpPosInterval(camera, 2, getCamBossPos)),
Func(self.setChatAbsolute, TTL.BossbotBossPreTwo1, CFSpeech),
Wait(3.0),
Func(self.setChatAbsolute, TTL.BossbotBossPreTwo2, CFSpeech),
Wait(3.0),
Parallel(
LerpHprInterval(self.banquetDoor, 2, Point3(0, 0, 0)),
LerpPosHprInterval(camera, 2, getCamRTPos, Point3(10, -8, 0))),
Func(self.setPos, bossEndPos),
Func(self.clearChat),
Func(rToon.setChatAbsolute, TTL.BossbotRTServeFood1, CFSpeech),
Wait(3.0),
Func(rToon.setChatAbsolute, TTL.BossbotRTServeFood2, CFSpeech),
Wait(1.0),
LerpHprInterval(self.banquetDoor, 2, Point3(120, 0, 0)),
Sequence(
Func(rToon.suit.loop, 'walk'),
rToon.hprInterval(1, VBase3(90, 0, 0)),
rToon.posInterval(2.5, rToonEndPos),
Func(rToon.suit.loop, 'neutral')),
self.createWalkInInterval(),
Func(self.banquetDoor.setH, 0),
Func(rToon.clearChat),
Func(self.__hideResistanceToon))
return track
def createWalkInInterval(self):
retval = Parallel()
delay = 0
index = 0
for toonId in self.involvedToons:
toon = base.cr.doId2do.get(toonId)
if not toon:
continue
destPos = Point3(-14 + index * 4, 25, 0)
def toWalk(toon):
if hasattr(toon, 'suit') and toon.suit:
toon.suit.loop('walk')
def toNeutral(toon):
if hasattr(toon, 'suit') and toon.suit:
toon.suit.loop('neutral')
retval.append(Sequence(Wait(delay), Func(toon.wrtReparentTo, render), Func(toWalk, toon), Func(toon.headsUp, 0, 0, 0), LerpPosInterval(toon, 3, Point3(0, 0, 0)), Func(toon.headsUp, destPos), LerpPosInterval(toon, 3, destPos), LerpHprInterval(toon, 1, Point3(0, 0, 0)), Func(toNeutral, toon)))
if toon == base.localAvatar:
retval.append(Sequence(Wait(delay), Func(camera.reparentTo, toon), Func(camera.setPos, toon.cameraPositions[0][0]), Func(camera.setHpr, 0, 0, 0)))
delay += 1.0
index += 1
return retval
def __onToBattleTwo(self, elapsedTime = 0):
self.doneBarrier('PrepareBattleTwo')
def exitPrepareBattleTwo(self):
self.clearInterval('PrepareBattleTwoMovie')
self.betweenPhaseMusic.stop()
def __arrangeToonsAroundResistanceToon(self):
radius = 9
numToons = len(self.involvedToons)
center = (numToons - 1) / 2.0
for i in xrange(numToons):
toon = self.cr.doId2do.get(self.involvedToons[i])
if toon:
angle = 90 - 25 * (i - center)
radians = angle * math.pi / 180.0
x = math.cos(radians) * radius
y = math.sin(radians) * radius
toon.reparentTo(render)
toon.setPos(self.resistanceToon, x, y, 0)
toon.headsUp(self.resistanceToon)
toon.loop('neutral')
toon.show()
def enterBattleTwo(self):
self.releaseToons(finalBattle=1)
for toonId in self.involvedToons:
toon = self.cr.doId2do.get(toonId)
if toon:
self.putToonInCogSuit(toon)
self.servingTimer = ToontownTimer.ToontownTimer()
self.servingTimer.posInTopRightCorner()
self.servingTimer.countdown(ToontownGlobals.BossbotBossServingDuration)
base.playMusic(self.phaseTwoMusic, looping=1, volume=0.9)
intervalName = 'BattleTwoSpeech'
seq = self.createTalkSequence(TTLocalizer.CEOSpeech, 10, intervalName)
seq.start()
self.storeInterval(seq, intervalName)
def exitBattleTwo(self):
if self.servingTimer:
self.servingTimer.destroy()
del self.servingTimer
self.servingTimer = None
for toonId in self.involvedToons:
self.removeFoodFromToon(toonId)
self.clearInterval('BattleTwoSpeech')
self.phaseTwoMusic.stop()
return
def setBelt(self, belt, beltIndex):
if beltIndex < len(self.belts):
self.belts[beltIndex] = belt
def localToonTouchedBeltFood(self, beltIndex, foodIndex, foodNum):
avId = base.localAvatar.doId
doRequest = False
if avId not in self.toonFoodStatus:
doRequest = True
elif not self.toonFoodStatus[avId]:
doRequest = True
if doRequest:
self.sendUpdate('requestGetFood', [beltIndex, foodIndex, foodNum])
def toonGotFood(self, avId, beltIndex, foodIndex, foodNum):
if self.belts[beltIndex]:
self.belts[beltIndex].removeFood(foodIndex)
self.putFoodOnToon(avId, beltIndex, foodNum)
def putFoodOnToon(self, avId, beltIndex, foodNum):
self.toonFoodStatus[avId] = (beltIndex, foodNum)
av = base.cr.doId2do.get(avId)
if av:
if hasattr(av, 'suit'):
intervalName = self.uniqueName('loadFoodSoundIval-%d' % avId)
seq = SoundInterval(self.pickupFoodSfx, node=av, name=intervalName)
oldSeq = self.activeIntervals.get(intervalName)
if oldSeq:
oldSeq.finish()
seq.start()
self.activeIntervals[intervalName] = seq
foodModel = loader.loadModel('phase_12/models/bossbotHQ/canoffood')
foodModel.setName('cogFood')
foodModel.setScale(ToontownGlobals.BossbotFoodModelScale)
foodModel.reparentTo(av.suit.getRightHand())
foodModel.setHpr(52.1961, 180.4983, -4.2882)
curAnim = av.suit.getCurrentAnim()
self.notify.debug('curAnim=%s' % curAnim)
if curAnim in ('walk', 'run'):
av.suit.loop('tray-walk')
elif curAnim == 'neutral':
self.notify.debug('looping tray-netural')
av.suit.loop('tray-neutral')
else:
self.notify.warning("don't know what to do with anim=%s" % curAnim)
def removeFoodFromToon(self, avId):
self.toonFoodStatus[avId] = None
av = base.cr.doId2do.get(avId)
if av:
cogFood = av.find('**/cogFood')
if not cogFood.isEmpty():
cogFood.removeNode()
return
def detachFoodFromToon(self, avId):
cogFood = None
self.toonFoodStatus[avId] = None
av = base.cr.doId2do.get(avId)
if av:
cogFood = av.find('**/cogFood')
if not cogFood.isEmpty():
retval = cogFood
cogFood.wrtReparentTo(render)
curAnim = av.suit.getCurrentAnim()
self.notify.debug('curAnim=%s' % curAnim)
if curAnim == 'tray-walk':
av.suit.loop('run')
elif curAnim == 'tray-neutral':
av.suit.loop('neutral')
else:
self.notify.warning("don't know what to do with anim=%s" % curAnim)
return cogFood
def setTable(self, table, tableIndex):
self.tables[tableIndex] = table
def localToonTouchedChair(self, tableIndex, chairIndex):
avId = base.localAvatar.doId
if avId in self.toonFoodStatus and self.toonFoodStatus[avId] != None:
self.sendUpdate('requestServeFood', [tableIndex, chairIndex])
return
def toonServeFood(self, avId, tableIndex, chairIndex):
food = self.detachFoodFromToon(avId)
table = self.tables[tableIndex]
table.serveFood(food, chairIndex)
def enterPrepareBattleThree(self):
self.calcNotDeadList()
self.battleANode.setPosHpr(*ToontownGlobals.DinerBattleAPosHpr)
self.battleBNode.setPosHpr(*ToontownGlobals.DinerBattleBPosHpr)
self.cleanupIntervals()
self.controlToons()
self.setToonsToNeutral(self.involvedToons)
for toonId in self.involvedToons:
toon = self.cr.doId2do.get(toonId)
if toon:
self.putToonInCogSuit(toon)
intervalName = 'PrepareBattleThreeMovie'
seq = Sequence(self.makePrepareBattleThreeMovie(), Func(self.__onToBattleThree), name=intervalName)
seq.start()
self.storeInterval(seq, intervalName)
base.playMusic(self.betweenPhaseMusic, looping=1, volume=0.9)
def calcNotDeadList(self):
if not self.notDeadList:
self.notDeadList = []
for tableIndex in xrange(len(self.tables)):
table = self.tables[tableIndex]
tableInfo = table.getNotDeadInfo()
self.notDeadList += tableInfo
def exitPrepareBattleThree(self):
self.clearInterval('PrepareBattleThreeMovie')
self.betweenPhaseMusic.stop()
def __onToBattleThree(self, elapsedTime = 0):
self.doneBarrier('PrepareBattleThree')
def makePrepareBattleThreeMovie(self):
loseSuitCamAngle = (0, 19, 6, -180, -5, 0)
track = Sequence(
Func(camera.reparentTo, self),
Func(camera.setPos, Point3(0, -45, 5)),
Func(camera.setHpr, Point3(0, 14, 0)),
Func(self.setChatAbsolute, TTL.BossbotPhase3Speech1, CFSpeech),
Wait(3.0),
Func(self.setChatAbsolute, TTL.BossbotPhase3Speech2, CFSpeech),
Wait(3.0),
Func(camera.setPosHpr, base.localAvatar, *loseSuitCamAngle),
Wait(1.0),
self.loseCogSuits(self.toonsA + self.toonsB, base.localAvatar, loseSuitCamAngle),
self.toonNormalEyes(self.involvedToons),
Wait(2),
Func(camera.reparentTo, self),
Func(camera.setPos, Point3(0, -45, 5)),
Func(camera.setHpr, Point3(0, 14, 0)),
Func(self.setChatAbsolute, TTL.BossbotPhase3Speech3, CFSpeech),
Wait(3.0),
Func(self.clearChat))
return track
def enterBattleThree(self):
self.cleanupIntervals()
self.calcNotDeadList()
for table in self.tables.values():
table.setAllDinersToSitNeutral()
self.battleANode.setPosHpr(*ToontownGlobals.DinerBattleAPosHpr)
self.battleBNode.setPosHpr(*ToontownGlobals.DinerBattleBPosHpr)
self.setToonsToNeutral(self.involvedToons)
for toonId in self.involvedToons:
toon = self.cr.doId2do.get(toonId)
if toon:
toon.takeOffSuit()
mult = 1
localAvatar.inventory.setBattleCreditMultiplier(mult)
self.toonsToBattlePosition(self.toonsA, self.battleANode)
self.toonsToBattlePosition(self.toonsB, self.battleBNode)
self.releaseToons()
base.playMusic(self.battleOneMusic, looping=1, volume=0.9)
def exitBattleThree(self):
self.cleanupBattles()
self.battleOneMusic.stop()
localAvatar.inventory.setBattleCreditMultiplier(1)
def claimOneChair(self):
chairInfo = None
if self.notDeadList:
chairInfo = self.notDeadList.pop()
return chairInfo
def enterPrepareBattleFour(self):
self.controlToons()
intervalName = 'PrepareBattleFourMovie'
seq = Sequence(self.makePrepareBattleFourMovie(), Func(self.__onToBattleFour), name=intervalName)
seq.start()
self.storeInterval(seq, intervalName)
base.playMusic(self.phaseFourMusic, looping=1, volume=0.9)
def exitPrepareBattleFour(self):
self.clearInterval('PrepareBattleFourMovie')
self.phaseFourMusic.stop()
def makePrepareBattleFourMovie(self):
rToon = self.resistanceToon
offsetZ = rToon.suit.getHeight() / 2.0
track = Sequence(
Func(self.__showResistanceToon, True),
Func(rToon.setPos, Point3(0, -5, 0)),
Func(rToon.setHpr, Point3(0, 0, 0)),
Func(camera.reparentTo, rToon),
Func(camera.setPos, Point3(0, 13, 3 + offsetZ)),
Func(camera.setHpr, Point3(-180, 0, 0)),
Func(self.banquetDoor.setH, 90),
Func(rToon.setChatAbsolute, TTL.BossbotRTPhase4Speech1, CFSpeech),
Wait(4.0),
Func(rToon.setChatAbsolute, TTL.BossbotRTPhase4Speech2, CFSpeech),
Wait(4.0),
Func(self.__hideResistanceToon),
Func(camera.reparentTo, self),
Func(camera.setPos, Point3(0, -45, 5)),
Func(camera.setHpr, Point3(0, 14, 0)),
Func(self.setChatAbsolute, TTL.BossbotPhase4Speech1, CFSpeech),
Func(self.banquetDoor.setH, 0),
Wait(3.0),
Func(self.setChatAbsolute, TTL.BossbotPhase4Speech2, CFSpeech),
Func(self.bossClub.setScale, 0.01),
Func(self.bossClub.reparentTo, self.rightHandJoint),
LerpScaleInterval(self.bossClub, 3, Point3(1, 1, 1)),
Func(self.clearChat))
return track
def __onToBattleFour(self, elapsedTime = 0):
self.doneBarrier('PrepareBattleFour')
def enterBattleFour(self):
DistributedBossCog.DistributedBossCog.enterBattleFour(self)
self.releaseToons(finalBattle=1)
self.setToonsToNeutral(self.involvedToons)
for toonId in self.involvedToons:
toon = self.cr.doId2do.get(toonId)
if toon:
toon.takeOffSuit()
self.bossClub.reparentTo(self.rightHandJoint)
self.generateHealthBar()
self.updateHealthBar()
base.playMusic(self.phaseFourMusic, looping=1, volume=0.9)
def exitBattleFour(self):
DistributedBossCog.DistributedBossCog.exitBattleFour(self)
self.phaseFourMusic.stop()
def d_hitBoss(self, bossDamage):
self.sendUpdate('hitBoss', [bossDamage])
def d_ballHitBoss(self, bossDamage):
self.sendUpdate('ballHitBoss', [bossDamage])
def setBossDamage(self, bossDamage, recoverRate, recoverStartTime):
if bossDamage > self.bossDamage:
delta = bossDamage - self.bossDamage
self.flashRed()
self.showHpText(-delta, scale=5)
self.bossDamage = bossDamage
self.updateHealthBar()
def setGolfSpot(self, golfSpot, golfSpotIndex):
self.golfSpots[golfSpotIndex] = golfSpot
def enterVictory(self):
self.notify.debug('----- enterVictory')
self.cleanupIntervals()
self.cleanupAttacks()
self.doAnimate('Ff_neutral', now=1)
self.stopMoveTask()
if hasattr(self, 'tableIndex'):
table = self.tables[self.tableIndex]
table.tableGroup.hide()
self.loop('neutral')
localAvatar.setCameraFov(ToontownGlobals.BossBattleCameraFov)
self.clearChat()
self.controlToons()
self.setToonsToNeutral(self.involvedToons)
self.happy = 1
self.raised = 1
self.forward = 1
intervalName = 'VictoryMovie'
seq = Sequence(self.makeVictoryMovie(), Func(self.__continueVictory), name=intervalName)
seq.start()
self.storeInterval(seq, intervalName)
base.playMusic(self.phaseFourMusic, looping=1, volume=0.9)
def __continueVictory(self):
self.notify.debug('----- __continueVictory')
self.stopAnimate()
self.doneBarrier('Victory')
def exitVictory(self):
self.notify.debug('----- exitVictory')
self.stopAnimate()
self.unstash()
localAvatar.setCameraFov(ToontownGlobals.CogHQCameraFov)
self.phaseFourMusic.stop()
def makeVictoryMovie(self):
self.show()
dustCloud = DustCloud.DustCloud(fBillboard=0, wantSound=1)
dustCloud.reparentTo(self)
dustCloud.setPos(0, -10, 3)
dustCloud.setScale(4)
dustCloud.wrtReparentTo(self.geom)
dustCloud.createTrack(12)
newHpr = self.getHpr()
newHpr.setX(newHpr.getX() + 180)
bossTrack = Sequence(
Func(self.show),
Func(camera.reparentTo, self),
Func(camera.setPos, Point3(0, -35, 25)),
Func(camera.setHpr, Point3(0, -20, 0)),
Func(self.setChatAbsolute, TTL.BossbotRewardSpeech1, CFSpeech),
Wait(3.0),
Func(self.setChatAbsolute, TTL.BossbotRewardSpeech2, CFSpeech),
Wait(2.0),
Func(self.clearChat),
Parallel(
Sequence(
Wait(0.5),
Func(self.demotedCeo.setPos, self.getPos()),
Func(self.demotedCeo.setHpr, newHpr),
Func(self.hide),
Wait(0.5),
Func(self.demotedCeo.reparentTo, self.geom),
Func(self.demotedCeo.unstash)),
Sequence(dustCloud.track)),
Wait(2.0),
Func(dustCloud.destroy))
return bossTrack
def enterReward(self):
self.cleanupIntervals()
self.clearChat()
self.resistanceToon.clearChat()
self.stash()
self.stopAnimate()
self.controlToons()
panelName = self.uniqueName('reward')
self.rewardPanel = RewardPanel.RewardPanel(panelName)
victory, camVictory, skipper = MovieToonVictory.doToonVictory(1, self.involvedToons, self.toonRewardIds, self.toonRewardDicts, self.deathList, self.rewardPanel, allowGroupShot=0, uberList=self.uberList, noSkip=True)
ival = Sequence(Parallel(victory, camVictory), Func(self.__doneReward))
intervalName = 'RewardMovie'
delayDeletes = []
for toonId in self.involvedToons:
toon = self.cr.doId2do.get(toonId)
if toon:
delayDeletes.append(DelayDelete.DelayDelete(toon, 'BossbotBoss.enterReward'))
ival.delayDeletes = delayDeletes
ival.start()
self.storeInterval(ival, intervalName)
base.playMusic(self.betweenPhaseMusic, looping=1, volume=0.9)
def __doneReward(self):
self.notify.debug('----- __doneReward')
self.doneBarrier('Reward')
self.toWalkMode()
def exitReward(self):
self.notify.debug('----- exitReward')
intervalName = 'RewardMovie'
self.clearInterval(intervalName)
self.unstash()
self.rewardPanel.destroy()
del self.rewardPanel
self.betweenPhaseMusic.stop()
def enterEpilogue(self):
self.cleanupIntervals()
self.clearChat()
self.resistanceToon.clearChat()
self.stash()
self.stopAnimate()
self.controlToons()
self.__showResistanceToon(False)
self.resistanceToon.reparentTo(render)
self.resistanceToon.setPosHpr(*ToontownGlobals.BossbotRTEpiloguePosHpr)
self.resistanceToon.loop('Sit')
self.__arrangeToonsAroundResistanceToonForReward()
camera.reparentTo(render)
camera.setPos(self.resistanceToon, -9, 12, 6)
camera.lookAt(self.resistanceToon, 0, 0, 3)
intervalName = 'EpilogueMovie'
seq = Sequence(self.makeEpilogueMovie(), name=intervalName)
seq.start()
self.storeInterval(seq, intervalName)
self.accept('doneChatPage', self.__doneEpilogue)
base.playMusic(self.epilogueMusic, looping=1, volume=0.9)
def __doneEpilogue(self, elapsedTime = 0):
self.notify.debug('----- __doneEpilogue')
intervalName = 'EpilogueMovieToonAnim'
self.clearInterval(intervalName)
track = Parallel(Sequence(Wait(0.5), Func(self.localToonToSafeZone)))
self.storeInterval(track, intervalName)
track.start()
def exitEpilogue(self):
self.notify.debug('----- exitEpilogue')
self.clearInterval('EpilogueMovieToonAnim')
self.unstash()
self.epilogueMusic.stop()
def makeEpilogueMovie(self):
epSpeech = TTLocalizer.BossbotRTCongratulations
epSpeech = self.__talkAboutPromotion(epSpeech)
bossTrack = Sequence(Func(self.resistanceToon.animFSM.request, 'neutral'), Func(self.resistanceToon.setLocalPageChat, epSpeech, 0))
return bossTrack
def __talkAboutPromotion(self, speech):
if self.prevCogSuitLevel < ToontownGlobals.MaxCogSuitLevel:
newCogSuitLevel = localAvatar.getCogLevels()[CogDisguiseGlobals.dept2deptIndex(self.style.dept)]
if newCogSuitLevel == ToontownGlobals.MaxCogSuitLevel:
speech += TTLocalizer.BossbotRTLastPromotion % (ToontownGlobals.MaxCogSuitLevel + 1)
if newCogSuitLevel in ToontownGlobals.CogSuitHPLevels:
speech += TTLocalizer.BossbotRTHPBoost
else:
speech += TTLocalizer.BossbotRTMaxed % (ToontownGlobals.MaxCogSuitLevel + 1)
if self.keyReward:
speech += TTLocalizer.BossRTKeyReward
return speech
def __arrangeToonsAroundResistanceToonForReward(self):
radius = 7
numToons = len(self.involvedToons)
center = (numToons - 1) / 2.0
for i in xrange(numToons):
toon = self.cr.doId2do.get(self.involvedToons[i])
if toon:
angle = 90 - 15 * (i - center)
radians = angle * math.pi / 180.0
x = math.cos(radians) * radius
y = math.sin(radians) * radius
toon.setPos(self.resistanceToon, x, y, 0)
toon.headsUp(self.resistanceToon)
toon.loop('neutral')
toon.show()
def doDirectedAttack(self, avId, attackCode):
toon = base.cr.doId2do.get(avId)
if toon:
distance = toon.getDistance(self)
gearRoot = self.rotateNode.attachNewNode('gearRoot-atk%d' % self.numAttacks)
gearRoot.setZ(10)
gearRoot.setTag('attackCode', str(attackCode))
gearModel = self.getGearFrisbee()
gearModel.setScale(0.2)
gearRoot.headsUp(toon)
toToonH = PythonUtil.fitDestAngle2Src(0, gearRoot.getH() + 180)
gearRoot.lookAt(toon)
neutral = 'Fb_neutral'
if not self.twoFaced:
neutral = 'Ff_neutral'
gearTrack = Parallel()
for i in xrange(4):
nodeName = '%s-%s' % (str(i), globalClock.getFrameTime())
node = gearRoot.attachNewNode(nodeName)
node.hide()
node.setPos(0, 5.85, 4.0)
gear = gearModel.instanceTo(node)
x = random.uniform(-5, 5)
z = random.uniform(-3, 3)
h = random.uniform(-720, 720)
if i == 2:
x = 0
z = 0
def detachNode(node):
if not node.isEmpty():
node.detachNode()
return Task.done
def detachNodeLater(node = node):
if node.isEmpty():
return
center = node.node().getBounds().getCenter()
node.node().setBounds(BoundingSphere(center, distance * 1.5))
node.node().setFinal(1)
self.doMethodLater(0.005, detachNode, 'detach-%s-%s' % (gearRoot.getName(), node.getName()), extraArgs=[node])
gearTrack.append(Sequence(Wait(i * 0.15), Func(node.show), Parallel(node.posInterval(1, Point3(x, distance, z), fluid=1), node.hprInterval(1, VBase3(h, 0, 0), fluid=1)), Func(detachNodeLater)))
if not self.raised:
neutral1Anim = self.getAnim('down2Up')
self.raised = 1
else:
neutral1Anim = ActorInterval(self, neutral, startFrame=48)
throwAnim = self.getAnim('throw')
neutral2Anim = ActorInterval(self, neutral)
extraAnim = Sequence()
if attackCode == ToontownGlobals.BossCogSlowDirectedAttack:
extraAnim = ActorInterval(self, neutral)
def detachGearRoot(task, gearRoot = gearRoot):
if not gearRoot.isEmpty():
gearRoot.detachNode()
return task.done
def detachGearRootLater(gearRoot = gearRoot):
if gearRoot.isEmpty():
return
self.doMethodLater(0.01, detachGearRoot, 'detach-%s' % gearRoot.getName())
seq = Sequence(ParallelEndTogether(self.pelvis.hprInterval(1, VBase3(toToonH, 0, 0)), neutral1Anim), extraAnim, Parallel(Sequence(Wait(0.19), gearTrack, Func(detachGearRootLater), self.pelvis.hprInterval(0.2, VBase3(0, 0, 0))), Sequence(Func(self.setChatAbsolute, random.choice(TTLocalizer.DirectedAttackBossTaunts[self.dna.dept]) % {'toon': toon.getName()}, CFSpeech | CFTimeout), throwAnim, neutral2Anim)))
self.doAnimate(seq, now=1, raised=1)
def setBattleDifficulty(self, diff):
self.notify.debug('battleDifficulty = %d' % diff)
self.battleDifficulty = diff
def doMoveAttack(self, tableIndex):
self.tableIndex = tableIndex
table = self.tables[tableIndex]
fromPos = self.getPos()
fromHpr = self.getHpr()
toPos = table.getPos()
foo = render.attachNewNode('foo')
foo.setPos(self.getPos())
foo.setHpr(self.getHpr())
foo.lookAt(table.getLocator())
toHpr = foo.getHpr()
toHpr.setX(toHpr.getX() - 180)
foo.removeNode()
reverse = False
moveTrack, hpr = self.moveBossToPoint(fromPos, fromHpr, toPos, toHpr, reverse)
self.moveTrack = moveTrack
self.moveTrack.start()
self.storeInterval(self.moveTrack, 'moveTrack')
def interruptMove(self):
if self.moveTrack and self.moveTrack.isPlaying():
self.moveTrack.pause()
self.stopMoveTask()
def setAttackCode(self, attackCode, avId = 0):
if self.state != 'BattleFour':
return
self.numAttacks += 1
self.notify.debug('numAttacks=%d' % self.numAttacks)
self.attackCode = attackCode
self.attackAvId = avId
if attackCode == ToontownGlobals.BossCogMoveAttack:
self.interruptMove()
self.doMoveAttack(avId)
elif attackCode == ToontownGlobals.BossCogGolfAttack:
self.interruptMove()
self.cleanupAttacks()
self.doGolfAttack(avId, attackCode)
elif attackCode == ToontownGlobals.BossCogDizzy:
self.setDizzy(1)
self.cleanupAttacks()
self.doAnimate(None, raised=0, happy=1)
elif attackCode == ToontownGlobals.BossCogDizzyNow:
self.setDizzy(1)
self.cleanupAttacks()
self.doAnimate('hit', happy=1, now=1)
elif attackCode == ToontownGlobals.BossCogSwatLeft:
self.setDizzy(0)
self.doAnimate('ltSwing', now=1)
elif attackCode == ToontownGlobals.BossCogSwatRight:
self.setDizzy(0)
self.doAnimate('rtSwing', now=1)
elif attackCode == ToontownGlobals.BossCogAreaAttack:
self.setDizzy(0)
self.doAnimate('areaAttack', now=1)
elif attackCode == ToontownGlobals.BossCogFrontAttack:
self.setDizzy(0)
self.doAnimate('frontAttack', now=1)
elif attackCode == ToontownGlobals.BossCogRecoverDizzyAttack:
self.setDizzy(0)
self.doAnimate('frontAttack', now=1)
elif attackCode == ToontownGlobals.BossCogDirectedAttack or attackCode == ToontownGlobals.BossCogSlowDirectedAttack or attackCode == ToontownGlobals.BossCogGearDirectedAttack:
self.interruptMove()
self.setDizzy(0)
self.doDirectedAttack(avId, attackCode)
elif attackCode == ToontownGlobals.BossCogGolfAreaAttack:
self.interruptMove()
self.setDizzy(0)
self.doGolfAreaAttack()
elif attackCode == ToontownGlobals.BossCogNoAttack:
self.setDizzy(0)
self.doAnimate(None, raised=1)
elif attackCode == ToontownGlobals.BossCogOvertimeAttack:
self.interruptMove()
self.setDizzy(0)
self.cleanupAttacks()
self.doOvertimeAttack(avId)
return
def signalAtTable(self):
self.sendUpdate('reachedTable', [self.tableIndex])
def closeEnter(self, colEntry):
tableStr = colEntry.getIntoNodePath().getNetTag('tableIndex')
if tableStr:
tableIndex = int(tableStr)
self.sendUpdate('hitTable', [tableIndex])
def closeExit(self, colEntry):
tableStr = colEntry.getIntoNodePath().getNetTag('tableIndex')
if tableStr:
tableIndex = int(tableStr)
if self.tableIndex != tableIndex:
self.sendUpdate('awayFromTable', [tableIndex])
def setSpeedDamage(self, speedDamage, recoverRate, timestamp):
recoverStartTime = globalClockDelta.networkToLocalTime(timestamp)
self.speedDamage = speedDamage
self.speedRecoverRate = recoverRate
self.speedRecoverStartTime = recoverStartTime
speedFraction = max(1 - speedDamage / self.maxSpeedDamage, 0)
self.treads.setColorScale(1, speedFraction, speedFraction, 1)
taskName = 'RecoverSpeedDamage'
taskMgr.remove(taskName)
if self.speedRecoverRate:
taskMgr.add(self.__recoverSpeedDamage, taskName)
def getSpeedDamage(self):
now = globalClock.getFrameTime()
elapsed = now - self.speedRecoverStartTime
return max(self.speedDamage - self.speedRecoverRate * elapsed / 60.0, 0)
def getFractionalSpeedDamage(self):
result = self.getSpeedDamage() / self.maxSpeedDamage
return result
def __recoverSpeedDamage(self, task):
speedDamage = self.getSpeedDamage()
speedFraction = max(1 - speedDamage / self.maxSpeedDamage, 0)
self.treads.setColorScale(1, speedFraction, speedFraction, 1)
return task.cont
def moveBossToPoint(self, fromPos, fromHpr, toPos, toHpr, reverse):
vector = Vec3(toPos - fromPos)
distance = vector.length()
self.distanceToTravel = distance
self.notify.debug('self.distanceToTravel = %s' % self.distanceToTravel)
if toHpr == None:
mat = Mat3(0, 0, 0, 0, 0, 0, 0, 0, 0)
headsUp(mat, vector, CSDefault)
scale = VBase3(0, 0, 0)
shear = VBase3(0, 0, 0)
toHpr = VBase3(0, 0, 0)
decomposeMatrix(mat, scale, shear, toHpr, CSDefault)
if fromHpr:
newH = PythonUtil.fitDestAngle2Src(fromHpr[0], toHpr[0])
toHpr = VBase3(newH, 0, 0)
else:
fromHpr = toHpr
turnTime = abs(toHpr[0] - fromHpr[0]) / self.getCurTurnSpeed()
if toHpr[0] < fromHpr[0]:
leftRate = ToontownGlobals.BossCogTreadSpeed
else:
leftRate = -ToontownGlobals.BossCogTreadSpeed
if reverse:
rollTreadRate = -ToontownGlobals.BossCogTreadSpeed
else:
rollTreadRate = ToontownGlobals.BossCogTreadSpeed
rollTime = distance / ToontownGlobals.BossCogRollSpeed
deltaPos = toPos - fromPos
self.toPos = toPos
self.fromPos = fromPos
self.dirVector = self.toPos - self.fromPos
self.dirVector.normalize()
track = Sequence(Func(self.setPos, fromPos), Func(self.headsUp, toPos), Parallel(self.hprInterval(turnTime, toHpr, fromHpr), self.rollLeftTreads(turnTime, leftRate), self.rollRightTreads(turnTime, -leftRate)), Func(self.startMoveTask))
return (track, toHpr)
def getCurTurnSpeed(self):
result = ToontownGlobals.BossbotTurnSpeedMax - (ToontownGlobals.BossbotTurnSpeedMax - ToontownGlobals.BossbotTurnSpeedMin) * self.getFractionalSpeedDamage()
return result
def getCurRollSpeed(self):
result = ToontownGlobals.BossbotRollSpeedMax - (ToontownGlobals.BossbotRollSpeedMax - ToontownGlobals.BossbotRollSpeedMin) * self.getFractionalSpeedDamage()
return result
def getCurTreadSpeed(self):
result = ToontownGlobals.BossbotTreadSpeedMax - (ToontownGlobals.BossbotTreadSpeedMax - ToontownGlobals.BossbotTreadSpeedMin) * self.getFractionalSpeedDamage()
return result
def startMoveTask(self):
taskMgr.add(self.moveBossTask, self.moveBossTaskName)
def stopMoveTask(self):
taskMgr.remove(self.moveBossTaskName)
def moveBossTask(self, task):
dt = globalClock.getDt()
distanceTravelledThisFrame = dt * self.getCurRollSpeed()
diff = self.toPos - self.getPos()
distanceLeft = diff.length()
def rollTexMatrix(t, object = object):
object.setTexOffset(TextureStage.getDefault(), t, 0)
self.treadsLeftPos += dt * self.getCurTreadSpeed()
self.treadsRightPos += dt * self.getCurTreadSpeed()
rollTexMatrix(self.treadsLeftPos, self.treadsLeft)
rollTexMatrix(self.treadsRightPos, self.treadsRight)
if distanceTravelledThisFrame >= distanceLeft:
self.setPos(self.toPos)
self.signalAtTable()
return Task.done
else:
newPos = self.getPos() + self.dirVector * dt * self.getCurRollSpeed()
self.setPos(newPos)
return Task.cont
def doZapToon(self, toon, pos = None, hpr = None, ts = 0, fling = 1, shake = 1):
zapName = toon.uniqueName('zap')
self.clearInterval(zapName)
zapTrack = Sequence(name=zapName)
if toon == localAvatar:
self.toOuchMode()
messenger.send('interrupt-pie')
self.enableLocalToonSimpleCollisions()
else:
zapTrack.append(Func(toon.stopSmooth))
def getSlideToPos(toon = toon):
return render.getRelativePoint(toon, Point3(0, -5, 0))
if pos != None and hpr != None:
(zapTrack.append(Func(toon.setPosHpr, pos, hpr)),)
toonTrack = Parallel()
if shake and toon == localAvatar:
toonTrack.append(Sequence(Func(camera.setZ, camera, 1), Wait(0.15), Func(camera.setZ, camera, -2), Wait(0.15), Func(camera.setZ, camera, 1)))
if fling:
if self.isToonRoaming(toon.doId):
toonTrack += [ActorInterval(toon, 'slip-backward')]
toonTrack += [toon.posInterval(0.5, getSlideToPos, fluid=1)]
else:
toonTrack += [ActorInterval(toon, 'slip-forward')]
zapTrack.append(toonTrack)
if toon == localAvatar:
zapTrack.append(Func(self.disableLocalToonSimpleCollisions))
currentState = self.state
if currentState in ('BattleFour', 'BattleTwo'):
zapTrack.append(Func(self.toFinalBattleMode))
else:
self.notify.warning('doZapToon going to walkMode, how did this happen?')
zapTrack.append(Func(self.toWalkMode))
else:
zapTrack.append(Func(toon.startSmooth))
if ts > 0:
startTime = ts
else:
zapTrack = Sequence(Wait(-ts), zapTrack)
startTime = 0
zapTrack.append(Func(self.clearInterval, zapName))
zapTrack.delayDelete = DelayDelete.DelayDelete(toon, 'BossbotBoss.doZapToon')
zapTrack.start(startTime)
self.storeInterval(zapTrack, zapName)
return
def zapLocalToon(self, attackCode, origin = None):
if self.localToonIsSafe or localAvatar.ghostMode or localAvatar.isStunned:
return
if globalClock.getFrameTime() < self.lastZapLocalTime + 1.0:
return
else:
self.lastZapLocalTime = globalClock.getFrameTime()
self.notify.debug('zapLocalToon frameTime=%s' % globalClock.getFrameTime())
messenger.send('interrupt-pie')
place = self.cr.playGame.getPlace()
currentState = None
if place:
currentState = place.fsm.getCurrentState().getName()
if currentState != 'walk' and currentState != 'finalBattle' and currentState != 'crane':
return
self.notify.debug('continuing zap')
toon = localAvatar
fling = 1
shake = 0
if attackCode == ToontownGlobals.BossCogAreaAttack:
fling = 0
shake = 1
if fling:
if origin == None:
origin = self
if self.isToonRoaming(toon.doId):
camera.wrtReparentTo(render)
toon.headsUp(origin)
camera.wrtReparentTo(toon)
bossRelativePos = toon.getPos(self.getGeomNode())
bp2d = Vec2(bossRelativePos[0], bossRelativePos[1])
bp2d.normalize()
pos = toon.getPos()
hpr = toon.getHpr()
timestamp = globalClockDelta.getFrameNetworkTime()
self.sendUpdate('zapToon', [pos[0],
pos[1],
pos[2],
hpr[0],
hpr[1],
hpr[2],
bp2d[0],
bp2d[1],
attackCode,
timestamp])
self.doZapToon(toon, fling=fling, shake=shake)
return
def getToonTableIndex(self, toonId):
tableIndex = -1
for table in self.tables.values():
if table.avId == toonId:
tableIndex = table.index
break
return tableIndex
def getToonGolfSpotIndex(self, toonId):
golfSpotIndex = -1
for golfSpot in self.golfSpots.values():
if golfSpot.avId == toonId:
golfSpotIndex = golfSpot.index
break
return golfSpotIndex
def isToonOnTable(self, toonId):
result = self.getToonTableIndex(toonId) != -1
return result
def isToonOnGolfSpot(self, toonId):
result = self.getToonGolfSpotIndex(toonId) != -1
return result
def isToonRoaming(self, toonId):
result = not self.isToonOnTable(toonId) and not self.isToonOnGolfSpot(toonId)
return result
def getGolfBall(self):
golfRoot = NodePath('golfRoot')
golfBall = loader.loadModel('phase_6/models/golf/golf_ball')
golfBall.setColorScale(0.75, 0.75, 0.75, 0.5)
golfBall.setTransparency(1)
ballScale = 5
golfBall.setScale(ballScale)
golfBall.reparentTo(golfRoot)
cs = CollisionSphere(0, 0, 0, ballScale * 0.25)
cs.setTangible(0)
cn = CollisionNode('BossZap')
cn.addSolid(cs)
cn.setIntoCollideMask(ToontownGlobals.WallBitmask)
cnp = golfRoot.attachNewNode(cn)
return golfRoot
def doGolfAttack(self, avId, attackCode):
toon = base.cr.doId2do.get(avId)
if toon:
distance = toon.getDistance(self)
self.notify.debug('distance = %s' % distance)
gearRoot = self.rotateNode.attachNewNode('gearRoot-atk%d' % self.numAttacks)
gearRoot.setZ(10)
gearRoot.setTag('attackCode', str(attackCode))
gearModel = self.getGolfBall()
self.ballLaunch = NodePath('')
self.ballLaunch.reparentTo(gearRoot)
self.ballLaunch.setPos(self.BallLaunchOffset)
gearRoot.headsUp(toon)
toToonH = PythonUtil.fitDestAngle2Src(0, gearRoot.getH() + 180)
gearRoot.lookAt(toon)
neutral = 'Fb_neutral'
if not self.twoFaced:
neutral = 'Ff_neutral'
gearTrack = Parallel()
for i in xrange(5):
nodeName = '%s-%s' % (str(i), globalClock.getFrameTime())
node = gearRoot.attachNewNode(nodeName)
node.hide()
node.reparentTo(self.ballLaunch)
node.wrtReparentTo(gearRoot)
distance = toon.getDistance(node)
gear = gearModel.instanceTo(node)
x = random.uniform(-5, 5)
z = random.uniform(-3, 3)
p = random.uniform(-720, -90)
y = distance + random.uniform(5, 15)
if i == 2:
x = 0
z = 0
y = distance + 10
def detachNode(node):
if not node.isEmpty():
node.detachNode()
return Task.done
def detachNodeLater(node = node):
if node.isEmpty():
return
node.node().setBounds(BoundingSphere(Point3(0, 0, 0), distance * 1.5))
node.node().setFinal(1)
self.doMethodLater(0.005, detachNode, 'detach-%s-%s' % (gearRoot.getName(), node.getName()), extraArgs=[node])
gearTrack.append(Sequence(Wait(26.0 / 24.0), Wait(i * 0.15), Func(node.show), Parallel(node.posInterval(1, Point3(x, y, z), fluid=1), node.hprInterval(1, VBase3(0, p, 0), fluid=1)), Func(detachNodeLater)))
if not self.raised:
neutral1Anim = self.getAnim('down2Up')
self.raised = 1
else:
neutral1Anim = ActorInterval(self, neutral, startFrame=48)
throwAnim = self.getAnim('golf_swing')
neutral2Anim = ActorInterval(self, neutral)
extraAnim = Sequence()
if attackCode == ToontownGlobals.BossCogSlowDirectedAttack:
extraAnim = ActorInterval(self, neutral)
def detachGearRoot(task, gearRoot = gearRoot):
if not gearRoot.isEmpty():
gearRoot.detachNode()
return task.done
def detachGearRootLater(gearRoot = gearRoot):
self.doMethodLater(0.01, detachGearRoot, 'detach-%s' % gearRoot.getName())
seq = Sequence(ParallelEndTogether(self.pelvis.hprInterval(1, VBase3(toToonH, 0, 0)), neutral1Anim), extraAnim, Parallel(Sequence(Wait(0.19), gearTrack, Func(detachGearRootLater), self.pelvis.hprInterval(0.2, VBase3(0, 0, 0))), Sequence(Func(self.setChatAbsolute, random.choice(TTLocalizer.DirectedAttackBossTaunts[self.dna.dept]) % {'toon': toon.getName()}, CFSpeech | CFTimeout), throwAnim, neutral2Anim), Sequence(Wait(0.85), SoundInterval(self.swingClubSfx, node=self, duration=0.45, cutOff=300, listenerNode=base.localAvatar))))
self.doAnimate(seq, now=1, raised=1)
def doGolfAreaAttack(self):
toons = []
for toonId in self.involvedToons:
toon = base.cr.doId2do.get(toonId)
if toon:
toons.append(toon)
if not toons:
return
neutral = 'Fb_neutral'
if not self.twoFaced:
neutral = 'Ff_neutral'
if not self.raised:
neutral1Anim = self.getAnim('down2Up')
self.raised = 1
else:
neutral1Anim = ActorInterval(self, neutral, startFrame=48)
throwAnim = self.getAnim('golf_swing')
neutral2Anim = ActorInterval(self, neutral)
extraAnim = Sequence()
if False:
extraAnim = ActorInterval(self, neutral)
gearModel = self.getGolfBall()
toToonH = self.rotateNode.getH() + 360
self.notify.debug('toToonH = %s' % toToonH)
gearRoots = []
allGearTracks = Parallel()
for toon in toons:
gearRoot = self.rotateNode.attachNewNode('gearRoot-atk%d-%d' % (self.numAttacks, toons.index(toon)))
gearRoot.setZ(10)
gearRoot.setTag('attackCode', str(ToontownGlobals.BossCogGolfAreaAttack))
gearRoot.lookAt(toon)
ballLaunch = NodePath('')
ballLaunch.reparentTo(gearRoot)
ballLaunch.setPos(self.BallLaunchOffset)
gearTrack = Parallel()
for i in xrange(5):
nodeName = '%s-%s' % (str(i), globalClock.getFrameTime())
node = gearRoot.attachNewNode(nodeName)
node.hide()
node.reparentTo(ballLaunch)
node.wrtReparentTo(gearRoot)
distance = toon.getDistance(node)
toonPos = toon.getPos(render)
nodePos = node.getPos(render)
vector = toonPos - nodePos
gear = gearModel.instanceTo(node)
x = random.uniform(-5, 5)
z = random.uniform(-3, 3)
p = random.uniform(-720, -90)
y = distance + random.uniform(5, 15)
if i == 2:
x = 0
z = 0
y = distance + 10
def detachNode(node):
if not node.isEmpty():
node.detachNode()
return Task.done
def detachNodeLater(node = node):
if node.isEmpty():
return
node.node().setBounds(BoundingSphere(Point3(0, 0, 0), distance * 1.5))
node.node().setFinal(1)
self.doMethodLater(0.005, detachNode, 'detach-%s-%s' % (gearRoot.getName(), node.getName()), extraArgs=[node])
gearTrack.append(Sequence(Wait(26.0 / 24.0), Wait(i * 0.15), Func(node.show), Parallel(node.posInterval(1, Point3(x, y, z), fluid=1), node.hprInterval(1, VBase3(0, p, 0), fluid=1)), Func(detachNodeLater)))
allGearTracks.append(gearTrack)
def detachGearRoots(gearRoots = gearRoots):
for gearRoot in gearRoots:
def detachGearRoot(task, gearRoot = gearRoot):
if not gearRoot.isEmpty():
gearRoot.detachNode()
return task.done
if gearRoot.isEmpty():
continue
self.doMethodLater(0.01, detachGearRoot, 'detach-%s' % gearRoot.getName())
gearRoots = []
rotateFire = Parallel(self.pelvis.hprInterval(2, VBase3(toToonH + 1440, 0, 0)), allGearTracks)
seq = Sequence(Func(base.playSfx, self.warningSfx), Func(self.saySomething, TTLocalizer.GolfAreaAttackTaunt), ParallelEndTogether(self.pelvis.hprInterval(2, VBase3(toToonH, 0, 0)), neutral1Anim), extraAnim, Parallel(Sequence(rotateFire, Func(detachGearRoots), Func(self.pelvis.setHpr, VBase3(0, 0, 0))), Sequence(throwAnim, neutral2Anim), Sequence(Wait(0.85), SoundInterval(self.swingClubSfx, node=self, duration=0.45, cutOff=300, listenerNode=base.localAvatar))))
self.doAnimate(seq, now=1, raised=1)
def saySomething(self, chatString):
intervalName = 'CEOTaunt'
seq = Sequence(name=intervalName)
seq.append(Func(self.setChatAbsolute, chatString, CFSpeech))
seq.append(Wait(4.0))
seq.append(Func(self.clearChat))
oldSeq = self.activeIntervals.get(intervalName)
if oldSeq:
oldSeq.finish()
seq.start()
self.activeIntervals[intervalName] = seq
def d_hitToon(self, toonId):
self.notify.debug('----- d_hitToon')
self.sendUpdate('hitToon', [toonId])
def toonGotHealed(self, toonId):
toon = base.cr.doId2do.get(toonId)
if toon:
base.playSfx(self.toonUpSfx, node=toon)
def localToonTouchedBeltToonup(self, beltIndex, toonupIndex, toonupNum):
avId = base.localAvatar.doId
doRequest = True
if doRequest:
self.sendUpdate('requestGetToonup', [beltIndex, toonupIndex, toonupNum])
def toonGotToonup(self, avId, beltIndex, toonupIndex, toonupNum):
if self.belts[beltIndex]:
self.belts[beltIndex].removeToonup(toonupIndex)
toon = base.cr.doId2do.get(avId)
if toon:
base.playSfx(self.toonUpSfx, node=toon)
def doOvertimeAttack(self, index):
attackCode = ToontownGlobals.BossCogOvertimeAttack
attackBelts = Sequence()
if index < len(self.belts):
belt = self.belts[index]
self.saySomething(TTLocalizer.OvertimeAttackTaunts[index])
if index:
self.bossClubIntervals[0].finish()
self.bossClubIntervals[1].loop()
else:
self.bossClubIntervals[1].finish()
self.bossClubIntervals[0].loop()
distance = belt.beltModel.getDistance(self)
gearRoot = self.rotateNode.attachNewNode('gearRoot')
gearRoot.setZ(10)
gearRoot.setTag('attackCode', str(attackCode))
gearModel = self.getGearFrisbee()
gearModel.setScale(0.2)
gearRoot.headsUp(belt.beltModel)
toToonH = PythonUtil.fitDestAngle2Src(0, gearRoot.getH() + 180)
gearRoot.lookAt(belt.beltModel)
neutral = 'Fb_neutral'
if not self.twoFaced:
neutral = 'Ff_neutral'
gearTrack = Parallel()
for i in xrange(4):
node = gearRoot.attachNewNode(str(i))
node.hide()
node.setPos(0, 5.85, 4.0)
gear = gearModel.instanceTo(node)
x = random.uniform(-5, 5)
z = random.uniform(-3, 3)
h = random.uniform(-720, 720)
gearTrack.append(Sequence(Wait(i * 0.15), Func(node.show), Parallel(node.posInterval(1, Point3(x, distance, z), fluid=1), node.hprInterval(1, VBase3(h, 0, 0), fluid=1)), Func(node.detachNode)))
if not self.raised:
neutral1Anim = self.getAnim('down2Up')
self.raised = 1
else:
neutral1Anim = ActorInterval(self, neutral, startFrame=48)
throwAnim = self.getAnim('throw')
neutral2Anim = ActorInterval(self, neutral)
extraAnim = Sequence()
if attackCode == ToontownGlobals.BossCogSlowDirectedAttack:
extraAnim = ActorInterval(self, neutral)
seq = Sequence(ParallelEndTogether(self.pelvis.hprInterval(1, VBase3(toToonH, 0, 0)), neutral1Anim), extraAnim, Parallel(Sequence(Wait(0.19), gearTrack, Func(gearRoot.detachNode), Func(self.explodeSfx.play), self.pelvis.hprInterval(0.2, VBase3(0, 0, 0))), Sequence(throwAnim, neutral2Anim)), Func(belt.request, 'Inactive'))
attackBelts.append(seq)
self.notify.debug('attackBelts duration= %.2f' % attackBelts.getDuration())
self.doAnimate(attackBelts, now=1, raised=1)