Interactive props!!

This commit is contained in:
John 2015-06-25 01:00:15 +03:00
parent 9c8e85b137
commit a837ae9701
5 changed files with 99 additions and 102 deletions

View file

@ -8,12 +8,12 @@ from toontown.hood import HoodUtil
class GenericAnimatedProp(AnimatedProp.AnimatedProp):
notify = DirectNotifyGlobal.directNotify.newCategory('GenericAnimatedProp')
AnimsUsingWav = []
def __init__(self, node):
AnimatedProp.AnimatedProp.__init__(self, node)
self.origAnimNameToSound = {}
code = node.getTag('DNACode')
if code.startswith('interactive_prop_'):
pathStr = code[len('interactive_prop_'):].split('__')[0]
elif code.startswith('animated_prop_generic_'):
@ -23,10 +23,12 @@ class GenericAnimatedProp(AnimatedProp.AnimatedProp):
nextUnderscore = tempStr.find('_')
finalStr = tempStr[nextUnderscore + 1:]
pathStr = finalStr.split('__')[0]
phaseDelimeter = len('phase_') + pathStr[len('phase_'):].find('_')
phaseStr = pathStr[:phaseDelimeter]
pathTokens = pathStr[phaseDelimeter + 1:].split('_')
self.path = phaseStr
for path in pathTokens:
self.path += '/'
self.path += path
@ -39,6 +41,11 @@ class GenericAnimatedProp(AnimatedProp.AnimatedProp):
def delete(self):
AnimatedProp.AnimatedProp.delete(self)
if hasattr(self, 'soundNode'):
self.soundNode.cleanup()
del self.soundNode
self.node.cleanup()
del self.node
del self.trashcan
@ -67,6 +74,7 @@ class GenericAnimatedProp(AnimatedProp.AnimatedProp):
self.hoodId = ToontownGlobals.ToontownCentral
fullString = str(node)
splits = fullString.split('/')
if len(splits) >= 5:
visId = int(splits[4])
self.visId = visId
@ -80,28 +88,22 @@ class GenericAnimatedProp(AnimatedProp.AnimatedProp):
def createSoundInterval(self, origAnimNameWithPath, maximumDuration):
if not hasattr(base, 'localAvatar'):
return Sequence()
sfxVolume = 1.0
cutoff = 45
if not hasattr(self, 'soundPath'):
self.soundPath = self.path.replace('/models/char', '/audio/sfx')
origAnimName = origAnimNameWithPath.split('/')[-1]
theSound = self.origAnimNameToSound.get(origAnimName)
if not theSound:
soundfile = origAnimName.replace('tt_a_ara', 'tt_s_ara')
fullPath = self.soundPath + '/' + soundfile
if origAnimName in self.AnimsUsingWav:
theSound = loader.loadSfx(fullPath + '.ogg')
else:
theSound = loader.loadSfx(fullPath + '.ogg')
self.origAnimNameToSound[origAnimName] = theSound
if theSound:
soundDur = theSound.length()
if maximumDuration < soundDur:
if base.config.GetBool('interactive-prop-info', False):
if self.visId == localAvatar.zoneId and origAnimName != 'tt_a_ara_dga_hydrant_idleIntoFight':
self.notify.warning('anim %s had duration of %s while sound has duration of %s' % (origAnimName, maximumDuration, soundDur))
soundDur = maximumDuration
result = SoundInterval(theSound, node=self.node, listenerNode=base.localAvatar, volume=sfxVolume, cutOff=cutoff, startTime=0, duration=soundDur)
else:
result = Sequence()
return result
sound = self.origAnimNameToSound.get(origAnimName)
if not sound:
sound = loader.loadSfx('%s/%s.ogg' % (self.soundPath, origAnimName.replace('tt_a_ara', 'tt_s_ara')))
self.origAnimNameToSound[origAnimName] = sound
if sound:
if not hasattr(self, 'soundNode'):
self.soundNode = render.attachNewNode('Sound Node')
self.soundNode.setPos(self.trashcan.getBounds().getCenter())
return SoundInterval(sound, node=self.soundNode, listenerNode=base.localAvatar, volume=1.0, cutOff=45, startTime=0, duration=min(sound.length(), maximumDuration))
return Sequence()

