from direct.actor import Actor from direct.directnotify import DirectNotifyGlobal from direct.interval.IntervalGlobal import * from direct.showbase.PythonUtil import Functor from direct.task.Task import Task from panda3d.core import * import random import types import math import AccessoryGlobals import Motion import TTEmote import ToonDNA import LaffMeter from ToonHead import * from otp.ai.MagicWordGlobal import * from otp.avatar import Avatar from otp.avatar import Emote from otp.avatar.Avatar import teleportNotify from otp.otpbase import OTPGlobals from otp.otpbase import OTPLocalizer from toontown.battle import SuitBattleGlobals from otp.nametag.NametagConstants import * from toontown.distributed import DelayDelete from toontown.effects import DustCloud from toontown.effects import Wake from toontown.hood import ZoneUtil from otp.nametag.NametagGroup import * from toontown.suit import SuitDNA from toontown.toonbase import TTLocalizer from toontown.toonbase import ToontownGlobals from toontown.toon import LaughingManGlobals def teleportDebug(requestStatus, msg, onlyIfToAv = True): if teleportNotify.getDebug(): teleport = 'teleport' if 'how' in requestStatus and requestStatus['how'][:len(teleport)] == teleport: if not onlyIfToAv or 'avId' in requestStatus and requestStatus['avId'] > 0: teleportNotify.debug(msg) SLEEP_STRING = TTLocalizer.ToonSleepString DogDialogueArray = [] CatDialogueArray = [] HorseDialogueArray = [] RabbitDialogueArray = [] MouseDialogueArray = [] DuckDialogueArray = [] MonkeyDialogueArray = [] BearDialogueArray = [] PigDialogueArray = [] LegsAnimDict = {} TorsoAnimDict = {} HeadAnimDict = {} Preloaded = {} Phase3AnimList = (('neutral', 'neutral'), ('run', 'run')) Phase3_5AnimList = (('walk', 'walk'), ('teleport', 'teleport'), ('book', 'book'), ('jump', 'jump'), ('running-jump', 'running-jump'), ('jump-squat', 'jump-zstart'), ('jump-idle', 'jump-zhang'), ('jump-land', 'jump-zend'), ('running-jump-squat', 'leap_zstart'), ('running-jump-idle', 'leap_zhang'), ('running-jump-land', 'leap_zend'), ('pushbutton', 'press-button'), ('throw', 'pie-throw'), ('victory', 'victory-dance'), ('sidestep-left', 'sidestep-left'), ('conked', 'conked'), ('cringe', 'cringe'), ('wave', 'wave'), ('shrug', 'shrug'), ('angry', 'angry'), ('tutorial-neutral', 'tutorial-neutral'), ('left-point', 'left-point'), ('right-point', 'right-point'), ('right-point-start', 'right-point-start'), ('give-props', 'give-props'), ('give-props-start', 'give-props-start'), ('right-hand', 'right-hand'), ('right-hand-start', 'right-hand-start'), ('duck', 'duck'), ('sidestep-right', 'jump-back-right'), ('periscope', 'periscope')) Phase4AnimList = (('sit', 'sit'), ('sit-start', 'intoSit'), ('swim', 'swim'), ('tug-o-war', 'tug-o-war'), ('sad-walk', 'losewalk'), ('sad-neutral', 'sad-neutral'), ('up', 'up'), ('down', 'down'), ('left', 'left'), ('right', 'right'), ('applause', 'applause'), ('confused', 'confused'), ('bow', 'bow'), ('curtsy', 'curtsy'), ('bored', 'bored'), ('think', 'think'), ('battlecast', 'fish'), ('cast', 'cast'), ('castlong', 'castlong'), ('fish-end', 'fishEND'), ('fish-neutral', 'fishneutral'), ('fish-again', 'fishAGAIN'), ('reel', 'reel'), ('reel-H', 'reelH'), ('reel-neutral', 'reelneutral'), ('pole', 'pole'), ('pole-neutral', 'poleneutral'), ('slip-forward', 'slip-forward'), ('slip-backward', 'slip-backward'), ('catch-neutral', 'gameneutral'), ('catch-run', 'gamerun'), ('catch-eatneutral', 'eat_neutral'), ('catch-eatnrun', 'eatnrun'), ('catch-intro-throw', 'gameThrow'), ('swing', 'swing'), ('pet-start', 'petin'), ('pet-loop', 'petloop'), ('pet-end', 'petend'), ('scientistJealous', 'scientistJealous'), ('scientistEmcee', 'scientistEmcee'), ('scientistWork', 'scientistWork'), ('scientistGame', 'scientistGame'), ('taunt', 'taunt')) Phase5AnimList = (('water-gun', 'water-gun'), ('hold-bottle', 'hold-bottle'), ('firehose', 'firehose'), ('spit', 'spit'), ('tickle', 'tickle'), ('smooch', 'smooch'), ('happy-dance', 'happy-dance'), ('sprinkle-dust', 'sprinkle-dust'), ('juggle', 'juggle'), ('climb', 'climb'), ('sound', 'shout'), ('toss', 'toss'), ('hold-magnet', 'hold-magnet'), ('hypnotize', 'hypnotize'), ('struggle', 'struggle'), ('lose', 'lose'), ('melt', 'melt')) Phase5_5AnimList = (('takePhone', 'takePhone'), ('phoneNeutral', 'phoneNeutral'), ('phoneBack', 'phoneBack'), ('bank', 'jellybeanJar'), ('callPet', 'callPet'), ('feedPet', 'feedPet'), ('start-dig', 'into_dig'), ('loop-dig', 'loop_dig'), ('water', 'water')) Phase6AnimList = (('headdown-putt', 'headdown-putt'), ('into-putt', 'into-putt'), ('loop-putt', 'loop-putt'), ('rotateL-putt', 'rotateL-putt'), ('rotateR-putt', 'rotateR-putt'), ('swing-putt', 'swing-putt'), ('look-putt', 'look-putt'), ('lookloop-putt', 'lookloop-putt'), ('bad-putt', 'bad-putt'), ('badloop-putt', 'badloop-putt'), ('good-putt', 'good-putt')) Phase9AnimList = (('push', 'push'),) Phase10AnimList = (('leverReach', 'leverReach'), ('leverPull', 'leverPull'), ('leverNeutral', 'leverNeutral')) Phase12AnimList = () LegDict = {'s': '/models/char/tt_a_chr_dgs_shorts_legs_', 'm': '/models/char/tt_a_chr_dgm_shorts_legs_', 'l': '/models/char/tt_a_chr_dgl_shorts_legs_'} TorsoDict = { 'ss': '/models/char/tt_a_chr_dgs_shorts_torso_', 'ms': '/models/char/tt_a_chr_dgm_shorts_torso_', 'ls': '/models/char/tt_a_chr_dgl_shorts_torso_', 'sd': '/models/char/tt_a_chr_dgs_skirt_torso_', 'md': '/models/char/tt_a_chr_dgm_skirt_torso_', 'ld': '/models/char/tt_a_chr_dgl_skirt_torso_'} def loadModels(): global Preloaded if not Preloaded: print 'Preloading avatars...' for key in LegDict.keys(): fileRoot = LegDict[key] Preloaded[fileRoot+'-1000'] = loader.loadModel('phase_3' + fileRoot + '1000') Preloaded[fileRoot+'-500'] = loader.loadModel('phase_3' + fileRoot + '500') Preloaded[fileRoot+'-250'] = loader.loadModel('phase_3' + fileRoot + '250') for key in TorsoDict.keys(): fileRoot = TorsoDict[key] Preloaded[fileRoot+'-1000'] = loader.loadModel('phase_3' + fileRoot + '1000') if len(key) > 1: Preloaded[fileRoot+'-500'] = loader.loadModel('phase_3' + fileRoot + '500') Preloaded[fileRoot+'-250'] = loader.loadModel('phase_3' + fileRoot + '250') def loadBasicAnims(): loadPhaseAnims() def unloadBasicAnims(): loadPhaseAnims(0) def loadTutorialBattleAnims(): loadPhaseAnims('phase_3.5') def unloadTutorialBattleAnims(): loadPhaseAnims('phase_3.5', 0) def loadMinigameAnims(): loadPhaseAnims('phase_4') def unloadMinigameAnims(): loadPhaseAnims('phase_4', 0) def loadBattleAnims(): loadPhaseAnims('phase_5') def unloadBattleAnims(): loadPhaseAnims('phase_5', 0) def loadSellbotHQAnims(): loadPhaseAnims('phase_9') def unloadSellbotHQAnims(): loadPhaseAnims('phase_9', 0) def loadCashbotHQAnims(): loadPhaseAnims('phase_10') def unloadCashbotHQAnims(): loadPhaseAnims('phase_10', 0) def loadBossbotHQAnims(): loadPhaseAnims('phase_12') def unloadBossbotHQAnims(): loadPhaseAnims('phase_12', 0) def loadPhaseAnims(phaseStr = 'phase_3', loadFlag = 1): if phaseStr == 'phase_3': animList = Phase3AnimList elif phaseStr == 'phase_3.5': animList = Phase3_5AnimList elif phaseStr == 'phase_4': animList = Phase4AnimList elif phaseStr == 'phase_5': animList = Phase5AnimList elif phaseStr == 'phase_5.5': animList = Phase5_5AnimList elif phaseStr == 'phase_6': animList = Phase6AnimList elif phaseStr == 'phase_9': animList = Phase9AnimList elif phaseStr == 'phase_10': animList = Phase10AnimList elif phaseStr == 'phase_12': animList = Phase12AnimList else: self.notify.error('Unknown phase string %s' % phaseStr) for key in LegDict.keys(): for anim in animList: if loadFlag: pass elif anim[0] in LegsAnimDict[key]: if base.localAvatar.style.legs == key: base.localAvatar.unloadAnims([anim[0]], 'legs', None) for key in TorsoDict.keys(): for anim in animList: if loadFlag: pass elif anim[0] in TorsoAnimDict[key]: if base.localAvatar.style.torso == key: base.localAvatar.unloadAnims([anim[0]], 'torso', None) for key in HeadDict.keys(): if key.find('d') >= 0: for anim in animList: if loadFlag: pass elif anim[0] in HeadAnimDict[key]: if base.localAvatar.style.head == key: base.localAvatar.unloadAnims([anim[0]], 'head', None) def compileGlobalAnimList(): phaseList = [Phase3AnimList, Phase3_5AnimList, Phase4AnimList, Phase5AnimList, Phase5_5AnimList, Phase6AnimList, Phase9AnimList, Phase10AnimList, Phase12AnimList] phaseStrList = ['phase_3', 'phase_3.5', 'phase_4', 'phase_5', 'phase_5.5', 'phase_6', 'phase_9', 'phase_10', 'phase_12'] for animList in phaseList: phaseStr = phaseStrList[phaseList.index(animList)] for key in LegDict.keys(): LegsAnimDict.setdefault(key, {}) for anim in animList: file = phaseStr + LegDict[key] + anim[1] LegsAnimDict[key][anim[0]] = file for key in TorsoDict.keys(): TorsoAnimDict.setdefault(key, {}) for anim in animList: file = phaseStr + TorsoDict[key] + anim[1] TorsoAnimDict[key][anim[0]] = file for key in HeadDict.keys(): if key.find('d') >= 0: HeadAnimDict.setdefault(key, {}) for anim in animList: file = phaseStr + HeadDict[key] + anim[1] HeadAnimDict[key][anim[0]] = file def loadDialog(): loadPath = 'phase_3.5/audio/dial/' DogDialogueFiles = ('AV_dog_short', 'AV_dog_med', 'AV_dog_long', 'AV_dog_question', 'AV_dog_exclaim', 'AV_dog_howl') global DogDialogueArray for file in DogDialogueFiles: DogDialogueArray.append(base.loadSfx(loadPath + file + '.ogg')) catDialogueFiles = ('AV_cat_short', 'AV_cat_med', 'AV_cat_long', 'AV_cat_question', 'AV_cat_exclaim', 'AV_cat_howl') global CatDialogueArray for file in catDialogueFiles: CatDialogueArray.append(base.loadSfx(loadPath + file + '.ogg')) horseDialogueFiles = ('AV_horse_short', 'AV_horse_med', 'AV_horse_long', 'AV_horse_question', 'AV_horse_exclaim', 'AV_horse_howl') global HorseDialogueArray for file in horseDialogueFiles: HorseDialogueArray.append(base.loadSfx(loadPath + file + '.ogg')) rabbitDialogueFiles = ('AV_rabbit_short', 'AV_rabbit_med', 'AV_rabbit_long', 'AV_rabbit_question', 'AV_rabbit_exclaim', 'AV_rabbit_howl') global RabbitDialogueArray for file in rabbitDialogueFiles: RabbitDialogueArray.append(base.loadSfx(loadPath + file + '.ogg')) mouseDialogueFiles = ('AV_mouse_short', 'AV_mouse_med', 'AV_mouse_long', 'AV_mouse_question', 'AV_mouse_exclaim', 'AV_mouse_howl') global MouseDialogueArray for file in mouseDialogueFiles: MouseDialogueArray.append(base.loadSfx(loadPath + file + '.ogg')) duckDialogueFiles = ('AV_duck_short', 'AV_duck_med', 'AV_duck_long', 'AV_duck_question', 'AV_duck_exclaim', 'AV_duck_howl') global DuckDialogueArray for file in duckDialogueFiles: DuckDialogueArray.append(base.loadSfx(loadPath + file + '.ogg')) monkeyDialogueFiles = ('AV_monkey_short', 'AV_monkey_med', 'AV_monkey_long', 'AV_monkey_question', 'AV_monkey_exclaim', 'AV_monkey_howl') global MonkeyDialogueArray for file in monkeyDialogueFiles: MonkeyDialogueArray.append(base.loadSfx(loadPath + file + '.ogg')) bearDialogueFiles = ('AV_bear_short', 'AV_bear_med', 'AV_bear_long', 'AV_bear_question', 'AV_bear_exclaim', 'AV_bear_howl') global BearDialogueArray for file in bearDialogueFiles: BearDialogueArray.append(base.loadSfx(loadPath + file + '.ogg')) pigDialogueFiles = ('AV_pig_short', 'AV_pig_med', 'AV_pig_long', 'AV_pig_question', 'AV_pig_exclaim', 'AV_pig_howl') global PigDialogueArray for file in pigDialogueFiles: PigDialogueArray.append(base.loadSfx(loadPath + file + '.ogg')) def unloadDialog(): global CatDialogueArray global PigDialogueArray global BearDialogueArray global DuckDialogueArray global RabbitDialogueArray global MouseDialogueArray global DogDialogueArray global HorseDialogueArray global MonkeyDialogueArray DogDialogueArray = [] CatDialogueArray = [] HorseDialogueArray = [] RabbitDialogueArray = [] MouseDialogueArray = [] DuckDialogueArray = [] MonkeyDialogueArray = [] BearDialogueArray = [] PigDialogueArray = [] def reconsiderAllToonsUnderstandable(): for av in Avatar.Avatar.ActiveAvatars: if isinstance(av, Toon): av.considerUnderstandable() class Toon(Avatar.Avatar, ToonHead): notify = DirectNotifyGlobal.directNotify.newCategory('Toon') afkTimeout = base.config.GetInt('afk-timeout', 600) def __init__(self): try: self.Toon_initialized return except: self.Toon_initialized = 1 Avatar.Avatar.__init__(self) ToonHead.__init__(self) self.forwardSpeed = 0.0 self.rotateSpeed = 0.0 self.avatarType = 'toon' self.motion = Motion.Motion(self) self.standWalkRunReverse = None self.playingAnim = None self.soundTeleport = None self.cheesyEffect = ToontownGlobals.CENormal self.effectTrack = None self.emoteTrack = None self.emote = None self.stunTrack = None self.__bookActors = [] self.__holeActors = [] self.holeClipPath = None self.wake = None self.lastWakeTime = 0 self.forceJumpIdle = False self.numPies = 0 self.pieType = 0 self.pieThrowType = ToontownGlobals.PieThrowArc self.pieModel = None self.__pieModelType = None self.pieScale = 1.0 self.hatNodes = [] self.glassesNodes = [] self.backpackNodes = [] self.hat = (0, 0, 0) self.glasses = (0, 0, 0) self.backpack = (0, 0, 0) self.shoes = (0, 0, 0) self.isStunned = 0 self.isDisguised = 0 self.defaultColorScale = None self.jar = None self.headMeter = None self.gmIcon = None self.partyHat = None self.setTag('pieCode', str(ToontownGlobals.PieCodeToon)) self.setFont(ToontownGlobals.getToonFont()) self.setSpeechFont(ToontownGlobals.getToonFont()) self.soundChatBubble = base.loadSfx('phase_3/audio/sfx/GUI_balloon_popup.ogg') self.swimRunSfx = base.loadSfx('phase_4/audio/sfx/AV_footstep_runloop_water.ogg') self.swimRunLooping = False self.animFSM = ClassicFSM('Toon', [State('off', self.enterOff, self.exitOff), State('neutral', self.enterNeutral, self.exitNeutral), State('victory', self.enterVictory, self.exitVictory), State('Happy', self.enterHappy, self.exitHappy), State('Sad', self.enterSad, self.exitSad), State('Catching', self.enterCatching, self.exitCatching), State('CatchEating', self.enterCatchEating, self.exitCatchEating), State('Sleep', self.enterSleep, self.exitSleep), State('walk', self.enterWalk, self.exitWalk), State('jumpSquat', self.enterJumpSquat, self.exitJumpSquat), State('jump', self.enterJump, self.exitJump), State('jumpAirborne', self.enterJumpAirborne, self.exitJumpAirborne), State('jumpLand', self.enterJumpLand, self.exitJumpLand), State('run', self.enterRun, self.exitRun), State('swim', self.enterSwim, self.exitSwim), State('swimhold', self.enterSwimHold, self.exitSwimHold), State('dive', self.enterDive, self.exitDive), State('cringe', self.enterCringe, self.exitCringe), State('OpenBook', self.enterOpenBook, self.exitOpenBook, ['ReadBook', 'CloseBook']), State('ReadBook', self.enterReadBook, self.exitReadBook), State('CloseBook', self.enterCloseBook, self.exitCloseBook), State('TeleportOut', self.enterTeleportOut, self.exitTeleportOut), State('Died', self.enterDied, self.exitDied), State('TeleportedOut', self.enterTeleportedOut, self.exitTeleportedOut), State('TeleportIn', self.enterTeleportIn, self.exitTeleportIn), State('Emote', self.enterEmote, self.exitEmote), State('SitStart', self.enterSitStart, self.exitSitStart), State('Sit', self.enterSit, self.exitSit), State('Push', self.enterPush, self.exitPush), State('Squish', self.enterSquish, self.exitSquish), State('FallDown', self.enterFallDown, self.exitFallDown), State('GolfPuttLoop', self.enterGolfPuttLoop, self.exitGolfPuttLoop), State('GolfRotateLeft', self.enterGolfRotateLeft, self.exitGolfRotateLeft), State('GolfRotateRight', self.enterGolfRotateRight, self.exitGolfRotateRight), State('GolfPuttSwing', self.enterGolfPuttSwing, self.exitGolfPuttSwing), State('GolfGoodPutt', self.enterGolfGoodPutt, self.exitGolfGoodPutt), State('GolfBadPutt', self.enterGolfBadPutt, self.exitGolfBadPutt), State('Flattened', self.enterFlattened, self.exitFlattened), State('CogThiefRunning', self.enterCogThiefRunning, self.exitCogThiefRunning), State('ScientistJealous', self.enterScientistJealous, self.exitScientistJealous), State('ScientistEmcee', self.enterScientistEmcee, self.exitScientistEmcee), State('ScientistWork', self.enterScientistWork, self.exitScientistWork), State('ScientistLessWork', self.enterScientistLessWork, self.exitScientistLessWork), State('ScientistPlay', self.enterScientistPlay, self.enterScientistPlay)], 'off', 'off') animStateList = self.animFSM.getStates() self.animFSM.enterInitialState() def stopAnimations(self): if hasattr(self, 'animFSM'): if not self.animFSM.isInternalStateInFlux(): self.animFSM.request('off') else: self.notify.warning('animFSM in flux, state=%s, not requesting off' % self.animFSM.getCurrentState().getName()) else: self.notify.warning('animFSM has been deleted') if self.effectTrack != None: self.effectTrack.finish() self.effectTrack = None if self.emoteTrack != None: self.emoteTrack.finish() self.emoteTrack = None if self.stunTrack != None: self.stunTrack.finish() self.stunTrack = None if self.wake: self.wake.stop() self.wake.destroy() self.wake = None self.cleanupPieModel() return def delete(self): try: self.Toon_deleted except: self.Toon_deleted = 1 self.stopAnimations() self.rightHands = None self.rightHand = None self.leftHands = None self.leftHand = None self.headParts = None self.torsoParts = None self.hipsParts = None self.legsParts = None del self.animFSM for bookActor in self.__bookActors: bookActor.cleanup() del self.__bookActors for holeActor in self.__holeActors: holeActor.cleanup() del self.__holeActors self.soundTeleport = None self.motion.delete() self.motion = None self.removeHeadMeter() self.removeGMIcon() self.removePartyHat() Avatar.Avatar.delete(self) ToonHead.delete(self) def updateToonDNA(self, newDNA, fForce = 0): self.style.gender = newDNA.getGender() oldDNA = self.style if fForce or newDNA.head != oldDNA.head or newDNA.laughingMan != oldDNA.laughingMan: self.swapToonHead(newDNA.head, newDNA.laughingMan) if fForce or newDNA.torso != oldDNA.torso: self.swapToonTorso(newDNA.torso, genClothes=0) self.loop('neutral') if fForce or newDNA.legs != oldDNA.legs: self.swapToonLegs(newDNA.legs) self.swapToonColor(newDNA) self.__swapToonClothes(newDNA) def setDNAString(self, dnaString): newDNA = ToonDNA.ToonDNA() newDNA.makeFromNetString(dnaString) if len(newDNA.torso) < 2: self.sendLogSuspiciousEvent('nakedToonDNA %s was requested' % newDNA.torso) newDNA.torso = newDNA.torso + 's' self.setDNA(newDNA) def setDNA(self, dna): if hasattr(self, 'isDisguised'): if self.isDisguised: return if self.style: self.updateToonDNA(dna) else: self.style = dna self.generateToon() self.initializeDropShadow() self.initializeNametag3d() def parentToonParts(self): if self.hasLOD(): for lodName in self.getLODNames(): if base.config.GetBool('want-new-anims', 1): if not self.getPart('torso', lodName).find('**/def_head').isEmpty(): self.attach('head', 'torso', 'def_head', lodName) else: self.attach('head', 'torso', 'joint_head', lodName) else: self.attach('head', 'torso', 'joint_head', lodName) self.attach('torso', 'legs', 'joint_hips', lodName) else: self.attach('head', 'torso', 'joint_head') self.attach('torso', 'legs', 'joint_hips') def unparentToonParts(self): if self.hasLOD(): for lodName in self.getLODNames(): self.getPart('head', lodName).reparentTo(self.getLOD(lodName)) self.getPart('torso', lodName).reparentTo(self.getLOD(lodName)) self.getPart('legs', lodName).reparentTo(self.getLOD(lodName)) else: self.getPart('head').reparentTo(self.getGeomNode()) self.getPart('torso').reparentTo(self.getGeomNode()) self.getPart('legs').reparentTo(self.getGeomNode()) def setLODs(self): self.setLODNode() levelOneIn = base.config.GetInt('lod1-in', 20) levelOneOut = base.config.GetInt('lod1-out', 0) levelTwoIn = base.config.GetInt('lod2-in', 80) levelTwoOut = base.config.GetInt('lod2-out', 20) levelThreeIn = base.config.GetInt('lod3-in', 280) levelThreeOut = base.config.GetInt('lod3-out', 80) self.addLOD(1000, levelOneIn, levelOneOut) self.addLOD(500, levelTwoIn, levelTwoOut) self.addLOD(250, levelThreeIn, levelThreeOut) def generateToon(self): self.setLODs() self.generateToonLegs() self.generateToonHead() self.generateToonTorso() self.generateToonColor() self.parentToonParts() self.rescaleToon() self.resetHeight() self.setupToonNodes() self.generateLaughingMan() def setupToonNodes(self): rightHand = NodePath('rightHand') self.rightHand = None self.rightHands = [] leftHand = NodePath('leftHand') self.leftHands = [] self.leftHand = None for lodName in self.getLODNames(): hand = self.getPart('torso', lodName).find('**/joint_Rhold') if base.config.GetBool('want-new-anims', 1): if not self.getPart('torso', lodName).find('**/def_joint_right_hold').isEmpty(): hand = self.getPart('torso', lodName).find('**/def_joint_right_hold') else: hand = self.getPart('torso', lodName).find('**/joint_Rhold') self.rightHands.append(hand) rightHand = rightHand.instanceTo(hand) if base.config.GetBool('want-new-anims', 1): if not self.getPart('torso', lodName).find('**/def_joint_left_hold').isEmpty(): hand = self.getPart('torso', lodName).find('**/def_joint_left_hold') else: hand = self.getPart('torso', lodName).find('**/joint_Lhold') self.leftHands.append(hand) leftHand = leftHand.instanceTo(hand) if self.rightHand == None: self.rightHand = rightHand if self.leftHand == None: self.leftHand = leftHand self.headParts = self.findAllMatches('**/__Actor_head') self.legsParts = self.findAllMatches('**/__Actor_legs') self.hipsParts = self.legsParts.findAllMatches('**/joint_hips') self.torsoParts = self.hipsParts.findAllMatches('**/__Actor_torso') return def initializeBodyCollisions(self, collIdStr): Avatar.Avatar.initializeBodyCollisions(self, collIdStr) if not self.ghostMode: self.collNode.setCollideMask(self.collNode.getIntoCollideMask() | ToontownGlobals.PieBitmask) def getBookActors(self): if self.__bookActors: return self.__bookActors bookActor = Actor.Actor('phase_3.5/models/props/book-mod', {'book': 'phase_3.5/models/props/book-chan'}) bookActor2 = Actor.Actor(other=bookActor) bookActor3 = Actor.Actor(other=bookActor) self.__bookActors = [bookActor, bookActor2, bookActor3] hands = self.getRightHands() for bookActor, hand in zip(self.__bookActors, hands): bookActor.reparentTo(hand) bookActor.hide() return self.__bookActors def getHoleActors(self): if self.__holeActors: return self.__holeActors holeActor = Actor.Actor('phase_3.5/models/props/portal-mod', {'hole': 'phase_3.5/models/props/portal-chan'}) holeActor2 = Actor.Actor(other=holeActor) holeActor3 = Actor.Actor(other=holeActor) self.__holeActors = [holeActor, holeActor2, holeActor3] for ha in self.__holeActors: if hasattr(self, 'uniqueName'): holeName = self.uniqueName('toon-portal') else: holeName = 'toon-portal' ha.setName(holeName) return self.__holeActors def rescaleToon(self): animalStyle = self.style.getAnimal() bodyScale = ToontownGlobals.toonBodyScales[animalStyle] headScale = ToontownGlobals.toonHeadScales[animalStyle] self.setAvatarScale(bodyScale) for lod in self.getLODNames(): self.getPart('head', lod).setScale(headScale) def getBodyScale(self): animalStyle = self.style.getAnimal() bodyScale = ToontownGlobals.toonBodyScales[animalStyle] return bodyScale def resetHeight(self): if hasattr(self, 'style') and self.style: animal = self.style.getAnimal() bodyScale = ToontownGlobals.toonBodyScales[animal] headScale = ToontownGlobals.toonHeadScales[animal][2] shoulderHeight = ToontownGlobals.legHeightDict[self.style.legs] * bodyScale + ToontownGlobals.torsoHeightDict[self.style.torso] * bodyScale height = shoulderHeight + ToontownGlobals.headHeightDict[self.style.head] * headScale self.shoulderHeight = shoulderHeight if self.cheesyEffect == ToontownGlobals.CEBigToon or self.cheesyEffect == ToontownGlobals.CEBigWhite: height *= ToontownGlobals.BigToonScale elif self.cheesyEffect == ToontownGlobals.CESmallToon: height *= ToontownGlobals.SmallToonScale self.setHeight(height) def generateToonLegs(self, copy = 1): global Preloaded legStyle = self.style.legs filePrefix = LegDict.get(legStyle) if filePrefix is None: self.notify.error('unknown leg style: %s' % legStyle) self.loadModel(Preloaded[filePrefix+'-1000'], 'legs', '1000', True) self.loadModel(Preloaded[filePrefix+'-500'], 'legs', '500', True) self.loadModel(Preloaded[filePrefix+'-250'], 'legs', '250', True) if not copy: self.showPart('legs', '1000') self.showPart('legs', '500') self.showPart('legs', '250') self.loadAnims(LegsAnimDict[legStyle], 'legs', '1000') self.loadAnims(LegsAnimDict[legStyle], 'legs', '500') self.loadAnims(LegsAnimDict[legStyle], 'legs', '250') self.findAllMatches('**/boots_short').stash() self.findAllMatches('**/boots_long').stash() self.findAllMatches('**/shoes').stash() return def swapToonLegs(self, legStyle, copy = 1): self.unparentToonParts() self.removePart('legs', '1000') self.removePart('legs', '500') self.removePart('legs', '250') # Bugfix: Until upstream Panda3D includes this, we have to do it here. if 'legs' in self._Actor__commonBundleHandles: del self._Actor__commonBundleHandles['legs'] self.style.legs = legStyle self.generateToonLegs(copy) self.generateToonColor() self.parentToonParts() self.rescaleToon() self.resetHeight() del self.shadowJoint self.initializeDropShadow() self.initializeNametag3d() def generateToonTorso(self, copy = 1, genClothes = 1): global Preloaded torsoStyle = self.style.torso filePrefix = TorsoDict.get(torsoStyle) if filePrefix is None: self.notify.error('unknown torso style: %s' % torsoStyle) self.loadModel(Preloaded[filePrefix+'-1000'], 'torso', '1000', True) if len(torsoStyle) == 1: self.loadModel(Preloaded[filePrefix+'-1000'], 'torso', '500', True) self.loadModel(Preloaded[filePrefix+'-1000'], 'torso', '250', True) else: self.loadModel(Preloaded[filePrefix+'-500'], 'torso', '500', True) self.loadModel(Preloaded[filePrefix+'-250'], 'torso', '250', True) if not copy: self.showPart('torso', '1000') self.showPart('torso', '500') self.showPart('torso', '250') self.loadAnims(TorsoAnimDict[torsoStyle], 'torso', '1000') self.loadAnims(TorsoAnimDict[torsoStyle], 'torso', '500') self.loadAnims(TorsoAnimDict[torsoStyle], 'torso', '250') if genClothes == 1 and not len(torsoStyle) == 1: self.generateToonClothes() return def swapToonTorso(self, torsoStyle, copy = 1, genClothes = 1): self.unparentToonParts() self.removePart('torso', '1000') self.removePart('torso', '500') self.removePart('torso', '250') # Bugfix: Until upstream Panda3D includes this, we have to do it here. if 'torso' in self._Actor__commonBundleHandles: del self._Actor__commonBundleHandles['torso'] self.style.torso = torsoStyle self.generateToonTorso(copy, genClothes) self.generateToonColor() self.parentToonParts() self.rescaleToon() self.resetHeight() self.setupToonNodes() self.generateBackpack() def generateToonHead(self, copy = 1): headHeight = ToonHead.generateToonHead(self, copy, self.style, ('1000', '500', '250')) if self.style.getAnimal() == 'dog': self.loadAnims(HeadAnimDict[self.style.head], 'head', '1000') self.loadAnims(HeadAnimDict[self.style.head], 'head', '500') self.loadAnims(HeadAnimDict[self.style.head], 'head', '250') def swapToonHead(self, headStyle=-1, laughingMan=-1, copy = 1): self.stopLookAroundNow() self.eyelids.request('open') self.unparentToonParts() self.removePart('head', '1000') self.removePart('head', '500') self.removePart('head', '250') # Bugfix: Until upstream Panda3D includes this, we have to do it here. if 'head' in self._Actor__commonBundleHandles: del self._Actor__commonBundleHandles['head'] if headStyle > -1: self.style.head = headStyle laughingMan = laughingMan or self.style.laughingMan or self.getWantLaughingManHoliday() self.generateToonHead(copy) self.generateToonColor() self.parentToonParts() self.rescaleToon() self.resetHeight() self.eyelids.request('open') self.startLookAround() if laughingMan: LaughingManGlobals.addToonEffect(self) def generateToonColor(self): ToonHead.generateToonColor(self, self.style) armColor = self.style.getArmColor() gloveColor = self.style.getGloveColor() legColor = self.style.getLegColor() for lodName in self.getLODNames(): torso = self.getPart('torso', lodName) if len(self.style.torso) == 1: parts = torso.findAllMatches('**/torso*') parts.setColor(armColor) for pieceName in ('arms', 'neck'): piece = torso.find('**/' + pieceName) piece.setColor(armColor) hands = torso.find('**/hands') hands.setColor(gloveColor) legs = self.getPart('legs', lodName) for pieceName in ('legs', 'feet'): piece = legs.find('**/%s;+s' % pieceName) piece.setColor(legColor) if self.cheesyEffect == ToontownGlobals.CEGreenToon: self.reapplyCheesyEffect() def swapToonColor(self, dna): self.setStyle(dna) self.generateToonColor() def __swapToonClothes(self, dna): self.setStyle(dna) self.generateToonClothes(fromNet=1) def sendLogSuspiciousEvent(self, msg): pass def generateToonClothes(self, fromNet = 0): swappedTorso = 0 if self.hasLOD(): if self.style.getGender() == 'f' and fromNet == 0: try: bottomPair = ToonDNA.GirlBottoms[self.style.botTex] except: bottomPair = ToonDNA.GirlBottoms[0] if len(self.style.torso) < 2: self.sendLogSuspiciousEvent('nakedToonDNA %s was requested' % self.style.torso) return 0 elif self.style.torso[1] == 's' and bottomPair[1] == ToonDNA.SKIRT: self.swapToonTorso(self.style.torso[0] + 'd', genClothes=0) swappedTorso = 1 elif self.style.torso[1] == 'd' and bottomPair[1] == ToonDNA.SHORTS: self.swapToonTorso(self.style.torso[0] + 's', genClothes=0) swappedTorso = 1 try: texName = ToonDNA.Shirts[self.style.topTex] except: texName = ToonDNA.Shirts[0] shirtTex = loader.loadTexture(texName, okMissing=True) if shirtTex is None: self.sendLogSuspiciousEvent('failed to load texture %s' % texName) shirtTex = loader.loadTexture(ToonDNA.Shirts[0]) shirtTex.setMinfilter(Texture.FTLinearMipmapLinear) shirtTex.setMagfilter(Texture.FTLinear) try: shirtColor = ToonDNA.ClothesColors[self.style.topTexColor] except: shirtColor = ToonDNA.ClothesColors[0] try: texName = ToonDNA.Sleeves[self.style.sleeveTex] except: texName = ToonDNA.Sleeves[0] sleeveTex = loader.loadTexture(texName, okMissing=True) if sleeveTex is None: self.sendLogSuspiciousEvent('failed to load texture %s' % texName) sleeveTex = loader.loadTexture(ToonDNA.Sleeves[0]) sleeveTex.setMinfilter(Texture.FTLinearMipmapLinear) sleeveTex.setMagfilter(Texture.FTLinear) try: sleeveColor = ToonDNA.ClothesColors[self.style.sleeveTexColor] except: sleeveColor = ToonDNA.ClothesColors[0] if self.style.getGender() == 'm': try: texName = ToonDNA.BoyShorts[self.style.botTex] except: texName = ToonDNA.BoyShorts[0] else: try: texName = ToonDNA.GirlBottoms[self.style.botTex][0] except: texName = ToonDNA.GirlBottoms[0][0] bottomTex = loader.loadTexture(texName, okMissing=True) if bottomTex is None: self.sendLogSuspiciousEvent('failed to load texture %s' % texName) if self.style.getGender() == 'm': bottomTex = loader.loadTexture(ToonDNA.BoyShorts[0]) else: bottomTex = loader.loadTexture(ToonDNA.GirlBottoms[0][0]) bottomTex.setMinfilter(Texture.FTLinearMipmapLinear) bottomTex.setMagfilter(Texture.FTLinear) try: bottomColor = ToonDNA.ClothesColors[self.style.botTexColor] except: bottomColor = ToonDNA.ClothesColors[0] darkBottomColor = bottomColor * 0.5 darkBottomColor.setW(1.0) for lodName in self.getLODNames(): thisPart = self.getPart('torso', lodName) top = thisPart.find('**/torso-top') top.setTexture(shirtTex, 1) top.setColor(shirtColor) sleeves = thisPart.find('**/sleeves') sleeves.setTexture(sleeveTex, 1) sleeves.setColor(sleeveColor) bottoms = thisPart.findAllMatches('**/torso-bot') for bottomNum in xrange(0, bottoms.getNumPaths()): bottom = bottoms.getPath(bottomNum) bottom.setTexture(bottomTex, 1) bottom.setColor(bottomColor) caps = thisPart.findAllMatches('**/torso-bot-cap') caps.setColor(darkBottomColor) return swappedTorso def generateLaughingMan(self, force=False): if force or self.getWantLaughingMan(): self.swapToonHead(laughingMan=True) def generateHat(self, fromRTM = False): hat = self.getHat() if hat[0] >= len(ToonDNA.HatModels): self.sendLogSuspiciousEvent('tried to put a wrong hat idx %d' % hat[0]) return if len(self.hatNodes) > 0: for hatNode in self.hatNodes: hatNode.removeNode() self.hatNodes = [] self.showEars() if hat[0] != 0: hatGeom = loader.loadModel(ToonDNA.HatModels[hat[0]], okMissing=True) if hatGeom: if hat[0] == 54: self.hideEars() if hat[1] != 0: texName = ToonDNA.HatTextures[hat[1]] tex = loader.loadTexture(texName, okMissing=True) if tex is None: self.sendLogSuspiciousEvent('failed to load texture %s' % texName) else: tex.setMinfilter(Texture.FTLinearMipmapLinear) tex.setMagfilter(Texture.FTLinear) hatGeom.setTexture(tex, 1) if fromRTM: reload(AccessoryGlobals) transOffset = None if AccessoryGlobals.ExtendedHatTransTable.get(hat[0]): transOffset = AccessoryGlobals.ExtendedHatTransTable[hat[0]].get(self.style.head[:2]) if transOffset is None: transOffset = AccessoryGlobals.HatTransTable.get(self.style.head[:2]) if transOffset is None: return hatGeom.setPos(transOffset[0][0], transOffset[0][1], transOffset[0][2]) hatGeom.setHpr(transOffset[1][0], transOffset[1][1], transOffset[1][2]) hatGeom.setScale(transOffset[2][0], transOffset[2][1], transOffset[2][2]) headNodes = self.findAllMatches('**/__Actor_head') for headNode in headNodes: hatNode = headNode.attachNewNode('hatNode') self.hatNodes.append(hatNode) hatGeom.instanceTo(hatNode) return def generateGlasses(self, fromRTM = False): glasses = self.getGlasses() if glasses[0] >= len(ToonDNA.GlassesModels): self.sendLogSuspiciousEvent('tried to put a wrong glasses idx %d' % glasses[0]) return if len(self.glassesNodes) > 0: for glassesNode in self.glassesNodes: glassesNode.removeNode() self.glassesNodes = [] self.showEyelashes() if glasses[0] != 0: glassesGeom = loader.loadModel(ToonDNA.GlassesModels[glasses[0]], okMissing=True) if glassesGeom: if glasses[0] in [15, 16]: self.hideEyelashes() if glasses[1] != 0: texName = ToonDNA.GlassesTextures[glasses[1]] tex = loader.loadTexture(texName, okMissing=True) if tex is None: self.sendLogSuspiciousEvent('failed to load texture %s' % texName) else: tex.setMinfilter(Texture.FTLinearMipmapLinear) tex.setMagfilter(Texture.FTLinear) glassesGeom.setTexture(tex, 1) if fromRTM: reload(AccessoryGlobals) transOffset = None if AccessoryGlobals.ExtendedGlassesTransTable.get(glasses[0]): transOffset = AccessoryGlobals.ExtendedGlassesTransTable[glasses[0]].get(self.style.head[:2]) if transOffset is None: transOffset = AccessoryGlobals.GlassesTransTable.get(self.style.head[:2]) if transOffset is None: return glassesGeom.setPos(transOffset[0][0], transOffset[0][1], transOffset[0][2]) glassesGeom.setHpr(transOffset[1][0], transOffset[1][1], transOffset[1][2]) glassesGeom.setScale(transOffset[2][0], transOffset[2][1], transOffset[2][2]) headNodes = self.findAllMatches('**/__Actor_head') for headNode in headNodes: glassesNode = headNode.attachNewNode('glassesNode') self.glassesNodes.append(glassesNode) glassesGeom.instanceTo(glassesNode) return def generateBackpack(self, fromRTM = False): backpack = self.getBackpack() if backpack[0] >= len(ToonDNA.BackpackModels): self.sendLogSuspiciousEvent('tried to put a wrong backpack idx %d' % backpack[0]) return if len(self.backpackNodes) > 0: for backpackNode in self.backpackNodes: backpackNode.removeNode() self.backpackNodes = [] if backpack[0] != 0: geom = loader.loadModel(ToonDNA.BackpackModels[backpack[0]], okMissing=True) if geom: if backpack[1] != 0: texName = ToonDNA.BackpackTextures[backpack[1]] tex = loader.loadTexture(texName, okMissing=True) if tex is None: self.sendLogSuspiciousEvent('failed to load texture %s' % texName) else: tex.setMinfilter(Texture.FTLinearMipmapLinear) tex.setMagfilter(Texture.FTLinear) geom.setTexture(tex, 1) if fromRTM: reload(AccessoryGlobals) transOffset = None if AccessoryGlobals.ExtendedBackpackTransTable.get(backpack[0]): transOffset = AccessoryGlobals.ExtendedBackpackTransTable[backpack[0]].get(self.style.torso[:1]) if transOffset is None: transOffset = AccessoryGlobals.BackpackTransTable.get(self.style.torso[:1]) if transOffset is None: return geom.setPos(transOffset[0][0], transOffset[0][1], transOffset[0][2]) geom.setHpr(transOffset[1][0], transOffset[1][1], transOffset[1][2]) geom.setScale(transOffset[2][0], transOffset[2][1], transOffset[2][2]) nodes = self.findAllMatches('**/def_joint_attachFlower') for node in nodes: theNode = node.attachNewNode('backpackNode') self.backpackNodes.append(theNode) geom.instanceTo(theNode) return def generateShoes(self): shoes = self.getShoes() if shoes[0] >= len(ToonDNA.ShoesModels): self.sendLogSuspiciousEvent('tried to put a wrong shoes idx %d' % shoes[0]) return self.findAllMatches('**/feet;+s').stash() self.findAllMatches('**/boots_short;+s').stash() self.findAllMatches('**/boots_long;+s').stash() self.findAllMatches('**/shoes;+s').stash() geoms = self.findAllMatches('**/%s;+s' % ToonDNA.ShoesModels[shoes[0]]) for geom in geoms: geom.unstash() if shoes[0] != 0: for geom in geoms: texName = ToonDNA.ShoesTextures[shoes[1]] if self.style.legs == 'l' and shoes[0] == 3: texName = texName[:-4] + 'LL.jpg' tex = loader.loadTexture(texName, okMissing=True) if tex is None: self.sendLogSuspiciousEvent('failed to load texture %s' % texName) else: tex.setMinfilter(Texture.FTLinearMipmapLinear) tex.setMagfilter(Texture.FTLinear) geom.setTexture(tex, 1) return def generateToonAccessories(self): self.generateHat() self.generateGlasses() self.generateBackpack() self.generateShoes() def setHat(self, hatIdx, textureIdx, colorIdx, fromRTM = False): self.hat = (hatIdx, textureIdx, colorIdx) self.generateHat(fromRTM=fromRTM) def getHat(self): return self.hat def getWantLaughingMan(self): return self.style.laughingMan or self.getWantLaughingManHoliday() def getWantLaughingManHoliday(self): return base.cr.newsManager and base.cr.newsManager.isHolidayRunning(ToontownGlobals.LAUGHING_MAN) def setGlasses(self, glassesIdx, textureIdx, colorIdx, fromRTM = False): self.glasses = (glassesIdx, textureIdx, colorIdx) self.generateGlasses(fromRTM=fromRTM) def getGlasses(self): return self.glasses def setBackpack(self, backpackIdx, textureIdx, colorIdx, fromRTM = False): self.backpack = (backpackIdx, textureIdx, colorIdx) self.generateBackpack(fromRTM=fromRTM) def getBackpack(self): return self.backpack def setShoes(self, shoesIdx, textureIdx, colorIdx): self.shoes = (shoesIdx, textureIdx, colorIdx) self.generateShoes() def getShoes(self): return self.shoes def getDialogueArray(self): if base.cr.newsManager.isHolidayRunning(ToontownGlobals.APRIL_TOONS_WEEK): animalType = random.choice(TTLocalizer.AnimalToSpecies.keys()) else: animalType = self.style.getType() if animalType == 'dog': dialogueArray = DogDialogueArray elif animalType == 'cat': dialogueArray = CatDialogueArray elif animalType == 'horse': dialogueArray = HorseDialogueArray elif animalType == 'mouse': dialogueArray = MouseDialogueArray elif animalType == 'rabbit': dialogueArray = RabbitDialogueArray elif animalType == 'duck': dialogueArray = DuckDialogueArray elif animalType == 'monkey': dialogueArray = MonkeyDialogueArray elif animalType == 'bear': dialogueArray = BearDialogueArray elif animalType == 'pig': dialogueArray = PigDialogueArray else: dialogueArray = None return dialogueArray def getShadowJoint(self): if hasattr(self, 'shadowJoint'): return self.shadowJoint shadowJoint = NodePath('shadowJoint') for lodName in self.getLODNames(): joint = self.getPart('legs', lodName).find('**/joint_shadow') shadowJoint = shadowJoint.instanceTo(joint) self.shadowJoint = shadowJoint return shadowJoint def getNametagJoints(self): joints = [] for lodName in self.getLODNames(): bundle = self.getPartBundle('legs', lodName) joint = bundle.findChild('joint_nameTag') if joint: joints.append(joint) return joints def getRightHands(self): return self.rightHands def getLeftHands(self): return self.leftHands def getHeadParts(self): return self.headParts def getHipsParts(self): return self.hipsParts def getTorsoParts(self): return self.torsoParts def getLegsParts(self): return self.legsParts def findSomethingToLookAt(self): if self.randGen.random() < 0.1 or not hasattr(self, 'cr'): x = self.randGen.choice((-0.8, -0.5, 0, 0.5, 0.8)) y = self.randGen.choice((-0.5, 0, 0.5, 0.8)) self.lerpLookAt(Point3(x, 1.5, y), blink=1) return nodePathList = [] for id, obj in self.cr.doId2do.items(): if hasattr(obj, 'getStareAtNodeAndOffset') and obj != self: node, offset = obj.getStareAtNodeAndOffset() if node.getY(self) > 0.0: nodePathList.append((node, offset)) if nodePathList: nodePathList.sort(lambda x, y: cmp(x[0].getDistance(self), y[0].getDistance(self))) if len(nodePathList) >= 2: if self.randGen.random() < 0.9: chosenNodePath = nodePathList[0] else: chosenNodePath = nodePathList[1] else: chosenNodePath = nodePathList[0] self.lerpLookAt(chosenNodePath[0].getPos(self), blink=1) else: ToonHead.findSomethingToLookAt(self) def setForceJumpIdle(self, value): self.forceJumpIdle = value def setupPickTrigger(self): Avatar.Avatar.setupPickTrigger(self) torso = self.getPart('torso', '1000') if torso == None: return 0 self.pickTriggerNp.reparentTo(torso) size = self.style.getTorsoSize() if size == 'short': self.pickTriggerNp.setPosHprScale(0, 0, 0.5, 0, 0, 0, 1.5, 1.5, 2) elif size == 'medium': self.pickTriggerNp.setPosHprScale(0, 0, 0.5, 0, 0, 0, 1, 1, 2) else: self.pickTriggerNp.setPosHprScale(0, 0, 1, 0, 0, 0, 1, 1, 2) return 1 def showBooks(self): for bookActor in self.getBookActors(): bookActor.show() def hideBooks(self): for bookActor in self.getBookActors(): bookActor.hide() def getWake(self): if not self.wake: self.wake = Wake.Wake(render, self) return self.wake def getJar(self): if not self.jar: self.jar = loader.loadModel('phase_5.5/models/estate/jellybeanJar') self.jar.setP(290.0) self.jar.setY(0.5) self.jar.setZ(0.5) self.jar.setScale(0.0) return self.jar def removeJar(self): if self.jar: self.jar.removeNode() self.jar = None return def setSpeed(self, forwardSpeed, rotateSpeed): self.forwardSpeed = forwardSpeed self.rotateSpeed = rotateSpeed action = None if self.standWalkRunReverse != None: if forwardSpeed >= ToontownGlobals.RunCutOff: action = OTPGlobals.RUN_INDEX elif forwardSpeed > ToontownGlobals.WalkCutOff: action = OTPGlobals.WALK_INDEX elif forwardSpeed < -ToontownGlobals.WalkCutOff: action = OTPGlobals.REVERSE_INDEX elif rotateSpeed != 0.0: action = OTPGlobals.WALK_INDEX else: action = OTPGlobals.STAND_INDEX anim, rate = self.standWalkRunReverse[action] self.motion.enter() self.motion.setState(anim, rate) if anim != self.playingAnim: self.playingAnim = anim self.playingRate = rate self.stop() self.loop(anim) self.setPlayRate(rate, anim) if self.isDisguised: rightHand = self.suit.rightHand numChildren = rightHand.getNumChildren() if numChildren > 0: anim = 'tray-' + anim if anim == 'tray-run': anim = 'tray-walk' self.suit.stop() self.suit.loop(anim) self.suit.setPlayRate(rate, anim) elif rate != self.playingRate: self.playingRate = rate if not self.isDisguised: self.setPlayRate(rate, anim) else: self.suit.setPlayRate(rate, anim) showWake, wakeWaterHeight = ZoneUtil.getWakeInfo() if showWake and self.getZ(render) < wakeWaterHeight and abs(forwardSpeed) > ToontownGlobals.WalkCutOff: currT = globalClock.getFrameTime() deltaT = currT - self.lastWakeTime if action == OTPGlobals.RUN_INDEX and deltaT > ToontownGlobals.WakeRunDelta or deltaT > ToontownGlobals.WakeWalkDelta: self.getWake().createRipple(wakeWaterHeight, rate=1, startFrame=4) if not self.swimRunLooping: base.playSfx(self.swimRunSfx, node=self, looping=1) self.lastWakeTime = currT self.swimRunLooping = True else: self.stopSwimRunSfx() return action def stopSwimRunSfx(self): if self.swimRunLooping: self.swimRunSfx.stop() self.swimRunLooping = False def enterOff(self, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): self.setActiveShadow(0) self.playingAnim = None return def exitOff(self): pass def enterNeutral(self, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): anim = 'neutral' self.pose(anim, int(self.getNumFrames(anim) * self.randGen.random())) self.loop(anim, restart=0) self.setPlayRate(animMultiplier, anim) self.playingAnim = anim self.setActiveShadow(1) def exitNeutral(self): self.stop() def enterVictory(self, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): anim = 'victory' frame = int(ts * self.getFrameRate(anim) * animMultiplier) self.pose(anim, frame) self.loop('victory', restart=0) self.setPlayRate(animMultiplier, 'victory') self.playingAnim = anim self.setActiveShadow(0) def exitVictory(self): self.stop() def enterHappy(self, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): self.playingAnim = None self.playingRate = None self.standWalkRunReverse = (('neutral', 1.0), ('walk', 1.0), ('run', 1.0), ('walk', -1.0)) self.setSpeed(self.forwardSpeed, self.rotateSpeed) self.setActiveShadow(1) return def exitHappy(self): self.standWalkRunReverse = None self.stop() self.motion.exit() return def enterSad(self, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): self.playingAnim = 'sad' self.playingRate = None self.standWalkRunReverse = (('sad-neutral', 1.0), ('sad-walk', 1.2), ('sad-walk', 1.2), ('sad-walk', -1.0)) self.setSpeed(0, 0) Emote.globalEmote.disableBody(self, 'toon, enterSad') self.setActiveShadow(1) if self.isLocal(): self.controlManager.disableAvatarJump() return def exitSad(self): self.standWalkRunReverse = None self.stop() self.motion.exit() Emote.globalEmote.releaseBody(self, 'toon, exitSad') if self.isLocal(): self.controlManager.enableAvatarJump() return def enterCatching(self, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): self.playingAnim = None self.playingRate = None self.standWalkRunReverse = (('catch-neutral', 1.0), ('catch-run', 1.0), ('catch-run', 1.0), ('catch-run', -1.0)) self.setSpeed(self.forwardSpeed, self.rotateSpeed) self.setActiveShadow(1) return def exitCatching(self): self.standWalkRunReverse = None self.stop() self.motion.exit() return def enterCatchEating(self, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): self.playingAnim = None self.playingRate = None self.standWalkRunReverse = (('catch-eatneutral', 1.0), ('catch-eatnrun', 1.0), ('catch-eatnrun', 1.0), ('catch-eatnrun', -1.0)) self.setSpeed(self.forwardSpeed, self.rotateSpeed) self.setActiveShadow(0) return def exitCatchEating(self): self.standWalkRunReverse = None self.stop() self.motion.exit() return def enterWalk(self, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): self.loop('walk') self.setPlayRate(animMultiplier, 'walk') self.setActiveShadow(1) def exitWalk(self): self.stop() def getJumpDuration(self): if self.playingAnim == 'neutral': return self.getDuration('jump', 'legs') else: return self.getDuration('running-jump', 'legs') def enterJump(self, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): if not self.isDisguised: if self.playingAnim == 'neutral': anim = 'jump' else: anim = 'running-jump' self.playingAnim = anim self.setPlayRate(animMultiplier, anim) self.play(anim) self.setActiveShadow(1) def exitJump(self): self.stop() self.playingAnim = 'neutral' def enterJumpSquat(self, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): if not self.isDisguised: if self.playingAnim == 'neutral': anim = 'jump-squat' else: anim = 'running-jump-squat' self.playingAnim = anim self.setPlayRate(animMultiplier, anim) self.play(anim) self.setActiveShadow(1) def exitJumpSquat(self): self.stop() self.playingAnim = 'neutral' def enterJumpAirborne(self, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): if not self.isDisguised: if self.playingAnim == 'neutral' or self.forceJumpIdle: anim = 'jump-idle' else: anim = 'running-jump-idle' self.playingAnim = anim self.setPlayRate(animMultiplier, anim) self.loop(anim) self.setActiveShadow(1) def exitJumpAirborne(self): self.stop() self.playingAnim = 'neutral' def enterJumpLand(self, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): if not self.isDisguised: if self.playingAnim == 'running-jump-idle': anim = 'running-jump-land' skipStart = 0.2 else: anim = 'jump-land' skipStart = 0.0 self.playingAnim = anim self.setPlayRate(animMultiplier, anim) self.play(anim) self.setActiveShadow(1) def exitJumpLand(self): self.stop() self.playingAnim = 'neutral' def enterRun(self, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): self.loop('run') self.setPlayRate(animMultiplier, 'run') Emote.globalEmote.disableBody(self, 'toon, enterRun') self.setActiveShadow(1) def exitRun(self): self.stop() Emote.globalEmote.releaseBody(self, 'toon, exitRun') def enterSwim(self, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): self.stopSwimRunSfx() Emote.globalEmote.disableAll(self, 'enterSwim') self.playingAnim = 'swim' self.loop('swim') self.setPlayRate(animMultiplier, 'swim') self.getGeomNode().setP(-89.0) self.dropShadow.hide() if self.isLocal(): self.book.obscureButton(1) self.useSwimControls() self.nametag3d.setPos(0, -2, 1) self.startBobSwimTask() self.setActiveShadow(0) def enterCringe(self, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): self.loop('cringe') self.getGeomNode().setPos(0, 0, -2) self.setPlayRate(animMultiplier, 'swim') def exitCringe(self, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): self.stop() self.getGeomNode().setPos(0, 0, 0) self.playingAnim = 'neutral' self.setPlayRate(animMultiplier, 'swim') def enterDive(self, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): self.loop('swim') if hasattr(self.getGeomNode(), 'setPos'): self.getGeomNode().setPos(0, 0, -2) self.setPlayRate(animMultiplier, 'swim') self.setActiveShadow(0) self.dropShadow.hide() self.nametag3d.setPos(0, -2, 1) def exitDive(self): self.stop() self.getGeomNode().setPos(0, 0, 0) self.playingAnim = 'neutral' self.dropShadow.show() self.nametag3d.setPos(0, 0, self.height + 0.5) def enterSwimHold(self, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): self.getGeomNode().setPos(0, 0, -2) self.nametag3d.setPos(0, -2, 1) self.pose('swim', 55) def exitSwimHold(self): self.stop() self.getGeomNode().setPos(0, 0, 0) self.playingAnim = 'neutral' self.dropShadow.show() self.nametag3d.setPos(0, 0, self.height + 0.5) def exitSwim(self): self.stop() self.playingAnim = 'neutral' self.stopBobSwimTask() self.getGeomNode().setPosHpr(0, 0, 0, 0, 0, 0) self.dropShadow.show() if self.isLocal(): self.useWalkControls() self.book.obscureButton(False) self.nametag3d.setPos(0, 0, self.height + 0.5) Emote.globalEmote.releaseAll(self, 'exitSwim') def startBobSwimTask(self): if getattr(self, 'swimBob', None): self.swimBob.finish() self.swimBob = None self.nametag3d.setZ(5.0) geomNode = self.getGeomNode() geomNode.setZ(4.0) self.swimBob = Sequence( geomNode.posInterval(1, Point3(0, -3, 3), startPos=Point3(0, -3, 4), blendType='easeInOut'), geomNode.posInterval(1, Point3(0, -3, 4), startPos=Point3(0, -3, 3), blendType='easeInOut')) self.swimBob.loop() def stopBobSwimTask(self): swimBob = getattr(self, 'swimBob', None) if swimBob: swimBob.finish() self.getGeomNode().setPos(0, 0, 0) self.nametag3d.setZ(1.0) def enterOpenBook(self, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): Emote.globalEmote.disableAll(self, 'enterOpenBook') self.playingAnim = 'openBook' self.stopLookAround() self.lerpLookAt(Point3(0, 1, -2)) bookTracks = Parallel() for bookActor in self.getBookActors(): bookTracks.append(ActorInterval(bookActor, 'book', startTime=1.2, endTime=1.5)) bookTracks.append(ActorInterval(self, 'book', startTime=1.2, endTime=1.5)) if hasattr(self, 'uniqueName'): trackName = self.uniqueName('openBook') else: trackName = 'openBook' self.track = Sequence(Func(self.showBooks), bookTracks, Wait(0.1), name=trackName) if callback: self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getName(), callback, extraArgs) self.track.start(ts) self.setActiveShadow(0) def exitOpenBook(self): self.playingAnim = 'neutralob' if self.track != None: self.ignore(self.track.getName()) self.track.finish() DelayDelete.cleanupDelayDeletes(self.track) self.track = None self.hideBooks() self.startLookAround() Emote.globalEmote.releaseAll(self, 'exitOpenBook') return def enterReadBook(self, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): Emote.globalEmote.disableBody(self, 'enterReadBook') self.playingAnim = 'readBook' self.stopLookAround() self.lerpLookAt(Point3(0, 1, -2)) self.showBooks() for bookActor in self.getBookActors(): bookActor.pingpong('book', fromFrame=38, toFrame=118) self.pingpong('book', fromFrame=38, toFrame=118) self.setActiveShadow(0) def exitReadBook(self): self.playingAnim = 'neutralrb' self.hideBooks() for bookActor in self.getBookActors(): bookActor.stop() self.startLookAround() Emote.globalEmote.releaseBody(self, 'exitReadBook') def enterCloseBook(self, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): Emote.globalEmote.disableAll(self, 'enterCloseBook') self.playingAnim = 'closeBook' bookTracks = Parallel() for bookActor in self.getBookActors(): bookTracks.append(ActorInterval(bookActor, 'book', startTime=4.96, endTime=6.5)) bookTracks.append(ActorInterval(self, 'book', startTime=4.96, endTime=6.5)) if hasattr(self, 'uniqueName'): trackName = self.uniqueName('closeBook') else: trackName = 'closeBook' self.track = Sequence(Func(self.showBooks), bookTracks, Func(self.hideBooks), name=trackName) if callback: self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getName(), callback, extraArgs) self.track.start(ts) self.setActiveShadow(0) def exitCloseBook(self): self.playingAnim = 'neutralcb' if self.track != None: self.ignore(self.track.getName()) self.track.finish() DelayDelete.cleanupDelayDeletes(self.track) self.track = None Emote.globalEmote.releaseAll(self, 'exitCloseBook') return def getSoundTeleport(self): if not self.soundTeleport: self.soundTeleport = base.loadSfx('phase_3.5/audio/sfx/AV_teleport.ogg') return self.soundTeleport def getTeleportOutTrack(self, autoFinishTrack = 1): def showHoles(holes, hands): for hole, hand in zip(holes, hands): hole.reparentTo(hand) def reparentHoles(holes, toon): holes[0].reparentTo(toon) holes[1].detachNode() holes[2].detachNode() holes[0].setBin('shadow', 0) holes[0].setDepthTest(0) holes[0].setDepthWrite(0) def cleanupHoles(holes): holes[0].detachNode() holes[0].clearBin() holes[0].clearDepthTest() holes[0].clearDepthWrite() holes = self.getHoleActors() hands = self.getRightHands() holeTrack = Track((0.0, Func(showHoles, holes, hands)), (0.5, SoundInterval(self.getSoundTeleport(), node=self)), (1.708, Func(reparentHoles, holes, self)), (3.4, Func(cleanupHoles, holes))) if hasattr(self, 'uniqueName'): trackName = self.uniqueName('teleportOut') else: trackName = 'teleportOut' track = Parallel(holeTrack, name=trackName, autoFinish=autoFinishTrack) for hole in holes: track.append(ActorInterval(hole, 'hole', duration=3.4)) track.append(ActorInterval(self, 'teleport', duration=3.4)) return track def startQuestMap(self): pass def stopQuestMap(self): pass def enterTeleportOut(self, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): name = self.name if hasattr(self, 'doId'): name += '-' + str(self.doId) self.notify.debug('enterTeleportOut %s' % name) if self.ghostMode or self.isDisguised: if callback: callback(*extraArgs) return self.playingAnim = 'teleport' Emote.globalEmote.disableAll(self, 'enterTeleportOut') if self.isLocal(): autoFinishTrack = 0 else: autoFinishTrack = 1 self.track = self.getTeleportOutTrack(autoFinishTrack) self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getName(), self.finishTeleportOut, [callback, extraArgs]) holeClip = PlaneNode('holeClip') self.holeClipPath = self.attachNewNode(holeClip) self.getGeomNode().setClipPlane(self.holeClipPath) self.nametag3d.setClipPlane(self.holeClipPath) avHeight = max(self.getHeight(), 3) self.track.start(ts) self.setActiveShadow(0) def finishTeleportOut(self, callback = None, extraArgs = []): name = self.name if hasattr(self, 'doId'): name += '-' + str(self.doId) self.notify.debug('finishTeleportOut %s' % name) if self.track != None: self.ignore(self.track.getName()) self.track.finish() DelayDelete.cleanupDelayDeletes(self.track) self.track = None if hasattr(self, 'animFSM'): self.animFSM.request('TeleportedOut') if callback: callback(*extraArgs) return def exitTeleportOut(self): name = self.name if hasattr(self, 'doId'): name += '-' + str(self.doId) self.notify.debug('exitTeleportOut %s' % name) if self.track != None: self.ignore(self.track.getName()) self.track.finish() self.track = None geomNode = self.getGeomNode() if geomNode and not geomNode.isEmpty(): self.getGeomNode().clearClipPlane() if self.nametag3d and not self.nametag3d.isEmpty(): self.nametag3d.clearClipPlane() if self.holeClipPath: self.holeClipPath.removeNode() self.holeClipPath = None Emote.globalEmote.releaseAll(self, 'exitTeleportOut') if self and not self.isEmpty(): self.show() return def enterTeleportedOut(self, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): self.setActiveShadow(0) def exitTeleportedOut(self): pass def getDiedInterval(self, autoFinishTrack = 1): sound = loader.loadSfx('phase_5/audio/sfx/ENC_Lose.ogg') if hasattr(self, 'uniqueName'): trackName = self.uniqueName('died') else: trackName = 'died' ival = Sequence(Func(Emote.globalEmote.disableBody, self), Func(self.sadEyes), Func(self.blinkEyes), Track((0, ActorInterval(self, 'lose')), (2, SoundInterval(sound, node=self)), (5.333, self.scaleInterval(1.5, VBase3(0.01, 0.01, 0.01), blendType='easeInOut'))), Func(self.detachNode), Func(self.setScale, 1, 1, 1), Func(self.normalEyes), Func(self.blinkEyes), Func(Emote.globalEmote.releaseBody, self), name=trackName, autoFinish=autoFinishTrack) return ival def enterDied(self, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): if self.ghostMode: if callback: callback(*extraArgs) return if self.isDisguised: self.takeOffSuit() self.playingAnim = 'lose' Emote.globalEmote.disableAll(self, 'enterDied') if self.isLocal(): autoFinishTrack = 0 else: autoFinishTrack = 1 if hasattr(self, 'jumpLandAnimFixTask') and self.jumpLandAnimFixTask: self.jumpLandAnimFixTask.remove() self.jumpLandAnimFixTask = None self.track = self.getDiedInterval(autoFinishTrack) if callback: self.track = Sequence(self.track, Func(callback, *extraArgs), autoFinish=autoFinishTrack) self.track.start(ts) self.setActiveShadow(0) return def finishDied(self, callback = None, extraArgs = []): if self.track != None: self.ignore(self.track.getName()) self.track.finish() DelayDelete.cleanupDelayDeletes(self.track) self.track = None if hasattr(self, 'animFSM'): self.animFSM.request('TeleportedOut') if callback: callback(*extraArgs) return def exitDied(self): if self.track != None: self.ignore(self.track.getName()) self.track.finish() DelayDelete.cleanupDelayDeletes(self.track) self.track = None Emote.globalEmote.releaseAll(self, 'exitDied') self.show() return def getTeleportInTrack(self): hole = self.getHoleActors()[0] hole.setBin('shadow', 0) hole.setDepthTest(0) hole.setDepthWrite(0) holeTrack = Sequence() holeTrack.append(Func(hole.reparentTo, self)) pos = Point3(0, -2.4, 0) holeTrack.append(Func(hole.setPos, self, pos)) holeTrack.append(ActorInterval(hole, 'hole', startTime=3.4, endTime=3.1)) holeTrack.append(Wait(0.6)) holeTrack.append(ActorInterval(hole, 'hole', startTime=3.1, endTime=3.4)) def restoreHole(hole): hole.setPos(0, 0, 0) hole.detachNode() hole.clearBin() hole.clearDepthTest() hole.clearDepthWrite() holeTrack.append(Func(restoreHole, hole)) toonTrack = Sequence(Wait(0.3), Func(self.getGeomNode().show), Func(self.nametag3d.show), ActorInterval(self, 'jump', startTime=0.45)) if hasattr(self, 'uniqueName'): trackName = self.uniqueName('teleportIn') else: trackName = 'teleportIn' return Parallel(holeTrack, toonTrack, name=trackName) def enterTeleportIn(self, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): if self.ghostMode or self.isDisguised: if callback: callback(*extraArgs) return self.show() self.playingAnim = 'teleport' Emote.globalEmote.disableAll(self, 'enterTeleportIn') self.pose('teleport', self.getNumFrames('teleport') - 1) self.getGeomNode().hide() self.nametag3d.hide() self.track = self.getTeleportInTrack() if callback: self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getName(), callback, extraArgs) self.track.start(ts) self.setActiveShadow(0) def exitTeleportIn(self): self.playingAnim = None if self.track != None: self.ignore(self.track.getName()) self.track.finish() DelayDelete.cleanupDelayDeletes(self.track) self.track = None if not self.ghostMode and not self.isDisguised: self.getGeomNode().show() self.nametag3d.show() Emote.globalEmote.releaseAll(self, 'exitTeleportIn') return def enterSitStart(self, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): Emote.globalEmote.disableBody(self) self.playingAnim = 'sit-start' if self.isLocal(): self.track = Sequence(ActorInterval(self, 'sit-start'), Func(self.b_setAnimState, 'Sit', animMultiplier)) else: self.track = Sequence(ActorInterval(self, 'sit-start')) self.track.start(ts) self.setActiveShadow(0) def exitSitStart(self): self.playingAnim = 'neutral' if self.track != None: self.track.finish() DelayDelete.cleanupDelayDeletes(self.track) self.track = None Emote.globalEmote.releaseBody(self) return def enterSit(self, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): Emote.globalEmote.disableBody(self) self.playingAnim = 'sit' self.loop('sit') self.setActiveShadow(0) def exitSit(self): self.playingAnim = 'neutral' Emote.globalEmote.releaseBody(self) def enterSleep(self, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): self.stopLookAround() self.stopBlink() self.closeEyes() self.lerpLookAt(Point3(0, 1, -4)) self.loop('neutral') self.setPlayRate(animMultiplier * 0.4, 'neutral') self.setChatAbsolute(SLEEP_STRING, CFThought) if self == base.localAvatar: self.notify.debug('Adding timeout task to Toon.') taskMgr.doMethodLater(self.afkTimeout, self.__handleAfkTimeout, self.uniqueName('afkTimeout')) self.setActiveShadow(0) def __handleAfkTimeout(self, task): self.notify.debug('Handling timeout task on Toon.') self.ignore('wakeup') self.takeOffSuit() base.cr.playGame.getPlace().fsm.request('final') self.b_setAnimState('TeleportOut', 1, self.__handleAfkExitTeleport, [0]) return Task.done def __handleAfkExitTeleport(self, requestStatus): self.notify.info('closing shard...') base.cr.gameFSM.request('closeShard', ['afkTimeout']) def exitSleep(self): taskMgr.remove(self.uniqueName('afkTimeout')) self.startLookAround() self.openEyes() self.startBlink() if config.GetBool('stuck-sleep-fix', 1): doClear = SLEEP_STRING in (self.nametag.getChat(), self.nametag.getStompText()) else: doClear = self.nametag.getChat() == SLEEP_STRING if doClear: self.clearChat() self.lerpLookAt(Point3(0, 1, 0), time=0.25) self.stop() def enterPush(self, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): Emote.globalEmote.disableBody(self) self.playingAnim = 'push' self.track = Sequence(ActorInterval(self, 'push')) self.track.loop() self.setActiveShadow(1) def exitPush(self): self.playingAnim = 'neutral' if self.track != None: self.track.finish() DelayDelete.cleanupDelayDeletes(self.track) self.track = None Emote.globalEmote.releaseBody(self) return def enterEmote(self, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): if len(extraArgs) > 0: emoteIndex = extraArgs[0] else: return self.playingAnim = None self.playingRate = None self.standWalkRunReverse = (('neutral', 1.0), ('walk', 1.0), ('run', 1.0), ('walk', -1.0)) self.setSpeed(self.forwardSpeed, self.rotateSpeed) if self.isLocal() and emoteIndex != Emote.globalEmote.EmoteSleepIndex: if self.sleepFlag: self.b_setAnimState('Happy', self.animMultiplier) self.wakeUp() duration = 0 self.emoteTrack, duration = Emote.globalEmote.doEmote(self, emoteIndex, ts) self.setActiveShadow(1) return def doEmote(self, emoteIndex, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): if not self.isLocal(): if base.localAvatar.isIgnored(self.doId): return duration = 0 if self.isLocal(): self.wakeUp() if self.hasTrackAnimToSpeed(): self.trackAnimToSpeed(None) self.emoteTrack, duration = Emote.globalEmote.doEmote(self, emoteIndex, ts) return def __returnToLastAnim(self, task): if self.playingAnim: self.loop(self.playingAnim) elif self.hp > 0: self.loop('neutral') else: self.loop('sad-neutral') return Task.done def __finishEmote(self, task): if self.isLocal(): if self.hp > 0: self.b_setAnimState('Happy') else: self.b_setAnimState('Sad') return Task.done def exitEmote(self): self.stop() if self.emoteTrack != None: self.emoteTrack.finish() self.emoteTrack = None taskMgr.remove(self.taskName('finishEmote')) return def enterSquish(self, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): Emote.globalEmote.disableAll(self) sound = loader.loadSfx('phase_9/audio/sfx/toon_decompress.ogg') lerpTime = 0.1 node = self.getGeomNode().getChild(0) origScale = node.getScale() self.track = Sequence(LerpScaleInterval(node, lerpTime, VBase3(2, 2, 0.025), blendType='easeInOut'), Wait(1.0), Parallel(Sequence(Wait(0.4), LerpScaleInterval(node, lerpTime, VBase3(1.4, 1.4, 1.4), blendType='easeInOut'), LerpScaleInterval(node, lerpTime / 2.0, VBase3(0.8, 0.8, 0.8), blendType='easeInOut'), LerpScaleInterval(node, lerpTime / 3.0, origScale, blendType='easeInOut')), ActorInterval(self, 'jump', startTime=0.2), SoundInterval(sound))) self.track.start(ts) self.setActiveShadow(1) def exitSquish(self): self.playingAnim = 'neutral' if self.track != None: self.track.finish() DelayDelete.cleanupDelayDeletes(self.track) self.track = None Emote.globalEmote.releaseAll(self) return def enterFallDown(self, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): self.playingAnim = 'fallDown' Emote.globalEmote.disableAll(self) self.track = Sequence(ActorInterval(self, 'slip-backward'), name='fallTrack') if callback: self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getName(), callback, extraArgs) self.track.start(ts) def exitFallDown(self): self.playingAnim = 'neutral' if self.track != None: self.ignore(self.track.getName()) self.track.finish() DelayDelete.cleanupDelayDeletes(self.track) self.track = None Emote.globalEmote.releaseAll(self) return def stunToon(self, ts = 0, callback = None, knockdown = 0): if not self.isStunned: if self.stunTrack: self.stunTrack.finish() self.stunTrack = None def setStunned(stunned): self.isStunned = stunned if self == base.localAvatar: messenger.send('toonStunned-' + str(self.doId), [self.isStunned]) node = self.getGeomNode() lerpTime = 0.5 down = self.doToonColorScale(VBase4(1, 1, 1, 0.6), lerpTime) up = self.doToonColorScale(VBase4(1, 1, 1, 0.9), lerpTime) clear = self.doToonColorScale(self.defaultColorScale, lerpTime) track = Sequence(Func(setStunned, 1), down, up, down, up, down, up, down, clear, Func(self.restoreDefaultColorScale), Func(setStunned, 0)) if knockdown: self.stunTrack = Parallel(ActorInterval(self, animName='slip-backward'), track) else: self.stunTrack = track self.stunTrack.start() return def getPieces(self, *pieces): results = [] for lodName in self.getLODNames(): for partName, pieceNames in pieces: part = self.getPart(partName, lodName) if part: if type(pieceNames) == types.StringType: pieceNames = (pieceNames,) for pieceName in pieceNames: npc = part.findAllMatches('**/%s;+s' % pieceName) for i in xrange(npc.getNumPaths()): results.append(npc[i]) return results def applyCheesyEffect(self, effect, lerpTime = 0): if self.effectTrack != None: self.effectTrack.finish() self.effectTrack = None if self.cheesyEffect != effect: oldEffect = self.cheesyEffect self.cheesyEffect = effect if oldEffect == ToontownGlobals.CENormal: self.effectTrack = self.__doCheesyEffect(effect, lerpTime) elif effect == ToontownGlobals.CENormal: self.effectTrack = self.__undoCheesyEffect(oldEffect, lerpTime) else: self.effectTrack = Sequence(self.__undoCheesyEffect(oldEffect, lerpTime / 2.0), self.__doCheesyEffect(effect, lerpTime / 2.0)) self.effectTrack.start() return def reapplyCheesyEffect(self, lerpTime = 0): if self.effectTrack != None: self.effectTrack.finish() self.effectTrack = None effect = self.cheesyEffect self.effectTrack = Sequence(self.__undoCheesyEffect(effect, 0), self.__doCheesyEffect(effect, lerpTime)) self.effectTrack.start() return def clearCheesyEffect(self, lerpTime = 0): self.applyCheesyEffect(ToontownGlobals.CENormal, lerpTime=lerpTime) if self.effectTrack != None: self.effectTrack.finish() self.effectTrack = None return def __doHeadScale(self, scale, lerpTime): if scale == None: scale = ToontownGlobals.toonHeadScales[self.style.getAnimal()] track = Parallel() for hi in xrange(self.headParts.getNumPaths()): head = self.headParts[hi] track.append(LerpScaleInterval(head, lerpTime, scale, blendType='easeInOut')) return track def __doLegsScale(self, scale, lerpTime): if scale == None: scale = 1 invScale = 1 else: invScale = 1.0 / scale track = Parallel() for li in xrange(self.legsParts.getNumPaths()): legs = self.legsParts[li] torso = self.torsoParts[li] track.append(LerpScaleInterval(legs, lerpTime, scale, blendType='easeInOut')) track.append(LerpScaleInterval(torso, lerpTime, invScale, blendType='easeInOut')) return track def __doToonScale(self, scale, lerpTime): if scale == None: scale = 1 node = self.getGeomNode().getChild(0) track = Sequence(Parallel(LerpHprInterval(node, lerpTime, Vec3(0.0, 0.0, 0.0), blendType='easeInOut'), LerpScaleInterval(node, lerpTime, scale, blendType='easeInOut')), Func(self.resetHeight)) return track def doToonColorScale(self, scale, lerpTime, keepDefault = 0): if keepDefault: self.defaultColorScale = scale if scale == None: scale = VBase4(1, 1, 1, 1) node = self.getGeomNode() caps = self.getPieces(('torso', 'torso-bot-cap')) track = Sequence() track.append(Func(node.setTransparency, 1)) if scale[3] != 1: for cap in caps: track.append(HideInterval(cap)) track.append(LerpColorScaleInterval(node, lerpTime, scale, blendType='easeInOut')) if scale[3] == 1: track.append(Func(node.clearTransparency)) for cap in caps: track.append(ShowInterval(cap)) elif scale[3] == 0: track.append(Func(node.clearTransparency)) return track def __doPumpkinHeadSwitch(self, lerpTime, toPumpkin): node = self.getGeomNode() dust = self.getDustCloud(0.0) track = Sequence() if toPumpkin: track.append(Func(self.stopBlink)) track.append(Func(self.closeEyes)) if lerpTime > 0.0: track.append(Func(dust.start)) track.append(Wait(0.5)) else: dust.finish() def hideParts(): self.notify.debug('hideParts') for head in self.headParts: for p in head.getChildren(): if hasattr(self, 'pumpkins') and not self.pumpkins.hasPath(p): p.hide() p.setTag('pumpkin', 'enabled') track.append(Func(hideParts)) track.append(Func(self.enablePumpkins, True)) else: if lerpTime > 0.0: track.append(Func(dust.start)) track.append(Wait(0.5)) else: dust.finish() def showHiddenParts(): self.notify.debug('showHiddenParts') for head in self.headParts: for p in head.getChildren(): if not self.pumpkins.hasPath(p) and p.getTag('pumpkin') == 'enabled': p.show() p.setTag('pumpkin', 'disabled') track.append(Func(showHiddenParts)) track.append(Func(self.enablePumpkins, False)) track.append(Func(self.startBlink)) return track def __doSnowManHeadSwitch(self, lerpTime, toSnowMan): node = self.getGeomNode() dust = self.getDustCloud(0.0) track = Sequence() if toSnowMan: track.append(Func(self.stopBlink)) track.append(Func(self.closeEyes)) if lerpTime > 0.0: track.append(Func(dust.start)) track.append(Wait(0.5)) else: dust.finish() def hideParts(): self.notify.debug('HidePaths') for hi in xrange(self.headParts.getNumPaths()): head = self.headParts[hi] parts = head.getChildren() for pi in xrange(parts.getNumPaths()): p = parts[pi] if not p.isHidden(): p.hide() p.setTag('snowman', 'enabled') track.append(Func(hideParts)) track.append(Func(self.enableSnowMen, True)) else: if lerpTime > 0.0: track.append(Func(dust.start)) track.append(Wait(0.5)) else: dust.finish() def showHiddenParts(): self.notify.debug('ShowHiddenPaths') for hi in xrange(self.headParts.getNumPaths()): head = self.headParts[hi] parts = head.getChildren() for pi in xrange(parts.getNumPaths()): p = parts[pi] if not self.snowMen.hasPath(p) and p.getTag('snowman') == 'enabled': p.show() p.setTag('snowman', 'disabled') track.append(Func(showHiddenParts)) track.append(Func(self.enableSnowMen, False)) track.append(Func(self.startBlink)) return track def __doGreenToon(self, lerpTime, toGreen): track = Sequence() greenTrack = Parallel() if lerpTime > 0.0: dust = self.getDustCloud(0.0) track.append(Func(dust.start)) track.append(Wait(0.5)) if toGreen: skinGreen = VBase4(76 / 255.0, 240 / 255.0, 84 / 255.0, 1) muzzleGreen = VBase4(4 / 255.0, 205 / 255.0, 90 / 255.0, 1) gloveGreen = VBase4(14 / 255.0, 173 / 255.0, 40 / 255.0, 1) greenTrack.append(self.__colorToonSkin(skinGreen, lerpTime)) greenTrack.append(self.__colorToonEars(skinGreen, muzzleGreen, lerpTime)) greenTrack.append(self.__colorScaleToonMuzzle(muzzleGreen, lerpTime)) greenTrack.append(self.__colorToonGloves(gloveGreen, lerpTime)) else: greenTrack.append(self.__colorToonSkin(None, lerpTime)) greenTrack.append(self.__colorToonEars(None, None, lerpTime)) greenTrack.append(self.__colorScaleToonMuzzle(None, lerpTime)) greenTrack.append(self.__colorToonGloves(None, lerpTime)) track.append(greenTrack) return track def __colorToonSkin(self, color, lerpTime): track = Sequence() colorTrack = Parallel() torsoPieces = self.getPieces(('torso', ('arms', 'neck'))) legPieces = self.getPieces(('legs', ('legs', 'feet'))) headPieces = self.getPieces(('head', '*head*')) if color == None: armColor = self.style.getArmColor() legColor = self.style.getLegColor() headColor = self.style.getHeadColor() else: armColor = color legColor = color headColor = color for piece in torsoPieces: colorTrack.append(Func(piece.setColor, armColor)) for piece in legPieces: colorTrack.append(Func(piece.setColor, legColor)) for piece in headPieces: if 'hatNode' not in str(piece) and 'glassesNode' not in str(piece): colorTrack.append(Func(piece.setColor, headColor)) track.append(colorTrack) return track def __colorToonEars(self, color, colorScale, lerpTime): track = Sequence() earPieces = self.getPieces(('head', '*ear*')) if len(earPieces) == 0: return track colorTrack = Parallel() if earPieces[0].hasColor(): if color == None: headColor = self.style.getHeadColor() else: headColor = color for piece in earPieces: colorTrack.append(Func(piece.setColor, headColor)) else: if colorScale == None: colorScale = VBase4(1, 1, 1, 1) for piece in earPieces: colorTrack.append(Func(piece.setColorScale, colorScale)) track.append(colorTrack) return track def __colorScaleToonMuzzle(self, scale, lerpTime): track = Sequence() colorTrack = Parallel() muzzlePieces = self.getPieces(('head', '*muzzle*')) if scale == None: scale = VBase4(1, 1, 1, 1) for piece in muzzlePieces: colorTrack.append(Func(piece.setColorScale, scale)) track.append(colorTrack) return track def __colorToonGloves(self, color, lerpTime): track = Sequence() colorTrack = Parallel() glovePieces = self.getPieces(('torso', '*hands*')) if color == None: for piece in glovePieces: colorTrack.append(Func(piece.clearColor)) else: for piece in glovePieces: colorTrack.append(Func(piece.setColor, color)) track.append(colorTrack) return track def __doBigAndWhite(self, color, scale, lerpTime): track = Parallel() track.append(self.__doToonColor(color, lerpTime)) track.append(self.__doToonScale(scale, lerpTime)) return track def __doVirtual(self): track = Parallel() track.append(self.__doToonColor(VBase4(0.25, 0.25, 1.0, 1), 0.0)) self.setPartsAdd(self.getHeadParts()) self.setPartsAdd(self.getTorsoParts()) self.setPartsAdd(self.getHipsParts()) self.setPartsAdd(self.getLegsParts()) return track def __doUnVirtual(self): track = Parallel() track.append(self.__doToonColor(None, 0.0)) self.setPartsNormal(self.getHeadParts(), 1) self.setPartsNormal(self.getTorsoParts(), 1) self.setPartsNormal(self.getHipsParts(), 1) self.setPartsNormal(self.getLegsParts(), 1) return track def setPartsAdd(self, parts): actorCollection = parts for thingIndex in xrange(0, actorCollection.getNumPaths()): thing = actorCollection[thingIndex] if thing.getName() not in ('joint_attachMeter', 'joint_nameTag'): thing.setAttrib(ColorBlendAttrib.make(ColorBlendAttrib.MAdd)) thing.setDepthWrite(False) self.setBin('fixed', 1) def setPartsNormal(self, parts, alpha = 0): actorCollection = parts for thingIndex in xrange(0, actorCollection.getNumPaths()): thing = actorCollection[thingIndex] if thing.getName() not in ('joint_attachMeter', 'joint_nameTag'): thing.setAttrib(ColorBlendAttrib.make(ColorBlendAttrib.MNone)) thing.setDepthWrite(True) self.setBin('default', 0) if alpha: thing.setTransparency(1) thing.setBin('transparent', 0) def __doToonGhostColorScale(self, scale, lerpTime, keepDefault = 0): if keepDefault: self.defaultColorScale = scale if scale == None: scale = VBase4(1, 1, 1, 1) node = self.getGeomNode() caps = self.getPieces(('torso', 'torso-bot-cap')) track = Sequence() track.append(Func(node.setTransparency, 1)) track.append(ShowInterval(node)) if scale[3] != 1: for cap in caps: track.append(HideInterval(cap)) track.append(LerpColorScaleInterval(node, lerpTime, scale, blendType='easeInOut')) if scale[3] == 1: track.append(Func(node.clearTransparency)) for cap in caps: track.append(ShowInterval(cap)) elif scale[3] == 0: track.append(Func(node.clearTransparency)) track.append(HideInterval(node)) return track def restoreDefaultColorScale(self): node = self.getGeomNode() if node: if self.defaultColorScale: node.setColorScale(self.defaultColorScale) if self.defaultColorScale[3] != 1: node.setTransparency(1) else: node.clearTransparency() else: node.clearColorScale() node.clearTransparency() def __doToonColor(self, color, lerpTime): node = self.getGeomNode() if color == None: return Func(node.clearColor) else: return Func(node.setColor, color, 1) return def __doPartsColorScale(self, scale, lerpTime): if scale == None: scale = VBase4(1, 1, 1, 1) node = self.getGeomNode() pieces = self.getPieces(('torso', ('arms', 'neck')), ('legs', ('legs', 'feet')), ('head', '+GeomNode')) track = Sequence() track.append(Func(node.setTransparency, 1)) for piece in pieces: if piece.getName()[:7] == 'muzzle-' and piece.getName()[-8:] != '-neutral': continue track.append(ShowInterval(piece)) p1 = Parallel() for piece in pieces: if piece.getName()[:7] == 'muzzle-' and piece.getName()[-8:] != '-neutral': continue p1.append(LerpColorScaleInterval(piece, lerpTime, scale, blendType='easeInOut')) track.append(p1) if scale[3] == 1: track.append(Func(node.clearTransparency)) elif scale[3] == 0: track.append(Func(node.clearTransparency)) for piece in pieces: if piece.getName()[:7] == 'muzzle-' and piece.getName()[-8:] != '-neutral': continue track.append(HideInterval(piece)) self.generateHat() self.generateGlasses() return track def __doCheesyEffect(self, effect, lerpTime): if effect == ToontownGlobals.CEBigHead: return self.__doHeadScale(2.5, lerpTime) elif effect == ToontownGlobals.CESmallHead: return self.__doHeadScale(0.5, lerpTime) elif effect == ToontownGlobals.CEBigLegs: return self.__doLegsScale(1.4, lerpTime) elif effect == ToontownGlobals.CESmallLegs: return self.__doLegsScale(0.6, lerpTime) elif effect == ToontownGlobals.CEBigToon: return self.__doToonScale(ToontownGlobals.BigToonScale, lerpTime) elif effect == ToontownGlobals.CESmallToon: return self.__doToonScale(ToontownGlobals.SmallToonScale, lerpTime) elif effect == ToontownGlobals.CEFlatPortrait: return self.__doToonScale(VBase3(1, 0.05, 1), lerpTime) elif effect == ToontownGlobals.CEFlatProfile: return self.__doToonScale(VBase3(0.05, 1, 1), lerpTime) elif effect == ToontownGlobals.CETransparent: return self.doToonColorScale(VBase4(1, 1, 1, 0.6), lerpTime, keepDefault=1) elif effect == ToontownGlobals.CENoColor: return self.__doToonColor(VBase4(1, 1, 1, 1), lerpTime) elif effect == ToontownGlobals.CEInvisible: return self.__doPartsColorScale(VBase4(1, 1, 1, 0), lerpTime) elif effect == ToontownGlobals.CEPumpkin: return self.__doPumpkinHeadSwitch(lerpTime, toPumpkin=True) elif effect == ToontownGlobals.CEBigWhite: return self.__doBigAndWhite(VBase4(1, 1, 1, 1), ToontownGlobals.BigToonScale, lerpTime) elif effect == ToontownGlobals.CESnowMan: return self.__doSnowManHeadSwitch(lerpTime, toSnowMan=True) elif effect == ToontownGlobals.CEGreenToon: return self.__doGreenToon(lerpTime, toGreen=True) elif effect == ToontownGlobals.CEVirtual: return self.__doVirtual() elif effect == ToontownGlobals.CEGhost: alpha = 0.25 if base.localAvatar.getAdminAccess() < self.adminAccess: alpha = 0 return Sequence(self.__doToonGhostColorScale(VBase4(1, 1, 1, alpha), lerpTime, keepDefault=1), Func(self.nametag3d.hide)) return Sequence() def __undoCheesyEffect(self, effect, lerpTime): if effect == ToontownGlobals.CEBigHead: return self.__doHeadScale(None, lerpTime) elif effect == ToontownGlobals.CESmallHead: return self.__doHeadScale(None, lerpTime) if effect == ToontownGlobals.CEBigLegs: return self.__doLegsScale(None, lerpTime) elif effect == ToontownGlobals.CESmallLegs: return self.__doLegsScale(None, lerpTime) elif effect == ToontownGlobals.CEBigToon: return self.__doToonScale(None, lerpTime) elif effect == ToontownGlobals.CESmallToon: return self.__doToonScale(None, lerpTime) elif effect == ToontownGlobals.CEFlatPortrait: return self.__doToonScale(None, lerpTime) elif effect == ToontownGlobals.CEFlatProfile: return self.__doToonScale(None, lerpTime) elif effect == ToontownGlobals.CETransparent: return self.doToonColorScale(None, lerpTime, keepDefault=1) elif effect == ToontownGlobals.CENoColor: return self.__doToonColor(None, lerpTime) elif effect == ToontownGlobals.CEInvisible: return self.__doPartsColorScale(None, lerpTime) elif effect == ToontownGlobals.CEPumpkin: return self.__doPumpkinHeadSwitch(lerpTime, toPumpkin=False) elif effect == ToontownGlobals.CEBigWhite: return self.__doBigAndWhite(None, None, lerpTime) elif effect == ToontownGlobals.CESnowMan: return self.__doSnowManHeadSwitch(lerpTime, toSnowMan=False) elif effect == ToontownGlobals.CEGreenToon: return self.__doGreenToon(lerpTime, toGreen=False) elif effect == ToontownGlobals.CEVirtual: return self.__doUnVirtual() elif effect == ToontownGlobals.CEGhost: return Sequence(Func(self.nametag3d.show), self.__doToonGhostColorScale(None, lerpTime, keepDefault=1)) return Sequence() def putOnSuit(self, suitType, setDisplayName = True, rental = False): if self.isDisguised: self.takeOffSuit() from toontown.suit import Suit deptIndex = suitType suit = Suit.Suit() dna = SuitDNA.SuitDNA() if rental == True: if SuitDNA.suitDepts[deptIndex] == 's': suitType = 'cc' elif SuitDNA.suitDepts[deptIndex] == 'm': suitType = 'sc' elif SuitDNA.suitDepts[deptIndex] == 'l': suitType = 'bf' elif SuitDNA.suitDepts[deptIndex] == 'c': suitType = 'f' else: self.notify.warning('Suspicious: Incorrect rental suit department requested') suitType = 'cc' dna.newSuit(suitType) suit.setStyle(dna) suit.isDisguised = 1 suit.generateSuit() suit.initializeDropShadow() suit.setPos(self.getPos()) suit.setHpr(self.getHpr()) for part in suit.getHeadParts(): part.hide() suitHeadNull = suit.find('**/joint_head') toonHead = self.getPart('head', '1000') Emote.globalEmote.disableAll(self) toonGeom = self.getGeomNode() toonGeom.hide() worldScale = toonHead.getScale(render) self.headOrigScale = toonHead.getScale() headPosNode = hidden.attachNewNode('headPos') toonHead.reparentTo(headPosNode) toonHead.setPos(0, 0, 0.2) headPosNode.reparentTo(suitHeadNull) headPosNode.setScale(render, worldScale) suitGeom = suit.getGeomNode() suitGeom.reparentTo(self) if rental == True: suit.makeRentalSuit(SuitDNA.suitDepts[deptIndex]) self.suit = suit self.suitGeom = suitGeom self.setHeight(suit.getHeight()) self.nametag3d.setPos(0, 0, self.height + 1.3) if self.isLocal(): if hasattr(self, 'book'): self.book.obscureButton(1) self.oldForward = ToontownGlobals.ToonForwardSpeed self.oldReverse = ToontownGlobals.ToonReverseSpeed self.oldRotate = ToontownGlobals.ToonRotateSpeed ToontownGlobals.ToonForwardSpeed = ToontownGlobals.SuitWalkSpeed ToontownGlobals.ToonReverseSpeed = ToontownGlobals.SuitWalkSpeed ToontownGlobals.ToonRotateSpeed = ToontownGlobals.ToonRotateSlowSpeed if self.hasTrackAnimToSpeed(): self.stopTrackAnimToSpeed() self.startTrackAnimToSpeed() self.controlManager.disableAvatarJump() indices = range(OTPLocalizer.SCMenuCommonCogIndices[0], OTPLocalizer.SCMenuCommonCogIndices[1] + 1) customIndices = OTPLocalizer.SCMenuCustomCogIndices[suitType] indices += range(customIndices[0], customIndices[1] + 1) self.chatMgr.chatInputSpeedChat.addCogMenu(indices) self.suit.loop('neutral') self.isDisguised = 1 self.setFont(ToontownGlobals.getSuitFont()) self.setSpeechFont(ToontownGlobals.getSuitFont()) if setDisplayName: if hasattr(base, 'idTags') and base.idTags: name = self.getAvIdName() else: name = self.getName() suitDept = SuitDNA.suitDepts.index(SuitDNA.getSuitDept(suitType)) suitName = SuitBattleGlobals.SuitAttributes[suitType]['name'] self.nametag.setDisplayName(TTLocalizer.SuitBaseNameWithLevel % {'name': name, 'dept': suitName, 'level': self.cogLevels[suitDept] + 1}) self.nametag.setWordwrap(9.0) def takeOffSuit(self): if not self.isDisguised: return suitType = self.suit.style.name toonHeadNull = self.find('**/1000/**/def_head') if not toonHeadNull: toonHeadNull = self.find('**/1000/**/joint_head') toonHead = self.getPart('head', '1000') toonHead.reparentTo(toonHeadNull) toonHead.setScale(self.headOrigScale) toonHead.setPos(0, 0, 0) headPosNode = self.suitGeom.find('**/headPos') headPosNode.removeNode() self.suitGeom.reparentTo(self.suit) self.resetHeight() self.nametag3d.setPos(0, 0, self.height + 0.5) toonGeom = self.getGeomNode() toonGeom.show() Emote.globalEmote.releaseAll(self) self.isDisguised = 0 self.setFont(ToontownGlobals.getToonFont()) self.setSpeechFont(ToontownGlobals.getToonFont()) self.nametag.setWordwrap(None) if hasattr(base, 'idTags') and base.idTags: name = self.getAvIdName() else: name = self.getName() self.setDisplayName(name) if self.isLocal(): if hasattr(self, 'book'): self.book.obscureButton(0) ToontownGlobals.ToonForwardSpeed = self.oldForward ToontownGlobals.ToonReverseSpeed = self.oldReverse ToontownGlobals.ToonRotateSpeed = self.oldRotate if self.hasTrackAnimToSpeed(): self.stopTrackAnimToSpeed() self.startTrackAnimToSpeed() del self.oldForward del self.oldReverse del self.oldRotate self.controlManager.enableAvatarJump() self.chatMgr.chatInputSpeedChat.removeCogMenu() self.suit.delete() del self.suit del self.suitGeom def makeWaiter(self): if not self.isDisguised: return self.suit.makeWaiter(self.suitGeom) def getPieModel(self): from toontown.toonbase import ToontownBattleGlobals from toontown.battle import BattleProps if self.pieModel != None and self.__pieModelType != self.pieType: self.pieModel.detachNode() self.pieModel = None if self.pieModel == None: self.__pieModelType = self.pieType pieName = ToontownBattleGlobals.pieNames[self.pieType] self.pieModel = BattleProps.globalPropPool.getProp(pieName) self.pieScale = self.pieModel.getScale() return self.pieModel def getPresentPieInterval(self, x, y, z, h): from toontown.toonbase import ToontownBattleGlobals from toontown.battle import BattleProps from toontown.battle import MovieUtil pie = self.getPieModel() pieName = ToontownBattleGlobals.pieNames[self.pieType] pieType = BattleProps.globalPropPool.getPropType(pieName) animPie = Sequence() pingpongPie = Sequence() if pieType == 'actor': animPie = ActorInterval(pie, pieName, startFrame=0, endFrame=31) pingpongPie = Func(pie.pingpong, pieName, fromFrame=32, toFrame=47) track = Sequence(Func(self.setPosHpr, x, y, z, h, 0, 0), Func(pie.reparentTo, self.rightHand), Func(pie.setPosHpr, 0, 0, 0, 0, 0, 0), Parallel(pie.scaleInterval(1, self.pieScale, startScale=MovieUtil.PNT3_NEARZERO), ActorInterval(self, 'throw', startFrame=0, endFrame=31), animPie), Func(self.pingpong, 'throw', fromFrame=32, toFrame=47), pingpongPie) return track def getTossPieInterval(self, x, y, z, h, power, throwType, beginFlyIval = Sequence()): from toontown.toonbase import ToontownBattleGlobals from toontown.battle import BattleProps pie = self.getPieModel() flyPie = pie.copyTo(NodePath('a')) pieName = ToontownBattleGlobals.pieNames[self.pieType] pieType = BattleProps.globalPropPool.getPropType(pieName) animPie = Sequence() if pieType == 'actor': animPie = ActorInterval(pie, pieName, startFrame=48) sound = loader.loadSfx('phase_3.5/audio/sfx/AA_pie_throw_only.ogg') if throwType == ToontownGlobals.PieThrowArc: t = power / 100.0 dist = 100 - 70 * t time = 1 + 0.5 * t proj = ProjectileInterval(None, startPos=Point3(0, 0, 0), endPos=Point3(0, dist, 0), duration=time) relVel = proj.startVel elif throwType == ToontownGlobals.PieThrowLinear: magnitude = power / 2. + 25 relVel = Vec3(0, 1, 0.25) relVel.normalize() relVel *= magnitude def getVelocity(toon = self, relVel = relVel): return render.getRelativeVector(toon, relVel) toss = Track((0, Sequence(Func(self.setPosHpr, x, y, z, h, 0, 0), Func(pie.reparentTo, self.rightHand), Func(pie.setPosHpr, 0, 0, 0, 0, 0, 0), Parallel(ActorInterval(self, 'throw', startFrame=48), animPie), Func(self.loop, 'neutral'))), (16.0 / 24.0, Func(pie.detachNode))) fly = Track((14.0 / 24.0, SoundInterval(sound, node=self)), (16.0 / 24.0, Sequence(Func(flyPie.reparentTo, render), Func(flyPie.setScale, self.pieScale), Func(flyPie.setPosHpr, self, 0.52, 0.97, 2.24, 89.42, -10.56, 87.94), beginFlyIval, ProjectileInterval(flyPie, startVel=getVelocity, duration=3), Func(flyPie.detachNode)))) return (toss, fly, flyPie) def getPieSplatInterval(self, x, y, z, pieCode): from toontown.toonbase import ToontownBattleGlobals from toontown.battle import BattleProps pieName = ToontownBattleGlobals.pieNames[self.pieType] splatName = 'splat-%s' % pieName if pieName == 'lawbook': splatName = 'dust' splat = BattleProps.globalPropPool.getProp(splatName) splat.setBillboardPointWorld(2) color = ToontownGlobals.PieCodeColors.get(pieCode) if color: splat.setColor(*color) vol = 1.0 if pieName == 'lawbook': sound = loader.loadSfx('phase_11/audio/sfx/LB_evidence_miss.ogg') vol = 0.25 else: sound = loader.loadSfx('phase_4/audio/sfx/AA_wholepie_only.ogg') ival = Parallel(Func(splat.reparentTo, render), Func(splat.setPos, x, y, z), SoundInterval(sound, node=splat, volume=vol), Sequence(ActorInterval(splat, splatName), Func(splat.detachNode))) return ival def cleanupPieModel(self): if self.pieModel != None: self.pieModel.detachNode() self.pieModel = None return def getFeedPetIval(self): return Sequence(ActorInterval(self, 'feedPet'), Func(self.animFSM.request, 'neutral')) def getScratchPetIval(self): return Sequence(ActorInterval(self, 'pet-start'), ActorInterval(self, 'pet-loop'), ActorInterval(self, 'pet-end')) def getCallPetIval(self): return ActorInterval(self, 'callPet') def enterGolfPuttLoop(self, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): self.loop('loop-putt') def exitGolfPuttLoop(self): self.stop() def enterGolfRotateLeft(self, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): self.loop('rotateL-putt') def exitGolfRotateLeft(self): self.stop() def enterGolfRotateRight(self, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): self.loop('rotateR-putt') def exitGolfRotateRight(self): self.stop() def enterGolfPuttSwing(self, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): self.loop('swing-putt') def exitGolfPuttSwing(self): self.stop() def enterGolfGoodPutt(self, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): self.loop('good-putt', restart=0) def exitGolfGoodPutt(self): self.stop() def enterGolfBadPutt(self, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): self.loop('badloop-putt', restart=0) def exitGolfBadPutt(self): self.stop() def enterFlattened(self, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): Emote.globalEmote.disableAll(self) sound = loader.loadSfx('phase_9/audio/sfx/toon_decompress.ogg') lerpTime = 0.1 node = self.getGeomNode().getChild(0) self.origScale = node.getScale() self.track = Sequence(LerpScaleInterval(node, lerpTime, VBase3(2, 2, 0.025), blendType='easeInOut')) self.track.start(ts) self.setActiveShadow(1) def exitFlattened(self): self.playingAnim = 'neutral' if self.track != None: self.track.finish() DelayDelete.cleanupDelayDeletes(self.track) self.track = None node = self.getGeomNode().getChild(0) node.setScale(self.origScale) Emote.globalEmote.releaseAll(self) return def enterCogThiefRunning(self, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): self.playingAnim = None self.playingRate = None self.standWalkRunReverse = (('neutral', 1.0), ('run', 1.0), ('run', 1.0), ('run', -1.0)) self.setSpeed(self.forwardSpeed, self.rotateSpeed) self.setActiveShadow(1) return def exitCogThiefRunning(self): self.standWalkRunReverse = None self.stop() self.motion.exit() return def enterScientistJealous(self, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): self.loop('scientistJealous') def exitScientistJealous(self): self.stop() def enterScientistEmcee(self, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): self.loop('scientistEmcee') def exitScientistEmcee(self): self.stop() def enterScientistWork(self, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): self.loop('scientistWork') def exitScientistWork(self): self.stop() def enterScientistLessWork(self, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): self.loop('scientistWork', fromFrame=319, toFrame=619) def exitScientistLessWork(self): self.stop() def enterScientistPlay(self, animMultiplier = 1, ts = 0, callback = None, extraArgs = []): self.loop('scientistGame') def exitScientistPlay(self): self.stop() def createTalkSequence(self, speech, waitTime): sequence = Sequence() for text in speech: sequence.append(Func(self.setChatAbsolute, text, CFSpeech)) sequence.append(Wait(len(text.split(' ')))) sequence.append(Func(self.clearChat)) sequence.append(Wait(waitTime)) return sequence def getDustCloud(self, delay=0.5, color=None): dustCloud = DustCloud.DustCloud(fBillboard=0, wantSound=1) dustCloud.setBillboardAxis(2.0) dustCloud.setZ(3) dustCloud.setScale(0.4) dustCloud.createTrack() sequence = Sequence(Wait(delay), Func(dustCloud.reparentTo, self), dustCloud.track, Func(dustCloud.destroy), name='dustCloudIval') if color is not None and hasattr(self, 'laffMeter'): self.laffMeter.color = color sequence.append(Func(self.laffMeter.adjustFace, self.hp, self.maxHp)) return sequence def createHeadMeter(self): if self.headMeter: return nodePath = NodePath(self.nametag.getNameIcon()) if nodePath.isEmpty(): return self.headMeter = LaffMeter.LaffMeter(self.style, self.getHp(), self.getMaxHp()) self.headMeter.av = self self.headMeter.reparentTo(nodePath) self.headMeter.setScale(1) self.headMeter.setBin("fixed", 40) self.headMeter.setDepthWrite(False) self.headMeter.start() self.setHeadPositions() def removeHeadMeter(self): if not self.headMeter: return self.headMeter.destroy() self.headMeter = None self.setHeadPositions() def setGMIcon(self, access): if self.gmIcon: return icons = loader.loadModel('phase_3/models/props/gm_icons') self.gmIcon = icons.find('**/access_level_%s' % access) np = NodePath(self.nametag.getNameIcon()) if np.isEmpty() or not self.gmIcon: return self.gmIcon.flattenStrong() self.gmIcon.reparentTo(np) self.gmIcon.setScale(1.6) self.gmIconInterval = LerpHprInterval(self.gmIcon, 3.0, Point3(0, 0, 0), Point3(-360, 0, 0)) self.gmIconInterval.loop() self.setHeadPositions() def removeGMIcon(self): if not self.gmIcon: return self.gmIconInterval.finish() self.gmIcon.detachNode() del self.gmIconInterval self.gmIcon = None self.setHeadPositions() def setPartyHat(self): if self.partyHat: return nodePath = NodePath(self.nametag.getNameIcon()) if nodePath.isEmpty(): return model = loader.loadModel('phase_4/models/parties/partyStickerbook') self.partyHat = model.find('**/Stickerbook_PartyIcon') self.partyHat.setHpr(0.0, 0.0, -50.0) self.partyHat.setScale(4) self.partyHat.setBillboardAxis() self.partyHat.reparentTo(nodePath) model.removeNode() self.setHeadPositions() def removePartyHat(self): if not self.partyHat: return self.partyHat.detachNode() self.partyHat = None self.setHeadPositions() def setHeadPositions(self): position = 2.5 if self.gmIcon: self.gmIcon.setZ(position) position += (2.5 if self.trophyStar else 2.7) if self.trophyStar: self.trophyStar.setZ(position) position += 2.7 if self.headMeter: self.headMeter.setZ(position) position += 3.3 if self.partyHat: self.partyHat.setZ(position) loadModels() compileGlobalAnimList() @magicWord(category=CATEGORY_PROGRAMMER, types=[int]) def headMeter(create=True): """ Create or remove the head meter. """ for av in base.cr.doId2do.values(): if isinstance(av, Toon): av.createHeadMeter() if create else av.removeHeadMeter() @magicWord(category=CATEGORY_PROGRAMMER, types=[int]) def partyHat(create=True): """ Create or remove the party hat. """ for av in base.cr.doId2do.values(): if isinstance(av, Toon): av.setPartyHat() if create else av.removePartyHat()