385 lines
17 KiB
Python
385 lines
17 KiB
Python
|
from panda3d.core import *
|
||
|
from direct.interval.IntervalGlobal import *
|
||
|
from direct.fsm import ClassicFSM, State
|
||
|
from direct.fsm import State
|
||
|
from direct.directnotify import DirectNotifyGlobal
|
||
|
import DistributedSuitBase
|
||
|
from toontown.toonbase import ToontownGlobals
|
||
|
from toontown.battle import MovieUtil
|
||
|
|
||
|
class DistributedLawbotBossSuit(DistributedSuitBase.DistributedSuitBase):
|
||
|
notify = DirectNotifyGlobal.directNotify.newCategory('DistributedLawbotBossSuit')
|
||
|
timeToShow = 1.0
|
||
|
timeToRelease = 3.15
|
||
|
throwPaperEndTime = 4.33
|
||
|
|
||
|
def __init__(self, cr):
|
||
|
self.flyingEvidenceTrack = None
|
||
|
try:
|
||
|
self.DistributedSuit_initialized
|
||
|
except:
|
||
|
self.DistributedSuit_initialized = 1
|
||
|
DistributedSuitBase.DistributedSuitBase.__init__(self, cr)
|
||
|
self.activeIntervals = {}
|
||
|
self.boss = None
|
||
|
self.fsm = ClassicFSM.ClassicFSM('DistributedLawbotBossSuit', [
|
||
|
State.State('Off',
|
||
|
self.enterOff,
|
||
|
self.exitOff, [
|
||
|
'Walk',
|
||
|
'Battle',
|
||
|
'neutral']),
|
||
|
State.State('Walk',
|
||
|
self.enterWalk,
|
||
|
self.exitWalk, [
|
||
|
'WaitForBattle',
|
||
|
'Battle']),
|
||
|
State.State('Battle',
|
||
|
self.enterBattle,
|
||
|
self.exitBattle, []),
|
||
|
State.State('neutral',
|
||
|
self.enterNeutral,
|
||
|
self.exitNeutral, [
|
||
|
'PreThrowProsecute',
|
||
|
'PreThrowAttack',
|
||
|
'Stunned']),
|
||
|
State.State('PreThrowProsecute',
|
||
|
self.enterPreThrowProsecute,
|
||
|
self.exitPreThrowProsecute,
|
||
|
['PostThrowProsecute',
|
||
|
'neutral',
|
||
|
'Stunned']),
|
||
|
State.State('PostThrowProsecute',
|
||
|
self.enterPostThrowProsecute,
|
||
|
self.exitPostThrowProsecute, [
|
||
|
'neutral',
|
||
|
'Stunned']),
|
||
|
State.State('PreThrowAttack',
|
||
|
self.enterPreThrowAttack,
|
||
|
self.exitPreThrowAttack, [
|
||
|
'PostThrowAttack',
|
||
|
'neutral',
|
||
|
'Stunned']),
|
||
|
State.State('PostThrowAttack',
|
||
|
self.enterPostThrowAttack,
|
||
|
self.exitPostThrowAttack, [
|
||
|
'neutral',
|
||
|
'Stunned']),
|
||
|
State.State('Stunned',
|
||
|
self.enterStunned,
|
||
|
self.exitStunned, [
|
||
|
'neutral']),
|
||
|
State.State('WaitForBattle',
|
||
|
self.enterWaitForBattle,
|
||
|
self.exitWaitForBattle, [
|
||
|
'Battle'])],
|
||
|
'Off', 'Off')
|
||
|
self.fsm.enterInitialState()
|
||
|
|
||
|
return
|
||
|
|
||
|
def generate(self):
|
||
|
self.notify.debug('DLBS.generate:')
|
||
|
DistributedSuitBase.DistributedSuitBase.generate(self)
|
||
|
|
||
|
def announceGenerate(self):
|
||
|
DistributedSuitBase.DistributedSuitBase.announceGenerate(self)
|
||
|
self.notify.debug('DLBS.announceGenerate')
|
||
|
colNode = self.find('**/distAvatarCollNode*')
|
||
|
colNode.setTag('pieCode', str(ToontownGlobals.PieCodeLawyer))
|
||
|
self.attackEvidenceA = self.getEvidence(True)
|
||
|
self.attackEvidenceB = self.getEvidence(True)
|
||
|
self.attackEvidence = self.attackEvidenceA
|
||
|
self.prosecuteEvidence = self.getEvidence(False)
|
||
|
self.hideName()
|
||
|
self.setPickable(False)
|
||
|
|
||
|
def disable(self):
|
||
|
self.notify.debug('DistributedSuit %d: disabling' % self.getDoId())
|
||
|
self.setState('Off')
|
||
|
DistributedSuitBase.DistributedSuitBase.disable(self)
|
||
|
self.cleanupIntervals()
|
||
|
self.boss = None
|
||
|
return
|
||
|
|
||
|
def delete(self):
|
||
|
try:
|
||
|
self.DistributedSuit_deleted
|
||
|
except:
|
||
|
self.DistributedSuit_deleted = 1
|
||
|
self.notify.debug('DistributedSuit %d: deleting' % self.getDoId())
|
||
|
del self.fsm
|
||
|
DistributedSuitBase.DistributedSuitBase.delete(self)
|
||
|
|
||
|
def d_requestBattle(self, pos, hpr):
|
||
|
self.cr.playGame.getPlace().setState('WaitForBattle')
|
||
|
self.sendUpdate('requestBattle', [pos[0],
|
||
|
pos[1],
|
||
|
pos[2],
|
||
|
hpr[0],
|
||
|
hpr[1],
|
||
|
hpr[2]])
|
||
|
return None
|
||
|
|
||
|
def __handleToonCollision(self, collEntry):
|
||
|
toonId = base.localAvatar.getDoId()
|
||
|
self.notify.debug('Distributed suit: requesting a Battle with ' + 'toon: %d' % toonId)
|
||
|
self.d_requestBattle(self.getPos(), self.getHpr())
|
||
|
self.setState('WaitForBattle')
|
||
|
return None
|
||
|
|
||
|
def enterWalk(self):
|
||
|
self.notify.debug('enterWalk')
|
||
|
self.enableBattleDetect('walk', self.__handleToonCollision)
|
||
|
self.loop('walk', 0)
|
||
|
pathPoints = [Vec3(50, 15, 0),
|
||
|
Vec3(50, 25, 0),
|
||
|
Vec3(20, 25, 0),
|
||
|
Vec3(20, 15, 0),
|
||
|
Vec3(50, 15, 0)]
|
||
|
self.tutWalkTrack = self.makePathTrack(self, pathPoints, 4.5, 'tutFlunkyWalk')
|
||
|
self.tutWalkTrack.loop()
|
||
|
|
||
|
def exitWalk(self):
|
||
|
self.notify.debug('exitWalk')
|
||
|
self.disableBattleDetect()
|
||
|
self.tutWalkTrack.pause()
|
||
|
self.tutWalkTrack = None
|
||
|
return
|
||
|
|
||
|
def enterNeutral(self):
|
||
|
self.notify.debug('enterNeutral')
|
||
|
self.notify.debug('DistributedLawbotBossSuit: Neutral')
|
||
|
self.loop('neutral', 0)
|
||
|
|
||
|
def exitNeutral(self):
|
||
|
self.notify.debug('exitNeutral')
|
||
|
|
||
|
def doAttack(self, x1, y1, z1, x2, y2, z2):
|
||
|
self.notify.debug('x1=%.2f y1=%.2f z2=%.2f x2=%.2f y2=%.2f z2=%.2f' % (x1,
|
||
|
y1,
|
||
|
z1,
|
||
|
x2,
|
||
|
y2,
|
||
|
z2))
|
||
|
self.curTargetPt = Point3(x2, y2, z2)
|
||
|
self.fsm.request('PreThrowAttack')
|
||
|
return
|
||
|
attackEvidence = self.getEvidence(True)
|
||
|
nodePath = render
|
||
|
node = nodePath.attachNewNode('attackEvidence-%s' % self.doId)
|
||
|
node.setPos(x1, y1, z1)
|
||
|
duration = 3.0
|
||
|
throwName = self.uniqueName('lawyerAttack')
|
||
|
throwingSeq = self.makeAttackThrowingTrack(attackEvidence, duration, Point3(x2, y2, z2))
|
||
|
fullSequence = Sequence(throwingSeq, name=throwName)
|
||
|
self.activeIntervals[throwName] = fullSequence
|
||
|
fullSequence.start()
|
||
|
|
||
|
def doProsecute(self):
|
||
|
self.notify.debug('doProsecute')
|
||
|
bounds = self.boss.prosecutionColNodePath.getBounds()
|
||
|
panCenter = bounds.getCenter()
|
||
|
localPos = panCenter
|
||
|
prosecutionPanPos = render.getRelativePoint(self.boss.prosecutionColNodePath, localPos)
|
||
|
self.curTargetPt = prosecutionPanPos
|
||
|
self.fsm.request('PreThrowProsecute')
|
||
|
return
|
||
|
attackEvidence = self.getEvidence(False)
|
||
|
nodePath = render
|
||
|
node = nodePath.attachNewNode('prosecuteEvidence-%s' % self.doId)
|
||
|
node.setPos(self.getPos())
|
||
|
duration = ToontownGlobals.LawbotBossLawyerToPanTime
|
||
|
throwName = self.uniqueName('lawyerProsecute')
|
||
|
throwingSeq = self.makeProsecuteThrowingTrack(attackEvidence, duration, prosecutionPanPos)
|
||
|
fullSequence = Sequence(throwingSeq, Func(self.boss.flashGreen), Func(self.clearInterval, throwName), name=throwName)
|
||
|
self.activeIntervals[throwName] = fullSequence
|
||
|
fullSequence.start()
|
||
|
|
||
|
def makeDummySequence(self):
|
||
|
retval = Sequence(Wait(10))
|
||
|
return retval
|
||
|
|
||
|
def makeProsecuteThrowingTrack(self, evidence, inFlightDuration, hitPos):
|
||
|
suitTrack = Sequence()
|
||
|
suitTrack.append(ActorInterval(self, 'throw-paper'))
|
||
|
throwPaperDuration = suitTrack.getDuration()
|
||
|
inFlight = Parallel(evidence.posInterval(inFlightDuration, hitPos, fluid=1))
|
||
|
origHpr = self.getHpr()
|
||
|
self.headsUp(hitPos)
|
||
|
newHpr = self.getHpr()
|
||
|
self.setHpr(origHpr)
|
||
|
rotateTrack = Sequence(self.hprInterval(self.timeToShow, newHpr, fluid=1))
|
||
|
propTrack = Sequence(Func(evidence.hide), Func(evidence.setPos, 0, 0.5, -0.3), Func(evidence.reparentTo, self.getRightHand()), Wait(self.timeToShow), Func(evidence.show), Wait(self.timeToRelease - self.timeToShow), Func(evidence.wrtReparentTo, render), Func(self.makeDummySequence), inFlight, Func(evidence.detachNode))
|
||
|
throwingTrack = Parallel(suitTrack, propTrack, rotateTrack)
|
||
|
return throwingTrack
|
||
|
|
||
|
def makeAttackThrowingTrack(self, evidence, inFlightDuration, hitPos):
|
||
|
suitTrack = Sequence()
|
||
|
suitTrack.append(ActorInterval(self, 'throw-paper'))
|
||
|
throwPaperDuration = suitTrack.getDuration()
|
||
|
origHpr = self.getHpr()
|
||
|
self.headsUp(hitPos)
|
||
|
newHpr = self.getHpr()
|
||
|
self.setHpr(origHpr)
|
||
|
rotateTrack = Sequence(self.hprInterval(self.timeToShow, newHpr, fluid=1))
|
||
|
propTrack = Sequence(Func(evidence.hide), Func(evidence.setPos, 0, 0.5, -0.3), Func(evidence.reparentTo, self.getRightHand()), Wait(self.timeToShow), Func(evidence.show), Wait(self.timeToRelease - self.timeToShow), Func(evidence.wrtReparentTo, render), Func(evidence.setZ, 1.3), evidence.posInterval(inFlightDuration, hitPos, fluid=1), Func(evidence.detachNode))
|
||
|
throwingTrack = Parallel(suitTrack, propTrack, rotateTrack)
|
||
|
return throwingTrack
|
||
|
|
||
|
def makePreThrowAttackTrack(self, evidence, inFlightDuration, hitPos):
|
||
|
suitTrack = Sequence()
|
||
|
suitTrack.append(ActorInterval(self, 'throw-paper', endTime=self.timeToRelease))
|
||
|
throwPaperDuration = suitTrack.getDuration()
|
||
|
origHpr = self.getHpr()
|
||
|
self.headsUp(hitPos)
|
||
|
newHpr = self.getHpr()
|
||
|
self.setHpr(origHpr)
|
||
|
rotateTrack = Sequence(self.hprInterval(self.timeToShow, newHpr, fluid=1))
|
||
|
propTrack = Sequence(Func(evidence.hide), Func(evidence.setPos, 0, 0.5, -0.3), Func(evidence.setScale, 1), Func(evidence.setHpr, 0, 0, 0), Func(evidence.reparentTo, self.getRightHand()), Wait(self.timeToShow), Func(evidence.show), Wait(self.timeToRelease - self.timeToShow))
|
||
|
throwingTrack = Parallel(suitTrack, propTrack, rotateTrack)
|
||
|
return throwingTrack
|
||
|
|
||
|
def makePostThrowAttackTrack(self, evidence, inFlightDuration, hitPos):
|
||
|
suitTrack = Sequence()
|
||
|
suitTrack.append(ActorInterval(self, 'throw-paper', startTime=self.timeToRelease))
|
||
|
propTrack = Sequence(Func(evidence.wrtReparentTo, render), Func(evidence.setScale, 1), Func(evidence.show), Func(evidence.setZ, 1.3), evidence.posInterval(inFlightDuration, hitPos, fluid=1), Func(evidence.hide))
|
||
|
return (suitTrack, propTrack)
|
||
|
|
||
|
def makePreThrowProsecuteTrack(self, evidence, inFlightDuration, hitPos):
|
||
|
return self.makePreThrowAttackTrack(evidence, inFlightDuration, hitPos)
|
||
|
|
||
|
def makePostThrowProsecuteTrack(self, evidence, inFlightDuration, hitPos):
|
||
|
suitTrack = Sequence()
|
||
|
suitTrack.append(ActorInterval(self, 'throw-paper', startTime=self.timeToRelease))
|
||
|
propTrack = Sequence(Func(evidence.wrtReparentTo, render), Func(evidence.setScale, 1), Func(evidence.show), evidence.posInterval(inFlightDuration, hitPos, fluid=1), Func(evidence.hide))
|
||
|
return (suitTrack, propTrack)
|
||
|
|
||
|
def getEvidence(self, usedForAttack = False):
|
||
|
model = loader.loadModel('phase_5/models/props/lawbook')
|
||
|
if usedForAttack:
|
||
|
bounds = model.getBounds()
|
||
|
center = bounds.getCenter()
|
||
|
radius = bounds.getRadius()
|
||
|
sphere = CollisionSphere(center.getX(), center.getY(), center.getZ(), radius)
|
||
|
colNode = CollisionNode('BossZap')
|
||
|
colNode.setTag('attackCode', str(ToontownGlobals.BossCogLawyerAttack))
|
||
|
colNode.addSolid(sphere)
|
||
|
model.attachNewNode(colNode)
|
||
|
model.setTransparency(1)
|
||
|
model.setAlphaScale(0.5)
|
||
|
return model
|
||
|
|
||
|
def cleanupIntervals(self):
|
||
|
for interval in self.activeIntervals.values():
|
||
|
interval.finish()
|
||
|
|
||
|
self.activeIntervals = {}
|
||
|
|
||
|
def clearInterval(self, name, finish = 1):
|
||
|
if name in self.activeIntervals:
|
||
|
ival = self.activeIntervals[name]
|
||
|
if finish:
|
||
|
ival.finish()
|
||
|
else:
|
||
|
ival.pause()
|
||
|
if name in self.activeIntervals:
|
||
|
del self.activeIntervals[name]
|
||
|
else:
|
||
|
self.notify.debug('interval: %s already cleared' % name)
|
||
|
|
||
|
def setBossCogId(self, bossCogId):
|
||
|
self.bossCogId = bossCogId
|
||
|
self.boss = base.cr.doId2do[bossCogId]
|
||
|
|
||
|
def doStun(self):
|
||
|
self.notify.debug('doStun')
|
||
|
self.fsm.request('Stunned')
|
||
|
|
||
|
def enterPreThrowProsecute(self):
|
||
|
duration = ToontownGlobals.LawbotBossLawyerToPanTime
|
||
|
throwName = self.uniqueName('preThrowProsecute')
|
||
|
preThrowTrack = self.makePreThrowProsecuteTrack(self.prosecuteEvidence, duration, self.curTargetPt)
|
||
|
fullSequence = Sequence(preThrowTrack, Func(self.requestStateIfNotInFlux, 'PostThrowProsecute'), name=throwName)
|
||
|
self.activeIntervals[throwName] = fullSequence
|
||
|
fullSequence.start()
|
||
|
|
||
|
def exitPreThrowProsecute(self):
|
||
|
throwName = self.uniqueName('preThrowProsecute')
|
||
|
if throwName in self.activeIntervals:
|
||
|
self.activeIntervals[throwName].pause()
|
||
|
del self.activeIntervals[throwName]
|
||
|
|
||
|
def enterPostThrowProsecute(self):
|
||
|
duration = ToontownGlobals.LawbotBossLawyerToPanTime
|
||
|
throwName = self.uniqueName('postThrowProsecute')
|
||
|
postThrowTrack, self.flyingEvidenceTrack = self.makePostThrowProsecuteTrack(self.prosecuteEvidence, duration, self.curTargetPt)
|
||
|
fullSequence = Sequence(postThrowTrack, Func(self.requestStateIfNotInFlux, 'neutral'), name=throwName)
|
||
|
self.activeIntervals[throwName] = fullSequence
|
||
|
fullSequence.start()
|
||
|
flyName = self.uniqueName('flyingEvidence')
|
||
|
self.activeIntervals[flyName] = self.flyingEvidenceTrack
|
||
|
self.flyingEvidenceTrack.append(Func(self.finishedWithFlying, 'prosecute'))
|
||
|
self.flyingEvidenceTrack.start()
|
||
|
|
||
|
def exitPostThrowProsecute(self):
|
||
|
throwName = self.uniqueName('postThrowProsecute')
|
||
|
if throwName in self.activeIntervals:
|
||
|
self.activeIntervals[throwName].finish()
|
||
|
del self.activeIntervals[throwName]
|
||
|
|
||
|
def requestStateIfNotInFlux(self, state):
|
||
|
if not self.fsm._ClassicFSM__internalStateInFlux:
|
||
|
self.fsm.request(state)
|
||
|
|
||
|
def enterPreThrowAttack(self):
|
||
|
if self.attackEvidence == self.attackEvidenceA:
|
||
|
self.attackEvidence = self.attackEvidenceB
|
||
|
else:
|
||
|
self.attackEvidence = self.attackEvidenceA
|
||
|
duration = 3.0
|
||
|
throwName = self.uniqueName('preThrowAttack')
|
||
|
preThrowTrack = self.makePreThrowAttackTrack(self.attackEvidence, duration, self.curTargetPt)
|
||
|
fullSequence = Sequence(preThrowTrack, Func(self.requestStateIfNotInFlux, 'PostThrowAttack'), name=throwName)
|
||
|
self.activeIntervals[throwName] = fullSequence
|
||
|
fullSequence.start()
|
||
|
|
||
|
def exitPreThrowAttack(self):
|
||
|
throwName = self.uniqueName('preThrowAttack')
|
||
|
if throwName in self.activeIntervals:
|
||
|
self.activeIntervals[throwName].pause()
|
||
|
del self.activeIntervals[throwName]
|
||
|
|
||
|
def enterPostThrowAttack(self):
|
||
|
duration = 3.0
|
||
|
throwName = self.uniqueName('postThrowAttack')
|
||
|
postThrowTrack, self.flyingEvidenceTrack = self.makePostThrowAttackTrack(self.attackEvidence, duration, self.curTargetPt)
|
||
|
fullSequence = Sequence(postThrowTrack, Func(self.requestStateIfNotInFlux, 'neutral'), name=throwName)
|
||
|
self.notify.debug('duration of postThrowAttack = %f' % fullSequence.getDuration())
|
||
|
self.activeIntervals[throwName] = fullSequence
|
||
|
fullSequence.start()
|
||
|
flyName = self.uniqueName('flyingEvidence')
|
||
|
self.activeIntervals[flyName] = self.flyingEvidenceTrack
|
||
|
self.flyingEvidenceTrack.append(Func(self.finishedWithFlying, 'attack'))
|
||
|
self.flyingEvidenceTrack.start()
|
||
|
|
||
|
def finishedWithFlying(self, str):
|
||
|
self.notify.debug('finished flyingEvidenceTrack %s' % str)
|
||
|
|
||
|
def exitPostThrowAttack(self):
|
||
|
throwName = self.uniqueName('postThrowAttack')
|
||
|
if throwName in self.activeIntervals:
|
||
|
self.activeIntervals[throwName].finish()
|
||
|
del self.activeIntervals[throwName]
|
||
|
|
||
|
def enterStunned(self):
|
||
|
stunSequence = MovieUtil.createSuitStunInterval(self, 0, ToontownGlobals.LawbotBossLawyerStunTime)
|
||
|
seqName = stunSequence.getName()
|
||
|
stunSequence.append(Func(self.fsm.request, 'neutral'))
|
||
|
self.activeIntervals[seqName] = stunSequence
|
||
|
stunSequence.start()
|
||
|
|
||
|
def exitStunned(self):
|
||
|
self.prosecuteEvidence.hide()
|
||
|
self.attackEvidence.hide()
|