View file

@ -111,8 +111,8 @@ class HydrantInteractiveProp(InteractiveAnimatedProp.InteractiveAnimatedProp):
if self.hasOverrideIval(origAnimName):
result.append(Func(self.showWater))
anim = self.createAnimIval('fight0' if 'fightBoost' in origAnimName else 'fight1')
result.append(anim)
animAndSound = self.createAnimAndSoundIval('fight0' if 'fightBoost' in origAnimName else 'fight1')
result.append(animAndSound)
result.append(Func(self.hideWater))
return result
return result

View file

@ -1,13 +1,11 @@
import math
import random
import GenericAnimatedProp
from direct.actor import Actor
from direct.interval.IntervalGlobal import Sequence, ActorInterval, Wait, Func, Parallel
from direct.fsm import FSM
from direct.showbase.PythonUtil import weightedChoice
from pandac.PandaModules import TextNode, Vec3
from direct.actor import Actor
from direct.fsm import FSM
from direct.interval.IntervalGlobal import Sequence, ActorInterval, Wait, Func, SoundInterval, Parallel
from direct.showbase.PythonUtil import weightedChoice
from toontown.toonbase import ToontownGlobals
from toontown.hood import ZoneUtil
import GenericAnimatedProp
import math, random
def clearPythonIvals(ival):
if hasattr(ival, 'function'):
@ -17,8 +15,6 @@ def clearPythonIvals(ival):
clearPythonIvals(oneIval)
ival.pythonIvals = []
return
class InteractiveAnimatedProp(GenericAnimatedProp.GenericAnimatedProp, FSM.FSM):
ZoneToIdles = {}
@ -44,6 +40,7 @@ class InteractiveAnimatedProp(GenericAnimatedProp.GenericAnimatedProp, FSM.FSM):
self.okToStartNextAnim = False
cellIndexStr = node.getTag('DNACellIndex')
self.cellIndex = ord(cellIndexStr)
self.origAnimNameToSound = {}
self.lastPlayingAnimPhase = 0
self.buildingsMakingMeSad = set()
GenericAnimatedProp.GenericAnimatedProp.__init__(self, node)
@ -67,20 +64,25 @@ class InteractiveAnimatedProp(GenericAnimatedProp.GenericAnimatedProp, FSM.FSM):
self.numIdles = len(self.ZoneToIdles[self.hoodId])
if self.hoodId in self.ZoneToFightAnims:
self.numFightAnims = len(self.ZoneToFightAnims[self.hoodId])
self.idleInterval = None
anim = node.getTag('DNAAnim')
self.trashcan = Actor.Actor(node, copy=0)
self.trashcan.reparentTo(node)
animDict = {}
animDict['anim'] = '%s/%s' % (self.path, anim)
for i in xrange(self.numIdles):
baseAnim = self.ZoneToIdles[self.hoodId][i]
if isinstance(baseAnim, tuple):
baseAnim = baseAnim[0]
animStr = self.path + '/' + baseAnim
animKey = 'idle%d' % i
animDict[animKey] = animStr
settleName = self.getSettleName(i)
if settleName:
settleStr = self.path + '/' + settleName
settleKey = 'settle%d' % i
@ -95,14 +97,17 @@ class InteractiveAnimatedProp(GenericAnimatedProp.GenericAnimatedProp, FSM.FSM):
animStr = self.path + '/' + self.ZoneToIdleIntoFightAnims[self.hoodId]
animKey = 'idleIntoFight'
animDict[animKey] = animStr
if self.hoodId in self.ZoneToIdleIntoFightAnims:
animStr = self.path + '/' + self.ZoneToVictoryAnims[self.hoodId]
animKey = 'victory'
animDict[animKey] = animStr
if self.hoodId in self.ZoneToSadAnims:
animStr = self.path + '/' + self.ZoneToSadAnims[self.hoodId]
animKey = 'sad'
animDict[animKey] = animStr
self.trashcan.loadAnims(animDict)
self.trashcan.pose('anim', 0)
self.node = self.trashcan
@ -113,6 +118,7 @@ class InteractiveAnimatedProp(GenericAnimatedProp.GenericAnimatedProp, FSM.FSM):
def createIdleInterval(self):
result = Sequence()
if self.numIdles >= 3:
numberOfAnimsAbove2 = self.numIdles - 2
for rareIdle in xrange(2, self.numIdles):
@ -152,26 +158,28 @@ class InteractiveAnimatedProp(GenericAnimatedProp.GenericAnimatedProp, FSM.FSM):
def createBattleCheerInterval(self):
result = Sequence()
for i in xrange(self.numFightAnims):
animKey = 'fight%d' % i
animIval = self.createAnimIval(animKey)
animAndSoundIval = self.createAnimAndSoundIval(animKey)
origAnimName = self.node.getAnimFilename(animKey).split('/')[-1]
if self.hasOverrideIval(origAnimName):
result.append(self.getOverrideIval(origAnimName))
elif self.hasSpecialIval(origAnimName):
result.append(Parallel(animIval, self.getSpecialIval(origAnimName)))
result.append(Parallel(animAndSoundIval, self.getSpecialIval(origAnimName)))
else:
result.append(animIval)
result.append(animAndSoundIval)
self.createBattleCheerText()
battleCheerTextIval = Sequence(Func(self.hpText.show), self.hpText.posInterval(duration=4.0, pos=Vec3(0, 0, 7), startPos=(0, 0, 3)), Func(self.hpText.hide))
ivalWithText = Parallel(battleCheerTextIval, result)
return ivalWithText
def createSadInterval(self):
result = Sequence()
if self.hoodId in self.ZoneToSadAnims:
result = self.createAnimIval('sad')
result = self.createAnimAndSoundIval('sad')
return result
def hasSpecialIval(self, origAnimName):
@ -188,18 +196,21 @@ class InteractiveAnimatedProp(GenericAnimatedProp.GenericAnimatedProp, FSM.FSM):
def createVictoryInterval(self):
result = Sequence()
if self.hoodId in self.ZoneToVictoryAnims:
animIval = self.createAnimIval('victory')
result.append(animIval)
animAndSoundIval = self.createAnimAndSoundIval('victory')
result.append(animAndSoundIval)
return result
def enter(self):
GenericAnimatedProp.GenericAnimatedProp.enter(self)
if base.config.GetBool('props-buff-battles', True):
self.notify.debug('props buff battles is true')
self.node.stop()
self.node.pose('idle0', 0)
self.idleInterval.loop()
self.requestIdleOrSad()
else:
self.notify.debug('props do not buff battles')
self.node.stop()
@ -215,6 +226,7 @@ class InteractiveAnimatedProp(GenericAnimatedProp.GenericAnimatedProp, FSM.FSM):
if not hasattr(self, 'node') or not self.node:
self.notify.warning("requestIdleOrSad returning hasattr(self,'node')=%s" % hasattr(self, 'node'))
return
if self.buildingsMakingMeSad:
self.request('Sad')
else:
@ -248,6 +260,7 @@ class InteractiveAnimatedProp(GenericAnimatedProp.GenericAnimatedProp, FSM.FSM):
def chooseIdleAnimToRun(self):
result = self.numIdles - 1
if base.config.GetBool('randomize-interactive-idles', True):
pairs = []
for i in xrange(self.numIdles):
@ -261,47 +274,54 @@ class InteractiveAnimatedProp(GenericAnimatedProp.GenericAnimatedProp, FSM.FSM):
result = self.lastPlayingAnimPhase + 1
if result >= len(self.ZoneToIdles[self.hoodId]):
result = 0
return result
def startNextIdleAnim(self):
self.notify.debug('startNextAnim self.okToStartNextAnim=%s' % self.okToStartNextAnim)
if not hasattr(self, 'node') or not self.node:
self.notify.warning("startNextIdleAnim returning hasattr(self,'node')=%s" % hasattr(self, 'node'))
return
self.curIval = None
if self.okToStartNextAnim:
self.notify.debug('got pass okToStartNextAnim')
whichAnim = self.chooseIdleAnimToRun()
if self.visId == localAvatar.zoneId:
self.notify.debug('whichAnim=%s' % whichAnim)
self.lastPlayingAnimPhase = whichAnim
self.curIval = self.createIdleAnimSequence(whichAnim)
self.notify.debug('starting curIval of length %s' % self.curIval.getDuration())
self.curIval.start()
else:
self.curIval = Wait(10)
self.curIval = Wait(3)
self.notify.debug('false self.okToStartNextAnim=%s' % self.okToStartNextAnim)
return
def createIdleAnimInterval(self, whichIdleAnim, startingTime = 0):
def createIdleAnimAndSoundInterval(self, whichIdleAnim, startingTime = 0):
animIval = self.node.actorInterval('idle%d' % whichIdleAnim, startTime=startingTime)
animIvalDuration = animIval.getDuration()
origAnimName = self.ZoneToIdles[self.hoodId][whichIdleAnim]
if isinstance(origAnimName, tuple):
origAnimName = origAnimName[0]
soundIval = self.createSoundInterval(origAnimName, animIvalDuration)
soundIvalDuration = soundIval.getDuration()
if self.hasSpecialIval(origAnimName):
specialIval = self.getSpecialIval(origAnimName)
return Parallel(animIval, specialIval)
return Parallel(animIval, soundIval, specialIval)
else:
return animIval
return Parallel(animIval, soundIval)
def createIdleAnimSequence(self, whichIdleAnim):
dummyResult = Sequence(Wait(self.IdlePauseTime))
if not hasattr(self, 'node') or not self.node:
self.notify.warning("createIdleAnimSequence returning dummyResult hasattr(self,'node')=%s" % hasattr(self, 'node'))
return dummyResult
idleAnim = self.createIdleAnimInterval(whichIdleAnim)
result = Sequence(idleAnim, Wait(self.IdlePauseTime), Func(self.startNextIdleAnim))
idleAnimAndSound = self.createIdleAnimAndSoundInterval(whichIdleAnim)
result = Sequence(idleAnimAndSound, Wait(self.IdlePauseTime), Func(self.startNextIdleAnim))
if isinstance(self.ZoneToIdles[self.hoodId][whichIdleAnim], tuple) and len(self.ZoneToIdles[self.hoodId][whichIdleAnim]) > 2:
info = self.ZoneToIdles[self.hoodId][whichIdleAnim]
origAnimName = info[0]
@ -314,17 +334,14 @@ class InteractiveAnimatedProp(GenericAnimatedProp.GenericAnimatedProp, FSM.FSM):
pauseTime = random.randrange(minPauseTime, maxPauseTime + 1)
result = Sequence()
for i in xrange(numberOfLoops):
result.append(idleAnim)
result.append(idleAnimAndSound)
if self.getSettleName(whichIdleAnim):
result.append(self.node.actorInterval('settle%d' % whichIdleAnim))
result.append(Wait(pauseTime))
result.append(Func(self.startNextIdleAnim))
return result
def gotoFaceoff(self):
self.notify.debugStateCall(self)
self.request('Faceoff')
return result
def gotoBattleCheer(self):
self.notify.debugStateCall(self)
@ -345,22 +362,14 @@ class InteractiveAnimatedProp(GenericAnimatedProp.GenericAnimatedProp, FSM.FSM):
def buildingLiberated(self, buildingDoId):
self.buildingsMakingMeSad.discard(buildingDoId)
if not self.buildingsMakingMeSad:
self.gotoIdle()
def enterFaceoff(self):
self.notify.debugStateCall(self)
self.curIval = self.createFaceoffInterval()
self.curIval.start()
def exitFaceoff(self):
self.notify.debugStateCall(self)
self.curIval.pause()
self.curIval = None
def calcWhichIdleAnim(self, animName):
result = 0
info = self.ZoneToIdles[self.hoodId]
for index, curInfo in enumerate(info):
if isinstance(curInfo, tuple):
if curInfo[0] == animName:
@ -373,82 +382,74 @@ class InteractiveAnimatedProp(GenericAnimatedProp.GenericAnimatedProp, FSM.FSM):
return result
def createFaceoffInterval(self):
result = Sequence()
if self.lastIdleAnimName:
whichIdleAnim = self.calcWhichIdleAnim(self.lastIdleAnimName)
anim = self.createIdleAnimInterval(whichIdleAnim, self.lastIdleTime)
result.append(anim)
idleIntoFightIval = self.createAnimIval('idleIntoFight')
result.append(idleIntoFightIval)
result.append(Func(self.gotoBattleCheer))
return result
def enterBattleCheer(self):
self.notify.debugStateCall(self)
self.curIval = self.battleCheerInterval
if self.curIval:
self.curIval.loop()
def exitBattleCheer(self):
self.notify.debugStateCall(self)
if self.curIval:
self.curIval.finish()
self.curIval = None
return
def enterVictory(self):
self.notify.debugStateCall(self)
self.curIval = self.victoryInterval
if self.curIval:
self.curIval.loop()
def exitVictory(self):
self.notify.debugStateCall(self)
if self.curIval:
self.curIval.finish()
self.curIval = None
return
def enterSad(self):
self.notify.debugStateCall(self)
self.curIval = self.sadInterval
if self.curIval:
self.curIval.loop()
def exitSad(self):
self.notify.debugStateCall(self)
if self.curIval:
self.curIval.finish()
self.curIval = None
return
def getSettleName(self, whichIdleAnim):
result = None
if isinstance(self.ZoneToIdles[self.hoodId][whichIdleAnim], tuple) and len(self.ZoneToIdles[self.hoodId][whichIdleAnim]) > 3:
result = self.ZoneToIdles[self.hoodId][whichIdleAnim][3]
return result
return self.ZoneToIdles[self.hoodId][whichIdleAnim][3]
return None
def getOrigIdleAnimName(self, whichIdleAnim):
result = None
if isinstance(self.ZoneToIdles[self.hoodId][whichIdleAnim], tuple):
result = self.ZoneToIdles[self.hoodId][whichIdleAnim][0]
else:
result = self.ZoneToIdles[self.hoodId][whichIdleAnim]
return result
anim = self.ZoneToIdles[self.hoodId][whichIdleAnim]
def createAnimIval(self, animKey):
return anim[0] if isinstance(anim, tuple) else anim
def createAnimAndSoundIval(self, animKey):
animIval = self.node.actorInterval(animKey)
animIvalDuration = animIval.getDuration()
origAnimName = self.node.getAnimFilename(animKey)
soundIval = self.createSoundInterval(origAnimName, animIvalDuration)
soundIvalDuration = soundIval.getDuration()
if self.hasSpecialIval(origAnimName):
specialIval = self.getSpecialIval(origAnimName)
return Parallel(animIval, specialIval)
return Parallel(animIval, soundIval, specialIval)
else:
return animIval
return Parallel(animIval, soundIval)
def clearCurIval(self):
if self.curIval:
self.curIval.finish()
clearPythonIvals(self.curIval)
self.curIval = None
self.curIval = None

