ToonTownRewritten/toontown/hood/ZeroAnimatedProp.py

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')