def __healJoke(heal, hasInteractivePropHealBonus): npcId = 0 if 'npcId' in heal: npcId = heal['npcId'] toon = NPCToons.createLocalNPC(npcId) if toon == None: return else: toon = heal['toon'] targets = heal['target'] ineffective = heal['sidestep'] level = heal['level'] jokeIndex = heal['hpbonus'] % len(HealJokes.toonHealJokes) if npcId != 0: track = Sequence(MovieNPCSOS.teleportIn(heal, toon)) else: track = Sequence(__runToHealSpot(heal)) tracks = Parallel() fSpeakPunchline = 58 tSpeakSetup = 0.0 tSpeakPunchline = 3.0 dPunchLine = 3.0 tTargetReact = tSpeakPunchline + 1.0 dTargetLaugh = 1.5 tRunBack = tSpeakPunchline + dPunchLine tDoSoundAnimation = tSpeakPunchline - float(fSpeakPunchline) / toon.getFrameRate('sound') megaphone = globalPropPool.getProp('megaphone') megaphone2 = MovieUtil.copyProp(megaphone) megaphones = [megaphone, megaphone2] hands = toon.getRightHands() dMegaphoneScale = 0.5 tracks.append(Sequence(Wait(tDoSoundAnimation), Func(MovieUtil.showProps, megaphones, hands), MovieUtil.getScaleIntervals(megaphones, dMegaphoneScale, MovieUtil.PNT3_NEARZERO, MovieUtil.PNT3_ONE), Wait(toon.getDuration('sound') - 2.0 * dMegaphoneScale), MovieUtil.getScaleIntervals(megaphones, dMegaphoneScale, MovieUtil.PNT3_ONE, MovieUtil.PNT3_NEARZERO), Func(MovieUtil.removeProps, megaphones))) tracks.append(Sequence(Wait(tDoSoundAnimation), ActorInterval(toon, 'sound'))) soundTrack = __getSoundTrack(level, 2.0, node=toon) tracks.append(soundTrack) joke = HealJokes.toonHealJokes[jokeIndex] tracks.append(Sequence(Wait(tSpeakSetup), Func(toon.setChatAbsolute, joke[0], CFSpeech | CFTimeout))) tracks.append(Sequence(Wait(tSpeakPunchline), Func(toon.setChatAbsolute, joke[1], CFSpeech | CFTimeout))) reactTrack = Sequence(Wait(tTargetReact)) for target in targets: targetToon = target['toon'] hp = target['hp'] reactTrack.append(Func(__healToon, targetToon, hp, ineffective, hasInteractivePropHealBonus)) reactTrack.append(Wait(dTargetLaugh)) for target in targets: targetToon = target['toon'] reactTrack.append(Func(targetToon.clearChat)) tracks.append(reactTrack) if npcId != 0: track.append(Sequence(Wait(tRunBack), Func(toon.clearChat), *MovieNPCSOS.teleportOut(heal, toon))) else: tracks.append(Sequence(Wait(tRunBack), Func(toon.clearChat), *__returnToBase(heal))) track.append(tracks) return track
def __healDance(heal, hasInteractivePropHealBonus): npcId = 0 if 'npcId' in heal: npcId = heal['npcId'] toon = NPCToons.createLocalNPC(npcId) if toon == None: return else: toon = heal['toon'] targets = heal['target'] ineffective = heal['sidestep'] level = heal['level'] if npcId != 0: track = Sequence(MovieNPCSOS.teleportIn(heal, toon)) else: track = Sequence(__runToHealSpot(heal)) delay = 3.0 first = 1 targetTrack = Sequence() for target in targets: targetToon = target['toon'] hp = target['hp'] reactIval = Func(__healToon, targetToon, hp, ineffective, hasInteractivePropHealBonus) if first: targetTrack.append(Wait(delay)) first = 0 targetTrack.append(reactIval) hat = globalPropPool.getProp('hat') hat2 = MovieUtil.copyProp(hat) hats = [hat, hat2] cane = globalPropPool.getProp('cane') cane2 = MovieUtil.copyProp(cane) canes = [cane, cane2] leftHands = toon.getLeftHands() rightHands = toon.getRightHands() dScale = 0.5 propTrack = Sequence(Func(MovieUtil.showProps, hats, rightHands, Point3(0.23, 0.09, 0.69), Point3(180, 0, 0)), Func(MovieUtil.showProps, canes, leftHands, Point3(-0.28, 0.0, 0.14), Point3(0.0, 0.0, -150.0)), MovieUtil.getScaleIntervals(hats + canes, dScale, MovieUtil.PNT3_NEARZERO, MovieUtil.PNT3_ONE), Wait(toon.getDuration('happy-dance') - 2.0 * dScale), MovieUtil.getScaleIntervals(hats + canes, dScale, MovieUtil.PNT3_ONE, MovieUtil.PNT3_NEARZERO), Func(MovieUtil.removeProps, hats + canes)) mtrack = Parallel(propTrack, ActorInterval(toon, 'happy-dance'), __getSoundTrack(level, 0.2, duration=6.4, node=toon), targetTrack) track.append(Func(toon.loop, 'neutral')) track.append(Wait(0.1)) track.append(mtrack) if npcId != 0: track.append(MovieNPCSOS.teleportOut(heal, toon)) else: track.append(__returnToBase(heal)) for target in targets: targetToon = target['toon'] track.append(Func(targetToon.clearChat)) return track
def doSounds(sounds): if len(sounds) == 0: return (None, None) npcArrivals, npcDepartures, npcs = MovieNPCSOS.doNPCTeleports(sounds) mtrack = Parallel() hitCount = 0 prevLevel = 0 prevSounds = [[], [], [], [], [], [], []] for sound in sounds: level = sound['level'] prevSounds[level].append(sound) for target in sound['target']: if target['hp'] > 0: hitCount += 1 break delay = 0.0 for soundList in prevSounds: if len(soundList) > 0: mtrack.append(__doSoundsLevel(soundList, delay, hitCount, npcs)) delay += TOON_SOUND_DELAY soundTrack = Sequence(npcArrivals, mtrack, npcDepartures) targets = sounds[0]['target'] camDuration = mtrack.getDuration() enterDuration = npcArrivals.getDuration() exitDuration = npcDepartures.getDuration() camTrack = MovieCamera.chooseSoundShot(sounds, targets, camDuration, enterDuration, exitDuration) return (soundTrack, camTrack)
def __doToonAttacks(self): if base.config.GetBool('want-toon-attack-anims', 1): track = Sequence(name='toon-attacks') camTrack = Sequence(name='toon-attacks-cam') ival, camIval = MovieFire.doFires(self.__findToonAttack(FIRE)) if ival: track.append(ival) camTrack.append(camIval) ival, camIval = MovieSOS.doSOSs(self.__findToonAttack(SOS)) if ival: track.append(ival) camTrack.append(camIval) ival, camIval = MovieNPCSOS.doNPCSOSs(self.__findToonAttack(NPCSOS)) if ival: track.append(ival) camTrack.append(camIval) ival, camIval = MoviePetSOS.doPetSOSs(self.__findToonAttack(PETSOS)) if ival: track.append(ival) camTrack.append(camIval) hasHealBonus = self.battle.getInteractivePropTrackBonus() == HEAL ival, camIval = MovieHeal.doHeals(self.__findToonAttack(HEAL), hasHealBonus) if ival: track.append(ival) camTrack.append(camIval) ival, camIval = MovieTrap.doTraps(self.__findToonAttack(TRAP)) if ival: track.append(ival) camTrack.append(camIval) ival, camIval = MovieLure.doLures(self.__findToonAttack(LURE)) if ival: track.append(ival) camTrack.append(camIval) ival, camIval = MovieSound.doSounds(self.__findToonAttack(SOUND)) if ival: track.append(ival) camTrack.append(camIval) ival, camIval = MovieThrow.doThrows(self.__findToonAttack(THROW)) if ival: track.append(ival) camTrack.append(camIval) ival, camIval = MovieSquirt.doSquirts(self.__findToonAttack(SQUIRT)) if ival: track.append(ival) camTrack.append(camIval) ival, camIval = MovieZap.doZaps(self.__findToonAttack(ZAP)) if ival: track.append(ival) camTrack.append(camIval) ival, camIval = MovieDrop.doDrops(self.__findToonAttack(DROP)) if ival: track.append(ival) camTrack.append(camIval) if len(track) == 0: return (None, None) else: return (track, camTrack) else: return (None, None) return None
def __healJuggle(heal, hasInteractivePropHealBonus): npcId = 0 if 'npcId' in heal: npcId = heal['npcId'] toon = NPCToons.createLocalNPC(npcId) if toon == None: return else: toon = heal['toon'] targets = heal['target'] ineffective = heal['sidestep'] level = heal['level'] if npcId != 0: track = Sequence(MovieNPCSOS.teleportIn(heal, toon)) else: track = Sequence(__runToHealSpot(heal)) delay = 4.0 first = 1 targetTrack = Sequence() for target in targets: targetToon = target['toon'] hp = target['hp'] reactIval = Func(__healToon, targetToon, hp, ineffective, hasInteractivePropHealBonus) if first == 1: targetTrack.append(Wait(delay)) first = 0 targetTrack.append(reactIval) cube = globalPropPool.getProp('cubes') cube2 = MovieUtil.copyProp(cube) cubes = [cube, cube2] hips = [toon.getLOD(toon.getLODNames()[0]).find('**/joint_hips'), toon.getLOD(toon.getLODNames()[1]).find('**/joint_hips')] cubeTrack = Sequence(Func(MovieUtil.showProps, cubes, hips), MovieUtil.getActorIntervals(cubes, 'cubes'), Func(MovieUtil.removeProps, cubes)) mtrack = Parallel(cubeTrack, __getSoundTrack(level, 0.7, duration=7.7, node=toon), ActorInterval(toon, 'juggle'), targetTrack) track.append(mtrack) if npcId != 0: track.append(MovieNPCSOS.teleportOut(heal, toon)) else: track.append(__returnToBase(heal)) for target in targets: targetToon = target['toon'] track.append(Func(targetToon.clearChat)) return track
def doZaps(zaps): if len(zaps) == 0: return (None, None) suitZapsDict = {} doneUber = 0 npcArrivals, npcDepartures, npcs = MovieNPCSOS.doNPCTeleports(zaps) skip = 0 for zap in zaps: skip = 0 if skip: pass elif type(zap['target']) == type([]): if 1: target = zap['target'][0] suitId = target['suit'].doId if suitId in suitZapsDict: suitZapsDict[suitId].append(zap) else: suitZapsDict[suitId] = [zap] else: suitId = zap['target']['suit'].doId if suitId in suitZapsDict: suitZapsDict[suitId].append(zap) else: suitZapsDict[suitId] = [zap] suitZaps = suitZapsDict.values() def compFunc(a, b): if len(a) > len(b): return 1 elif len(a) < len(b): return -1 return 0 suitZaps.sort(compFunc) delay = 0.0 mtrack = Parallel() for st in suitZaps: if len(st) > 0: ival = __doSuitZaps(st, npcs) if ival: mtrack.append(Sequence(Wait(delay), ival)) delay = delay + TOON_ZAP_SUIT_DELAY zapTrack = Sequence(npcArrivals, mtrack, npcDepartures) enterDuration = npcArrivals.getDuration() exitDuration = npcDepartures.getDuration() camDuration = zapTrack.getDuration() camTrack = MovieCamera.chooseLureShot(zaps, camDuration, enterDuration, exitDuration) return (zapTrack, camTrack)
def doLures(lures): if len(lures) == 0: return (None, None) npcArrivals, npcDepartures, npcs = MovieNPCSOS.doNPCTeleports(lures) mtrack = Parallel() for l in lures: ival = __doLureLevel(l, npcs) if ival: mtrack.append(ival) lureTrack = Sequence(npcArrivals, mtrack, npcDepartures) camDuration = mtrack.getDuration() enterDuration = npcArrivals.getDuration() exitDuration = npcDepartures.getDuration() camTrack = MovieCamera.chooseLureShot(lures, camDuration, enterDuration, exitDuration) return (lureTrack, camTrack)
def doTraps(traps): if len(traps) == 0: return (None, None) npcArrivals, npcDepartures, npcs = MovieNPCSOS.doNPCTeleports(traps) hasUberTrapConflict = False suitTrapsDict = {} for trap in traps: targets = trap['target'] if len(targets) == 1: suitId = targets[0]['suit'].doId if suitId in suitTrapsDict: suitTrapsDict[suitId].append(trap) else: suitTrapsDict[suitId] = [trap] else: for target in targets: suitId = target['suit'].doId if suitId not in suitTrapsDict: suitTrapsDict[suitId] = [trap] break if trap['level'] == UBER_GAG_LEVEL_INDEX: if len(traps) > 1: hasUberTrapConflict = True for oneTarget in trap['target']: suit = oneTarget['suit'] if suit.battleTrap != NO_TRAP: hasUberTrapConflict = True suitTrapLists = suitTrapsDict.values() mtrack = Parallel() for trapList in suitTrapLists: trapPropList = [] for i in xrange(len(trapList)): trap = trapList[i] level = trap['level'] if level == 0: banana = globalPropPool.getProp('banana') banana2 = MovieUtil.copyProp(banana) trapPropList.append([banana, banana2]) elif level == 1: rake = globalPropPool.getProp('rake') rake2 = MovieUtil.copyProp(rake) rake.pose('rake', 0) rake2.pose('rake', 0) trapPropList.append([rake, rake2]) elif level == 2: marbles = globalPropPool.getProp('marbles') marbles2 = MovieUtil.copyProp(marbles) trapPropList.append([marbles, marbles2]) elif level == 3: trapPropList.append([globalPropPool.getProp('quicksand')]) elif level == 4: trapPropList.append([globalPropPool.getProp('trapdoor')]) elif level == 5: tnt = globalPropPool.getProp('tnt') tnt2 = MovieUtil.copyProp(tnt) trapPropList.append([tnt, tnt2]) elif level == 6: tnt = globalPropPool.getProp('traintrack') tnt2 = MovieUtil.copyProp(tnt) trapPropList.append([tnt, tnt2]) else: notify.warning( '__doTraps() - Incorrect trap level: %d' % level) if len(trapList) == 1 and not hasUberTrapConflict: ival = __doTrapLevel(trapList[0], trapPropList[0]) if ival: mtrack.append(ival) else: subMtrack = Parallel() for i in xrange(len(trapList)): trap = trapList[i] trapProps = trapPropList[i] ival = __doTrapLevel(trap, trapProps, explode=1) if ival: subMtrack.append(ival) mtrack.append(subMtrack) trapTrack = Sequence(npcArrivals, mtrack, npcDepartures) camDuration = mtrack.getDuration() enterDuration = npcArrivals.getDuration() exitDuration = npcDepartures.getDuration() camTrack = MovieCamera.chooseTrapShot(traps, camDuration, enterDuration, exitDuration) return (trapTrack, camTrack)
def __healDive(heal, hasInteractivePropHealBonus): splash = Splash.Splash(render) splash.reparentTo(render) npcId = 0 if 'npcId' in heal: npcId = heal['npcId'] toon = NPCToons.createLocalNPC(npcId) if toon == None: return None else: toon = heal['toon'] targets = heal['target'] ineffective = heal['sidestep'] level = heal['level'] if npcId != 0: track = Sequence(MovieNPCSOS.teleportIn(heal, toon)) else: track = Sequence(__runToHealSpot(heal)) delay = 7.0 first = 1 targetTrack = Sequence() for target in targets: targetToon = target['toon'] hp = target['hp'] reactIval = Func(__healToon, targetToon, hp, ineffective, hasInteractivePropHealBonus) if first == 1: targetTrack.append(Wait(delay)) first = 0 targetTrack.append(reactIval) thisBattle = heal['battle'] toonsInBattle = thisBattle.toons glass = globalPropPool.getProp('glass') glass.setScale(4.0) glass.setHpr(0.0, 90.0, 0.0) ladder = globalPropPool.getProp('ladder') placeNode = NodePath('lookNode') diveProps = [glass, ladder] ladderScale = toon.getBodyScale() / 0.66 scaleUpPoint = Point3(0.5, 0.5, 0.45) * ladderScale basePos = toon.getPos() glassOffset = Point3(0, 1.1, 0.2) glassToonOffset = Point3(0, 1.2, 0.2) splashOffset = Point3(0, 1.0, 0.4) ladderOffset = Point3(0, 4, 0) ladderToonSep = Point3(0, 1, 0) * ladderScale diveOffset = Point3(0, 0, 10) divePos = add3(add3(ladderOffset, diveOffset), ladderToonSep) ladder.setH(toon.getH()) glassPos = render.getRelativePoint(toon, glassOffset) glassToonPos = render.getRelativePoint(toon, glassToonOffset) ladderPos = render.getRelativePoint(toon, ladderOffset) climbladderPos = render.getRelativePoint(toon, add3(ladderOffset, ladderToonSep)) divePos = render.getRelativePoint(toon, divePos) topDivePos = render.getRelativePoint(toon, diveOffset) lookBase = render.getRelativePoint(toon, ladderOffset) lookTop = render.getRelativePoint(toon, add3(ladderOffset, diveOffset)) LookGlass = render.getRelativePoint(toon, glassOffset) splash.setPos(splashOffset) walkToLadderTime = 1.0 climbTime = 5.0 diveTime = 1.0 ladderGrowTime = 1.5 splash.setPos(glassPos) toonNode = toon.getGeomNode() placeNode.reparentTo(render) placeNode.setScale(5.0) placeNode.setPos(toon.getPos(render)) placeNode.setHpr(toon.getHpr(render)) toonscale = toonNode.getScale() toonFacing = toon.getHpr() propTrack = Sequence(Func(MovieUtil.showProp, glass, render, glassPos), Func(MovieUtil.showProp, ladder, render, ladderPos), Func(toonsLook, toonsInBattle, placeNode, Point3(0, 0, 0)), Func(placeNode.setPos, lookBase), LerpScaleInterval(ladder, ladderGrowTime, scaleUpPoint, startScale=MovieUtil.PNT3_NEARZERO), Func(placeNode.setPos, lookTop), Wait(2.1), MovieCamera.toonGroupHighShot(None, 0), Wait(2.1), Func(placeNode.setPos, LookGlass), Wait(0.4), MovieCamera.allGroupLowShot(None, 0), Wait(1.8), LerpScaleInterval(ladder, ladderGrowTime, MovieUtil.PNT3_NEARZERO, startScale=scaleUpPoint), Func(MovieUtil.removeProps, diveProps)) mtrack = Parallel(propTrack, __getSoundTrack(level, 0.6, duration=9.0, node=toon), Sequence(Parallel(Sequence(ActorInterval(toon, 'walk', loop=0, duration=walkToLadderTime), ActorInterval(toon, 'neutral', loop=0, duration=0.1)), LerpPosInterval(toon, walkToLadderTime, climbladderPos), Wait(ladderGrowTime)), Parallel(ActorInterval(toon, 'climb', loop=0, endFrame=116), Sequence(Wait(4.6), Func(toonNode.setTransparency, 1), LerpColorScaleInterval(toonNode, 0.25, VBase4(1, 1.0, 1, 0.0), blendType='easeInOut'), LerpScaleInterval(toonNode, 0.01, 0.1, startScale=toonscale), LerpHprInterval(toon, 0.01, toonFacing), LerpPosInterval(toon, 0.0, glassToonPos), Func(toonNode.clearTransparency), Func(toonNode.clearColorScale), Parallel(ActorInterval(toon, 'swim', loop=1, startTime=0.0, endTime=1.0), Wait(1.0))), Sequence(Wait(4.6), Func(splash.play), Wait(1.0), Func(splash.destroy))), Wait(0.5), Parallel(ActorInterval(toon, 'jump', loop=0, startTime=0.2), LerpScaleInterval(toonNode, 0.5, toonscale, startScale=0.1), Func(stopLook, toonsInBattle))), targetTrack) track.append(mtrack) if npcId != 0: track.append(MovieNPCSOS.teleportOut(heal, toon)) else: track.append(__returnToBase(heal)) for target in targets: targetToon = target['toon'] track.append(Func(targetToon.clearChat)) return track
def doFires(fires): npcArrivals, npcDepartures, npcs = MovieNPCSOS.doNPCTeleports(fires) if len(fires) == 0: return (None, None) suitFiresDict = {} i = 0 try: attempt = fires[0]['target'][i]['suit'] doAdd = True except: doAdd = False for fire in fires: if doAdd: suitId = fire['target'][i]['suit'].doId i = i + 1 else: suitId = fire['target']['suit'].doId if suitId in suitFiresDict: suitFiresDict[suitId].append(fire) else: suitFiresDict[suitId] = [fire] suitFires = suitFiresDict.values() def compFunc(a, b): if len(a) > len(b): return 1 if len(a) < len(b): return -1 return 0 suitFires.sort(compFunc) totalHitDict = {} singleHitDict = {} groupHitDict = {} i = 0 for fire in fires: if doAdd: suitId = fire['target'][i]['suit'].doId else: suitId = fire['target']['suit'].doId if doAdd: if fire['target'][i]['hp'] > 0: addHit(singleHitDict, suitId, 1) addHit(totalHitDict, suitId, 1) else: addHit(singleHitDict, suitId, 0) addHit(totalHitDict, suitId, 0) i = i + 1 elif fire['target']['hp'] > 0: addHit(singleHitDict, suitId, 1) addHit(totalHitDict, suitId, 1) else: addHit(singleHitDict, suitId, 0) addHit(totalHitDict, suitId, 0) notify.debug('singleHitDict = %s' % singleHitDict) notify.debug('groupHitDict = %s' % groupHitDict) notify.debug('totalHitDict = %s' % totalHitDict) delay = 0.0 mtrack = Parallel() firedTargets = [] for sf in suitFires: if len(sf) > 0: ival = __doSuitFires(sf) if ival: mtrack.append(Sequence(Wait(delay), ival)) delay = delay + TOON_FIRE_SUIT_DELAY retTrack = Sequence() retTrack.append(npcArrivals) retTrack.append(mtrack) retTrack.append(npcDepartures) enterDuration = npcArrivals.getDuration() exitDuration = npcDepartures.getDuration() camDuration = retTrack.getDuration() camTrack = MovieCamera.chooseFireShot(fires, suitFiresDict, camDuration, enterDuration, exitDuration) return (retTrack, camTrack)
def doThrows(throws): npcArrivals, npcDepartures, npcs = MovieNPCSOS.doNPCTeleports(throws) if len(throws) == 0: return (None, None) suitThrowsDict = {} for throw in throws: if attackAffectsGroup(throw['track'], throw['level']): pass else: suitId = throw['target']['suit'].doId if suitId in suitThrowsDict: suitThrowsDict[suitId].append(throw) else: suitThrowsDict[suitId] = [throw] suitThrows = suitThrowsDict.values() def compFunc(a, b): if len(a) > len(b): return 1 if len(a) < len(b): return -1 return 0 suitThrows.sort(compFunc) totalHitDict = {} singleHitDict = {} groupHitDict = {} for throw in throws: if attackAffectsGroup(throw['track'], throw['level']): for i in xrange(len(throw['target'])): target = throw['target'][i] suitId = target['suit'].doId if target['hp'] > 0: addHit(groupHitDict, suitId, 1) addHit(totalHitDict, suitId, 1) else: addHit(groupHitDict, suitId, 0) addHit(totalHitDict, suitId, 0) else: suitId = throw['target']['suit'].doId if throw['target']['hp'] > 0: addHit(singleHitDict, suitId, 1) addHit(totalHitDict, suitId, 1) else: addHit(singleHitDict, suitId, 0) addHit(totalHitDict, suitId, 0) notify.debug('singleHitDict = %s' % singleHitDict) notify.debug('groupHitDict = %s' % groupHitDict) notify.debug('totalHitDict = %s' % totalHitDict) delay = 0.0 mtrack = Parallel() for st in suitThrows: if len(st) > 0: ival = __doSuitThrows(st, npcs) if ival: mtrack.append(Sequence(Wait(delay), ival)) delay = delay + TOON_THROW_SUIT_DELAY retTrack = Sequence() retTrack.append(npcArrivals) retTrack.append(mtrack) groupThrowIvals = Parallel() groupThrows = [] for throw in throws: if attackAffectsGroup(throw['track'], throw['level']): groupThrows.append(throw) for throw in groupThrows: tracks = None tracks = __throwGroupPie(throw, 0, groupHitDict, npcs) if tracks: for track in tracks: groupThrowIvals.append(track) retTrack.append(groupThrowIvals) retTrack.append(npcDepartures) camDuration = retTrack.getDuration() enterDuration = npcArrivals.getDuration() exitDuration = npcDepartures.getDuration() camTrack = MovieCamera.chooseThrowShot(throws, suitThrowsDict, camDuration, enterDuration=enterDuration, exitDuration=exitDuration) return (retTrack, camTrack)
def doDrops(drops): if len(drops) == 0: return (None, None) npcArrivals, npcDepartures, npcs = MovieNPCSOS.doNPCTeleports(drops) suitDropsDict = {} groupDrops = [] for drop in drops: track = drop['track'] level = drop['level'] targets = drop['target'] if len(targets) == 1: suitId = targets[0]['suit'].doId if suitId in suitDropsDict: suitDropsDict[suitId].append((drop, targets[0])) else: suitDropsDict[suitId] = [(drop, targets[0])] elif level <= MAX_LEVEL_INDEX and attackAffectsGroup(track, level): groupDrops.append(drop) else: for target in targets: suitId = target['suit'].doId if suitId in suitDropsDict: otherDrops = suitDropsDict[suitId] alreadyInList = 0 for oDrop in otherDrops: if oDrop[0]['toon'] == drop['toon']: alreadyInList = 1 if alreadyInList == 0: suitDropsDict[suitId].append((drop, target)) else: suitDropsDict[suitId] = [(drop, target)] suitDrops = suitDropsDict.values() def compFunc(a, b): if len(a) > len(b): return 1 elif len(a) < len(b): return -1 return 0 suitDrops.sort(compFunc) delay = 0.0 mtrack = Parallel(name='toplevel-drop') npcDrops = {} for st in suitDrops: if len(st) > 0: ival = __doSuitDrops(st, npcs, npcDrops) if ival: mtrack.append(Sequence(Wait(delay), ival)) delay = delay + TOON_DROP_SUIT_DELAY dropTrack = Sequence(npcArrivals, mtrack, npcDepartures) camDuration = mtrack.getDuration() if groupDrops: ival = __doGroupDrops(groupDrops) dropTrack.append(ival) camDuration += ival.getDuration() enterDuration = npcArrivals.getDuration() exitDuration = npcDepartures.getDuration() camTrack = MovieCamera.chooseDropShot(drops, suitDropsDict, camDuration, enterDuration, exitDuration) return (dropTrack, camTrack)