View file

@ -69,9 +69,6 @@ class MailboxInteractiveProp(InteractiveAnimatedProp.InteractiveAnimatedProp):
IdlePauseTime = base.config.GetFloat('prop-idle-pause-time', 0.0)
def __init__(self, node):
InteractiveAnimatedProp.InteractiveAnimatedProp.__init__(self, node)
def setupActor(self, node):
self.pieActor = Actor.Actor('phase_5/models/char/tt_r_prp_ext_piePackage', {'fightBoost': 'phase_5/models/char/tt_a_prp_ext_piePackage_fightBoost'})
self.pieActor.reparentTo(self.node)

View file

@ -66,7 +66,4 @@ class TrashcanInteractiveProp(InteractiveAnimatedProp.InteractiveAnimatedProp):
ToontownGlobals.TheBrrrgh: ('tt_a_ara_tbr_trashcan_fightBoost', 'tt_a_ara_tbr_trashcan_fightCheer', 'tt_a_ara_tbr_trashcan_fightIdle'),
ToontownGlobals.DonaldsDreamland: ('tt_a_ara_ddl_trashcan_fightBoost', 'tt_a_ara_ddl_trashcan_fightCheer', 'tt_a_ara_ddl_trashcan_fightIdle')}
IdlePauseTime = base.config.GetFloat('prop-idle-pause-time', 0.0)
def __init__(self, node):
InteractiveAnimatedProp.InteractiveAnimatedProp.__init__(self, node)
IdlePauseTime = base.config.GetFloat('prop-idle-pause-time', 0.0)