177 lines
7 KiB
Python
177 lines
7 KiB
Python
import types
|
|
import math
|
|
from direct.interval.IntervalGlobal import Sequence, Wait, ActorInterval, Func, SoundInterval, Parallel
|
|
from direct.task import Task
|
|
from direct.fsm import FSM
|
|
from direct.showbase.PythonUtil import weightedChoice
|
|
from toontown.hood import GenericAnimatedProp
|
|
from toontown.hood import AnimatedProp
|
|
from toontown.toonbase import ToontownGlobals
|
|
from direct.directnotify import DirectNotifyGlobal
|
|
|
|
class ZeroAnimatedProp(GenericAnimatedProp.GenericAnimatedProp, FSM.FSM):
|
|
notify = DirectNotifyGlobal.directNotify.newCategory('ZeroAnimatedProp')
|
|
|
|
def __init__(self, node, propString, phaseInfo, holidayId):
|
|
self.propString = propString
|
|
self.phaseInfo = phaseInfo
|
|
self.holidayId = holidayId
|
|
GenericAnimatedProp.GenericAnimatedProp.__init__(self, node)
|
|
FSM.FSM.__init__(self, '%sZeroAnimPropFsm' % self.propString)
|
|
self.node.unloadAnims('anim')
|
|
self.loadPhaseAnims()
|
|
self.phaseIvals = []
|
|
self.curIval = None
|
|
self.curPhase = -1
|
|
self.okToStartNextAnim = False
|
|
return
|
|
|
|
def delete(self):
|
|
self.exit()
|
|
GenericAnimatedProp.GenericAnimatedProp.delete(self)
|
|
|
|
def loadPhaseAnims(self):
|
|
animDict = {}
|
|
for key, info in self.phaseInfo.iteritems():
|
|
if type(info[0]) == types.TupleType:
|
|
for index, anims in enumerate(info[0]):
|
|
fullPath = self.path + '/' + anims
|
|
animName = 'phase%d_%d' % (key, index)
|
|
animDict[animName] = fullPath
|
|
|
|
else:
|
|
animName = 'phase%d' % key
|
|
fullPath = self.path + '/' + info[0]
|
|
animDict[animName] = fullPath
|
|
|
|
self.node.loadAnims(animDict)
|
|
|
|
def createPhaseIntervals(self):
|
|
if self.phaseIvals:
|
|
self.notify.debug('not creating phase ivals again')
|
|
return
|
|
self.phaseIvals = []
|
|
for key, info in self.phaseInfo.iteritems():
|
|
self.notify.debug('key=%s' % key)
|
|
if type(info[0]) == types.TupleType:
|
|
ival = Sequence()
|
|
for index, anims in enumerate(info[0]):
|
|
animName = 'phase%d_%d' % (key, index)
|
|
animIval = self.node.actorInterval(animName)
|
|
animIvalDuration = animIval.getDuration()
|
|
soundIval = self.createSoundInterval(anims, animIvalDuration)
|
|
soundIvalDuration = soundIval.getDuration()
|
|
animAndSound = Parallel(soundIval, animIval)
|
|
ival.append(animAndSound)
|
|
|
|
self.phaseIvals.append(ival)
|
|
else:
|
|
animName = 'phase%d' % key
|
|
animIval = self.node.actorInterval('phase%d' % key)
|
|
animIvalDuration = animIval.getDuration()
|
|
soundIval = self.createSoundInterval(info[0], animIvalDuration)
|
|
soundIvalDuration = soundIval.getDuration()
|
|
ival = Parallel(animIval, soundIval)
|
|
self.phaseIvals.append(ival)
|
|
|
|
def enter(self):
|
|
self.node.postFlatten()
|
|
self.createPhaseIntervals()
|
|
AnimatedProp.AnimatedProp.enter(self)
|
|
defaultAnim = self.node.getAnimControl('anim')
|
|
numFrames = defaultAnim.getNumFrames()
|
|
self.node.pose('phase0', 0)
|
|
self.accept('%sZeroPhase' % self.propString, self.handleNewPhase)
|
|
self.accept('%sZeroIsRunning' % self.propString, self.handleNewIsRunning)
|
|
self.startIfNeeded()
|
|
|
|
def startIfNeeded(self):
|
|
try:
|
|
self.curPhase = self.getPhaseToRun()
|
|
if self.curPhase >= 0:
|
|
self.request('DoAnim')
|
|
except:
|
|
pass
|
|
|
|
def chooseAnimToRun(self):
|
|
result = self.curPhase
|
|
if config.GetBool('anim-props-randomized', True):
|
|
pairs = []
|
|
for i in xrange(self.curPhase + 1):
|
|
pairs.append((math.pow(2, i), i))
|
|
|
|
sum = math.pow(2, self.curPhase + 1) - 1
|
|
result = weightedChoice(pairs, sum=sum)
|
|
self.notify.debug('chooseAnimToRun curPhase=%s pairs=%s result=%s' % (self.curPhase, pairs, result))
|
|
return result
|
|
|
|
def createAnimSequence(self, animPhase):
|
|
result = Sequence(self.phaseIvals[animPhase], Wait(self.phaseInfo[self.curPhase][1]), Func(self.startNextAnim))
|
|
return result
|
|
|
|
def startNextAnim(self):
|
|
self.notify.debug('startNextAnim self.okToStartNextAnim=%s' % self.okToStartNextAnim)
|
|
self.curIval = None
|
|
if self.okToStartNextAnim:
|
|
self.notify.debug('got pass okToStartNextAnim')
|
|
whichAnim = self.chooseAnimToRun()
|
|
self.notify.debug('whichAnim=%s' % whichAnim)
|
|
self.lastPlayingAnimPhase = whichAnim
|
|
self.curIval = self.createAnimSequence(whichAnim)
|
|
self.notify.debug('starting curIval of length %s' % self.curIval.getDuration())
|
|
self.curIval.start()
|
|
else:
|
|
self.notify.debug('false self.okToStartNextAnim=%s' % self.okToStartNextAnim)
|
|
return
|
|
|
|
def enterDoAnim(self):
|
|
self.notify.debug('enterDoAnim curPhase=%d' % self.curPhase)
|
|
self.okToStartNextAnim = True
|
|
self.startNextAnim()
|
|
|
|
def exitDoAnim(self):
|
|
self.notify.debug('exitDoAnim curPhase=%d' % self.curPhase)
|
|
self.okToStartNextAnim = False
|
|
self.curIval.finish()
|
|
self.curIval = None
|
|
return
|
|
|
|
def getPhaseToRun(self):
|
|
result = -1
|
|
enoughInfoToRun = False
|
|
if base.cr.newsManager.isHolidayRunning(self.holidayId):
|
|
zeroMgrString = '%sZeroMgr' % self.propString
|
|
if hasattr(base.cr, zeroMgrString):
|
|
zeroMgr = eval('base.cr.%s' % zeroMgrString)
|
|
if not zeroMgr.isDisabled():
|
|
enoughInfoToRun = True
|
|
else:
|
|
self.notify.debug('isDisabled = %s' % zeroMgr.isDisabled())
|
|
else:
|
|
self.notify.debug('base.cr does not have %s' % zeroMgrString)
|
|
else:
|
|
self.notify.debug('holiday is not running')
|
|
self.notify.debug('enoughInfoToRun = %s' % enoughInfoToRun)
|
|
if enoughInfoToRun and zeroMgr.getIsRunning():
|
|
curPhase = zeroMgr.getCurPhase()
|
|
if curPhase >= len(self.phaseIvals):
|
|
curPhase = len(self.phaseIvals) - 1
|
|
self.notify.warning('zero mgr says to go to phase %d, but we only have %d ivals. forcing curPhase to %d' % (curPhase, len(self.phaseIvals), curPhase))
|
|
result = curPhase
|
|
return result
|
|
|
|
def exit(self):
|
|
self.okToStartNextAnim = False
|
|
self.ignore('%sZeroPhase' % self.propString)
|
|
self.ignore('%sZeroIsRunning' % self.propString)
|
|
GenericAnimatedProp.GenericAnimatedProp.exit(self)
|
|
self.request('Off')
|
|
|
|
def handleNewPhase(self, newPhase):
|
|
self.startIfNeeded()
|
|
|
|
def handleNewIsRunning(self, isRunning):
|
|
if isRunning:
|
|
self.startIfNeeded()
|
|
else:
|
|
self.request('Off')
|