class DynamicHuman(HumanBase.HumanBase, Biped.Biped): notify = DirectNotifyGlobal.directNotify.newCategory('Human') def __init__(self, other = None): Biped.Biped.__init__(self, other, HumanAnimationMixer) self.model = None self.zombie = False self.crazyColorSkin = False self.crazyColorSkinIndex = 0 self.flattenPending = None if __dev__: self.optimizeLOD = base.config.GetBool('optimize-avatar-lod', 1) else: self.optimizeLOD = 0 self.master = 0 self.loaded = 0 self.playingRate = None self.shadowFileName = 'models/misc/drop_shadow' self.setFont(PiratesGlobals.getInterfaceFont()) self._DynamicHuman__blinkName = 'blink-' + str(self.this) self.eyeLids = None self.eyeBalls = None self.eyeIris = None self.reducedAnimList = None self.headNode = None self.extraNode = None self.scaleNode = None self.rootNode = None self.floorOffsetZ = 0.0 self.headFudgeHpr = Vec3(0, 0, 0) self.randGen = random.Random() self.randGen.seed(random.random()) self.eyeFSM = ClassicFSM('eyeFSM', [ State('off', self.enterEyeFSMOff, self.exitEyeFSMOff, [ 'open', 'closed']), State('open', self.enterEyeFSMOpen, self.exitEyeFSMOpen, [ 'closed', 'off']), State('closed', self.enterEyeFSMClosed, self.exitEyeFSMClosed, [ 'open', 'off'])], 'off', 'off') self.eyeFSM.enterInitialState() self.isPaid = True if other != None: self.copyHuman(other) def removeCopiedNodes(self): self.dropShadow = self.find('**/drop_shadow*') if not self.dropShadow.isEmpty(): self.deleteDropShadow() def flattenHuman(self): self.deleteNametag3d() self.getWeaponJoints() def _DynamicHuman__doneFlattenHuman(self, models): self.flattenPending = None self.getWeaponJoints() def copyHuman(self, other): self.gender = other.gender self.loaded = other.loaded self.type = other.type self.loadAnimatedHead = other.loadAnimatedHead self.flattenHuman() self.model = None def delete(self): try: pass except: self.Human_deleted = 1 taskMgr.remove(self._DynamicHuman__blinkName) if self.dropShadow and not self.dropShadow.isEmpty(): self.deleteDropShadow() del self.eyeFSM self.controlShapes = None self.sliderNames = None if self.model: self.model.delete() del self.model Biped.Biped.delete(self) def isDeleted(self): try: if self.Human_deleted == 1: return True except: return False def setupExtraNodes(self): idx = 0 if self.gender == 'f': idx = 1 jointName = 'def_head01' jointNameExtra = 'def_extra_jt' jointNameScale = 'def_scale_jt' lods = self.getLODNames() self.headNode = self.controlJoint(None, 'legs', jointName, lods[0]) self.extraNode = self.controlJoint(None, 'legs', jointNameExtra, lods[0]) self.scaleNode = self.controlJoint(None, 'legs', jointNameScale, lods[0]) self.rootNode = self.getLOD('2000').find('**/dx_root') self.floorOffsetZ = self.rootNode.getZ() for lod in lods[1:]: self.controlJoint(self.headNode, 'legs', jointName, lod) self.controlJoint(self.extraNode, 'legs', jointNameExtra, lod) self.controlJoint(self.scaleNode, 'legs', jointNameScale, lod) exposedHeadJoint = self.getLOD(lod).find('**/def_head01') if not exposedHeadJoint.isEmpty(): exposedHeadJoint.removeNode() continue self.headNode.setScale(HeadScales[idx][self.style.getBodyShape()]) self.setGlobalScale(self.calcBodyScale()) def undoExtraNodes(self): jointNameExtra = 'def_extra_jt' jointNameScale = 'def_scale_jt' joints = self.findAllMatches('**/*' + jointNameExtra) if not joints.isEmpty(): joints.detach() joints.clear() if self.headNode: self.headNode.removeNode() self.headNode = None self.extraNode.removeNode() self.extraNode = None joints = self.findAllMatches('**/*' + jointNameScale) if not joints.isEmpty(): joints.detach() joints.clear() if self.scaleNode: self.scaleNode.removeNode() self.scaleNode = None self.rootNode = None def fixEyes(self): self.eyeLids = { } self.eyeBalls = { } self.eyeIris = { } for lodName in self.getLODNames(): geom = self.getPart('head', lodName) self.eyeLids[lodName] = geom.findAllMatches('**/*eyelid*') self.eyeBalls[lodName] = geom.findAllMatches('**/eye_ball*') self.eyeIris[lodName] = geom.findAllMatches('**/eye_iris*') self.eyeLids[lodName].stash() self.eyeBalls[lodName].unstash() self.eyeIris[lodName].unstash() def generateFaceTexture(self): faceTextureIdx = self.style.head.texture if self.gender == 'f': face_textures = PirateFemale.face_textures else: face_textures = PirateMale.face_textures tex_name = self.getTrySafe(face_textures, faceTextureIdx) if tex_name != None: tex = self.model.faceTextures.findTexture(tex_name) if tex == None: return None else: return None for lodName in self.getLODNames(): self.findAllMatches('**/body_master_face').setTexture(tex, 1) def generateSkinColor(self): skinColor = self.style.getSkinColor() self.model.faces[0].setColorScale(skinColor) if self.model.newAvatars: self.model.currentBody.setColorScale(skinColor) else: numPaths = self.model.body.getNumPaths() if self.zombie: self.model.body.setColorScale(Vec4(1, 1, 1, 1)) else: self.model.body.setColorScale(skinColor) def generateSkinTexture(self): bodyTextureIdx = self.style.body.skin if self.zombie: if self.gender == 'f': bodyTextureIdx = PirateFemale.ZOMB_BODY_TEXTURE else: bodyTextureIdx = PirateMale.ZOMB_BODY_TEXTURE if self.gender == 'f': body_textures = PirateFemale.body_textures[self.style.body.shape] else: body_textures = PirateMale.body_textures[self.style.body.shape] tex_name = self.getTrySafe(body_textures, bodyTextureIdx) if tex_name != None: tex = self.model.bodyTextures.findTexture(tex_name) else: return None for parts in self.model.bodys: parts.setTexture(tex, 1) def generateHairColor(self, colorName = None, colorModel = None): self.model.setHairBaseColor() def getTrySafe(self, list, idx): try: if type(idx) == str: lookup = idx.split('_cut')[0] else: lookup = idx return list[lookup] except: return None def generateEyesTexture(self): eyesTextureIdx = self.style.head.eyes.color if self.gender == 'f': eye_iris_textures = PirateFemale.eye_iris_textures else: eye_iris_textures = PirateMale.eye_iris_textures tex_name = self.getTrySafe(eye_iris_textures, eyesTextureIdx) if tex_name != None: tex = self.eyeIrisTextures.findTexture(tex_name) else: return None self.model.irises.setTexture(tex, 1) def generateHatColor(self): style = self.style if self.zombie: style = self.model.dnaZomb hatColor = style.lookupHatColor() geom = self.getGeomNode() geom.findAllMatches('**/hat_band*').setColorScale(hatColor) def generateClothesColor(self): style = self.style if self.zombie: style = self.model.dnaZomb clothesTopColor = style.lookupClothesTopColor() clothesBotColor = style.lookupClothesBotColor() geom = self.getGeomNode() geom.findAllMatches('**/clothing_layer1_shirt*').setColorScale(clothesTopColor[0]) geom.findAllMatches('**/clothing_layer2_vest*').setColorScale(clothesTopColor[1]) geom.findAllMatches('**/clothing_layer3_coat*').setColorScale(clothesTopColor[2]) geom.findAllMatches('**/clothing_layer1_pant*').setColorScale(clothesBotColor[0]) geom.findAllMatches('**/clothing_layer2_belt*').setColorScale(clothesBotColor[1]) geom.findAllMatches('**/clothing_layer1_shoe*').setColorScale(clothesBotColor[2]) def generateColor(self): self.generateSkinColor() self.generateHairColor() self.generateHatColor() def makeAnimDict(self, gender, animNames): self.animDict = [] for currAnim in animNames: anim = animNames.get(currAnim) for currAnimName in anim: self.animTable.append([ currAnimName, currAnimName]) self.reducedAnimList = self.animDict def forceLoadAnimDict(self): for anim in self.animDict: self.getAnimControls(anim[0]) def createAnimDict(self, customList = None): if self.gender == 'f': filePrefix = 'models/char/f' genderPrefix = 'f' else: filePrefix = 'models/char/m' genderPrefix = 'm' filePrefix += 'p' animList = self.reducedAnimList if animList is None: animList = AnimListDict[self.type] AnimDict.clear() for anim in animList: animSuffix = '' for customAnim in CustomAnimDict[genderPrefix + self.type]: if anim[0] == customAnim: animSuffix = '_' + genderPrefix + NewModelDict.get(self.type) break continue AnimDict[anim[0]] = filePrefix + '_' + anim[1] + animSuffix if self.reducedAnimList is None: AnimDict.pop('intro') return filePrefix def generateBody(self, copy = 1): filePrefix = self.createAnimDict() lodString = '2000' self.loadModel(filePrefix + '_' + lodString, 'modelRoot', '2000', copy) self.loadAnims(AnimDict, 'modelRoot', 'all') if loader.loadModel(filePrefix + '_' + '1000', allowInstance = True) != None: lodString = '1000' self.loadModel(filePrefix + '_' + lodString, 'modelRoot', '1000', copy) if loader.loadModel(filePrefix + '_' + '500', allowInstance = True) != None: lodString = '500' self.loadModel(filePrefix + '_' + lodString, 'modelRoot', '500', copy) self.makeSubpart('head', [ 'zz_head01'], []) self.makeSubpart('torso', [ 'zz_spine01'], [ 'zz_head01']) self.makeSubpart('legs', [ 'dx_root'], [ 'zz_spine01']) self.setSubpartsComplete(True) self.getWeaponJoints() self.eyeIrisTextures = loader.loadModel('models/misc/eye_iris.bam') def refreshBody(self): if self.style.getGender() == 'f': gender = 1 cjs = FemaleBodyShapeControlJoints matrix = FemaleBodyShapeControlJointMatrix else: gender = 0 cjs = MaleBodyShapeControlJoints matrix = MaleBodyShapeControlJointMatrix type = self.style.getBodyShape() filePrefix = self.createAnimDict() self.loadAnims(AnimDict, 'modelRoot', 'all') for jointName in cjs: joint = self.find('**/*' + jointName) vector = matrix[jointName][type] if jointName.find('def') != -1: joint.setScale(vector) continue joint.setPos(vector) self.headNode.setScale(HeadScales[gender][self.style.getBodyShape()]) self.setGlobalScale(self.calcBodyScale()) self.createAnimDict() self.stop(self.getCurrentAnim()) self.loop(self.getCurrentAnim()) def setLODs(self): self.setLODNode() avatarDetail = base.config.GetString('avatar-detail', 'high') if avatarDetail == 'high': dist = [ 0, 20, 80, 280] elif avatarDetail == 'med': dist = [ 0, 10, 40, 280] elif avatarDetail == 'low': dist = [ 0, 5, 20, 280] else: raise StandardError, 'Invalid avatar-detail: %s' % avatarDetail self.addLOD(2000, dist[1], dist[0]) self.addLOD(1000, dist[2], dist[1]) self.addLOD(500, dist[3], dist[2]) if self.optimizeLOD: lowLOD = self.getLOD('500') lowLOD.setTextureOff(1000) lowLOD.setTransparency(0, 1000) self.getLODNode().setCenter(Point3(0, 0, 5)) def showLOD(self, lodName): if not self.model.loaded: self.model.setupHead(lodName) self.model.setupBody(lodName) self.model.setupClothing(lodName) if self.master: self.model.setupSelectionChoices('NPC') self.model.loaded = 1 self.model.setFromDNA() self.generateEyesTexture() if self.optimizeLOD: self.optimizeLowLOD() self.generateColor() def loadHuman(self, gender = 'm', other = None): if other: pirate = other pirate.style = self.style else: pirate = self pirate.gender = gender if self.loaded: return None if pirate.gender == 'f': pirate.type = BodyDefs.femaleFrames[pirate.style.getBodyShape()] controlShapes = PirateFemale.ControlShapes sliderNames = PirateFemale.SliderNames else: pirate.type = BodyDefs.maleFrames[pirate.style.getBodyShape()] controlShapes = PirateMale.ControlShapes sliderNames = PirateMale.SliderNames if not pirate.loaded: pirate.setLODs() pirate.loadAnimatedHead = True pirate.generateBody() if pirate.gender == 'f': pirate.model = PirateFemale.PirateFemale(pirate, pirate.style) self.pirateFemale = PirateFemale.PirateFemale(pirate, pirate.style) else: pirate.model = PirateMale.PirateMale(pirate, pirate.style) self.pirateMale = PirateMale.PirateMale(pirate, pirate.style) if base.config.GetBool('debug-dynamic-human', 0): pirate.model.newAvatars = True else: pirate.model.newAvatars = False pirate.faceAwayFromViewer() pirate.fixEyes() else: pirate.model.dna = pirate.style pirate.reducedAnimList = self.reducedAnimList pirate.createAnimDict() pirate.loadAnims(AnimDict, 'modelRoot', 'all') self.lods = pirate.getLODNames() if pirate.gender == 'f': self.headFudgeHpr = Vec3(0, 0, 0) idx = 1 else: self.headFudgeHpr = Vec3(0, 0, 0) idx = 0 pirate.zombie = self.zombie pirate.showLOD(2000) pirate.loaded = 1 self.model = pirate.model if pirate.zombie: pirate.showZombie() else: pirate.showNormal() if hasattr(self, 'motionFSM'): self.motionFSM.setAvatar(self) self.controlShapes = controlShapes self.sliderNames = sliderNames if other: self.copyActor(other) self.fixEyes() self.copyHuman(other) self.undoExtraNodes() self.setupExtraNodes() self.applyBodyShaper() self.applyHeadShaper() if other: pirate.zombie = 0 pirate.showNormal() pirate.unloadAnims(AnimDict, None, None) pirate.removeAnimControlDict() pirate.reducedAnimList = None self.initializeMiscNodes() self.startBlink() def initializeMiscNodes(self): self.initializeNametag3d() self.initializeDropShadow() if self.getLOD('2000') == None: return None exposedHeadJoint = self.getLOD('2000').find('**/def_head01') if not exposedHeadJoint.isEmpty(): idx = 0 if self.gender == 'f': idx = 1 exposedHeadJoint.setScale(1) self.headNode.reparentTo(exposedHeadJoint) self.headNode.setScale(HeadScales[idx][self.style.getBodyShape()]) def undoControlJoints(self): self.getGeomNode().getParent().findAllMatches('def_*').detach() self.getGeomNode().getParent().findAllMatches('trs_*').detach() self.findAllMatches('def_*').detach() self.findAllMatches('trs_*').detach() def cleanupHuman(self, gender = 'm'): self.eyeFSM.request('off') self.undoExtraNodes() self.undoControlJoints() self.eyeLids = { } self.eyeBalls = { } self.eyeIris = { } self.flush() self.loaded = 0 self.master = 0 def generateHuman(self, gender = 'm', others = None): other = None if others: if gender == 'f': other = others[1] else: other = others[0] if other and not (other.master) and other.loaded: other.cleanupHuman() elif self.loaded: self.cleanupHuman() self.loadHuman(self.style.gender, other) if self.isLocal(): self.renderReflection = True self.setRenderReflection() self.disableMixing() self.enableMixing() generateHuman = quickProfile('loadHuman')(generateHuman) def getShadowJoint(self): return self def getNametagJoints(self): joints = [] for lodName in self.getLODNames(): bundle = self.getPartBundle('legs', lodName) joint = bundle.findChild('name_tag') if joint: joints.append(joint) continue return joints def _DynamicHuman__blinkOpenEyes(self, task): if self.eyeFSM.getCurrentState().getName() == 'closed': self.eyeFSM.request('open') r = self.randGen.random() if r < 0.10000000000000001: t = 0.20000000000000001 else: t = r * 4.0 + 1.0 taskMgr.doMethodLater(t, self._DynamicHuman__blinkCloseEyes, self._DynamicHuman__blinkName) return Task.done def _DynamicHuman__blinkCloseEyes(self, task): if self.eyeFSM.getCurrentState().getName() != 'open': taskMgr.doMethodLater(4.0, self._DynamicHuman__blinkCloseEyes, self._DynamicHuman__blinkName) else: self.eyeFSM.request('closed') taskMgr.doMethodLater(0.125, self._DynamicHuman__blinkOpenEyes, self._DynamicHuman__blinkName) return Task.done def startBlink(self): taskMgr.remove(self._DynamicHuman__blinkName) if self.eyeLids: self.openEyes() taskMgr.doMethodLater(self.randGen.random() * 4.0 + 1, self._DynamicHuman__blinkCloseEyes, self._DynamicHuman__blinkName) def stopBlink(self): taskMgr.remove(self._DynamicHuman__blinkName) if self.eyeLids: self.eyeFSM.request('open') def closeEyes(self): self.eyeFSM.request('closed') def openEyes(self): self.eyeFSM.request('open') def enterEyeFSMOff(self): pass def exitEyeFSMOff(self): pass def enterEyeFSMOpen(self): for lodName in self.getLODNames(): if not self.eyeLids[lodName].isEmpty(): self.eyeLids[lodName].hide() self.eyeBalls[lodName].show() self.eyeIris[lodName].show() continue def exitEyeFSMOpen(self): pass def enterEyeFSMClosed(self): return None for lodName in self.getLODNames(): if not self.eyeLids[lodName].isEmpty(): self.eyeLids[lodName].show() self.eyeBalls[lodName].hide() self.eyeIris[lodName].hide() continue def exitEyeFSMClosed(self): pass def setControlValue(self, r, name): if self.style.getGender() == 'f': matrixF = FemaleHeadShapeControlJointMatrix matrixI = FemaleHeadShapeInitialControlJointMatrix else: matrixF = MaleHeadShapeControlJointMatrix matrixI = MaleHeadShapeInitialControlJointMatrix shapes = self.controlShapes ctl = shapes[name] slider = ctl[0] if r < 0.0: if len(ctl) > 1: slider = ctl[1] for i in range(0, len(slider)): jointName = slider[i][0] jointCtls = self.findAllMatches(jointName) posI = matrixI[jointName][0] hprI = matrixI[jointName][1] sclI = matrixI[jointName][2] posF = VBase3(posI[0], posI[1], posI[2]) hprF = VBase3(hprI[0], hprI[1], hprI[2]) sclF = VBase3(sclI[0], sclI[1], sclI[2]) self.notify.debug('scv: %s initial %s' % (jointName, posI)) dr = slider[i][4] * r ctl[0][i][5] = dr posDelta = VBase3(0, 0, 0) hprDelta = VBase3(0, 0, 0) sclDelta = VBase3(0, 0, 0) for sliderIdx in xrange(0, len(matrixF[jointName])): sliderName = matrixF[jointName][sliderIdx] jointSet = shapes[sliderName][0] for jointIdx in xrange(0, len(jointSet)): if jointSet[jointIdx][0] == jointName: if jointSet[jointIdx][1] == TX: posDelta.setX(posDelta.getX() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == TY: posDelta.setY(posDelta.getY() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == TZ: posDelta.setZ(posDelta.getZ() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == RX: hprDelta.setX(hprDelta.getX() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == RY: hprDelta.setY(hprDelta.getY() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == RZ: hprDelta.setZ(hprDelta.getZ() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == SX: if r < 0.0: sclDelta.setX(sclDelta.getX() + jointSet[jointIdx][5] / jointSet[jointIdx][2]) else: sclDelta.setX(sclDelta.getX() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == SY: if r < 0.0: sclDelta.setY(sclDelta.getY() + jointSet[jointIdx][5] / jointSet[jointIdx][2]) else: sclDelta.setY(sclDelta.getY() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == SZ: if r < 0.0: sclDelta.setZ(sclDelta.getZ() + jointSet[jointIdx][5] / jointSet[jointIdx][2]) else: sclDelta.setZ(sclDelta.getZ() + jointSet[jointIdx][5]) else: self.notify.warning('scv:wrong element = %s' % jointSet[jointIdx][1]) jointSet[jointIdx][1] == TX self.notify.debug('scv: %s composite posDelta = %s' % (jointName, posDelta)) posF.setX(posI[0] + posDelta[0]) posF.setY(posI[1] + posDelta[1]) posF.setZ(posI[2] + posDelta[2]) self.notify.debug('scv: %s final posDelta%s' % (jointName, posF)) self.notify.debug('scv: %s composite hprDelta = %s' % (jointName, hprDelta)) hprF.setX(hprI[0] + hprDelta[0]) hprF.setY(hprI[1] + hprDelta[1]) hprF.setZ(hprI[2] + hprDelta[2]) self.notify.debug('scv: %s final hprDelta%s' % (jointName, hprF)) self.notify.debug('scv: %s composite sclDelta = %s' % (jointName, sclDelta)) sclF.setX(sclI[0] + sclDelta[0]) sclF.setY(sclI[1] + sclDelta[1]) sclF.setZ(sclI[2] + sclDelta[2]) self.notify.debug('scv: %s final sclDelta%s' % (jointName, sclF)) for j in range(0, jointCtls.getNumPaths()): jointCtl = jointCtls[j] jointCtl.setPosHprScale(posF, hprF, sclF) def applyBodyShaper(self): if self.style.getGender() == 'f': cjs = FemaleBodyShapeControlJoints matrix = FemaleBodyShapeControlJointMatrix else: cjs = MaleBodyShapeControlJoints matrix = MaleBodyShapeControlJointMatrix type = self.style.getBodyShape() for jointName in cjs: for lodName in self.getLODNames(): if lodName == '2000': joint = self.controlJoint(None, 'legs', jointName, lodName) continue joint = self.controlJoint(joint, 'legs', jointName, lodName) joint = self.find('**/*' + jointName) vector = matrix[jointName][type] if jointName.find('def') != -1: joint.setScale(vector) continue joint.setPos(vector) def undoBodyShaper(self): if self.style.getGender() == 'f': cjs = FemaleBodyShapeControlJoints else: cjs = MaleBodyShapeControlJoints def applyHeadShaper(self): self.createControlJoints() self.initHeadControlShapes() self.setHeadControlShapeValues() def undoHeadShaper(self): if self.style.getGender() == 'f': cjs = FemaleHeadShapeControlJoints else: cjs = MaleHeadShapeControlJoints def createControlJoints(self): if self.style.getGender() == 'f': cjs = FemaleHeadShapeControlJoints else: cjs = MaleHeadShapeControlJoints for jointName in cjs: for lodName in self.getLODNames(): if lodName == '2000': joint = self.controlJoint(None, 'legs', jointName, lodName) continue if lodName == '1000': continue continue if lodName == '500': continue continue def initHeadControlShapes(self): if self.style.getGender() == 'f': cjs = FemaleHeadShapeControlJoints matrixF = FemaleHeadShapeControlJointMatrix matrixI = FemaleHeadShapeInitialControlJointMatrix else: cjs = MaleHeadShapeControlJoints matrixF = MaleHeadShapeControlJointMatrix matrixI = MaleHeadShapeInitialControlJointMatrix if len(matrixF['initialized']) > 0: return None initializedMatrixI = len(matrixI['initialized']) initializedMatrixF = len(matrixF['initialized']) for jointName in cjs: transform = TransformState.makeMat(self.getJointTransform('legs', jointName, '2000')) pos = Vec3(transform.getPos()) hpr = Vec3(transform.getHpr()) scale = Vec3(transform.getScale()) matrixI[jointName].append(pos) matrixI[jointName].append(hpr) matrixI[jointName].append(scale) matrixI['initialized'].append('initialized') shapes = self.controlShapes names = self.sliderNames for i in xrange(0, len(shapes)): slider = shapes[names[i]] for k in xrange(0, len(slider[0])): slider[0][k][4] = slider[0][k][2] if len(slider) > 1: slider[1][k][4] = slider[1][k][2] continue for i in xrange(0, len(shapes)): slider = shapes[names[i]] for k in xrange(0, len(slider[0])): jointCtl = slider[0][k] jointName = jointCtl[0] matrixF[jointName].append(names[i]) pos = matrixI[jointName][0] hpr = matrixI[jointName][1] scl = matrixI[jointName][2] if jointCtl[1] < 3: posDelta = jointCtl[4] - pos[jointCtl[1]] jointCtl[4] = posDelta if len(slider) > 1: jointCtl = slider[1][k] jointCtl[4] = posDelta len(slider) > 1 if jointCtl[1] > 2 and jointCtl[1] < 6: hprDelta = jointCtl[4] - hpr[jointCtl[1] - 3] jointCtl[4] = hprDelta if len(slider) > 1: jointCtl = slider[1][k] jointCtl[4] = hprDelta len(slider) > 1 sclDelta = jointCtl[4] - scl[jointCtl[1] - 6] jointCtl[4] = sclDelta if len(slider) > 1: jointCtl = slider[1][k] jointCtl[4] = sclDelta continue matrixF['initialized'].append('initialized') def setHeadControlShapeValues_old(self): value = self.style.getHeadSize() mappedValue = 0.90000000000000002 + (1 + value) * 0.10000000000000001 self.extraNode.setScale(2 - mappedValue, mappedValue, 1) self.setControlValue(self.style.getHeadWidth(), 'headWidth') self.setControlValue(self.style.getHeadHeight(), 'headHeight') self.setControlValue(self.style.getHeadRoundness(), 'headRoundness') self.setControlValue(self.style.getJawWidth(), 'jawWidth') self.setControlValue(self.style.getJawAngle(), 'jawChinAngle') self.setControlValue(self.style.getJawChinSize(), 'jawChinSize') self.setControlValue(self.style.getJawLength(), 'jawLength') self.setControlValue(self.style.getMouthWidth(), 'mouthWidth') self.setControlValue(self.style.getMouthLipThickness(), 'mouthLipThickness') self.setControlValue(self.style.getCheekFat(), 'cheekFat') self.setControlValue(self.style.getBrowProtruding(), 'browProtruding') self.setControlValue(self.style.getEyeCorner(), 'eyeCorner') self.setControlValue(self.style.getEyeOpeningSize(), 'eyeOpeningSize') self.setControlValue(self.style.getEyeBulge(), 'eyeSpacing') self.setControlValue(self.style.getNoseBridgeWidth(), 'noseBridgeWidth') self.setControlValue(self.style.getNoseNostrilWidth(), 'noseNostrilWidth') self.setControlValue(self.style.getNoseLength(), 'noseLength') self.setControlValue(self.style.getNoseBump(), 'noseBump') self.setControlValue(self.style.getNoseNostrilHeight(), 'noseNostrilHeight') self.setControlValue(self.style.getNoseNostrilAngle(), 'noseNostrilAngle') self.setControlValue(self.style.getNoseBridgeBroke(), 'noseBridgeBroke') self.setControlValue(self.style.getNoseNostrilBroke(), 'noseNostrilBroke') self.setControlValue(self.style.getEarScale(), 'earScale') self.setControlValue(self.style.getEarFlapAngle(), 'earFlap') self.setControlValue(self.style.getEarPosition(), 'earPosition') def getGlobalScale(self): return self.scaleNode.getScale() def setGlobalScale(self, scale): self.scaleNode.setScale(scale) self.scaleNode.setZ(-(self.floorOffsetZ * (1 - scale))) def calcBodyScale(self): idx = 0 if self.gender == 'f': idx = 1 mappedValue = (0.80000000000000004 + (1 + self.style.getBodyHeight()) * 0.20000000000000001) * BodyScales[idx][self.style.getBodyShape()] return mappedValue def showZombie(self): self.model.irises.stash() self.model.faces[0].stash() self.model.faceZomb.unstash() self.generateSkinTexture() def showNormal(self): self.model.irises.unstash() self.model.faces[0].unstash() self.model.faceZomb.stash() self.generateSkinTexture() def takeAwayTexture(self, geoms, omitFace = False): emptyRenderState = RenderState.makeEmpty() eyeIrisColor = VBase4(0, 0, 0, 1) for i in range(0, geoms.getNumPaths()): element = geoms[i] if 'eye_iris' in element.getName(): element.setColorScale(eyeIrisColor) elif omitFace and 'master_face' in element.getName(): continue element.setTextureOff() geom = element.node() for j in range(0, geom.getNumGeoms()): geom.setGeomState(j, emptyRenderState) def optimizeMedLOD(self): medLOD = self.getLOD('1000') geoms = medLOD.findAllMatches('**/teeth*') geoms.stash() self.medSkinGone = False geoms = medLOD.find('**/body_forearm*') if geoms.isEmpty(): self.medSkinGone = True geoms = medLOD.findAllMatches('**/body_*') self.takeAwayTexture(geoms, True) geoms = medLOD.findAllMatches('**/hair_*') self.takeAwayTexture(geoms) if self.gender != 'f': geoms = medLOD.findAllMatches('**/beard_*') self.takeAwayTexture(geoms) geoms = medLOD.findAllMatches('**/mustache_*') self.takeAwayTexture(geoms) geoms = medLOD.findAllMatches('**/eye_*') self.takeAwayTexture(geoms) geoms = medLOD.findAllMatches('**/clothing_layer2_belt_*') self.takeAwayTexture(geoms) geoms = medLOD.findAllMatches('**/clothing_layer1_shoe_*') self.takeAwayTexture(geoms) def optimizeLowLOD(self): lowLOD = self.getLOD('500') geoms = lowLOD.findAllMatches('**/teeth*') geoms.stash() geoms = lowLOD.findAllMatches('**/+GeomNode') self.takeAwayTexture(geoms) def setHeadControlShapeValues(self): value = self.style.getHeadSize() mappedValue = 0.90000000000000002 + (1 + value) * 0.10000000000000001 self.extraNode.setScale(2 - mappedValue, mappedValue, 1) self.setControlValue_new(self.style.getHeadWidth(), 'headWidth') self.setControlValue_new(self.style.getHeadHeight(), 'headHeight') self.setControlValue_new(self.style.getHeadRoundness(), 'headRoundness') self.setControlValue_new(self.style.getJawWidth(), 'jawWidth') self.setControlValue_new(self.style.getJawAngle(), 'jawChinAngle') self.setControlValue_new(self.style.getJawChinSize(), 'jawChinSize') self.setControlValue_new(self.style.getJawLength(), 'jawLength') self.setControlValue_new(self.style.getMouthWidth(), 'mouthWidth') self.setControlValue_new(self.style.getMouthLipThickness(), 'mouthLipThickness') self.setControlValue_new(self.style.getCheekFat(), 'cheekFat') self.setControlValue_new(self.style.getBrowProtruding(), 'browProtruding') self.setControlValue_new(self.style.getEyeCorner(), 'eyeCorner') self.setControlValue_new(self.style.getEyeOpeningSize(), 'eyeOpeningSize') self.setControlValue_new(self.style.getEyeBulge(), 'eyeSpacing') self.setControlValue_new(self.style.getNoseBridgeWidth(), 'noseBridgeWidth') self.setControlValue_new(self.style.getNoseNostrilWidth(), 'noseNostrilWidth') self.setControlValue_new(self.style.getNoseLength(), 'noseLength') self.setControlValue_new(self.style.getNoseBump(), 'noseBump') self.setControlValue_new(self.style.getNoseNostrilHeight(), 'noseNostrilHeight') self.setControlValue_new(self.style.getNoseNostrilAngle(), 'noseNostrilAngle') self.setControlValue_new(self.style.getNoseBridgeBroke(), 'noseBridgeBroke') self.setControlValue_new(self.style.getNoseNostrilBroke(), 'noseNostrilBroke') self.setControlValue_new(self.style.getEarScale(), 'earScale') self.setControlValue_new(self.style.getEarFlapAngle(), 'earFlap') self.setControlValue_new(self.style.getEarPosition(), 'earPosition') self.postProcess_setHeadControlShapeValues() def setControlValue_new(self, r, name): ctl = self.controlShapes[name] zeroindex = ctl[0] sliders = zeroindex if r < 0.0: if len(ctl) > 1: sliders = ctl[1] for i in range(0, len(sliders)): zeroindex[i][5] = sliders[i][4] * r def postProcess_setHeadControlShapeValues(self): if self.style.getGender() == 'f': cjs = FemaleHeadShapeControlJoints matrixF = FemaleHeadShapeControlJointMatrix matrixI = FemaleHeadShapeInitialControlJointMatrix else: cjs = MaleHeadShapeControlJoints matrixF = MaleHeadShapeControlJointMatrix matrixI = MaleHeadShapeInitialControlJointMatrix posDelta = VBase3() hprDelta = VBase3() sclDelta = VBase3() fdict2 = { 0: posDelta.addX, 1: posDelta.addY, 2: posDelta.addZ, 3: hprDelta.addX, 4: hprDelta.addY, 5: hprDelta.addZ, 6: sclDelta.addX, 7: sclDelta.addY, 8: sclDelta.addZ } for jointName in cjs: posDelta.assign(matrixI[jointName][0]) hprDelta.assign(matrixI[jointName][1]) sclDelta.assign(matrixI[jointName][2]) for sliderIdx in xrange(0, len(matrixF[jointName])): sliderName = matrixF[jointName][sliderIdx] jointSet = self.controlShapes[sliderName][0] for sliderJoint in jointSet: if sliderJoint[0] == jointName: fdict2[sliderJoint[1]](sliderJoint[5]) continue self.find(jointName).setPosHprScale(posDelta, hprDelta, sclDelta)
class MasterHuman(HumanBase.HumanBase, Biped.Biped): notify = DirectNotifyGlobal.directNotify.newCategory('Human') prebuiltAnimData = { } def __init__(self, other = None): Biped.Biped.__init__(self, other, HumanAnimationMixer) self.model = None self.useFaceTex = True self.joints = { } self.jointTrans = { } self.jointTrans2 = { } self.zombie = False self.crazyColorSkin = False self.crazyColorSkinIndex = 0 self.flattenPending = None self.optimizeLOD = base.config.GetBool('optimize-avatar-lod', 1) self.master = 0 self.loaded = 0 self.playingRate = None self.shadowFileName = 'models/misc/drop_shadow' self.setFont(PiratesGlobals.getInterfaceFont()) self._MasterHuman__blinkName = 'blink-' + str(self.this) self.eyeLids = None self.eyeBalls = None self.eyeIris = None self.reducedAnimList = None self.rootScale = 1.0 self.headNode = None self.extraNode = None self.scaleNode = None self.rootNode = None self.floorOffsetZ = 0.0 self.headFudgeHpr = Vec3(0, 0, 0) self.frozeSomething = True self.randGen = random.Random() self.randGen.seed(random.random()) self.eyeFSM = ClassicFSM('eyeFSM', [ State('off', self.enterEyeFSMOff, self.exitEyeFSMOff, [ 'open', 'closed']), State('open', self.enterEyeFSMOpen, self.exitEyeFSMOpen, [ 'closed', 'off']), State('closed', self.enterEyeFSMClosed, self.exitEyeFSMClosed, [ 'open', 'off'])], 'off', 'off') self.eyeFSM.enterInitialState() if other != None: self.copyHuman(other) self.isPaid = False def removeCopiedNodes(self): self.dropShadow = self.find('**/drop_shadow*') if not self.dropShadow.isEmpty(): self.deleteDropShadow() else: self.dropShadow = None def flattenHuman(self): self.deleteNametag3d() self.getWeaponJoints() def _MasterHuman__doneFlattenHuman(self, models): self.flattenPending = None self.getWeaponJoints() def copyHuman(self, other): self.gender = other.gender self.loaded = other.loaded self.type = other.type self.loadAnimatedHead = other.loadAnimatedHead self.model = None def delete(self): try: pass except: self.Human_deleted = 1 taskMgr.remove(self._MasterHuman__blinkName) if self.dropShadow and not self.dropShadow.isEmpty(): self.deleteDropShadow() del self.eyeFSM self.controlShapes = None self.sliderNames = None if self.model: self.model.delete() del self.model Biped.Biped.delete(self) def isDeleted(self): try: if self.Human_deleted == 1: return True except: return False def fixEyes(self): self.eyeLids = { } self.eyeBalls = { } self.eyeIris = { } for lodName in self.getLODNames(): geom = self.getPart('head', lodName) self.eyeLids[lodName] = geom.findAllMatches('**/*eyelid*') self.eyeBalls[lodName] = geom.findAllMatches('**/eye_ball*') self.eyeIris[lodName] = geom.findAllMatches('**/eye_iris*') self.eyeLids[lodName].stash() self.eyeBalls[lodName].unstash() self.eyeIris[lodName].unstash() def getCrazyColorSkinIndex(self): return self.crazyColorSkinIndex def setCrazyColorSkinIndex(self, index): if len(HumanDNA.crazySkinColors) > index: self.crazyColorSkinIndex = index else: self.notify.warning('(MasterHuman)index: %d is out of bounds for crazyColorSkin: %d' % (index, len(HumanDNA.crazySkinColors))) def generateSkinColor(self): skinColor = self.style.getSkinColor() lowColor = self.model.lowLODSkinColor color = VBase4(lowColor[0] * skinColor[0], lowColor[1] * skinColor[1], lowColor[2] * skinColor[2], 1.0) self.model.faces[0].setColorScale(skinColor) if self.model.newAvatars: self.model.currentBody.setColorScale(skinColor) if self.optimizeLOD: self.model.currentBody[2].setColorScale(color) self.model.faces[0][2].setColorScale(color) else: numPaths = self.model.body.getNumPaths() medIdx = numPaths / 3 lowIdx = (numPaths / 3) * 2 if self.zombie: self.model.body.setColorScale(Vec4(1, 1, 1, 1)) if self.optimizeLOD: color = VBase4(121 / 255.0, 124 / 255.0, 103 / 255.0, 1.0) for i in xrange(lowIdx, numPaths): self.model.body[i].setColorScale(color) self.model.faceZomb[2].setColorScale(color) else: self.model.body.setColorScale(skinColor) lowColor = self.model.lowLODSkinColor if self.optimizeLOD: color = VBase4(lowColor[0] * skinColor[0], lowColor[1] * skinColor[1], lowColor[2] * skinColor[2], 1.0) for i in xrange(lowIdx, numPaths): self.model.body[i].setColorScale(color) def generateSkinTexture(self): bodyTextureIdx = self.style.body.skin if self.zombie: if self.gender == 'f': bodyTextureIdx = PirateFemale.ZOMB_BODY_TEXTURE else: bodyTextureIdx = PirateMale.ZOMB_BODY_TEXTURE if self.gender == 'f': body_textures = PirateFemale.body_textures[self.style.body.shape] else: body_textures = PirateMale.body_textures[0] #self.style.body.shape] tex_name = self.getTrySafe(body_textures, bodyTextureIdx) if tex_name != None: tex = self.model.bodyTextures.findTexture(tex_name) else: return None if tex: for parts in self.model.bodys: numPaths = parts.getNumPaths() for i in xrange(numPaths): parts[i].setTexture(tex, 1) def generateFaceTexture(self, default): if default: faceTextureIdx = 0 else: faceTextureIdx = self.style.head.texture if faceTextureIdx >= len(self.model.faceTexturesSet): faceTextureIdx = 0 self.model.faces[0].setTexture(self.model.faceTexturesSet[faceTextureIdx]) def generateHairColor(self, colorName = None, colorModel = None): self.model.setHairBaseColor() def getTrySafe(self, list, idx): try: if type(idx) == str: lookup = idx.split('_cut')[0] else: lookup = idx return list[lookup] except: return None def generateEyesTexture(self): eyesTextureIdx = self.style.head.eyes.color if self.gender == 'f': eye_iris_textures = PirateFemale.eye_iris_textures else: eye_iris_textures = PirateMale.eye_iris_textures tex_name = self.getTrySafe(eye_iris_textures, eyesTextureIdx) if tex_name != None: tex = self.eyeIrisTextures.findTexture(tex_name) else: return None if tex: self.model.irises.setTexture(tex, 1) def generateHatColor(self): style = self.model.dna if self.zombie: style = self.model.dnaZomb hatColor = style.lookupHatColor() geom = self.getGeomNode() parts = geom.findAllMatches('**/hat_band*') parts.setColorScale(hatColor) def generateClothesColor(self): style = self.model.dna if self.zombie: style = self.model.dnaZomb clothesTopColor = style.lookupClothesTopColor() clothesBotColor = style.lookupClothesBotColor() geom = self.getGeomNode() if self.optimizeLOD: def tempColorParts(parts, ct): numPaths = parts.getNumPaths() lowIdx = (numPaths / 3) * 2 for j in xrange(lowIdx): parts[j].setColorScale(ct) for j in xrange(lowIdx, numPaths): cl = parts[j].getColorScale() compoundColor = VBase4(cl[0] * ct[0], cl[1] * ct[1], cl[2] * ct[2], 1.0) parts[j].setColorScale(compoundColor) else: def tempColorParts(parts, ct): parts.setColorScale(ct) colorParts = tempColorParts parts = geom.findAllMatches('**/clothing_layer1_shirt*') colorParts(parts, clothesTopColor[0]) parts = geom.findAllMatches('**/clothing_layer2_vest*') colorParts(parts, clothesTopColor[1]) parts = geom.findAllMatches('**/clothing_layer3_coat*') colorParts(parts, clothesTopColor[2]) parts = geom.findAllMatches('**/clothing_layer1_pant*') colorParts(parts, clothesBotColor[0]) del colorParts def generateTexture(self): self.generateFaceTexture(not (self.useFaceTex)) self.generateEyesTexture() def generateColor(self): self.generateSkinColor() self.generateHairColor() self.generateHatColor() def makeAnimDict(self, gender, animNames): self.animTable = [] for currAnim in animNames: anim = animNames.get(currAnim) for currAnimName in anim: self.animTable.append([ currAnimName, currAnimName]) self.reducedAnimList = self.animTable def forceLoadAnimDict(self): for anim in self.animTable: self.getAnimControls(anim[0]) def createAnimDict(self, customList = None): if self.reducedAnimList is None: self.animDict = self.prebuiltAnimData[self.gender + self.type] return None if self.gender == 'f': filePrefix = 'models/char/f' genderPrefix = 'f' else: filePrefix = 'models/char/m' genderPrefix = 'm' filePrefix += 'p' animList = self.reducedAnimList if animList is None: animList = AnimListDict[self.type] self.animDict = { } for anim in animList: animSuffix = '' for i in range(0, len(CustomAnimDict[genderPrefix + self.type])): if anim[0] == CustomAnimDict[genderPrefix + self.type][i]: animSuffix = '_' + genderPrefix + NewModelDict.get(self.type) break continue self.animDict[anim[0]] = filePrefix + '_' + anim[1] + animSuffix if self.reducedAnimList is None: self.animDict.pop('intro') return filePrefix def generateBody(self, copy = 1): if self.gender == 'm': filePrefix = 'models/char/mp' else: filePrefix = 'models/char/fp' messenger.send('tick') lodString = '2000' self.loadModel(filePrefix + '_' + lodString, 'modelRoot', '2000', copy) messenger.send('tick') if loader.loadModel(filePrefix + '_' + '1000', allowInstance = True) != None: lodString = '1000' self.loadModel(filePrefix + '_' + lodString, 'modelRoot', '1000', copy) messenger.send('tick') if loader.loadModel(filePrefix + '_' + '500', allowInstance = True) != None: lodString = '500' self.loadModel(filePrefix + '_' + lodString, 'modelRoot', '500', copy) messenger.send('tick') self.makeSubpart('head', [ 'zz_head01'], []) self.makeSubpart('torso', [ 'zz_spine01'], [ 'zz_head01']) self.makeSubpart('legs', [ 'dx_root'], [ 'zz_spine01']) self.setSubpartsComplete(True) self.eyeIrisTextures = loader.loadModel('models/misc/eye_iris.bam') def setLODs(self): self.setLODNode() avatarDetail = base.config.GetString('avatar-detail', 'high') if avatarDetail == 'high': dist = [ 0, 20, 80, 1000000000] elif avatarDetail == 'med': dist = [ 0, 10, 20, 1000000000] elif avatarDetail == 'low': dist = [ 0, 0, 10, 1000000000] else: raise StandardError, 'Invalid avatar-detail: %s' % avatarDetail self.addLOD(2000, dist[1], dist[0]) self.addLOD(1000, dist[2], dist[1]) self.addLOD(500, dist[3], dist[2]) if self.optimizeLOD: lowLOD = self.getLOD('500') lowLOD.setTransparency(0, 1000) self.getLODNode().setCenter(Point3(0, 0, 5)) def showLOD(self, lodName): self.generateTexture() self.model.setFromDNA() tex = self.model.faces[0][2].findTexture('*face*') def loadHuman(self, gender = 'm', other = None): self.gender = gender if self.gender == 'f': controlShapes = PirateFemale.ControlShapes sliderNames = PirateFemale.SliderNames else: controlShapes = PirateMale.ControlShapes sliderNames = PirateMale.SliderNames self.setLODs() self.loadAnimatedHead = True self.generateBody() if self.gender == 'f': self.type = BodyDefs.femaleFrames[self.style.getBodyShape()] self.model = PirateFemale.PirateFemale(self, self.style) else: self.type = BodyDefs.maleFrames[self.style.getBodyShape()] self.model = PirateMale.PirateMale(self, self.style) self.faceAwayFromViewer() self.lods = self.getLODNames() if self.gender == 'f': self.headFudgeHpr = Vec3(0, 0, 0) idx = 1 else: self.headFudgeHpr = Vec3(0, 0, 0) idx = 0 messenger.send('tick') self.model.setupHead(2000) messenger.send('tick') self.model.setupBody(2000) messenger.send('tick') self.model.setupClothing(2000) messenger.send('tick') if self.master: self.model.setupSelectionChoices('NPC') self.showNormal() self.createAnimDict() messenger.send('tick') self.initAnimsOnAllLODs([ 'head', 'legs', 'torso', 'modelRoot']) messenger.send('tick') self.controlShapes = controlShapes self.sliderNames = sliderNames self.initHeadControlShapes() self.storeJoints() self.find('**/nametag3d').detachNode() self.findAllMatches('**/name_tag').detach() self.rootNode = self.getLOD('2000').find('**/dx_root') self.floorOffsetZ = self.rootNode.getZ() messenger.send('tick') root = self.getLOD('500') gr = SceneGraphReducer() gr.applyAttribs(root.node(), gr.TTTransform | gr.TTTexMatrix | gr.TTOther) gr.makeCompatibleFormat(root.node(), 0) gr.premunge(root.node(), RenderState.makeEmpty()) gr.decompose(root.node()) stashedSet = root.findAllMatches('**/@@*') stashedSet.unstash() gr.makeCompatibleFormat(root.node(), 0) stashedSet.stash() messenger.send('tick') for face in self.model.faces[0]: node = face.node() for i in range(node.getNumGeoms()): face.node().setGeomState(i, RenderState.makeEmpty()) def initializeMiscNodes(self): self.initializeNametag3d() self.initializeDropShadow() if self.getLOD('2000') == None: return None exposedHeadJoint = self.getLOD('2000').find('**/def_head01') if not exposedHeadJoint.isEmpty(): idx = 0 if self.gender == 'f': idx = 1 exposedHeadJoint.setScale(1) self.headNode.reparentTo(exposedHeadJoint) self.headNode.setScale(HeadScales[idx][self.style.getBodyShape()]) def undoControlJoints(self): self.getGeomNode().getParent().findAllMatches('def_*').detach() self.getGeomNode().getParent().findAllMatches('trs_*').detach() self.findAllMatches('def_*').detach() self.findAllMatches('trs_*').detach() def cleanupHuman(self, gender = 'm'): self.eyeFSM.request('off') self.undoControlJoints() self.eyeLids = { } self.eyeBalls = { } self.eyeIris = { } self.flush() self.loaded = 0 self.master = 0 def generateHuman(self, gender = 'm'): self.loadHuman(self.style.gender) def getShadowJoint(self): return self def getNametagJoints(self): joints = [] for lodName in self.getLODNames(): bundle = self.getPartBundle('legs', lodName) joint = bundle.findChild('name_tag') if joint: joints.append(joint) continue return joints def _MasterHuman__blinkOpenEyes(self, task): if self.eyeFSM.getCurrentState().getName() == 'closed': self.eyeFSM.request('open') r = self.randGen.random() if r < 0.10000000000000001: t = 0.20000000000000001 else: t = r * 4.0 + 1.0 taskMgr.doMethodLater(t, self._MasterHuman__blinkCloseEyes, self._MasterHuman__blinkName) return Task.done def _MasterHuman__blinkCloseEyes(self, task): if self.eyeFSM.getCurrentState().getName() != 'open': taskMgr.doMethodLater(4.0, self._MasterHuman__blinkCloseEyes, self._MasterHuman__blinkName) else: self.eyeFSM.request('closed') taskMgr.doMethodLater(0.125, self._MasterHuman__blinkOpenEyes, self._MasterHuman__blinkName) return Task.done def startBlink(self): taskMgr.remove(self._MasterHuman__blinkName) if self.eyeLids: self.openEyes() taskMgr.doMethodLater(self.randGen.random() * 4.0 + 1, self._MasterHuman__blinkCloseEyes, self._MasterHuman__blinkName) def stopBlink(self): taskMgr.remove(self._MasterHuman__blinkName) if self.eyeLids: self.eyeFSM.request('open') def closeEyes(self): self.eyeFSM.request('closed') def openEyes(self): self.eyeFSM.request('open') def enterEyeFSMOff(self): pass def exitEyeFSMOff(self): pass def enterEyeFSMOpen(self): for lodName in self.getLODNames(): if not self.eyeLids[lodName].isEmpty(): self.eyeLids[lodName].hide() self.eyeBalls[lodName].show() self.eyeIris[lodName].show() continue def exitEyeFSMOpen(self): pass def enterEyeFSMClosed(self): return None for lodName in self.getLODNames(): if not self.eyeLids[lodName].isEmpty(): self.eyeLids[lodName].show() self.eyeBalls[lodName].hide() self.eyeIris[lodName].hide() continue def exitEyeFSMClosed(self): pass def setControlValue(self, r, name): if self.style.getGender() == 'f': matrixF = FemaleHeadShapeControlJointMatrix matrixI = FemaleHeadShapeInitialControlJointMatrix else: matrixF = MaleHeadShapeControlJointMatrix matrixI = MaleHeadShapeInitialControlJointMatrix shapes = self.controlShapes ctl = shapes[name] slider = ctl[0] if r < 0.0: if len(ctl) > 1: slider = ctl[1] for i in range(0, len(slider)): jointName = slider[i][0] jointCtls = self.findAllMatches(jointName) posI = matrixI[jointName][0] hprI = matrixI[jointName][1] sclI = matrixI[jointName][2] posF = VBase3(posI[0], posI[1], posI[2]) hprF = VBase3(hprI[0], hprI[1], hprI[2]) sclF = VBase3(sclI[0], sclI[1], sclI[2]) self.notify.debug('scv: %s initial %s' % (jointName, posI)) dr = slider[i][4] * r ctl[0][i][5] = dr posDelta = VBase3(0, 0, 0) hprDelta = VBase3(0, 0, 0) sclDelta = VBase3(0, 0, 0) for sliderIdx in xrange(0, len(matrixF[jointName])): sliderName = matrixF[jointName][sliderIdx] jointSet = shapes[sliderName][0] for jointIdx in xrange(0, len(jointSet)): if jointSet[jointIdx][0] == jointName: if jointSet[jointIdx][1] == TX: posDelta.setX(posDelta.getX() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == TY: posDelta.setY(posDelta.getY() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == TZ: posDelta.setZ(posDelta.getZ() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == RX: hprDelta.setX(hprDelta.getX() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == RY: hprDelta.setY(hprDelta.getY() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == RZ: hprDelta.setZ(hprDelta.getZ() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == SX: if r < 0.0: sclDelta.setX(sclDelta.getX() + jointSet[jointIdx][5] / jointSet[jointIdx][2]) else: sclDelta.setX(sclDelta.getX() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == SY: if r < 0.0: sclDelta.setY(sclDelta.getY() + jointSet[jointIdx][5] / jointSet[jointIdx][2]) else: sclDelta.setY(sclDelta.getY() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == SZ: if r < 0.0: sclDelta.setZ(sclDelta.getZ() + jointSet[jointIdx][5] / jointSet[jointIdx][2]) else: sclDelta.setZ(sclDelta.getZ() + jointSet[jointIdx][5]) else: self.notify.warning('scv:wrong element = %s' % jointSet[jointIdx][1]) jointSet[jointIdx][1] == TX self.notify.debug('scv: %s composite posDelta = %s' % (jointName, posDelta)) posF.setX(posI[0] + posDelta[0]) posF.setY(posI[1] + posDelta[1]) posF.setZ(posI[2] + posDelta[2]) self.notify.debug('scv: %s final posDelta%s' % (jointName, posF)) self.notify.debug('scv: %s composite hprDelta = %s' % (jointName, hprDelta)) hprF.setX(hprI[0] + hprDelta[0]) hprF.setY(hprI[1] + hprDelta[1]) hprF.setZ(hprI[2] + hprDelta[2]) self.notify.debug('scv: %s final hprDelta%s' % (jointName, hprF)) self.notify.debug('scv: %s composite sclDelta = %s' % (jointName, sclDelta)) sclF.setX(sclI[0] + sclDelta[0]) sclF.setY(sclI[1] + sclDelta[1]) sclF.setZ(sclI[2] + sclDelta[2]) self.notify.debug('scv: %s final sclDelta%s' % (jointName, sclF)) for j in range(0, jointCtls.getNumPaths()): jointCtl = jointCtls[j] jointCtl.setPosHprScale(posF, hprF, sclF) def applyBodyShaper(self): if self.style.getGender() == 'f': tjs = FemaleBodyShapeTranslateJoints sjs = FemaleBodyShapeScaleJoints matrix = FemaleBodyShapeControlJointMatrix else: tjs = MaleBodyShapeTranslateJoints sjs = MaleBodyShapeScaleJoints matrix = MaleBodyShapeControlJointMatrix type = 0 #self.style.getBodyShape() for jointName in tjs: transData = self.jointTrans[jointName] vector = matrix[jointName][type] self.joints[jointName].applyFreezeMatrix(vector, transData[1], transData[2]) for jointName in sjs: transData = self.jointTrans[jointName] vector = matrix[jointName][type] self.joints[jointName].applyFreezeMatrix(transData[0], transData[1], vector) value = self.style.getHeadSize() mappedValue = 0.90000000000000002 + (1 + value) * 0.10000000000000001 transData = self.jointTrans['def_extra_jt'] self.joints['def_extra_jt'].applyFreezeMatrix(transData[0], transData[1], Vec3(2 - mappedValue, mappedValue, 1)) transData = self.jointTrans['def_head01'] idx = 0 if self.style.gender == 'f': idx = 1 self.joints['def_head01'].applyFreezeMatrix(transData[0], transData[1], Vec3(HeadScales[idx][0])) #self.style.getBodyShape()])) self.setGlobalScale(self.calcBodyScale()) def undoBodyShaper(self): if self.style.getGender() == 'f': cjs = FemaleBodyShapeControlJoints else: cjs = MaleBodyShapeControlJoints def applyHeadShaper(self): self.setHeadControlShapeValues() def undoHeadShaper(self): if self.style.getGender() == 'f': cjs = FemaleHeadShapeControlJoints else: cjs = MaleHeadShapeControlJoints def createControlJoints(self): if self.style.getGender() == 'f': cjs = FemaleHeadShapeControlJoints else: cjs = MaleHeadShapeControlJoints for jointName in cjs: for lodName in self.getLODNames(): if lodName == '2000': joint = self.controlJoint(None, 'legs', jointName, lodName) continue if lodName == '1000': continue continue if lodName == '500': continue continue def initHeadControlShapes(self): if self.style.getGender() == 'f': cjs = FemaleHeadShapeControlJoints matrixF = FemaleHeadShapeControlJointMatrix matrixI = FemaleHeadShapeInitialControlJointMatrix matrixIHelper = FemaleHeadInitHelper else: cjs = MaleHeadShapeControlJoints matrixF = MaleHeadShapeControlJointMatrix matrixI = MaleHeadShapeInitialControlJointMatrix matrixIHelper = MaleHeadInitHelper if len(matrixF['initialized']) > 0: return None initializedMatrixI = len(matrixI['initialized']) initializedMatrixF = len(matrixF['initialized']) for jointName in cjs: transform = TransformState.makeMat(self.getJointTransform('legs', jointName, '2000')) pos = Vec3(transform.getPos()) hpr = Vec3(transform.getHpr()) scale = Vec3(transform.getScale()) matrixI[jointName].append(pos) matrixI[jointName].append(hpr) matrixI[jointName].append(scale) matrixIHelper[jointName] = [ pos[0], pos[1], pos[2], hpr[0], hpr[1], hpr[2], scale[0], scale[1], scale[2]] matrixI['initialized'].append('initialized') shapes = self.controlShapes names = self.sliderNames for i in xrange(0, len(shapes)): slider = shapes[names[i]] for k in xrange(0, len(slider[0])): slider[0][k][4] = slider[0][k][2] if len(slider) > 1: slider[1][k][4] = slider[1][k][2] continue for i in xrange(0, len(shapes)): slider = shapes[names[i]] for k in xrange(0, len(slider[0])): jointCtl = slider[0][k] jointName = jointCtl[0] matrixF[jointName].append(names[i]) pos = matrixI[jointName][0] hpr = matrixI[jointName][1] scl = matrixI[jointName][2] if jointCtl[1] < 3: posDelta = jointCtl[4] - pos[jointCtl[1]] jointCtl[4] = posDelta if len(slider) > 1: jointCtl = slider[1][k] jointCtl[4] = posDelta len(slider) > 1 if jointCtl[1] > 2 and jointCtl[1] < 6: hprDelta = jointCtl[4] - hpr[jointCtl[1] - 3] jointCtl[4] = hprDelta if len(slider) > 1: jointCtl = slider[1][k] jointCtl[4] = hprDelta len(slider) > 1 sclDelta = 12 #jointCtl[4] - scl[jointCtl[1] - 6] jointCtl[4] = sclDelta if len(slider) > 1: jointCtl = slider[1][k] jointCtl[4] = sclDelta continue matrixF['initialized'].append('initialized') def setHeadControlShapeValues_old(self): value = self.style.getHeadSize() mappedValue = 0.90000000000000002 + (1 + value) * 0.10000000000000001 self.setControlValue(self.style.getHeadWidth(), 'headWidth') self.setControlValue(self.style.getHeadHeight(), 'headHeight') self.setControlValue(self.style.getHeadRoundness(), 'headRoundness') self.setControlValue(self.style.getJawWidth(), 'jawWidth') self.setControlValue(self.style.getJawAngle(), 'jawChinAngle') self.setControlValue(self.style.getJawChinSize(), 'jawChinSize') self.setControlValue(self.style.getJawLength(), 'jawLength') self.setControlValue(self.style.getMouthWidth(), 'mouthWidth') self.setControlValue(self.style.getMouthLipThickness(), 'mouthLipThickness') self.setControlValue(self.style.getCheekFat(), 'cheekFat') self.setControlValue(self.style.getBrowProtruding(), 'browProtruding') self.setControlValue(self.style.getEyeCorner(), 'eyeCorner') self.setControlValue(self.style.getEyeOpeningSize(), 'eyeOpeningSize') self.setControlValue(self.style.getEyeBulge(), 'eyeSpacing') self.setControlValue(self.style.getNoseBridgeWidth(), 'noseBridgeWidth') self.setControlValue(self.style.getNoseNostrilWidth(), 'noseNostrilWidth') self.setControlValue(self.style.getNoseLength(), 'noseLength') self.setControlValue(self.style.getNoseBump(), 'noseBump') self.setControlValue(self.style.getNoseNostrilHeight(), 'noseNostrilHeight') self.setControlValue(self.style.getNoseNostrilAngle(), 'noseNostrilAngle') self.setControlValue(self.style.getNoseBridgeBroke(), 'noseBridgeBroke') self.setControlValue(self.style.getNoseNostrilBroke(), 'noseNostrilBroke') self.setControlValue(self.style.getEarScale(), 'earScale') self.setControlValue(self.style.getEarFlapAngle(), 'earFlap') self.setControlValue(self.style.getEarPosition(), 'earPosition') def getGlobalScale(self): return self.scaleNode.getScale() def setGlobalScale(self, scale): transData = self.jointTrans['def_head01'] pos = Vec3(transData[0]) pos.setZ(-(self.floorOffsetZ * (1 - scale))) self.joints['def_scale_jt'].applyFreezeMatrix(pos, transData[1], Vec3(scale)) self.rootScale = scale def calcBodyScale(self): idx = 0 if self.gender == 'f': idx = 1 mappedValue = (0.80000000000000004 + (1 + self.style.getBodyHeight()) * 0.20000000000000001) * BodyScales[idx][0]#self.style.getBodyShape()] return mappedValue def showZombie(self): self.model.irises.stash() self.model.faces[0].stash() self.model.faceZomb.unstash() self.generateSkinTexture() def showNormal(self): self.model.irises.unstash() self.model.faces[0].unstash() self.model.faceZomb.stash() self.generateSkinTexture() def takeAwayTexture(self, geoms, omitFace = False): emptyRenderState = RenderState.makeEmpty() eyeIrisColor = VBase4(0, 0, 0, 1) for i in range(0, geoms.getNumPaths()): element = geoms[i] if 'eye_iris' in element.getName(): element.setColorScale(eyeIrisColor) elif omitFace and 'master_face' in element.getName(): continue element.setTextureOff() geom = element.node() for j in range(0, geom.getNumGeoms()): geom.setGeomState(j, emptyRenderState) def optimizeMedLOD(self): medLOD = self.getLOD('1000') geoms = medLOD.findAllMatches('**/teeth*') geoms.stash() self.medSkinGone = False geoms = medLOD.find('**/body_forearm*') if geoms.isEmpty(): self.medSkinGone = True geoms = medLOD.findAllMatches('**/body_*') self.takeAwayTexture(geoms, True) geoms = medLOD.findAllMatches('**/hair_*') self.takeAwayTexture(geoms) if self.gender != 'f': geoms = medLOD.findAllMatches('**/beard_*') self.takeAwayTexture(geoms) geoms = medLOD.findAllMatches('**/mustache_*') self.takeAwayTexture(geoms) geoms = medLOD.findAllMatches('**/eye_*') self.takeAwayTexture(geoms) geoms = medLOD.findAllMatches('**/clothing_layer2_belt_*') self.takeAwayTexture(geoms) geoms = medLOD.findAllMatches('**/clothing_layer1_shoe_*') self.takeAwayTexture(geoms) def optimizeLowLOD(self): lowLOD = self.getLOD('500') geoms = lowLOD.findAllMatches('**/teeth*') geoms.stash() geoms = lowLOD.findAllMatches('**/+GeomNode') self.takeAwayTexture(geoms) def setHeadControlShapeValues(self): value = self.style.getHeadSize() mappedValue = 0.90000000000000002 + (1 + value) * 0.10000000000000001 self.setControlValue_new(self.style.getHeadWidth(), 'headWidth') self.setControlValue_new(self.style.getHeadHeight(), 'headHeight') self.setControlValue_new(self.style.getHeadRoundness(), 'headRoundness') self.setControlValue_new(self.style.getJawWidth(), 'jawWidth') self.setControlValue_new(self.style.getJawAngle(), 'jawChinAngle') self.setControlValue_new(self.style.getJawChinSize(), 'jawChinSize') self.setControlValue_new(self.style.getJawLength(), 'jawLength') self.setControlValue_new(self.style.getMouthWidth(), 'mouthWidth') self.setControlValue_new(self.style.getMouthLipThickness(), 'mouthLipThickness') self.setControlValue_new(self.style.getCheekFat(), 'cheekFat') self.setControlValue_new(self.style.getBrowProtruding(), 'browProtruding') self.setControlValue_new(self.style.getEyeCorner(), 'eyeCorner') self.setControlValue_new(self.style.getEyeOpeningSize(), 'eyeOpeningSize') self.setControlValue_new(self.style.getEyeBulge(), 'eyeSpacing') self.setControlValue_new(self.style.getNoseBridgeWidth(), 'noseBridgeWidth') self.setControlValue_new(self.style.getNoseNostrilWidth(), 'noseNostrilWidth') self.setControlValue_new(self.style.getNoseLength(), 'noseLength') self.setControlValue_new(self.style.getNoseBump(), 'noseBump') self.setControlValue_new(self.style.getNoseNostrilHeight(), 'noseNostrilHeight') self.setControlValue_new(self.style.getNoseNostrilAngle(), 'noseNostrilAngle') self.setControlValue_new(self.style.getNoseBridgeBroke(), 'noseBridgeBroke') self.setControlValue_new(self.style.getNoseNostrilBroke(), 'noseNostrilBroke') self.setControlValue_new(self.style.getEarScale(), 'earScale') self.setControlValue_new(self.style.getEarFlapAngle(), 'earFlap') self.setControlValue_new(self.style.getEarPosition(), 'earPosition') self.postProcess_setHeadControlShapeValues() def setControlValue_new(self, r, name): ctl = self.controlShapes[name] zeroindex = ctl[0] sliders = zeroindex if r < 0.0: if len(ctl) > 1: sliders = ctl[1] for i in range(0, len(sliders)): zeroindex[i][5] = sliders[i][4] * r def postProcess_setHeadControlShapeValues(self): if self.style.getGender() == 'f': cjs = FemaleHeadShapeControlJoints matrixF = FemaleHeadShapeControlJointMatrix matrixIHelper = FemaleHeadInitHelper else: cjs = MaleHeadShapeControlJoints matrixF = MaleHeadShapeControlJointMatrix matrixIHelper = MaleHeadInitHelper for jointName in cjs: transList = list(matrixIHelper[jointName]) for sliderName in matrixF[jointName]: for sliderJoint in self.controlShapes[sliderName][0]: if sliderJoint[0] == jointName: transList[sliderJoint[1]] += sliderJoint[5] continue self.joints[jointName].applyFreezeMatrix(Vec3(*transList[0:3]), Vec3(*transList[3:6]), Vec3(*transList[6:9])) def quickGetJointTransform(self, jointName): return self.joints[jointName][0].getDefaultValue() def storeJoints(self): if self.style.gender == 'm': bJoints = MaleBodyShapeControlJoints hJoints = MaleHeadShapeControlJoints else: bJoints = FemaleBodyShapeControlJoints hJoints = FemaleHeadShapeControlJoints for name in bJoints + hJoints + ('def_head01', 'def_extra_jt', 'def_scale_jt'): joint = self.getJoints(jointName = name) self.joints[name] = joint[0] ts = TransformState.makeMat(joint[0].getDefaultValue()) self.jointTrans[name] = (Vec3(ts.getPos()), Vec3(ts.getHpr()), Vec3(ts.getScale())) def setupAnimDicts(cls): for t in BodyDefs.maleFrames: cls.storeAnimDict('models/char/mp', 'm', t) for t in BodyDefs.femaleFrames: cls.storeAnimDict('models/char/fp', 'f', t) setupAnimDicts = classmethod(setupAnimDicts) def storeAnimDict(cls, prefix, gender, type): qualifier = gender + type animList = AnimListDict[type] cls.prebuiltAnimData[qualifier] = { } for anim in animList: animSuffix = '' for i in range(0, len(CustomAnimDict[qualifier])): if anim[0] == CustomAnimDict[qualifier][i]: animSuffix = '_' + gender + NewModelDict.get(type) break continue cls.prebuiltAnimData[qualifier][anim[0]] = prefix + '_' + anim[1] + animSuffix cls.prebuiltAnimData[qualifier].pop('intro') storeAnimDict = classmethod(storeAnimDict)
class MasterHuman(HumanBase.HumanBase, Biped.Biped): __module__ = __name__ notify = DirectNotifyGlobal.directNotify.newCategory('Human') prebuiltAnimData = {} def __init__(self, other=None): Biped.Biped.__init__(self, other, HumanAnimationMixer) self.model = None self.useFaceTex = True self.joints = {} self.jointTrans = {} self.jointTrans2 = {} self.zombie = False self.crazyColorSkin = False self.crazyColorSkinIndex = 0 self.flattenPending = None self.optimizeLOD = base.config.GetBool('optimize-avatar-lod', 1) self.master = 0 self.loaded = 0 self.playingRate = None self.shadowFileName = 'models/misc/drop_shadow' self.setFont(PiratesGlobals.getInterfaceFont()) self.__blinkName = 'blink-' + str(self.this) self.eyeLids = None self.eyeBalls = None self.eyeIris = None self.reducedAnimList = None self.rootScale = 1.0 self.headNode = None self.extraNode = None self.scaleNode = None self.rootNode = None self.floorOffsetZ = 0.0 self.headFudgeHpr = Vec3(0, 0, 0) self.frozeSomething = True self.randGen = random.Random() self.randGen.seed(random.random()) self.eyeFSM = ClassicFSM('eyeFSM', [ State('off', self.enterEyeFSMOff, self.exitEyeFSMOff, [ 'open', 'closed']), State('open', self.enterEyeFSMOpen, self.exitEyeFSMOpen, [ 'closed', 'off']), State('closed', self.enterEyeFSMClosed, self.exitEyeFSMClosed, [ 'open', 'off'])], 'off', 'off') self.eyeFSM.enterInitialState() if other != None: self.copyHuman(other) self.isPaid = False return def removeCopiedNodes(self): self.dropShadow = self.find('**/drop_shadow*') if not self.dropShadow.isEmpty(): self.deleteDropShadow() else: self.dropShadow = None return def flattenHuman(self): self.deleteNametag3d() self.getWeaponJoints() def __doneFlattenHuman(self, models): self.flattenPending = None self.getWeaponJoints() return def copyHuman(self, other): self.gender = other.gender self.loaded = other.loaded self.type = other.type self.loadAnimatedHead = other.loadAnimatedHead self.model = None return def delete(self): try: self.Human_deleted except: self.Human_deleted = 1 taskMgr.remove(self.__blinkName) if self.dropShadow and not self.dropShadow.isEmpty(): self.deleteDropShadow() del self.eyeFSM self.controlShapes = None self.sliderNames = None if self.model: self.model.delete() del self.model Biped.Biped.delete(self) return def isDeleted(self): try: self.Human_deleted if self.Human_deleted == 1: return True except: return False def fixEyes(self): self.eyeLids = {} self.eyeBalls = {} self.eyeIris = {} for lodName in self.getLODNames(): geom = self.getPart('head', lodName) self.eyeLids[lodName] = geom.findAllMatches('**/*eyelid*') self.eyeBalls[lodName] = geom.findAllMatches('**/eye_ball*') self.eyeIris[lodName] = geom.findAllMatches('**/eye_iris*') self.eyeLids[lodName].stash() self.eyeBalls[lodName].unstash() self.eyeIris[lodName].unstash() def getCrazyColorSkinIndex(self): return self.crazyColorSkinIndex def setCrazyColorSkinIndex(self, index): if len(HumanDNA.crazySkinColors) > index: self.crazyColorSkinIndex = index else: self.notify.warning('(MasterHuman)index: %d is out of bounds for crazyColorSkin: %d' % (index, len(HumanDNA.crazySkinColors))) def generateSkinColor(self): skinColor = self.style.getSkinColor() lowColor = self.model.lowLODSkinColor color = VBase4(lowColor[0] * skinColor[0], lowColor[1] * skinColor[1], lowColor[2] * skinColor[2], 1.0) self.model.faces[0].setColorScale(skinColor) if self.model.newAvatars: self.model.currentBody.setColorScale(skinColor) if self.optimizeLOD: self.model.currentBody[2].setColorScale(color) self.model.faces[0][2].setColorScale(color) else: numPaths = self.model.body.getNumPaths() medIdx = numPaths / 3 lowIdx = numPaths / 3 * 2 if self.zombie: self.model.body.setColorScale(Vec4(1, 1, 1, 1)) if self.optimizeLOD: color = VBase4(121 / 255.0, 124 / 255.0, 103 / 255.0, 1.0) for i in xrange(lowIdx, numPaths): self.model.body[i].setColorScale(color) self.model.faceZomb[2].setColorScale(color) else: self.model.body.setColorScale(skinColor) lowColor = self.model.lowLODSkinColor if self.optimizeLOD: color = VBase4(lowColor[0] * skinColor[0], lowColor[1] * skinColor[1], lowColor[2] * skinColor[2], 1.0) for i in xrange(lowIdx, numPaths): self.model.body[i].setColorScale(color) def generateSkinTexture(self): bodyTextureIdx = self.style.body.skin if self.zombie: if self.gender == 'f': bodyTextureIdx = PirateFemale.ZOMB_BODY_TEXTURE else: bodyTextureIdx = PirateMale.ZOMB_BODY_TEXTURE if self.gender == 'f': body_textures = PirateFemale.body_textures[self.style.body.shape] else: body_textures = PirateMale.body_textures[self.style.body.shape] tex_name = self.getTrySafe(body_textures, bodyTextureIdx) if tex_name != None: tex = self.model.bodyTextures.findTexture(tex_name) else: return if tex: for parts in self.model.bodys: numPaths = parts.getNumPaths() for i in xrange(numPaths): parts[i].setTexture(tex, 1) return def generateFaceTexture(self, default): if default: faceTextureIdx = 0 else: faceTextureIdx = self.style.head.texture if faceTextureIdx >= len(self.model.faceTexturesSet): faceTextureIdx = 0 self.model.faces[0].setTexture(self.model.faceTexturesSet[faceTextureIdx]) def generateHairColor(self, colorName=None, colorModel=None): self.model.setHairBaseColor() def getTrySafe(self, list, idx): try: if type(idx) == str: lookup = idx.split('_cut')[0] else: lookup = idx return list[lookup] except: return return def generateEyesTexture(self): eyesTextureIdx = self.style.head.eyes.color if self.gender == 'f': eye_iris_textures = PirateFemale.eye_iris_textures else: eye_iris_textures = PirateMale.eye_iris_textures tex_name = self.getTrySafe(eye_iris_textures, eyesTextureIdx) if tex_name != None: tex = self.eyeIrisTextures.findTexture(tex_name) else: return if tex: self.model.irises.setTexture(tex, 1) return def generateHatColor(self): style = self.model.dna if self.zombie: style = self.model.dnaZomb hatColor = style.lookupHatColor() geom = self.getGeomNode() parts = geom.findAllMatches('**/hat_band*') parts.setColorScale(hatColor) def generateClothesColor(self): style = self.model.dna if self.zombie: style = self.model.dnaZomb clothesTopColor = style.lookupClothesTopColor() clothesBotColor = style.lookupClothesBotColor() geom = self.getGeomNode() if self.optimizeLOD: def tempColorParts(parts, ct): numPaths = parts.getNumPaths() lowIdx = numPaths / 3 * 2 for j in xrange(lowIdx): parts[j].setColorScale(ct) for j in xrange(lowIdx, numPaths): cl = parts[j].getColorScale() compoundColor = VBase4(cl[0] * ct[0], cl[1] * ct[1], cl[2] * ct[2], 1.0) parts[j].setColorScale(compoundColor) else: def tempColorParts(parts, ct): parts.setColorScale(ct) colorParts = tempColorParts parts = geom.findAllMatches('**/clothing_layer1_shirt*') colorParts(parts, clothesTopColor[0]) parts = geom.findAllMatches('**/clothing_layer2_vest*') colorParts(parts, clothesTopColor[1]) parts = geom.findAllMatches('**/clothing_layer3_coat*') colorParts(parts, clothesTopColor[2]) parts = geom.findAllMatches('**/clothing_layer1_pant*') colorParts(parts, clothesBotColor[0]) del colorParts def generateTexture(self): self.generateFaceTexture(not self.useFaceTex) self.generateEyesTexture() def generateColor(self): self.generateSkinColor() self.generateHairColor() self.generateHatColor() def makeAnimDict(self, gender, animNames): self.animTable = [] for currAnim in animNames: anim = animNames.get(currAnim) for currAnimName in anim: self.animTable.append([currAnimName, currAnimName]) self.reducedAnimList = self.animTable def forceLoadAnimDict(self): for anim in self.animTable: self.getAnimControls(anim[0]) def createAnimDict(self, customList=None): if self.reducedAnimList is None: self.animDict = self.prebuiltAnimData[self.gender + self.type] return if self.gender == 'f': filePrefix = 'models/char/f' genderPrefix = 'f' else: filePrefix = 'models/char/m' genderPrefix = 'm' filePrefix += 'p' animList = self.reducedAnimList if animList is None: animList = AnimListDict[self.type] self.animDict = {} for anim in animList: animSuffix = '' for i in range(0, len(CustomAnimDict[genderPrefix + self.type])): if anim[0] == CustomAnimDict[genderPrefix + self.type][i]: animSuffix = '_' + genderPrefix + NewModelDict.get(self.type) break self.animDict[anim[0]] = filePrefix + '_' + anim[1] + animSuffix if self.reducedAnimList is None: self.animDict.pop('intro') return filePrefix def generateBody(self, copy=1): if self.gender == 'm': filePrefix = 'models/char/mp' else: filePrefix = 'models/char/fp' messenger.send('tick') lodString = '2000' self.loadModel(filePrefix + '_' + lodString, 'modelRoot', '2000', copy) messenger.send('tick') if loader.loadModel(filePrefix + '_' + '1000', allowInstance=True) != None: lodString = '1000' self.loadModel(filePrefix + '_' + lodString, 'modelRoot', '1000', copy) messenger.send('tick') if loader.loadModel(filePrefix + '_' + '500', allowInstance=True) != None: lodString = '500' self.loadModel(filePrefix + '_' + lodString, 'modelRoot', '500', copy) messenger.send('tick') self.makeSubpart('head', ['zz_head01'], []) self.makeSubpart('torso', ['zz_spine01'], ['zz_head01']) self.makeSubpart('legs', ['dx_root'], ['zz_spine01']) self.setSubpartsComplete(True) self.eyeIrisTextures = loader.loadModel('models/misc/eye_iris.bam') return def setLODs(self): self.setLODNode() avatarDetail = base.config.GetString('avatar-detail', 'high') if avatarDetail == 'high': dist = [ 0, 20, 80, 1000000000] else: if avatarDetail == 'med': dist = [ 0, 10, 20, 1000000000] else: if avatarDetail == 'low': dist = [ 0, 0, 10, 1000000000] else: raise StandardError, 'Invalid avatar-detail: %s' % avatarDetail self.addLOD(2000, dist[1], dist[0]) self.addLOD(1000, dist[2], dist[1]) self.addLOD(500, dist[3], dist[2]) if self.optimizeLOD: lowLOD = self.getLOD('500') lowLOD.setTransparency(0, 1000) self.getLODNode().setCenter(Point3(0, 0, 5)) def showLOD(self, lodName): self.generateTexture() self.model.setFromDNA() tex = self.model.faces[0][2].findTexture('*face*') def loadHuman(self, gender='m', other=None): self.gender = gender if self.gender == 'f': controlShapes = PirateFemale.ControlShapes sliderNames = PirateFemale.SliderNames else: controlShapes = PirateMale.ControlShapes sliderNames = PirateMale.SliderNames self.setLODs() self.loadAnimatedHead = True self.generateBody() if self.gender == 'f': self.type = BodyDefs.femaleFrames[self.style.getBodyShape()] self.model = PirateFemale.PirateFemale(self, self.style) else: self.type = BodyDefs.maleFrames[self.style.getBodyShape()] self.model = PirateMale.PirateMale(self, self.style) self.faceAwayFromViewer() self.lods = self.getLODNames() if self.gender == 'f': self.headFudgeHpr = Vec3(0, 0, 0) idx = 1 else: self.headFudgeHpr = Vec3(0, 0, 0) idx = 0 messenger.send('tick') self.model.setupHead(2000) messenger.send('tick') self.model.setupBody(2000) messenger.send('tick') self.model.setupClothing(2000) messenger.send('tick') if self.master: self.model.setupSelectionChoices('NPC') self.showNormal() self.createAnimDict() messenger.send('tick') self.initAnimsOnAllLODs(['head', 'legs', 'torso', 'modelRoot']) messenger.send('tick') self.controlShapes = controlShapes self.sliderNames = sliderNames self.initHeadControlShapes() self.storeJoints() self.find('**/nametag3d').detachNode() self.findAllMatches('**/name_tag').detach() self.rootNode = self.getLOD('2000').find('**/dx_root') self.floorOffsetZ = self.rootNode.getZ() messenger.send('tick') root = self.getLOD('500') gr = SceneGraphReducer() gr.applyAttribs(root.node(), gr.TTTransform | gr.TTTexMatrix | gr.TTOther) gr.makeCompatibleFormat(root.node(), 0) gr.premunge(root.node(), RenderState.makeEmpty()) gr.decompose(root.node()) stashedSet = root.findAllMatches('**/@@*') stashedSet.unstash() gr.makeCompatibleFormat(root.node(), 0) stashedSet.stash() messenger.send('tick') for face in self.model.faces[0]: node = face.node() for i in range(node.getNumGeoms()): face.node().setGeomState(i, RenderState.makeEmpty()) def initializeMiscNodes(self): self.initializeNametag3d() self.initializeDropShadow() if self.getLOD('2000') == None: return exposedHeadJoint = self.getLOD('2000').find('**/def_head01') if not exposedHeadJoint.isEmpty(): idx = 0 if self.gender == 'f': idx = 1 exposedHeadJoint.setScale(1) self.headNode.reparentTo(exposedHeadJoint) self.headNode.setScale(HeadScales[idx][self.style.getBodyShape()]) return def undoControlJoints(self): self.getGeomNode().getParent().findAllMatches('def_*').detach() self.getGeomNode().getParent().findAllMatches('trs_*').detach() self.findAllMatches('def_*').detach() self.findAllMatches('trs_*').detach() def cleanupHuman(self, gender='m'): self.eyeFSM.request('off') self.undoControlJoints() self.eyeLids = {} self.eyeBalls = {} self.eyeIris = {} self.flush() self.loaded = 0 self.master = 0 def generateHuman(self, gender='m'): self.loadHuman(self.style.gender) def getShadowJoint(self): return self def getNametagJoints(self): joints = [] for lodName in self.getLODNames(): bundle = self.getPartBundle('legs', lodName) joint = bundle.findChild('name_tag') if joint: joints.append(joint) return joints def __blinkOpenEyes(self, task): if self.eyeFSM.getCurrentState().getName() == 'closed': self.eyeFSM.request('open') r = self.randGen.random() if r < 0.1: t = 0.2 else: t = r * 4.0 + 1.0 taskMgr.doMethodLater(t, self.__blinkCloseEyes, self.__blinkName) return Task.done def __blinkCloseEyes(self, task): if self.eyeFSM.getCurrentState().getName() != 'open': taskMgr.doMethodLater(4.0, self.__blinkCloseEyes, self.__blinkName) else: self.eyeFSM.request('closed') taskMgr.doMethodLater(0.125, self.__blinkOpenEyes, self.__blinkName) return Task.done def startBlink(self): taskMgr.remove(self.__blinkName) if self.eyeLids: self.openEyes() taskMgr.doMethodLater(self.randGen.random() * 4.0 + 1, self.__blinkCloseEyes, self.__blinkName) def stopBlink(self): taskMgr.remove(self.__blinkName) if self.eyeLids: self.eyeFSM.request('open') def closeEyes(self): self.eyeFSM.request('closed') def openEyes(self): self.eyeFSM.request('open') def enterEyeFSMOff(self): pass def exitEyeFSMOff(self): pass def enterEyeFSMOpen(self): for lodName in self.getLODNames(): if not self.eyeLids[lodName].isEmpty(): self.eyeLids[lodName].hide() self.eyeBalls[lodName].show() self.eyeIris[lodName].show() def exitEyeFSMOpen(self): pass def enterEyeFSMClosed(self): return for lodName in self.getLODNames(): if not self.eyeLids[lodName].isEmpty(): self.eyeLids[lodName].show() self.eyeBalls[lodName].hide() self.eyeIris[lodName].hide() def exitEyeFSMClosed(self): pass def setControlValue(self, r, name): if self.style.getGender() == 'f': matrixF = FemaleHeadShapeControlJointMatrix matrixI = FemaleHeadShapeInitialControlJointMatrix else: matrixF = MaleHeadShapeControlJointMatrix matrixI = MaleHeadShapeInitialControlJointMatrix shapes = self.controlShapes ctl = shapes[name] slider = ctl[0] if r < 0.0: if len(ctl) > 1: slider = ctl[1] for i in range(0, len(slider)): jointName = slider[i][0] jointCtls = self.findAllMatches(jointName) posI = matrixI[jointName][0] hprI = matrixI[jointName][1] sclI = matrixI[jointName][2] posF = VBase3(posI[0], posI[1], posI[2]) hprF = VBase3(hprI[0], hprI[1], hprI[2]) sclF = VBase3(sclI[0], sclI[1], sclI[2]) self.notify.debug('scv: %s initial %s' % (jointName, posI)) dr = slider[i][4] * r ctl[0][i][5] = dr posDelta = VBase3(0, 0, 0) hprDelta = VBase3(0, 0, 0) sclDelta = VBase3(0, 0, 0) for sliderIdx in xrange(0, len(matrixF[jointName])): sliderName = matrixF[jointName][sliderIdx] jointSet = shapes[sliderName][0] for jointIdx in xrange(0, len(jointSet)): if jointSet[jointIdx][0] == jointName: if jointSet[jointIdx][1] == TX: posDelta.setX(posDelta.getX() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == TY: posDelta.setY(posDelta.getY() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == TZ: posDelta.setZ(posDelta.getZ() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == RX: hprDelta.setX(hprDelta.getX() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == RY: hprDelta.setY(hprDelta.getY() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == RZ: hprDelta.setZ(hprDelta.getZ() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == SX: if r < 0.0: sclDelta.setX(sclDelta.getX() + jointSet[jointIdx][5] / jointSet[jointIdx][2]) else: sclDelta.setX(sclDelta.getX() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == SY: if r < 0.0: sclDelta.setY(sclDelta.getY() + jointSet[jointIdx][5] / jointSet[jointIdx][2]) else: sclDelta.setY(sclDelta.getY() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == SZ: if r < 0.0: sclDelta.setZ(sclDelta.getZ() + jointSet[jointIdx][5] / jointSet[jointIdx][2]) else: sclDelta.setZ(sclDelta.getZ() + jointSet[jointIdx][5]) else: self.notify.warning('scv:wrong element = %s' % jointSet[jointIdx][1]) self.notify.debug('scv: %s composite posDelta = %s' % (jointName, posDelta)) posF.setX(posI[0] + posDelta[0]) posF.setY(posI[1] + posDelta[1]) posF.setZ(posI[2] + posDelta[2]) self.notify.debug('scv: %s final posDelta%s' % (jointName, posF)) self.notify.debug('scv: %s composite hprDelta = %s' % (jointName, hprDelta)) hprF.setX(hprI[0] + hprDelta[0]) hprF.setY(hprI[1] + hprDelta[1]) hprF.setZ(hprI[2] + hprDelta[2]) self.notify.debug('scv: %s final hprDelta%s' % (jointName, hprF)) self.notify.debug('scv: %s composite sclDelta = %s' % (jointName, sclDelta)) sclF.setX(sclI[0] + sclDelta[0]) sclF.setY(sclI[1] + sclDelta[1]) sclF.setZ(sclI[2] + sclDelta[2]) self.notify.debug('scv: %s final sclDelta%s' % (jointName, sclF)) for j in range(0, jointCtls.getNumPaths()): jointCtl = jointCtls[j] jointCtl.setPosHprScale(posF, hprF, sclF) def applyBodyShaper(self): if self.style.getGender() == 'f': tjs = FemaleBodyShapeTranslateJoints sjs = FemaleBodyShapeScaleJoints matrix = FemaleBodyShapeControlJointMatrix else: tjs = MaleBodyShapeTranslateJoints sjs = MaleBodyShapeScaleJoints matrix = MaleBodyShapeControlJointMatrix type = self.style.getBodyShape() for jointName in tjs: transData = self.jointTrans[jointName] vector = matrix[jointName][type] self.joints[jointName].applyFreezeMatrix(vector, transData[1], transData[2]) for jointName in sjs: transData = self.jointTrans[jointName] vector = matrix[jointName][type] self.joints[jointName].applyFreezeMatrix(transData[0], transData[1], vector) value = self.style.getHeadSize() mappedValue = 0.9 + (1 + value) * 0.1 transData = self.jointTrans['def_extra_jt'] self.joints['def_extra_jt'].applyFreezeMatrix(transData[0], transData[1], Vec3(2 - mappedValue, mappedValue, 1)) transData = self.jointTrans['def_head01'] idx = 0 if self.style.gender == 'f': idx = 1 self.joints['def_head01'].applyFreezeMatrix(transData[0], transData[1], Vec3(HeadScales[idx][self.style.getBodyShape()])) self.setGlobalScale(self.calcBodyScale()) def undoBodyShaper(self): if self.style.getGender() == 'f': cjs = FemaleBodyShapeControlJoints else: cjs = MaleBodyShapeControlJoints def applyHeadShaper(self): self.setHeadControlShapeValues() def undoHeadShaper(self): if self.style.getGender() == 'f': cjs = FemaleHeadShapeControlJoints else: cjs = MaleHeadShapeControlJoints def createControlJoints(self): if self.style.getGender() == 'f': cjs = FemaleHeadShapeControlJoints else: cjs = MaleHeadShapeControlJoints for jointName in cjs: for lodName in self.getLODNames(): if lodName == '2000': joint = self.controlJoint(None, 'legs', jointName, lodName) elif lodName == '1000': continue elif lodName == '500': continue return def initHeadControlShapes(self): if self.style.getGender() == 'f': cjs = FemaleHeadShapeControlJoints matrixF = FemaleHeadShapeControlJointMatrix matrixI = FemaleHeadShapeInitialControlJointMatrix matrixIHelper = FemaleHeadInitHelper else: cjs = MaleHeadShapeControlJoints matrixF = MaleHeadShapeControlJointMatrix matrixI = MaleHeadShapeInitialControlJointMatrix matrixIHelper = MaleHeadInitHelper if len(matrixF['initialized']) > 0: return initializedMatrixI = len(matrixI['initialized']) initializedMatrixF = len(matrixF['initialized']) for jointName in cjs: transform = TransformState.makeMat(self.getJointTransform('legs', jointName, '2000')) pos = Vec3(transform.getPos()) hpr = Vec3(transform.getHpr()) scale = Vec3(transform.getScale()) matrixI[jointName].append(pos) matrixI[jointName].append(hpr) matrixI[jointName].append(scale) matrixIHelper[jointName] = [ pos[0], pos[1], pos[2], hpr[0], hpr[1], hpr[2], scale[0], scale[1], scale[2]] matrixI['initialized'].append('initialized') shapes = self.controlShapes names = self.sliderNames for i in xrange(0, len(shapes)): slider = shapes[names[i]] for k in xrange(0, len(slider[0])): slider[0][k][4] = slider[0][k][2] if len(slider) > 1: slider[1][k][4] = slider[1][k][2] for i in xrange(0, len(shapes)): slider = shapes[names[i]] for k in xrange(0, len(slider[0])): jointCtl = slider[0][k] jointName = jointCtl[0] matrixF[jointName].append(names[i]) pos = matrixI[jointName][0] hpr = matrixI[jointName][1] scl = matrixI[jointName][2] if jointCtl[1] < 3: posDelta = jointCtl[4] - pos[jointCtl[1]] jointCtl[4] = posDelta if len(slider) > 1: jointCtl = slider[1][k] jointCtl[4] = posDelta elif jointCtl[1] > 2: if jointCtl[1] < 6: hprDelta = jointCtl[4] - hpr[jointCtl[1] - 3] jointCtl[4] = hprDelta jointCtl = len(slider) > 1 and slider[1][k] jointCtl[4] = hprDelta else: sclDelta = jointCtl[4] - scl[jointCtl[1] - 6] jointCtl[4] = sclDelta if len(slider) > 1: jointCtl = slider[1][k] jointCtl[4] = sclDelta matrixF['initialized'].append('initialized') def setHeadControlShapeValues_old(self): value = self.style.getHeadSize() mappedValue = 0.9 + (1 + value) * 0.1 self.setControlValue(self.style.getHeadWidth(), 'headWidth') self.setControlValue(self.style.getHeadHeight(), 'headHeight') self.setControlValue(self.style.getHeadRoundness(), 'headRoundness') self.setControlValue(self.style.getJawWidth(), 'jawWidth') self.setControlValue(self.style.getJawAngle(), 'jawChinAngle') self.setControlValue(self.style.getJawChinSize(), 'jawChinSize') self.setControlValue(self.style.getJawLength(), 'jawLength') self.setControlValue(self.style.getMouthWidth(), 'mouthWidth') self.setControlValue(self.style.getMouthLipThickness(), 'mouthLipThickness') self.setControlValue(self.style.getCheekFat(), 'cheekFat') self.setControlValue(self.style.getBrowProtruding(), 'browProtruding') self.setControlValue(self.style.getEyeCorner(), 'eyeCorner') self.setControlValue(self.style.getEyeOpeningSize(), 'eyeOpeningSize') self.setControlValue(self.style.getEyeBulge(), 'eyeSpacing') self.setControlValue(self.style.getNoseBridgeWidth(), 'noseBridgeWidth') self.setControlValue(self.style.getNoseNostrilWidth(), 'noseNostrilWidth') self.setControlValue(self.style.getNoseLength(), 'noseLength') self.setControlValue(self.style.getNoseBump(), 'noseBump') self.setControlValue(self.style.getNoseNostrilHeight(), 'noseNostrilHeight') self.setControlValue(self.style.getNoseNostrilAngle(), 'noseNostrilAngle') self.setControlValue(self.style.getNoseBridgeBroke(), 'noseBridgeBroke') self.setControlValue(self.style.getNoseNostrilBroke(), 'noseNostrilBroke') self.setControlValue(self.style.getEarScale(), 'earScale') self.setControlValue(self.style.getEarFlapAngle(), 'earFlap') self.setControlValue(self.style.getEarPosition(), 'earPosition') def getGlobalScale(self): return self.scaleNode.getScale() def setGlobalScale(self, scale): transData = self.jointTrans['def_head01'] pos = Vec3(transData[0]) pos.setZ(-(self.floorOffsetZ * (1 - scale))) self.joints['def_scale_jt'].applyFreezeMatrix(pos, transData[1], Vec3(scale)) self.rootScale = scale def calcBodyScale(self): idx = 0 if self.gender == 'f': idx = 1 mappedValue = (0.8 + (1 + self.style.getBodyHeight()) * 0.2) * BodyScales[idx][self.style.getBodyShape()] return mappedValue def showZombie(self): self.model.irises.stash() self.model.faces[0].stash() self.model.faceZomb.unstash() self.generateSkinTexture() def showNormal(self): self.model.irises.unstash() self.model.faces[0].unstash() self.model.faceZomb.stash() self.generateSkinTexture() def takeAwayTexture(self, geoms, omitFace=False): emptyRenderState = RenderState.makeEmpty() eyeIrisColor = VBase4(0, 0, 0, 1) for i in range(0, geoms.getNumPaths()): element = geoms[i] if 'eye_iris' in element.getName(): element.setColorScale(eyeIrisColor) else: if omitFace and 'master_face' in element.getName(): continue element.setTextureOff() geom = element.node() for j in range(0, geom.getNumGeoms()): geom.setGeomState(j, emptyRenderState) def optimizeMedLOD(self): medLOD = self.getLOD('1000') geoms = medLOD.findAllMatches('**/teeth*') geoms.stash() self.medSkinGone = False geoms = medLOD.find('**/body_forearm*') if geoms.isEmpty(): self.medSkinGone = True geoms = medLOD.findAllMatches('**/body_*') self.takeAwayTexture(geoms, True) geoms = medLOD.findAllMatches('**/hair_*') self.takeAwayTexture(geoms) if self.gender != 'f': geoms = medLOD.findAllMatches('**/beard_*') self.takeAwayTexture(geoms) geoms = medLOD.findAllMatches('**/mustache_*') self.takeAwayTexture(geoms) geoms = medLOD.findAllMatches('**/eye_*') self.takeAwayTexture(geoms) geoms = medLOD.findAllMatches('**/clothing_layer2_belt_*') self.takeAwayTexture(geoms) geoms = medLOD.findAllMatches('**/clothing_layer1_shoe_*') self.takeAwayTexture(geoms) def optimizeLowLOD(self): lowLOD = self.getLOD('500') geoms = lowLOD.findAllMatches('**/teeth*') geoms.stash() geoms = lowLOD.findAllMatches('**/+GeomNode') self.takeAwayTexture(geoms) def setHeadControlShapeValues(self): value = self.style.getHeadSize() mappedValue = 0.9 + (1 + value) * 0.1 self.setControlValue_new(self.style.getHeadWidth(), 'headWidth') self.setControlValue_new(self.style.getHeadHeight(), 'headHeight') self.setControlValue_new(self.style.getHeadRoundness(), 'headRoundness') self.setControlValue_new(self.style.getJawWidth(), 'jawWidth') self.setControlValue_new(self.style.getJawAngle(), 'jawChinAngle') self.setControlValue_new(self.style.getJawChinSize(), 'jawChinSize') self.setControlValue_new(self.style.getJawLength(), 'jawLength') self.setControlValue_new(self.style.getMouthWidth(), 'mouthWidth') self.setControlValue_new(self.style.getMouthLipThickness(), 'mouthLipThickness') self.setControlValue_new(self.style.getCheekFat(), 'cheekFat') self.setControlValue_new(self.style.getBrowProtruding(), 'browProtruding') self.setControlValue_new(self.style.getEyeCorner(), 'eyeCorner') self.setControlValue_new(self.style.getEyeOpeningSize(), 'eyeOpeningSize') self.setControlValue_new(self.style.getEyeBulge(), 'eyeSpacing') self.setControlValue_new(self.style.getNoseBridgeWidth(), 'noseBridgeWidth') self.setControlValue_new(self.style.getNoseNostrilWidth(), 'noseNostrilWidth') self.setControlValue_new(self.style.getNoseLength(), 'noseLength') self.setControlValue_new(self.style.getNoseBump(), 'noseBump') self.setControlValue_new(self.style.getNoseNostrilHeight(), 'noseNostrilHeight') self.setControlValue_new(self.style.getNoseNostrilAngle(), 'noseNostrilAngle') self.setControlValue_new(self.style.getNoseBridgeBroke(), 'noseBridgeBroke') self.setControlValue_new(self.style.getNoseNostrilBroke(), 'noseNostrilBroke') self.setControlValue_new(self.style.getEarScale(), 'earScale') self.setControlValue_new(self.style.getEarFlapAngle(), 'earFlap') self.setControlValue_new(self.style.getEarPosition(), 'earPosition') self.postProcess_setHeadControlShapeValues() def setControlValue_new(self, r, name): ctl = self.controlShapes[name] zeroindex = ctl[0] sliders = zeroindex if r < 0.0: if len(ctl) > 1: sliders = ctl[1] for i in range(0, len(sliders)): zeroindex[i][5] = sliders[i][4] * r def postProcess_setHeadControlShapeValues(self): if self.style.getGender() == 'f': cjs = FemaleHeadShapeControlJoints matrixF = FemaleHeadShapeControlJointMatrix matrixIHelper = FemaleHeadInitHelper else: cjs = MaleHeadShapeControlJoints matrixF = MaleHeadShapeControlJointMatrix matrixIHelper = MaleHeadInitHelper for jointName in cjs: transList = list(matrixIHelper[jointName]) for sliderName in matrixF[jointName]: for sliderJoint in self.controlShapes[sliderName][0]: if sliderJoint[0] == jointName: transList[sliderJoint[1]] += sliderJoint[5] self.joints[jointName].applyFreezeMatrix(Vec3(*transList[0:3]), Vec3(*transList[3:6]), Vec3(*transList[6:9])) def quickGetJointTransform(self, jointName): return self.joints[jointName][0].getDefaultValue() def storeJoints(self): if self.style.gender == 'm': bJoints = MaleBodyShapeControlJoints hJoints = MaleHeadShapeControlJoints else: bJoints = FemaleBodyShapeControlJoints hJoints = FemaleHeadShapeControlJoints for name in bJoints + hJoints + ('def_head01', 'def_extra_jt', 'def_scale_jt'): joint = self.getJoints(jointName=name) self.joints[name] = joint[0] ts = TransformState.makeMat(joint[0].getDefaultValue()) self.jointTrans[name] = (Vec3(ts.getPos()), Vec3(ts.getHpr()), Vec3(ts.getScale())) @classmethod def setupAnimDicts(cls): for t in BodyDefs.maleFrames: cls.storeAnimDict('models/char/mp', 'm', t) for t in BodyDefs.femaleFrames: cls.storeAnimDict('models/char/fp', 'f', t) @classmethod def storeAnimDict(cls, prefix, gender, type): qualifier = gender + type animList = AnimListDict[type] cls.prebuiltAnimData[qualifier] = {} for anim in animList: animSuffix = '' for i in range(0, len(CustomAnimDict[qualifier])): if anim[0] == CustomAnimDict[qualifier][i]: animSuffix = '_' + gender + NewModelDict.get(type) break cls.prebuiltAnimData[qualifier][anim[0]] = prefix + '_' + anim[1] + animSuffix cls.prebuiltAnimData[qualifier].pop('intro')
class DistributedWeatherCycle(DistributedObject): notify = DirectNotifyGlobal.directNotify.newCategory( 'DistributedWeatherCycle') def __init__(self, cr): DistributedObject.__init__(self, cr) self.fsm = ClassicFSM(self.__class__.__name__, [ State('off', self.enterOff, self.exitOff, ['morning']), State('morning', self.enterMorning, self.exitMorning, ['afternoon']), State('afternoon', self.enterAfternoon, self.exitAfternoon, ['evening']), State('evening', self.enterEvening, self.exitEvening, ['midnight']), State('midnight', self.enterMidnight, self.exitMidnight, ['morning']) ], 'off', 'off') self.fsm.enterInitialState() self.__interval = None def setState(self, state): self.fsm.request(state) def getState(self): return self.fsm.getCurrentState()._State__name def setDuration(self, duration): self.duration = duration def getDuration(self): return self.duration def enterOff(self): pass def exitOff(self): pass def enterMorning(self): self.__interval = LerpColorScaleInterval( render, self.getDuration(), WeatherGlobals.cycleColors[0], startColorScale=render.getColorScale()) self.__interval.start() def exitMorning(self): if not self.__interval: return self.__interval.finish() self.__interval = None def enterAfternoon(self): self.__interval = LerpColorScaleInterval( render, self.getDuration(), WeatherGlobals.cycleColors[1], startColorScale=render.getColorScale()) self.__interval.start() def exitAfternoon(self): if not self.__interval: return self.__interval.finish() self.__interval = None def enterEvening(self): self.__interval = LerpColorScaleInterval( render, self.getDuration(), WeatherGlobals.cycleColors[2], startColorScale=render.getColorScale()) self.__interval.start() def exitEvening(self): if not self.__interval: return self.__interval.finish() self.__interval = None def enterMidnight(self): self.__interval = LerpColorScaleInterval( render, self.getDuration(), WeatherGlobals.cycleColors[3], startColorScale=render.getColorScale()) self.__interval.start() def exitMidnight(self): if not self.__interval: return self.__interval.finish() self.__interval = None
class Human(HumanBase.HumanBase, Biped.Biped): notify = DirectNotifyGlobal.directNotify.newCategory('Human') prebuiltAnimData = {} def __init__(self, other=None): Biped.Biped.__init__(self, other, HumanAnimationMixer) self.zombie = False self.crazyColorSkin = False self.crazyColorSkinIndex = 0 self.flattenPending = None self.flattenSuperLowName = None self.optimizeLOD = base.config.GetBool('optimize-avatar-lod', 1) self.loaded = 0 self.playingRate = None self.shadowFileName = 'models/misc/drop_shadow' self.setFont(PiratesGlobals.getInterfaceFont()) self._Human__blinkName = 'blink-' + str(self.this) self.eyeLids = None self.eyeBalls = None self.eyeIris = None self.reducedAnimList = None self.headNode = None self.headEffects = NodePath('headEffects') self.extraNode = None self.scaleNode = None self.rootNode = None self.floorOffsetZ = 0.0 self.isGhost = 0 self.headFudgeHpr = Vec3(0, 0, 0) self.randGen = random.Random() self.randGen.seed(random.random()) self.eyeFSM = ClassicFSM('eyeFSM', [ State('off', self.enterEyeFSMOff, self.exitEyeFSMOff, ['open', 'closed']), State('open', self.enterEyeFSMOpen, self.exitEyeFSMOpen, ['closed', 'off']), State('closed', self.enterEyeFSMClosed, self.exitEyeFSMClosed, ['open', 'off']) ], 'off', 'off') self.eyeFSM.enterInitialState() if other != None: self.copyHuman(other) def removeCopiedNodes(self): self.dropShadow = self.find('**/drop_shadow*') if not self.dropShadow.isEmpty(): self.deleteDropShadow() else: self.dropShadow = None billboardNode = self.find('**/billboardNode') if not billboardNode.isEmpty(): billboardNode.removeNode() self.getGeomNode().getParent().removeNode() def flattenHuman(self): self.getWeaponJoints() def flattenSuperLow(self): name = 'flattenSuperLow-%s' % self.this self.flattenSuperLowName = name model = self.getLOD('500') self.accept(name, self._Human__doneFlattenSuperLow) taskMgr.remove(name) taskMgr.add(self.flattenSuperLowTask, name, extraArgs=[model], taskChain='background') def flattenSuperLowTask(self, model): model = model.copyTo(NodePath()) rhn = model.find('**/rightHand') lhn = model.find('**/leftHand') if lhn: lhn.detachNode() if rhn: rhn.detachNode() node = model.node() gr = SceneGraphReducer() model.node().setAttrib(TransparencyAttrib.make(0), 2000) gr.applyAttribs( node, SceneGraphReducer.TTApplyTextureColor | SceneGraphReducer.TTTexMatrix | SceneGraphReducer.TTOther | SceneGraphReducer.TTCullFace | SceneGraphReducer.TTTransform | SceneGraphReducer.TTColor | SceneGraphReducer.TTColorScale) num_removed = gr.flatten(node, -1) gr.makeCompatibleState(node) gr.collectVertexData( node, ~(SceneGraphReducer.CVDFormat | SceneGraphReducer.CVDName | SceneGraphReducer.CVDAnimationType)) gr.unify(node, 0) name = self.flattenSuperLowName if name: messenger.send(name, [model], taskChain='default') def _Human__doneFlattenSuperLow(self, flat): self.headNode = flat.find('**/def_head01') self.rootNode = flat.find('**/dx_root') self.getWeaponJoints() orig = self.getLOD('500') orig.getChildren().detach() self.loadModel(flat, lodName='500', copy=False, autoBindAnims=False) self.getWeaponJoints() if hasattr(self, 'animProp') and self.animProp: self.resetAnimProp() self.findAllMatches('**/def_head01').detach() self.findAllMatches('**/dx_root').detach() for lodName in self.getLODNames(): if lodName == '500': self.headNode.reparentTo( self.getLOD(lodName).find('**/+Character')) self.rootNode.reparentTo( self.getLOD(lodName).find('**/+Character')) continue self.headNode.instanceTo( self.getLOD(lodName).find('**/+Character')) self.rootNode.instanceTo( self.getLOD(lodName).find('**/+Character')) self.headEffects.reparentTo(self.headNode) def _Human__doneFlattenHuman(self, models): self.flattenPending = None self.getWeaponJoints() def copyHuman(self, other): self.gender = other.gender self.loaded = other.loaded self.loadAnimatedHead = other.loadAnimatedHead self.rootScale = other.rootScale def delete(self): try: pass except: self.Human_deleted = 1 taskMgr.remove(self._Human__blinkName) name = self.flattenSuperLowName if name: self.flattenSuperLowName = None self.ignore(name) taskMgr.remove(name) if self.dropShadow and not self.dropShadow.isEmpty(): self.deleteDropShadow() del self.eyeFSM self.controlShapes = None self.sliderNames = None Biped.Biped.delete(self) def isDeleted(self): try: if self.Human_deleted == 1: return True except: return False def fixEyes(self): self.eyeLids = {} self.eyeBalls = {} self.eyeIris = {} for lodName in self.getLODNames(): geom = self.getPart('head', lodName) self.eyeLids[lodName] = geom.findAllMatches('**/*eyelid*') self.eyeBalls[lodName] = geom.findAllMatches('**/eye_ball*') self.eyeIris[lodName] = geom.findAllMatches('**/eye_iris*') self.eyeLids[lodName].stash() self.eyeBalls[lodName].unstash() self.eyeIris[lodName].unstash() def makeAnimDict(self, gender, animNames): self.animTable = [] for currAnim in animNames: anim = animNames.get(currAnim) for currAnimName in anim: self.animTable.append([currAnimName, currAnimName]) self.reducedAnimList = self.animTable def forceLoadAnimDict(self): for anim in self.animDict.keys(): self.getAnimControls(anim) def createAnimDict(self, customList=None): filePrefix = 'models/char/m' genderPrefix = 'm' if self.style.gender == 'f': self.type = BodyDefs.femaleFrames[self.style.getBodyShape()] filePrefix = 'models/char/f' genderPrefix = 'f' else: self.type = BodyDefs.maleFrames[self.style.getBodyShape()] if self.reducedAnimList is None: self.animDict = self.prebuiltAnimData[genderPrefix + self.type] return None filePrefix += 'p' animList = self.reducedAnimList self.animDict = {} for anim in animList: animSuffix = '' for i in range(0, len(CustomAnimDict[genderPrefix + self.type])): if anim[0] == CustomAnimDict[genderPrefix + self.type][i]: animSuffix = '_' + genderPrefix + NewModelDict.get( self.type) break continue self.animDict[anim[0]] = filePrefix + '_' + anim[1] + animSuffix return filePrefix def getIsPaid(self): return True def setupGhostNodes(self): lod = NodePath(self.getLODNode()) for node in lod.getChildren(): eyes = node.findAllMatches('**/eye*') if eyes: eyes.wrtReparentTo(eyes[0].getParent().attachNewNode( ModelNode('eyes'))) continue def loadHuman(self, other): other.style = self.style other.gender = self.style.gender other.model.dna = self.style self.createAnimDict() if self.style.gender == 'f': self.headFudgeHpr = Vec3(0, 0, 0) idx = 1 else: self.headFudgeHpr = Vec3(0, 0, 0) idx = 0 other.zombie = self.zombie other.crazyColorSkin = self.crazyColorSkin other.setCrazyColorSkinIndex(self.getCrazyColorSkinIndex()) yieldThread('anim dict') other.isPaid = self.getIsPaid() other.showLOD(2000) yieldThread('showLOD') base.loadingScreen.tick() if other.zombie: other.showZombie() if hasattr(self, 'motionFSM'): self.motionFSM.setAvatar(self) base.loadingScreen.tick() yieldThread('zombie') other.applyBodyShaper() base.loadingScreen.tick() yieldThread('body shaper') base.loadingScreen.tick() other.applyHeadShaper() yieldThread('head shaper') base.loadingScreen.tick() if self.zombie == 2: other.model.eyeBalls.unstash() other.model.irises.stash() elif self.zombie: other.model.eyeBalls.stash() other.model.irises.stash() else: other.model.eyeBalls.unstash() other.model.irises.unstash() base.loadingScreen.tick() self.copyActor(other) base.loadingScreen.tick() self.floorOffsetZ = other.rootNode.getZ() yieldThread('copyActor') self.copyHuman(other) if self.isGhost: self.setupGhostNodes() gnodes = self.getLOD('500').findAllMatches('**/+GeomNode') for node in gnodes: node.setTextureOff(other.model.tattooStage) base.loadingScreen.tick() self.flattenSuperLow() self.rootNode = self.getLOD('500').find('**/dx_root') self.headNode = self.getLOD('500').find('**/def_head01') lodNames = self.getLODNames() self.scaleNode = self.controlJoint(None, 'legs', 'def_scale_jt', lodNames[0]) if len(lodNames) > 1: for i in range(1, len(lodNames)): self.controlJoint(self.scaleNode, 'legs', 'def_scale_jt', lodNames[i]) self.setGlobalScale(self.calcBodyScale()) yieldThread('copyHuman') base.loadingScreen.tick() self.loadAnimsOnAllLODs(self.animDict, 'modelRoot') base.loadingScreen.tick() yieldThread('loadAnims') other.zombie = 0 other.crazyColorSkin = 0 other.setCrazyColorSkinIndex(0) other.showNormal() yieldThread('show normal') self.initializeNametag3d() self.initializeDropShadow() self.setName(self.getName()) yieldThread('misc nodes') base.loadingScreen.tick() self.loaded = 1 def setGlobalScale(self, scale): self.scaleNode.setScale(scale) self.rootScale = scale self.scaleNode.setZ(-(self.floorOffsetZ * (1 - scale))) def initializeMiscNodes(self): self.initializeNametag3d() self.initializeDropShadow() def undoControlJoints(self): self.getGeomNode().getParent().findAllMatches('def_*').detach() self.getGeomNode().getParent().findAllMatches('trs_*').detach() self.findAllMatches('def_*').detach() self.findAllMatches('trs_*').detach() def cleanupHuman(self, gender='m'): self.eyeFSM.request('off') self.undoControlJoints() self.removeCopiedNodes() self.eyeLids = {} self.eyeBalls = {} self.eyeIris = {} self.flush() self.loaded = 0 self.master = 0 def getCrazyColorSkinIndex(self): return self.crazyColorSkinIndex def setCrazyColorSkinIndex(self, index): if len(HumanDNA.crazySkinColors) > index: self.crazyColorSkinIndex = index else: self.notify.warning( '(Human)index: %d is out of bounds for crazyColorSkin: %d' % (index, len(HumanDNA.crazySkinColors))) def generateHuman(self, gender, others, useFaceTex=False): parent = self.getParent() self.detachNode() if gender == 'f': other = others[1] else: other = others[0] if self.loaded: self.cleanupHuman() other.useFaceTex = useFaceTex self.loadHuman(other) if self.isLocal(): self.renderReflection = True self.setRenderReflection() self.resetEffectParent() self.enableMixing() self.reparentTo(parent) def getShadowJoint(self): return self.nametagNodePath def getNametagJoints(self): joints = [] for lodName in self.getLODNames(): bundle = self.getPartBundle('modelRoot', lodName) joint = bundle.findChild('name_tag') if joint: joints.append(joint) continue return joints def _Human__blinkOpenEyes(self, task): if self.eyeFSM.getCurrentState().getName() == 'closed': self.eyeFSM.request('open') r = self.randGen.random() if r < 0.10000000000000001: t = 0.20000000000000001 else: t = r * 4.0 + 1.0 taskMgr.doMethodLater(t, self._Human__blinkCloseEyes, self._Human__blinkName) return Task.done def _Human__blinkCloseEyes(self, task): if self.eyeFSM.getCurrentState().getName() != 'open': taskMgr.doMethodLater(4.0, self._Human__blinkCloseEyes, self._Human__blinkName) else: self.eyeFSM.request('closed') taskMgr.doMethodLater(0.125, self._Human__blinkOpenEyes, self._Human__blinkName) return Task.done def startBlink(self): taskMgr.remove(self._Human__blinkName) if self.eyeLids: self.openEyes() taskMgr.doMethodLater(self.randGen.random() * 4.0 + 1, self._Human__blinkCloseEyes, self._Human__blinkName) def stopBlink(self): taskMgr.remove(self._Human__blinkName) if self.eyeLids: self.eyeFSM.request('open') def closeEyes(self): self.eyeFSM.request('closed') def openEyes(self): self.eyeFSM.request('open') def enterEyeFSMOff(self): pass def exitEyeFSMOff(self): pass def enterEyeFSMOpen(self): for lodName in self.getLODNames(): self.eyeLids[lodName].hide() self.eyeBalls[lodName].show() self.eyeIris[lodName].show() def exitEyeFSMOpen(self): pass def enterEyeFSMClosed(self): return None for lodName in self.getLODNames(): self.eyeLids[lodName].show() self.eyeBalls[lodName].hide() self.eyeIris[lodName].hide() def exitEyeFSMClosed(self): pass def getGlobalScale(self): return self.rootScale def calcBodyScale(self): idx = 0 if self.gender == 'f': idx = 1 mappedValue = (0.80000000000000004 + (1 + self.style.getBodyHeight()) * 0.20000000000000001 ) * BodyScales[idx][self.style.getBodyShape()] return mappedValue def setupAnimDicts(cls): for t in BodyDefs.maleFrames: cls.storeAnimDict('models/char/mp', 'm', t) for t in BodyDefs.femaleFrames: cls.storeAnimDict('models/char/fp', 'f', t) setupAnimDicts = classmethod(setupAnimDicts) def storeAnimDict(cls, prefix, gender, type): qualifier = gender + type animList = AnimListDict[type] cls.prebuiltAnimData[qualifier] = {} for anim in animList: if anim[0] == 'intro': continue animSuffix = '' for i in range(0, len(CustomAnimDict[qualifier])): if anim[0] == CustomAnimDict[qualifier][i]: animSuffix = '_' + gender + NewModelDict.get(type) break continue cls.prebuiltAnimData[qualifier][ anim[0]] = prefix + '_' + anim[1] + animSuffix storeAnimDict = classmethod(storeAnimDict)
class CogInvasionClientRepository(AstronClientRepository): notify = directNotify.newCategory("CIClientRepository") GameGlobalsId = DO_ID_COGINVASION SetZoneDoneEvent = 'CICRSetZoneDone' EmuSetZoneDoneEvent = 'CICREmuSetZoneDone' SetInterest = 'Set' ClearInterest = 'Clear' ClearInterestDoneEvent = 'CICRClearInterestDone' ITAG_PERM = 'perm' ITAG_AVATAR = 'avatar' ITAG_SHARD = 'shard' ITAG_WORLD = 'world' ITAG_GAME = 'game' def __init__(self, serverVersion): self.serverVersion = serverVersion AstronClientRepository.__init__( self, ['phase_3/etc/direct.dc', 'phase_3/etc/toon.dc']) self.loginFSM = ClassicFSM('login', [ State('off', self.enterOff, self.exitOff), State('connect', self.enterConnect, self.exitConnect), State('disconnect', self.enterDisconnect, self.exitDisconnect), State('avChoose', self.enterAvChoose, self.exitAvChoose), State('playingGame', self.enterPlayingGame, self.exitPlayingGame), State('serverUnavailable', self.enterServerUnavailable, self.exitServerUnavailable), State('makeAToon', self.enterMakeAToon, self.exitMakeAToon), State('submitNewToon', self.enterSubmitNewToon, self.exitSubmitNewToon), State('noShards', self.enterNoShards, self.exitNoShards), State('waitForSetAvatarResponse', self.enterWaitForSetAvatarResponse, self.exitWaitForSetAvatarResponse), State('waitForShardList', self.enterWaitForShardList, self.exitWaitForShardList), State('ejected', self.enterEjected, self.exitEjected), State('districtReset', self.enterDistrictReset, self.exitDistrictReset), State('died', self.enterDied, self.exitDied), State('betaInform', self.enterBetaInform, self.exitBetaInform) ], 'off', 'off') self.loginFSM.enterInitialState() self.gameFSM = ClassicFSM('game', [ State('off', self.enterGameOff, self.exitGameOff), State('waitForGameEnterResponse', self.enterWaitForGameEnterResponse, self.exitWaitForGameEnterResponse), State('playGame', self.enterPlayGame, self.exitPlayGame), State('closeShard', self.enterCloseShard, self.exitCloseShard), State('switchShards', self.enterSwitchShards, self.exitSwitchShards) ], 'off', 'off') self.gameFSM.enterInitialState() #self.taskNameAllocator = UniqueIdAllocator(0, 1000000000) self.avChooser = AvChooser(self.loginFSM) self.playGame = PlayGame(self.gameFSM, "playGameDone") self.hoodMgr = HoodMgr() self.makeAToon = MakeAToon() self.loginToken = os.environ.get("LOGIN_TOKEN") self.serverAddress = os.environ.get("GAME_SERVER") self.serverURL = URLSpec("http://%s" % self.serverAddress) self.parentMgr.registerParent(CIGlobals.SPRender, render) self.parentMgr.registerParent(CIGlobals.SPHidden, hidden) self.adminAccess = False self.localAvChoice = None self.SuitsActive = 0 self.BossActive = 0 self.accServerTimesNA = 0 self.maxAccServerTimesNA = 10 self.setZonesEmulated = 0 self.old_setzone_interest_handle = None self.setZoneQueue = Queue() self.accept(self.SetZoneDoneEvent, self._handleEmuSetZoneDone) self.handler = None self.__currentAvId = 0 self.myDistrict = None self.activeDistricts = {} self.shardListHandle = None self.uberZoneInterest = None self.isShowingPlayerIds = False self.doBetaInform = False self.dTutorial = None self.requestedName = None self.whisperNoise = base.loadSfx( 'phase_3.5/audio/sfx/GUI_whisper_3.ogg') self.checkHttp() #self.http.addPreapprovedServerCertificateFilename(self.serverURL, Filename('phase_3/etc/gameserver.crt')) #self.tournamentMusicChunks = {} #self.threadedTaskChain = taskMgr.setupTaskChain("threadedTaskChainForSoundIntervals", numThreads = 2) self.attackMgr = base.cl_attackMgr base.minigame = None self.newToonSlot = None base.finalExitCallbacks.insert(0, self.__handleExit) self.accountName = os.environ.get('ACCOUNT_NAME', '') self.csm = self.generateGlobalObject(DO_ID_CLIENT_SERVICES_MANAGER, 'ClientServicesManager') self.friendsManager = self.generateGlobalObject( DO_ID_FRIENDS_MANAGER, 'FriendsManager') self.uin = self.generateGlobalObject(DO_ID_UNIQUE_INTEREST_NOTIFIER, 'UniqueInterestNotifier') self.statsManager = self.generateGlobalObject(DO_ID_STATS_MANAGER, 'StatsManager') self.pingToggle = False self.currentPing = None self.pingText = OnscreenText("", align=TextNode.ALeft, parent=base.a2dBottomLeft, fg=(1, 1, 1, 1), shadow=(0, 0, 0, 0.5), pos=(0.3, 0.09)) self.pingText.setBin('gsg-popup', 1000) self.pingText.hide() SpeedHackChecker.startChecking() self.loginFSM.request('connect') return def readerPollUntilEmpty(self, task): while self.readerPollOnce(): pass if not metadata.IS_PRODUCTION: if ConfigVariableBool('simulated-latency', False).getValue(): latency = random.uniform( ConfigVariableDouble('simulated-latency-min', 0.125).getValue(), ConfigVariableDouble('simulated-latency-max', 0.15).getValue()) task.delayTime = latency return task.again return task.cont def togglePing(self): self.pingToggle = not self.pingToggle if self.pingToggle: taskMgr.add(self.__districtPingTask, "CICR.districtPingTask") self.showPing() else: self.hidePing() taskMgr.remove("CICR.districtPingTask") def showPing(self): self.pingText.show() def hidePing(self): self.pingText.hide() def handleNewPing(self): if self.currentPing is None: display = "?" else: display = int(round(self.currentPing)) self.pingText.setText("Ping: {0} ms".format(display)) def __districtPingTask(self, task): if self.myDistrict: # Figure out how much network latency there is. self.myDistrict.d_ping() task.delayTime = 1.0 return task.again def deleteObject(self, doId): """ implementation copied from AstronClientRepository.py Brian: modified to also delete owner views Removes the object from the client's view of the world. This should normally not be called directly except in the case of error recovery, since the server will normally be responsible for deleting and disabling objects as they go out of scope. After this is called, future updates by server on this object will be ignored (with a warning message). The object will become valid again the next time the server sends a generate message for this doId. This is not a distributed message and does not delete the object on the server or on any other client. """ if doId in self.doId2do: # If it is in the dictionary, remove it. obj = self.doId2do[doId] # Remove it from the dictionary del self.doId2do[doId] # Disable, announce, and delete the object itself... # unless delayDelete is on... obj.deleteOrDelay() if self.isLocalId(doId): self.freeDoId(doId) elif doId in self.doId2ownerView: # If it is in the owner dictionary, remove it. obj = self.doId2ownerView[doId] # Remove it from the dictionary del self.doId2ownerView[doId] # Disable, announce, and delete the object itself... # unless delayDelete is on... obj.deleteOrDelay() if self.isLocalId(doId): self.freeDoId(doId) elif self.cache.contains(doId): # If it is in the cache, remove it. self.cache.delete(doId) if self.isLocalId(doId): self.freeDoId(doId) elif self.cacheOwner.contains(doId): # If it is in the owner cache, remove it. self.cacheOwner.delete(doId) if self.isLocalId(doId): self.freeDoId(doId) else: # Otherwise, ignore it self.notify.warning("Asked to delete non-existent DistObj " + str(doId)) #def uniqueName(self, idString): # return "%s-%s" % (idString, self.taskNameAllocator.allocate()) #def removeTask(self, taskName): # div = taskName.split('-') # self.taskNameAllocator.free(div[1]) # taskMgr.remove(taskName) def __handleExit(self): try: base.localAvatar.b_setAnimState('teleportOut') except: pass ccoginvasion.CTMusicData.stop_am_update_task() self.gameFSM.request('closeShard', ['off']) def isChristmas(self): return self.holidayManager.getHoliday() == HolidayType.CHRISTMAS def showPlayerIds(self): print "Showing player ids..." self.isShowingPlayerIds = True for av in self.doId2do.values(): if av.__class__.__name__ in [ "DistributedPlayerToon", "LocalToon", "DistributedSuit" ]: av.showAvId() def hidePlayerIds(self): print "Hiding player ids..." self.isShowingPlayerIds = False for av in self.doId2do.values(): if av.__class__.__name__ in [ "DistributedPlayerToon", "LocalToon", 'DistributedSuit' ]: av.showName() def sendSetLocation(self, doId, parentId, zoneId): dg = PyDatagram() dg.addUint16(CLIENT_OBJECT_LOCATION) dg.addUint32(doId) dg.addUint32(parentId) dg.addUint32(zoneId) self.send(dg) def getNextSetZoneDoneEvent(self): return '%s-%s' % (self.EmuSetZoneDoneEvent, self.setZonesEmulated + 1) def getLastSetZoneDoneEvent(self): return '%s-%s' % (self.EmuSetZoneDoneEvent, self.setZonesEmulated) def getQuietZoneLeftEvent(self): return 'leftQuietZone-%s' % (id(self), ) def b_setLocation(self, do, parentId, zoneId): self.sendSetLocation(do.doId, parentId, zoneId) do.setLocation(parentId, zoneId) def sendSetZoneMsg(self, zoneId, visibleZoneList=None): event = self.getNextSetZoneDoneEvent() self.setZonesEmulated += 1 parentId = base.localAvatar.defaultShard self.sendSetLocation(base.localAvatar.doId, parentId, zoneId) localAvatar.setLocation(parentId, zoneId) interestZones = zoneId if visibleZoneList is not None: interestZones = visibleZoneList self._addInterestOpToQueue( self.SetInterest, [parentId, interestZones, 'OldSetZoneEmulator'], event) return def resetInterestStateForConnectionLoss(self): self.old_setzone_interest_handle = None self.setZoneQueue.clear() return def _removeEmulatedSetZone(self, doneEvent): self._addInterestOpToQueue(self.ClearInterest, None, doneEvent) return def _addInterestOpToQueue(self, op, args, event): self.setZoneQueue.push([op, args, event]) if len(self.setZoneQueue) == 1: self._sendNextSetZone() def _sendNextSetZone(self): op, args, event = self.setZoneQueue.top() if op == self.SetInterest: parentId, interestZones, name = args if self.old_setzone_interest_handle is None: self.old_setzone_interest_handle = self.addInterest( parentId, interestZones, name, self.SetZoneDoneEvent) else: self.alterInterest(self.old_setzone_interest_handle, parentId, interestZones, name, self.SetZoneDoneEvent) elif op == self.ClearInterest: self.removeInterest(self.old_setzone_interest_handle, self.SetZoneDoneEvent) self.old_setzone_interest_handle = None else: self.notify.error('unknown setZone op: %s' % op) return def _handleEmuSetZoneDone(self): op, args, event = self.setZoneQueue.pop() queueIsEmpty = self.setZoneQueue.isEmpty() if event is not None: messenger.send(event) if not queueIsEmpty: self._sendNextSetZone() return def enterSwitchShards(self, shardId, hoodId, zoneId, avId): self._switchShardParams = [shardId, hoodId, zoneId, avId] self.removeShardInterest(self._handleOldShardGone) def _handleOldShardGone(self): status = {} status['hoodId'] = self._switchShardParams[1] status['zoneId'] = self._switchShardParams[2] status['avId'] = self._switchShardParams[3] self.gameFSM.request('waitForGameEnterResponse', [status, self._switchShardParams[0]]) def exitSwitchShards(self): del self._switchShardParams def enterBetaInform(self): msg = ( "Welcome to Cog Invasion Online!\n\nBefore playing, please remember that the game is in Alpha, " "and that you may encounter bugs and incomplete features.\n\nIf you happen to encounter any bugs, " "please report them to us by using the Contact Us Page at coginvasion.com.\n\nHave fun!" ) self.dialog = GlobalDialog(message=msg, style=3, doneEvent="gameEnterChoice") self.dialog.show() self.acceptOnce("gameEnterChoice", self.handleGameEnterChoice) def handleGameEnterChoice(self): self.loginFSM.request('avChoose') def exitBetaInform(self): self.ignore("gameEnterChoice") self.dialog.cleanup() del self.dialog def enterCloseShard(self, nextState='avChoose'): self.setNoNewInterests(True) self._removeLocalAvFromStateServer(nextState) def exitCloseShard(self): self.setNoNewInterests(False) self.ignore(self.ClearInterestDoneEvent) return def _removeLocalAvFromStateServer(self, nextState): self.sendSetAvatarIdMsg(0) self._removeAllOV() callback = Functor(self.loginFSM.request, nextState) self.removeShardInterest(callback) def removeShardInterest(self, callback): self._removeCurrentShardInterest( Functor(self._removeShardInterestComplete, callback)) def _removeShardInterestComplete(self, callback): self.cache.flush() self.doDataCache.flush() callback() return def _removeCurrentShardInterest(self, callback): if self.old_setzone_interest_handle is None: callback() return self.acceptOnce(self.ClearInterestDoneEvent, Functor(self._removeCurrentUberZoneInterest, callback)) self._removeEmulatedSetZone(self.ClearInterestDoneEvent) return def _removeCurrentUberZoneInterest(self, callback): self.acceptOnce(self.ClearInterestDoneEvent, Functor(self._removeShardInterestDone, callback)) self.removeInterest(self.uberZoneInterest, self.ClearInterestDoneEvent) def _removeShardInterestDone(self, callback): self.uberZoneInterest = None callback() return def _removeAllOV(self): owners = self.doId2ownerView.keys() for doId in owners: self.disableDoId(doId, ownerView=True) def enterDied(self): self.deathDialog = GlobalDialog(message=CIGlobals.SuitDefeatMsg, style=2, doneEvent="deathChoice") self.deathDialog.show() self.acceptOnce("deathChoice", self.handleDeathChoice) def handleDeathChoice(self): value = self.deathDialog.getValue() if value: self.loginFSM.request('avChoose') else: sys.exit() def exitDied(self): self.deathDialog.cleanup() del self.deathDialog self.ignore("deathChoice") def enterConnect(self): self.connectingDialog = GlobalDialog(message=CIGlobals.ConnectingMsg) self.connectingDialog.show() self.connect([self.serverURL], successCallback=self.handleConnected, failureCallback=self.handleConnectFail) def handleConnected(self): self.notify.info("Sending CLIENT_HELLO...") self.acceptOnce("CLIENT_HELLO_RESP", self.handleClientHelloResp) self.acceptOnce("CLIENT_EJECT", self.handleEjected) self.acceptOnce("LOST_CONNECTION", self.handleLostConnection) AstronClientRepository.sendHello(self, self.serverVersion) def handleLostConnection(self): self.deleteAllObjects() self.loginFSM.request('disconnect', [1]) def deleteAllObjects(self): for doId in self.doId2do.keys(): obj = self.doId2do[doId] if not isinstance(obj, DistributedObjectGlobal) and not hasattr( obj, 'isDistrict'): if hasattr(base, 'localAvatar') and doId != base.localAvatar.doId: self.deleteObject(doId) def handleEjected(self, errorCode, reason): self.notify.info("OMG I WAS EJECTED!") self.ignore("LOST_CONNECTION") errorMsg = ErrorCode2ErrorMsg.get(errorCode, None) or UnknownErrorMsg % errorCode self.loginFSM.request('ejected', [errorMsg]) def handleClientHelloResp(self): self.notify.info("Got CLIENT_HELLO_RESP!") self.acceptOnce(self.csm.getLoginAcceptedEvent(), self.handleLoginAccepted) self.csm.d_requestLogin(self.loginToken, self.accountName) def handleLoginAccepted(self): self.notify.info("Woo-hoo, I am authenticated!") base.cr.holidayManager = self.generateGlobalObject( DO_ID_HOLIDAY_MANAGER, 'HolidayManager') base.cr.nameServicesManager = self.generateGlobalObject( DO_ID_NAME_SERVICES_MANAGER, 'NameServicesManager') self.loginFSM.request('waitForShardList') def handleConnectFail(self, _, __): self.notify.info("Could not connect to gameserver, notifying user.") self.connectingDialog.cleanup() self.connectingDialog = GlobalDialog( message=CIGlobals.NoConnectionMsg % self.serverAddress + " " + CIGlobals.TryAgain, style=2, doneEvent="connectFail") self.connectingDialog.show() self.acceptOnce("connectFail", self.handleConnectFailButton) def handleConnectFailButton(self): value = self.connectingDialog.getValue() if value: self.loginFSM.request('connect') else: sys.exit() def exitConnect(self): self.ignore("connectFail") self.ignore("CLIENT_HELLO_RESP") self.ignore(self.csm.getLoginAcceptedEvent()) self.connectingDialog.cleanup() del self.connectingDialog def enterEjected(self, errorMsg): self.ejectDialog = GlobalDialog(message=errorMsg, style=3, doneEvent='ejectDone') self.ejectDialog.show() self.acceptOnce('ejectDone', sys.exit) def exitEjected(self): self.ignore('ejectDone') self.ejectDialog.cleanup() del self.ejectDialog def enterServerUnavailable(self): self.notify.info(CIGlobals.ServerUnavailable) self.serverNA = GlobalDialog(message=CIGlobals.ServerUnavailable, style=4, doneEvent="serverNAEvent") self.serverNA.show() self.acceptOnce("serverNAEvent", sys.exit) self.startServerNAPoll() def startServerNAPoll(self): self.notify.info("Starting server poll...") self.accServerTimesNA = 1 taskMgr.add(self.serverNAPoll, "serverNAPoll") def serverNAPoll(self, task): dg = PyDatagram() dg.addUint16(ACC_IS_SERVER_UP) self.send(dg) task.delayTime = 3.0 return Task.again def __handleServerNAResp(self, resp): if resp == ACC_SERVER_UP: taskMgr.remove("serverNAPoll") # Enter the previous state that we were in, which should have # been some state where we communicate with the acc server. self.loginFSM.request(self.loginFSM.getLastState().getName()) else: self.accServerTimesNA += 1 if self.accServerTimesNA >= self.maxAccServerTimesNA: taskMgr.remove("serverNAPoll") self.notify.info( "Giving up on polling account server after %s times." % self.accServerTimesNA) self.loginFSM.request("disconnect", enterArgList=[1]) self.accServerTimesNA = 0 def exitServerUnavailable(self): self.ignore("serverNAEvent") self.serverNA.cleanup() del self.serverNA def enterOff(self): pass def exitOff(self): pass def playTheme(self): base.playMusic(CIGlobals.getThemeSong(), looping=1) def enterAvChoose(self, newToonSlot=None): ModelPool.garbageCollect() TexturePool.garbageCollect() self.avChooser.load() self.avChooser.enter(newToonSlot) if newToonSlot is None: self.playTheme() self.accept("enterMakeAToon", self.__handleMakeAToonReq) self.accept("avChooseDone", self.__handleAvChooseDone) def __handleMakeAToonReq(self, slot): self.loginFSM.request('makeAToon', [slot]) def __handleAvChooseDone(self, avChoice): print "------- AvChooseDone -------" print "Toon name: %s" % avChoice.getName() print "Slot: %s" % avChoice.getSlot() print "DNA: %s" % avChoice.getDNA() self.loginFSM.request("waitForSetAvatarResponse", [avChoice]) def exitAvChoose(self): self.avChooser.exit() self.avChooser.unload() self.ignore("enterMakeAToon") self.ignore("avChooseDone") def handlePlayGame(self, msgType, di): if msgType == CLIENT_ENTER_OBJECT_REQUIRED_OTHER_OWNER: self.handleGenerateWithRequiredOtherOwner(msgType, di) else: AstronClientRepository.handleDatagram(self, di) def enterPlayingGame(self): zoneId = localAvatar.getLastHood() hoodId = ZoneUtil.getHoodId(zoneId) status = {"hoodId": hoodId, "zoneId": zoneId, "avId": self.localAvId} shardId = self.myDistrict.doId self.gameFSM.request('waitForGameEnterResponse', [status, shardId]) def exitPlayingGame(self): self.deleteAllObjects() self.handler = None self.gameFSM.request('off') camera.reparentTo(render) camera.setPos(0, 0, 0) camera.setHpr(0, 0, 0) self.localAvChoice = None if loader.inBulkBlock: loader.endBulkLoad(loader.blockName) def enterNoShards(self): self.noShardDialog = GlobalDialog(message=CIGlobals.NoShardsMsg + " " + CIGlobals.TryAgain, style=2, doneEvent='noShardsDone') self.noShardDialog.show() self.acceptOnce('noShardsDone', self.handleNoShardsDone) def handleNoShardsDone(self): value = self.noShardDialog.getValue() if value: self.loginFSM.request('waitForShardList') else: sys.exit() def exitNoShards(self): self.noShardDialog.cleanup() del self.noShardDialog self.ignore('noShardsDone') def enterWaitForShardList(self): self.shardListHandle = self.addTaggedInterest( self.GameGlobalsId, ZoneUtil.DistrictZone, self.ITAG_PERM, 'localShardList', event='shardList_complete') self.acceptOnce('shardList_complete', self._handleShardListComplete) def _handleShardListComplete(self): if self._shardsAreAvailable(): self.myDistrict = self._chooseAShard() if self.doBetaInform: self.loginFSM.request('betaInform') else: self.loginFSM.request('avChoose') taskMgr.add(self.monitorDistrict, "monitorMyDistrict") else: self.loginFSM.request('noShards') def monitorDistrict(self, task): if self.myDistrict is None and self.isConnected(): self.loginFSM.request('districtReset') return task.done return task.cont def _shardsAreAvailable(self): for shard in self.activeDistricts.values(): if shard.available: return True return False def _chooseAShard(self): choices = [] for shard in self.activeDistricts.values(): choices.append(shard) return random.choice(choices) def exitWaitForShardList(self): self.ignore('shardList_complete') def enterDistrictReset(self): self.districtResetDialog = GlobalDialog( message=CIGlobals.DistrictResetMsg, style=3, doneEvent='distresetdone') self.districtResetDialog.show() self.acceptOnce('distresetdone', sys.exit) def exitDistrictReset(self): self.districtResetDialog.cleanup() del self.districtResetDialog def enterWaitForSetAvatarResponse(self, choice): #self.acceptOnce(self.csm.getSetAvatarEvent(), self.__handleSetAvatarResponse) self.sendSetAvatarMsg(choice) def enterLoadDone(self): self.loginFSM.request("playingGame") def __handleSetAvatarResponse(self, avId, di): print "Entering game..." enterLoad = EnterLoad(self.enterLoadDone) dclass = self.dclassesByName['DistributedPlayerToon'] localAvatar = LocalToon.LocalToon(base.cr) localAvatar.dclass = dclass base.localAvatar = localAvatar __builtins__['localAvatar'] = base.localAvatar localAvatar.doId = avId self.localAvId = avId parentId = None zoneId = None localAvatar.setLocation(parentId, zoneId) localAvatar.generateInit() localAvatar.generate() dclass.receiveUpdateBroadcastRequiredOwner(localAvatar, di) localAvatar.announceGenerate() localAvatar.postGenerateMessage() self.doId2do[avId] = localAvatar # TEMPORARY: #localAvatar.hoodsDiscovered = [1000, 2000, 3000, 4000, 5000, 9000] #localAvatar.teleportAccess = [1000, 2000, 3000, 4000, 5000, 9000] enterLoad.load() del enterLoad def exitWaitForSetAvatarResponse(self): self.ignore(self.csm.getSetAvatarEvent()) def enterWaitForGameEnterResponse(self, status, shardId): if shardId is not None: district = self.activeDistricts[shardId] else: district = None if not district: self.loginFSM.request('noShards') return else: self.myDistrict = district self.notify.info("Entering shard %s" % shardId) localAvatar.setLocation(shardId, status['zoneId']) localAvatar.defaultShard = shardId self.handleEnteredShard(status) return def handleEnteredShard(self, status): self.uberZoneInterest = self.addInterest(localAvatar.defaultShard, ZoneUtil.UberZone, 'uberZone', 'uberZoneInterestComplete') self.acceptOnce('uberZoneInterestComplete', self.uberZoneInterestComplete, [status]) def uberZoneInterestComplete(self, status): self.__gotTimeSync = 0 if self.timeManager is None: print "No time manager" DistributedSmoothNode.globalActivateSmoothing(0, 0) self.gotTimeSync(status) else: print "Time manager found" DistributedSmoothNode.globalActivateSmoothing(1, 0) #h = HashVal() #hashPrcVariables(h) #pyc = HashVal() #if not __dev__: # self.hashFiles(pyc) #self.timeManager.d_setSignature(self.userSignature, h.asBin(), pyc.asBin()) #self.timeManager.sendCpuInfo() self.timeManager.lastAttempt = -self.timeManager.minWait * 2 if self.timeManager.synchronize('startup'): self.accept('gotTimeSync', self.gotTimeSync, [status]) else: self.gotTimeSync(status) return def getPing(self): if self.myDistrict: return self.myDistrict.currentPing return 0 def exitWaitForGameEnterResponse(self): self.ignore('uberZoneInterestComplete') return def gotTimeSync(self, status): self.notify.info('gotTimeSync') self.ignore('gotTimeSync') self.__gotTimeSync = 1 self.prepareToEnter(status) def prepareToEnter(self, status): if not self.__gotTimeSync: self.notify.info("still waiting for time sync") return self.gameFSM.request('playGame', [status]) def enterMakeAToon(self, slot): base.stopMusic() self.makeAToon.setSlot(slot) self.makeAToon.loadEnviron() self.makeAToon.load() self.makeAToon.matFSM.request('genderShop') self.acceptOnce("quitCreateAToon", self.__handleMakeAToonQuit) self.acceptOnce("createAToonFinished", self.__handleMakeAToonDone) def __handleMakeAToonQuit(self): self.loginFSM.request("avChoose") def __handleMakeAToonDone(self, dnaStrand, slot, name): self.loginFSM.request('submitNewToon', enterArgList=[dnaStrand, slot, name]) def exitMakeAToon(self): self.makeAToon.setSlot(-1) self.makeAToon.enterExit(None) self.ignore("quitCreateAToon") self.ignore("createAToonFinished") def enterSubmitNewToon(self, dnaStrand, slot, name, skipTutorial=0): self.newToonSlot = slot self.submittingDialog = GlobalDialog(message=CIGlobals.Submitting) self.submittingDialog.show() self.acceptOnce(self.csm.getToonCreatedEvent(), self.__handleSubmitNewToonResp) self.csm.sendSubmitNewToon(dnaStrand, slot, name, skipTutorial) def __handleSubmitNewToonResp(self, avId): # Now that our toon exists in the database, we can add send over the name we wanted to NameServicesManagerUD. if self.requestedName is not None: self.nameServicesManager.d_requestName(self.requestedName, avId) self.requestedName = None self.loginFSM.request('avChoose', [self.newToonSlot]) def exitSubmitNewToon(self): self.newToonSlot = None self.ignore(self.csm.getToonCreatedEvent()) self.submittingDialog.cleanup() del self.submittingDialog def enterGameOff(self): pass def exitGameOff(self): pass def enterPlayGame(self, status): base.stopMusic() base.transitions.noFade() if self.localAvChoice is None: self.notify.error( "called enterPlayGame() without self.localAvChoice being set!") return if localAvatar.getTutorialCompleted() == 1: zoneId = status['zoneId'] hoodId = status['hoodId'] avId = status['avId'] self.playGame.load() self.playGame.enter(hoodId, zoneId, avId) else: self.sendQuietZoneRequest() localAvatar.sendUpdate('createTutorial') self.myDistrict.d_joining() def tutorialCreated(self, zoneId): # zoneId = the zone the tutorial resides in # tutId = the doId of the tutorial requestStatus = {'zoneId': zoneId} self.tutQuietZoneState = QuietZoneState('tutQuietZoneDone') self.tutQuietZoneState.load() self.tutQuietZoneState.enter(requestStatus) self.acceptOnce('tutQuietZoneDone', self.__handleTutQuietZoneDone) def __handleTutQuietZoneDone(self): # We've entered the zone that the tutorial is in. self.tutQuietZoneState.exit() self.tutQuietZoneState.unload() del self.tutQuietZoneState def exitPlayGame(self): self.ignore('tutQuietZoneDone') if hasattr(self, 'tutQuietZoneDone'): self.tutQuietZoneState.exit() self.tutQuietZoneState.unload() del self.tutQuietZoneState base.stopMusic() self.playGame.exit() self.playGame.unload() def enterDisconnect(self, isPlaying, booted=0, bootReason=None): self.notify.info( "Disconnect details: isPlaying = %s, booted = %s, bootReason = %s" % (isPlaying, booted, bootReason)) style = 3 if isPlaying == 1: if not booted: msg = CIGlobals.DisconnectionMsg else: if not booted: msg = CIGlobals.JoinFailureMsg if self.isConnected(): self.sendDisconnect() self.disconnectDialog = GlobalDialog(message=msg, style=style, doneEvent="disconnectDone") self.disconnectDialog.show() if style == 3: self.acceptOnce("disconnectDone", sys.exit) else: self.acceptOnce("disconnectDone", self.handleDisconnectDone) def handleDisconnectDone(self): value = self.disconnectDialog.getValue() if value: self.loginFSM.request('connect') else: sys.exit() def exitDisconnect(self): self.ignore("disconnectDone") self.disconnectDialog.cleanup() del self.disconnectDialog def renderFrame(self): gsg = base.win.getGsg() if gsg: render2d.prepareScene(gsg) base.graphicsEngine.renderFrame() def renderFrames(self): base.graphicsEngine.renderFrame() base.graphicsEngine.renderFrame() def handleDatagram(self, di): if self.notify.getDebug(): print "ClientRepository received datagram:" #di.getDatagram().dumpHex(ostream) msgType = self.getMsgType() self.currentSenderId = None if self.handler is None: self.astronHandle(di) else: self.handler(msgType, di) self.considerHeartbeat() def astronHandle(self, di): AstronClientRepository.handleDatagram(self, di) def handleQuietZoneGenerateWithRequired(self, di): doId = di.getUint32() parentId = di.getUint32() zoneId = di.getUint32() classId = di.getUint16() dclass = self.dclassesByNumber[classId] if dclass.getClassDef().neverDisable: dclass.startGenerate() distObj = self.generateWithRequiredFields(dclass, doId, di, parentId, zoneId) dclass.stopGenerate() def handleQuietZoneGenerateWithRequiredOther(self, di): doId = di.getUint32() parentId = di.getUint32() zoneId = di.getUint32() classId = di.getUint16() dclass = self.dclassesByNumber[classId] if dclass.getClassDef().neverDisable: dclass.startGenerate() distObj = self.generateWithRequiredOtherFields( dclass, doId, di, parentId, zoneId) dclass.stopGenerate() def handleQuietZoneUpdateField(self, di): di2 = DatagramIterator(di) doId = di2.getUint32() if doId in self.deferredDoIds: args, deferrable, dg0, updates = self.deferredDoIds[doId] dclass = args[2] if not dclass.getClassDef().neverDisable: return else: do = self.getDo(doId) if do: if not do.neverDisable: return AstronClientRepository.handleUpdateField(self, di) def handleDelete(self, di): doId = di.getUint32() self.deleteObject(doId) def _abandonShard(self): for doId, obj in self.doId2do.items(): if obj.parentId == localAvatar.defaultShard and obj is not localAvatar: self.deleteObject(doId) def handleEnterObjectRequiredOwner(self, di): if self.loginFSM.getCurrentState().getName( ) == 'waitForSetAvatarResponse': doId = di.getUint32() parentId = di.getUint32() zoneId = di.getUint32() dclassId = di.getUint16() self.__handleSetAvatarResponse(doId, di) else: AstronClientRepository.handleEnterObjectRequiredOwner(self, di) def addTaggedInterest(self, parentId, zoneId, mainTag, desc, otherTags=[], event=None): return self.addInterest(parentId, zoneId, desc, event) def sendSetAvatarMsg(self, choice): avId = choice.getAvId() self.sendSetAvatarIdMsg(avId) self.localAvChoice = choice def sendSetAvatarIdMsg(self, avId): if avId != self.__currentAvId: self.__currentAvId = avId self.csm.sendSetAvatar(avId) def sendQuietZoneRequest(self): self.sendSetZoneMsg(ZoneUtil.QuietZone)
class DistributedWeatherCycleAI(DistributedObjectAI): notify = DirectNotifyGlobal.directNotify.newCategory( 'DistributedWeatherCycleAI') def __init__(self, air): DistributedObjectAI.__init__(self, air) self.fsm = ClassicFSM(self.__class__.__name__, [ State('off', self.enterOff, self.exitOff, ['morning']), State('morning', self.enterMorning, self.exitMorning, ['afternoon']), State('afternoon', self.enterAfternoon, self.exitAfternoon, ['evening']), State('evening', self.enterEvening, self.exitEvening, ['midnight']), State('midnight', self.enterMidnight, self.exitMidnight, ['morning']) ], 'off', 'off') self.fsm.enterInitialState() self.duration = 0 def generate(self): DistributedObjectAI.generate(self) def announceGenerate(self): DistributedObjectAI.announceGenerate(self) taskMgr.doMethodLater(self.getDuration(), self.update, 'update-time') def delete(self): DistributedObjectAI.delete(self) taskMgr.remove('update-time') def update(self, task): self.b_setState(self.fsm.getCurrentState()._State__transitions[0]) return task.again def setState(self, state): self.fsm.request(state) def d_setState(self, state): self.sendUpdate('setState', [state]) def b_setState(self, state): self.setState(state) self.d_setState(state) def getState(self): return self.fsm.getCurrentState()._State__name def setDuration(self, duration): self.duration = duration def d_setDuration(self, duration): self.sendUpdate('setDuration', [duration]) def b_setDuration(self, duration): self.setDuration(duration) self.d_setDuration(duration) def getDuration(self): return self.duration def enterOff(self): pass def exitOff(self): pass def enterMorning(self): pass def exitMorning(self): pass def enterAfternoon(self): pass def exitAfternoon(self): pass def enterEvening(self): pass def exitEvening(self): pass def enterMidnight(self): pass def exitMidnight(self): pass
class GameEnemy(Enemy): def __init__(self, arena): Enemy.__init__(self) self.arena = arena self.aiCharacter = None self.spotToken = self.uniqueName('spot') self.lastAnimation = None self.tunnelSequence = None self.hurtSequence = None self.gridPos = None self.fsm = ClassicFSM('GameEnemy', [ State('Off', self.enterOff, self.exitOff), State('TunnelIn', self.enterTunnelIn, self.exitTunnelIn), State('WalkToGrid', self.enterWalkToGrid, self.exitWalkToGrid), State('AttackHQ', self.enterAttackHQ, self.exitAttackHQ), State('Idle', self.enterIdle, self.exitIdle) ], 'Off', 'Off') self.fsm.enterInitialState() def announceDead(self): messenger.send('enemyDied', [self]) def isAlive(self): return self.fsm.getCurrentState() != 'Off' and self.currHP > 0 def delete(self): self.removeFromGame() if self.fsm.getCurrentState().getName() != 'Off': self.fsm.request('Off') if self in self.arena.enemies: self.arena.enemies.remove(self) Enemy.delete(self) def getGridPos(self): if self.gridPos is None: self.gridPos = self.arena.enemyGrid.occupyRandomSpot( self.spotToken) return self.gridPos def enableAI(self): if self.aiCharacter: print('Tried to enable AI when already enabled.') return self.aiCharacter = AICharacter(self.uniqueName('enemy'), self, 10, 12, 16) self.arena.aiWorld.addAiChar(self.aiCharacter) def disableAI(self): if not self.aiCharacter: print('Tried to disable AI when already disabled.') return self.arena.aiWorld.removeAiChar(self.uniqueName('enemy')) self.aiCharacter = None def pauseTunnel(self): if self.tunnelSequence: self.tunnelSequence.pause() self.tunnelSequence = None def setTunnelRunning(self, running): if not self.tunnelSequence: return if running: self.tunnelSequence.resume() else: self.tunnelSequence.pause() def loop(self, animName, restart=1, partName=None, fromFrame=None, toFrame=None): # Keep track of the last played animation. result = Enemy.loop(self, animName, restart, partName, fromFrame, toFrame) self.lastAnimation = animName return result def takeDamage(self): if self.currHP <= 0: return if not self.lastAnimation: self.lastAnimation = self.getCurrentAnim() hpTaken = random.randrange(30, 50) self.currHP = max(0, self.currHP - hpTaken) self.showHpText(-hpTaken) self.updateHealthBar() if self.hurtSequence: self.hurtSequence.pause() if self.currHP > 0: self.hurtSequence = Sequence( Func(self.setTunnelRunning, False), Func(self.getLeftHand().getChildren().hide), Func(self.getRightHand().getChildren().hide), ActorInterval(self, 'pie-small-react'), Func(self.getLeftHand().getChildren().show), Func(self.getRightHand().getChildren().show), Func(self.loop, self.lastAnimation), Func(self.setTunnelRunning, True)) else: self.hurtSequence = Sequence(Func(self.pauseTunnel), self.getExplosionTrack(), Func(self.announceDead)) self.hurtSequence.start() def removeFromGame(self): if self.arena.enemyGrid: self.arena.enemyGrid.releaseSpot(self.spotToken) if self.hurtSequence: self.hurtSequence.pause() self.hurtSequence = None self.pauseTunnel() def enterOff(self): self.removeFromGame() if self.getCurrentAnim() != 'neutral': self.loop('neutral') if self.aiCharacter: self.disableAI() def exitOff(self): pass def enterTunnelIn(self, tunnel): self.pauseTunnel() pivotNode = tunnel.attachNewNode(self.uniqueName('pivotNode')) pivotNode.setPos(tunnelPivotPos) pivotNode.setHpr(0, 0, 0) endX = tunnel.getX(render) * 0.4 pivotLerpDur = pivotDur * (90.0 / pivotAngle) self.reparentTo(pivotNode) self.setPos(0, 0, 0) self.setX(tunnel, endX) startX = self.getX() targetX = startX - random.uniform(1.0, 15.0) self.setHpr(tunnel, 0, 0, 0) pivotNode.setH(-pivotAngle) finalX = startX - random.uniform(10.5, 14.5) finalY = -48 finalPos = Point3(finalX, finalY, 0) self.tunnelSequence = Sequence( Func(self.loop, 'walk'), Parallel( pivotNode.hprInterval(pivotDur, hpr=Point3(0, 0, 0), name=self.uniqueName('tunnelInPivot')), Sequence( Wait(pivotDur - pivotLerpDur), self.posInterval( pivotLerpDur, pos=Point3(targetX, 0, 0), name=self.uniqueName('tunnelInPivotLerpPos')), )), Func(self.wrtReparentTo, render), Func(pivotNode.removeNode), Func(self.headsUp, finalPos), self.posInterval(pivotLerpDur + 1.0, pos=finalPos), Func(self.fsm.request, 'WalkToGrid')) self.tunnelSequence.start() def exitTunnelIn(self): self.pauseTunnel() def enterWalkToGrid(self): pos = self.getGridPos() targetHpr = GameUtils.getHeadsUpHpr(self.getPos(render), pos) targetHpr[0] = PythonUtil.fitDestAngle2Src(self.getH(), targetHpr[0]) hqHpr = GameUtils.getHeadsUpHpr(pos, self.arena.tempHQ.getPos(render)) hqHpr[0] = PythonUtil.fitDestAngle2Src(targetHpr[0], hqHpr[0]) distance = (self.getPos() - pos).length() hDiff = abs(self.getH() - targetHpr.getX()) hqHDiff = abs(targetHpr.getX() - hqHpr.getX()) self.tunnelSequence = Sequence( Func(self.loop, 'walk'), self.hprInterval(hDiff / GameGlobals.EnemyTurnSpeed, targetHpr, blendType='easeInOut'), self.posInterval(distance / GameGlobals.EnemyForwardSpeed, pos, blendType='easeInOut'), self.hprInterval(hqHDiff / GameGlobals.EnemyTurnSpeed, hqHpr, blendType='easeInOut'), Func(self.loop, 'neutral'), Func(self.__reachedGrid)) self.tunnelSequence.start() def exitWalkToGrid(self): pass def __reachedGrid(self): if random.random() > 0.5: self.fsm.request('AttackHQ') else: self.fsm.request('Idle') def enterIdle(self, *args): pos = self.getGridPos() hpr = GameUtils.getHeadsUpHpr(pos, self.arena.tempHQ.getPos(render)) self.reparentTo(render) self.setPosHpr(pos, hpr) if self.getCurrentAnim() != 'neutral': self.loop('neutral') taskMgr.doMethodLater(random.randrange(1.0, 10.0), self.attackNow, self.uniqueName('nextAttack')) def exitIdle(self): taskMgr.remove(self.uniqueName('nextAttack')) def enterAttackHQ(self): attack = EnemyAttacks.chooseAttack(self) hitPoint = self.arena.getHQHitPoint() self.pauseTunnel() self.tunnelSequence = Sequence(attack(self, hitPoint), Func(self.fsm.request, 'Idle')) self.tunnelSequence.start() def exitAttackHQ(self): self.pauseTunnel() def attackNow(self, task): if self.hurtSequence and self.hurtSequence.isPlaying(): return task.again self.fsm.request('AttackHQ')
class Toon(Avatar.Avatar, ToonHead, ToonDNA.ToonDNA): def __init__(self, cr, mat=0): self.cr = cr try: self.Toon_initialized return except: self.Toon_initialized = 1 Avatar.Avatar.__init__(self, mat) ToonDNA.ToonDNA.__init__(self) ToonHead.__init__(self, cr) self.forwardSpeed = 0.0 self.rotateSpeed = 0.0 self.strafeSpeed = 0.0 self.avatarType = CIGlobals.Toon self.track = None self.standWalkRunReverse = None self.playingAnim = None self.playingRate = None self.tag = None self.money = 0 self.lookAtTrack = None self.portal1 = None self.portal2 = None self.gunAttached = False self.gun = None self.tokenIcon = None self.tokenIconIval = None self.forcedTorsoAnim = None self.fallSfx = base.audio3d.loadSfx( "phase_4/audio/sfx/MG_cannon_hit_dirt.ogg") base.audio3d.attachSoundToObject(self.fallSfx, self) self.eyes = loader.loadTexture("phase_3/maps/eyes.jpg", "phase_3/maps/eyes_a.rgb") self.myTaskId = random.uniform(0, 1231231232132131231232) self.closedEyes = loader.loadTexture("phase_3/maps/eyesClosed.jpg", "phase_3/maps/eyesClosed_a.rgb") self.soundChatBubble = loader.loadSfx( "phase_3/audio/sfx/GUI_balloon_popup.ogg") self.shadowCaster = None self.chatSoundDict = {} self.backpack = None self.animFSM = ClassicFSM('Toon', [ State('off', self.enterOff, self.exitOff), State('neutral', self.enterNeutral, self.exitNeutral), State('swim', self.enterSwim, self.exitSwim), State('walk', self.enterWalk, self.exitWalk), State('run', self.enterRun, self.exitRun), State('openBook', self.enterOpenBook, self.exitOpenBook), State('readBook', self.enterReadBook, self.exitReadBook), State('closeBook', self.enterCloseBook, self.exitCloseBook), State('teleportOut', self.enterTeleportOut, self.exitTeleportOut), State('teleportIn', self.enterTeleportIn, self.exitTeleportIn), State('died', self.enterDied, self.exitDied), State('fallFWD', self.enterFallFWD, self.exitFallFWD), State('fallBCK', self.enterFallBCK, self.exitFallBCK), State('jump', self.enterJump, self.exitJump), State('leap', self.enterLeap, self.exitLeap), State('laugh', self.enterLaugh, self.exitLaugh), State('happy', self.enterHappyJump, self.exitHappyJump), State('shrug', self.enterShrug, self.exitShrug), State('hdance', self.enterHDance, self.exitHDance), State('wave', self.enterWave, self.exitWave), State('scientistEmcee', self.enterScientistEmcee, self.exitScientistEmcee), State('scientistWork', self.enterScientistWork, self.exitScientistWork), State('scientistGame', self.enterScientistGame, self.exitScientistGame), State('scientistJealous', self.enterScientistJealous, self.exitScientistJealous), State('cringe', self.enterCringe, self.exitCringe), State('conked', self.enterConked, self.exitConked), State('win', self.enterWin, self.exitWin), State('walkBack', self.enterWalkBack, self.exitWalkBack), State('deadNeutral', self.enterDeadNeutral, self.exitDeadNeutral), State('deadWalk', self.enterDeadWalk, self.exitDeadWalk), State('squish', self.enterSquish, self.exitSquish), State('Happy', self.enterHappy, self.exitHappy), State('Sad', self.enterSad, self.exitSad) ], 'off', 'off') animStateList = self.animFSM.getStates() self.animFSM.enterInitialState() if not hasattr(base, 'localAvatar') or not base.localAvatar == self: Avatar.Avatar.initializeBodyCollisions(self, self.avatarType, 3, 1) def showAvId(self): pass def showName(self): pass 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 enterHappy(self, ts=0, callback=None, extraArgs=[]): self.playingAnim = None self.standWalkRunReverse = (('neutral', 1.0), ('walk', 1.0), ('run', 1.0), ('walk', -1.0), ('strafe', 1.0), ('strafe', -1.0)) self.setSpeed(self.forwardSpeed, self.rotateSpeed) def exitHappy(self): self.standWalkRunReverse = None self.stop() def enterSad(self, ts=0, callback=None, extraArgs=[]): self.playingAnim = 'sad' self.standWalkRunReverse = (('dneutral', 1.0), ('dwalk', 1.2), ('dwalk', 1.2), ('dwalk', -1.0)) self.setSpeed(0, 0) def exitSad(self): self.standWalkRunReverse = None self.stop() #if hasattr(self, 'doId'): # if hasattr(base, 'localAvatar'): # if base.localAvatar.doId == self.doId: # self.controlManager.enableAvatarJump() def setSpeed(self, forwardSpeed, rotateSpeed, strafeSpeed=0.0): self.forwardSpeed = forwardSpeed self.rotateSpeed = rotateSpeed self.strafeSpeed = strafeSpeed action = None if self.standWalkRunReverse != None: if (forwardSpeed >= CIGlobals.RunCutOff and strafeSpeed < CIGlobals.RunCutOff and strafeSpeed > -CIGlobals.RunCutOff): action = CIGlobals.RUN_INDEX elif strafeSpeed >= CIGlobals.RunCutOff or strafeSpeed <= -CIGlobals.RunCutOff: if strafeSpeed > 0: action = CIGlobals.STRAFE_RIGHT_INDEX elif strafeSpeed < 0: action = CIGlobals.STRAFE_LEFT_INDEX elif forwardSpeed > CIGlobals.WalkCutOff: action = CIGlobals.WALK_INDEX elif forwardSpeed < -CIGlobals.WalkCutOff: action = CIGlobals.REVERSE_INDEX elif rotateSpeed != 0.0: action = CIGlobals.WALK_INDEX else: action = CIGlobals.STAND_INDEX anim, rate = self.standWalkRunReverse[action] if anim != self.playingAnim or rate != self.playingRate: self.playingAnim = anim self.playingRate = rate doingGagAnim = False if self.backpack: if self.backpack.getCurrentGag(): if self.backpack.getCurrentGag().getState() in [ GagState.START, GagState.RELEASED ]: doingGagAnim = True self.loop(anim, partName="legs") if self.animal == "dog": self.loop(anim, partName="head") if not doingGagAnim: if self.forcedTorsoAnim == None: self.loop(anim) else: self.loop(self.forcedTorsoAnim, partName='head') self.loop(self.forcedTorsoAnim, partName='torso') self.loop(anim, partName='legs') self.setPlayRate(rate, anim) return action def enterSquish(self, ts=0, callback=None, extraArgs=[]): self.playingAnim = 'squish' sound = loader.loadSfx('phase_9/audio/sfx/toon_decompress.ogg') lerpTime = 0.1 node = self.getGeomNode().getChild(0) origScale = node.getScale() if hasattr(self, 'uniqueName'): name = self.uniqueName('getSquished') else: name = 'getSquished' 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, 'happy', startTime=0.2), SoundInterval(sound)), name=name) self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getDoneEvent(), self.squishDone, [callback, extraArgs]) self.track.delayDelete = DelayDelete.DelayDelete(self, name) self.track.start(ts) def squishDone(self, callback=None, extraArgs=[]): self.__doCallback(callback, extraArgs) def exitSquish(self): if self.track: self.ignore(self.track.getName()) DelayDelete.cleanupDelayDeletes(self.track) self.track.finish() self.track = None self.playingAnim = 'neutral' def enterDeadNeutral(self, ts=0, callback=None, extraArgs=[]): self.loop('dneutral') def exitDeadNeutral(self): self.stop() def enterDeadWalk(self, ts=0, callback=None, extraArgs=[]): self.loop('dwalk') def exitDeadWalk(self): self.stop() def setBackpack(self, pack): self.backpack = pack def getGhost(self): return 0 def updateChatSoundDict(self): self.chatSoundDict['exclaim'] = base.audio3d.loadSfx( self.getToonAnimalNoise('exclaim')) self.chatSoundDict['question'] = base.audio3d.loadSfx( self.getToonAnimalNoise('question')) self.chatSoundDict['short'] = base.audio3d.loadSfx( self.getToonAnimalNoise('short')) self.chatSoundDict['medium'] = base.audio3d.loadSfx( self.getToonAnimalNoise('med')) self.chatSoundDict['long'] = base.audio3d.loadSfx( self.getToonAnimalNoise('long')) self.chatSoundDict['howl'] = base.audio3d.loadSfx( self.getToonAnimalNoise('howl')) base.audio3d.attachSoundToObject(self.chatSoundDict['exclaim'], self.getPart('head')) base.audio3d.attachSoundToObject(self.chatSoundDict['question'], self.getPart('head')) base.audio3d.attachSoundToObject(self.chatSoundDict['short'], self.getPart('head')) base.audio3d.attachSoundToObject(self.chatSoundDict['medium'], self.getPart('head')) base.audio3d.attachSoundToObject(self.chatSoundDict['long'], self.getPart('head')) base.audio3d.attachSoundToObject(self.chatSoundDict['howl'], self.getPart('head')) def ghostOn(self): self.getGeomNode().hide() self.nametag3d.hide() self.getShadow().hide() if self.tokenIcon: self.tokenIcon.hide() self.stashBodyCollisions() def ghostOff(self): self.unstashBodyCollisions() if self.tokenIcon: self.tokenIcon.show() self.getShadow().show() self.nametag3d.show() self.getGeomNode().show() def attachGun(self, gunName): self.detachGun() if gunName == "pistol": self.gun = loader.loadModel("phase_4/models/props/water-gun.bam") self.gun.reparentTo(self.find('**/def_joint_right_hold')) self.gun.setPos(Point3(0.28, 0.1, 0.08)) self.gun.setHpr(VBase3(85.6, -4.44, 94.43)) self.gunAttached = True elif gunName == "shotgun": self.gun = loader.loadModel("phase_4/models/props/shotgun.egg") self.gun.setScale(0.75) self.gun.reparentTo(self.find('**/def_joint_right_hold')) self.gun.setPos(Point3(-0.5, -0.2, 0.19)) self.gun.setHpr(Vec3(350, 272.05, 0)) color = random.choice([ VBase4(1, 0.25, 0.25, 1), VBase4(0.25, 1, 0.25, 1), VBase4(0.25, 0.25, 1, 1) ]) self.gun.setColorScale(color) self.gunAttached = True elif gunName == "sniper": self.gun = loader.loadModel("phase_4/models/props/sniper.egg") self.gun.setScale(0.75) self.gun.reparentTo(self.find('**/def_joint_right_hold')) self.gun.setPos(Point3(-0.5, -0.2, 0.19)) self.gun.setHpr(Vec3(350, 272.05, 0)) color = random.choice([ VBase4(1, 0.25, 0.25, 1), VBase4(0.25, 1, 0.25, 1), VBase4(0.25, 0.25, 1, 1) ]) self.gun.setColorScale(color) self.gunAttached = True def detachGun(self): if self.gun and self.gunAttached: self.gun.removeNode() self.gun = None self.gunAttached = False def stopAnimations(self): if hasattr(self, 'animFSM'): if not self.animFSM.isInternalStateInFlux(): self.animFSM.request('off') else: notify.warning( "animFSM in flux, state=%s, not requesting off" % self.animFSM.getCurrentState().getName()) else: notify.warning("animFSM has been deleted") if self.track != None: self.track.finish() DelayDelete.cleanupDelayDeletes(self.track) self.track = None return def disable(self): try: self.Toon_disabled except: self.Toon_disabled = 1 self.backpack = None self.stopAnimations() self.removeAdminToken() ToonHead.delete(self) self.deleteCurrentToon() self.chatSoundDict = {} Avatar.Avatar.disable(self) def delete(self): try: self.Toon_deleted except: self.Toon_deleted = 1 del self.animFSM self.forwardSpeed = None self.chatSoundDict = None self.rotateSpeed = None self.avatarType = None self.track = None self.standWalkRunReverse = None self.currentAnim = None self.toon_head = None self.forcedTorsoAnim = None self.toon_torso = None self.toon_legs = None self.gender = None self.headtype = None self.head = None self.legtype = None self.torsotype = None self.hr = None self.hg = None self.hb = None self.tr = None self.tg = None self.tb = None self.lr = None self.lg = None self.lb = None self.shir = None self.shig = None self.shib = None self.shor = None self.shog = None self.shob = None self.shirt = None self.sleeve = None self.short = None self.tag = None self.money = None self.lookAtTrack = None self.portal1 = None self.portal2 = None self.backpack = None self.fallSfx = None self.eyes = None self.myTaskId = None self.closedEyes = None self.soundChatBubble = None self.lastAction = None self.lastState = None self.playingAnim = None self.playingRate = None Avatar.Avatar.delete(self) return def initCollisions(self): self.collNodePath.setCollideMask(BitMask32(0)) self.collNodePath.node().setFromCollideMask(CIGlobals.WallBitmask) pusher = CollisionHandlerPusher() pusher.setInPattern("%in") pusher.addCollider(self.collNodePath, self) base.cTrav.addCollider(self.collNodePath, pusher) def deleteCurrentToon(self): if self.shadowCaster: self.shadowCaster.clear() self.shadowCaster = None try: self.stopLookAround() self.stopBlink() except: pass self.pupils = [] if 'head' in self._Actor__commonBundleHandles: del self._Actor__commonBundleHandles['head'] if 'torso' in self._Actor__commonBundleHandles: del self._Actor__commonBundleHandles['torso'] if 'legs' in self._Actor__commonBundleHandles: del self._Actor__commonBundleHandles['legs'] self.deleteShadow() self.removePart('head') self.removePart('torso') self.removePart('legs') self.detachGun() def setAdminToken(self, tokenId): if tokenId in ToonGlobals.STAFF_TOKENS.keys(): icons = loader.loadModel("phase_3/models/props/gm_icons.bam") self.tokenIcon = icons.find('**/access_level_%s' % (ToonGlobals.STAFF_TOKENS[tokenId])) self.tokenIcon.reparentTo(self) x = self.nametag3d.getX() y = self.nametag3d.getY() z = self.nametag3d.getZ() self.tokenIcon.setPos(Vec3(x, y, z) + (0, 0, 0.5)) self.tokenIcon.setScale(0.4) self.tokenIconIval = Sequence( LerpHprInterval(self.tokenIcon, duration=3.0, hpr=Vec3(360, 0, 0), startHpr=Vec3(0, 0, 0))) self.tokenIconIval.loop() icons.removeNode() def removeAdminToken(self): if self.tokenIcon != None and self.tokenIconIval != None: self.tokenIconIval.finish() self.tokenIcon.removeNode() self.tokenIconIval = None self.tokenIcon = None def setChat(self, chatString): if not self.isThought(chatString): if not self.getGhost() or self.doId == base.localAvatar.doId: if "ooo" in chatString.lower(): sfx = self.chatSoundDict['howl'] elif "!" in chatString.lower(): sfx = self.chatSoundDict['exclaim'] elif "?" in chatString.lower(): sfx = self.chatSoundDict['question'] elif len(chatString) <= 9: sfx = self.chatSoundDict['short'] elif 10 <= len(chatString) <= 19: sfx = self.chatSoundDict['medium'] elif len(chatString) >= 20: sfx = self.chatSoundDict['long'] base.playSfx(sfx, node=self) Avatar.Avatar.setChat(self, chatString) def setName(self, nameString): Avatar.Avatar.setName(self, nameString, avatarType=self.avatarType) def setDNAStrand(self, dnaStrand, makeTag=1): ToonDNA.ToonDNA.setDNAStrand(self, dnaStrand) self.deleteCurrentToon() self.generateToon(makeTag) def generateToon(self, makeTag=1): self.generateLegs() self.generateTorso() self.generateHead() self.setToonColor() self.setClothes() self.setGloves() self.parentToonParts() self.rescaleToon() if makeTag: self.setupNameTag() Avatar.Avatar.initShadow(self) if self.cr.isShowingPlayerIds: self.showAvId() self.updateChatSoundDict() def attachTNT(self): self.pies.attachTNT() self.holdTNTAnim() def detachTNT(self): self.pies.detachTNT() self.animFSM.request(self.animFSM.getCurrentState().getName()) def holdTNTAnim(self): self.pose("toss", 22, partName="torso") def parentToonParts(self): self.attach('head', 'torso', 'def_head') self.attach('torso', 'legs', 'joint_hips') def unparentToonParts(self): self.getPart('head').reparentTo(self.getGeomNode()) self.getPart('torso').reparentTo(self.getGeomNode()) self.getPart('legs').reparentTo(self.getGeomNode()) def rescaleToon(self): animal = self.getAnimal() bodyScale = CIGlobals.toonBodyScales[animal] headScale = CIGlobals.toonHeadScales[animal][2] shoulderHeight = CIGlobals.legHeightDict[ self.legs] * bodyScale + CIGlobals.torsoHeightDict[ self.torso] * bodyScale height = shoulderHeight + CIGlobals.headHeightDict[ self.head] * headScale bodyScale = CIGlobals.toonBodyScales[animal] self.setAvatarScale(bodyScale) self.getPart('head').setScale(headScale) self.setHeight(height) def setGloves(self): color = self.getGloveColor() gloves = self.find('**/hands') gloves.setColor(color) def setClothes(self): shirt, shirtcolor = self.getShirtStyle() short, shortcolor = self.getShortStyle() sleeve, sleevecolor = self.getSleeveStyle() torsot = self.findAllMatches('**/torso-top') torsob = self.findAllMatches('**/torso-bot') sleeves = self.findAllMatches('**/sleeves') torsot.setTexture(loader.loadTexture(shirt), 1) torsob.setTexture(loader.loadTexture(short), 1) sleeves.setTexture(loader.loadTexture(sleeve), 1) torsot.setColor(shirtcolor) sleeves.setColor(sleevecolor) torsob.setColor(shortcolor) def generateLegs(self): ToonGlobals.generateBodyPart(self, 'legs', self.getLegs(), 3, 'shorts') self.find('**/boots_long').stash() self.find('**/boots_short').stash() self.find('**/shoes').stash() def generateTorso(self): ToonGlobals.generateBodyPart(self, 'torso', self.getTorso(), 3, '') def generateHead(self, pat=0): gender = self.getGender() head = self.getAnimal() headtype = self.getHead() ToonHead.generateHead(self, gender, head, headtype) def setToonColor(self): self.setHeadColor() self.setTorsoColor() self.setLegColor() def setLegColor(self): legcolor = self.getLegColor() self.findAllMatches('**/legs').setColor(legcolor) self.findAllMatches('**/feet').setColor(legcolor) def setTorsoColor(self): torsocolor = self.getTorsoColor() self.findAllMatches('**/arms').setColor(torsocolor) self.findAllMatches('**/neck').setColor(torsocolor) self.findAllMatches('**/hands').setColor(1, 1, 1, 1) def setForcedTorsoAnim(self, string): self.forcedTorsoAnim = string self.loop(string, partName="torso") def clearForcedTorsoAnim(self): self.forcedTorsoAnim = None self.animFSM.request(self.animFSM.getCurrentState().getName()) def enterOff(self, ts=0, callback=None, extraArgs=[]): self.currentAnim = None return def exitOff(self): pass def enterWin(self, ts=0, callback=None, extraArgs=[]): self.playingAnim = 'win' self.sfx = base.audio3d.loadSfx("phase_3.5/audio/sfx/ENC_Win.ogg") self.sfx.setLoop(True) base.audio3d.attachSoundToObject(self.sfx, self) base.playSfx(self.sfx, node=self) self.loop("win") def exitWin(self): self.stop() self.sfx.stop() del self.sfx self.playingAnim = 'neutral' def enterShrug(self, ts=0, callback=None, extraArgs=[]): self.play("shrug") def exitShrug(self): self.exitGeneral() def enterHDance(self, ts=0, callback=None, extraArgs=[]): self.play("hdance") def exitHDance(self): self.exitGeneral() def enterScientistWork(self, ts=0, callback=None, extraArgs=[]): self.loop("scwork") def exitScientistWork(self): self.exitGeneral() def enterScientistEmcee(self, ts=0, callback=None, extraArgs=[]): self.loop("scemcee") def exitScientistEmcee(self): self.exitGeneral() def enterScientistGame(self, ts=0, callback=None, extraArgs=[]): self.loop("scgame") def exitScientistGame(self): self.exitGeneral() def enterScientistJealous(self, ts=0, callback=None, extraArgs=[]): self.loop("scjealous") def exitScientistJealous(self): self.exitGeneral() def enterWave(self, ts=0, callback=None, extraArgs=[]): self.play("wave") def exitWave(self): self.exitGeneral() def enterLaugh(self, ts=0, callback=None, extraArgs=[]): self.setPlayRate(5.0, "neutral") self.loop("neutral") def exitLaugh(self): self.setPlayRate(1.0, "neutral") self.stop() def enterNeutral(self, ts=0, callback=None, extraArgs=[]): if self.backpack: if self.backpack.getCurrentGag(): if self.backpack.getCurrentGag().getState() in [ GagState.START, GagState.RELEASED ]: self.loop("neutral", partName="legs") if self.animal == "dog": self.loop("neutral", partName="head") return if self.forcedTorsoAnim != None: self.loop(self.forcedTorsoAnim, partName='torso') self.loop("neutral", partName="legs") return self.loop("neutral") self.playingAnim = 'neutral' def exitNeutral(self): self.exitGeneral() self.playingAnim = 'neutral' def exitGeneral(self): if self.backpack: if self.backpack.getCurrentGag(): if self.backpack.getCurrentGag().getState() in [ GagState.START, GagState.RELEASED ]: self.stop(partName='legs') else: self.stop() else: self.stop() else: self.stop() def enterRun(self, ts=0, callback=None, extraArgs=[]): if self.backpack: if self.backpack.getCurrentGag(): if self.backpack.getCurrentGag().getState() in [ GagState.START, GagState.RELEASED ]: self.loop("run", partName="legs") if self.animal == "dog": self.loop("run", partName="head") return if self.forcedTorsoAnim != None: self.loop(self.forcedTorsoAnim, partName='torso') self.loop("run", partName="legs") return self.loop("run") def exitRun(self): self.exitGeneral() def enterWalk(self, ts=0, callback=None, extraArgs=[]): if self.backpack: if self.backpack.getCurrentGag(): if self.backpack.getCurrentGag().getState() in [ GagState.START, GagState.RELEASED ]: self.loop("walk", partName="legs") if self.animal == "dog": self.loop("walk", partName="head") return if self.forcedTorsoAnim != None: self.loop(self.forcedTorsoAnim, partName='torso') self.loop("walk", partName="legs") return self.loop("walk") def exitWalk(self): self.exitGeneral() def enterWalkBack(self, ts=0, callback=None, extraArgs=[]): self.setPlayRate(-1.0, "walk") self.enterWalk() def exitWalkBack(self): self.exitWalk() self.setPlayRate(1.0, "walk") def enterOpenBook(self, ts=0, callback=None, extraArgs=[]): self.playingAnim = 'book' self.book1 = Actor("phase_3.5/models/props/book-mod.bam", {"chan": "phase_3.5/models/props/book-chan.bam"}) self.book1.reparentTo( self.getPart('torso').find('**/def_joint_right_hold')) self.track = ActorInterval(self, "book", startFrame=CIGlobals.OpenBookFromFrame, endFrame=CIGlobals.OpenBookToFrame, name=self.uniqueName('enterOpenBook')) self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getDoneEvent(), self.__doCallback, [callback, extraArgs]) self.track.start(ts) self.book1.play("chan", fromFrame=CIGlobals.OpenBookFromFrame, toFrame=CIGlobals.OpenBookToFrame) def exitOpenBook(self): if self.track: self.ignore(self.track.getDoneEvent()) self.track.finish() self.track = None if self.book1: self.book1.cleanup() self.book1 = None self.playingAnim = 'neutral' def enterReadBook(self, ts=0, callback=None, extraArgs=[]): self.playingAnim = 'book' self.book2 = Actor("phase_3.5/models/props/book-mod.bam", {"chan": "phase_3.5/models/props/book-chan.bam"}) self.book2.reparentTo( self.getPart('torso').find('**/def_joint_right_hold')) self.pingpong("book", fromFrame=CIGlobals.ReadBookFromFrame, toFrame=CIGlobals.ReadBookToFrame) self.book2.pingpong("chan", fromFrame=CIGlobals.ReadBookFromFrame, toFrame=CIGlobals.ReadBookToFrame) def exitReadBook(self): if self.book2: self.book2.cleanup() self.book2 = None self.playingAnim = 'neutral' def enterCloseBook(self, ts=0, callback=None, extraArgs=[]): self.playingAnim = 'book' self.book3 = Actor("phase_3.5/models/props/book-mod.bam", {"chan": "phase_3.5/models/props/book-chan.bam"}) self.book3.reparentTo( self.getPart('torso').find('**/def_joint_right_hold')) self.track = ActorInterval(self, "book", startFrame=CIGlobals.CloseBookFromFrame, endFrame=CIGlobals.CloseBookToFrame, name=self.uniqueName('enterCloseBook')) self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getDoneEvent(), self.__doCallback, [callback, extraArgs]) self.track.start(ts) self.book3.play("chan", fromFrame=CIGlobals.CloseBookFromFrame, toFrame=CIGlobals.CloseBookToFrame) def exitCloseBook(self): if self.track: self.ignore(self.track.getDoneEvent()) self.track.finish() self.track = None if self.book3: self.book3.cleanup() self.book3 = None self.playingAnim = 'neutral' def enterTeleportOut(self, ts=0, callback=None, extraArgs=[]): self.notify.info( str(self.doId) + "-" + str(self.zoneId) + ": enterTeleportOut") self.playingAnim = 'tele' self.portal1 = Actor( "phase_3.5/models/props/portal-mod.bam", {"chan": "phase_3.5/models/props/portal-chan.bam"}) self.portal1.play("chan") self.portal1.reparentTo( self.getPart('legs').find('**/def_joint_right_hold')) self.play("tele") if hasattr(self, 'uniqueName'): name = self.uniqueName('enterTeleportOut') else: name = 'enterTeleportOut' self.track = Sequence(Wait(0.4), Func(self.teleportOutSfx), Wait(1.3), Func(self.throwPortal), Wait(3.4), name=name) self.track.delayDelete = DelayDelete.DelayDelete(self, name) self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getName(), self.teleportOutDone, [callback, extraArgs]) self.track.start(ts) def doPortalBins(self, portal): portal.setBin('shadow', 0) portal.setDepthWrite(0) portal.setDepthTest(0) def teleportOutDone(self, callback, requestStatus): self.notify.info( str(self.doId) + "-" + str(self.zoneId) + ": teleportOutDone") self.__doCallback(callback, requestStatus) self.exitTeleportOut() def teleportOutSfx(self): self.outSfx = base.audio3d.loadSfx( "phase_3.5/audio/sfx/AV_teleport.ogg") base.audio3d.attachSoundToObject(self.outSfx, self.portal1) base.playSfx(self.outSfx, node=self) def throwPortal(self): self.doPortalBins(self.portal1) self.portal1.reparentTo(self.getPart('legs').find('**/joint_nameTag')) self.portal1.setScale(CIGlobals.PortalScale) self.portal1.setY(6.5) self.portal1.setH(180) def exitTeleportOut(self): self.notify.info( str(self.doId) + "-" + str(self.zoneId) + ": exitTeleportOut") if self.track != None: self.ignore(self.track.getName()) self.track.finish() DelayDelete.cleanupDelayDeletes(self.track) self.track = None if self.portal1: self.portal1.cleanup() self.portal1 = None self.playingAnim = 'neutral' def getTeleportInTrack(self, portal): self.doPortalBins(portal) holeTrack = Sequence() holeTrack.append(Func(portal.reparentTo, self)) pos = Point3(0, -2.4, 0) holeTrack.append(Func(portal.setPos, pos)) holeTrack.append( ActorInterval(portal, 'chan', startTime=3.4, endTime=3.1)) holeTrack.append(Wait(0.6)) holeTrack.append( ActorInterval(portal, 'chan', startTime=3.1, endTime=3.4)) def restorePortal(portal): portal.setPos(0, 0, 0) portal.detachNode() portal.clearBin() portal.clearDepthTest() portal.clearDepthWrite() holeTrack.append(Func(restorePortal, portal)) toonTrack = Sequence(Wait(0.3), Func(self.getGeomNode().show), Func(self.nametag3d.show), ActorInterval(self, 'happy', startTime=0.45)) if hasattr(self, 'uniqueName'): trackName = self.uniqueName('teleportIn') else: trackName = 'teleportIn' return Parallel(toonTrack, holeTrack, name=trackName) def enterTeleportIn(self, ts=0, callback=None, extraArgs=[]): self.playingAnim = 'happy' self.portal2 = Actor( "phase_3.5/models/props/portal-mod.bam", {"chan": "phase_3.5/models/props/portal-chan.bam"}) self.show() self.getGeomNode().hide() self.nametag3d.hide() self.track = self.getTeleportInTrack(self.portal2) self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getName(), self.teleportInDone, [callback, extraArgs]) self.track.delayDelete = DelayDelete.DelayDelete( self, self.track.getName()) self.track.start(ts) def teleportInDone(self, callback, extraArgs): self.__doCallback(callback, extraArgs) self.exitTeleportIn() def exitTeleportIn(self): if self.track != None: self.ignore(self.track.getName()) self.track.finish() DelayDelete.cleanupDelayDeletes(self.track) self.track = None if self.portal2: self.portal2.cleanup() self.portal2 = None if self.getGeomNode(): self.getGeomNode().show() if self.nametag3d: self.nametag3d.show() self.playingAnim = 'neutral' def enterFallFWD(self, ts=0, callback=None, extraArgs=[]): self.playingAnim = 'fallf' self.play("fallf") Sequence(Wait(0.5), SoundInterval(self.fallSfx, node=self)).start() def exitFallFWD(self): self.exitGeneral() self.playingAnim = 'neutral' def enterFallBCK(self, ts=0, callback=None, extraArgs=[]): self.playingAnim = 'fallb' self.play("fallb") Sequence(Wait(0.5), SoundInterval(self.fallSfx, node=self)).start() def exitFallBCK(self): self.playingAnim = 'neutral' self.exitGeneral() def enterHappyJump(self, ts=0, callback=None, extraArgs=[]): self.playingAnim = 'happy' self.play("happy") def exitHappyJump(self): self.exitGeneral() self.playingAnim = 'neutral' def enterSwim(self, ts=0, callback=None, extraArgs=[]): self.playingAnim = 'swim' self.loop("swim") self.getGeomNode().setP(-89.0) self.getGeomNode().setZ(4.0) nt = self.nametag3d nt.setX(0) nt.setY(-2) nt.setZ(5.0) def exitSwim(self): self.exitGeneral() self.getGeomNode().setP(0.0) self.getGeomNode().setZ(0.0) nt = self.nametag3d nt.setX(0) nt.setY(0) nt.setZ(self.getHeight() + 0.3) self.playingAnim = 'neutral' def enterDied(self, ts=0, callback=None, extraArgs=[]): self.playingAnim = 'lose' self.isdying = True self.play("lose") self.track = Sequence(Wait(2.2), Func(self.dieSfx), Wait(2.8), self.getGeomNode().scaleInterval( 2, Point3(0.01), startScale=(self.getGeomNode().getScale())), Func(self.delToon), name=self.uniqueName('enterDied')) self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getDoneEvent(), self.diedDone, [callback, extraArgs]) self.track.delayDelete = DelayDelete.DelayDelete( self, 'enterTeleportOut') self.track.start(ts) def diedDone(self, callback, extraArgs): self.__doCallback(callback, extraArgs) self.exitDied() def __doCallback(self, callback, extraArgs): if callback: if extraArgs: callback(*extraArgs) else: callback() def dieSfx(self): self.Losesfx = base.audio3d.loadSfx("phase_5/audio/sfx/ENC_Lose.ogg") base.audio3d.attachSoundToObject(self.Losesfx, self) base.playSfx(self.Losesfx, node=self) def delToon(self): self.isdead = True def exitDied(self): if self.track != None: self.ignore(self.track.getDoneEvent()) self.track.finish() DelayDelete.cleanupDelayDeletes(self.track) self.track = None self.rescaleToon() self.playingAnim = 'neutral' def enterJump(self, ts=0, callback=None, extraArgs=[]): self.playingAnim = 'jump' self.loop("jump") def exitJump(self): self.exitGeneral() self.playingAnim = 'neutral' def enterLeap(self, ts=0, callback=None, extraArgs=[]): self.playingAnim = 'leap' self.loop("leap") def exitLeap(self): self.exitGeneral() self.playingAnim = 'neutral' def enterCringe(self, ts=0, callback=None, extraArgs=[]): self.play("cringe") def exitCringe(self): self.exitGeneral() def enterConked(self, ts=0, callback=None, extraArgs=[]): self.play("conked") def exitConked(self): self.exitGeneral()
class ToonFPS(DirectObject): notify = directNotify.newCategory("ToonFPS") WeaponName2DamageData = {"pistol": (30.0, 10.0, 150.0, 0.3), "shotgun": (40.0, 15.0, 155.0, 0.5), "sniper": (40.0, 15.0, 155.0, 0.5)} def __init__(self, mg, weaponName = "pistol"): self.mg = mg self.weaponName = weaponName self.v_model_root = None self.v_model = None self.weapon = None self.track = None self.draw = None self.shoot = None self.reload = None self.empty = None self.cockBack = None self.cockFwd = None self.player_node = None # blach (02Aug15) # Drastically improved the accuracy of bullets... DRASTICALLY self.shooterTrav = None self.shooterRay = None self.shooterRayNode = None self.shooterHandler = None self.gui = ToonFPSGui(self) self.fsm = ClassicFSM('ToonFPS', [State('off', self.enterOff, self.exitOff), State('alive', self.enterAlive, self.exitAlive), State('dead', self.enterDead, self.exitDead)], 'off', 'off') #self.deadFSM = ClassicFSM('dead', [State('off', self.enterOff, self.exitOff), # State(']) self.aliveFSM = ClassicFSM('alive', [State('off', self.enterOff, self.exitOff), State('draw', self.enterDraw, self.exitDraw, ['idle']), State('idle', self.enterIdle, self.exitIdle, ['shoot', 'reload']), State('shoot', self.enterShoot, self.exitShoot, ['idle']), State('reload', self.enterReload, self.exitReload, ['idle'])], 'off', 'off') self.fsm.getStateNamed('alive').addChild(self.aliveFSM) #self.fsm.getStateNamed('dead').addChild(self.deadFSM) self.fsm.enterInitialState() self.aliveFSM.enterInitialState() if self.weaponName == "pistol": self.ammo = 14 elif self.weaponName == "shotgun": self.ammo = 7 self.hp = 125 self.max_hp = 125 self.firstPerson = FirstPerson() def movementTask(self, task): if (inputState.isSet('jump') or base.localAvatar.walkControls.isAirborne): if base.localAvatar.getAnimState() != "jump": base.localAvatar.setAnimState("jump") base.localAvatar.playMovementSfx(None) self.mg.sendUpdate("jumpingAvatar", [base.localAvatar.doId]) return Task.cont def enterAlive(self): if not self.mg.fsm.getCurrentState().getName() in ['gameOver', 'announceGameOver', 'finalScores']: self.start() self.resetHp() self.resetAmmo() if self.mg.fsm.getCurrentState().getName() == "play": self.reallyStart() def exitAlive(self): self.end() self.v_model.reparentTo(hidden) if self.mg.fsm.getCurrentState().getName() != "play": self.reallyEnd() def updatePoints(self): self.points = self.kills - self.deaths def enterDead(self, killer): base.localAvatar.getGeomNode().show() self.gui.end() base.localAvatar.attachCamera() self.freezeCamSfx = base.loadSfx("phase_4/audio/sfx/freeze_cam.ogg") self.freezeCamImage = None self.freezeCamImageFile = None base.camera.setZ(base.camera.getZ() + 2.0) taskMgr.add( self.cameraLookAtKillerTask, "lookAtKiller", extraArgs = [killer], appendTask = True ) taskMgr.doMethodLater( 2.0, self.startZoomOnKiller, "startFreezeCam", extraArgs = [killer], appendTask = True ) def startZoomOnKiller(self, killer, task): taskMgr.add( self.__zoomOnKillerTask, "zoomOnKiller", extraArgs = [killer], appendTask = True ) return task.done def __zoomOnKillerTask(self, killer, task): if base.camera.getDistance(killer) <= 10.0 and self.freezeCamSfx.status() == self.freezeCamSfx.READY: base.playSfx(self.freezeCamSfx) if base.camera.getDistance(killer) < 7.0: self.doFreezeCam() return task.done base.camera.setY(base.camera, 60 * globalClock.getDt()) return task.again def doFreezeCam(self): taskMgr.remove("lookAtKiller") self.frameBuffer = PNMImage() base.win.getScreenshot(self.frameBuffer) self.freezeCamTex = Texture() self.freezeCamTex.load(self.frameBuffer) self.freezeCamImage = OnscreenImage(image = self.freezeCamTex, parent=render2d) def cameraLookAtKillerTask(self, killer, task): try: base.camera.lookAt(killer, 0, 0, 3) except AssertionError: pass return task.cont def exitDead(self): taskMgr.remove("zoomOnKiller") taskMgr.remove("lookAtKiller") taskMgr.remove("startFreezeCam") del self.freezeCamSfx if self.freezeCamImage: self.freezeCamImage.destroy() del self.freezeCamImage self.frameBuffer.clear() self.freezeCamTex.clear() del self.frameBuffer del self.freezeCamTex base.localAvatar.detachCamera() base.localAvatar.getGeomNode().hide() self.gui.start() def load(self): if self.weaponName == "pistol": self.draw = base.loadSfx("phase_4/audio/sfx/draw_secondary.ogg") self.shoot = base.loadSfx("phase_4/audio/sfx/pistol_shoot.ogg") self.reload = base.loadSfx("phase_4/audio/sfx/pistol_worldreload.ogg") elif self.weaponName == "sniper": self.draw = base.loadSfx("phase_4/audio/sfx/draw_primary.ogg") self.shoot = base.loadSfx("phase_4/audio/sfx/shotgun_shoot.ogg") self.cockBack = base.loadSfx("phase_4/audio/sfx/shotgun_cock_back.ogg") self.cockFwd = base.loadSfx("phase_4/audio/sfx/shotgun_cock_forward.ogg") elif self.weaponName == "shotgun": self.draw = base.loadSfx("phase_4/audio/sfx/draw_primary.ogg") self.shoot = base.loadSfx("phase_4/audio/sfx/shotgun_shoot.ogg") self.cockBack = base.loadSfx("phase_4/audio/sfx/shotgun_cock_back.ogg") self.cockFwd = base.loadSfx("phase_4/audio/sfx/shotgun_cock_forward.ogg") self.empty = base.loadSfx("phase_4/audio/sfx/shotgun_empty.ogg") self.v_model_root = base.camera.attachNewNode('v_model_root') self.v_model = Actor('phase_4/models/minigames/v_dgm.egg', {'pidle': 'phase_4/models/minigames/v_dgm-pistol-idle.egg', 'pshoot': 'phase_4/models/minigames/v_dgm-pistol-shoot.egg', 'preload': 'phase_4/models/minigames/v_dgm-pistol-reload.egg', 'pdraw': 'phase_4/models/minigames/v_dgm-pistol-draw.egg', 'sidle': 'phase_4/models/minigames/v_dgm-shotgun-idle.egg', 'sshoot': 'phase_4/models/minigames/v_dgm-shotgun-shoot.egg'}) if self.weaponName == "pistol": self.weapon = loader.loadModel("phase_4/models/props/water-gun.bam") self.weapon.reparentTo(self.v_model.exposeJoint(None, "modelRoot", "Bone.011")) self.weapon.setX(-0.125) self.weapon.setY(0.5) self.weapon.setScale(0.65) elif self.weaponName == "sniper": self.weapon = loader.loadModel("phase_4/models/props/sniper.egg") self.weapon.reparentTo(self.v_model.exposeJoint(None, "modelRoot", "Bone.029")) self.weapon.setScale(0.75) self.weapon.setPos(0.45, -1.03, -1.17) self.weapon.setHpr(9.46, 308.19, 75.78) elif self.weaponName == "shotgun": self.weapon = loader.loadModel("phase_4/models/props/shotgun.egg") self.weapon.reparentTo(self.v_model.exposeJoint(None, "modelRoot", "Bone.029")) self.weapon.setScale(0.75) self.weapon.setPos(0.45, -1.03, -1.17) self.weapon.setHpr(9.46, 308.19, 75.78) self.gui.load() def start(self): base.camLens.setNear(0.1) self.shooterTrav = CollisionTraverser('ToonFPS.shooterTrav') ray = CollisionRay() rayNode = CollisionNode('ToonFPS.rayNode') rayNode.addSolid(ray) rayNode.setCollideMask(BitMask32(0)) rayNode.setFromCollideMask(CIGlobals.WallBitmask | CIGlobals.FloorBitmask) self.shooterRay = ray self.shooterRayNode = base.camera.attachNewNode(rayNode) self.shooterHandler = CollisionHandlerQueue() self.shooterTrav.addCollider(self.shooterRayNode, self.shooterHandler) self.firstPerson.start() self.v_model_root.reparentTo(base.camera) self.v_model.reparentTo(self.v_model_root) if self.weaponName == "pistol": self.v_model_root.setZ(-1.8) self.v_model_root.setY(0.3) self.v_model_root.setX(-0.1) self.v_model_root.setH(2) elif self.weaponName == "sniper": self.v_model_root.setPos(-0.42, -0.81, -1.7) self.v_model_root.setHpr(359, 352.87, 0.00) elif self.weaponName == "shotgun": self.v_model_root.setPos(-0.42, -0.81, -1.7) self.v_model_root.setHpr(359, 352.87, 0.00) self.gui.start() self.firstPerson.disableMouse() self.aliveFSM.request('draw') def reallyStart(self): self.firstPerson.reallyStart() base.localAvatar.startTrackAnimToSpeed() #taskMgr.add(self.movementTask, "toonBattleMovement") def end(self): if self.aliveFSM.getCurrentState().getName() != 'off': self.aliveFSM.request('off') if self.firstPerson: self.firstPerson.enableMouse() self.firstPerson.end() taskMgr.remove("toonBattleMovement") if self.mg.fsm.getCurrentState().getName() != "play": self.fsm.request('off') def reallyEnd(self): try: self.ToonFPS_reallyEnded return except: self.ToonFPS_reallyEnded = 1 if self.shooterRayNode: self.shooterRayNode.removeNode() self.shooterRayNode = None self.shooterRay = None self.shooterTrav = None self.shooterHandler = None if self.firstPerson: self.firstPerson.reallyEnd() if self.v_model_root: self.v_model_root.reparentTo(hidden) if self.v_model: self.v_model.reparentTo(hidden) self.v_model.setPosHpr(0, 0, 0, 0, 0, 0) if self.gui: self.gui.end() base.camLens.setNear(1.0) def cleanup(self): try: self.ToonFPS_cleanedUp return except: self.ToonFPS_cleanedUp = 1 taskMgr.remove("lookAtKiller") taskMgr.remove("toonBattleMovement") if self.firstPerson: self.firstPerson.cleanup() self.firstPerson = None self.draw = None self.shoot = None self.reload = None self.empty = None self.ammo = None try: self.aliveFSM.requestFinalState() self.fsm.requestFinalState() except: self.notify.warning('Redundant call to enter the final state.') self.fsm = None self.aliveFSM = None self.player_node = None self.min_camerap = None self.max_camerap = None self.hp = None self.max_hp = None if self.v_model: self.v_model.cleanup() self.v_model = None if self.weapon: self.weapon.removeNode() self.weapon = None if self.weapon: self.v_model_root.removeNode() self.v_model_root = None if self.gui: self.gui.cleanup() def damageTaken(self, amount, avId): if self.hp <= 0.0: killer = self.mg.cr.doId2do.get(avId, None) self.fsm.request('dead', [killer]) self.gui.adjustHpMeter() def enterDraw(self): self.draw.play() if self.weaponName == "pistol": self.track = ActorInterval(self.v_model, 'pdraw', playRate = 1.6, name = 'drawTrack') elif self.weaponName == "shotgun": self.v_model.pose('sidle', 15) self.track = LerpQuatInterval(self.v_model, duration = 0.5, quat = (0, 0, 0), startHpr = (70, -50, 0), blendType = 'easeOut', name = 'drawTrack') elif self.weaponName == "sniper": self.v_model.pose('sidle', 15) self.track = LerpQuatInterval(self.v_model, duration = 0.5, quat = (0, 0, 0), startHpr = (70, -50, 0), blendType = 'easeOut', name = 'drawTrack') self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getDoneEvent(), self.aliveFSM.request, ['idle']) self.track.start() def exitDraw(self): #self.draw.stop() if self.track: self.ignore(self.track.getDoneEvent()) self.track.finish() self.track = None def enterIdle(self): if self.weaponName == "pistol": self.v_model.loop('pidle') elif self.weaponName == "shotgun": self.track = Sequence(LerpQuatInterval(self.v_model, duration = 2.0, quat = (0, 1, 0), startHpr = (0, 0, 0), blendType = 'easeInOut'), LerpQuatInterval(self.v_model, duration = 2.0, quat = (0, 0, 0), startHpr = (0, 1, 0), blendType = 'easeInOut')) self.track.loop() elif self.weaponName == "sniper": self.track = Sequence(LerpQuatInterval(self.v_model, duration = 2.0, quat = (0, 1, 0), startHpr = (0, 0, 0), blendType = 'easeInOut'), LerpQuatInterval(self.v_model, duration = 2.0, quat = (0, 0, 0), startHpr = (0, 1, 0), blendType = 'easeInOut')) self.track.loop() self.accept('mouse1', self.requestShoot) if self.ammo <= 0: self.gui.notifyNoAmmo() if self.ammo < 14: self.accept('r', self.aliveFSM.request, ['reload']) def requestShoot(self): if self.mg.fsm.getCurrentState().getName() != "play": return if self.ammo > 0: self.aliveFSM.request('shoot') else: self.empty.play() def exitIdle(self): self.v_model.stop() if self.track: self.track.finish() self.track = None self.ignore('mouse1') self.ignore('r') def enterShoot(self): self.shoot.play() if self.weaponName == "pistol": self.track = ActorInterval(self.v_model, 'pshoot', playRate = 2, name = 'shootTrack') elif self.weaponName == "shotgun": self.track = Parallel( Sequence( LerpQuatInterval(self.v_model, duration = 0.05, quat = (0, 3, 0), startHpr = (0, 0, 0)), LerpQuatInterval(self.v_model, duration = 0.1, quat = (0, 0, 0), startHpr = (0, 3, 0)) ), Sequence( LerpPosInterval(self.v_model, duration = 0.05, pos = (0, -0.3, 0), startPos = (0, 0, 0)), LerpPosInterval(self.v_model, duration = 0.1, pos = (0, 0, 0), startPos = (0, -0.3, 0)), Wait(0.1) ), ) elif self.weaponName == "sniper": self.track = Parallel( Sequence( LerpQuatInterval(self.v_model, duration = 0.05, quat = (0, 3, 0), startHpr = (0, 0, 0)), LerpQuatInterval(self.v_model, duration = 0.1, quat = (0, 0, 0), startHpr = (0, 3, 0)) ), Sequence( LerpPosInterval(self.v_model, duration = 0.05, pos = (0, -0.3, 0), startPos = (0, 0, 0)), LerpPosInterval(self.v_model, duration = 0.1, pos = (0, 0, 0), startPos = (0, -0.3, 0)), Wait(0.1) ), ) self.track.setDoneEvent('shootTrack') self.acceptOnce(self.track.getDoneEvent(), self.aliveFSM.request, ['idle']) self.track.start() self.ammo -= 1 self.gui.adjustAmmoGui() self.mg.makeSmokeEffect(self.weapon.find('**/joint_nozzle').getPos(render)) self.traverse() def traverse(self): mpos = base.mouseWatcherNode.getMouse() self.shooterRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) self.shooterTrav.traverse(render) def calcDamage(self, avatar): dmgData = self.WeaponName2DamageData[self.weaponName] maxDamage = dmgData[0] minDistance = dmgData[1] maxDistance = dmgData[2] factor = dmgData[3] distance = base.localAvatar.getDistance(avatar) if distance < minDistance: distance = minDistance elif distance > maxDistance: distance = maxDistance damage = maxDamage - ((distance - minDistance) * factor) return damage def exitShoot(self): #self.shoot.stop() self.ignore('shootTrack') if self.track: self.track.finish() self.track = None def enterReload(self): self.gui.deleteNoAmmoLabel() if self.weaponName == "pistol": self.track = Parallel(Sequence(Wait(0.3), Func(self.reload.play), Func(self.resetAmmo)), ActorInterval(self.v_model, 'preload', playRate = 1.5), name = 'reloadTrack') elif self.weaponName == "shotgun": self.track = Sequence(Func(self.draw.play), LerpQuatInterval(self.v_model, duration = 0.5, quat = (70, -50, 0), startHpr = (0, 0, 0), blendType = 'easeIn'), SoundInterval(self.cockBack), SoundInterval(self.cockFwd), Func(self.resetAmmo), Func(self.draw.play), LerpQuatInterval(self.v_model, duration = 0.5, quat = (0, 0, 0), startHpr = (70, -50, 0), blendType = 'easeOut'), name = 'reloadTrack') elif self.weaponName == "sniper": self.track = Sequence(Func(self.draw.play), LerpQuatInterval(self.v_model, duration = 0.5, quat = (70, -50, 0), startHpr = (0, 0, 0), blendType = 'easeIn'), SoundInterval(self.cockBack), SoundInterval(self.cockFwd), Func(self.resetAmmo), Func(self.draw.play), LerpQuatInterval(self.v_model, duration = 0.5, quat = (0, 0, 0), startHpr = (70, -50, 0), blendType = 'easeOut'), name = 'reloadTrack') self.track.setDoneEvent('reloadTrack') self.acceptOnce(self.track.getDoneEvent(), self.aliveFSM.request, ['idle']) self.track.start() def exitReload(self): #self.reload.stop() self.ignore('reloadTrack') if self.track: self.track.finish() self.track = None def resetAmmo(self): if self.weaponName == "pistol": self.ammo = 14 elif self.weaponName == "shotgun": self.ammo = 7 elif self.weaponName == "sniper": self.ammo = 7 self.gui.resetAmmo() def resetHp(self): self.hp = self.max_hp self.gui.adjustHpMeter() def enterOff(self): pass def exitOff(self): pass
class Toon(Avatar.Avatar, ToonHead): notify = DirectNotifyGlobal.directNotify.newCategory('Toon') def __init__(self): Avatar.Avatar.__init__(self) ToonHead.__init__(self) try: self.Toon_initialized return except: self.Toon_initialized = 1 self.avatarType = 'toon' 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) ], '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.newDNA = newDNA self.style.gender = newDNA.getGender() oldDNA = self.style if fForce or newDNA.head != oldDNA.head: self.swapToonHead(newDNA.head) 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 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 generateToon(self): self.setDNAString() self.generateToonLegs() self.generateToonHead() self.generateToonTorso() self.generateToonColor() self.parentToonParts() #self.rescaleToon() #self.resetHeight() self.setupToonNodes() 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() | BitmaskGlobals.PieBitmask) def generateToonLegs(self, copy=1): global Preloaded legStyle = self.newDNA.legs filePrefix = LegDict.get(legStyle) if filePrefix is None: self.notify.error('unknown leg style: %s' % legStyle) print(Preloaded[filePrefix + '-1000']) # self.loadModel(Preloaded[filePrefix+'-1000'], 'legs', '1000', True) self.loadModel(Preloaded[filePrefix + '-1000']) if not copy: self.showPart('legs', '1000') self.loadAnims(LegsAnimDict[legStyle], 'legs', '1000') 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') # 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 not copy: self.showPart('torso', '1000') self.loadAnims(TorsoAnimDict[torsoStyle], 'torso', '1000') 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') # 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() def setDNAString(self): self.newDNA = ToonDNA.ToonDNA() self.setDNA(self.newDNA) def setDNA(self, dna): self.style = dna #self.generateToon() def generateToonHead(self, copy=1): headHeight = ToonHead.generateToonHead(self, copy, self.style, '1000') if self.style.getAnimal() == 'dog': self.loadAnims(HeadAnimDict[self.style.head], 'head', '1000') def swapToonHead(self, headStyle=-1, copy=1): self.stopLookAroundNow() self.eyelids.request('open') self.unparentToonParts() self.removePart('head', '1000') # 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 self.generateToonHead(copy) self.generateToonColor() self.parentToonParts() self.rescaleToon() self.resetHeight() self.eyelids.request('open') self.startLookAround() 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 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 getDialogueArray(self): 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 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 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 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 enterOff(self, animMultiplier=1, ts=0, callback=None): self.playingAnim = None return def exitOff(self): pass 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 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 __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 __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 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 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) self.suit.loop('neutral') self.isDisguised = 1 self.setFont(ToontownGlobals.getSuitFont()) self.nametag.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.nametag.setSpeechFont(ToontownGlobals.getToonFont()) self.nametag.setWordwrap(None) if hasattr(base, 'idTags') and base.idTags: name = self.getAvIdName() else: name = self.getName() self.setDisplayName(name) self.suit.delete() del self.suit del self.suitGeom def makeWaiter(self): if not self.isDisguised: return self.suit.makeWaiter(self.suitGeom)
class CrashGUIItem(DirectFrame): notify = directNotify.newCategory('CrashGUIItem') DownZ = -0.25 UpZ = 0.5 def __init__(self, visItem, visScale, frameX, visX, textX, textZ, textScale, spins = False, font = CIGlobals.getToonFont(), align = TextNode.ACenter): DirectFrame.__init__(self, parent = base.a2dTopCenter, pos = (frameX, 0, self.UpZ)) self.frameX = frameX self.item = visItem self.item.flattenLight() self.item.setDepthWrite(1) self.item.setDepthTest(1) self.item.setScale(visScale) self.item.setX(visX) self.item.reparentTo(self) self.spinIval = None if spins: self.spinIval = LerpHprInterval( self.item, duration = 0.5, hpr = Vec3(360, 0, 0), startHpr = Vec3(0, 0, 0) ) self.spinIval.loop() self.text = OnscreenText(parent = self, pos = (textX, textZ, 0), scale = textScale, shadow = (0, 0, 0, 1), fg = (0.5, 0.5, 1.0, 1.0), font = font, align = align) self.fsm = ClassicFSM( "ItemFSM", [ State('off', self.enterOff, self.exitOff), State('up', self.enterUp, self.exitUp), State('up2down', self.enterUp2Down, self.exitUp2Down), State('down', self.enterDown, self.exitDown), State('down2up', self.enterDown2Up, self.exitDown2Up) ], "up", "off" ); self.fsm.enterInitialState() self.initialiseoptions(CrashGUIItem) def taskName(self, name): return name + "-" + str(id(self)) def enterOff(self): pass def exitOff(self): pass def enterUp(self): self.setZ(self.UpZ) def exitUp(self): pass def enterUp2Down(self): self.ival = LerpPosInterval( self, duration = 0.5, pos = (self.frameX, 0, self.DownZ), startPos = (self.frameX, 0, self.UpZ), name = self.taskName('up2downival')) self.ival.setDoneEvent(self.ival.getName()) self.acceptOnce(self.ival.getDoneEvent(), self.__up2DownDone) self.ival.start() def __up2DownDone(self): self.fsm.request('down') def exitUp2Down(self): self.ignore(self.ival.getDoneEvent()) self.ival.finish() del self.ival def enterDown(self): self.setZ(self.DownZ) downTime = 3.0 taskMgr.doMethodLater(downTime, self.__downTask, self.taskName('downTask')) def __downTask(self, task): self.fsm.request('down2up') return task.done def exitDown(self): taskMgr.remove(self.taskName('downTask')) def enterDown2Up(self): self.ival = LerpPosInterval( self, duration = 0.5, pos = (self.frameX, 0, self.UpZ), startPos = (self.frameX, 0, self.DownZ), name = self.taskName('down2upival')) self.ival.setDoneEvent(self.ival.getName()) self.acceptOnce(self.ival.getDoneEvent(), self.__down2UpDone) self.ival.start() def __down2UpDone(self): self.fsm.request('up') def exitDown2Up(self): self.ignore(self.ival.getDoneEvent()) self.ival.finish() del self.ival def setTextText(self, text): self.text.setText(text) def show(self): if self.fsm.getCurrentState().getName() in ['up', 'down2up']: self.fsm.request('up2down') elif self.fsm.getCurrentState().getName() == 'down': taskMgr.remove(self.taskName('downTask')) self.enterDown()
class Char(Avatar.Avatar): def __init__(self): try: self.Char_initialized return except: self.Char_initialized = 1 Avatar.Avatar.__init__(self) self.avatarType = CIGlobals.CChar self.avatarName = None self.currentAnim = None self.charType = '' self.eyes = loader.loadTexture('phase_3/maps/eyes1.jpg', 'phase_3/maps/eyes1_a.rgb') self.closedEyes = loader.loadTexture('phase_3/maps/mickey_eyes_closed.jpg', 'phase_3/maps/mickey_eyes_closed_a.rgb') self.animFSM = ClassicFSM('Char', [State('off', self.enterOff, self.exitOff), State('neutral', self.enterNeutral, self.exitNeutral), State('walk', self.enterWalk, self.exitWalk), State('run', self.enterRun, self.exitRun)], 'off', 'off') animStateList = self.animFSM.getStates() self.animFSM.enterInitialState() Avatar.Avatar.initializeBodyCollisions(self, self.avatarType, 3.5, 1) return def stopAnimations(self): if hasattr(self, 'animFSM'): if not self.animFSM.isInternalStateInFlux(): self.animFSM.request('off') else: notify.warning('animFSM in flux, state=%s, not requesting off' % self.animFSM.getCurrentState().getName()) else: notify.warning('animFSM has been deleted') def disable(self): self.stopBlink() self.stopAnimations() Avatar.Avatar.disable(self) def delete(self): try: self.Char_deleted except: self.Char_deleted = 1 del self.animFSM Avatar.Avatar.delete(self) def setChat(self, chatString): if self.charType == CIGlobals.Mickey: self.dial = base.audio3d.loadSfx('phase_3/audio/dial/mickey.wav') elif self.charType == CIGlobals.Minnie: self.dial = base.audio3d.loadSfx('phase_3/audio/dial/minnie.wav') elif self.charType == CIGlobals.Goofy: self.dial = base.audio3d.loadSfx('phase_6/audio/dial/goofy.wav') base.audio3d.attachSoundToObject(self.dial, self) self.dial.play() Avatar.Avatar.setChat(self, chatString) def setName(self, nameString, charName = None): self.avatarName = nameString Avatar.Avatar.setName(self, nameString, avatarType=self.avatarType, charName=charName) def generateChar(self, charType): self.charType = charType if charType == CIGlobals.Mickey or charType == CIGlobals.Minnie: self.loadModel('phase_3/models/char/' + charType.lower() + '-' + str(CIGlobals.ModelDetail(self.avatarType)) + '.bam') self.loadAnims({'neutral': 'phase_3/models/char/' + charType.lower() + '-wait.bam', 'walk': 'phase_3/models/char/' + charType.lower() + '-walk.bam', 'run': 'phase_3/models/char/' + charType.lower() + '-run.bam', 'left-start': 'phase_3.5/models/char/' + charType.lower() + '-left-start.bam', 'left': 'phase_3.5/models/char/' + charType.lower() + '-left.bam', 'right-start': 'phase_3.5/models/char/' + charType.lower() + '-right-start.bam', 'right': 'phase_3.5/models/char/' + charType.lower() + '-right.bam'}) if charType == CIGlobals.Mickey: self.mickeyEye = self.controlJoint(None, 'modelRoot', 'joint_pupilR') self.mickeyEye.setY(0.025) for bundle in self.getPartBundleDict().values(): bundle = bundle['modelRoot'].getBundle() earNull = bundle.findChild('sphere3') if not earNull: earNull = bundle.findChild('*sphere3') earNull.clearNetTransforms() for bundle in self.getPartBundleDict().values(): charNodepath = bundle['modelRoot'].partBundleNP bundle = bundle['modelRoot'].getBundle() earNull = bundle.findChild('sphere3') if not earNull: earNull = bundle.findChild('*sphere3') ears = charNodepath.find('**/sphere3') if ears.isEmpty(): ears = charNodepath.find('**/*sphere3') ears.clearEffect(CharacterJointEffect.getClassType()) earRoot = charNodepath.attachNewNode('earRoot') earPitch = earRoot.attachNewNode('earPitch') earPitch.setP(40.0) ears.reparentTo(earPitch) earNull.addNetTransform(earRoot.node()) ears.clearMat() ears.node().setPreserveTransform(ModelNode.PTNone) ears.setP(-40.0) ears.flattenMedium() ears.setBillboardAxis() self.startBlink() elif charType == CIGlobals.Pluto: self.loadModel('phase_6/models/char/pluto-1000.bam') self.loadAnims({'walk': 'phase_6/models/char/pluto-walk.bam', 'neutral': 'phase_6/models/char/pluto-neutral.bam', 'sit': 'phase_6/models/char/pluto-sit.bam', 'stand': 'phase_6/models/char/pluto-stand.bam'}) elif charType == CIGlobals.Goofy: self.loadModel('phase_6/models/char/TT_G-1500.bam') self.loadAnims({'neutral': 'phase_6/models/char/TT_GWait.bam', 'walk': 'phase_6/models/char/TT_GWalk.bam'}) else: raise StandardError('unknown char %s!' % charType) Avatar.Avatar.initShadow(self) return def initializeLocalCollisions(self, name, radius): Avatar.Avatar.initializeLocalCollisions(self, radius, 2, name) def startBlink(self): randomStart = random.uniform(0.5, 5) taskMgr.add(self.blinkTask, 'blinkTask') def stopBlink(self): taskMgr.remove('blinkTask') taskMgr.remove('doBlink') taskMgr.remove('openEyes') def blinkTask(self, task): taskMgr.add(self.doBlink, 'doBlink') delay = random.uniform(0.5, 7) task.delayTime = delay return task.again def doBlink(self, task): self.closeEyes() taskMgr.doMethodLater(0.2, self.openEyes, 'openEyes') return task.done def closeEyes(self): self.find('**/joint_pupilR').hide() self.find('**/joint_pupilL').hide() if self.charType == CIGlobals.Mickey: self.mickeyEye.setY(-0.025) self.mickeyEye.hide() self.find('**/eyes').setTexture(self.closedEyes, 1) def openEyes(self, task): self.find('**/joint_pupilR').show() self.find('**/joint_pupilL').show() if self.charType == CIGlobals.Mickey: self.mickeyEye.setY(0.025) self.mickeyEye.show() self.find('**/eyes').setTexture(self.eyes, 1) return task.done def enterOff(self): self.currentAnim = None return def exitOff(self): pass def enterNeutral(self): self.loop('neutral') def exitNeutral(self): self.stop() def enterWalk(self): self.loop('walk') def exitWalk(self): self.stop() def enterRun(self): self.loop('run') def exitRun(self): self.stop()
class CogBrain(DirectObject): PANIC_SPEED = 0.15 PANIC_DELAY = 0.5 RUNAWAY_SPEED = 0.1 RUNAWAY_SAFE_DISTANCE = 50 MAX_BOSS_HELPERS = 5 PANIC_HP_FACTOR = 0.222 ATTACK_DISTANCE = 40.0 MAX_ATTACKERS = 3 Difficulty2MaxAttackThrows = {} for level in range(1, 5): Difficulty2MaxAttackThrows[level] = 3 for level in range(5, 10): Difficulty2MaxAttackThrows[level] = 4 for level in range(9, 13): Difficulty2MaxAttackThrows[level] = 5 def __init__(self, suit): self.suit = suit self.panicHP = self.suit.getMaxHealth() * self.PANIC_HP_FACTOR self.fsm = ClassicFSM('CogBrain', [State('off', self.enterOff, self.exitOff), State('neutral', self.enterNeutral, self.exitNeutral), State('followBoss', self.enterFollowBoss, self.exitFollowBoss), State('panic', self.enterPanic, self.exitPanic), State('runAway', self.enterRunAway, self.exitRunAway)], 'off', 'off') self.fsm.enterInitialState() def start(self): taskMgr.add(self.__think, self.suit.uniqueName('think')) def end(self, andGoOff = 1): taskMgr.remove(self.suit.uniqueName('think')) if andGoOff: self.fsm.request('off') def __think(self, task = None): if task: task.delayTime = 1 if self.suit.getAttacking(): if task: return task.again else: return _help_priority = 0 _panic_priority = 0 _run_priority = 0 _helper_suits = 0 boss = None for av in self.suit.getManager().suits.values(): if av.doId != self.suit.doId: if av.head in ('vp',): boss = av for suit in self.suit.getManager().suits.values(): if suit.doId != self.suit.doId: if suit.brain: if suit.brain.fsm.getCurrentState().getName() == 'followBoss': _helper_suits += 1 if _helper_suits == self.MAX_BOSS_HELPERS - 1: _help_priority = 2 elif _helper_suits == self.MAX_BOSS_HELPERS - 2: _help_priority = 2.5 elif _helper_suits == self.MAX_BOSS_HELPERS - 3: _help_priority = 3.5 elif _helper_suits == self.MAX_BOSS_HELPERS - 4: _help_priority = 4 elif _helper_suits == self.MAX_BOSS_HELPERS - 5: _help_priority = 4.5 if boss == None or _helper_suits == self.MAX_BOSS_HELPERS: _help_priority = 0 if self.fsm.getCurrentState().getName() == 'followBoss': if self.bossSpotKey != boss.boss.spot: self.fsm.request('followBoss', [boss]) return task.again _toons_in_range = 0 in_range = 15 for av in self.suit.air.doId2do.values(): if av.__class__.__name__ == 'DistributedToonAI': if av.zoneId == self.suit.zoneId: if self.suit.getDistance(av) <= in_range: _toons_in_range += 1 if self.fsm.getCurrentState().getName() == 'followBoss': _panic_priority = _toons_in_range / 0.85 else: _panic_priority = _toons_in_range / 0.75 if self.fsm.getCurrentState().getName() == 'panic' and _toons_in_range > 0: _run_priority = 5 if self.suit.getHealth() <= self.panicHP: if _panic_priority < 4: _panic_priority = 4 if _run_priority == 5: self.fsm.request('runAway', [av]) del _help_priority del _panic_priority del _run_priority del _helper_suits del boss del in_range del _toons_in_range try: del av except: pass if task: return task.done else: return elif _panic_priority <= 2 and _help_priority <= 2: state_num = random.randint(0, 2) if state_num == 0 or state_num == 1: new_state = 'neutral' else: new_state = 'followBoss' if boss == None or _help_priority == 0: if self.fsm.getCurrentState().getName() != 'neutral': self.fsm.request('neutral') else: new_state = 'neutral' if self.fsm.getCurrentState().getName() != new_state: if self.fsm.getCurrentState().getName() == 'followBoss': del _help_priority del _panic_priority del _run_priority del _helper_suits del boss del in_range del _toons_in_range try: del args except: pass try: del new_state except: pass try: del state_num except: pass try: del av except: pass if task: return task.again else: return args = [] if new_state == 'followBoss': args = [boss] self.fsm.request(new_state, args) elif _panic_priority > _help_priority: if self.fsm.getCurrentState().getName() != 'panic': self.fsm.request('panic') del _help_priority del _panic_priority del _run_priority del _helper_suits del boss del in_range del _toons_in_range try: del args except: pass try: del new_state except: pass try: del state_num except: pass try: del av except: pass if task: return task.done else: return elif _panic_priority < _help_priority: if self.fsm.getCurrentState().getName() != 'followBoss': self.fsm.request('followBoss', [boss]) elif _panic_priority == _help_priority: new_state = random.choice(['panic', 'followBoss']) if self.fsm.getCurrentState().getName() != new_state: args = [] if new_state == 'followBoss': args = [boss] self.fsm.request(new_state, args) del _help_priority del _panic_priority del _run_priority del _helper_suits del boss del in_range del _toons_in_range try: del args except: pass try: del new_state except: pass try: del state_num except: pass try: del av except: pass if task: return task.again else: return def enterOff(self): pass def exitOff(self): pass def enterNeutral(self): self.suit.createPath(fromCurPos=True) self.numAttacksThrown = 0 if not self.suit.isBackup(): self.neutral_startLookingForToons() def neutral_startLookingForToons(self): taskMgr.add(self.__lookForToons, self.suit.uniqueName('lookForToon')) def neutral_stopLookingForToons(self): taskMgr.remove(self.suit.uniqueName('lookForToon')) def __lookForToons(self, task): if self.suit.isBackup() or not hasattr(self, 'numAttacksThrown'): return task.done elif self.suit.getAttacking(): task.delayTime = 1.0 return task.again elif self.numAttacksThrown >= self.Difficulty2MaxAttackThrows[self.suit.getLevel()]: self.numAttacksThrown = 0 if not self.suit.isWalking(): self.suit.createPath(path_key=self.suit.currentPath, fromCurPos=True) task.delayTime = 10 return task.again else: closestToonOrTurret = None obj2range = {} for obj in base.air.doId2do.values(): if obj.__class__.__name__ in ('DistributedToonAI', 'DistributedPieTurretAI'): if obj.zoneId == self.suit.zoneId: if not obj.isDead(): if obj.__class__.__name__ == 'DistributedToonAI': if obj.getNumAttackers() < self.MAX_ATTACKERS: dist = obj.getDistance(self.suit) if dist <= self.ATTACK_DISTANCE: obj2range[obj] = dist else: dist = obj.getDistance(self.suit) if dist <= self.ATTACK_DISTANCE: obj2range[obj] = dist ranges = [] for distance in obj2range.values(): ranges.append(distance) ranges.sort() for obj in obj2range.keys(): distance = obj2range[obj] if distance == ranges[0]: closestToonOrTurret = obj if closestToonOrTurret != None and not self.suit.getAttacking(): if self.suit.head != 'vp': if self.suit.walkTrack: self.ignore(self.suit.walkTrack.getName()) self.suit.walkTrack.clearToInitial() self.suit.walkTrack = None self.suit.b_setSuitState(3, -1, -1) self.suit.b_setAnimState('neutral') self.end(0) self.suit.headsUp(closestToonOrTurret) self.suit.attackToon(closestToonOrTurret) self.suit.setAttacking(True) if closestToonOrTurret.__class__.__name__ == 'DistributedToonAI': closestToonOrTurret.addNewAttacker(self.suit.doId) self.numAttacksThrown += 1 return task.done if self.numAttacksThrown > 0: if not self.suit.isWalking(): self.suit.createPath(path_key=self.suit.currentPath, fromCurPos=True) elif not self.suit.isWalking(): self.suit.createPath(fromCurPos=True) self.numAttacksThrown = 0 task.delayTime = 3.5 return task.again def exitNeutral(self): self.neutral_stopLookingForToons() del self.numAttacksThrown def enterPanic(self): taskMgr.add(self.__panic, self.suit.uniqueName('panic')) def __panic(self, task): self.suit.createPath(durationFactor=self.PANIC_SPEED, fromCurPos=True) if task.time == 2.0: self.__think(None) task.delayTime = self.PANIC_DELAY return task.again def exitPanic(self): taskMgr.remove(self.suit.uniqueName('panic')) def enterFollowBoss(self, boss): self.boss = boss if boss.boss.spot == None: self.bossSpot = boss.getPos(render) else: self.bossSpot = CIGlobals.SuitSpawnPoints[self.suit.hood][boss.boss.spot] if self.suit.currentPath == boss.boss.spot: self.suit.createPath(path_key=boss.boss.spot, fromCurPos=True) else: self.suit.currentPathQueue = SuitPathFinder.find_path(self.suit.hood, self.suit.currentPath, boss.boss.spot) self.suit.currentPathQueue.remove(self.suit.currentPathQueue[0]) self.suit.createPath(fromCurPos=True) taskMgr.add(self.__followBoss, self.suit.uniqueName('followBoss')) self.bossSpotKey = boss.boss.spot return def __followBoss(self, task): if self.boss not in self.suit.getManager().suits.values(): self.fsm.request('neutral') return task.done elif self.suit.getDistance(self.boss) <= 4: self.suit.b_setSuitState(3, -1, -1) if self.suit.walkTrack: self.suit.ignore(self.suit.walkTrack.getDoneEvent()) self.suit.walkTrack.pause() self.suit.walkTrack = None self.suit.b_setAnimState('neutral') self.suit.setH(self.suit.getH() - 180) self.suit.d_setH(self.suit.getH()) return task.done else: return task.cont def exitFollowBoss(self): self.suit.resetPathQueue() taskMgr.remove(self.suit.uniqueName('followBoss')) del self.boss del self.bossSpot del self.bossSpotKey def enterRunAway(self, toon): self.toon = toon self.suit.createPath(durationFactor=self.RUNAWAY_SPEED, fromCurPos=True) taskMgr.add(self.__runAway, self.suit.uniqueName('runAway')) def __runAway(self, task): try: if self.suit.getDistance(self.toon) >= self.RUNAWAY_SAFE_DISTANCE: self.start() return task.done if self.suit.walkTrack == None or self.suit.walkTrack.isStopped(): self.suit.createPath(durationFactor=self.RUNAWAY_SPEED, fromCurPos=True) return task.cont except: self.fsm.request('neutral') return task.done return def exitRunAway(self): taskMgr.remove(self.suit.uniqueName('runAway')) del self.toon
class Human(HumanBase.HumanBase, Biped.Biped): notify = DirectNotifyGlobal.directNotify.newCategory("Human") prebuiltAnimData = {} def __init__(self, other=None): Biped.Biped.__init__(self, other, HumanAnimationMixer) self.zombie = False self.crazyColorSkin = False self.crazyColorSkinIndex = 0 self.flattenPending = None self.flattenSuperLowName = None self.optimizeLOD = base.config.GetBool("optimize-avatar-lod", 1) self.loaded = 0 self.playingRate = None self.shadowFileName = "models/misc/drop_shadow" self.setFont(PiratesGlobals.getInterfaceFont()) self._Human__blinkName = "blink-" + str(self.this) self.eyeLids = None self.eyeBalls = None self.eyeIris = None self.reducedAnimList = None self.headNode = None self.headEffects = NodePath("headEffects") self.extraNode = None self.scaleNode = None self.rootNode = None self.floorOffsetZ = 0.0 self.isGhost = 0 self.headFudgeHpr = Vec3(0, 0, 0) self.randGen = random.Random() self.randGen.seed(random.random()) self.eyeFSM = ClassicFSM( "eyeFSM", [ State("off", self.enterEyeFSMOff, self.exitEyeFSMOff, ["open", "closed"]), State("open", self.enterEyeFSMOpen, self.exitEyeFSMOpen, ["closed", "off"]), State("closed", self.enterEyeFSMClosed, self.exitEyeFSMClosed, ["open", "off"]), ], "off", "off", ) self.eyeFSM.enterInitialState() if other != None: self.copyHuman(other) def removeCopiedNodes(self): self.dropShadow = self.find("**/drop_shadow*") if not self.dropShadow.isEmpty(): self.deleteDropShadow() else: self.dropShadow = None billboardNode = self.find("**/billboardNode") if not billboardNode.isEmpty(): billboardNode.removeNode() self.getGeomNode().getParent().removeNode() def flattenHuman(self): self.getWeaponJoints() def flattenSuperLow(self): name = "flattenSuperLow-%s" % self.this self.flattenSuperLowName = name model = self.getLOD("500") self.accept(name, self._Human__doneFlattenSuperLow) taskMgr.remove(name) taskMgr.add(self.flattenSuperLowTask, name, extraArgs=[model], taskChain="background") def flattenSuperLowTask(self, model): model = model.copyTo(NodePath()) rhn = model.find("**/rightHand") lhn = model.find("**/leftHand") if lhn: lhn.detachNode() if rhn: rhn.detachNode() node = model.node() gr = SceneGraphReducer() model.node().setAttrib(TransparencyAttrib.make(0), 2000) gr.applyAttribs( node, SceneGraphReducer.TTApplyTextureColor | SceneGraphReducer.TTTexMatrix | SceneGraphReducer.TTOther | SceneGraphReducer.TTCullFace | SceneGraphReducer.TTTransform | SceneGraphReducer.TTColor | SceneGraphReducer.TTColorScale, ) num_removed = gr.flatten(node, -1) gr.makeCompatibleState(node) gr.collectVertexData( node, ~(SceneGraphReducer.CVDFormat | SceneGraphReducer.CVDName | SceneGraphReducer.CVDAnimationType) ) gr.unify(node, 0) name = self.flattenSuperLowName if name: messenger.send(name, [model], taskChain="default") def _Human__doneFlattenSuperLow(self, flat): self.headNode = flat.find("**/def_head01") self.rootNode = flat.find("**/dx_root") self.getWeaponJoints() orig = self.getLOD("500") orig.getChildren().detach() self.loadModel(flat, lodName="500", copy=False, autoBindAnims=False) self.getWeaponJoints() if hasattr(self, "animProp") and self.animProp: self.resetAnimProp() self.findAllMatches("**/def_head01").detach() self.findAllMatches("**/dx_root").detach() for lodName in self.getLODNames(): if lodName == "500": self.headNode.reparentTo(self.getLOD(lodName).find("**/+Character")) self.rootNode.reparentTo(self.getLOD(lodName).find("**/+Character")) continue self.headNode.instanceTo(self.getLOD(lodName).find("**/+Character")) self.rootNode.instanceTo(self.getLOD(lodName).find("**/+Character")) self.headEffects.reparentTo(self.headNode) def _Human__doneFlattenHuman(self, models): self.flattenPending = None self.getWeaponJoints() def copyHuman(self, other): self.gender = other.gender self.loaded = other.loaded self.loadAnimatedHead = other.loadAnimatedHead self.rootScale = other.rootScale def delete(self): try: pass except: self.Human_deleted = 1 taskMgr.remove(self._Human__blinkName) name = self.flattenSuperLowName if name: self.flattenSuperLowName = None self.ignore(name) taskMgr.remove(name) if self.dropShadow and not self.dropShadow.isEmpty(): self.deleteDropShadow() del self.eyeFSM self.controlShapes = None self.sliderNames = None Biped.Biped.delete(self) def isDeleted(self): try: if self.Human_deleted == 1: return True except: return False def fixEyes(self): self.eyeLids = {} self.eyeBalls = {} self.eyeIris = {} for lodName in self.getLODNames(): geom = self.getPart("head", lodName) self.eyeLids[lodName] = geom.findAllMatches("**/*eyelid*") self.eyeBalls[lodName] = geom.findAllMatches("**/eye_ball*") self.eyeIris[lodName] = geom.findAllMatches("**/eye_iris*") self.eyeLids[lodName].stash() self.eyeBalls[lodName].unstash() self.eyeIris[lodName].unstash() def makeAnimDict(self, gender, animNames): self.animTable = [] for currAnim in animNames: anim = animNames.get(currAnim) for currAnimName in anim: self.animTable.append([currAnimName, currAnimName]) self.reducedAnimList = self.animTable def forceLoadAnimDict(self): for anim in self.animDict.keys(): self.getAnimControls(anim) def createAnimDict(self, customList=None): filePrefix = "models/char/m" genderPrefix = "m" if self.style.gender == "f": self.type = BodyDefs.femaleFrames[self.style.getBodyShape()] filePrefix = "models/char/f" genderPrefix = "f" else: self.type = BodyDefs.maleFrames[self.style.getBodyShape()] if self.reducedAnimList is None: self.animDict = self.prebuiltAnimData[genderPrefix + self.type] return None filePrefix += "p" animList = self.reducedAnimList self.animDict = {} for anim in animList: animSuffix = "" for i in range(0, len(CustomAnimDict[genderPrefix + self.type])): if anim[0] == CustomAnimDict[genderPrefix + self.type][i]: animSuffix = "_" + genderPrefix + NewModelDict.get(self.type) break continue self.animDict[anim[0]] = filePrefix + "_" + anim[1] + animSuffix return filePrefix def getIsPaid(self): return True def setupGhostNodes(self): lod = NodePath(self.getLODNode()) for node in lod.getChildren(): eyes = node.findAllMatches("**/eye*") if eyes: eyes.wrtReparentTo(eyes[0].getParent().attachNewNode(ModelNode("eyes"))) continue def loadHuman(self, other): other.style = self.style other.gender = self.style.gender other.model.dna = self.style self.createAnimDict() if self.style.gender == "f": self.headFudgeHpr = Vec3(0, 0, 0) idx = 1 else: self.headFudgeHpr = Vec3(0, 0, 0) idx = 0 other.zombie = self.zombie other.crazyColorSkin = self.crazyColorSkin other.setCrazyColorSkinIndex(self.getCrazyColorSkinIndex()) yieldThread("anim dict") other.isPaid = self.getIsPaid() other.showLOD(2000) yieldThread("showLOD") base.loadingScreen.tick() if other.zombie: other.showZombie() if hasattr(self, "motionFSM"): self.motionFSM.setAvatar(self) base.loadingScreen.tick() yieldThread("zombie") other.applyBodyShaper() base.loadingScreen.tick() yieldThread("body shaper") base.loadingScreen.tick() other.applyHeadShaper() yieldThread("head shaper") base.loadingScreen.tick() if self.zombie == 2: other.model.eyeBalls.unstash() other.model.irises.stash() elif self.zombie: other.model.eyeBalls.stash() other.model.irises.stash() else: other.model.eyeBalls.unstash() other.model.irises.unstash() base.loadingScreen.tick() self.copyActor(other) base.loadingScreen.tick() self.floorOffsetZ = other.rootNode.getZ() yieldThread("copyActor") self.copyHuman(other) if self.isGhost: self.setupGhostNodes() gnodes = self.getLOD("500").findAllMatches("**/+GeomNode") for node in gnodes: node.setTextureOff(other.model.tattooStage) base.loadingScreen.tick() self.flattenSuperLow() self.rootNode = self.getLOD("500").find("**/dx_root") self.headNode = self.getLOD("500").find("**/def_head01") lodNames = self.getLODNames() self.scaleNode = self.controlJoint(None, "legs", "def_scale_jt", lodNames[0]) if len(lodNames) > 1: for i in range(1, len(lodNames)): self.controlJoint(self.scaleNode, "legs", "def_scale_jt", lodNames[i]) self.setGlobalScale(self.calcBodyScale()) yieldThread("copyHuman") base.loadingScreen.tick() self.loadAnimsOnAllLODs(self.animDict, "modelRoot") base.loadingScreen.tick() yieldThread("loadAnims") other.zombie = 0 other.crazyColorSkin = 0 other.setCrazyColorSkinIndex(0) other.showNormal() yieldThread("show normal") self.initializeNametag3d() self.initializeDropShadow() self.setName(self.getName()) yieldThread("misc nodes") base.loadingScreen.tick() self.loaded = 1 def setGlobalScale(self, scale): self.scaleNode.setScale(scale) self.rootScale = scale self.scaleNode.setZ(-(self.floorOffsetZ * (1 - scale))) def initializeMiscNodes(self): self.initializeNametag3d() self.initializeDropShadow() def undoControlJoints(self): self.getGeomNode().getParent().findAllMatches("def_*").detach() self.getGeomNode().getParent().findAllMatches("trs_*").detach() self.findAllMatches("def_*").detach() self.findAllMatches("trs_*").detach() def cleanupHuman(self, gender="m"): self.eyeFSM.request("off") self.undoControlJoints() self.removeCopiedNodes() self.eyeLids = {} self.eyeBalls = {} self.eyeIris = {} self.flush() self.loaded = 0 self.master = 0 def getCrazyColorSkinIndex(self): return self.crazyColorSkinIndex def setCrazyColorSkinIndex(self, index): if len(HumanDNA.crazySkinColors) > index: self.crazyColorSkinIndex = index else: self.notify.warning( "(Human)index: %d is out of bounds for crazyColorSkin: %d" % (index, len(HumanDNA.crazySkinColors)) ) def generateHuman(self, gender, others, useFaceTex=False): parent = self.getParent() self.detachNode() if gender == "f": other = others[1] else: other = others[0] if self.loaded: self.cleanupHuman() other.useFaceTex = useFaceTex self.loadHuman(other) if self.isLocal(): self.renderReflection = True self.setRenderReflection() self.resetEffectParent() self.enableMixing() self.reparentTo(parent) def getShadowJoint(self): return self.nametagNodePath def getNametagJoints(self): joints = [] for lodName in self.getLODNames(): bundle = self.getPartBundle("modelRoot", lodName) joint = bundle.findChild("name_tag") if joint: joints.append(joint) continue return joints def _Human__blinkOpenEyes(self, task): if self.eyeFSM.getCurrentState().getName() == "closed": self.eyeFSM.request("open") r = self.randGen.random() if r < 0.10000000000000001: t = 0.20000000000000001 else: t = r * 4.0 + 1.0 taskMgr.doMethodLater(t, self._Human__blinkCloseEyes, self._Human__blinkName) return Task.done def _Human__blinkCloseEyes(self, task): if self.eyeFSM.getCurrentState().getName() != "open": taskMgr.doMethodLater(4.0, self._Human__blinkCloseEyes, self._Human__blinkName) else: self.eyeFSM.request("closed") taskMgr.doMethodLater(0.125, self._Human__blinkOpenEyes, self._Human__blinkName) return Task.done def startBlink(self): taskMgr.remove(self._Human__blinkName) if self.eyeLids: self.openEyes() taskMgr.doMethodLater(self.randGen.random() * 4.0 + 1, self._Human__blinkCloseEyes, self._Human__blinkName) def stopBlink(self): taskMgr.remove(self._Human__blinkName) if self.eyeLids: self.eyeFSM.request("open") def closeEyes(self): self.eyeFSM.request("closed") def openEyes(self): self.eyeFSM.request("open") def enterEyeFSMOff(self): pass def exitEyeFSMOff(self): pass def enterEyeFSMOpen(self): for lodName in self.getLODNames(): self.eyeLids[lodName].hide() self.eyeBalls[lodName].show() self.eyeIris[lodName].show() def exitEyeFSMOpen(self): pass def enterEyeFSMClosed(self): return None for lodName in self.getLODNames(): self.eyeLids[lodName].show() self.eyeBalls[lodName].hide() self.eyeIris[lodName].hide() def exitEyeFSMClosed(self): pass def getGlobalScale(self): return self.rootScale def calcBodyScale(self): idx = 0 if self.gender == "f": idx = 1 mappedValue = (0.80000000000000004 + (1 + self.style.getBodyHeight()) * 0.20000000000000001) * BodyScales[idx][ self.style.getBodyShape() ] return mappedValue def setupAnimDicts(cls): for t in BodyDefs.maleFrames: cls.storeAnimDict("models/char/mp", "m", t) for t in BodyDefs.femaleFrames: cls.storeAnimDict("models/char/fp", "f", t) setupAnimDicts = classmethod(setupAnimDicts) def storeAnimDict(cls, prefix, gender, type): qualifier = gender + type animList = AnimListDict[type] cls.prebuiltAnimData[qualifier] = {} for anim in animList: if anim[0] == "intro": continue animSuffix = "" for i in range(0, len(CustomAnimDict[qualifier])): if anim[0] == CustomAnimDict[qualifier][i]: animSuffix = "_" + gender + NewModelDict.get(type) break continue cls.prebuiltAnimData[qualifier][anim[0]] = prefix + "_" + anim[1] + animSuffix storeAnimDict = classmethod(storeAnimDict)
class DynamicHuman(HumanBase.HumanBase, Biped.Biped): notify = DirectNotifyGlobal.directNotify.newCategory('Human') def __init__(self, other = None): Biped.Biped.__init__(self, other, HumanAnimationMixer) self.model = None self.zombie = False self.crazyColorSkin = False self.crazyColorSkinIndex = 0 self.flattenPending = None if __dev__: self.optimizeLOD = base.config.GetBool('optimize-avatar-lod', 1) else: self.optimizeLOD = 0 self.master = 0 self.loaded = 0 self.playingRate = None self.shadowFileName = 'models/misc/drop_shadow' self.setFont(PiratesGlobals.getInterfaceFont()) self._DynamicHuman__blinkName = 'blink-' + str(self.this) self.eyeLids = None self.eyeBalls = None self.eyeIris = None self.reducedAnimList = None self.headNode = None self.extraNode = None self.scaleNode = None self.rootNode = None self.floorOffsetZ = 0.0 self.headFudgeHpr = Vec3(0, 0, 0) self.randGen = random.Random() self.randGen.seed(random.random()) self.eyeFSM = ClassicFSM('eyeFSM', [ State('off', self.enterEyeFSMOff, self.exitEyeFSMOff, [ 'open', 'closed']), State('open', self.enterEyeFSMOpen, self.exitEyeFSMOpen, [ 'closed', 'off']), State('closed', self.enterEyeFSMClosed, self.exitEyeFSMClosed, [ 'open', 'off'])], 'off', 'off') self.eyeFSM.enterInitialState() self.isPaid = True if other != None: self.copyHuman(other) def removeCopiedNodes(self): self.dropShadow = self.find('**/drop_shadow*') if not self.dropShadow.isEmpty(): self.deleteDropShadow() def flattenHuman(self): self.deleteNametag3d() self.getWeaponJoints() def _DynamicHuman__doneFlattenHuman(self, models): self.flattenPending = None self.getWeaponJoints() def copyHuman(self, other): self.gender = other.gender self.loaded = other.loaded self.type = other.type self.loadAnimatedHead = other.loadAnimatedHead self.flattenHuman() self.model = None def delete(self): self.Human_deleted = 1 taskMgr.remove(self._DynamicHuman__blinkName) if self.dropShadow and not self.dropShadow.isEmpty(): self.deleteDropShadow() del self.eyeFSM self.controlShapes = None self.sliderNames = None if self.model: self.model.delete() del self.model Biped.Biped.delete(self) def isDeleted(self): try: if self.Human_deleted == 1: return True except: return False def setupExtraNodes(self): idx = 0 if self.gender == 'f': idx = 1 jointName = 'def_head01' jointNameExtra = 'def_extra_jt' jointNameScale = 'def_scale_jt' lods = self.getLODNames() self.headNode = self.controlJoint(None, 'legs', jointName, lods[0]) self.extraNode = self.controlJoint(None, 'legs', jointNameExtra, lods[0]) self.scaleNode = self.controlJoint(None, 'legs', jointNameScale, lods[0]) self.rootNode = self.getLOD('2000').find('**/dx_root') self.floorOffsetZ = self.rootNode.getZ() for lod in lods[1:]: self.controlJoint(self.headNode, 'legs', jointName, lod) self.controlJoint(self.extraNode, 'legs', jointNameExtra, lod) self.controlJoint(self.scaleNode, 'legs', jointNameScale, lod) exposedHeadJoint = self.getLOD(lod).find('**/def_head01') if not exposedHeadJoint.isEmpty(): exposedHeadJoint.removeNode() continue self.headNode.setScale(HeadScales[idx][self.style.getBodyShape()]) self.setGlobalScale(self.calcBodyScale()) def undoExtraNodes(self): jointNameExtra = 'def_extra_jt' jointNameScale = 'def_scale_jt' joints = self.findAllMatches('**/*' + jointNameExtra) if not joints.isEmpty(): joints.detach() joints.clear() if self.headNode: self.headNode.removeNode() self.headNode = None self.extraNode.removeNode() self.extraNode = None joints = self.findAllMatches('**/*' + jointNameScale) if not joints.isEmpty(): joints.detach() joints.clear() if self.scaleNode: self.scaleNode.removeNode() self.scaleNode = None self.rootNode = None def fixEyes(self): self.eyeLids = { } self.eyeBalls = { } self.eyeIris = { } for lodName in self.getLODNames(): geom = self.getPart('head', lodName) self.eyeLids[lodName] = geom.findAllMatches('**/*eyelid*') self.eyeBalls[lodName] = geom.findAllMatches('**/eye_ball*') self.eyeIris[lodName] = geom.findAllMatches('**/eye_iris*') self.eyeLids[lodName].stash() self.eyeBalls[lodName].unstash() self.eyeIris[lodName].unstash() def generateFaceTexture(self): faceTextureIdx = self.style.head.texture if self.gender == 'f': face_textures = PirateFemale.face_textures else: face_textures = PirateMale.face_textures tex_name = self.getTrySafe(face_textures, faceTextureIdx) if tex_name != None: tex = self.model.faceTextures.findTexture(tex_name) if tex == None: return None else: return None for lodName in self.getLODNames(): self.findAllMatches('**/body_master_face').setTexture(tex, 1) def generateSkinColor(self): skinColor = self.style.getSkinColor() self.model.faces[0].setColorScale(skinColor) if self.model.newAvatars: self.model.currentBody.setColorScale(skinColor) else: numPaths = self.model.body.getNumPaths() if self.zombie: self.model.body.setColorScale(Vec4(1, 1, 1, 1)) else: self.model.body.setColorScale(skinColor) def generateSkinTexture(self): bodyTextureIdx = self.style.body.skin if self.zombie: if self.gender == 'f': bodyTextureIdx = PirateFemale.ZOMB_BODY_TEXTURE else: bodyTextureIdx = PirateMale.ZOMB_BODY_TEXTURE if self.gender == 'f': body_textures = PirateFemale.body_textures[self.style.body.shape] else: body_textures = PirateMale.body_textures[self.style.body.shape] tex_name = self.getTrySafe(body_textures, bodyTextureIdx) if tex_name != None: tex = self.model.bodyTextures.findTexture(tex_name) else: return None for parts in self.model.bodys: parts.setTexture(tex, 1) def generateHairColor(self, colorName = None, colorModel = None): self.model.setHairBaseColor() def getTrySafe(self, list, idx): try: if type(idx) == str: lookup = idx.split('_cut')[0] else: lookup = idx return list[lookup] except: return None def generateEyesTexture(self): eyesTextureIdx = self.style.head.eyes.color if self.gender == 'f': eye_iris_textures = PirateFemale.eye_iris_textures else: eye_iris_textures = PirateMale.eye_iris_textures tex_name = self.getTrySafe(eye_iris_textures, eyesTextureIdx) if tex_name != None: tex = self.eyeIrisTextures.findTexture(tex_name) else: return None self.model.irises.setTexture(tex, 1) def generateHatColor(self): style = self.style if self.zombie: style = self.model.dnaZomb hatColor = style.lookupHatColor() geom = self.getGeomNode() geom.findAllMatches('**/hat_band*').setColorScale(hatColor) def generateClothesColor(self): style = self.style if self.zombie: style = self.model.dnaZomb clothesTopColor = style.lookupClothesTopColor() clothesBotColor = style.lookupClothesBotColor() geom = self.getGeomNode() geom.findAllMatches('**/clothing_layer1_shirt*').setColorScale(clothesTopColor[0]) geom.findAllMatches('**/clothing_layer2_vest*').setColorScale(clothesTopColor[1]) geom.findAllMatches('**/clothing_layer3_coat*').setColorScale(clothesTopColor[2]) geom.findAllMatches('**/clothing_layer1_pant*').setColorScale(clothesBotColor[0]) geom.findAllMatches('**/clothing_layer2_belt*').setColorScale(clothesBotColor[1]) geom.findAllMatches('**/clothing_layer1_shoe*').setColorScale(clothesBotColor[2]) def generateColor(self): self.generateSkinColor() self.generateHairColor() self.generateHatColor() def makeAnimDict(self, gender, animNames): self.animDict = [] for currAnim in animNames: anim = animNames.get(currAnim) for currAnimName in anim: self.animTable.append([ currAnimName, currAnimName]) self.reducedAnimList = self.animDict def forceLoadAnimDict(self): for anim in self.animDict: self.getAnimControls(anim[0]) def createAnimDict(self, customList = None): if self.gender == 'f': filePrefix = 'models/char/f' genderPrefix = 'f' else: filePrefix = 'models/char/m' genderPrefix = 'm' filePrefix += 'p' animList = self.reducedAnimList if animList is None: animList = AnimListDict[self.type] AnimDict.clear() for anim in animList: animSuffix = '' for customAnim in CustomAnimDict[genderPrefix + self.type]: if anim[0] == customAnim: animSuffix = '_' + genderPrefix + NewModelDict.get(self.type) break continue AnimDict[anim[0]] = filePrefix + '_' + anim[1] + animSuffix if self.reducedAnimList is None: AnimDict.pop('intro') return filePrefix def generateBody(self, copy = 1): filePrefix = self.createAnimDict() lodString = '2000' self.loadModel(filePrefix + '_' + lodString, 'modelRoot', '2000', copy) self.loadAnims(AnimDict, 'modelRoot', 'all') if loader.loadModel(filePrefix + '_' + '1000', allowInstance = True) != None: lodString = '1000' self.loadModel(filePrefix + '_' + lodString, 'modelRoot', '1000', copy) if loader.loadModel(filePrefix + '_' + '500', allowInstance = True) != None: lodString = '500' self.loadModel(filePrefix + '_' + lodString, 'modelRoot', '500', copy) self.makeSubpart('head', [ 'zz_head01'], []) self.makeSubpart('torso', [ 'zz_spine01'], [ 'zz_head01']) self.makeSubpart('legs', [ 'dx_root'], [ 'zz_spine01']) self.setSubpartsComplete(True) self.getWeaponJoints() self.eyeIrisTextures = loader.loadModel('models/misc/eye_iris.bam') def refreshBody(self): if self.style.getGender() == 'f': gender = 1 cjs = FemaleBodyShapeControlJoints matrix = FemaleBodyShapeControlJointMatrix else: gender = 0 cjs = MaleBodyShapeControlJoints matrix = MaleBodyShapeControlJointMatrix type = self.style.getBodyShape() filePrefix = self.createAnimDict() self.loadAnims(AnimDict, 'modelRoot', 'all') for jointName in cjs: joint = self.find('**/*' + jointName) vector = matrix[jointName][type] if jointName.find('def') != -1: joint.setScale(vector) continue joint.setPos(vector) self.headNode.setScale(HeadScales[gender][self.style.getBodyShape()]) self.setGlobalScale(self.calcBodyScale()) self.createAnimDict() self.stop(self.getCurrentAnim()) self.loop(self.getCurrentAnim()) def setLODs(self): self.setLODNode() avatarDetail = base.config.GetString('avatar-detail', 'high') if avatarDetail == 'high': dist = [ 0, 20, 80, 280] elif avatarDetail == 'med': dist = [ 0, 10, 40, 280] elif avatarDetail == 'low': dist = [ 0, 5, 20, 280] else: raise StandardError, 'Invalid avatar-detail: %s' % avatarDetail self.addLOD(2000, dist[1], dist[0]) self.addLOD(1000, dist[2], dist[1]) self.addLOD(500, dist[3], dist[2]) if self.optimizeLOD: lowLOD = self.getLOD('500') lowLOD.setTextureOff(1000) lowLOD.setTransparency(0, 1000) self.getLODNode().setCenter(Point3(0, 0, 5)) def showLOD(self, lodName): if not self.model.loaded: self.model.setupHead(lodName) self.model.setupBody(lodName) self.model.setupClothing(lodName) if self.master: self.model.setupSelectionChoices('NPC') self.model.loaded = 1 self.model.setFromDNA() self.generateEyesTexture() if self.optimizeLOD: self.optimizeLowLOD() self.generateColor() def loadHuman(self, gender = 'm', other = None): if other: pirate = other pirate.style = self.style else: pirate = self pirate.gender = gender if self.loaded: return None if pirate.gender == 'f': pirate.type = BodyDefs.femaleFrames[pirate.style.getBodyShape()] controlShapes = PirateFemale.ControlShapes sliderNames = PirateFemale.SliderNames else: pirate.type = BodyDefs.maleFrames[pirate.style.getBodyShape()] controlShapes = PirateMale.ControlShapes sliderNames = PirateMale.SliderNames if not pirate.loaded: pirate.setLODs() pirate.loadAnimatedHead = True pirate.generateBody() if pirate.gender == 'f': pirate.model = PirateFemale.PirateFemale(pirate, pirate.style) self.pirateFemale = PirateFemale.PirateFemale(pirate, pirate.style) else: pirate.model = PirateMale.PirateMale(pirate, pirate.style) self.pirateMale = PirateMale.PirateMale(pirate, pirate.style) if base.config.GetBool('debug-dynamic-human', 0): pirate.model.newAvatars = True else: pirate.model.newAvatars = False pirate.faceAwayFromViewer() pirate.fixEyes() else: pirate.model.dna = pirate.style pirate.reducedAnimList = self.reducedAnimList pirate.createAnimDict() pirate.loadAnims(AnimDict, 'modelRoot', 'all') self.lods = pirate.getLODNames() if pirate.gender == 'f': self.headFudgeHpr = Vec3(0, 0, 0) idx = 1 else: self.headFudgeHpr = Vec3(0, 0, 0) idx = 0 pirate.zombie = self.zombie pirate.showLOD(2000) pirate.loaded = 1 self.model = pirate.model if pirate.zombie: pirate.showZombie() else: pirate.showNormal() if hasattr(self, 'motionFSM'): self.motionFSM.setAvatar(self) self.controlShapes = controlShapes self.sliderNames = sliderNames if other: self.copyActor(other) self.fixEyes() self.copyHuman(other) self.undoExtraNodes() self.setupExtraNodes() self.applyBodyShaper() self.applyHeadShaper() if other: pirate.zombie = 0 pirate.showNormal() pirate.unloadAnims(AnimDict, None, None) pirate.removeAnimControlDict() pirate.reducedAnimList = None self.initializeMiscNodes() self.startBlink() def initializeMiscNodes(self): self.initializeNametag3d() self.initializeDropShadow() if self.getLOD('2000') == None: return None exposedHeadJoint = self.getLOD('2000').find('**/def_head01') if not exposedHeadJoint.isEmpty(): idx = 0 if self.gender == 'f': idx = 1 exposedHeadJoint.setScale(1) self.headNode.reparentTo(exposedHeadJoint) self.headNode.setScale(HeadScales[idx][self.style.getBodyShape()]) def undoControlJoints(self): self.getGeomNode().getParent().findAllMatches('def_*').detach() self.getGeomNode().getParent().findAllMatches('trs_*').detach() self.findAllMatches('def_*').detach() self.findAllMatches('trs_*').detach() def cleanupHuman(self, gender = 'm'): self.eyeFSM.request('off') self.undoExtraNodes() self.undoControlJoints() self.eyeLids = { } self.eyeBalls = { } self.eyeIris = { } self.flush() self.loaded = 0 self.master = 0 def generateHuman(self, gender = 'm', others = None): other = None if others: if gender == 'f': other = others[1] else: other = others[0] if other and not (other.master) and other.loaded: other.cleanupHuman() elif self.loaded: self.cleanupHuman() self.loadHuman(self.style.gender, other) if self.isLocal(): self.renderReflection = True self.setRenderReflection() self.disableMixing() self.enableMixing() generateHuman = quickProfile('loadHuman')(generateHuman) def getShadowJoint(self): return self def getNametagJoints(self): joints = [] for lodName in self.getLODNames(): bundle = self.getPartBundle('legs', lodName) joint = bundle.findChild('name_tag') if joint: joints.append(joint) continue return joints def _DynamicHuman__blinkOpenEyes(self, task): if self.eyeFSM.getCurrentState().getName() == 'closed': self.eyeFSM.request('open') r = self.randGen.random() if r < 0.10000000000000001: t = 0.20000000000000001 else: t = r * 4.0 + 1.0 taskMgr.doMethodLater(t, self._DynamicHuman__blinkCloseEyes, self._DynamicHuman__blinkName) return Task.done def _DynamicHuman__blinkCloseEyes(self, task): if self.eyeFSM.getCurrentState().getName() != 'open': taskMgr.doMethodLater(4.0, self._DynamicHuman__blinkCloseEyes, self._DynamicHuman__blinkName) else: self.eyeFSM.request('closed') taskMgr.doMethodLater(0.125, self._DynamicHuman__blinkOpenEyes, self._DynamicHuman__blinkName) return Task.done def startBlink(self): taskMgr.remove(self._DynamicHuman__blinkName) if self.eyeLids: self.openEyes() taskMgr.doMethodLater(self.randGen.random() * 4.0 + 1, self._DynamicHuman__blinkCloseEyes, self._DynamicHuman__blinkName) def stopBlink(self): taskMgr.remove(self._DynamicHuman__blinkName) if self.eyeLids: self.eyeFSM.request('open') def closeEyes(self): self.eyeFSM.request('closed') def openEyes(self): self.eyeFSM.request('open') def enterEyeFSMOff(self): pass def exitEyeFSMOff(self): pass def enterEyeFSMOpen(self): for lodName in self.getLODNames(): if not self.eyeLids[lodName].isEmpty(): self.eyeLids[lodName].hide() self.eyeBalls[lodName].show() self.eyeIris[lodName].show() continue def exitEyeFSMOpen(self): pass def enterEyeFSMClosed(self): return None for lodName in self.getLODNames(): if not self.eyeLids[lodName].isEmpty(): self.eyeLids[lodName].show() self.eyeBalls[lodName].hide() self.eyeIris[lodName].hide() continue def exitEyeFSMClosed(self): pass def setControlValue(self, r, name): if self.style.getGender() == 'f': matrixF = FemaleHeadShapeControlJointMatrix matrixI = FemaleHeadShapeInitialControlJointMatrix else: matrixF = MaleHeadShapeControlJointMatrix matrixI = MaleHeadShapeInitialControlJointMatrix shapes = self.controlShapes ctl = shapes[name] slider = ctl[0] if r < 0.0: if len(ctl) > 1: slider = ctl[1] for i in range(0, len(slider)): jointName = slider[i][0] jointCtls = self.findAllMatches(jointName) posI = matrixI[jointName][0] hprI = matrixI[jointName][1] sclI = matrixI[jointName][2] posF = VBase3(posI[0], posI[1], posI[2]) hprF = VBase3(hprI[0], hprI[1], hprI[2]) sclF = VBase3(sclI[0], sclI[1], sclI[2]) self.notify.debug('scv: %s initial %s' % (jointName, posI)) dr = slider[i][4] * r ctl[0][i][5] = dr posDelta = VBase3(0, 0, 0) hprDelta = VBase3(0, 0, 0) sclDelta = VBase3(0, 0, 0) for sliderIdx in xrange(0, len(matrixF[jointName])): sliderName = matrixF[jointName][sliderIdx] jointSet = shapes[sliderName][0] for jointIdx in xrange(0, len(jointSet)): if jointSet[jointIdx][0] == jointName: if jointSet[jointIdx][1] == TX: posDelta.setX(posDelta.getX() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == TY: posDelta.setY(posDelta.getY() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == TZ: posDelta.setZ(posDelta.getZ() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == RX: hprDelta.setX(hprDelta.getX() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == RY: hprDelta.setY(hprDelta.getY() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == RZ: hprDelta.setZ(hprDelta.getZ() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == SX: if r < 0.0: sclDelta.setX(sclDelta.getX() + jointSet[jointIdx][5] / jointSet[jointIdx][2]) else: sclDelta.setX(sclDelta.getX() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == SY: if r < 0.0: sclDelta.setY(sclDelta.getY() + jointSet[jointIdx][5] / jointSet[jointIdx][2]) else: sclDelta.setY(sclDelta.getY() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == SZ: if r < 0.0: sclDelta.setZ(sclDelta.getZ() + jointSet[jointIdx][5] / jointSet[jointIdx][2]) else: sclDelta.setZ(sclDelta.getZ() + jointSet[jointIdx][5]) else: self.notify.warning('scv:wrong element = %s' % jointSet[jointIdx][1]) jointSet[jointIdx][1] == TX self.notify.debug('scv: %s composite posDelta = %s' % (jointName, posDelta)) posF.setX(posI[0] + posDelta[0]) posF.setY(posI[1] + posDelta[1]) posF.setZ(posI[2] + posDelta[2]) self.notify.debug('scv: %s final posDelta%s' % (jointName, posF)) self.notify.debug('scv: %s composite hprDelta = %s' % (jointName, hprDelta)) hprF.setX(hprI[0] + hprDelta[0]) hprF.setY(hprI[1] + hprDelta[1]) hprF.setZ(hprI[2] + hprDelta[2]) self.notify.debug('scv: %s final hprDelta%s' % (jointName, hprF)) self.notify.debug('scv: %s composite sclDelta = %s' % (jointName, sclDelta)) sclF.setX(sclI[0] + sclDelta[0]) sclF.setY(sclI[1] + sclDelta[1]) sclF.setZ(sclI[2] + sclDelta[2]) self.notify.debug('scv: %s final sclDelta%s' % (jointName, sclF)) for j in range(0, jointCtls.getNumPaths()): jointCtl = jointCtls[j] jointCtl.setPosHprScale(posF, hprF, sclF) def applyBodyShaper(self): if self.style.getGender() == 'f': cjs = FemaleBodyShapeControlJoints matrix = FemaleBodyShapeControlJointMatrix else: cjs = MaleBodyShapeControlJoints matrix = MaleBodyShapeControlJointMatrix type = self.style.getBodyShape() for jointName in cjs: for lodName in self.getLODNames(): if lodName == '2000': joint = self.controlJoint(None, 'legs', jointName, lodName) continue joint = self.controlJoint(joint, 'legs', jointName, lodName) joint = self.find('**/*' + jointName) vector = matrix[jointName][type] if jointName.find('def') != -1: joint.setScale(vector) continue joint.setPos(vector) def undoBodyShaper(self): if self.style.getGender() == 'f': cjs = FemaleBodyShapeControlJoints else: cjs = MaleBodyShapeControlJoints def applyHeadShaper(self): self.createControlJoints() self.initHeadControlShapes() self.setHeadControlShapeValues() def undoHeadShaper(self): if self.style.getGender() == 'f': cjs = FemaleHeadShapeControlJoints else: cjs = MaleHeadShapeControlJoints def createControlJoints(self): if self.style.getGender() == 'f': cjs = FemaleHeadShapeControlJoints else: cjs = MaleHeadShapeControlJoints for jointName in cjs: for lodName in self.getLODNames(): if lodName == '2000': joint = self.controlJoint(None, 'legs', jointName, lodName) continue if lodName == '1000': continue continue if lodName == '500': continue continue def initHeadControlShapes(self): if self.style.getGender() == 'f': cjs = FemaleHeadShapeControlJoints matrixF = FemaleHeadShapeControlJointMatrix matrixI = FemaleHeadShapeInitialControlJointMatrix else: cjs = MaleHeadShapeControlJoints matrixF = MaleHeadShapeControlJointMatrix matrixI = MaleHeadShapeInitialControlJointMatrix if len(matrixF['initialized']) > 0: return None initializedMatrixI = len(matrixI['initialized']) initializedMatrixF = len(matrixF['initialized']) for jointName in cjs: transform = TransformState.makeMat(self.getJointTransform('legs', jointName, '2000')) pos = Vec3(transform.getPos()) hpr = Vec3(transform.getHpr()) scale = Vec3(transform.getScale()) matrixI[jointName].append(pos) matrixI[jointName].append(hpr) matrixI[jointName].append(scale) matrixI['initialized'].append('initialized') shapes = self.controlShapes names = self.sliderNames for i in xrange(0, len(shapes)): slider = shapes[names[i]] for k in xrange(0, len(slider[0])): slider[0][k][4] = slider[0][k][2] if len(slider) > 1: slider[1][k][4] = slider[1][k][2] continue for i in xrange(0, len(shapes)): slider = shapes[names[i]] for k in xrange(0, len(slider[0])): jointCtl = slider[0][k] jointName = jointCtl[0] matrixF[jointName].append(names[i]) pos = matrixI[jointName][0] hpr = matrixI[jointName][1] scl = matrixI[jointName][2] if jointCtl[1] < 3: posDelta = jointCtl[4] - pos[jointCtl[1]] jointCtl[4] = posDelta if len(slider) > 1: jointCtl = slider[1][k] jointCtl[4] = posDelta if len(slider) > 1: if jointCtl[1] > 2 and jointCtl[1] < 6: hprDelta = jointCtl[4] - hpr[jointCtl[1] - 3] jointCtl[4] = hprDelta if len(slider) > 1: jointCtl = slider[1][k] jointCtl[4] = hprDelta #if len(slider) > 1: #sclDelta = jointCtl[4] - scl[jointCtl[1] - 6] #jointCtl[4] = sclDelta #if len(slider) > 1: # jointCtl = slider[1][k] # jointCtl[4] = sclDelta matrixF['initialized'].append('initialized') def setHeadControlShapeValues_old(self): value = self.style.getHeadSize() mappedValue = 0.90000000000000002 + (1 + value) * 0.10000000000000001 self.extraNode.setScale(2 - mappedValue, mappedValue, 1) self.setControlValue(self.style.getHeadWidth(), 'headWidth') self.setControlValue(self.style.getHeadHeight(), 'headHeight') self.setControlValue(self.style.getHeadRoundness(), 'headRoundness') self.setControlValue(self.style.getJawWidth(), 'jawWidth') self.setControlValue(self.style.getJawAngle(), 'jawChinAngle') self.setControlValue(self.style.getJawChinSize(), 'jawChinSize') self.setControlValue(self.style.getJawLength(), 'jawLength') self.setControlValue(self.style.getMouthWidth(), 'mouthWidth') self.setControlValue(self.style.getMouthLipThickness(), 'mouthLipThickness') self.setControlValue(self.style.getCheekFat(), 'cheekFat') self.setControlValue(self.style.getBrowProtruding(), 'browProtruding') self.setControlValue(self.style.getEyeCorner(), 'eyeCorner') self.setControlValue(self.style.getEyeOpeningSize(), 'eyeOpeningSize') self.setControlValue(self.style.getEyeBulge(), 'eyeSpacing') self.setControlValue(self.style.getNoseBridgeWidth(), 'noseBridgeWidth') self.setControlValue(self.style.getNoseNostrilWidth(), 'noseNostrilWidth') self.setControlValue(self.style.getNoseLength(), 'noseLength') self.setControlValue(self.style.getNoseBump(), 'noseBump') self.setControlValue(self.style.getNoseNostrilHeight(), 'noseNostrilHeight') self.setControlValue(self.style.getNoseNostrilAngle(), 'noseNostrilAngle') self.setControlValue(self.style.getNoseBridgeBroke(), 'noseBridgeBroke') self.setControlValue(self.style.getNoseNostrilBroke(), 'noseNostrilBroke') self.setControlValue(self.style.getEarScale(), 'earScale') self.setControlValue(self.style.getEarFlapAngle(), 'earFlap') self.setControlValue(self.style.getEarPosition(), 'earPosition') def getGlobalScale(self): return self.scaleNode.getScale() def setGlobalScale(self, scale): self.scaleNode.setScale(scale) self.scaleNode.setZ(-(self.floorOffsetZ * (1 - scale))) def calcBodyScale(self): idx = 0 if self.gender == 'f': idx = 1 mappedValue = (0.80000000000000004 + (1 + self.style.getBodyHeight()) * 0.20000000000000001) * BodyScales[idx][self.style.getBodyShape()] return mappedValue def showZombie(self): self.model.irises.stash() self.model.faces[0].stash() self.model.faceZomb.unstash() self.generateSkinTexture() def showNormal(self): self.model.irises.unstash() self.model.faces[0].unstash() self.model.faceZomb.stash() self.generateSkinTexture() def takeAwayTexture(self, geoms, omitFace = False): emptyRenderState = RenderState.makeEmpty() eyeIrisColor = VBase4(0, 0, 0, 1) for i in range(0, geoms.getNumPaths()): element = geoms[i] if 'eye_iris' in element.getName(): element.setColorScale(eyeIrisColor) elif omitFace and 'master_face' in element.getName(): continue element.setTextureOff() geom = element.node() for j in range(0, geom.getNumGeoms()): geom.setGeomState(j, emptyRenderState) def optimizeMedLOD(self): medLOD = self.getLOD('1000') geoms = medLOD.findAllMatches('**/teeth*') geoms.stash() self.medSkinGone = False geoms = medLOD.find('**/body_forearm*') if geoms.isEmpty(): self.medSkinGone = True geoms = medLOD.findAllMatches('**/body_*') self.takeAwayTexture(geoms, True) geoms = medLOD.findAllMatches('**/hair_*') self.takeAwayTexture(geoms) if self.gender != 'f': geoms = medLOD.findAllMatches('**/beard_*') self.takeAwayTexture(geoms) geoms = medLOD.findAllMatches('**/mustache_*') self.takeAwayTexture(geoms) geoms = medLOD.findAllMatches('**/eye_*') self.takeAwayTexture(geoms) geoms = medLOD.findAllMatches('**/clothing_layer2_belt_*') self.takeAwayTexture(geoms) geoms = medLOD.findAllMatches('**/clothing_layer1_shoe_*') self.takeAwayTexture(geoms) def optimizeLowLOD(self): lowLOD = self.getLOD('500') geoms = lowLOD.findAllMatches('**/teeth*') geoms.stash() geoms = lowLOD.findAllMatches('**/+GeomNode') self.takeAwayTexture(geoms) def setHeadControlShapeValues(self): value = self.style.getHeadSize() mappedValue = 0.90000000000000002 + (1 + value) * 0.10000000000000001 self.extraNode.setScale(2 - mappedValue, mappedValue, 1) self.setControlValue_new(self.style.getHeadWidth(), 'headWidth') self.setControlValue_new(self.style.getHeadHeight(), 'headHeight') self.setControlValue_new(self.style.getHeadRoundness(), 'headRoundness') self.setControlValue_new(self.style.getJawWidth(), 'jawWidth') self.setControlValue_new(self.style.getJawAngle(), 'jawChinAngle') self.setControlValue_new(self.style.getJawChinSize(), 'jawChinSize') self.setControlValue_new(self.style.getJawLength(), 'jawLength') self.setControlValue_new(self.style.getMouthWidth(), 'mouthWidth') self.setControlValue_new(self.style.getMouthLipThickness(), 'mouthLipThickness') self.setControlValue_new(self.style.getCheekFat(), 'cheekFat') self.setControlValue_new(self.style.getBrowProtruding(), 'browProtruding') self.setControlValue_new(self.style.getEyeCorner(), 'eyeCorner') self.setControlValue_new(self.style.getEyeOpeningSize(), 'eyeOpeningSize') self.setControlValue_new(self.style.getEyeBulge(), 'eyeSpacing') self.setControlValue_new(self.style.getNoseBridgeWidth(), 'noseBridgeWidth') self.setControlValue_new(self.style.getNoseNostrilWidth(), 'noseNostrilWidth') self.setControlValue_new(self.style.getNoseLength(), 'noseLength') self.setControlValue_new(self.style.getNoseBump(), 'noseBump') self.setControlValue_new(self.style.getNoseNostrilHeight(), 'noseNostrilHeight') self.setControlValue_new(self.style.getNoseNostrilAngle(), 'noseNostrilAngle') self.setControlValue_new(self.style.getNoseBridgeBroke(), 'noseBridgeBroke') self.setControlValue_new(self.style.getNoseNostrilBroke(), 'noseNostrilBroke') self.setControlValue_new(self.style.getEarScale(), 'earScale') self.setControlValue_new(self.style.getEarFlapAngle(), 'earFlap') self.setControlValue_new(self.style.getEarPosition(), 'earPosition') self.postProcess_setHeadControlShapeValues() def setControlValue_new(self, r, name): ctl = self.controlShapes[name] zeroindex = ctl[0] sliders = zeroindex if r < 0.0: if len(ctl) > 1: sliders = ctl[1] for i in range(0, len(sliders)): zeroindex[i][5] = sliders[i][4] * r def postProcess_setHeadControlShapeValues(self): if self.style.getGender() == 'f': cjs = FemaleHeadShapeControlJoints matrixF = FemaleHeadShapeControlJointMatrix matrixI = FemaleHeadShapeInitialControlJointMatrix else: cjs = MaleHeadShapeControlJoints matrixF = MaleHeadShapeControlJointMatrix matrixI = MaleHeadShapeInitialControlJointMatrix posDelta = VBase3() hprDelta = VBase3() sclDelta = VBase3() fdict2 = { 0: posDelta.addX, 1: posDelta.addY, 2: posDelta.addZ, 3: hprDelta.addX, 4: hprDelta.addY, 5: hprDelta.addZ, 6: sclDelta.addX, 7: sclDelta.addY, 8: sclDelta.addZ } for jointName in cjs: posDelta.assign(matrixI[jointName][0]) hprDelta.assign(matrixI[jointName][1]) sclDelta.assign(matrixI[jointName][2]) for sliderIdx in xrange(0, len(matrixF[jointName])): sliderName = matrixF[jointName][sliderIdx] jointSet = self.controlShapes[sliderName][0] for sliderJoint in jointSet: if sliderJoint[0] == jointName: fdict2[sliderJoint[1]](sliderJoint[5]) continue self.find(jointName).setPosHprScale(posDelta, hprDelta, sclDelta)
class InventoryGui(DirectObject): directNotify = DirectNotify().newCategory('InventoryGui') HiddenPos = (0.2, 0, 0) VisiblePos = (-0.1725, 0, 0) SwitchTime = 0.3 AutoShowTime = 1.5 DELETED = False def __init__(self): DirectObject.__init__(self) self.backpack = base.localAvatar.backpack if not self.backpack: return self.backpack.loadoutGUI = self self.oneSlotPos = [(0, 0, 0)] self.twoSlotsPos = [(0, 0, 0.3), (0, 0, -0.2)] self.threeSlotsPos = [(0, 0, 0.5), (0, 0, 0), (0, 0, -0.5)] self.fourSlotPos = [(0, 0, 0.5), (0, 0, 0.15), (0, 0, -0.2), (0, 0, -0.55)] self.availableSlot = 0 self.slots = [] self.activeSlot = None self.defaultSlots = 3 self.prevSlot = None self.ammoLabel = None self.inventoryFrame = DirectFrame(parent=base.a2dRightCenter, pos=(-0.1725, 0, 0)) self.visibilityBtn = DirectButton(text='', relief=None, text_bg=(1, 1, 1, 0), parent=base.a2dRightCenter, pos=(-0.1725, 0, 0), frameSize=(-0.2, 0.2, -0.725, 0.7), clickSound=None, rolloverSound=None) self.visibilityBtn.bind(DGG.WITHIN, self.__handleVisEnter) self.visibilityBtn.bind(DGG.WITHOUT, self.__handleVisExit) self.visibilityBtn.setBin('background', 10) self.visibilityBtn = None self.visibilityBtnStatus = 0 self.switchSound = True self.switchSoundSfx = base.loadSfx( 'phase_3/audio/sfx/GUI_balloon_popup.ogg') self.visibilityFSM = ClassicFSM('InventoryGui-VisibilityFSM', [ State('off', self.enterOff, self.exitOff), State('hidden', self.enterHidden, self.exitHidden), State('hidden2visible', self.enterHidden2Visible, self.exitHidden2Visible), State('visible', self.enterVisible, self.exitVisible), State('visible2hidden', self.enterVisible2Hidden, self.exitVisible2Hidden) ], 'off', 'off') self.visibilityFSM.enterInitialState() self.visibilityFSM.request('hidden') return def enterOff(self): pass def exitOff(self): pass def enterHidden(self): self.inventoryFrame.setPos(InventoryGui.HiddenPos) self.inventoryFrame.hide() def exitHidden(self): pass def enterVisible(self, autoShow=False): self.inventoryFrame.setPos(InventoryGui.VisiblePos) self.inventoryFrame.show() if self.visibilityBtnStatus == 0: if autoShow is False: self.visibilityFSM.request('visible2hidden') def exitVisible(self): pass def enterHidden2Visible(self, autoShow=False): self.inventoryFrame.show() self.moveIval = LerpPosInterval(self.inventoryFrame, duration=InventoryGui.SwitchTime, pos=InventoryGui.VisiblePos, startPos=InventoryGui.HiddenPos) self.moveIval.setDoneEvent('hidden2visible') self.acceptOnce('hidden2visible', self.visibilityFSM.request, ['visible', [autoShow]]) self.moveIval.start() def exitHidden2Visible(self): self.ignore('hidden2visible') self.moveIval.finish() del self.moveIval def enterVisible2Hidden(self): self.moveIval = LerpPosInterval(self.inventoryFrame, duration=InventoryGui.SwitchTime, pos=InventoryGui.HiddenPos, startPos=InventoryGui.VisiblePos) self.moveIval.setDoneEvent('visible2hidden') self.acceptOnce('visible2hidden', self.visibilityFSM.request, ['hidden']) self.moveIval.start() def exitVisible2Hidden(self): self.ignore('visible2hidden') self.moveIval.finish() del self.moveIval def click_setWeapon(self, slot, cmd): self.setWeapon(slot, playSound=False) def setWeapon(self, slot, playSound=True, showUpIfHidden=False): if isinstance(slot, str): for iSlot in self.slots: if iSlot.getGag(): if iSlot.getGag().getID() == slot: slot = iSlot if self.activeSlot and slot != self.activeSlot: self.activeSlot.setOutlineImage('idle') self.prevSlot = self.activeSlot if slot.getGag() and self.backpack.getSupply(slot.getGag().getID( )) > 0 and not slot.getGag().getState() == GagState.RECHARGING: if self.activeSlot != slot: gagId = slot.getGag().getID() base.localAvatar.needsToSwitchToGag = gagId if base.localAvatar.gagsTimedOut == False: base.localAvatar.b_equip(gagId) base.localAvatar.enableGagKeys() slot.setOutlineImage('selected') self.activeSlot = slot else: if self.activeSlot == slot and slot.getGag().getState() in [ GagState.LOADED, GagState.RECHARGING ]: base.localAvatar.needsToSwitchToGag = 'unequip' if base.localAvatar.gagsTimedOut == False: base.localAvatar.b_unEquip() base.localAvatar.enableGagKeys() self.activeSlot = None self.update() if self.switchSound and playSound: base.playSfx(self.switchSoundSfx) if showUpIfHidden: base.taskMgr.remove('showUpIfHidden') self.__autoVisEnter() base.taskMgr.doMethodLater(InventoryGui.AutoShowTime, self.__autoVisExitTask, 'showUpIfHidden') return def __autoVisExitTask(self, task): if self.visibilityBtnStatus == 0: self.__handleVisExit(None, updateBtnStatus=False) return task.done def __autoVisEnter(self): self.__handleVisEnter(None, True, False) return def __handleVisEnter(self, foo, autoShow=False, updateBtnStatus=True): if updateBtnStatus: self.visibilityBtnStatus = 1 if self.visibilityFSM.getCurrentState().getName() == 'hidden': self.visibilityFSM.request('hidden2visible', [autoShow]) else: if self.visibilityFSM.getCurrentState().getName( ) == 'visible2hidden': self.visibilityFSM.request('visible') def __handleVisExit(self, foo, updateBtnStatus=True): if updateBtnStatus: self.visibilityBtnStatus = 0 base.taskMgr.remove('showUpIfHidden') if self.visibilityFSM.getCurrentState().getName() == 'visible': self.visibilityFSM.request('visible2hidden') def createGui(self): self.deleteGui() posGroup = self.threeSlotsPos if self.defaultSlots == 4: posGroup = self.fourSlotPos for slot in range(len(posGroup) + 1): if slot == 3: posGroup = self.fourSlotPos slotObj = Slot(self, slot + 1, posGroup[slot], self.inventoryFrame) self.slots.append(slotObj) if slot == 3: slotObj.hide() self.ammoLabel = DirectLabel(text='Ammo: 0', text_fg=(1, 1, 1, 1), relief=None, text_shadow=(0, 0, 0, 1), text_scale=0.08, pos=(0.2, 0, 0.35), parent=base.a2dBottomLeft) self.ammoLabel.hide() self.enableWeaponSwitch() self.resetScroll() self.update() return def deleteGui(self): self.disableWeaponSwitch() for slot in self.slots: slot.destroy() self.slots = [] if self.ammoLabel: self.ammoLabel.destroy() self.ammoLabel = None self.DELETED = True return def resetScroll(self): nextGag = 0 prevGag = -1 curGag = -1 if self.prevSlot: prevGag = self.slots.index(self.prevSlot) if self.activeSlot: curGag = self.slots.index(self.activeSlot) if curGag == len(self.slots) - 1: nextGag = 0 prevGag = curGag - 1 else: if curGag == 0: nextGag = 1 prevGag = len(self.slots) - 1 else: if curGag == -1: prevGag = len(self.slots) - 1 else: nextGag = curGag + 1 prevGag = curGag - 1 self.accept('wheel_down', self.setWeapon, extraArgs=[self.slots[nextGag], True, True]) self.accept('wheel_up', self.setWeapon, extraArgs=[self.slots[prevGag], True, True]) def update(self): if not self.backpack: return for element in [self.ammoLabel, self.inventoryFrame]: if not element: return updateSlots = list(self.slots) for slot in self.slots: gag = slot.getGag() if not gag: updateSlots.remove(slot) slot.hide() continue supply = self.backpack.getSupply(gag.getID()) index = self.slots.index(slot) if not gag and len(self.backpack.getGags()) - 1 >= index: gag = self.backpack.getGagByIndex(index) slot.setGag(gag) if self.backpack.getSupply(gag.getID( )) > 0 and not gag.getState() == GagState.RECHARGING: slot.setOutlineImage('idle') else: slot.setOutlineImage('no_ammo') elif slot == self.activeSlot: self.ammoLabel['text_fg'] = (1, 1, 1, 1) if supply > 0 and not gag.getState() == GagState.RECHARGING: slot.setOutlineImage('selected') else: if supply <= 0: self.ammoLabel['text_fg'] = (0.9, 0, 0, 1) slot.setOutlineImage('no_ammo') self.activeSlot = None self.ammoLabel.show() self.ammoLabel['text'] = 'Ammo: %s' % self.backpack.getSupply( slot.getGag().getID()) elif self.backpack.getSupply(slot.getGag().getID( )) > 0 and not gag.getState() == GagState.RECHARGING: slot.setOutlineImage('idle') else: slot.setOutlineImage('no_ammo') numSlots = len(updateSlots) posGroup = { 1: self.oneSlotPos, 2: self.twoSlotsPos, 3: self.threeSlotsPos, 4: self.fourSlotPos }.get(numSlots) for i in xrange(len(updateSlots)): updateSlots[i].setPos(posGroup[i]) updateSlots[i].show() if self.activeSlot == None: self.ammoLabel.hide() self.ammoLabel['text'] = 'Ammo: 0' self.resetScroll() return def setBackpack(self, backpack): self.backpack = backpack def updateLoadout(self): if self.backpack: loadout = self.backpack.getLoadout() if len(loadout) <= 3: self.reseatSlots() else: if len(loadout) == 4: self.reseatSlots(slots=4) for i in range(len(self.slots)): slot = self.slots[i] if i < len(loadout): slot.setGag(loadout[i]) else: slot.setGag(None) self.update() return def reseatSlots(self, slots=3): for slot in range(len(self.slots) - 1): if slots == 4: self.slots[slot].setPos(self.fourSlotPos[slot]) else: self.slots[slot].setPos(self.threeSlotsPos[slot]) def enableWeaponSwitch(self): for index in range(len(self.slots)): self.accept(str(index + 1), self.setWeapon, extraArgs=[self.slots[index], True, True]) def disableWeaponSwitch(self): for key in ['1', '2', '3', '4', 'wheel_down', 'wheel_up']: self.ignore(key) def getSlots(self): return self.slots def getActiveSlot(self): return self.activeSlot def isDeleted(self): return self.DELETED
class DistributedDisneyCharAI(DistributedAvatarAI, DistributedSmoothNodeAI): notify = directNotify.newCategory('DistributedDisneyCharAI') def __init__(self, air, charId): DistributedAvatarAI.__init__(self, air) DistributedSmoothNodeAI.__init__(self, air) self.fsm = ClassicFSM('DDCharAI', [State('off', self.enterOff, self.exitOff), State('neutral', self.enterNeutral, self.exitNeutral), State('walking', self.enterWalking, self.exitWalking)], 'off', 'off') self.fsm.enterInitialState() self.charId = charId self.avatars = [] self.inConvo = False self.chatsThisConvo = 0 self.toonOfInterest = 0 self.saidGoodbye = False self.currentPointLetter = None self.lastPointLetter = None self.talkEnabled = True def requestStateData(self): if self.charId == SAILOR_DONALD: return avId = self.air.getAvatarIdFromSender() if self.fsm.getCurrentState().getName() == 'neutral': self.sendUpdateToAvatarId(avId, 'doNeutral', [self.currentPointLetter]) elif self.fsm.getCurrentState().getName() == 'walking': self.sendUpdateToAvatarId(avId, 'doWalking', [self.currentPointLetter, self.lastPointLetter, self.walkingTimestamp]) def getCharId(self): return self.charId def chooseChat(self, chatType): if chatType == 'greet': sharedOrMine = random.choice([SHARED_GREETINGS, CHAR_GREETINGS]) elif chatType == 'comment': num = random.randint(1, 100) if num in SHARED_COMMENT_CHANCE: sharedOrMine = SHARED_COMMENTS elif num in UNIQUE_COMMENT_CHANCE: sharedOrMine = CHAR_COMMENTS elif chatType == 'bye': sharedOrMine = random.choice([SHARED_GOODBYES, CHAR_GOODBYES]) if sharedOrMine < CHAR_GREETINGS: # It's shared chatList = CHATTER[sharedOrMine] elif sharedOrMine >= CHAR_GREETINGS: # It's unique chatList = CHATTER[sharedOrMine][self.charId] chat = random.choice(chatList) index = chatList.index(chat) return [sharedOrMine, index] def enterOff(self): pass def exitOff(self): pass def enterNeutral(self, pickRandomPoint = False): if self.talkEnabled: taskMgr.doMethodLater(random.uniform(*CHECK_FOR_PEEPS_RANGE), self.__neutralTask, self.uniqueName('neutralTask')) if self.charId != SAILOR_DONALD: self.startLonelyTask() if pickRandomPoint: self.currentPointLetter = random.choice(WALK_POINTS[self.charId].keys()) self.sendUpdate('doNeutral', [self.currentPointLetter]) def startLonelyTask(self): self.lonelyThreshold = random.randint(*TIMES_LONELY_RANGE) self.timesLonely = 0 taskMgr.doMethodLater(random.uniform(*LONELY_TIME_RANGE), self.__lonelyTask, self.uniqueName('lonelyTask')) def __lonelyTask(self, task): # Nobody came over to talk to me. if self.isLonely() and not self.inConvo: self.timesLonely += 1 if self.timesLonely >= self.lonelyThreshold: # Let's walk somewhere else -- maybe we'll find people there. self.fsm.request('walking') return task.done task.delayTime = random.uniform(*TIMES_LONELY_RANGE) return task.again def __neutralTask(self, task): if self.saidGoodbye: # Alright, let's go walking. self.fsm.request('walking') return task.done # Wait for peoples to walk over to me! if self.wantsToChat() and not self.inConvo: # Aye! We got someone! taskMgr.remove(self.uniqueName('lonelyTask')) # Let's pick a random person out of my huge circle of friends to talk to. peep = random.choice(self.avatars) self.toonOfInterest = peep # Let's greet them! chatType, index = self.chooseChat('greet') self.chatsThisConvo = 1 # Alright, tell all of the DisneyChar clients to talk to this person! self.sendUpdate('talk2Toon', [chatType, index, peep]) # Don't mess with me, i'm in a conversation! self.inConvo = True task.delayTime = random.uniform(*TALK_AGAIN_RANGE) return task.again elif self.inConvo: # Seems like they're still interested in me. Let's keep talking. if not self.toonOfInterest in self.avatars: # Wait, no they're not. if self.wantsToChat(): # Luckily I have more friends to talk to! self.toonOfInterest = random.choice(self.avatars) elif self.isLonely(): # Wow, all my friends left me. self.startLonelyTask() self.inConvo = False task.delayTime = random.uniform(*CHECK_FOR_PEEPS_RANGE) return task.again if self.chatsThisConvo >= CHAT_THRESHOLD: # Ugh, i'm bored. Say goodbye and go for a walk. chatType, index = self.chooseChat('bye') self.sendUpdate('talk2Toon', [chatType, index, self.toonOfInterest]) self.saidGoodbye = True task.delayTime = 3.0 return task.again self.toonOfInterest = random.choice(self.avatars) # Say a random comment. chatType, index = self.chooseChat('comment') self.sendUpdate('talk2Toon', [chatType, index, self.toonOfInterest]) self.chatsThisConvo += 1 task.delayTime = random.uniform(*TALK_AGAIN_RANGE) return task.again task.delayTime = random.uniform(*CHECK_FOR_PEEPS_RANGE) return task.again def exitNeutral(self): taskMgr.remove(self.uniqueName('lonelyTask')) taskMgr.remove(self.uniqueName('neutralTask')) self.chatsThisConvo = 0 self.toonOfInterest = 0 self.saidGoodbye = False self.inConvo = False del self.lonelyThreshold del self.timesLonely def enterWalking(self): if self.currentPointLetter is None: # We haven't walked anywhere yet. # Choose any random point. point = random.choice(WALK_POINTS[self.charId].items()) pointLetter = point[0] timeUntilNeutral = 1.0 else: pointLetter = self.choosePoint() point = WALK_POINTS[self.charId][pointLetter][0] lastPoint = WALK_POINTS[self.charId][self.currentPointLetter][0] timeUntilNeutral = (point.getXy() - lastPoint.getXy()).length() * 0.2 if self.charId == PLUTO: timeUntilNeutral += PLUTO_STANDUP_TIME elif self.charId == SLEEP_DONALD: timeUntilNeutral += SLEEP_DONALD_N2W_TIME taskMgr.doMethodLater(timeUntilNeutral, self.__walkingTask, self.uniqueName('walkingTask')) self.walkingTimestamp = globalClockDelta.getRealNetworkTime() self.sendUpdate('doWalking', [pointLetter, self.currentPointLetter, self.walkingTimestamp]) self.lastPointLetter = self.currentPointLetter self.currentPointLetter = pointLetter def __walkingTask(self, task): self.fsm.request('neutral') return task.done def exitWalking(self): taskMgr.remove(self.uniqueName('walkingTask')) def choosePoint(self): accessiblePointIndices = WALK_POINTS[self.charId][self.currentPointLetter][1] return random.choice(accessiblePointIndices) def isLonely(self): return len(self.avatars) == 0 def wantsToChat(self): return (self.fsm.getCurrentState().getName() == 'neutral' and len(self.avatars) > 0) def avatarEnter(self): avId = self.air.getAvatarIdFromSender() if not avId in self.avatars: toon = self.air.doId2do.get(avId) if toon: self.acceptOnce(toon.getDeleteEvent(), self.avatarExit) self.acceptOnce(toon.getZoneChangeEvent(), self.avatarExit, [avId]) self.avatars.append(avId) def avatarExit(self, avId = None, foo = None, foo2 = None): print "avatar Exit" if avId == None: avId = self.air.getAvatarIdFromSender() if avId in self.avatars: toon = self.air.doId2do.get(avId) if toon: self.ignore(toon.getZoneChangeEvent()) self.ignore(toon.getDeleteEvent()) self.avatars.remove(avId) def announceGenerate(self): DistributedAvatarAI.announceGenerate(self) data = CHAR_DATA[self.charId] self.talkEnabled = data[4] self.fsm.request('neutral', [True])
class PlayGame(StateData): notify = directNotify.newCategory('PlayGame') Hood2HoodClass = {ZoneUtil.ToontownCentral: TTHood.TTHood, ZoneUtil.MinigameArea: MGHood.MGHood, ZoneUtil.TheBrrrgh: BRHood.BRHood, ZoneUtil.DonaldsDreamland: DLHood.DLHood, ZoneUtil.MinniesMelodyland: MLHood.MLHood, ZoneUtil.DaisyGardens: DGHood.DGHood, ZoneUtil.DonaldsDock: DDHood.DDHood, ZoneUtil.BattleTTC: CTCHood.CTCHood, ZoneUtil.CogTropolis: CTHood.CTHood} Hood2HoodState = {ZoneUtil.ToontownCentral: 'TTHood', ZoneUtil.MinigameArea: 'MGHood', ZoneUtil.TheBrrrgh: 'BRHood', ZoneUtil.DonaldsDreamland: 'DLHood', ZoneUtil.MinniesMelodyland: 'MLHood', ZoneUtil.DaisyGardens: 'DGHood', ZoneUtil.DonaldsDock: 'DDHood', ZoneUtil.BattleTTC: 'CTCHood', ZoneUtil.CogTropolis: 'CTHood'} def __init__(self, parentFSM, doneEvent): StateData.__init__(self, "playGameDone") self.doneEvent = doneEvent self.fsm = ClassicFSM('World', [State('off', self.enterOff, self.exitOff, ['quietZone']), State('quietZone', self.enterQuietZone, self.exitQuietZone, ['TTHood', 'BRHood', 'DLHood', 'MLHood', 'DGHood', 'DDHood', 'MGHood', 'CTCHood', 'CTHood']), State('TTHood', self.enterTTHood, self.exitTTHood, ['quietZone']), State('BRHood', self.enterBRHood, self.exitBRHood, ['quietZone']), State('DLHood', self.enterDLHood, self.exitDLHood, ['quietZone']), State('MLHood', self.enterMLHood, self.exitMLHood, ['quietZone']), State('DGHood', self.enterDGHood, self.exitDGHood, ['quietZone']), State('DDHood', self.enterDDHood, self.exitDDHood, ['quietZone']), State('MGHood', self.enterMGHood, self.exitMGHood, ['quietZone']), State('CTCHood', self.enterCTCHood, self.exitCTCHood, ['quietZone']), State('CTHood', self.enterCTHood, self.exitCTHood, ['quietZone'])], 'off', 'off') self.fsm.enterInitialState() self.parentFSM = parentFSM self.parentFSM.getStateNamed('playGame').addChild(self.fsm) self.hoodDoneEvent = 'hoodDone' self.hood = None self.quietZoneDoneEvent = uniqueName('quietZoneDone') self.quietZoneStateData = None self.place = None self.lastHood = None self.suitManager = None def enter(self, hoodId, zoneId, avId): StateData.enter(self) whereName = ZoneUtil.getWhereName(zoneId) loaderName = ZoneUtil.getLoaderName(zoneId) self.fsm.request('quietZone', [{'zoneId': zoneId, 'hoodId': hoodId, 'where': whereName, 'how': 'teleportIn', 'avId': avId, 'shardId': None, 'loader': loaderName}]) def exit(self): StateData.exit(self) def getCurrentWorldName(self): return self.fsm.getCurrentState().getName() def enterOff(self): pass def exitOff(self): pass def enterCTHood(self, requestStatus): self.accept(self.hoodDoneEvent, self.handleHoodDone) self.hood.enter(requestStatus) def exitCTHood(self): self.ignore(self.hoodDoneEvent) self.hood.exit() self.hood.unload() self.hood = None self.lastHood = ZoneUtil.CogTropolis def enterCTCHood(self, requestStatus): self.accept(self.hoodDoneEvent, self.handleHoodDone) self.hood.enter(requestStatus) def exitCTCHood(self): self.ignore(self.hoodDoneEvent) self.hood.exit() self.hood.unload() self.hood = None self.lastHood = ZoneUtil.ToontownCentral def enterDDHood(self, requestStatus): self.accept(self.hoodDoneEvent, self.handleHoodDone) self.hood.enter(requestStatus) def exitDDHood(self): self.ignore(self.hoodDoneEvent) self.hood.exit() self.hood.unload() self.hood = None self.lastHood = ZoneUtil.DonaldsDock def enterDGHood(self, requestStatus): self.accept(self.hoodDoneEvent, self.handleHoodDone) self.hood.enter(requestStatus) def exitDGHood(self): self.ignore(self.hoodDoneEvent) self.hood.exit() self.hood.unload() self.hood = None self.lastHood = ZoneUtil.DaisyGardens def enterMLHood(self, requestStatus): self.accept(self.hoodDoneEvent, self.handleHoodDone) self.hood.enter(requestStatus) def exitMLHood(self): self.ignore(self.hoodDoneEvent) self.hood.exit() self.hood.unload() self.hood = None self.lastHood = ZoneUtil.MinniesMelodyland def enterDLHood(self, requestStatus): self.accept(self.hoodDoneEvent, self.handleHoodDone) self.hood.enter(requestStatus) def exitDLHood(self): self.ignore(self.hoodDoneEvent) self.hood.exit() self.hood.unload() self.hood = None self.lastHood = ZoneUtil.DonaldsDreamland def enterBRHood(self, requestStatus): self.accept(self.hoodDoneEvent, self.handleHoodDone) self.hood.enter(requestStatus) def exitBRHood(self): self.ignore(self.hoodDoneEvent) self.hood.exit() self.hood.unload() self.hood = None self.lastHood = ZoneUtil.TheBrrrgh def enterTTHood(self, requestStatus): self.accept(self.hoodDoneEvent, self.handleHoodDone) self.hood.enter(requestStatus) def exitTTHood(self): self.ignore(self.hoodDoneEvent) self.hood.exit() self.hood.unload() self.hood = None self.lastHood = ZoneUtil.ToontownCentral def enterMGHood(self, requestStatus): self.accept(self.hoodDoneEvent, self.handleHoodDone) self.hood.enter(requestStatus) def exitMGHood(self): self.ignore(self.hoodDoneEvent) self.hood.exit() self.hood.unload() self.hood = None self.lastHood = ZoneUtil.MinigameArea def handleHoodDone(self): doneStatus = self.hood.getDoneStatus() if doneStatus['zoneId'] is None: self.doneStatus = doneStatus messenger.send(self.doneEvent) else: self.fsm.request('quietZone', [doneStatus]) def loadDNAStore(self): if hasattr(self, 'dnaStore'): self.dnaStore.reset_nodes() self.dnaStore.reset_hood_nodes() self.dnaStore.reset_place_nodes() self.dnaStore.reset_hood() self.dnaStore.reset_fonts() self.dnaStore.reset_DNA_vis_groups() self.dnaStore.reset_materials() self.dnaStore.reset_block_numbers() self.dnaStore.reset_block_zones() self.dnaStore.reset_suit_points() del self.dnaStore self.dnaStore = DNAStorage() loadDNAFile(self.dnaStore, 'phase_4/dna/storage.pdna') self.dnaStore.storeFont('humanist', CIGlobals.getToonFont()) self.dnaStore.storeFont('mickey', CIGlobals.getMickeyFont()) self.dnaStore.storeFont('suit', CIGlobals.getSuitFont()) loadDNAFile(self.dnaStore, 'phase_3.5/dna/storage_interior.pdna') def enterQuietZone(self, requestStatus): self.acceptOnce(self.quietZoneDoneEvent, self.handleQuietZoneDone, [requestStatus]) self.acceptOnce('enteredQuietZone', self.handleEnteredQuietZone, [requestStatus]) self.quietZoneStateData = QuietZoneState(self.quietZoneDoneEvent, 0) self.quietZoneStateData.load() self.quietZoneStateData.enter(requestStatus) def handleEnteredQuietZone(self, requestStatus): hoodId = requestStatus['hoodId'] if self.Hood2HoodClass.has_key(hoodId): hoodClass = self.Hood2HoodClass[hoodId] base.transitions.noTransitions() loader.beginBulkLoad('hood', hoodId, 100) self.loadDNAStore() self.hood = hoodClass(self.fsm, self.hoodDoneEvent, self.dnaStore, hoodId) self.hood.load() hoodState = self.Hood2HoodState[hoodId] self.fsm.request(hoodState, [requestStatus], exitCurrent = 0) self.quietZoneStateData.fsm.request('waitForSetZoneResponse') def handleQuietZoneDone(self, requestStatus): if self.hood: self.hood.enterTheLoader(requestStatus) self.hood.loader.enterThePlace(requestStatus) loader.endBulkLoad('hood') self.exitQuietZone() def exitQuietZone(self): if self.quietZoneStateData: self.ignore('enteredQuietZone') self.ignore(self.quietZoneDoneEvent) self.quietZoneStateData.exit() self.quietZoneStateData.unload() self.quietZoneStateData = None def setPlace(self, place): self.place = place def getPlace(self): return self.place
class CogBrain(DirectObject): PANIC_SPEED = 0.15 PANIC_DELAY = 0.5 RUNAWAY_SPEED = 0.1 RUNAWAY_SAFE_DISTANCE = 50 MAX_BOSS_HELPERS = 5 PANIC_HP_FACTOR = .222 ATTACK_DISTANCE = 40.0 MAX_ATTACKERS = 3 Difficulty2MaxAttackThrows = {} for level in range(1, 4 + 1): Difficulty2MaxAttackThrows[level] = 3 for level in range(5, 9 + 1): Difficulty2MaxAttackThrows[level] = 4 for level in range(9, 12 + 1): Difficulty2MaxAttackThrows[level] = 5 def __init__(self, suit): self.suit = suit self.panicHP = self.suit.getMaxHealth() * self.PANIC_HP_FACTOR self.fsm = ClassicFSM( 'CogBrain', [ State('off', self.enterOff, self.exitOff), State('neutral', self.enterNeutral, self.exitNeutral), State('followBoss', self.enterFollowBoss, self.exitFollowBoss), State('panic', self.enterPanic, self.exitPanic), State('runAway', self.enterRunAway, self.exitRunAway) ], 'off', 'off' ) self.fsm.enterInitialState() def start(self): taskMgr.add(self.__think, self.suit.uniqueName('think')) def end(self, andGoOff = 1): taskMgr.remove(self.suit.uniqueName('think')) if andGoOff: self.fsm.request('off') def __think(self, task = None): if task: task.delayTime = 1 # Let's do some thinking! if self.suit.getAttacking(): # Don't think when I attack. if task: return task.again else: return _help_priority = 0 _panic_priority = 0 _run_priority = 0 # PRIORITY SCALE: # 5 or > = Top Priority # 4 = Very Important # 3 = Quite Important # 2 = Not really important # 1 = Not important # First things first, is there a boss I can help? _helper_suits = 0 boss = None for av in self.suit.getManager().suits.values(): if av.doId != self.suit.doId: if av.head in ["vp"]: # Looks like there is! How many suits are already helping that boss? boss = av for suit in self.suit.getManager().suits.values(): if suit.doId != self.suit.doId: if suit.brain: if suit.brain.fsm.getCurrentState().getName() == "followBoss": # Alright, there's someone helping... _helper_suits += 1 if _helper_suits == self.MAX_BOSS_HELPERS - 1: _help_priority = 2 elif _helper_suits == self.MAX_BOSS_HELPERS - 2: _help_priority = 2.5 elif _helper_suits == self.MAX_BOSS_HELPERS - 3: _help_priority = 3.5 elif _helper_suits == self.MAX_BOSS_HELPERS - 4: _help_priority = 4 elif _helper_suits == self.MAX_BOSS_HELPERS - 5: _help_priority = 4.5 if boss == None or _helper_suits == self.MAX_BOSS_HELPERS: _help_priority = 0 if self.fsm.getCurrentState().getName() == "followBoss": if self.bossSpotKey != boss.boss.spot: self.fsm.request('followBoss', [boss]) return task.again # Let me check how many toons are near me... _toons_in_range = 0 # What would I call: in range? in_range = 15 # 15 units near me for av in self.suit.air.doId2do.values(): if av.__class__.__name__ == "DistributedToonAI": if av.zoneId == self.suit.zoneId: if self.suit.getDistance(av) <= in_range: # Yikes, someone's near me! _toons_in_range += 1 if self.fsm.getCurrentState().getName() == "followBoss": # I need to be tougher when defending my boss! _panic_priority = _toons_in_range / .85 else: _panic_priority = _toons_in_range / .75 if self.fsm.getCurrentState().getName() == "panic" and _toons_in_range > 0: # Wait, I'm panicking and toons are near me, RUN! _run_priority = 5 # Next, how are we doing? if self.suit.getHealth() <= self.panicHP: # Oh no, I'm close to dying! # This is pretty important! # Don't make me less panicky if I'm panicked # more about something else. if _panic_priority < 4: _panic_priority = 4 # Alright, let's decide what I should do. if _run_priority == 5: # 5 or 0 is the only priority running away can have. # If my running away priority is 5, I better do it! self.fsm.request('runAway', [av]) del _help_priority del _panic_priority del _run_priority del _helper_suits del boss del in_range del _toons_in_range try: del av except: pass if task: return task.done else: return elif _panic_priority <= 2 and _help_priority <= 2: # Eh, nothing is really that important. # Let me just choose to help the boss or chill out. state_num = random.randint(0, 2) if state_num == 0 or state_num == 1: new_state = "neutral" else: new_state = "followBoss" if boss == None or _help_priority == 0: # There's no boss, just chill. if self.fsm.getCurrentState().getName() != "neutral": self.fsm.request('neutral') else: new_state = "neutral" if self.fsm.getCurrentState().getName() != new_state: if self.fsm.getCurrentState().getName() == "followBoss": del _help_priority del _panic_priority del _run_priority del _helper_suits del boss del in_range del _toons_in_range try: del args except: pass try: del new_state except: pass try: del state_num except: pass try: del av except: pass if task: return task.again else: return args = [] if new_state == 'followBoss': args = [boss] self.fsm.request(new_state, args) elif _panic_priority > _help_priority: # Who cares about my boss! Panic!!! if self.fsm.getCurrentState().getName() != "panic": self.fsm.request('panic') del _help_priority del _panic_priority del _run_priority del _helper_suits del boss del in_range del _toons_in_range try: del args except: pass try: del new_state except: pass try: del state_num except: pass try: del av except: pass if task: return task.done else: return elif _panic_priority < _help_priority: # The boss needs help! Help him! if self.fsm.getCurrentState().getName() != "followBoss": self.fsm.request('followBoss', [boss]) elif _panic_priority == _help_priority: new_state = random.choice(['panic', 'followBoss']) if self.fsm.getCurrentState().getName() != new_state: args = [] if new_state == "followBoss": args = [boss] self.fsm.request(new_state, args) del _help_priority del _panic_priority del _run_priority del _helper_suits del boss del in_range del _toons_in_range try: del args except: pass try: del new_state except: pass try: del state_num except: pass try: del av except: pass if task: return task.again def enterOff(self): pass def exitOff(self): pass def enterNeutral(self): # Okay, just strollin' along, looking for some Toons to attack. self.suit.createPath(fromCurPos = True) self.numAttacksThrown = 0 if not self.suit.isBackup(): self.neutral_startLookingForToons() def neutral_startLookingForToons(self): taskMgr.add(self.__lookForToons, self.suit.uniqueName('lookForToon')) def neutral_stopLookingForToons(self): taskMgr.remove(self.suit.uniqueName('lookForToon')) def __lookForToons(self, task): # This is so we wont't have to do a bunch of calculations # when we won't even be attacking if we already are. if self.suit.isBackup() or not hasattr(self, 'numAttacksThrown'): return task.done if self.suit.getAttacking(): task.delayTime = 1.0 return task.again if self.numAttacksThrown >= self.Difficulty2MaxAttackThrows[self.suit.getLevel()]: self.numAttacksThrown = 0 if not self.suit.isWalking(): self.suit.createPath(path_key = self.suit.currentPath, fromCurPos = True) task.delayTime = 10 return task.again closestToonOrTurret = None obj2range = {} for obj in base.air.doId2do.values(): if obj.__class__.__name__ in ["DistributedToonAI", "DistributedPieTurretAI"]: if obj.zoneId == self.suit.zoneId: if not obj.isDead(): if obj.__class__.__name__ == "DistributedToonAI": # This helps with the stun lock problem. if obj.getNumAttackers() < self.MAX_ATTACKERS: dist = obj.getDistance(self.suit) if dist <= self.ATTACK_DISTANCE: obj2range[obj] = dist else: dist = obj.getDistance(self.suit) if dist <= self.ATTACK_DISTANCE: obj2range[obj] = dist ranges = [] for distance in obj2range.values(): ranges.append(distance) ranges.sort() for obj in obj2range.keys(): distance = obj2range[obj] if distance == ranges[0]: closestToonOrTurret = obj if closestToonOrTurret != None and not self.suit.getAttacking(): if self.suit.head != "vp": if self.suit.walkTrack: self.ignore(self.suit.walkTrack.getName()) self.suit.walkTrack.clearToInitial() self.suit.walkTrack = None self.suit.b_setSuitState(3, -1, -1) self.suit.b_setAnimState("neutral") self.end(0) self.suit.headsUp(closestToonOrTurret) self.suit.attackToon(closestToonOrTurret) self.suit.setAttacking(True) if closestToonOrTurret.__class__.__name__ == "DistributedToonAI": closestToonOrTurret.addNewAttacker(self.suit.doId) self.numAttacksThrown += 1 return task.done else: if self.numAttacksThrown > 0: if not self.suit.isWalking(): self.suit.createPath(path_key = self.suit.currentPath, fromCurPos = True) else: if not self.suit.isWalking(): self.suit.createPath(fromCurPos = True) self.numAttacksThrown = 0 task.delayTime = 3.5 return task.again def exitNeutral(self): self.neutral_stopLookingForToons() del self.numAttacksThrown def enterPanic(self): # Ahh, what's going on?! What do I do!? Help! taskMgr.add(self.__panic, self.suit.uniqueName('panic')) def __panic(self, task): self.suit.createPath(durationFactor = self.PANIC_SPEED, fromCurPos = True) if task.time == 2.0: self.__think(None) task.delayTime = self.PANIC_DELAY return task.again def exitPanic(self): taskMgr.remove(self.suit.uniqueName('panic')) def enterFollowBoss(self, boss): # I'll follow this boss, he can protect me, or maybe I can heal him up. self.boss = boss # Let me find out where this boss is... if boss.boss.spot == None: self.bossSpot = boss.getPos(render) else: self.bossSpot = CIGlobals.SuitSpawnPoints[self.suit.hood][boss.boss.spot] # Let me find my way there... if self.suit.currentPath == boss.boss.spot: # Wait a minute, we're already here! Walk straight to the boss. self.suit.createPath(path_key = boss.boss.spot, fromCurPos = True) else: self.suit.currentPathQueue = SuitPathFinder.find_path(self.suit.hood, self.suit.currentPath, boss.boss.spot) self.suit.currentPathQueue.remove(self.suit.currentPathQueue[0]) # Okay, let's start walking the path! self.suit.createPath(fromCurPos = True) # I want to keep a little bit of a distance from the boss... taskMgr.add(self.__followBoss, self.suit.uniqueName('followBoss')) self.bossSpotKey = boss.boss.spot def __followBoss(self, task): if not self.boss in self.suit.getManager().suits.values(): self.fsm.request('neutral') return task.done if self.suit.getDistance(self.boss) <= 4: # Okay, stop here! self.suit.b_setSuitState(3, -1, -1) if self.suit.walkTrack: self.suit.ignore(self.suit.walkTrack.getDoneEvent()) self.suit.walkTrack.pause() self.suit.walkTrack = None self.suit.b_setAnimState("neutral") # I want to protect this boss, so I need to stand in front of him. self.suit.setH(self.suit.getH() - 180) self.suit.d_setH(self.suit.getH()) return task.done return task.cont def exitFollowBoss(self): self.suit.resetPathQueue() taskMgr.remove(self.suit.uniqueName('followBoss')) del self.boss del self.bossSpot del self.bossSpotKey def enterRunAway(self, toon): # Get me away from this guy! self.toon = toon # Now, run! self.suit.createPath(durationFactor = self.RUNAWAY_SPEED, fromCurPos = True) # I'll only run until I'm a safe distance from them. taskMgr.add(self.__runAway, self.suit.uniqueName('runAway')) def __runAway(self, task): try: if self.suit.getDistance(self.toon) >= self.RUNAWAY_SAFE_DISTANCE: # Okay, we're safe! self.start() return task.done elif self.suit.walkTrack == None or self.suit.walkTrack.isStopped(): # He's still on us, keep running! self.suit.createPath(durationFactor = self.RUNAWAY_SPEED, fromCurPos = True) return task.cont except: self.fsm.request('neutral') return task.done def exitRunAway(self): taskMgr.remove(self.suit.uniqueName('runAway')) del self.toon
class Toon(Avatar.Avatar, ToonHead, ToonDNA.ToonDNA): notify = directNotify.newCategory("Toon") def __init__(self, cr, mat=0): self.cr = cr try: self.Toon_initialized return except: self.Toon_initialized = 1 Avatar.Avatar.__init__(self, mat) ToonDNA.ToonDNA.__init__(self) ToonHead.__init__(self, cr) self.collsSetup = False self.forwardSpeed = 0.0 self.rotateSpeed = 0.0 self.strafeSpeed = 0.0 self.avatarType = CIGlobals.Toon self.track = None self.standWalkRunReverse = None self.playingAnim = None self.playingRate = None self.tag = None self.money = 0 self.lookAtTrack = None self.portal1 = None self.portal2 = None self.spineA = NodePath() self.tokenIcon = None self.tokenIconIval = None self.fallSfx = base.audio3d.loadSfx( "phase_4/audio/sfx/MG_cannon_hit_dirt.ogg") base.audio3d.attachSoundToObject(self.fallSfx, self) self.eyes = loader.loadTexture("phase_3/maps/eyes.jpg", "phase_3/maps/eyes_a.rgb") self.myTaskId = random.uniform(0, 1231231232132131231232) self.closedEyes = loader.loadTexture("phase_3/maps/eyesClosed.jpg", "phase_3/maps/eyesClosed_a.rgb") self.soundChatBubble = loader.loadSfx( "phase_3/audio/sfx/GUI_balloon_popup.ogg") self.shadowCaster = None self.accessories = [] self.chatSoundDict = {} self.backpack = None self.forceRunSpeed = False self.animFSM = ClassicFSM('Toon', [ State('off', self.enterOff, self.exitOff), State('neutral', self.enterNeutral, self.exitNeutral), State('swim', self.enterSwim, self.exitSwim), State('walk', self.enterWalk, self.exitWalk), State('run', self.enterRun, self.exitRun), State('bow', self.enterBow, self.exitBow), State('openBook', self.enterOpenBook, self.exitOpenBook), State('readBook', self.enterReadBook, self.exitReadBook), State('closeBook', self.enterCloseBook, self.exitCloseBook), State('teleportOut', self.enterTeleportOut, self.exitTeleportOut), State('teleportIn', self.enterTeleportIn, self.exitTeleportIn), State('died', self.enterDied, self.exitDied), State('fallFWD', self.enterFallFWD, self.exitFallFWD), State('fallBCK', self.enterFallBCK, self.exitFallBCK), State('jump', self.enterJump, self.exitJump), State('leap', self.enterLeap, self.exitLeap), State('laugh', self.enterLaugh, self.exitLaugh), State('happy', self.enterHappyJump, self.exitHappyJump), State('shrug', self.enterShrug, self.exitShrug), State('hdance', self.enterHDance, self.exitHDance), State('wave', self.enterWave, self.exitWave), State('scientistEmcee', self.enterScientistEmcee, self.exitScientistEmcee), State('scientistWork', self.enterScientistWork, self.exitScientistWork), State('scientistGame', self.enterScientistGame, self.exitScientistGame), State('scientistJealous', self.enterScientistJealous, self.exitScientistJealous), State('cringe', self.enterCringe, self.exitCringe), State('conked', self.enterConked, self.exitConked), State('win', self.enterWin, self.exitWin), State('walkBack', self.enterWalkBack, self.exitWalkBack), State('deadNeutral', self.enterDeadNeutral, self.exitDeadNeutral), State('deadWalk', self.enterDeadWalk, self.exitDeadWalk), State('squish', self.enterSquish, self.exitSquish), State('Happy', self.enterHappy, self.exitHappy), State('Sad', self.enterSad, self.exitSad), State('Swim', self.enterSwim, self.exitSwim) ], 'off', 'off') animStateList = self.animFSM.getStates() self.animFSM.enterInitialState() if not hasattr(self, 'uniqueName'): self.uniqueName = types.MethodType(uniqueName, self) self.activities = { ACT_DIE: Die(self), ACT_VICTORY_DANCE: VictoryDance(self), ACT_TOON_BOW: Bow(self), ACT_JUMP: Jump(self) } def setActivity(self, act, timestamp=0): Avatar.Avatar.setActivity(self, act, timestamp) if act == ACT_NONE: self.animFSM.request("Happy") def getUpperBodySubpart(self): if self.getAnimal() == "dog": return ["torso-top", "head"] return ["torso-top"] def getLowerBodySubpart(self): return ["legs", "torso-pants"] def getRightHandNode(self): return self.find("**/def_joint_right_hold") def getLeftHandNode(self): return self.find("**/def_joint_left_hold") def getHeadNode(self): return self.getPart('head') def getEyePoint(self): # middle of the head return Point3(0, 0, self.getHeight() - (self.getHeadHeight() / 2.0)) def setForceRunSpeed(self, flag): self.forceRunSpeed = flag def resetTorsoRotation(self): if not self.isEmpty(): spine = self.find("**/def_spineB") if not spine.isEmpty(): spine.setH(0) spine.detachNode() self.getPart("legs").setH(0) self.releaseJoint("torso", "def_spineB") def showAvId(self): pass def showName(self): pass 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 enterHappy(self, ts=0, callback=None, extraArgs=[]): self.playingAnim = None self.standWalkRunReverse = (('neutral', 1.0), ('walk', 1.0), ('run', 1.0), ('walk', -1.0), ('strafe', 1.0), ('strafe', -1.0)) self.setSpeed(self.forwardSpeed, self.rotateSpeed) def exitHappy(self): self.standWalkRunReverse = None self.stop() def enterSad(self, ts=0, callback=None, extraArgs=[]): self.playingAnim = 'sad' self.standWalkRunReverse = (('dneutral', 1.0), ('dwalk', 1.2), ('dwalk', 1.2), ('dwalk', -1.0)) self.setSpeed(0, 0) def exitSad(self): self.standWalkRunReverse = None self.stop() #if hasattr(self, 'doId'): # if hasattr(base, 'localAvatar'): # if base.localAvatar.doId == self.doId: # self.controlManager.enableAvatarJump() def setSpeed(self, forwardSpeed, rotateSpeed, strafeSpeed=0.0): if self.forceRunSpeed: forwardSpeed = CIGlobals.RunCutOff self.forwardSpeed = forwardSpeed self.rotateSpeed = rotateSpeed self.strafeSpeed = strafeSpeed action = None if self.standWalkRunReverse != None: rotateCutOff = CIGlobals.RotateCutOff if not self.isLocalAvatar( ) else CIGlobals.WalkCutOff if strafeSpeed < CIGlobals.StrafeCutOff and strafeSpeed > -CIGlobals.StrafeCutOff: self.resetTorsoRotation() if forwardSpeed >= CIGlobals.RunCutOff: action = CIGlobals.RUN_INDEX elif forwardSpeed > CIGlobals.WalkCutOff: action = CIGlobals.WALK_INDEX elif forwardSpeed < -CIGlobals.WalkCutOff: action = CIGlobals.REVERSE_INDEX elif abs(rotateSpeed) > rotateCutOff: action = CIGlobals.WALK_INDEX elif abs(strafeSpeed) > CIGlobals.RunCutOff: action = CIGlobals.RUN_INDEX elif abs(strafeSpeed) > CIGlobals.WalkCutOff: action = CIGlobals.WALK_INDEX else: action = CIGlobals.STAND_INDEX if abs(strafeSpeed) > CIGlobals.WalkCutOff: spine = self.find("**/def_spineB") if spine.isEmpty(): spine = self.controlJoint(None, "torso", "def_spineB") movementVec = Vec3(strafeSpeed, forwardSpeed, 0) movementVec.normalize() movementAngle = rad2Deg( math.atan2(movementVec[1], movementVec[0])) - 90.0 if action == CIGlobals.REVERSE_INDEX: movementAngle -= 180 spine.setH(-movementAngle) self.getPart('legs').setH(movementAngle) anim, rate = self.standWalkRunReverse[action] if anim != self.playingAnim or rate != self.playingRate or self.forcedTorsoAnim != self.lastForcedTorsoAnim: self.playingAnim = anim self.playingRate = rate self.lastForcedTorsoAnim = self.forcedTorsoAnim if self.forcedTorsoAnim is None: self.loop(anim) else: # Whatever happens to the legs should also happen on the pants. self.loop(anim, partName='torso-pants') self.loop(anim, partName='legs') self.setPlayRate(rate, anim) return action def enterSquish(self, ts=0, callback=None, extraArgs=[]): self.playingAnim = 'squish' sound = loader.loadSfx('phase_9/audio/sfx/toon_decompress.ogg') lerpTime = 0.1 node = self.getGeomNode().getChild(0) origScale = node.getScale() if hasattr(self, 'uniqueName'): name = self.uniqueName('getSquished') else: name = 'getSquished' 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, 'happy', startTime=0.2), SoundInterval(sound)), name=name) self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getDoneEvent(), self.squishDone, [callback, extraArgs]) self.track.delayDelete = DelayDelete.DelayDelete(self, name) self.track.start(ts) def squishDone(self, callback=None, extraArgs=[]): self.__doCallback(callback, extraArgs) def exitSquish(self): if self.track: self.ignore(self.track.getName()) DelayDelete.cleanupDelayDeletes(self.track) self.track.finish() self.track = None self.playingAnim = 'neutral' def enterDeadNeutral(self, ts=0, callback=None, extraArgs=[]): self.loop('dneutral') def exitDeadNeutral(self): self.stop() def enterDeadWalk(self, ts=0, callback=None, extraArgs=[]): self.loop('dwalk') def exitDeadWalk(self): self.stop() def setBackpack(self, pack): self.backpack = pack def getGhost(self): return 0 def updateChatSoundDict(self): self.chatSoundDict['exclaim'] = base.audio3d.loadSfx( self.getToonAnimalNoise('exclaim')) self.chatSoundDict['question'] = base.audio3d.loadSfx( self.getToonAnimalNoise('question')) self.chatSoundDict['short'] = base.audio3d.loadSfx( self.getToonAnimalNoise('short')) self.chatSoundDict['medium'] = base.audio3d.loadSfx( self.getToonAnimalNoise('med')) self.chatSoundDict['long'] = base.audio3d.loadSfx( self.getToonAnimalNoise('long')) self.chatSoundDict['howl'] = base.audio3d.loadSfx( self.getToonAnimalNoise('howl')) base.audio3d.attachSoundToObject(self.chatSoundDict['exclaim'], self.getPart('head')) base.audio3d.attachSoundToObject(self.chatSoundDict['question'], self.getPart('head')) base.audio3d.attachSoundToObject(self.chatSoundDict['short'], self.getPart('head')) base.audio3d.attachSoundToObject(self.chatSoundDict['medium'], self.getPart('head')) base.audio3d.attachSoundToObject(self.chatSoundDict['long'], self.getPart('head')) base.audio3d.attachSoundToObject(self.chatSoundDict['howl'], self.getPart('head')) def __actAsGone(self): if self.nametag3d: self.nametag3d.hide() if self.getShadow(): self.getShadow().hide() if self.tokenIcon: self.tokenIcon.hide() #self.stashBodyCollisions() def __restoreHide(self): if self.tokenIcon: self.tokenIcon.show() if self.getShadow(): self.getShadow().show() if self.nametag3d: self.nametag3d.show() if self.getGeomNode(): self.getGeomNode().setTransparency(False) self.getGeomNode().setAlphaScale(1.0) self.getGeomNode().show() #self.unstashBodyCollisions() def handleGhost(self, flag): alpha = 1.0 if not flag else 0.25 local = self == base.localAvatar if flag: if self.getAccessLevel() >= base.localAvatar.getAccessLevel(): # Other staff members at this access level or higher should # be able to see this avatar still. alpha = 0.25 #self.stashBodyCollisions() elif not local: self.getGeomNode().setTransparency(True) self.getGeomNode().setColorScale(1.0, 1.0, 1.0, 0.0) self.__actAsGone() else: self.__restoreHide() if local: self.getGeomNode().setTransparency(flag) self.getGeomNode().setColorScale(1.0, 1.0, 1.0, alpha) 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.track != None: self.track.finish() DelayDelete.cleanupDelayDeletes(self.track) self.track = None return def disable(self): try: self.Toon_disabled except: self.Toon_disabled = 1 self.ignoreAll() self.backpack = None self.collsSetup = False self.stopAnimations() self.removeAdminToken() ToonHead.delete(self) self.deleteCurrentToon() self.chatSoundDict = {} Avatar.Avatar.disable(self) def delete(self): try: self.Toon_deleted except: self.Toon_deleted = 1 del self.animFSM self.forwardSpeed = None self.chatSoundDict = None self.rotateSpeed = None self.avatarType = None self.track = None self.standWalkRunReverse = None self.currentAnim = None self.toon_head = None self.forcedTorsoAnim = None self.lastForcedTorsoAnim = None self.toon_torso = None self.toon_legs = None self.gender = None self.headtype = None self.head = None self.legtype = None self.torsotype = None self.hr = None self.hg = None self.hb = None self.tr = None self.tg = None self.tb = None self.lr = None self.lg = None self.lb = None self.shir = None self.shig = None self.shib = None self.shor = None self.shog = None self.shob = None self.shirt = None self.sleeve = None self.short = None self.tag = None self.money = None self.lookAtTrack = None self.portal1 = None self.portal2 = None self.backpack = None self.fallSfx = None self.eyes = None self.myTaskId = None self.closedEyes = None self.soundChatBubble = None self.lastAction = None self.lastState = None self.playingAnim = None self.playingRate = None self.accessories = None Avatar.Avatar.delete(self) return def initCollisions(self): self.collNodePath.setCollideMask(BitMask32(0)) self.collNodePath.node().setFromCollideMask(CIGlobals.WallBitmask) pusher = CollisionHandlerPusher() pusher.setInPattern("%in") pusher.addCollider(self.collNodePath, self) base.cTrav.addCollider(self.collNodePath, pusher) def deleteCurrentToon(self): if self.shadowCaster: self.shadowCaster.clear() self.shadowCaster = None for accessory in self.accessories: accessory.removeNode() self.accessories = [] self.pupils = [] if 'head' in self._Actor__commonBundleHandles: del self._Actor__commonBundleHandles['head'] if 'torso' in self._Actor__commonBundleHandles: del self._Actor__commonBundleHandles['torso'] if 'legs' in self._Actor__commonBundleHandles: del self._Actor__commonBundleHandles['legs'] self.deleteShadow() self.removePart('head') self.removePart('torso') self.removePart('legs') self.clearPythonData() self.flush() def setAdminToken(self, tokenInstance): if tokenInstance: matPath = tokenInstance.getMaterialPath() self.tokenIcon = loader.loadModel( "phase_3/models/props/staffIcon.bam") self.tokenIcon.reparentTo(self) self.tokenIcon.setScale(0.75) self.tokenIcon.setShaderAuto() # Let's update the material. self.tokenIcon.setBSPMaterial(matPath, 1) # Let's position the icon above the nametag. x, y, z = self.nametag3d.getPos() self.tokenIcon.setPos(Vec3(x, y, z + self.tokenIcon.getSz())) r, g, b, _ = tokenInstance.getColor() # Let's add the glow. glow = loader.loadModel( 'phase_4/models/minigames/particleGlow.bam') glow.reparentTo(self.tokenIcon) glow.setScale(2.50) glow.setColorScale((r, g, b, 0.50), 1) glow.setBSPMaterial('phase_4/maps/particleGlow.mat', 1) glow.setDepthWrite(False, 1) glow.setShaderAuto() glow.setTwoSided(1) self.tokenIconIval = Sequence( LerpHprInterval(self.tokenIcon, duration=3.0, hpr=Vec3(360, 0, 0), startHpr=Vec3(0, 0, 0))) self.tokenIconIval.loop() else: self.removeAdminToken() def removeAdminToken(self): if self.tokenIcon != None and self.tokenIconIval != None: self.tokenIconIval.finish() self.tokenIcon.removeNode() self.tokenIconIval = None self.tokenIcon = None def playChatSfx(self, chatString): if not self.getGhost() or self.doId == base.localAvatar.doId: if "ooo" in chatString.lower(): sfx = self.chatSoundDict['howl'] elif "!" in chatString.lower(): sfx = self.chatSoundDict['exclaim'] elif "?" in chatString.lower(): sfx = self.chatSoundDict['question'] elif len(chatString) <= 9: sfx = self.chatSoundDict['short'] elif 10 <= len(chatString) <= 19: sfx = self.chatSoundDict['medium'] elif len(chatString) >= 20: sfx = self.chatSoundDict['long'] base.playSfx(sfx, node=self) def chatStompComplete(self, chatString): if not self.thoughtInProg and CIGlobals.getSettingsMgr().getSetting( "chs").getValue(): self.playChatSfx(chatString) def setName(self, nameString): Avatar.Avatar.setName(self, nameString) def setDNAStrand(self, dnaStrand, makeTag=1): ToonDNA.ToonDNA.setDNAStrand(self, dnaStrand) self.deleteCurrentToon() self.generateToon(makeTag) def generateMask(self): # No accessories yet. if self.shirt == self.maleTopDNA2maleTop['135'][ 0] or self.shirt == self.maleTopDNA2maleTop['136'][0]: # This toon is wearing the tsa suit, give them some sweet shades. name = 'tsaGlasses' glasses = loader.loadModel( AccessoryGlobals.AccessoryName2Model[name]) glassesNode = self.getPart('head').attachNewNode('glassesNode') glasses.reparentTo(glassesNode) data = AccessoryGlobals.MaskTransExtended[name].get(self.animal) if not data: data = AccessoryGlobals.MaskTrans.get(self.animal) posHprScale = AccessoryGlobals.MaskTrans[self.animal][ self.headLength] else: posHprScale = AccessoryGlobals.MaskTransExtended[name][ self.animal].get(self.headLength) if not posHprScale: posHprScale = AccessoryGlobals.MaskTrans[self.animal][ self.headLength] glasses.setPos(posHprScale[0]) glasses.setHpr(posHprScale[1]) glasses.setScale(posHprScale[2]) self.accessories.append(glassesNode) def generateToon(self, makeTag=1): self.generateLegs() self.generateTorso() self.generateHead() self.setToonColor() self.setClothes() self.setGloves() self.parentToonParts() self.rescaleToon() self.generateMask() # Make torso subparts so we can play a run animation on the pants but another animation on the spine and arms. if self.gender == 'boy': self.makeSubpart("torso-pants", [ "def_left_pant_bottom", "def_left_pant_top", "def_right_pant_bottom", "def_right_pant_top" ], parent="torso") elif self.gender == 'girl': if self.torso == 'dgs_skirt': self.makeSubpart("torso-pants", [ "def_left_skirt_backA", "def_left_skirt_frontA", "def_left_skirt_topA", "def_right_skirt_backA", "def_right_skirt_frontA", "def_right_skirt_topA" ], parent="torso") elif self.torso == 'dgl_skirt': self.makeSubpart("torso-pants", [ "def_left_skirt_bottomA", "def_left_skirt_topA", "def_right_hip" ], parent="torso") else: self.makeSubpart("torso-pants", [ "def_left_skirt_bottomA", "def_left_skirt_topA", "def_right_skirt_bottomA", "def_right_skirt_topA" ], parent="torso") self.makeSubpart("torso-top", ["def_spineB"], parent="torso") Avatar.Avatar.initShadow(self) self.updateChatSoundDict() self.setBlend(frameBlend=True) bodyMat = CIGlobals.getCharacterMaterial(shininess=5, specular=(0.5, 0.5, 0.5, 1)) self.setMaterial(bodyMat, 1) if not hasattr(base, 'localAvatar') or base.localAvatar != self: self.setupPhysics(1.0, self.getHeight()) # We can safely optimize the scene graph and combine nodes since we're done manipulating # the separate pieces. After this point, the separate pieces of the toon are no # longer manipulatable, such as arms, sleeves, shirt, etc. If this needs to be done, # the toon will have to be regenerated. # Don't do it in Make-A-Toon though, as we have to be constantly modifying the pieces. if not self.mat: self.optimize() if makeTag: self.setupNameTag() if self.cr.isShowingPlayerIds: self.showAvId() self.loop('neutral') def optimize(self): self.getPart('legs').flattenStrong() self.postFlatten() def attachTNT(self): self.pies.attachTNT() self.holdTNTAnim() def detachTNT(self): self.pies.detachTNT() self.animFSM.request(self.animFSM.getCurrentState().getName()) def holdTNTAnim(self): self.pose("toss", 22, partName="torso") def parentToonParts(self): self.attach('head', 'torso', 'def_head') self.attach('torso', 'legs', 'joint_hips') def unparentToonParts(self): self.getPart('head').reparentTo(self.getGeomNode()) self.getPart('torso').reparentTo(self.getGeomNode()) self.getPart('legs').reparentTo(self.getGeomNode()) def getHeadHeight(self): animal = self.getAnimal() headScale = ToonGlobals.HeadScales[animal][2] headHeight = ToonGlobals.HeadHeightDict[self.head] * headScale return headHeight def rescaleToon(self): if not self.getHead(): return animal = self.getAnimal() bodyScale = ToonGlobals.BodyScales[animal] headScale = ToonGlobals.HeadScales[animal][2] shoulderHeight = ToonGlobals.LegHeightDict[ self.getLegs()] * bodyScale + ToonGlobals.TorsoHeightDict[ self.getTorso()] * bodyScale height = shoulderHeight + ToonGlobals.HeadHeightDict[ self.getHead()] * headScale bodyScale = ToonGlobals.BodyScales[animal] self.setAvatarScale(bodyScale) self.getPart('head').setScale(headScale) self.setHeight(height) def setGloves(self): color = self.getGloveColor() gloves = self.find('**/hands') gloves.setColor(color) def setClothes(self): shirt, shirtcolor = self.getShirtStyle() short, shortcolor = self.getShortStyle() sleeve, sleevecolor = self.getSleeveStyle() torsot = self.findAllMatches('**/torso-top') torsob = self.findAllMatches('**/torso-bot') sleeves = self.findAllMatches('**/sleeves') torsot.setBSPMaterial(shirt, 1) torsob.setBSPMaterial(short, 1) sleeves.setBSPMaterial(sleeve, 1) torsot.setColor(shirtcolor) sleeves.setColor(sleevecolor) torsob.setColor(shortcolor) def generateLegs(self): ToonGlobals.generateBodyPart(self, 'legs', self.getLegs(), 3, 'shorts') self.find('**/boots_long').stash() self.find('**/boots_short').stash() self.find('**/shoes').stash() def generateTorso(self): ToonGlobals.generateBodyPart(self, 'torso', self.getTorso(), 3, '') def generateHead(self, pat=0): gender = self.getGender() head = self.getAnimal() headtype = self.getHead() ToonHead.generateHead(self, gender, head, headtype) def setToonColor(self): self.setHeadColor() self.setTorsoColor() self.setLegColor() def setLegColor(self): legcolor = self.getLegColor() self.findAllMatches('**/legs').setColor(legcolor) self.findAllMatches('**/feet').setColor(legcolor) def setTorsoColor(self): torsocolor = self.getTorsoColor() self.findAllMatches('**/arms').setColor(torsocolor) self.findAllMatches('**/neck').setColor(torsocolor) self.findAllMatches('**/hands').setColor(1, 1, 1, 1) def enterOff(self, ts=0, callback=None, extraArgs=[]): self.currentAnim = None return def exitOff(self): pass def enterWin(self, ts=0, callback=None, extraArgs=[]): self.playingAnim = 'win' self.sfx = base.audio3d.loadSfx("phase_3.5/audio/sfx/ENC_Win.ogg") self.sfx.setLoop(True) base.audio3d.attachSoundToObject(self.sfx, self) base.playSfx(self.sfx, node=self, looping=1) self.loop("win") def exitWin(self): self.stop() self.sfx.stop() del self.sfx self.playingAnim = 'neutral' def enterShrug(self, ts=0, callback=None, extraArgs=[]): self.play("shrug") def exitShrug(self): self.exitGeneral() def enterHDance(self, ts=0, callback=None, extraArgs=[]): self.play("hdance") def exitHDance(self): self.exitGeneral() def enterScientistWork(self, ts=0, callback=None, extraArgs=[]): self.loop("scwork") def exitScientistWork(self): self.exitGeneral() def enterScientistEmcee(self, ts=0, callback=None, extraArgs=[]): self.loop("scemcee") def exitScientistEmcee(self): self.exitGeneral() def enterScientistGame(self, ts=0, callback=None, extraArgs=[]): self.loop("scgame") def exitScientistGame(self): self.exitGeneral() def enterScientistJealous(self, ts=0, callback=None, extraArgs=[]): self.loop("scjealous") def exitScientistJealous(self): self.exitGeneral() def enterWave(self, ts=0, callback=None, extraArgs=[]): self.play("wave") def exitWave(self): self.exitGeneral() def enterLaugh(self, ts=0, callback=None, extraArgs=[]): self.setPlayRate(5.0, "neutral") self.loop("neutral") def exitLaugh(self): self.setPlayRate(1.0, "neutral") self.stop() def enterNeutral(self, ts=0, callback=None, extraArgs=[]): if self.forcedTorsoAnim != None: self.loop(self.forcedTorsoAnim, partName='torso') self.loop("neutral", partName="legs") return self.loop("neutral") self.playingAnim = 'neutral' def exitNeutral(self): self.exitGeneral() self.playingAnim = 'neutral' def exitGeneral(self): self.stop() def enterRun(self, ts=0, callback=None, extraArgs=[]): if self.forcedTorsoAnim != None: self.loop(self.forcedTorsoAnim, partName='torso') self.loop('run', partName='legs') return self.loop("run") def exitRun(self): self.exitGeneral() def enterWalk(self, ts=0, callback=None, extraArgs=[]): if self.forcedTorsoAnim != None: self.loop(self.forcedTorsoAnim, partName='torso') self.loop('walk', partName='legs') return self.loop('walk') def exitWalk(self): self.exitGeneral() def enterWalkBack(self, ts=0, callback=None, extraArgs=[]): self.setPlayRate(-1.0, "walk") self.enterWalk() def exitWalkBack(self): self.exitWalk() self.setPlayRate(1.0, "walk") def enterOpenBook(self, ts=0, callback=None, extraArgs=[]): self.playingAnim = 'book' self.book1 = Actor("phase_3.5/models/props/book-mod.bam", {"chan": "phase_3.5/models/props/book-chan.bam"}) self.book1.reparentTo( self.getPart('torso').find('**/def_joint_right_hold')) self.track = ActorInterval(self, "book", startFrame=CIGlobals.OpenBookFromFrame, endFrame=CIGlobals.OpenBookToFrame, name=self.uniqueName('enterOpenBook')) self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getDoneEvent(), self.__doCallback, [callback, extraArgs]) self.track.start(ts) self.book1.play("chan", fromFrame=CIGlobals.OpenBookFromFrame, toFrame=CIGlobals.OpenBookToFrame) def exitOpenBook(self): if self.track: self.ignore(self.track.getDoneEvent()) self.track.finish() self.track = None if self.book1: self.book1.cleanup() self.book1 = None self.playingAnim = 'neutral' def enterReadBook(self, ts=0, callback=None, extraArgs=[]): self.playingAnim = 'book' self.book2 = Actor("phase_3.5/models/props/book-mod.bam", {"chan": "phase_3.5/models/props/book-chan.bam"}) self.book2.reparentTo( self.getPart('torso').find('**/def_joint_right_hold')) self.pingpong("book", fromFrame=CIGlobals.ReadBookFromFrame, toFrame=CIGlobals.ReadBookToFrame) self.book2.pingpong("chan", fromFrame=CIGlobals.ReadBookFromFrame, toFrame=CIGlobals.ReadBookToFrame) def exitReadBook(self): if self.book2: self.book2.cleanup() self.book2 = None self.playingAnim = 'neutral' def enterCloseBook(self, ts=0, callback=None, extraArgs=[]): self.playingAnim = 'book' self.book3 = Actor("phase_3.5/models/props/book-mod.bam", {"chan": "phase_3.5/models/props/book-chan.bam"}) self.book3.reparentTo( self.getPart('torso').find('**/def_joint_right_hold')) self.track = ActorInterval(self, "book", startFrame=CIGlobals.CloseBookFromFrame, endFrame=CIGlobals.CloseBookToFrame, name=self.uniqueName('enterCloseBook')) self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getDoneEvent(), self.__doCallback, [callback, extraArgs]) self.track.start(ts) self.book3.play("chan", fromFrame=CIGlobals.CloseBookFromFrame, toFrame=CIGlobals.CloseBookToFrame) self.lerpLookAt(self.getPart('head'), (0, 0, 0)) def exitCloseBook(self): if self.track: self.ignore(self.track.getDoneEvent()) self.track.finish() self.track = None if self.book3: self.book3.cleanup() self.book3 = None self.playingAnim = 'neutral' def enterTeleportOut(self, ts=0, callback=None, extraArgs=[]): self.notify.info( str(self.doId) + "-" + str(self.zoneId) + ": enterTeleportOut") self.playingAnim = 'tele' self.portal1 = Actor( "phase_3.5/models/props/portal-mod.bam", {"chan": "phase_3.5/models/props/portal-chan.bam"}) self.portal1.play("chan") self.portal1.reparentTo( self.getPart('legs').find('**/def_joint_right_hold')) self.play("tele") if hasattr(self, 'uniqueName'): name = self.uniqueName('enterTeleportOut') else: name = 'enterTeleportOut' self.track = Sequence(Wait(0.4), Func(self.teleportOutSfx), Wait(1.3), Func(self.throwPortal), Wait(1.1), Func(self.__actAsGone), Wait(1.5), name=name) self.track.delayDelete = DelayDelete.DelayDelete(self, name) self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getName(), self.teleportOutDone, [callback, extraArgs]) self.track.start(ts) def doPortalBins(self, portal): portal.setBin('portal', 19) portal.setDepthWrite(0) portal.setDepthTest(0) def teleportOutDone(self, callback, requestStatus): self.notify.info( str(self.doId) + "-" + str(self.zoneId) + ": teleportOutDone") self.__doCallback(callback, requestStatus) self.exitTeleportOut() def teleportOutSfx(self): self.outSfx = base.audio3d.loadSfx( "phase_3.5/audio/sfx/AV_teleport.ogg") base.audio3d.attachSoundToObject(self.outSfx, self.portal1) base.playSfx(self.outSfx, node=self) def throwPortal(self): self.doPortalBins(self.portal1) self.portal1.reparentTo(self.getPart('legs').find('**/joint_nameTag')) self.portal1.setScale(CIGlobals.PortalScale) self.portal1.setY(6.5) self.portal1.setH(180) def exitTeleportOut(self): self.notify.info( str(self.doId) + "-" + str(self.zoneId) + ": exitTeleportOut") if self.track != None: self.ignore(self.track.getName()) self.track.finish() DelayDelete.cleanupDelayDeletes(self.track) self.track = None if self.portal1: self.portal1.cleanup() self.portal1 = None if hasattr(self, 'shadow') and self.shadow is not None: self.shadow.show() self.__restoreHide() self.playingAnim = 'neutral' def getTeleportInTrack(self, portal): self.doPortalBins(portal) holeTrack = Sequence() holeTrack.append(Func(portal.reparentTo, self)) pos = Point3(0, -2.4, 0) holeTrack.append(Func(portal.setPos, pos)) holeTrack.append( ActorInterval(portal, 'chan', startTime=3.4, endTime=3.1)) holeTrack.append(Wait(0.6)) holeTrack.append( ActorInterval(portal, 'chan', startTime=3.1, endTime=3.4)) def restorePortal(portal): portal.setPos(0, 0, 0) portal.detachNode() portal.clearBin() portal.clearDepthTest() portal.clearDepthWrite() holeTrack.append(Func(restorePortal, portal)) toonTrack = Sequence(Wait(0.3), Func(self.__restoreHide), ActorInterval(self, 'happy', startTime=0.45)) if hasattr(self, 'uniqueName'): trackName = self.uniqueName('teleportIn') else: trackName = 'teleportIn' return Parallel(toonTrack, holeTrack, name=trackName) def enterTeleportIn(self, ts=0, callback=None, extraArgs=[]): self.playingAnim = 'happy' self.portal2 = Actor( "phase_3.5/models/props/portal-mod.bam", {"chan": "phase_3.5/models/props/portal-chan.bam"}) self.show() self.getGeomNode().hide() self.nametag3d.hide() self.track = self.getTeleportInTrack(self.portal2) self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getName(), self.teleportInDone, [callback, extraArgs]) if hasattr(self, 'acquireDelayDelete'): self.track.delayDelete = DelayDelete.DelayDelete( self, self.track.getName()) self.track.start(ts) def teleportInDone(self, callback, extraArgs): self.exitTeleportIn() self.__doCallback(callback, extraArgs) def exitTeleportIn(self): if self.track != None: self.ignore(self.track.getName()) self.track.finish() DelayDelete.cleanupDelayDeletes(self.track) self.track = None if self.portal2: self.portal2.cleanup() self.portal2 = None if self.nametag3d: self.nametag3d.show() self.playingAnim = 'neutral' def enterFallFWD(self, ts=0, callback=None, extraArgs=[]): self.playingAnim = 'fallf' self.play("fallf") Sequence(Wait(0.5), SoundInterval(self.fallSfx, node=self)).start() def exitFallFWD(self): self.exitGeneral() self.playingAnim = 'neutral' def enterFallBCK(self, ts=0, callback=None, extraArgs=[]): self.playingAnim = 'fallb' self.play("fallb") Sequence(Wait(0.5), SoundInterval(self.fallSfx, node=self)).start() def exitFallBCK(self): self.playingAnim = 'neutral' self.exitGeneral() def enterHappyJump(self, ts=0, callback=None, extraArgs=[]): self.playingAnim = 'happy' self.play("happy") def exitHappyJump(self): self.exitGeneral() self.playingAnim = 'neutral' def enterSwim(self, ts=0, callback=None, extraArgs=[]): self.playingAnim = 'swim' self.loop("swim") self.resetTorsoRotation() toon = self.getGeomNode() toon.setP(-89.0) if self.shadow: self.shadow.hide() self.swimBobTrack = Sequence( LerpPosInterval(toon, duration=1, pos=(0, -3, 3), startPos=(0, -3, 4), blendType='easeInOut'), LerpPosInterval(toon, duration=1, pos=(0, -3, 4), startPos=(0, -3, 3), blendType='easeInOut')) self.swimBobTrack.loop() self.nametag3d.setZ(5.0) def exitSwim(self): self.swimBobTrack.finish() del self.swimBobTrack if self.shadow: self.shadow.show() self.exitGeneral() self.getGeomNode().setPosHpr(0, 0, 0, 0, 0, 0) nt = self.nametag3d nt.setX(0) nt.setY(0) nt.setZ(self.getHeight() + 0.5) self.playingAnim = 'neutral' def enterDied(self, ts=0, callback=None, extraArgs=[]): def shouldDisableGags(): if hasattr(self, 'disableGags'): self.disableGags() if hasattr(self, 'setEquippedAttack'): self.setEquippedAttack(-1) self.playingAnim = 'lose' self.isdying = True self.play("lose") self.track = Sequence(Func(self.clearForcedTorsoAnim), Func(shouldDisableGags), Wait(2.2), Func(self.dieSfx), Wait(2.8), self.getGeomNode().scaleInterval( 2, Point3(0.01), startScale=(self.getGeomNode().getScale())), Func(self.delToon), name=self.uniqueName('enterDied')) self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getDoneEvent(), self.diedDone, [callback, extraArgs]) self.track.delayDelete = DelayDelete.DelayDelete( self, 'enterTeleportOut') self.track.start(ts) def diedDone(self, callback, extraArgs): self.__doCallback(callback, extraArgs) self.exitDied() def __doCallback(self, callback, extraArgs): if callback: if extraArgs: callback(*extraArgs) else: callback() def dieSfx(self): self.Losesfx = base.audio3d.loadSfx("phase_5/audio/sfx/ENC_Lose.ogg") base.audio3d.attachSoundToObject(self.Losesfx, self) base.playSfx(self.Losesfx, node=self) def delToon(self): self.isdead = True def exitDied(self): if self.track != None: self.ignore(self.track.getDoneEvent()) self.track.finish() DelayDelete.cleanupDelayDeletes(self.track) self.track = None if hasattr(self, 'enableGags'): self.enableGags() self.rescaleToon() self.playingAnim = 'neutral' def enterBow(self, ts=0, callback=None, extraArgs=[]): self.play("bow") self.playingAnim = 'bow' def exitBow(self): self.exitGeneral() self.playingAnim = 'neutral' def enterJump(self, ts=0, callback=None, extraArgs=[]): self.playingAnim = 'jump' self.loop("jump") def exitJump(self): self.exitGeneral() self.playingAnim = 'neutral' def enterLeap(self, ts=0, callback=None, extraArgs=[]): self.playingAnim = 'leap' self.loop("leap") def exitLeap(self): self.exitGeneral() self.playingAnim = 'neutral' def enterCringe(self, ts=0, callback=None, extraArgs=[]): self.play("cringe") def exitCringe(self): self.exitGeneral() def enterConked(self, ts=0, callback=None, extraArgs=[]): self.play("conked") def exitConked(self): self.exitGeneral()
class Toon(Avatar.Avatar, ToonHead, ToonDNA.ToonDNA): def __init__(self, cr, mat = 0): self.cr = cr try: self.Toon_initialized return except: self.Toon_initialized = 1 Avatar.Avatar.__init__(self, mat) ToonDNA.ToonDNA.__init__(self) ToonHead.__init__(self, cr) self.forwardSpeed = 0.0 self.rotateSpeed = 0.0 self.avatarType = CIGlobals.Toon self.track = None self.standWalkRunReverse = None self.playingAnim = None self.tag = None self.money = 0 self.lookAtTrack = None self.portal1 = None self.portal2 = None self.gunAttached = False self.gun = None self.tokenIcon = None self.tokenIconIval = None self.backpack = None self.forcedTorsoAnim = None self.fallSfx = base.audio3d.loadSfx('phase_4/audio/sfx/MG_cannon_hit_dirt.mp3') base.audio3d.attachSoundToObject(self.fallSfx, self) self.eyes = loader.loadTexture('phase_3/maps/eyes.jpg', 'phase_3/maps/eyes_a.rgb') self.myTaskId = random.uniform(0, 1231231232132131231232L) self.closedEyes = loader.loadTexture('phase_3/maps/eyesClosed.jpg', 'phase_3/maps/eyesClosed_a.rgb') self.soundChatBubble = loader.loadSfx('phase_3/audio/sfx/GUI_balloon_popup.mp3') self.shadowCaster = None self.chatSoundDict = {} self.animFSM = ClassicFSM('Toon', [State('off', self.enterOff, self.exitOff), State('neutral', self.enterNeutral, self.exitNeutral), State('swim', self.enterSwim, self.exitSwim), State('walk', self.enterWalk, self.exitWalk), State('run', self.enterRun, self.exitRun), State('openBook', self.enterOpenBook, self.exitOpenBook), State('readBook', self.enterReadBook, self.exitReadBook), State('closeBook', self.enterCloseBook, self.exitCloseBook), State('teleportOut', self.enterTeleportOut, self.exitTeleportOut), State('teleportIn', self.enterTeleportIn, self.exitTeleportIn), State('died', self.enterDied, self.exitDied), State('fallFWD', self.enterFallFWD, self.exitFallFWD), State('fallBCK', self.enterFallBCK, self.exitFallBCK), State('jump', self.enterJump, self.exitJump), State('leap', self.enterLeap, self.exitLeap), State('laugh', self.enterLaugh, self.exitLaugh), State('happy', self.enterHappyJump, self.exitHappyJump), State('shrug', self.enterShrug, self.exitShrug), State('hdance', self.enterHDance, self.exitHDance), State('wave', self.enterWave, self.exitWave), State('scientistEmcee', self.enterScientistEmcee, self.exitScientistEmcee), State('scientistWork', self.enterScientistWork, self.exitScientistWork), State('scientistGame', self.enterScientistGame, self.exitScientistGame), State('scientistJealous', self.enterScientistJealous, self.exitScientistJealous), State('cringe', self.enterCringe, self.exitCringe), State('conked', self.enterConked, self.exitConked), State('win', self.enterWin, self.exitWin), State('walkBack', self.enterWalkBack, self.exitWalkBack), State('deadNeutral', self.enterDeadNeutral, self.exitDeadNeutral), State('deadWalk', self.enterDeadWalk, self.exitDeadWalk), State('squish', self.enterSquish, self.exitSquish), State('Happy', self.enterHappy, self.exitHappy), State('Sad', self.enterSad, self.exitSad)], 'off', 'off') animStateList = self.animFSM.getStates() self.animFSM.enterInitialState() if not hasattr(base, 'localAvatar') or not base.localAvatar == self: Avatar.Avatar.initializeBodyCollisions(self, self.avatarType, 3, 1) return def enterHappy(self, ts = 0, callback = None, extraArgs = []): self.playingAnim = None self.standWalkRunReverse = (('neutral', 1.0), ('walk', 1.0), ('run', 1.0), ('walk', -1.0)) self.setSpeed(self.forwardSpeed, self.rotateSpeed) return def exitHappy(self): self.standWalkRunReverse = None self.stop() return def enterSad(self, ts = 0, callback = None, extraArgs = []): self.playingAnim = 'sad' self.standWalkRunReverse = (('dneutral', 1.0), ('dwalk', 1.2), ('dwalk', 1.2), ('dwalk', -1.0)) self.setSpeed(0, 0) def exitSad(self): self.standWalkRunReverse = None self.stop() return def setSpeed(self, forwardSpeed, rotateSpeed): self.forwardSpeed = forwardSpeed self.rotateSpeed = rotateSpeed action = None if self.standWalkRunReverse != None: if forwardSpeed >= CIGlobals.RunCutOff: action = CIGlobals.RUN_INDEX elif forwardSpeed > CIGlobals.WalkCutOff: action = CIGlobals.WALK_INDEX elif forwardSpeed < -CIGlobals.WalkCutOff: action = CIGlobals.REVERSE_INDEX elif rotateSpeed != 0.0: action = CIGlobals.WALK_INDEX else: action = CIGlobals.STAND_INDEX anim, rate = self.standWalkRunReverse[action] if anim != self.playingAnim: self.playingAnim = anim self.stop() self.loop(anim) self.setPlayRate(rate, anim) return action def enterSquish(self, ts = 0, callback = None, extraArgs = []): self.playingAnim = 'squish' sound = loader.loadSfx('phase_9/audio/sfx/toon_decompress.mp3') lerpTime = 0.1 node = self.getGeomNode().getChild(0) origScale = node.getScale() if hasattr(self, 'uniqueName'): name = self.uniqueName('getSquished') else: name = 'getSquished' 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, 'happy', startTime=0.2), SoundInterval(sound)), name=name) self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getDoneEvent(), self.squishDone, [callback, extraArgs]) self.track.delayDelete = DelayDelete.DelayDelete(self, name) self.track.start(ts) def squishDone(self, callback = None, extraArgs = []): self.__doCallback(callback, extraArgs) def exitSquish(self): if self.track: self.ignore(self.track.getName()) DelayDelete.cleanupDelayDeletes(self.track) self.track.finish() self.track = None self.playingAnim = 'neutral' return def enterDeadNeutral(self, ts = 0, callback = None, extraArgs = []): self.loop('dneutral') def exitDeadNeutral(self): self.stop() def enterDeadWalk(self, ts = 0, callback = None, extraArgs = []): self.loop('dwalk') def exitDeadWalk(self): self.stop() def setBackpack(self, pack): self.backpack = pack def getGhost(self): return 0 def updateChatSoundDict(self): self.chatSoundDict['exclaim'] = base.audio3d.loadSfx(self.getToonAnimalNoise('exclaim')) self.chatSoundDict['question'] = base.audio3d.loadSfx(self.getToonAnimalNoise('question')) self.chatSoundDict['short'] = base.audio3d.loadSfx(self.getToonAnimalNoise('short')) self.chatSoundDict['medium'] = base.audio3d.loadSfx(self.getToonAnimalNoise('med')) self.chatSoundDict['long'] = base.audio3d.loadSfx(self.getToonAnimalNoise('long')) self.chatSoundDict['howl'] = base.audio3d.loadSfx(self.getToonAnimalNoise('howl')) base.audio3d.attachSoundToObject(self.chatSoundDict['exclaim'], self.getPart('head')) base.audio3d.attachSoundToObject(self.chatSoundDict['question'], self.getPart('head')) base.audio3d.attachSoundToObject(self.chatSoundDict['short'], self.getPart('head')) base.audio3d.attachSoundToObject(self.chatSoundDict['medium'], self.getPart('head')) base.audio3d.attachSoundToObject(self.chatSoundDict['long'], self.getPart('head')) base.audio3d.attachSoundToObject(self.chatSoundDict['howl'], self.getPart('head')) def ghostOn(self): self.getGeomNode().hide() self.getNameTag().hide() self.getShadow().hide() if self.tokenIcon: self.tokenIcon.hide() self.stashBodyCollisions() def ghostOff(self): self.unstashBodyCollisions() if self.tokenIcon: self.tokenIcon.show() self.getShadow().show() self.getNameTag().show() self.getGeomNode().show() def attachGun(self, gunName): self.detachGun() if gunName == 'pistol': self.gun = loader.loadModel('phase_4/models/props/water-gun.bam') self.gun.reparentTo(self.find('**/def_joint_right_hold')) self.gun.setPos(Point3(0.28, 0.1, 0.08)) self.gun.setHpr(VBase3(85.6, -4.44, 94.43)) self.gunAttached = True elif gunName == 'shotgun': self.gun = loader.loadModel('phase_4/models/props/shotgun.egg') self.gun.setScale(0.75) self.gun.reparentTo(self.find('**/def_joint_right_hold')) self.gun.setPos(Point3(-0.5, -0.2, 0.19)) self.gun.setHpr(Vec3(350, 272.05, 0)) color = random.choice([VBase4(1, 0.25, 0.25, 1), VBase4(0.25, 1, 0.25, 1), VBase4(0.25, 0.25, 1, 1)]) self.gun.setColorScale(color) self.gunAttached = True def detachGun(self): if self.gun and self.gunAttached: self.gun.removeNode() self.gun = None self.gunAttached = False return def stopAnimations(self): if hasattr(self, 'animFSM'): if not self.animFSM.isInternalStateInFlux(): self.animFSM.request('off') else: notify.warning('animFSM in flux, state=%s, not requesting off' % self.animFSM.getCurrentState().getName()) else: notify.warning('animFSM has been deleted') if self.track != None: self.track.finish() DelayDelete.cleanupDelayDeletes(self.track) self.track = None return def disable(self): try: self.Toon_disabled except: self.Toon_disabled = 1 self.backpack = None self.stopAnimations() self.removeAdminToken() ToonHead.delete(self) self.deleteCurrentToon() self.chatSoundDict = {} return def delete(self): try: self.Toon_deleted except: self.Toon_deleted = 1 del self.animFSM self.forwardSpeed = None self.chatSoundDict = None self.rotateSpeed = None self.avatarType = None self.track = None self.standWalkRunReverse = None self.currentAnim = None self.toon_head = None self.forcedTorsoAnim = None self.toon_torso = None self.toon_legs = None self.gender = None self.headtype = None self.head = None self.legtype = None self.torsotype = None self.hr = None self.hg = None self.hb = None self.tr = None self.tg = None self.tb = None self.lr = None self.lg = None self.lb = None self.shir = None self.shig = None self.shib = None self.shor = None self.shog = None self.shob = None self.shirt = None self.sleeve = None self.short = None self.tag = None self.money = None self.lookAtTrack = None self.portal1 = None self.portal2 = None self.backpack = None self.fallSfx = None self.eyes = None self.myTaskId = None self.closedEyes = None self.soundChatBubble = None self.lastAction = None self.lastState = None self.playingAnim = None Avatar.Avatar.delete(self) return def initCollisions(self): self.collNodePath.setCollideMask(BitMask32(0)) self.collNodePath.node().setFromCollideMask(CIGlobals.WallBitmask) pusher = CollisionHandlerPusher() pusher.setInPattern('%in') pusher.addCollider(self.collNodePath, self) base.cTrav.addCollider(self.collNodePath, pusher) def deleteCurrentToon(self): if self.shadowCaster: self.shadowCaster.clear() self.shadowCaster = None try: self.stopLookAround() self.stopBlink() except: pass self.pupils = [] if 'head' in self._Actor__commonBundleHandles: del self._Actor__commonBundleHandles['head'] if 'torso' in self._Actor__commonBundleHandles: del self._Actor__commonBundleHandles['torso'] if 'legs' in self._Actor__commonBundleHandles: del self._Actor__commonBundleHandles['legs'] self.deleteShadow() self.removePart('head') self.removePart('torso') self.removePart('legs') self.detachGun() return def enterGagShop(self): DirectLabel(text='ENTERED GAG SHOP', relief=None, text_scale=0.08) return def setAdminToken(self, tokenId): tokens = {0: 500} if tokenId in tokens.keys(): icons = loader.loadModel('phase_3/models/props/gm_icons.bam') self.tokenIcon = icons.find('**/access_level_%s' % tokens[tokenId]) self.tokenIcon.reparentTo(self) x = self.getNameTag().getX() y = self.getNameTag().getY() z = self.getNameTag().getZ() self.tokenIcon.setPos(Vec3(x, y, z) + (0, 0, 0.5)) self.tokenIcon.setScale(0.4) self.tokenIconIval = Sequence(LerpHprInterval(self.tokenIcon, duration=3.0, hpr=Vec3(360, 0, 0), startHpr=Vec3(0, 0, 0))) self.tokenIconIval.loop() icons.removeNode() def removeAdminToken(self): if self.tokenIcon != None and self.tokenIconIval != None: self.tokenIconIval.finish() self.tokenIcon.removeNode() self.tokenIconIval = None self.tokenIcon = None return def setChat(self, chatString): if not self.isThought(chatString): if not self.getGhost() or self.doId == base.localAvatar.doId: if 'ooo' in chatString.lower(): sfx = self.chatSoundDict['howl'] elif '!' in chatString.lower(): sfx = self.chatSoundDict['exclaim'] elif '?' in chatString.lower(): sfx = self.chatSoundDict['question'] elif len(chatString) <= 9: sfx = self.chatSoundDict['short'] elif 10 <= len(chatString) <= 19: sfx = self.chatSoundDict['medium'] elif len(chatString) >= 20: sfx = self.chatSoundDict['long'] sfx.play() Avatar.Avatar.setChat(self, chatString) def setName(self, nameString): Avatar.Avatar.setName(self, nameString, avatarType=self.avatarType) def setDNAStrand(self, dnaStrand, makeTag = 1): ToonDNA.ToonDNA.setDNAStrand(self, dnaStrand) self.deleteCurrentToon() self.generateToon(makeTag) def generateToon(self, makeTag = 1): self.generateLegs() self.generateTorso() self.generateHead() self.setToonColor() self.setClothes() self.setGloves() self.parentToonParts() self.rescaleToon() if makeTag: self.setupNameTag() Avatar.Avatar.initShadow(self) if self.cr.isShowingPlayerIds: self.showAvId() self.updateChatSoundDict() def attachTNT(self): self.pies.attachTNT() self.holdTNTAnim() def detachTNT(self): self.pies.detachTNT() self.animFSM.request(self.animFSM.getCurrentState().getName()) def holdTNTAnim(self): self.pose('toss', 22, partName='torso') def parentToonParts(self): self.attach('head', 'torso', 'def_head') self.attach('torso', 'legs', 'joint_hips') def unparentToonParts(self): self.getPart('head').reparentTo(self.getGeomNode()) self.getPart('torso').reparentTo(self.getGeomNode()) self.getPart('legs').reparentTo(self.getGeomNode()) def rescaleToon(self): animal = self.getAnimal() bodyScale = CIGlobals.toonBodyScales[animal] headScale = CIGlobals.toonHeadScales[animal][2] shoulderHeight = CIGlobals.legHeightDict[self.legs] * bodyScale + CIGlobals.torsoHeightDict[self.torso] * bodyScale height = shoulderHeight + CIGlobals.headHeightDict[self.head] * headScale bodyScale = CIGlobals.toonBodyScales[animal] self.setAvatarScale(bodyScale) self.setHeight(height) def setGloves(self): color = self.getGloveColor() gloves = self.find('**/hands') gloves.setColor(color) def setClothes(self): shirt, shirtcolor = self.getShirtStyle() short, shortcolor = self.getShortStyle() sleeve, sleevecolor = self.getSleeveStyle() torsot = self.findAllMatches('**/torso-top') torsob = self.findAllMatches('**/torso-bot') sleeves = self.findAllMatches('**/sleeves') torsot.setTexture(loader.loadTexture(shirt), 1) torsob.setTexture(loader.loadTexture(short), 1) sleeves.setTexture(loader.loadTexture(sleeve), 1) torsot.setColor(shirtcolor) sleeves.setColor(sleevecolor) torsob.setColor(shortcolor) def generateLegs(self): legtype = self.getLegs() self.loadModel('phase_3/models/char/tt_a_chr_' + legtype + '_shorts_legs_' + str(CIGlobals.getModelDetail(self.avatarType)) + '.bam', 'legs') self.loadAnims({'neutral': 'phase_3/models/char/tt_a_chr_' + legtype + '_shorts_legs_neutral.bam', 'run': 'phase_3/models/char/tt_a_chr_' + legtype + '_shorts_legs_run.bam', 'walk': 'phase_3.5/models/char/tt_a_chr_' + legtype + '_shorts_legs_walk.bam', 'pie': 'phase_3.5/models/char/tt_a_chr_' + legtype + '_shorts_legs_pie-throw.bam', 'fallb': 'phase_4/models/char/tt_a_chr_' + legtype + '_shorts_legs_slip-backward.bam', 'fallf': 'phase_4/models/char/tt_a_chr_' + legtype + '_shorts_legs_slip-forward.bam', 'lose': 'phase_5/models/char/tt_a_chr_' + legtype + '_shorts_legs_lose.bam', 'win': 'phase_3.5/models/char/tt_a_chr_' + legtype + '_shorts_legs_victory-dance.bam', 'squirt': 'phase_5/models/char/tt_a_chr_' + legtype + '_shorts_legs_water-gun.bam', 'zend': 'phase_3.5/models/char/tt_a_chr_' + legtype + '_shorts_legs_jump-zend.bam', 'tele': 'phase_3.5/models/char/tt_a_chr_' + legtype + '_shorts_legs_teleport.bam', 'book': 'phase_3.5/models/char/tt_a_chr_' + legtype + '_shorts_legs_book.bam', 'leap': 'phase_3.5/models/char/tt_a_chr_' + legtype + '_shorts_legs_leap_zhang.bam', 'jump': 'phase_3.5/models/char/tt_a_chr_' + legtype + '_shorts_legs_jump-zhang.bam', 'happy': 'phase_3.5/models/char/tt_a_chr_' + legtype + '_shorts_legs_jump.bam', 'shrug': 'phase_3.5/models/char/tt_a_chr_' + legtype + '_shorts_legs_shrug.bam', 'hdance': 'phase_5/models/char/tt_a_chr_' + legtype + '_shorts_legs_happy-dance.bam', 'wave': 'phase_3.5/models/char/tt_a_chr_' + legtype + '_shorts_legs_wave.bam', 'scemcee': 'phase_4/models/char/tt_a_chr_dgm_shorts_legs_scientistEmcee.bam', 'scwork': 'phase_4/models/char/tt_a_chr_' + legtype + '_shorts_legs_scientistWork.bam', 'scgame': 'phase_4/models/char/tt_a_chr_' + legtype + '_shorts_legs_scientistGame.bam', 'scjealous': 'phase_4/models/char/tt_a_chr_' + legtype + '_shorts_legs_scientistJealous.bam', 'swim': 'phase_4/models/char/tt_a_chr_' + legtype + '_shorts_legs_swim.bam', 'toss': 'phase_5/models/char/tt_a_chr_' + legtype + '_shorts_legs_toss.bam', 'cringe': 'phase_3.5/models/char/tt_a_chr_' + legtype + '_shorts_legs_cringe.bam', 'conked': 'phase_3.5/models/char/tt_a_chr_' + legtype + '_shorts_legs_conked.bam', 'catchneutral': 'phase_4/models/char/tt_a_chr_' + legtype + '_shorts_legs_gameneutral.bam', 'catchrun': 'phase_4/models/char/tt_a_chr_' + legtype + '_shorts_legs_gamerun.bam', 'hold-bottle': 'phase_5/models/char/tt_a_chr_' + legtype + '_shorts_legs_hold-bottle.bam', 'push-button': 'phase_3.5/models/char/tt_a_chr_' + legtype + '_shorts_legs_press-button.bam', 'happy-dance': 'phase_5/models/char/tt_a_chr_' + legtype + '_shorts_legs_happy-dance.bam', 'juggle': 'phase_5/models/char/tt_a_chr_' + legtype + '_shorts_legs_juggle.bam', 'shout': 'phase_5/models/char/tt_a_chr_' + legtype + '_shorts_legs_shout.bam', 'dneutral': 'phase_4/models/char/tt_a_chr_' + legtype + '_shorts_legs_sad-neutral.bam', 'dwalk': 'phase_4/models/char/tt_a_chr_' + legtype + '_shorts_legs_losewalk.bam', 'smooch': 'phase_5/models/char/tt_a_chr_' + legtype + '_shorts_legs_smooch.bam', 'conked': 'phase_3.5/models/char/tt_a_chr_' + legtype + '_shorts_legs_conked.bam', 'sound': 'phase_5/models/char/tt_a_chr_' + legtype + '_shorts_legs_shout.bam', 'sprinkle-dust': 'phase_5/models/char/tt_a_chr_' + legtype + '_shorts_legs_sprinkle-dust.bam', 'start-sit': 'phase_4/models/char/tt_a_chr_' + legtype + '_shorts_legs_intoSit.bam', 'sit': 'phase_4/models/char/char/tt_a_chr_' + legtype + '_shorts_legs_sit.bam'}, 'legs') self.findAllMatches('**/boots_long').stash() self.findAllMatches('**/boots_short').stash() self.findAllMatches('**/shoes').stash() def generateTorso(self): torsotype = self.getTorso() self.loadModel('phase_3/models/char/tt_a_chr_' + torsotype + '_torso_' + str(CIGlobals.getModelDetail(self.avatarType)) + '.bam', 'torso') self.loadAnims({'neutral': 'phase_3/models/char/tt_a_chr_' + torsotype + '_torso_neutral.bam', 'run': 'phase_3/models/char/tt_a_chr_' + torsotype + '_torso_run.bam', 'walk': 'phase_3.5/models/char/tt_a_chr_' + torsotype + '_torso_walk.bam', 'pie': 'phase_3.5/models/char/tt_a_chr_' + torsotype + '_torso_pie-throw.bam', 'fallb': 'phase_4/models/char/tt_a_chr_' + torsotype + '_torso_slip-backward.bam', 'fallf': 'phase_4/models/char/tt_a_chr_' + torsotype + '_torso_slip-forward.bam', 'lose': 'phase_5/models/char/tt_a_chr_' + torsotype + '_torso_lose.bam', 'win': 'phase_3.5/models/char/tt_a_chr_' + torsotype + '_torso_victory-dance.bam', 'squirt': 'phase_5/models/char/tt_a_chr_' + torsotype + '_torso_water-gun.bam', 'zend': 'phase_3.5/models/char/tt_a_chr_' + torsotype + '_torso_jump-zend.bam', 'tele': 'phase_3.5/models/char/tt_a_chr_' + torsotype + '_torso_teleport.bam', 'book': 'phase_3.5/models/char/tt_a_chr_' + torsotype + '_torso_book.bam', 'leap': 'phase_3.5/models/char/tt_a_chr_' + torsotype + '_torso_leap_zhang.bam', 'jump': 'phase_3.5/models/char/tt_a_chr_' + torsotype + '_torso_jump-zhang.bam', 'happy': 'phase_3.5/models/char/tt_a_chr_' + torsotype + '_torso_jump.bam', 'shrug': 'phase_3.5/models/char/tt_a_chr_' + torsotype + '_torso_shrug.bam', 'hdance': 'phase_5/models/char/tt_a_chr_' + torsotype + '_torso_happy-dance.bam', 'wave': 'phase_3.5/models/char/tt_a_chr_' + torsotype + '_torso_wave.bam', 'scemcee': 'phase_4/models/char/tt_a_chr_dgm_shorts_torso_scientistEmcee.bam', 'scwork': 'phase_4/models/char/tt_a_chr_' + torsotype + '_torso_scientistWork.bam', 'scgame': 'phase_4/models/char/tt_a_chr_' + torsotype + '_torso_scientistGame.bam', 'scjealous': 'phase_4/models/char/tt_a_chr_' + torsotype + '_torso_scientistJealous.bam', 'swim': 'phase_4/models/char/tt_a_chr_' + torsotype + '_torso_swim.bam', 'toss': 'phase_5/models/char/tt_a_chr_' + torsotype + '_torso_toss.bam', 'cringe': 'phase_3.5/models/char/tt_a_chr_' + torsotype + '_torso_cringe.bam', 'conked': 'phase_3.5/models/char/tt_a_chr_' + torsotype + '_torso_conked.bam', 'catchneutral': 'phase_4/models/char/tt_a_chr_' + torsotype + '_torso_gameneutral.bam', 'catchrun': 'phase_4/models/char/tt_a_chr_' + torsotype + '_torso_gamerun.bam', 'hold-bottle': 'phase_5/models/char/tt_a_chr_' + torsotype + '_torso_hold-bottle.bam', 'push-button': 'phase_3.5/models/char/tt_a_chr_' + torsotype + '_torso_press-button.bam', 'happy-dance': 'phase_5/models/char/tt_a_chr_' + torsotype + '_torso_happy-dance.bam', 'juggle': 'phase_5/models/char/tt_a_chr_' + torsotype + '_torso_juggle.bam', 'shout': 'phase_5/models/char/tt_a_chr_' + torsotype + '_torso_shout.bam', 'dneutral': 'phase_4/models/char/tt_a_chr_' + torsotype + '_torso_sad-neutral.bam', 'dwalk': 'phase_4/models/char/tt_a_chr_' + torsotype + '_torso_losewalk.bam', 'smooch': 'phase_5/models/char/tt_a_chr_' + torsotype + '_torso_smooch.bam', 'conked': 'phase_3.5/models/char/tt_a_chr_' + torsotype + '_torso_conked.bam', 'sound': 'phase_5/models/char/tt_a_chr_' + torsotype + '_torso_shout.bam', 'sprinkle-dust': 'phase_5/models/char/tt_a_chr_' + torsotype + '_torso_sprinkle-dust.bam', 'start-sit': 'phase_4/models/char/tt_a_chr_' + torsotype + '_torso_intoSit.bam', 'sit': 'phase_4/models/char/tt_a_chr_' + torsotype + '_torso_sit.bam'}, 'torso') def generateHead(self, pat = 0): gender = self.getGender() head = self.getAnimal() headtype = self.getHead() ToonHead.generateHead(self, gender, head, headtype) def setToonColor(self): self.setHeadColor() self.setTorsoColor() self.setLegColor() def setLegColor(self): legcolor = self.getLegColor() self.findAllMatches('**/legs').setColor(legcolor) self.findAllMatches('**/feet').setColor(legcolor) def setTorsoColor(self): torsocolor = self.getTorsoColor() self.findAllMatches('**/arms').setColor(torsocolor) self.findAllMatches('**/neck').setColor(torsocolor) self.findAllMatches('**/hands').setColor(1, 1, 1, 1) def setForcedTorsoAnim(self, string): self.forcedTorsoAnim = string self.loop(string, partName='torso') def clearForcedTorsoAnim(self): self.forcedTorsoAnim = None self.animFSM.request(self.animFSM.getCurrentState().getName()) return def enterOff(self, ts = 0, callback = None, extraArgs = []): self.currentAnim = None return def exitOff(self): pass def enterWin(self, ts = 0, callback = None, extraArgs = []): self.playingAnim = 'win' self.sfx = base.audio3d.loadSfx('phase_3.5/audio/sfx/ENC_Win.mp3') self.sfx.setLoop(True) base.audio3d.attachSoundToObject(self.sfx, self) base.playSfx(self.sfx) self.loop('win') def exitWin(self): self.stop() self.sfx.stop() del self.sfx self.playingAnim = 'neutral' def enterShrug(self, ts = 0, callback = None, extraArgs = []): self.play('shrug') def exitShrug(self): self.exitGeneral() def enterHDance(self, ts = 0, callback = None, extraArgs = []): self.play('hdance') def exitHDance(self): self.exitGeneral() def enterScientistWork(self, ts = 0, callback = None, extraArgs = []): self.loop('scwork') def exitScientistWork(self): self.exitGeneral() def enterScientistEmcee(self, ts = 0, callback = None, extraArgs = []): self.loop('scemcee') def exitScientistEmcee(self): self.exitGeneral() def enterScientistGame(self, ts = 0, callback = None, extraArgs = []): self.loop('scgame') def exitScientistGame(self): self.exitGeneral() def enterScientistJealous(self, ts = 0, callback = None, extraArgs = []): self.loop('scjealous') def exitScientistJealous(self): self.exitGeneral() def enterWave(self, ts = 0, callback = None, extraArgs = []): self.play('wave') def exitWave(self): self.exitGeneral() def enterLaugh(self, ts = 0, callback = None, extraArgs = []): self.setPlayRate(5.0, 'neutral') self.loop('neutral') def exitLaugh(self): self.setPlayRate(1.0, 'neutral') self.stop() def enterNeutral(self, ts = 0, callback = None, extraArgs = []): if self.backpack: if self.backpack.getCurrentGag(): if self.backpack.getCurrentGag().getState() != GagState.LOADED: self.loop('neutral', partName='legs') if self.animal == 'dog': self.loop('neutral', partName='head') return if self.forcedTorsoAnim != None: self.loop(self.forcedTorsoAnim, partName='torso') self.loop('neutral', partName='legs') return else: self.loop('neutral') self.playingAnim = 'neutral' return def exitNeutral(self): self.exitGeneral() self.playingAnim = 'neutral' def exitGeneral(self): if self.backpack: if self.backpack.getCurrentGag(): if self.backpack.getCurrentGag().getState() != GagState.LOADED: self.stop(partName='legs') else: self.stop() else: self.stop() else: self.stop() def enterRun(self, ts = 0, callback = None, extraArgs = []): if self.backpack: if self.backpack.getCurrentGag(): if self.backpack.getCurrentGag().getState() != GagState.LOADED: self.loop('run', partName='legs') if self.animal == 'dog': self.loop('run', partName='head') return if self.forcedTorsoAnim != None: self.loop(self.forcedTorsoAnim, partName='torso') self.loop('run', partName='legs') return else: self.loop('run') return def exitRun(self): self.exitGeneral() def enterWalk(self, ts = 0, callback = None, extraArgs = []): if self.backpack: if self.backpack.getCurrentGag(): if self.backpack.getCurrentGag().getState() != GagState.LOADED: self.loop('walk', partName='legs') if self.animal == 'dog': self.loop('walk', partName='head') return if self.forcedTorsoAnim != None: self.loop(self.forcedTorsoAnim, partName='torso') self.loop('walk', partName='legs') return else: self.loop('walk') return def exitWalk(self): self.exitGeneral() def enterWalkBack(self, ts = 0, callback = None, extraArgs = []): self.setPlayRate(-1.0, 'walk') self.enterWalk() def exitWalkBack(self): self.exitWalk() self.setPlayRate(1.0, 'walk') def enterOpenBook(self, ts = 0, callback = None, extraArgs = []): self.playingAnim = 'book' self.book1 = Actor('phase_3.5/models/props/book-mod.bam', {'chan': 'phase_3.5/models/props/book-chan.bam'}) self.book1.reparentTo(self.getPart('torso').find('**/def_joint_right_hold')) self.track = ActorInterval(self, 'book', startFrame=CIGlobals.OpenBookFromFrame, endFrame=CIGlobals.OpenBookToFrame, name=self.uniqueName('enterOpenBook')) self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getDoneEvent(), self.__doCallback, [callback, extraArgs]) self.track.start(ts) self.book1.play('chan', fromFrame=CIGlobals.OpenBookFromFrame, toFrame=CIGlobals.OpenBookToFrame) def exitOpenBook(self): if self.track: self.ignore(self.track.getDoneEvent()) self.track.finish() self.track = None if self.book1: self.book1.cleanup() self.book1 = None self.playingAnim = 'neutral' return def enterReadBook(self, ts = 0, callback = None, extraArgs = []): self.playingAnim = 'book' self.book2 = Actor('phase_3.5/models/props/book-mod.bam', {'chan': 'phase_3.5/models/props/book-chan.bam'}) self.book2.reparentTo(self.getPart('torso').find('**/def_joint_right_hold')) self.pingpong('book', fromFrame=CIGlobals.ReadBookFromFrame, toFrame=CIGlobals.ReadBookToFrame) self.book2.pingpong('chan', fromFrame=CIGlobals.ReadBookFromFrame, toFrame=CIGlobals.ReadBookToFrame) def exitReadBook(self): if self.book2: self.book2.cleanup() self.book2 = None self.playingAnim = 'neutral' return def enterCloseBook(self, ts = 0, callback = None, extraArgs = []): self.playingAnim = 'book' self.book3 = Actor('phase_3.5/models/props/book-mod.bam', {'chan': 'phase_3.5/models/props/book-chan.bam'}) self.book3.reparentTo(self.getPart('torso').find('**/def_joint_right_hold')) self.track = ActorInterval(self, 'book', startFrame=CIGlobals.CloseBookFromFrame, endFrame=CIGlobals.CloseBookToFrame, name=self.uniqueName('enterCloseBook')) self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getDoneEvent(), self.__doCallback, [callback, extraArgs]) self.track.start(ts) self.book3.play('chan', fromFrame=CIGlobals.CloseBookFromFrame, toFrame=CIGlobals.CloseBookToFrame) def exitCloseBook(self): if self.track: self.ignore(self.track.getDoneEvent()) self.track.finish() self.track = None if self.book3: self.book3.cleanup() self.book3 = None self.playingAnim = 'neutral' return def enterTeleportOut(self, ts = 0, callback = None, extraArgs = []): self.notify.info(str(self.doId) + '-' + str(self.zoneId) + ': enterTeleportOut') self.playingAnim = 'tele' self.portal1 = Actor('phase_3.5/models/props/portal-mod.bam', {'chan': 'phase_3.5/models/props/portal-chan.bam'}) self.portal1.play('chan') self.portal1.reparentTo(self.getPart('legs').find('**/def_joint_right_hold')) self.play('tele') if hasattr(self, 'uniqueName'): name = self.uniqueName('enterTeleportOut') else: name = 'enterTeleportOut' self.track = Sequence(Wait(0.4), Func(self.teleportOutSfx), Wait(1.3), Func(self.throwPortal), Wait(3.4), name=name) self.track.delayDelete = DelayDelete.DelayDelete(self, name) self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getName(), self.teleportOutDone, [callback, extraArgs]) self.track.start(ts) def doPortalBins(self, portal): portal.setBin('shadow', 0) portal.setDepthWrite(0) portal.setDepthTest(0) def teleportOutDone(self, callback, requestStatus): self.notify.info(str(self.doId) + '-' + str(self.zoneId) + ': teleportOutDone') self.__doCallback(callback, requestStatus) self.exitTeleportOut() def teleportOutSfx(self): self.outSfx = base.audio3d.loadSfx('phase_3.5/audio/sfx/AV_teleport.mp3') base.audio3d.attachSoundToObject(self.outSfx, self.portal1) self.outSfx.play() def throwPortal(self): self.doPortalBins(self.portal1) self.portal1.reparentTo(self.getPart('legs').find('**/joint_nameTag')) self.portal1.setScale(CIGlobals.PortalScale) self.portal1.setY(6.5) self.portal1.setH(180) def exitTeleportOut(self): self.notify.info(str(self.doId) + '-' + str(self.zoneId) + ': exitTeleportOut') if self.track != None: self.ignore(self.track.getName()) self.track.finish() DelayDelete.cleanupDelayDeletes(self.track) self.track = None if self.portal1: self.portal1.cleanup() self.portal1 = None self.playingAnim = 'neutral' return def getTeleportInTrack(self, portal): self.doPortalBins(portal) holeTrack = Sequence() holeTrack.append(Func(portal.reparentTo, self)) pos = Point3(0, -2.4, 0) holeTrack.append(Func(portal.setPos, pos)) holeTrack.append(ActorInterval(portal, 'chan', startTime=3.4, endTime=3.1)) holeTrack.append(Wait(0.6)) holeTrack.append(ActorInterval(portal, 'chan', startTime=3.1, endTime=3.4)) def restorePortal(portal): portal.setPos(0, 0, 0) portal.detachNode() portal.clearBin() portal.clearDepthTest() portal.clearDepthWrite() holeTrack.append(Func(restorePortal, portal)) toonTrack = Sequence(Wait(0.3), Func(self.getGeomNode().show), Func(self.getNameTag().show), ActorInterval(self, 'happy', startTime=0.45)) if hasattr(self, 'uniqueName'): trackName = self.uniqueName('teleportIn') else: trackName = 'teleportIn' return Parallel(toonTrack, holeTrack, name=trackName) def enterTeleportIn(self, ts = 0, callback = None, extraArgs = []): self.playingAnim = 'happy' self.portal2 = Actor('phase_3.5/models/props/portal-mod.bam', {'chan': 'phase_3.5/models/props/portal-chan.bam'}) self.show() self.getGeomNode().hide() self.getNameTag().hide() self.track = self.getTeleportInTrack(self.portal2) self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getName(), self.teleportInDone, [callback, extraArgs]) self.track.delayDelete = DelayDelete.DelayDelete(self, self.track.getName()) self.track.start(ts) def teleportInDone(self, callback, extraArgs): self.__doCallback(callback, extraArgs) self.exitTeleportIn() def exitTeleportIn(self): if self.track != None: self.ignore(self.track.getName()) self.track.finish() DelayDelete.cleanupDelayDeletes(self.track) self.track = None if self.portal2: self.portal2.cleanup() self.portal2 = None if self.getGeomNode(): self.getGeomNode().show() if self.getNameTag(): self.getNameTag().show() self.playingAnim = 'neutral' return def enterFallFWD(self, ts = 0, callback = None, extraArgs = []): self.playingAnim = 'fallf' self.play('fallf') Sequence(Wait(0.5), Func(self.fallSfx.play)).start() def exitFallFWD(self): self.exitGeneral() self.playingAnim = 'neutral' def enterFallBCK(self, ts = 0, callback = None, extraArgs = []): self.playingAnim = 'fallb' self.play('fallb') Sequence(Wait(0.5), Func(self.fallSfx.play)).start() def exitFallBCK(self): self.playingAnim = 'neutral' self.exitGeneral() def enterHappyJump(self, ts = 0, callback = None, extraArgs = []): self.playingAnim = 'happy' self.play('happy') def exitHappyJump(self): self.exitGeneral() self.playingAnim = 'neutral' def enterSwim(self, ts = 0, callback = None, extraArgs = []): self.playingAnim = 'swim' self.loop('swim') self.getGeomNode().setP(-89.0) self.getGeomNode().setZ(4.0) nt = self.getNameTag() nt.setX(0) nt.setY(-2) nt.setZ(5.0) def exitSwim(self): self.exitGeneral() self.getGeomNode().setP(0.0) self.getGeomNode().setZ(0.0) nt = self.getNameTag() nt.setX(0) nt.setY(0) nt.setZ(self.getHeight() + 0.3) self.playingAnim = 'neutral' def enterDied(self, ts = 0, callback = None, extraArgs = []): self.playingAnim = 'lose' self.isdying = True self.play('lose') self.track = Sequence(Wait(2.2), Func(self.dieSfx), Wait(2.8), self.getGeomNode().scaleInterval(2, Point3(0.01), startScale=self.getGeomNode().getScale()), Func(self.delToon), name=self.uniqueName('enterDied')) self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getDoneEvent(), self.diedDone, [callback, extraArgs]) self.track.delayDelete = DelayDelete.DelayDelete(self, 'enterTeleportOut') self.track.start(ts) def diedDone(self, callback, extraArgs): self.__doCallback(callback, extraArgs) self.exitDied() def __doCallback(self, callback, extraArgs): if callback: if extraArgs: callback(*extraArgs) else: callback() def dieSfx(self): self.Losesfx = base.audio3d.loadSfx('phase_5/audio/sfx/ENC_Lose.mp3') base.audio3d.attachSoundToObject(self.Losesfx, self) self.Losesfx.play() def delToon(self): self.isdead = True def exitDied(self): if self.track != None: self.ignore(self.track.getDoneEvent()) self.track.finish() DelayDelete.cleanupDelayDeletes(self.track) self.track = None self.rescaleToon() self.playingAnim = 'neutral' return def enterJump(self, ts = 0, callback = None, extraArgs = []): self.playingAnim = 'jump' self.loop('jump') def exitJump(self): self.exitGeneral() self.playingAnim = 'neutral' def enterLeap(self, ts = 0, callback = None, extraArgs = []): self.playingAnim = 'leap' self.loop('leap') def exitLeap(self): self.exitGeneral() self.playingAnim = 'neutral' def enterCringe(self, ts = 0, callback = None, extraArgs = []): self.play('cringe') def exitCringe(self): self.exitGeneral() def enterConked(self, ts = 0, callback = None, extraArgs = []): self.play('conked') def exitConked(self): self.exitGeneral()
class ToonHead(Actor.Actor): notify = DirectNotifyGlobal.directNotify.newCategory('ToonHead') EyesOpen = loader.loadTexture('phase_3/maps/eyes.jpg', 'phase_3/maps/eyes_a.rgb') EyesOpen.setMinfilter(Texture.FTLinear) EyesOpen.setMagfilter(Texture.FTLinear) EyesClosed = loader.loadTexture('phase_3/maps/eyesClosed.jpg', 'phase_3/maps/eyesClosed_a.rgb') EyesClosed.setMinfilter(Texture.FTLinear) EyesClosed.setMagfilter(Texture.FTLinear) EyesSadOpen = loader.loadTexture('phase_3/maps/eyesSad.jpg', 'phase_3/maps/eyesSad_a.rgb') EyesSadOpen.setMinfilter(Texture.FTLinear) EyesSadOpen.setMagfilter(Texture.FTLinear) EyesSadClosed = loader.loadTexture('phase_3/maps/eyesSadClosed.jpg', 'phase_3/maps/eyesSadClosed_a.rgb') EyesSadClosed.setMinfilter(Texture.FTLinear) EyesSadClosed.setMagfilter(Texture.FTLinear) EyesAngryOpen = loader.loadTexture('phase_3/maps/eyesAngry.jpg', 'phase_3/maps/eyesAngry_a.rgb') EyesAngryOpen.setMinfilter(Texture.FTLinear) EyesAngryOpen.setMagfilter(Texture.FTLinear) EyesAngryClosed = loader.loadTexture('phase_3/maps/eyesAngryClosed.jpg', 'phase_3/maps/eyesAngryClosed_a.rgb') EyesAngryClosed.setMinfilter(Texture.FTLinear) EyesAngryClosed.setMagfilter(Texture.FTLinear) EyesSurprised = loader.loadTexture('phase_3/maps/eyesSurprised.jpg', 'phase_3/maps/eyesSurprised_a.rgb') EyesSurprised.setMinfilter(Texture.FTLinear) EyesSurprised.setMagfilter(Texture.FTLinear) Muzzle = loader.loadTexture('phase_3/maps/muzzleShrtGeneric.jpg') Muzzle.setMinfilter(Texture.FTLinear) Muzzle.setMagfilter(Texture.FTLinear) MuzzleSurprised = loader.loadTexture( 'phase_3/maps/muzzleShortSurprised.jpg') MuzzleSurprised.setMinfilter(Texture.FTLinear) MuzzleSurprised.setMagfilter(Texture.FTLinear) LeftA = Point3(0.06, 0.0, 0.14) LeftB = Point3(-0.13, 0.0, 0.1) LeftC = Point3(-0.05, 0.0, 0.0) LeftD = Point3(0.06, 0.0, 0.0) RightA = Point3(0.13, 0.0, 0.1) RightB = Point3(-0.06, 0.0, 0.14) RightC = Point3(-0.06, 0.0, 0.0) RightD = Point3(0.05, 0.0, 0.0) LeftAD = Point3( LeftA[0] - LeftA[2] * (LeftD[0] - LeftA[0]) / (LeftD[2] - LeftA[2]), 0.0, 0.0) LeftBC = Point3( LeftB[0] - LeftB[2] * (LeftC[0] - LeftB[0]) / (LeftC[2] - LeftB[2]), 0.0, 0.0) RightAD = Point3( RightA[0] - RightA[2] * (RightD[0] - RightA[0]) / (RightD[2] - RightA[2]), 0.0, 0.0) RightBC = Point3( RightB[0] - RightB[2] * (RightC[0] - RightB[0]) / (RightC[2] - RightB[2]), 0.0, 0.0) def __init__(self): Actor.Actor.__init__(self) self.toonName = 'ToonHead-' + str(self.this) self.__blinkName = 'blink-' + self.toonName self.__stareAtName = 'stareAt-' + self.toonName self.__lookName = 'look-' + self.toonName self.lookAtTrack = None self.__muzzles = [] self.__surpriseMuzzles = [] self.__angryMuzzles = [] self.__sadMuzzles = [] self.__smileMuzzles = [] self.__laughMuzzles = [] self.__eyes = None self.__eyelashOpen = None self.__eyelashClosed = None self.__lod500Eyes = None self.__lod250Eyes = None self.__lpupil = None self.__lod500lPupil = None self.__lod250lPupil = None self.__rpupil = None self.__lod500rPupil = None self.__lod250rPupil = None self.__muzzle = None self.__eyesOpen = ToonHead.EyesOpen self.__eyesClosed = ToonHead.EyesClosed self.__height = 0.0 self.__eyelashesHiddenByGlasses = False self.randGen = random.Random() self.randGen.seed(random.random()) self.eyelids = ClassicFSM('eyelids', [ State('off', self.enterEyelidsOff, self.exitEyelidsOff, ['open', 'closed', 'surprised']), State('open', self.enterEyelidsOpen, self.exitEyelidsOpen, ['closed', 'surprised', 'off']), State('surprised', self.enterEyelidsSurprised, self.exitEyelidsSurprised, ['open', 'closed', 'off']), State('closed', self.enterEyelidsClosed, self.exitEyelidsClosed, ['open', 'surprised', 'off']) ], 'off', 'off') self.eyelids.enterInitialState() self.emote = None self.__stareAtNode = NodePath() self.__defaultStarePoint = Point3(0, 0, 0) self.__stareAtPoint = self.__defaultStarePoint self.__stareAtTime = 0 self.lookAtPositionCallbackArgs = None def delete(self): try: self.ToonHead_deleted except: self.ToonHead_deleted = 1 taskMgr.remove(self.__blinkName) taskMgr.remove(self.__lookName) taskMgr.remove(self.__stareAtName) if self.lookAtTrack: self.lookAtTrack.finish() self.lookAtTrack = None del self.eyelids del self.__stareAtNode del self.__stareAtPoint if self.__eyes: del self.__eyes if self.__lpupil: del self.__lpupil if self.__rpupil: del self.__rpupil if self.__eyelashOpen: del self.__eyelashOpen if self.__eyelashClosed: del self.__eyelashClosed self.lookAtPositionCallbackArgs = None Actor.Actor.delete(self) return def setupHead(self, dna, forGui=0): self.__height = self.generateToonHead(dna, forGui=forGui) self.generateToonColor(dna) animalStyle = dna.getAnimal() bodyScale = toonBodyScales[animalStyle] headScale = toonHeadScales[animalStyle] self.getGeomNode().setScale(headScale[0] * bodyScale * 1.3, headScale[1] * bodyScale * 1.3, headScale[2] * bodyScale * 1.3) if forGui: self.getGeomNode().setDepthWrite(1) self.getGeomNode().setDepthTest(1) if dna.getAnimal() == 'dog': self.loop('neutral') def fitAndCenterHead(self, maxDim, forGui=0): p1 = Point3() p2 = Point3() self.calcTightBounds(p1, p2) if forGui: h = 180 t = p1[0] p1.setX(-p2[0]) p2.setX(-t) else: h = 0 d = p2 - p1 biggest = max(d[0], d[2]) s = maxDim / biggest mid = (p1 + d / 2.0) * s self.setPosHprScale(-mid[0], -mid[1] + 1, -mid[2], h, 0, 0, s, s, s) def setLookAtPositionCallbackArgs(self, argTuple): self.lookAtPositionCallbackArgs = argTuple def getHeight(self): return self.__height def getRandomForwardLookAtPoint(self): x = self.randGen.choice((-0.8, -0.5, 0, 0.5, 0.8)) z = self.randGen.choice((-0.5, 0, 0.5, 0.8)) return Point3(x, 1.5, z) def findSomethingToLookAt(self): if self.lookAtPositionCallbackArgs is not None: pnt = self.lookAtPositionCallbackArgs[0].getLookAtPosition( self.lookAtPositionCallbackArgs[1], self.lookAtPositionCallbackArgs[2]) self.startStareAt(self, pnt) return if self.randGen.random() < 0.33: lookAtPnt = self.getRandomForwardLookAtPoint() else: lookAtPnt = self.__defaultStarePoint self.lerpLookAt(lookAtPnt, blink=1) return def generateToonHead(self, style, lods=['1000'], forGui=0): headStyle = style.head fix = None if headStyle == 'dls': filePrefix = HeadDict['dls'] headHeight = 0.75 elif headStyle == 'dss': filePrefix = HeadDict['dss'] headHeight = 0.5 elif headStyle == 'dsl': filePrefix = HeadDict['dsl'] headHeight = 0.5 elif headStyle == 'dll': filePrefix = HeadDict['dll'] headHeight = 0.75 elif headStyle == 'cls': filePrefix = HeadDict['c'] fix = self.__fixHeadLongShort headHeight = 0.75 elif headStyle == 'css': filePrefix = HeadDict['c'] fix = self.__fixHeadShortShort headHeight = 0.5 elif headStyle == 'csl': filePrefix = HeadDict['c'] fix = self.__fixHeadShortLong headHeight = 0.5 elif headStyle == 'cll': filePrefix = HeadDict['c'] fix = self.__fixHeadLongLong headHeight = 0.75 elif headStyle == 'hls': filePrefix = HeadDict['h'] fix = self.__fixHeadLongShort headHeight = 0.75 elif headStyle == 'hss': filePrefix = HeadDict['h'] fix = self.__fixHeadShortShort headHeight = 0.5 elif headStyle == 'hsl': filePrefix = HeadDict['h'] fix = self.__fixHeadShortLong headHeight = 0.5 elif headStyle == 'hll': filePrefix = HeadDict['h'] fix = self.__fixHeadLongLong headHeight = 0.75 elif headStyle == 'mls': filePrefix = HeadDict['m'] fix = self.__fixHeadLongShort headHeight = 0.75 elif headStyle == 'mss': filePrefix = HeadDict['m'] fix = self.__fixHeadShortShort headHeight = 0.5 elif headStyle == 'rls': filePrefix = HeadDict['r'] fix = self.__fixHeadLongShort headHeight = 0.75 elif headStyle == 'rss': filePrefix = HeadDict['r'] fix = self.__fixHeadShortShort headHeight = 0.5 elif headStyle == 'rsl': filePrefix = HeadDict['r'] fix = self.__fixHeadShortLong headHeight = 0.5 elif headStyle == 'rll': filePrefix = HeadDict['r'] fix = self.__fixHeadLongLong headHeight = 0.75 elif headStyle == 'fls': filePrefix = HeadDict['f'] fix = self.__fixHeadLongShort headHeight = 0.75 elif headStyle == 'fss': filePrefix = HeadDict['f'] fix = self.__fixHeadShortShort headHeight = 0.5 elif headStyle == 'fsl': filePrefix = HeadDict['f'] fix = self.__fixHeadShortLong headHeight = 0.5 elif headStyle == 'fll': filePrefix = HeadDict['f'] fix = self.__fixHeadLongLong headHeight = 0.75 elif headStyle == 'pls': filePrefix = HeadDict['p'] fix = self.__fixHeadLongShort headHeight = 0.75 elif headStyle == 'pss': filePrefix = HeadDict['p'] fix = self.__fixHeadShortShort headHeight = 0.5 elif headStyle == 'psl': filePrefix = HeadDict['p'] fix = self.__fixHeadShortLong headHeight = 0.5 elif headStyle == 'pll': filePrefix = HeadDict['p'] fix = self.__fixHeadLongLong headHeight = 0.75 elif headStyle == 'bls': filePrefix = HeadDict['b'] fix = self.__fixHeadLongShort headHeight = 0.75 elif headStyle == 'bss': filePrefix = HeadDict['b'] fix = self.__fixHeadShortShort headHeight = 0.5 elif headStyle == 'bsl': filePrefix = HeadDict['b'] fix = self.__fixHeadShortLong headHeight = 0.5 elif headStyle == 'bll': filePrefix = HeadDict['b'] fix = self.__fixHeadLongLong headHeight = 0.75 elif headStyle == 'sls': filePrefix = HeadDict['s'] fix = self.__fixHeadLongShort headHeight = 0.75 elif headStyle == 'sss': filePrefix = HeadDict['s'] fix = self.__fixHeadShortShort headHeight = 0.5 elif headStyle == 'ssl': filePrefix = HeadDict['s'] fix = self.__fixHeadShortLong headHeight = 0.5 elif headStyle == 'sll': filePrefix = HeadDict['s'] fix = self.__fixHeadLongLong headHeight = 0.75 else: ToonHead.notify.error('unknown head style: %s' % headStyle) if len(lods) == 1: self.loadModel('phase_3' + filePrefix + lods[0], 'head', 'lodRoot', 1) if fix is not None: fix(style, None, 1) if not forGui: self.__lods = lods self.__style = style self.__headStyle = headStyle self.__copy = 1 else: for lod in lods: self.loadModel('phase_3' + filePrefix + lod, 'head', lod, 1) if fix is not None: fix(style, lod, 1) if not forGui: self.__lods = lods self.__style = style self.__headStyle = headStyle self.__copy = 1 self.__fixEyes(style, forGui) self.setupEyelashes(style) self.eyelids.request('closed') self.eyelids.request('open') self.setupMuzzles(style) return headHeight def hideEars(self): self.findAllMatches('**/ears*;+s').stash() def showEars(self): self.findAllMatches('**/ears*;+s').unstash() def hideEyelashes(self): if self.__eyelashOpen: self.__eyelashOpen.stash() if self.__eyelashClosed: self.__eyelashClosed.stash() self.__eyelashesHiddenByGlasses = True def showEyelashes(self): if self.__eyelashOpen: self.__eyelashOpen.unstash() if self.__eyelashClosed: self.__eyelashClosed.unstash() self.__eyelashesHiddenByGlasses = False def generateToonColor(self, style): parts = self.findAllMatches('**/head*') parts.setColor(style.getHeadColor()) animalType = style.getAnimal() if animalType == 'cat' or animalType == 'rabbit' or animalType == 'bear' or animalType == 'mouse' or animalType == 'pig': parts = self.findAllMatches('**/ear?-*') parts.setColor(style.getHeadColor()) def __fixEyes(self, style, forGui=0): mode = -3 if forGui: mode = -2 if self.hasLOD(): for lodName in self.getLODNames(): self.drawInFront('eyes*', 'head-front*', mode, lodName=lodName) if not self.find('**/joint_pupil*').isEmpty(): self.drawInFront('joint_pupil*', 'eyes*', -1, lodName=lodName) else: self.drawInFront('def_*_pupil', 'eyes*', -1, lodName=lodName) self.__eyes = self.getLOD(1000).find('**/eyes*') self.__lod500Eyes = self.getLOD(500).find('**/eyes*') self.__lod250Eyes = self.getLOD(250).find('**/eyes*') if self.__lod500Eyes.isEmpty(): self.__lod500Eyes = None else: self.__lod500Eyes.setColorOff() if not self.find('**/joint_pupilL*').isEmpty(): self.__lod500lPupil = self.__lod500Eyes.find( '**/joint_pupilL*') self.__lod500rPupil = self.__lod500Eyes.find( '**/joint_pupilR*') else: self.__lod500lPupil = self.__lod500Eyes.find( '**/def_left_pupil*') self.__lod500rPupil = self.__lod500Eyes.find( '**/def_right_pupil*') if self.__lod250Eyes.isEmpty(): self.__lod250Eyes = None else: self.__lod250Eyes.setColorOff() if not self.find('**/joint_pupilL*').isEmpty(): self.__lod250lPupil = self.__lod250Eyes.find( '**/joint_pupilL*') self.__lod250rPupil = self.__lod250Eyes.find( '**/joint_pupilR*') else: self.__lod250lPupil = self.__lod250Eyes.find( '**/def_left_pupil*') self.__lod250rPupil = self.__lod250Eyes.find( '**/def_right_pupil*') else: self.drawInFront('eyes*', 'head-front*', mode) if not self.find('joint_pupil*').isEmpty(): self.drawInFront('joint_pupil*', 'eyes*', -1) else: self.drawInFront('def_*_pupil', 'eyes*', -1) self.__eyes = self.find('**/eyes*') if not self.__eyes.isEmpty(): self.__eyes.setColorOff() self.__lpupil = None self.__rpupil = None if not self.find('**/joint_pupilL*').isEmpty(): if self.getLOD(1000): lp = self.getLOD(1000).find('**/joint_pupilL*') rp = self.getLOD(1000).find('**/joint_pupilR*') else: lp = self.find('**/joint_pupilL*') rp = self.find('**/joint_pupilR*') elif not self.getLOD(1000): lp = self.find('**/def_left_pupil*') rp = self.find('**/def_right_pupil*') else: lp = self.getLOD(1000).find('**/def_left_pupil*') rp = self.getLOD(1000).find('**/def_right_pupil*') if lp.isEmpty() or rp.isEmpty(): print('Unable to locate pupils.') else: leye = self.__eyes.attachNewNode('leye') reye = self.__eyes.attachNewNode('reye') lmat = Mat4(0.802174, 0.59709, 0, 0, -0.586191, 0.787531, 0.190197, 0, 0.113565, -0.152571, 0.981746, 0, -0.233634, 0.418062, 0.0196875, 1) leye.setMat(lmat) rmat = Mat4(0.786788, -0.617224, 0, 0, 0.602836, 0.768447, 0.214658, 0, -0.132492, -0.16889, 0.976689, 0, 0.233634, 0.418062, 0.0196875, 1) reye.setMat(rmat) self.__lpupil = leye.attachNewNode('lpupil') self.__rpupil = reye.attachNewNode('rpupil') lpt = self.__eyes.attachNewNode('') rpt = self.__eyes.attachNewNode('') lpt.wrtReparentTo(self.__lpupil) rpt.wrtReparentTo(self.__rpupil) lp.reparentTo(lpt) rp.reparentTo(rpt) self.__lpupil.adjustAllPriorities(1) self.__rpupil.adjustAllPriorities(1) if self.__lod500Eyes: self.__lod500lPupil.adjustAllPriorities(1) self.__lod500rPupil.adjustAllPriorities(1) if self.__lod250Eyes: self.__lod250lPupil.adjustAllPriorities(1) self.__lod250rPupil.adjustAllPriorities(1) animalType = style.getAnimal() if animalType != 'dog': self.__lpupil.flattenStrong() self.__rpupil.flattenStrong() def __setPupilDirection(self, x, y): if y < 0.0: y2 = -y left1 = self.LeftAD + (self.LeftD - self.LeftAD) * y2 left2 = self.LeftBC + (self.LeftC - self.LeftBC) * y2 right1 = self.RightAD + (self.RightD - self.RightAD) * y2 right2 = self.RightBC + (self.RightC - self.RightBC) * y2 else: y2 = y left1 = self.LeftAD + (self.LeftA - self.LeftAD) * y2 left2 = self.LeftBC + (self.LeftB - self.LeftBC) * y2 right1 = self.RightAD + (self.RightA - self.RightAD) * y2 right2 = self.RightBC + (self.RightB - self.RightBC) * y2 left0 = Point3( 0.0, 0.0, left1[2] - left1[0] * (left2[2] - left1[2]) / (left2[0] - left1[0])) right0 = Point3( 0.0, 0.0, right1[2] - right1[0] * (right2[2] - right1[2]) / (right2[0] - right1[0])) if x < 0.0: x2 = -x left = left0 + (left2 - left0) * x2 right = right0 + (right2 - right0) * x2 else: x2 = x left = left0 + (left1 - left0) * x2 right = right0 + (right1 - right0) * x2 self.__lpupil.setPos(left) self.__rpupil.setPos(right) def __lookPupilsAt(self, node, point): if node is not None: mat = node.getMat(self.__eyes) point = mat.xformPoint(point) distance = 1.0 recip_z = 1.0 / max(0.1, point[1]) x = distance * point[0] * recip_z y = distance * point[2] * recip_z x = min(max(x, -1), 1) y = min(max(y, -1), 1) self.__setPupilDirection(x, y) def __lookHeadAt(self, node, point, frac=1.0, lod=None): reachedTarget = 1 if lod is None: head = self.getPart('head', self.getLODNames()[0]) else: head = self.getPart('head', lod) if node is not None: headParent = head.getParent() mat = node.getMat(headParent) point = mat.xformPoint(point) rot = Mat3(0, 0, 0, 0, 0, 0, 0, 0, 0) lookAt(rot, Vec3(point), Vec3(0, 0, 1), CSDefault) scale = VBase3(0, 0, 0) hpr = VBase3(0, 0, 0) if decomposeMatrix(rot, scale, hpr, CSDefault): hpr = VBase3(min(max(hpr[0], -60), 60), min(max(hpr[1], -20), 30), 0) if frac != 1: currentHpr = head.getHpr() reachedTarget = abs(hpr[0] - currentHpr[0]) < 1.0 and abs( hpr[1] - currentHpr[1]) < 1.0 hpr = currentHpr + (hpr - currentHpr) * frac if lod is None: for lodName in self.getLODNames(): head = self.getPart('head', lodName) head.setHpr(hpr) else: head.setHpr(hpr) return reachedTarget def setupEyelashes(self, style): if style.getGender() == 'm': if self.__eyelashOpen: self.__eyelashOpen.removeNode() self.__eyelashOpen = None if self.__eyelashClosed: self.__eyelashClosed.removeNode() self.__eyelashClosed = None else: if self.__eyelashOpen: self.__eyelashOpen.removeNode() if self.__eyelashClosed: self.__eyelashClosed.removeNode() animal = style.head[0] model = loader.loadModel('phase_3' + EyelashDict[animal]) if self.hasLOD(): head = self.getPart('head', '1000') else: head = self.getPart('head', 'lodRoot') length = style.head[1] if length == 'l': openString = 'open-long' closedString = 'closed-long' else: openString = 'open-short' closedString = 'closed-short' self.__eyelashOpen = model.find('**/' + openString).copyTo(head) self.__eyelashClosed = model.find('**/' + closedString).copyTo(head) model.removeNode() def __fixHeadLongLong(self, style, lodName=None, copy=1): if lodName is None: searchRoot = self else: searchRoot = self.find('**/' + str(lodName)) otherParts = searchRoot.findAllMatches('**/*short*') for partNum in range(0, otherParts.getNumPaths()): if copy: otherParts.getPath(partNum).removeNode() else: otherParts.getPath(partNum).stash() def __fixHeadLongShort(self, style, lodName=None, copy=1): animalType = style.getAnimal() if lodName is None: searchRoot = self else: searchRoot = self.find('**/' + str(lodName)) if animalType != 'duck' and animalType != 'horse': if animalType == 'rabbit': if copy: searchRoot.find('**/ears-long').removeNode() else: searchRoot.find('**/ears-long').hide() elif copy: searchRoot.find('**/ears-short').removeNode() else: searchRoot.find('**/ears-short').hide() if animalType != 'rabbit': if copy: searchRoot.find('**/eyes-short').removeNode() else: searchRoot.find('**/eyes-short').hide() if animalType != 'dog': if copy: searchRoot.find('**/joint_pupilL_short').removeNode() searchRoot.find('**/joint_pupilR_short').removeNode() else: searchRoot.find('**/joint_pupilL_short').stash() searchRoot.find('**/joint_pupilR_short').stash() if copy: self.find('**/head-short').removeNode() self.find('**/head-front-short').removeNode() else: self.find('**/head-short').hide() self.find('**/head-front-short').hide() if animalType != 'rabbit': muzzleParts = searchRoot.findAllMatches('**/muzzle-long*') for partNum in range(0, muzzleParts.getNumPaths()): if copy: muzzleParts.getPath(partNum).removeNode() else: muzzleParts.getPath(partNum).hide() else: muzzleParts = searchRoot.findAllMatches('**/muzzle-short*') for partNum in range(0, muzzleParts.getNumPaths()): if copy: muzzleParts.getPath(partNum).removeNode() else: muzzleParts.getPath(partNum).hide() def __fixHeadShortLong(self, style, lodName=None, copy=1): animalType = style.getAnimal() if lodName is None: searchRoot = self else: searchRoot = self.find('**/' + str(lodName)) if animalType != 'duck' and animalType != 'horse': if animalType == 'rabbit': if copy: searchRoot.find('**/ears-short').removeNode() else: searchRoot.find('**/ears-short').hide() elif copy: searchRoot.find('**/ears-long').removeNode() else: searchRoot.find('**/ears-long').hide() if animalType != 'rabbit': if copy: searchRoot.find('**/eyes-long').removeNode() else: searchRoot.find('**/eyes-long').hide() if animalType != 'dog': if copy: searchRoot.find('**/joint_pupilL_long').removeNode() searchRoot.find('**/joint_pupilR_long').removeNode() else: searchRoot.find('**/joint_pupilL_long').stash() searchRoot.find('**/joint_pupilR_long').stash() if copy: searchRoot.find('**/head-long').removeNode() searchRoot.find('**/head-front-long').removeNode() else: searchRoot.find('**/head-long').hide() searchRoot.find('**/head-front-long').hide() if animalType != 'rabbit': muzzleParts = searchRoot.findAllMatches('**/muzzle-short*') for partNum in range(0, muzzleParts.getNumPaths()): if copy: muzzleParts.getPath(partNum).removeNode() else: muzzleParts.getPath(partNum).hide() else: muzzleParts = searchRoot.findAllMatches('**/muzzle-long*') for partNum in range(0, muzzleParts.getNumPaths()): if copy: muzzleParts.getPath(partNum).removeNode() else: muzzleParts.getPath(partNum).hide() def __fixHeadShortShort(self, style, lodName=None, copy=1): if lodName is None: searchRoot = self else: searchRoot = self.find('**/' + str(lodName)) otherParts = searchRoot.findAllMatches('**/*long*') for partNum in range(0, otherParts.getNumPaths()): if copy: otherParts.getPath(partNum).removeNode() else: otherParts.getPath(partNum).stash() def __blinkOpenEyes(self, task): if self.eyelids.getCurrentState().getName() == 'closed': self.eyelids.request('open') r = self.randGen.random() if r < 0.1: t = 0.2 else: t = r * 4.0 + 1.0 taskMgr.doMethodLater(t, self.__blinkCloseEyes, self.__blinkName) return task.done def __blinkCloseEyes(self, task): if self.eyelids.getCurrentState().getName() != 'open': taskMgr.doMethodLater(4.0, self.__blinkCloseEyes, self.__blinkName) else: self.eyelids.request('closed') taskMgr.doMethodLater(0.125, self.__blinkOpenEyes, self.__blinkName) return task.done def startBlink(self): taskMgr.remove(self.__blinkName) if self.__eyes: self.openEyes() taskMgr.doMethodLater(self.randGen.random() * 4.0 + 1, self.__blinkCloseEyes, self.__blinkName) def stopBlink(self): taskMgr.remove(self.__blinkName) if self.__eyes: self.eyelids.request('open') def closeEyes(self): self.eyelids.request('closed') def openEyes(self): self.eyelids.request('open') def surpriseEyes(self): self.eyelids.request('surprised') def sadEyes(self): self.__eyesOpen = ToonHead.EyesSadOpen self.__eyesClosed = ToonHead.EyesSadClosed def angryEyes(self): self.__eyesOpen = ToonHead.EyesAngryOpen self.__eyesClosed = ToonHead.EyesAngryClosed def normalEyes(self): self.__eyesOpen = ToonHead.EyesOpen self.__eyesClosed = ToonHead.EyesClosed def blinkEyes(self): taskMgr.remove(self.__blinkName) self.eyelids.request('closed') taskMgr.doMethodLater(0.1, self.__blinkOpenEyes, self.__blinkName) def __stareAt(self, task): frac = 2 * globalClock.getDt() reachedTarget = self.__lookHeadAt(self.__stareAtNode, self.__stareAtPoint, frac) self.__lookPupilsAt(self.__stareAtNode, self.__stareAtPoint) if reachedTarget and self.__stareAtNode is None: return task.done return task.cont def doLookAroundToStareAt(self, node, point): self.startStareAt(node, point) self.startLookAround() def startStareAtHeadPoint(self, point): self.startStareAt(self, point) def startStareAt(self, node, point): taskMgr.remove(self.__stareAtName) if self.lookAtTrack: self.lookAtTrack.finish() self.lookAtTrack = None self.__stareAtNode = node if point is not None: self.__stareAtPoint = point else: self.__stareAtPoint = self.__defaultStarePoint self.__stareAtTime = globalClock.getFrameTime() taskMgr.add(self.__stareAt, self.__stareAtName) def lerpLookAt(self, point, time=1.0, blink=0): taskMgr.remove(self.__stareAtName) if self.lookAtTrack: self.lookAtTrack.finish() self.lookAtTrack = None lodNames = self.getLODNames() if lodNames: lodName = lodNames[0] else: return 0 head = self.getPart('head', lodName) startHpr = head.getHpr() startLpupil = self.__lpupil.getPos() startRpupil = self.__rpupil.getPos() self.__lookHeadAt(None, point, lod=lodName) self.__lookPupilsAt(None, point) endHpr = head.getHpr() endLpupil = self.__lpupil.getPos() * 0.5 endRpupil = self.__rpupil.getPos() * 0.5 head.setHpr(startHpr) self.__lpupil.setPos(startLpupil) self.__rpupil.setPos(startRpupil) if startHpr.almostEqual(endHpr, 10): return 0 if blink: self.blinkEyes() lookToTgt_TimeFraction = 0.2 lookToTgtTime = time * lookToTgt_TimeFraction returnToEyeCenterTime = time - lookToTgtTime - 0.5 origin = Point3(0, 0, 0) blendType = 'easeOut' self.lookAtTrack = Parallel(Sequence( LerpPosInterval(self.__lpupil, lookToTgtTime, endLpupil, blendType=blendType), Wait(0.5), LerpPosInterval(self.__lpupil, returnToEyeCenterTime, origin, blendType=blendType)), Sequence( LerpPosInterval(self.__rpupil, lookToTgtTime, endRpupil, blendType=blendType), Wait(0.5), LerpPosInterval(self.__rpupil, returnToEyeCenterTime, origin, blendType=blendType)), name=self.__stareAtName) for lodName in self.getLODNames(): head = self.getPart('head', lodName) self.lookAtTrack.append( LerpHprInterval(head, time, endHpr, blendType='easeInOut')) self.lookAtTrack.start() return 1 def stopStareAt(self): self.lerpLookAt(Vec3.forward()) def stopStareAtNow(self): taskMgr.remove(self.__stareAtName) if self.lookAtTrack: self.lookAtTrack.finish() self.lookAtTrack = None if self.__lpupil and self.__rpupil: self.__setPupilDirection(0, 0) for lodName in self.getLODNames(): head = self.getPart('head', lodName) head.setHpr(0, 0, 0) def __lookAround(self, task): self.findSomethingToLookAt() t = self.randGen.random() * 4.0 + 3.0 taskMgr.doMethodLater(t, self.__lookAround, self.__lookName) return task.done def startLookAround(self): taskMgr.remove(self.__lookName) t = self.randGen.random() * 5.0 + 2.0 taskMgr.doMethodLater(t, self.__lookAround, self.__lookName) def stopLookAround(self): taskMgr.remove(self.__lookName) self.stopStareAt() def stopLookAroundNow(self): taskMgr.remove(self.__lookName) self.stopStareAtNow() def enterEyelidsOff(self): pass def exitEyelidsOff(self): pass def enterEyelidsOpen(self): if not self.__eyes.isEmpty(): self.__eyes.setTexture(self.__eyesOpen, 1) if self.__eyelashOpen: self.__eyelashOpen.show() if self.__eyelashClosed: self.__eyelashClosed.hide() if self.__lod500Eyes: self.__lod500Eyes.setTexture(self.__eyesOpen, 1) if self.__lod250Eyes: self.__lod250Eyes.setTexture(self.__eyesOpen, 1) if self.__lpupil: self.__lpupil.show() self.__rpupil.show() if self.__lod500lPupil: self.__lod500lPupil.show() self.__lod500rPupil.show() if self.__lod250lPupil: self.__lod250lPupil.show() self.__lod250rPupil.show() def exitEyelidsOpen(self): pass def enterEyelidsClosed(self): if not self.__eyes.isEmpty() and self.__eyesClosed: self.__eyes.setTexture(self.__eyesClosed, 1) if self.__eyelashOpen: self.__eyelashOpen.hide() if self.__eyelashClosed: self.__eyelashClosed.show() if self.__lod500Eyes: self.__lod500Eyes.setTexture(self.__eyesClosed, 1) if self.__lod250Eyes: self.__lod250Eyes.setTexture(self.__eyesClosed, 1) if self.__lpupil: self.__lpupil.hide() self.__rpupil.hide() if self.__lod500lPupil: self.__lod500lPupil.hide() self.__lod500rPupil.hide() if self.__lod250lPupil: self.__lod250lPupil.hide() self.__lod250rPupil.hide() def exitEyelidsClosed(self): pass def enterEyelidsSurprised(self): if not self.__eyes.isEmpty() and ToonHead.EyesSurprised: self.__eyes.setTexture(ToonHead.EyesSurprised, 1) if self.__eyelashOpen: self.__eyelashOpen.hide() if self.__eyelashClosed: self.__eyelashClosed.hide() if self.__lod500Eyes: self.__lod500Eyes.setTexture(ToonHead.EyesSurprised, 1) if self.__lod250Eyes: self.__lod250Eyes.setTexture(ToonHead.EyesSurprised, 1) if self.__muzzle: self.__muzzle.setTexture(ToonHead.MuzzleSurprised, 1) if self.__lpupil: self.__lpupil.show() self.__rpupil.show() if self.__lod500lPupil: self.__lod500lPupil.show() self.__lod500rPupil.show() if self.__lod250lPupil: self.__lod250lPupil.show() self.__lod250rPupil.show() def exitEyelidsSurprised(self): if self.__muzzle: self.__muzzle.setTexture(ToonHead.Muzzle, 1) def setupMuzzles(self, style): self.__muzzles = [] self.__surpriseMuzzles = [] self.__angryMuzzles = [] self.__sadMuzzles = [] self.__smileMuzzles = [] self.__laughMuzzles = [] def hideAddNonEmptyItemToList(item, list): if not item.isEmpty(): item.hide() list.append(item) if self.hasLOD(): for lodName in self.getLODNames(): animal = style.getAnimal() if animal != 'dog': muzzle = self.find('**/' + lodName + '/**/muzzle*neutral') else: muzzle = self.find('**/' + lodName + '/**/muzzle*') if lodName == '1000' or lodName == '500': filePrefix = DogMuzzleDict[style.head] muzzles = loader.loadModel('phase_3' + filePrefix + lodName) if not self.find( '**/' + lodName + '/**/__Actor_head/def_head').isEmpty(): muzzles.reparentTo( self.find('**/' + lodName + '/**/__Actor_head/def_head')) else: muzzles.reparentTo( self.find('**/' + lodName + '/**/joint_toHead')) surpriseMuzzle = self.find('**/' + lodName + '/**/muzzle*surprise') angryMuzzle = self.find('**/' + lodName + '/**/muzzle*angry') sadMuzzle = self.find('**/' + lodName + '/**/muzzle*sad') smileMuzzle = self.find('**/' + lodName + '/**/muzzle*smile') laughMuzzle = self.find('**/' + lodName + '/**/muzzle*laugh') self.__muzzles.append(muzzle) hideAddNonEmptyItemToList(surpriseMuzzle, self.__surpriseMuzzles) hideAddNonEmptyItemToList(angryMuzzle, self.__angryMuzzles) hideAddNonEmptyItemToList(sadMuzzle, self.__sadMuzzles) hideAddNonEmptyItemToList(smileMuzzle, self.__smileMuzzles) hideAddNonEmptyItemToList(laughMuzzle, self.__laughMuzzles) else: if style.getAnimal() != 'dog': muzzle = self.find('**/muzzle*neutral') else: muzzle = self.find('**/muzzle*') filePrefix = DogMuzzleDict[style.head] muzzles = loader.loadModel('phase_3' + filePrefix + '1000') if not self.find('**/def_head').isEmpty(): muzzles.reparentTo(self.find('**/def_head')) else: muzzles.reparentTo(self.find('**/joint_toHead')) surpriseMuzzle = self.find('**/muzzle*surprise') angryMuzzle = self.find('**/muzzle*angry') sadMuzzle = self.find('**/muzzle*sad') smileMuzzle = self.find('**/muzzle*smile') laughMuzzle = self.find('**/muzzle*laugh') self.__muzzles.append(muzzle) hideAddNonEmptyItemToList(surpriseMuzzle, self.__surpriseMuzzles) hideAddNonEmptyItemToList(angryMuzzle, self.__angryMuzzles) hideAddNonEmptyItemToList(sadMuzzle, self.__sadMuzzles) hideAddNonEmptyItemToList(smileMuzzle, self.__smileMuzzles) hideAddNonEmptyItemToList(laughMuzzle, self.__laughMuzzles) def getMuzzles(self): return self.__muzzles def getSurpriseMuzzles(self): return self.__surpriseMuzzles def getAngryMuzzles(self): return self.__angryMuzzles def getSadMuzzles(self): return self.__sadMuzzles def getSmileMuzzles(self): return self.__smileMuzzles def getLaughMuzzles(self): return self.__laughMuzzles def showNormalMuzzle(self): for muzzleNum in range(len(self.__muzzles)): self.__muzzles[muzzleNum].show() def hideNormalMuzzle(self): for muzzleNum in range(len(self.__muzzles)): self.__muzzles[muzzleNum].hide() def showAngryMuzzle(self): for muzzleNum in range(len(self.__angryMuzzles)): self.__angryMuzzles[muzzleNum].show() self.__muzzles[muzzleNum].hide() def hideAngryMuzzle(self): for muzzleNum in range(len(self.__angryMuzzles)): self.__angryMuzzles[muzzleNum].hide() self.__muzzles[muzzleNum].show() def showSadMuzzle(self): for muzzleNum in range(len(self.__sadMuzzles)): self.__sadMuzzles[muzzleNum].show() self.__muzzles[muzzleNum].hide() def hideSadMuzzle(self): for muzzleNum in range(len(self.__sadMuzzles)): self.__sadMuzzles[muzzleNum].hide() self.__muzzles[muzzleNum].show() def showSmileMuzzle(self): for muzzleNum in range(len(self.__smileMuzzles)): self.__smileMuzzles[muzzleNum].show() self.__muzzles[muzzleNum].hide() def hideSmileMuzzle(self): for muzzleNum in range(len(self.__smileMuzzles)): self.__smileMuzzles[muzzleNum].hide() self.__muzzles[muzzleNum].show() def showLaughMuzzle(self): for muzzleNum in range(len(self.__laughMuzzles)): self.__laughMuzzles[muzzleNum].show() self.__muzzles[muzzleNum].hide() def hideLaughMuzzle(self): for muzzleNum in range(len(self.__laughMuzzles)): self.__laughMuzzles[muzzleNum].hide() self.__muzzles[muzzleNum].show() def showSurpriseMuzzle(self): for muzzleNum in range(len(self.__surpriseMuzzles)): self.__surpriseMuzzles[muzzleNum].show() self.__muzzles[muzzleNum].hide() def hideSurpriseMuzzle(self): for muzzleNum in range(len(self.__surpriseMuzzles)): self.__surpriseMuzzles[muzzleNum].hide() self.__muzzles[muzzleNum].show()
class CogInvasionClientRepository(AstronClientRepository): notify = directNotify.newCategory('CIClientRepository') GameGlobalsId = DO_ID_COGINVASION SetZoneDoneEvent = 'CICRSetZoneDone' EmuSetZoneDoneEvent = 'CICREmuSetZoneDone' SetInterest = 'Set' ClearInterest = 'Clear' ClearInterestDoneEvent = 'CICRClearInterestDone' ITAG_PERM = 'perm' ITAG_AVATAR = 'avatar' ITAG_SHARD = 'shard' ITAG_WORLD = 'world' ITAG_GAME = 'game' def __init__(self, music, serverVersion): self.music = music self.serverVersion = serverVersion AstronClientRepository.__init__(self, ['phase_3/etc/direct.dc', 'phase_3/etc/toon.dc']) self.loginFSM = ClassicFSM('login', [State('off', self.enterOff, self.exitOff), State('connect', self.enterConnect, self.exitConnect), State('disconnect', self.enterDisconnect, self.exitDisconnect), State('avChoose', self.enterAvChoose, self.exitAvChoose), State('playingGame', self.enterPlayingGame, self.exitPlayingGame), State('serverUnavailable', self.enterServerUnavailable, self.exitServerUnavailable), State('makeAToon', self.enterMakeAToon, self.exitMakeAToon), State('submitNewToon', self.enterSubmitNewToon, self.exitSubmitNewToon), State('noShards', self.enterNoShards, self.exitNoShards), State('waitForSetAvatarResponse', self.enterWaitForSetAvatarResponse, self.exitWaitForSetAvatarResponse), State('waitForShardList', self.enterWaitForShardList, self.exitWaitForShardList), State('ejected', self.enterEjected, self.exitEjected), State('districtReset', self.enterDistrictReset, self.exitDistrictReset), State('died', self.enterDied, self.exitDied), State('betaInform', self.enterBetaInform, self.exitBetaInform)], 'off', 'off') self.loginFSM.enterInitialState() self.gameFSM = ClassicFSM('game', [State('off', self.enterGameOff, self.exitGameOff), State('waitForGameEnterResponse', self.enterWaitForGameEnterResponse, self.exitWaitForGameEnterResponse), State('playGame', self.enterPlayGame, self.exitPlayGame), State('closeShard', self.enterCloseShard, self.exitCloseShard), State('switchShards', self.enterSwitchShards, self.exitSwitchShards)], 'off', 'off') self.gameFSM.enterInitialState() self.avChooser = AvChooser(self.loginFSM) self.playGame = PlayGame(self.gameFSM, 'playGameDone') self.hoodMgr = HoodMgr() self.makeAToon = MakeAToon() self.loginToken = os.environ.get('LOGIN_TOKEN') self.serverAddress = os.environ.get('GAME_SERVER') self.serverURL = URLSpec('http://%s' % self.serverAddress) self.parentMgr.registerParent(CIGlobals.SPRender, render) self.parentMgr.registerParent(CIGlobals.SPHidden, hidden) self.adminAccess = False self.localAvChoice = None self.SuitsActive = 0 self.BossActive = 0 self.accServerTimesNA = 0 self.maxAccServerTimesNA = 10 self.setZonesEmulated = 0 self.old_setzone_interest_handle = None self.setZoneQueue = Queue() self.accept(self.SetZoneDoneEvent, self._handleEmuSetZoneDone) self.handler = None self.__currentAvId = 0 self.myDistrict = None self.activeDistricts = {} self.shardListHandle = None self.uberZoneInterest = None self.isShowingPlayerIds = False self.doBetaInform = True self.dTutorial = None self.requestedName = None self.whisperNoise = base.loadSfx('phase_3.5/audio/sfx/GUI_whisper_3.ogg') self.checkHttp() base.audio3d = Audio3DManager(base.sfxManagerList[0], camera) base.audio3d.setDropOffFactor(0) base.audio3d.setDopplerFactor(3.0) base.lifter = CollisionHandlerFloor() base.pusher = CollisionHandlerPusher() base.queue = CollisionHandlerQueue() base.minigame = None base.finalExitCallbacks.insert(0, self.__handleExit) self.csm = self.generateGlobalObject(DO_ID_CLIENT_SERVICES_MANAGER, 'ClientServicesManager') self.friendsManager = self.generateGlobalObject(DO_ID_FRIENDS_MANAGER, 'FriendsManager') SpeedHackChecker.startChecking() self.loginFSM.request('connect') return def __handleExit(self): try: base.localAvatar.b_setAnimState('teleportOut') except: pass self.gameFSM.request('closeShard', ['off']) def showPlayerIds(self): print 'Showing player ids...' self.isShowingPlayerIds = True for av in self.doId2do.values(): if av.__class__.__name__ in ('DistributedToon', 'LocalToon', 'DistributedSuit'): av.showAvId() def hidePlayerIds(self): print 'Hiding player ids...' self.isShowingPlayerIds = False for av in self.doId2do.values(): if av.__class__.__name__ in ('DistributedToon', 'LocalToon', 'DistributedSuit'): av.showName() def sendSetLocation(self, doId, parentId, zoneId): dg = PyDatagram() dg.addUint16(CLIENT_OBJECT_LOCATION) dg.addUint32(doId) dg.addUint32(parentId) dg.addUint32(zoneId) self.send(dg) def getNextSetZoneDoneEvent(self): return '%s-%s' % (self.EmuSetZoneDoneEvent, self.setZonesEmulated + 1) def getLastSetZoneDoneEvent(self): return '%s-%s' % (self.EmuSetZoneDoneEvent, self.setZonesEmulated) def getQuietZoneLeftEvent(self): return 'leftQuietZone-%s' % (id(self),) def sendSetZoneMsg(self, zoneId, visibleZoneList=None): event = self.getNextSetZoneDoneEvent() self.setZonesEmulated += 1 parentId = base.localAvatar.defaultShard self.sendSetLocation(base.localAvatar.doId, parentId, zoneId) localAvatar.setLocation(parentId, zoneId) interestZones = zoneId if visibleZoneList is not None: interestZones = visibleZoneList self._addInterestOpToQueue(self.SetInterest, [parentId, interestZones, 'OldSetZoneEmulator'], event) return def resetInterestStateForConnectionLoss(self): self.old_setzone_interest_handle = None self.setZoneQueue.clear() return def _removeEmulatedSetZone(self, doneEvent): self._addInterestOpToQueue(self.ClearInterest, None, doneEvent) return def _addInterestOpToQueue(self, op, args, event): self.setZoneQueue.push([op, args, event]) if len(self.setZoneQueue) == 1: self._sendNextSetZone() def _sendNextSetZone(self): op, args, event = self.setZoneQueue.top() if op == self.SetInterest: parentId, interestZones, name = args if self.old_setzone_interest_handle == None: self.old_setzone_interest_handle = self.addInterest(parentId, interestZones, name, self.SetZoneDoneEvent) else: self.alterInterest(self.old_setzone_interest_handle, parentId, interestZones, name, self.SetZoneDoneEvent) else: if op == self.ClearInterest: self.removeInterest(self.old_setzone_interest_handle, self.SetZoneDoneEvent) self.old_setzone_interest_handle = None else: self.notify.error('unknown setZone op: %s' % op) return def _handleEmuSetZoneDone(self): op, args, event = self.setZoneQueue.pop() queueIsEmpty = self.setZoneQueue.isEmpty() if event is not None: messenger.send(event) if not queueIsEmpty: self._sendNextSetZone() return def enterSwitchShards(self, shardId, hoodId, zoneId, avId): self._switchShardParams = [ shardId, hoodId, zoneId, avId] self.removeShardInterest(self._handleOldShardGone) def _handleOldShardGone(self): status = {} status['hoodId'] = self._switchShardParams[1] status['zoneId'] = self._switchShardParams[2] status['avId'] = self._switchShardParams[3] print status['avId'] self.gameFSM.request('waitForGameEnterResponse', [status, self._switchShardParams[0]]) def exitSwitchShards(self): del self._switchShardParams def enterBetaInform(self): msg = 'There may be some features that are present in the game, but are neither finished nor fully functional yet.\n\nAre you sure you want to enter?' self.dialog = GlobalDialog(message=msg, style=1, doneEvent='gameEnterChoice') self.dialog.show() self.acceptOnce('gameEnterChoice', self.handleGameEnterChoice) def handleGameEnterChoice(self): value = self.dialog.getValue() if value: self.loginFSM.request('avChoose') else: sys.exit() def exitBetaInform(self): self.ignore('gameEnterChoice') self.dialog.cleanup() del self.dialog def enterCloseShard(self, nextState='avChoose'): self.setNoNewInterests(True) self._removeLocalAvFromStateServer(nextState) def exitCloseShard(self): self.setNoNewInterests(False) self.ignore(self.ClearInterestDoneEvent) def _removeLocalAvFromStateServer(self, nextState): self.sendSetAvatarIdMsg(0) self._removeAllOV() callback = Functor(self.loginFSM.request, nextState) self.removeShardInterest(callback) def removeShardInterest(self, callback): self._removeCurrentShardInterest(Functor(self._removeShardInterestComplete, callback)) def _removeShardInterestComplete(self, callback): self.cache.flush() self.doDataCache.flush() callback() def _removeCurrentShardInterest(self, callback): if self.old_setzone_interest_handle is None: callback() return self.acceptOnce(self.ClearInterestDoneEvent, Functor(self._removeCurrentUberZoneInterest, callback)) self._removeEmulatedSetZone(self.ClearInterestDoneEvent) return def _removeCurrentUberZoneInterest(self, callback): self.acceptOnce(self.ClearInterestDoneEvent, Functor(self._removeShardInterestDone, callback)) self.removeInterest(self.uberZoneInterest, self.ClearInterestDoneEvent) def _removeShardInterestDone(self, callback): self.uberZoneInterest = None callback() return def _removeAllOV(self): owners = self.doId2ownerView.keys() for doId in owners: self.disableDoId(doId, ownerView=True) def enterDied(self): self.deathDialog = GlobalDialog(message=CIGlobals.SuitDefeatMsg, style=2, doneEvent='deathChoice') self.deathDialog.show() self.acceptOnce('deathChoice', self.handleDeathChoice) def handleDeathChoice(self): value = self.deathDialog.getValue() if value: self.loginFSM.request('avChoose') else: sys.exit() def exitDied(self): self.deathDialog.cleanup() del self.deathDialog self.ignore('deathChoice') def enterConnect(self): self.connectingDialog = GlobalDialog(message=CIGlobals.ConnectingMsg) self.connectingDialog.show() self.connect([self.serverURL], successCallback=self.handleConnected, failureCallback=self.handleConnectFail) def handleConnected(self): self.notify.info('Sending CLIENT_HELLO...') self.acceptOnce('CLIENT_HELLO_RESP', self.handleClientHelloResp) self.acceptOnce('CLIENT_EJECT', self.handleEjected) self.acceptOnce('LOST_CONNECTION', self.handleLostConnection) AstronClientRepository.sendHello(self, self.serverVersion) def handleLostConnection(self): self.deleteAllObjects() self.loginFSM.request('disconnect', [1]) def deleteAllObjects(self): for doId in self.doId2do.keys(): obj = self.doId2do[doId] if hasattr(base, 'localAvatar'): if doId != base.localAvatar.doId: if obj.__class__.__name__ not in ('ClientServicesManager', 'DistributedDistrict', 'FriendsManager', 'HolidayManager', 'NameServicesManager'): self.deleteObject(doId) else: self.deleteObject(doId) def handleEjected(self, errorCode, reason): self.notify.info('OMG I WAS EJECTED!') self.ignore('LOST_CONNECTION') errorMsg = ErrorCode2ErrorMsg.get(errorCode, None) or UnknownErrorMsg % errorCode self.loginFSM.request('ejected', [errorMsg]) return def handleClientHelloResp(self): self.notify.info('Got CLIENT_HELLO_RESP!') self.acceptOnce(self.csm.getLoginAcceptedEvent(), self.handleLoginAccepted) self.csm.d_requestLogin(self.loginToken) def handleLoginAccepted(self): self.notify.info('Woo-hoo, I am authenticated!') base.cr.holidayManager = self.generateGlobalObject(DO_ID_HOLIDAY_MANAGER, 'HolidayManager') base.cr.nameServicesManager = self.generateGlobalObject(DO_ID_NAME_SERVICES_MANAGER, 'NameServicesManager') self.loginFSM.request('waitForShardList') def handleConnectFail(self, foo1, foo2): self.notify.info('Could not connect to gameserver, notifying user.') self.connectingDialog.cleanup() self.connectingDialog = GlobalDialog(message=CIGlobals.NoConnectionMsg % self.serverAddress + ' ' + CIGlobals.TryAgain, style=2, doneEvent='connectFail') self.connectingDialog.show() self.acceptOnce('connectFail', self.handleConnectFailButton) def handleConnectFailButton(self): value = self.connectingDialog.getValue() if value: self.loginFSM.request('connect') else: sys.exit() def exitConnect(self): self.ignore('connectFail') self.ignore('CLIENT_HELLO_RESP') self.ignore(self.csm.getLoginAcceptedEvent()) self.connectingDialog.cleanup() del self.connectingDialog def enterEjected(self, errorMsg): self.ejectDialog = GlobalDialog(message=errorMsg, style=3, doneEvent='ejectDone') self.ejectDialog.show() self.acceptOnce('ejectDone', sys.exit) def exitEjected(self): self.ignore('ejectDone') self.ejectDialog.cleanup() del self.ejectDialog def enterServerUnavailable(self): self.notify.info(CIGlobals.ServerUnavailable) self.serverNA = GlobalDialog(message=CIGlobals.ServerUnavailable, style=4, doneEvent='serverNAEvent') self.serverNA.show() self.acceptOnce('serverNAEvent', sys.exit) self.startServerNAPoll() def startServerNAPoll(self): self.notify.info('Starting server poll...') self.accServerTimesNA = 1 taskMgr.add(self.serverNAPoll, 'serverNAPoll') def serverNAPoll(self, task): dg = PyDatagram() dg.addUint16(ACC_IS_SERVER_UP) self.send(dg) task.delayTime = 3.0 return Task.again def __handleServerNAResp(self, resp): if resp == ACC_SERVER_UP: taskMgr.remove('serverNAPoll') self.loginFSM.request(self.loginFSM.getLastState().getName()) else: self.accServerTimesNA += 1 if self.accServerTimesNA >= self.maxAccServerTimesNA: taskMgr.remove('serverNAPoll') self.notify.info('Giving up on polling account server after %s times.' % self.accServerTimesNA) self.loginFSM.request('disconnect', enterArgList=[1]) self.accServerTimesNA = 0 def exitServerUnavailable(self): self.ignore('serverNAEvent') self.serverNA.cleanup() del self.serverNA def enterOff(self): pass def exitOff(self): pass def enterAvChoose(self): ModelPool.garbageCollect() TexturePool.garbageCollect() self.avChooser.load() self.avChooser.enter() if not self.music: self.music = base.loadMusic(CIGlobals.getThemeSong()) base.playMusic(self.music, volume=0.75, looping=1) self.accept('enterMakeAToon', self.__handleMakeAToonReq) self.accept('avChooseDone', self.__handleAvChooseDone) def __handleMakeAToonReq(self, slot): self.loginFSM.request('makeAToon', [slot]) def __handleAvChooseDone(self, avChoice): print '------- AvChooseDone -------' print 'Toon name: %s' % avChoice.getName() print 'Slot: %s' % avChoice.getSlot() print 'DNA: %s' % avChoice.getDNA() self.loginFSM.request('waitForSetAvatarResponse', [avChoice]) def exitAvChoose(self): self.avChooser.exit() self.avChooser.unload() self.ignore('enterMakeAToon') self.ignore('avChooseDone') def handlePlayGame(self, msgType, di): if msgType == CLIENT_ENTER_OBJECT_REQUIRED_OTHER_OWNER: self.handleGenerateWithRequiredOtherOwner(msgType, di) else: AstronClientRepository.handleDatagram(self, di) def enterPlayingGame(self): zoneId = localAvatar.getLastHood() hoodId = ZoneUtil.getHoodId(zoneId) status = {'hoodId': hoodId, 'zoneId': zoneId, 'avId': self.localAvId} shardId = self.myDistrict.doId self.gameFSM.request('waitForGameEnterResponse', [status, shardId]) def exitPlayingGame(self): self.deleteAllObjects() self.handler = None self.gameFSM.request('off') if hasattr(base, 'localAvatar'): camera.reparentTo(render) camera.setPos(0, 0, 0) camera.setHpr(0, 0, 0) del base.localAvatar del __builtins__['localAvatar'] self.localAvChoice = None if loader.inBulkBlock: loader.endBulkLoad(loader.blockName) return def enterNoShards(self): self.noShardDialog = GlobalDialog(message=CIGlobals.NoShardsMsg + ' ' + CIGlobals.TryAgain, style=2, doneEvent='noShardsDone') self.noShardDialog.show() self.acceptOnce('noShardsDone', self.handleNoShardsDone) def handleNoShardsDone(self): value = self.noShardDialog.getValue() if value: self.loginFSM.request('waitForShardList') else: sys.exit() def exitNoShards(self): self.noShardDialog.cleanup() del self.noShardDialog self.ignore('noShardsDone') def enterWaitForShardList(self): self.shardListHandle = self.addTaggedInterest(self.GameGlobalsId, CIGlobals.DistrictZone, self.ITAG_PERM, 'localShardList', event='shardList_complete') self.acceptOnce('shardList_complete', self._handleShardListComplete) def _handleShardListComplete(self): if self._shardsAreAvailable(): self.myDistrict = self._chooseAShard() if self.doBetaInform: self.loginFSM.request('betaInform') else: self.loginFSM.request('avChoose') taskMgr.add(self.monitorDistrict, 'monitorMyDistrict') else: self.loginFSM.request('noShards') def monitorDistrict(self, task): if self.myDistrict is None and self.isConnected(): self.loginFSM.request('districtReset') return task.done return task.cont def _shardsAreAvailable(self): for shard in self.activeDistricts.values(): if shard.available: return True return False def _chooseAShard(self): choices = [] for shard in self.activeDistricts.values(): choices.append(shard) return random.choice(choices) def exitWaitForShardList(self): self.ignore('shardList_complete') def enterDistrictReset(self): self.districtResetDialog = GlobalDialog(message=CIGlobals.DistrictResetMsg, style=3, doneEvent='distresetdone') self.districtResetDialog.show() self.acceptOnce('distresetdone', sys.exit) def exitDistrictReset(self): self.districtResetDialog.cleanup() del self.districtResetDialog def enterWaitForSetAvatarResponse(self, choice): self.sendSetAvatarMsg(choice) def enterLoadDone(self): self.loginFSM.request('playingGame') def __handleSetAvatarResponse(self, avId, di): print 'Entering game...' enterLoad = EnterLoad(self.enterLoadDone) dclass = self.dclassesByName['DistributedToon'] localAvatar = LocalToon.LocalToon(base.cr) localAvatar.dclass = dclass base.localAvatar = localAvatar __builtins__['localAvatar'] = base.localAvatar localAvatar.doId = avId self.localAvId = avId parentId = None zoneId = None localAvatar.setLocation(parentId, zoneId) localAvatar.generateInit() localAvatar.generate() dclass.receiveUpdateBroadcastRequiredOwner(localAvatar, di) localAvatar.announceGenerate() localAvatar.postGenerateMessage() self.doId2do[avId] = localAvatar localAvatar.hoodsDiscovered = [ 1000, 2000, 3000, 4000, 5000, 9000] localAvatar.teleportAccess = [1000, 2000, 3000, 4000, 5000, 9000] enterLoad.load() del enterLoad return def exitWaitForSetAvatarResponse(self): self.ignore(self.csm.getSetAvatarEvent()) def enterWaitForGameEnterResponse(self, status, shardId): if shardId is not None: district = self.activeDistricts[shardId] else: district = None if not district: self.loginFSM.request('noShards') return self.myDistrict = district self.notify.info('Entering shard %s' % shardId) localAvatar.setLocation(shardId, status['zoneId']) localAvatar.defaultShard = shardId self.handleEnteredShard(status) return def handleEnteredShard(self, status): self.uberZoneInterest = self.addInterest(localAvatar.defaultShard, CIGlobals.UberZone, 'uberZone', 'uberZoneInterestComplete') self.acceptOnce('uberZoneInterestComplete', self.uberZoneInterestComplete, [status]) def uberZoneInterestComplete(self, status): self.__gotTimeSync = 0 if self.timeManager == None: print 'No time manager' DistributedSmoothNode.globalActivateSmoothing(0, 0) self.gotTimeSync(status) else: print 'Time manager found' DistributedSmoothNode.globalActivateSmoothing(1, 0) if self.timeManager.synchronize('startup'): self.accept('gotTimeSync', self.gotTimeSync, [status]) else: self.gotTimeSync(status) return def exitWaitForGameEnterResponse(self): self.ignore('uberZoneInterestComplete') def gotTimeSync(self, status): self.notify.info('gotTimeSync') self.ignore('gotTimeSync') self.__gotTimeSync = 1 self.prepareToEnter(status) def prepareToEnter(self, status): if not self.__gotTimeSync: self.notify.info('still waiting for time sync') return self.gameFSM.request('playGame', [status]) def enterMakeAToon(self, slot): if self.music: self.music.stop() self.music = None self.makeAToon.setSlot(slot) self.makeAToon.loadEnviron() self.makeAToon.load() self.makeAToon.matFSM.request('genderShop') self.acceptOnce('quitCreateAToon', self.__handleMakeAToonQuit) self.acceptOnce('createAToonFinished', self.__handleMakeAToonDone) return def __handleMakeAToonQuit(self): self.loginFSM.request('avChoose') def __handleMakeAToonDone(self, dnaStrand, slot, name): self.loginFSM.request('submitNewToon', enterArgList=[dnaStrand, slot, name]) def exitMakeAToon(self): self.makeAToon.setSlot(-1) self.makeAToon.enterExit(None) self.ignore('quitCreateAToon') self.ignore('createAToonFinished') return def enterSubmitNewToon(self, dnaStrand, slot, name, skipTutorial=0): self.submittingDialog = GlobalDialog(message=CIGlobals.Submitting) self.submittingDialog.show() self.acceptOnce(self.csm.getToonCreatedEvent(), self.__handleSubmitNewToonResp) self.csm.sendSubmitNewToon(dnaStrand, slot, name, skipTutorial) def __handleSubmitNewToonResp(self, avId): if self.requestedName is not None: self.nameServicesManager.d_requestName(self.requestedName, avId) self.requestedName = None self.loginFSM.request('avChoose') return def exitSubmitNewToon(self): self.ignore(self.csm.getToonCreatedEvent()) self.submittingDialog.cleanup() del self.submittingDialog def enterGameOff(self): pass def exitGameOff(self): pass def enterPlayGame(self, status): if self.music: self.music.stop() self.music = None base.transitions.noFade() if self.localAvChoice == None: self.notify.error('called enterPlayGame() without self.localAvChoice being set!') return if localAvatar.getTutorialCompleted() == 1 or True: zoneId = status['zoneId'] hoodId = status['hoodId'] avId = status['avId'] self.playGame.load() self.playGame.enter(hoodId, zoneId, avId) else: self.sendQuietZoneRequest() localAvatar.sendUpdate('createTutorial') self.myDistrict.d_joining() return def tutorialCreated(self, zoneId): requestStatus = {'zoneId': zoneId} self.tutQuietZoneState = QuietZoneState('tutQuietZoneDone') self.tutQuietZoneState.load() self.tutQuietZoneState.enter(requestStatus) self.acceptOnce('tutQuietZoneDone', self.__handleTutQuietZoneDone) def __handleTutQuietZoneDone(self): self.tutQuietZoneState.exit() self.tutQuietZoneState.unload() del self.tutQuietZoneState def exitPlayGame(self): self.ignore('tutQuietZoneDone') if hasattr(self, 'tutQuietZoneDone'): self.tutQuietZoneState.exit() self.tutQuietZoneState.unload() del self.tutQuietZoneState if self.music: self.music.stop() self.music = None self.playGame.exit() self.playGame.unload() return def enterDisconnect(self, isPlaying, booted=0, bootReason=None): self.notify.info('Disconnect details: isPlaying = %s, booted = %s, bootReason = %s' % ( isPlaying, booted, bootReason)) style = 3 if isPlaying == 1: if not booted: msg = CIGlobals.DisconnectionMsg else: if not booted: msg = CIGlobals.JoinFailureMsg if self.isConnected(): self.sendDisconnect() self.disconnectDialog = GlobalDialog(message=msg, style=style, doneEvent='disconnectDone') self.disconnectDialog.show() if style == 3: self.acceptOnce('disconnectDone', sys.exit) else: self.acceptOnce('disconnectDone', self.handleDisconnectDone) def handleDisconnectDone(self): value = self.disconnectDialog.getValue() if value: self.loginFSM.request('connect') else: sys.exit() def exitDisconnect(self): self.ignore('disconnectDone') self.disconnectDialog.cleanup() del self.disconnectDialog def renderFrame(self): gsg = base.win.getGsg() if gsg: render2d.prepareScene(gsg) base.graphicsEngine.renderFrame() def handleDatagram(self, di): if self.notify.getDebug(): print 'ClientRepository received datagram:' msgType = self.getMsgType() self.currentSenderId = None if self.handler == None: self.astronHandle(di) else: self.handler(msgType, di) self.considerHeartbeat() return def astronHandle(self, di): AstronClientRepository.handleDatagram(self, di) def handleQuietZoneGenerateWithRequired(self, di): doId = di.getUint32() parentId = di.getUint32() zoneId = di.getUint32() classId = di.getUint16() dclass = self.dclassesByNumber[classId] if dclass.getClassDef().neverDisable: dclass.startGenerate() distObj = self.generateWithRequiredFields(dclass, doId, di, parentId, zoneId) dclass.stopGenerate() def handleQuietZoneGenerateWithRequiredOther(self, di): doId = di.getUint32() parentId = di.getUint32() zoneId = di.getUint32() classId = di.getUint16() dclass = self.dclassesByNumber[classId] if dclass.getClassDef().neverDisable: dclass.startGenerate() distObj = self.generateWithRequiredOtherFields(dclass, doId, di, parentId, zoneId) dclass.stopGenerate() def handleQuietZoneUpdateField(self, di): di2 = DatagramIterator(di) doId = di2.getUint32() if doId in self.deferredDoIds: args, deferrable, dg0, updates = self.deferredDoIds[doId] dclass = args[2] if not dclass.getClassDef().neverDisable: return else: do = self.getDo(doId) if do: if not do.neverDisable: return AstronClientRepository.handleUpdateField(self, di) def handleDelete(self, di): doId = di.getUint32() self.deleteObject(doId) def _abandonShard(self): for doId, obj in self.doId2do.items(): if obj.parentId == localAvatar.defaultShard and obj is not localAvatar: self.deleteObject(doId) def handleEnterObjectRequiredOwner(self, di): if self.loginFSM.getCurrentState().getName() == 'waitForSetAvatarResponse': doId = di.getUint32() parentId = di.getUint32() zoneId = di.getUint32() dclassId = di.getUint16() self.__handleSetAvatarResponse(doId, di) def addTaggedInterest(self, parentId, zoneId, mainTag, desc, otherTags=[], event=None): return self.addInterest(parentId, zoneId, desc, event) def sendSetAvatarMsg(self, choice): avId = choice.getAvId() self.sendSetAvatarIdMsg(avId) self.localAvChoice = choice def sendSetAvatarIdMsg(self, avId): if avId != self.__currentAvId: self.__currentAvId = avId self.csm.sendSetAvatar(avId) def sendQuietZoneRequest(self): self.sendSetZoneMsg(CIGlobals.QuietZone)
class Char(Avatar.Avatar): def __init__(self): try: self.Char_initialized return except: self.Char_initialized = 1 Avatar.Avatar.__init__(self) self.avatarType = CIGlobals.CChar self.avatarName = None self.currentAnim = None self.charType = '' self.eyes = loader.loadTexture('phase_3/maps/eyes1.jpg', 'phase_3/maps/eyes1_a.rgb') self.closedEyes = loader.loadTexture('phase_3/maps/mickey_eyes_closed.jpg', 'phase_3/maps/mickey_eyes_closed_a.rgb') self.animFSM = ClassicFSM('Char', [State('off', self.enterOff, self.exitOff), State('neutral', self.enterNeutral, self.exitNeutral), State('walk', self.enterWalk, self.exitWalk), State('run', self.enterRun, self.exitRun)], 'off', 'off') animStateList = self.animFSM.getStates() self.animFSM.enterInitialState() Avatar.Avatar.initializeBodyCollisions(self, self.avatarType, 3.5, 1) return def getNametagJoints(self): return [] def stopAnimations(self): if hasattr(self, 'animFSM'): if not self.animFSM.isInternalStateInFlux(): self.animFSM.request('off') else: notify.warning('animFSM in flux, state=%s, not requesting off' % self.animFSM.getCurrentState().getName()) else: notify.warning('animFSM has been deleted') def disable(self): self.stopBlink() self.stopAnimations() Avatar.Avatar.disable(self) def delete(self): try: self.Char_deleted except: self.Char_deleted = 1 del self.animFSM Avatar.Avatar.delete(self) def setChat(self, chatString): if self.charType == CIGlobals.Mickey: self.dial = base.audio3d.loadSfx('phase_3/audio/dial/mickey.ogg') else: if self.charType == CIGlobals.Minnie: self.dial = base.audio3d.loadSfx('phase_3/audio/dial/minnie.ogg') else: if self.charType == CIGlobals.Goofy: self.dial = base.audio3d.loadSfx('phase_6/audio/dial/goofy.ogg') base.audio3d.attachSoundToObject(self.dial, self) self.dial.play() Avatar.Avatar.setChat(self, chatString) def setName(self, nameString, charName=None): self.avatarName = nameString Avatar.Avatar.setName(self, nameString, avatarType=self.avatarType, charName=charName) def setupNameTag(self, tempName=None): Avatar.Avatar.setupNameTag(self, tempName) self.nametag.setNametagColor(NametagGlobals.NametagColors[NametagGlobals.CCNPC]) self.nametag.setActive(0) self.nametag.updateAll() def generateChar(self, charType): self.charType = charType if charType == CIGlobals.Mickey or charType == CIGlobals.Minnie: self.loadModel('phase_3/models/char/' + charType.lower() + '-' + str(CIGlobals.ModelDetail(self.avatarType)) + '.bam') self.loadAnims({'neutral': 'phase_3/models/char/' + charType.lower() + '-wait.bam', 'walk': 'phase_3/models/char/' + charType.lower() + '-walk.bam', 'run': 'phase_3/models/char/' + charType.lower() + '-run.bam', 'left-start': 'phase_3.5/models/char/' + charType.lower() + '-left-start.bam', 'left': 'phase_3.5/models/char/' + charType.lower() + '-left.bam', 'right-start': 'phase_3.5/models/char/' + charType.lower() + '-right-start.bam', 'right': 'phase_3.5/models/char/' + charType.lower() + '-right.bam'}) if charType == CIGlobals.Mickey: self.mickeyEye = self.controlJoint(None, 'modelRoot', 'joint_pupilR') self.mickeyEye.setY(0.025) for bundle in self.getPartBundleDict().values(): bundle = bundle['modelRoot'].getBundle() earNull = bundle.findChild('sphere3') if not earNull: earNull = bundle.findChild('*sphere3') earNull.clearNetTransforms() for bundle in self.getPartBundleDict().values(): charNodepath = bundle['modelRoot'].partBundleNP bundle = bundle['modelRoot'].getBundle() earNull = bundle.findChild('sphere3') if not earNull: earNull = bundle.findChild('*sphere3') ears = charNodepath.find('**/sphere3') if ears.isEmpty(): ears = charNodepath.find('**/*sphere3') ears.clearEffect(CharacterJointEffect.getClassType()) earRoot = charNodepath.attachNewNode('earRoot') earPitch = earRoot.attachNewNode('earPitch') earPitch.setP(40.0) ears.reparentTo(earPitch) earNull.addNetTransform(earRoot.node()) ears.clearMat() ears.node().setPreserveTransform(ModelNode.PTNone) ears.setP(-40.0) ears.flattenMedium() ears.setBillboardAxis() self.startBlink() else: if charType == CIGlobals.Pluto: self.loadModel('phase_6/models/char/pluto-1000.bam') self.loadAnims({'walk': 'phase_6/models/char/pluto-walk.bam', 'neutral': 'phase_6/models/char/pluto-neutral.bam', 'sit': 'phase_6/models/char/pluto-sit.bam', 'stand': 'phase_6/models/char/pluto-stand.bam'}) else: if charType == CIGlobals.Goofy: self.loadModel('phase_6/models/char/TT_G-1500.bam') self.loadAnims({'neutral': 'phase_6/models/char/TT_GWait.bam', 'walk': 'phase_6/models/char/TT_GWalk.bam'}) else: raise StandardError('unknown char %s!' % charType) Avatar.Avatar.initShadow(self) return def initializeLocalCollisions(self, name, radius): Avatar.Avatar.initializeLocalCollisions(self, radius, 2, name) def startBlink(self): randomStart = random.uniform(0.5, 5) taskMgr.add(self.blinkTask, 'blinkTask') def stopBlink(self): taskMgr.remove('blinkTask') taskMgr.remove('doBlink') taskMgr.remove('openEyes') def blinkTask(self, task): taskMgr.add(self.doBlink, 'doBlink') delay = random.uniform(0.5, 7) task.delayTime = delay return task.again def doBlink(self, task): self.closeEyes() taskMgr.doMethodLater(0.2, self.openEyes, 'openEyes') return task.done def closeEyes(self): self.find('**/joint_pupilR').hide() self.find('**/joint_pupilL').hide() if self.charType == CIGlobals.Mickey: self.mickeyEye.setY(-0.025) self.mickeyEye.hide() self.find('**/eyes').setTexture(self.closedEyes, 1) def openEyes(self, task): self.find('**/joint_pupilR').show() self.find('**/joint_pupilL').show() if self.charType == CIGlobals.Mickey: self.mickeyEye.setY(0.025) self.mickeyEye.show() self.find('**/eyes').setTexture(self.eyes, 1) return task.done def enterOff(self): self.currentAnim = None return def exitOff(self): pass def enterNeutral(self): self.loop('neutral') def exitNeutral(self): self.stop() def enterWalk(self): self.loop('walk') def exitWalk(self): self.stop() def enterRun(self): self.loop('run') def exitRun(self): self.stop()
class ToonHead(Actor.Actor): notify = DirectNotifyGlobal.directNotify.newCategory('ToonHead') EyesOpen = loader.loadTexture('phase_3/maps/eyes.jpg', 'phase_3/maps/eyes_a.rgb') EyesOpen.setMinfilter(Texture.FTLinear) EyesOpen.setMagfilter(Texture.FTLinear) EyesClosed = loader.loadTexture('phase_3/maps/eyesClosed.jpg', 'phase_3/maps/eyesClosed_a.rgb') EyesClosed.setMinfilter(Texture.FTLinear) EyesClosed.setMagfilter(Texture.FTLinear) EyesSadOpen = loader.loadTexture('phase_3/maps/eyesSad.jpg', 'phase_3/maps/eyesSad_a.rgb') EyesSadOpen.setMinfilter(Texture.FTLinear) EyesSadOpen.setMagfilter(Texture.FTLinear) EyesSadClosed = loader.loadTexture('phase_3/maps/eyesSadClosed.jpg', 'phase_3/maps/eyesSadClosed_a.rgb') EyesSadClosed.setMinfilter(Texture.FTLinear) EyesSadClosed.setMagfilter(Texture.FTLinear) EyesAngryOpen = loader.loadTexture('phase_3/maps/eyesAngry.jpg', 'phase_3/maps/eyesAngry_a.rgb') EyesAngryOpen.setMinfilter(Texture.FTLinear) EyesAngryOpen.setMagfilter(Texture.FTLinear) EyesAngryClosed = loader.loadTexture('phase_3/maps/eyesAngryClosed.jpg', 'phase_3/maps/eyesAngryClosed_a.rgb') EyesAngryClosed.setMinfilter(Texture.FTLinear) EyesAngryClosed.setMagfilter(Texture.FTLinear) EyesSurprised = loader.loadTexture('phase_3/maps/eyesSurprised.jpg', 'phase_3/maps/eyesSurprised_a.rgb') EyesSurprised.setMinfilter(Texture.FTLinear) EyesSurprised.setMagfilter(Texture.FTLinear) Muzzle = loader.loadTexture('phase_3/maps/muzzleShrtGeneric.jpg') Muzzle.setMinfilter(Texture.FTLinear) Muzzle.setMagfilter(Texture.FTLinear) MuzzleSurprised = loader.loadTexture('phase_3/maps/muzzleShortSurprised.jpg') MuzzleSurprised.setMinfilter(Texture.FTLinear) MuzzleSurprised.setMagfilter(Texture.FTLinear) LeftA = Point3(0.06, 0.0, 0.14) LeftB = Point3(-0.13, 0.0, 0.1) LeftC = Point3(-0.05, 0.0, 0.0) LeftD = Point3(0.06, 0.0, 0.0) RightA = Point3(0.13, 0.0, 0.1) RightB = Point3(-0.06, 0.0, 0.14) RightC = Point3(-0.06, 0.0, 0.0) RightD = Point3(0.05, 0.0, 0.0) LeftAD = Point3(LeftA[0] - LeftA[2] * (LeftD[0] - LeftA[0]) / (LeftD[2] - LeftA[2]), 0.0, 0.0) LeftBC = Point3(LeftB[0] - LeftB[2] * (LeftC[0] - LeftB[0]) / (LeftC[2] - LeftB[2]), 0.0, 0.0) RightAD = Point3(RightA[0] - RightA[2] * (RightD[0] - RightA[0]) / (RightD[2] - RightA[2]), 0.0, 0.0) RightBC = Point3(RightB[0] - RightB[2] * (RightC[0] - RightB[0]) / (RightC[2] - RightB[2]), 0.0, 0.0) def __init__(self): try: self.ToonHead_initialized except: self.ToonHead_initialized = 1 Actor.Actor.__init__(self) self.toonName = 'ToonHead-' + str(self.this) self.__blinkName = 'blink-' + self.toonName self.__stareAtName = 'stareAt-' + self.toonName self.__lookName = 'look-' + self.toonName self.lookAtTrack = None self.__eyes = None self.__eyelashOpen = None self.__eyelashClosed = None self.__lod500Eyes = None self.__lod250Eyes = None self.__lpupil = None self.__lod500lPupil = None self.__lod250lPupil = None self.__rpupil = None self.__lod500rPupil = None self.__lod250rPupil = None self.__muzzle = None self.__eyesOpen = ToonHead.EyesOpen self.__eyesClosed = ToonHead.EyesClosed self.__height = 0.0 self.__eyelashesHiddenByGlasses = False self.randGen = random.Random() self.randGen.seed(random.random()) self.eyelids = ClassicFSM('eyelids', [ State('off', self.enterEyelidsOff, self.exitEyelidsOff, ['open', 'closed', 'surprised']), State('open', self.enterEyelidsOpen, self.exitEyelidsOpen, ['closed', 'surprised', 'off']), State('surprised', self.enterEyelidsSurprised, self.exitEyelidsSurprised, ['open', 'closed', 'off']), State('closed', self.enterEyelidsClosed, self.exitEyelidsClosed, ['open', 'surprised', 'off']) ], 'off', 'off') self.eyelids.enterInitialState() self.emote = None self.__stareAtNode = NodePath() self.__defaultStarePoint = Point3(0, 0, 0) self.__stareAtPoint = self.__defaultStarePoint self.__stareAtTime = 0 self.lookAtPositionCallbackArgs = None def delete(self): try: self.ToonHead_deleted except: self.ToonHead_deleted = 1 taskMgr.remove(self.__blinkName) taskMgr.remove(self.__lookName) taskMgr.remove(self.__stareAtName) if self.lookAtTrack: self.lookAtTrack.finish() self.lookAtTrack = None del self.eyelids del self.__stareAtNode del self.__stareAtPoint if self.__eyes: del self.__eyes if self.__lpupil: del self.__lpupil if self.__rpupil: del self.__rpupil if self.__eyelashOpen: del self.__eyelashOpen if self.__eyelashClosed: del self.__eyelashClosed self.lookAtPositionCallbackArgs = None Actor.Actor.delete(self) def setupHead(self, dna, forGui = 0): self.__height = self.generateToonHead(1, dna, ('1000',), forGui) self.generateToonColor(dna) animalStyle = dna.getAnimal() bodyScale = ToontownGlobals.toonBodyScales[animalStyle] headScale = ToontownGlobals.toonHeadScales[animalStyle] self.getGeomNode().setScale(headScale[0] * bodyScale * 1.3, headScale[1] * bodyScale * 1.3, headScale[2] * bodyScale * 1.3) if forGui: self.getGeomNode().setDepthWrite(1) self.getGeomNode().setDepthTest(1) if dna.getAnimal() == 'dog': self.loop('neutral') def fitAndCenterHead(self, maxDim, forGui = 0): p1 = Point3() p2 = Point3() self.calcTightBounds(p1, p2) if forGui: h = 180 t = p1[0] p1.setX(-p2[0]) p2.setX(-t) else: h = 0 d = p2 - p1 biggest = max(d[0], d[2]) s = maxDim / biggest mid = (p1 + d / 2.0) * s self.setPosHprScale(-mid[0], -mid[1] + 1, -mid[2], h, 0, 0, s, s, s) def setLookAtPositionCallbackArgs(self, argTuple): self.lookAtPositionCallbackArgs = argTuple def getHeight(self): return self.__height def getRandomForwardLookAtPoint(self): x = self.randGen.choice((-0.8, -0.5, 0, 0.5, 0.8)) z = self.randGen.choice((-0.5, 0, 0.5, 0.8)) return Point3(x, 1.5, z) def findSomethingToLookAt(self): if self.lookAtPositionCallbackArgs != None: pnt = self.lookAtPositionCallbackArgs[0].getLookAtPosition(self.lookAtPositionCallbackArgs[1], self.lookAtPositionCallbackArgs[2]) self.startStareAt(self, pnt) return if self.randGen.random() < 0.33: lookAtPnt = self.getRandomForwardLookAtPoint() else: lookAtPnt = self.__defaultStarePoint self.lerpLookAt(lookAtPnt, blink=1) def generateToonHead(self, copy, style, lods, forGui=0): headStyle = style.head fix = None if headStyle == 'dls': filePrefix = HeadDict['dls'] headHeight = 0.75 elif headStyle == 'dss': filePrefix = HeadDict['dss'] headHeight = 0.5 elif headStyle == 'dsl': filePrefix = HeadDict['dsl'] headHeight = 0.5 elif headStyle == 'dll': filePrefix = HeadDict['dll'] headHeight = 0.75 elif headStyle == 'cls': filePrefix = HeadDict['c'] fix = self.__fixHeadLongShort headHeight = 0.75 elif headStyle == 'css': filePrefix = HeadDict['c'] fix = self.__fixHeadShortShort headHeight = 0.5 elif headStyle == 'csl': filePrefix = HeadDict['c'] fix = self.__fixHeadShortLong headHeight = 0.5 elif headStyle == 'cll': filePrefix = HeadDict['c'] fix = self.__fixHeadLongLong headHeight = 0.75 elif headStyle == 'hls': filePrefix = HeadDict['h'] fix = self.__fixHeadLongShort headHeight = 0.75 elif headStyle == 'hss': filePrefix = HeadDict['h'] fix = self.__fixHeadShortShort headHeight = 0.5 elif headStyle == 'hsl': filePrefix = HeadDict['h'] fix = self.__fixHeadShortLong headHeight = 0.5 elif headStyle == 'hll': filePrefix = HeadDict['h'] fix = self.__fixHeadLongLong headHeight = 0.75 elif headStyle == 'mls': filePrefix = HeadDict['m'] fix = self.__fixHeadLongShort headHeight = 0.75 elif headStyle == 'mss': filePrefix = HeadDict['m'] fix = self.__fixHeadShortShort headHeight = 0.5 elif headStyle == 'rls': filePrefix = HeadDict['r'] fix = self.__fixHeadLongShort headHeight = 0.75 elif headStyle == 'rss': filePrefix = HeadDict['r'] fix = self.__fixHeadShortShort headHeight = 0.5 elif headStyle == 'rsl': filePrefix = HeadDict['r'] fix = self.__fixHeadShortLong headHeight = 0.5 elif headStyle == 'rll': filePrefix = HeadDict['r'] fix = self.__fixHeadLongLong headHeight = 0.75 elif headStyle == 'fls': filePrefix = HeadDict['f'] fix = self.__fixHeadLongShort headHeight = 0.75 elif headStyle == 'fss': filePrefix = HeadDict['f'] fix = self.__fixHeadShortShort headHeight = 0.5 elif headStyle == 'fsl': filePrefix = HeadDict['f'] fix = self.__fixHeadShortLong headHeight = 0.5 elif headStyle == 'fll': filePrefix = HeadDict['f'] fix = self.__fixHeadLongLong headHeight = 0.75 elif headStyle == 'pls': filePrefix = HeadDict['p'] fix = self.__fixHeadLongShort headHeight = 0.75 elif headStyle == 'pss': filePrefix = HeadDict['p'] fix = self.__fixHeadShortShort headHeight = 0.5 elif headStyle == 'psl': filePrefix = HeadDict['p'] fix = self.__fixHeadShortLong headHeight = 0.5 elif headStyle == 'pll': filePrefix = HeadDict['p'] fix = self.__fixHeadLongLong headHeight = 0.75 elif headStyle == 'bls': filePrefix = HeadDict['b'] fix = self.__fixHeadLongShort headHeight = 0.75 elif headStyle == 'bss': filePrefix = HeadDict['b'] fix = self.__fixHeadShortShort headHeight = 0.5 elif headStyle == 'bsl': filePrefix = HeadDict['b'] fix = self.__fixHeadShortLong headHeight = 0.5 elif headStyle == 'bll': filePrefix = HeadDict['b'] fix = self.__fixHeadLongLong headHeight = 0.75 elif headStyle == 'sls': filePrefix = HeadDict['s'] fix = self.__fixHeadLongShort headHeight = 0.75 elif headStyle == 'sss': filePrefix = HeadDict['s'] fix = self.__fixHeadShortShort headHeight = 0.5 elif headStyle == 'ssl': filePrefix = HeadDict['s'] fix = self.__fixHeadShortLong headHeight = 0.5 elif headStyle == 'sll': filePrefix = HeadDict['s'] fix = self.__fixHeadLongLong headHeight = 0.75 else: ToonHead.notify.error('unknown head style: %s' % headStyle) if len(lods) == 1: self.loadModel('phase_3' + filePrefix + lods[0], 'head', 'lodRoot', copy) if not copy: self.showAllParts('head') if fix != None: fix(style, None, copy) if not forGui: self.__lods = lods self.__style = style self.__headStyle = headStyle self.__copy = copy else: for lod in lods: self.loadModel('phase_3' + filePrefix + lod, 'head', lod, copy) if not copy: self.showAllParts('head', lod) if fix != None: fix(style, lod, copy) if not forGui: self.__lods = lods self.__style = style self.__headStyle = headStyle self.__copy = copy self.__fixEyes(style, forGui) self.setupEyelashes(style) self.eyelids.request('closed') self.eyelids.request('open') self.setupMuzzles(style) return headHeight def hideEars(self): self.findAllMatches('**/ears*;+s').stash() def showEars(self): self.findAllMatches('**/ears*;+s').unstash() def hideEyelashes(self): if self.__eyelashOpen: self.__eyelashOpen.stash() if self.__eyelashClosed: self.__eyelashClosed.stash() self.__eyelashesHiddenByGlasses = True def showEyelashes(self): if self.__eyelashOpen: self.__eyelashOpen.unstash() if self.__eyelashClosed: self.__eyelashClosed.unstash() self.__eyelashesHiddenByGlasses = False def generateToonColor(self, style): parts = self.findAllMatches('**/head*') parts.setColor(style.getHeadColor()) animalType = style.getAnimal() if animalType == 'cat' or animalType == 'rabbit' or animalType == 'bear' or animalType == 'mouse' or animalType == 'pig': parts = self.findAllMatches('**/ear?-*') parts.setColor(style.getHeadColor()) def __fixEyes(self, style, forGui = 0): mode = -3 if forGui: mode = -2 if self.hasLOD(): for lodName in self.getLODNames(): self.drawInFront('eyes*', 'head-front*', mode, lodName=lodName) if base.config.GetBool('want-new-anims', 1): if not self.find('**/joint_pupil*').isEmpty(): self.drawInFront('joint_pupil*', 'eyes*', -1, lodName=lodName) else: self.drawInFront('def_*_pupil', 'eyes*', -1, lodName=lodName) else: self.drawInFront('joint_pupil*', 'eyes*', -1, lodName=lodName) self.__eyes = self.getLOD(1000).find('**/eyes*') self.__lod500Eyes = self.getLOD(500).find('**/eyes*') self.__lod250Eyes = self.getLOD(250).find('**/eyes*') if self.__lod500Eyes.isEmpty(): self.__lod500Eyes = None else: self.__lod500Eyes.setColorOff() if base.config.GetBool('want-new-anims', 1): if not self.find('**/joint_pupilL*').isEmpty(): self.__lod500lPupil = self.__lod500Eyes.find('**/joint_pupilL*') self.__lod500rPupil = self.__lod500Eyes.find('**/joint_pupilR*') else: self.__lod500lPupil = self.__lod500Eyes.find('**/def_left_pupil*') self.__lod500rPupil = self.__lod500Eyes.find('**/def_right_pupil*') else: self.__lod500lPupil = self.__lod500Eyes.find('**/joint_pupilL*') self.__lod500rPupil = self.__lod500Eyes.find('**/joint_pupilR*') if self.__lod250Eyes.isEmpty(): self.__lod250Eyes = None else: self.__lod250Eyes.setColorOff() if base.config.GetBool('want-new-anims', 1): if not self.find('**/joint_pupilL*').isEmpty(): self.__lod250lPupil = self.__lod250Eyes.find('**/joint_pupilL*') self.__lod250rPupil = self.__lod250Eyes.find('**/joint_pupilR*') else: self.__lod250lPupil = self.__lod250Eyes.find('**/def_left_pupil*') self.__lod250rPupil = self.__lod250Eyes.find('**/def_right_pupil*') else: self.__lod250lPupil = self.__lod250Eyes.find('**/joint_pupilL*') self.__lod250rPupil = self.__lod250Eyes.find('**/joint_pupilR*') else: self.drawInFront('eyes*', 'head-front*', mode) if base.config.GetBool('want-new-anims', 1): if not self.find('joint_pupil*').isEmpty(): self.drawInFront('joint_pupil*', 'eyes*', -1) else: self.drawInFront('def_*_pupil', 'eyes*', -1) else: self.drawInFront('joint_pupil*', 'eyes*', -1) self.__eyes = self.find('**/eyes*') if not self.__eyes.isEmpty(): self.__eyes.setColorOff() self.__lpupil = None self.__rpupil = None if base.config.GetBool('want-new-anims', 1): if not self.find('**/joint_pupilL*').isEmpty(): if self.getLOD(1000): lp = self.getLOD(1000).find('**/joint_pupilL*') rp = self.getLOD(1000).find('**/joint_pupilR*') else: lp = self.find('**/joint_pupilL*') rp = self.find('**/joint_pupilR*') elif not self.getLOD(1000): lp = self.find('**/def_left_pupil*') rp = self.find('**/def_right_pupil*') else: lp = self.getLOD(1000).find('**/def_left_pupil*') rp = self.getLOD(1000).find('**/def_right_pupil*') else: lp = self.__eyes.find('**/joint_pupilL*') rp = self.__eyes.find('**/joint_pupilR*') if lp.isEmpty() or rp.isEmpty(): print 'Unable to locate pupils.' else: leye = self.__eyes.attachNewNode('leye') reye = self.__eyes.attachNewNode('reye') lmat = Mat4(0.802174, 0.59709, 0, 0, -0.586191, 0.787531, 0.190197, 0, 0.113565, -0.152571, 0.981746, 0, -0.233634, 0.418062, 0.0196875, 1) leye.setMat(lmat) rmat = Mat4(0.786788, -0.617224, 0, 0, 0.602836, 0.768447, 0.214658, 0, -0.132492, -0.16889, 0.976689, 0, 0.233634, 0.418062, 0.0196875, 1) reye.setMat(rmat) self.__lpupil = leye.attachNewNode('lpupil') self.__rpupil = reye.attachNewNode('rpupil') lpt = self.__eyes.attachNewNode('') rpt = self.__eyes.attachNewNode('') lpt.wrtReparentTo(self.__lpupil) rpt.wrtReparentTo(self.__rpupil) lp.reparentTo(lpt) rp.reparentTo(rpt) self.__lpupil.adjustAllPriorities(1) self.__rpupil.adjustAllPriorities(1) if self.__lod500Eyes: self.__lod500lPupil.adjustAllPriorities(1) self.__lod500rPupil.adjustAllPriorities(1) if self.__lod250Eyes: self.__lod250lPupil.adjustAllPriorities(1) self.__lod250rPupil.adjustAllPriorities(1) animalType = style.getAnimal() if animalType != 'dog': self.__lpupil.flattenStrong() self.__rpupil.flattenStrong() return def __setPupilDirection(self, x, y): if y < 0.0: y2 = -y left1 = self.LeftAD + (self.LeftD - self.LeftAD) * y2 left2 = self.LeftBC + (self.LeftC - self.LeftBC) * y2 right1 = self.RightAD + (self.RightD - self.RightAD) * y2 right2 = self.RightBC + (self.RightC - self.RightBC) * y2 else: y2 = y left1 = self.LeftAD + (self.LeftA - self.LeftAD) * y2 left2 = self.LeftBC + (self.LeftB - self.LeftBC) * y2 right1 = self.RightAD + (self.RightA - self.RightAD) * y2 right2 = self.RightBC + (self.RightB - self.RightBC) * y2 left0 = Point3(0.0, 0.0, left1[2] - left1[0] * (left2[2] - left1[2]) / (left2[0] - left1[0])) right0 = Point3(0.0, 0.0, right1[2] - right1[0] * (right2[2] - right1[2]) / (right2[0] - right1[0])) if x < 0.0: x2 = -x left = left0 + (left2 - left0) * x2 right = right0 + (right2 - right0) * x2 else: x2 = x left = left0 + (left1 - left0) * x2 right = right0 + (right1 - right0) * x2 self.__lpupil.setPos(left) self.__rpupil.setPos(right) def __lookPupilsAt(self, node, point): if node != None: mat = node.getMat(self.__eyes) point = mat.xformPoint(point) distance = 1.0 recip_z = 1.0 / max(0.1, point[1]) x = distance * point[0] * recip_z y = distance * point[2] * recip_z x = min(max(x, -1), 1) y = min(max(y, -1), 1) self.__setPupilDirection(x, y) return def __lookHeadAt(self, node, point, frac = 1.0, lod = None): reachedTarget = 1 if lod == None: head = self.getPart('head', self.getLODNames()[0]) else: head = self.getPart('head', lod) if node != None: headParent = head.getParent() mat = node.getMat(headParent) point = mat.xformPoint(point) rot = Mat3(0, 0, 0, 0, 0, 0, 0, 0, 0) lookAt(rot, Vec3(point), Vec3(0, 0, 1), CSDefault) scale = VBase3(0, 0, 0) hpr = VBase3(0, 0, 0) if decomposeMatrix(rot, scale, hpr, CSDefault): hpr = VBase3(min(max(hpr[0], -60), 60), min(max(hpr[1], -20), 30), 0) if frac != 1: currentHpr = head.getHpr() reachedTarget = abs(hpr[0] - currentHpr[0]) < 1.0 and abs(hpr[1] - currentHpr[1]) < 1.0 hpr = currentHpr + (hpr - currentHpr) * frac if lod == None: for lodName in self.getLODNames(): head = self.getPart('head', lodName) head.setHpr(hpr) else: head.setHpr(hpr) return reachedTarget def setupEyelashes(self, style): if style.getGender() == 'm': if self.__eyelashOpen: self.__eyelashOpen.removeNode() self.__eyelashOpen = None if self.__eyelashClosed: self.__eyelashClosed.removeNode() self.__eyelashClosed = None else: if self.__eyelashOpen: self.__eyelashOpen.removeNode() if self.__eyelashClosed: self.__eyelashClosed.removeNode() animal = style.head[0] model = loader.loadModel('phase_3' + EyelashDict[animal]) if self.hasLOD(): head = self.getPart('head', '1000') else: head = self.getPart('head', 'lodRoot') length = style.head[1] if length == 'l': openString = 'open-long' closedString = 'closed-long' else: openString = 'open-short' closedString = 'closed-short' self.__eyelashOpen = model.find('**/' + openString).copyTo(head) self.__eyelashClosed = model.find('**/' + closedString).copyTo(head) model.removeNode() return def __fixHeadLongLong(self, style, lodName=None, copy=1): if lodName == None: searchRoot = self else: searchRoot = self.find('**/' + str(lodName)) otherParts = searchRoot.findAllMatches('**/*short*') for partNum in range(0, otherParts.getNumPaths()): if copy: otherParts.getPath(partNum).removeNode() else: otherParts.getPath(partNum).stash() def __fixHeadLongShort(self, style, lodName=None, copy=1): animalType = style.getAnimal() headStyle = style.head if lodName == None: searchRoot = self else: searchRoot = self.find('**/' + str(lodName)) if animalType != 'duck' and animalType != 'horse': if animalType == 'rabbit': if copy: searchRoot.find('**/ears-long').removeNode() else: searchRoot.find('**/ears-long').hide() elif copy: searchRoot.find('**/ears-short').removeNode() else: searchRoot.find('**/ears-short').hide() if animalType != 'rabbit': if copy: searchRoot.find('**/eyes-short').removeNode() else: searchRoot.find('**/eyes-short').hide() if animalType != 'dog': if copy: searchRoot.find('**/joint_pupilL_short').removeNode() searchRoot.find('**/joint_pupilR_short').removeNode() else: searchRoot.find('**/joint_pupilL_short').stash() searchRoot.find('**/joint_pupilR_short').stash() if copy: self.find('**/head-short').removeNode() self.find('**/head-front-short').removeNode() else: self.find('**/head-short').hide() self.find('**/head-front-short').hide() if animalType != 'rabbit': muzzleParts = searchRoot.findAllMatches('**/muzzle-long*') for partNum in range(0, muzzleParts.getNumPaths()): if copy: muzzleParts.getPath(partNum).removeNode() else: muzzleParts.getPath(partNum).hide() else: muzzleParts = searchRoot.findAllMatches('**/muzzle-short*') for partNum in range(0, muzzleParts.getNumPaths()): if copy: muzzleParts.getPath(partNum).removeNode() else: muzzleParts.getPath(partNum).hide() def __fixHeadShortLong(self, style, lodName=None, copy=1): animalType = style.getAnimal() headStyle = style.head if lodName == None: searchRoot = self else: searchRoot = self.find('**/' + str(lodName)) if animalType != 'duck' and animalType != 'horse': if animalType == 'rabbit': if copy: searchRoot.find('**/ears-short').removeNode() else: searchRoot.find('**/ears-short').hide() elif copy: searchRoot.find('**/ears-long').removeNode() else: searchRoot.find('**/ears-long').hide() if animalType != 'rabbit': if copy: searchRoot.find('**/eyes-long').removeNode() else: searchRoot.find('**/eyes-long').hide() if animalType != 'dog': if copy: searchRoot.find('**/joint_pupilL_long').removeNode() searchRoot.find('**/joint_pupilR_long').removeNode() else: searchRoot.find('**/joint_pupilL_long').stash() searchRoot.find('**/joint_pupilR_long').stash() if copy: searchRoot.find('**/head-long').removeNode() searchRoot.find('**/head-front-long').removeNode() else: searchRoot.find('**/head-long').hide() searchRoot.find('**/head-front-long').hide() if animalType != 'rabbit': muzzleParts = searchRoot.findAllMatches('**/muzzle-short*') for partNum in range(0, muzzleParts.getNumPaths()): if copy: muzzleParts.getPath(partNum).removeNode() else: muzzleParts.getPath(partNum).hide() else: muzzleParts = searchRoot.findAllMatches('**/muzzle-long*') for partNum in range(0, muzzleParts.getNumPaths()): if copy: muzzleParts.getPath(partNum).removeNode() else: muzzleParts.getPath(partNum).hide() def __fixHeadShortShort(self, style, lodName=None, copy=1): if lodName == None: searchRoot = self else: searchRoot = self.find('**/' + str(lodName)) otherParts = searchRoot.findAllMatches('**/*long*') for partNum in range(0, otherParts.getNumPaths()): if copy: otherParts.getPath(partNum).removeNode() else: otherParts.getPath(partNum).stash() def __blinkOpenEyes(self, task): if self.eyelids.getCurrentState().getName() == 'closed': self.eyelids.request('open') r = self.randGen.random() if r < 0.1: t = 0.2 else: t = r * 4.0 + 1.0 taskMgr.doMethodLater(t, self.__blinkCloseEyes, self.__blinkName) return Task.done def __blinkCloseEyes(self, task): if self.eyelids.getCurrentState().getName() != 'open': taskMgr.doMethodLater(4.0, self.__blinkCloseEyes, self.__blinkName) else: self.eyelids.request('closed') taskMgr.doMethodLater(0.125, self.__blinkOpenEyes, self.__blinkName) return Task.done def startBlink(self): taskMgr.remove(self.__blinkName) if self.__eyes: self.openEyes() taskMgr.doMethodLater(self.randGen.random() * 4.0 + 1, self.__blinkCloseEyes, self.__blinkName) def stopBlink(self): taskMgr.remove(self.__blinkName) if self.__eyes: self.eyelids.request('open') def closeEyes(self): self.eyelids.request('closed') def openEyes(self): self.eyelids.request('open') def surpriseEyes(self): self.eyelids.request('surprised') def sadEyes(self): self.__eyesOpen = ToonHead.EyesSadOpen self.__eyesClosed = ToonHead.EyesSadClosed def angryEyes(self): self.__eyesOpen = ToonHead.EyesAngryOpen self.__eyesClosed = ToonHead.EyesAngryClosed def normalEyes(self): self.__eyesOpen = ToonHead.EyesOpen self.__eyesClosed = ToonHead.EyesClosed def blinkEyes(self): taskMgr.remove(self.__blinkName) self.eyelids.request('closed') taskMgr.doMethodLater(0.1, self.__blinkOpenEyes, self.__blinkName) def __stareAt(self, task): frac = 2 * globalClock.getDt() reachedTarget = self.__lookHeadAt(self.__stareAtNode, self.__stareAtPoint, frac) self.__lookPupilsAt(self.__stareAtNode, self.__stareAtPoint) if reachedTarget and self.__stareAtNode == None: return Task.done else: return Task.cont return def doLookAroundToStareAt(self, node, point): self.startStareAt(node, point) self.startLookAround() def startStareAtHeadPoint(self, point): self.startStareAt(self, point) def startStareAt(self, node, point): taskMgr.remove(self.__stareAtName) if self.lookAtTrack: self.lookAtTrack.finish() self.lookAtTrack = None self.__stareAtNode = node if point != None: self.__stareAtPoint = point else: self.__stareAtPoint = self.__defaultStarePoint self.__stareAtTime = globalClock.getFrameTime() taskMgr.add(self.__stareAt, self.__stareAtName) return def lerpLookAt(self, point, time = 1.0, blink = 0): taskMgr.remove(self.__stareAtName) if self.lookAtTrack: self.lookAtTrack.finish() self.lookAtTrack = None lodNames = self.getLODNames() if lodNames: lodName = lodNames[0] else: return 0 head = self.getPart('head', lodName) startHpr = head.getHpr() startLpupil = self.__lpupil.getPos() startRpupil = self.__rpupil.getPos() self.__lookHeadAt(None, point, lod=lodName) self.__lookPupilsAt(None, point) endHpr = head.getHpr() endLpupil = self.__lpupil.getPos() * 0.5 endRpupil = self.__rpupil.getPos() * 0.5 head.setHpr(startHpr) self.__lpupil.setPos(startLpupil) self.__rpupil.setPos(startRpupil) if startHpr.almostEqual(endHpr, 10): return 0 if blink: self.blinkEyes() lookToTgt_TimeFraction = 0.2 lookToTgtTime = time * lookToTgt_TimeFraction returnToEyeCenterTime = time - lookToTgtTime - 0.5 origin = Point3(0, 0, 0) blendType = 'easeOut' self.lookAtTrack = Parallel(Sequence(LerpPosInterval(self.__lpupil, lookToTgtTime, endLpupil, blendType=blendType), Wait(0.5), LerpPosInterval(self.__lpupil, returnToEyeCenterTime, origin, blendType=blendType)), Sequence(LerpPosInterval(self.__rpupil, lookToTgtTime, endRpupil, blendType=blendType), Wait(0.5), LerpPosInterval(self.__rpupil, returnToEyeCenterTime, origin, blendType=blendType)), name=self.__stareAtName) for lodName in self.getLODNames(): head = self.getPart('head', lodName) self.lookAtTrack.append(LerpHprInterval(head, time, endHpr, blendType='easeInOut')) self.lookAtTrack.start() return 1 def stopStareAt(self): self.lerpLookAt(Vec3.forward()) def stopStareAtNow(self): taskMgr.remove(self.__stareAtName) if self.lookAtTrack: self.lookAtTrack.finish() self.lookAtTrack = None if self.__lpupil and self.__rpupil: self.__setPupilDirection(0, 0) for lodName in self.getLODNames(): head = self.getPart('head', lodName) head.setHpr(0, 0, 0) def __lookAround(self, task): self.findSomethingToLookAt() t = self.randGen.random() * 4.0 + 3.0 taskMgr.doMethodLater(t, self.__lookAround, self.__lookName) return Task.done def startLookAround(self): taskMgr.remove(self.__lookName) t = self.randGen.random() * 5.0 + 2.0 taskMgr.doMethodLater(t, self.__lookAround, self.__lookName) def stopLookAround(self): taskMgr.remove(self.__lookName) self.stopStareAt() def stopLookAroundNow(self): taskMgr.remove(self.__lookName) self.stopStareAtNow() def enterEyelidsOff(self): return None def exitEyelidsOff(self): return None def enterEyelidsOpen(self): if not self.__eyes.isEmpty(): self.__eyes.setTexture(self.__eyesOpen, 1) if self.__eyelashOpen: self.__eyelashOpen.show() if self.__eyelashClosed: self.__eyelashClosed.hide() if self.__lod500Eyes: self.__lod500Eyes.setTexture(self.__eyesOpen, 1) if self.__lod250Eyes: self.__lod250Eyes.setTexture(self.__eyesOpen, 1) if self.__lpupil: self.__lpupil.show() self.__rpupil.show() if self.__lod500lPupil: self.__lod500lPupil.show() self.__lod500rPupil.show() if self.__lod250lPupil: self.__lod250lPupil.show() self.__lod250rPupil.show() def exitEyelidsOpen(self): return None def enterEyelidsClosed(self): if not self.__eyes.isEmpty() and self.__eyesClosed: self.__eyes.setTexture(self.__eyesClosed, 1) if self.__eyelashOpen: self.__eyelashOpen.hide() if self.__eyelashClosed: self.__eyelashClosed.show() if self.__lod500Eyes: self.__lod500Eyes.setTexture(self.__eyesClosed, 1) if self.__lod250Eyes: self.__lod250Eyes.setTexture(self.__eyesClosed, 1) if self.__lpupil: self.__lpupil.hide() self.__rpupil.hide() if self.__lod500lPupil: self.__lod500lPupil.hide() self.__lod500rPupil.hide() if self.__lod250lPupil: self.__lod250lPupil.hide() self.__lod250rPupil.hide() def exitEyelidsClosed(self): return None def enterEyelidsSurprised(self): if not self.__eyes.isEmpty() and ToonHead.EyesSurprised: self.__eyes.setTexture(ToonHead.EyesSurprised, 1) if self.__eyelashOpen: self.__eyelashOpen.hide() if self.__eyelashClosed: self.__eyelashClosed.hide() if self.__lod500Eyes: self.__lod500Eyes.setTexture(ToonHead.EyesSurprised, 1) if self.__lod250Eyes: self.__lod250Eyes.setTexture(ToonHead.EyesSurprised, 1) if self.__muzzle: self.__muzzle.setTexture(ToonHead.MuzzleSurprised, 1) if self.__lpupil: self.__lpupil.show() self.__rpupil.show() if self.__lod500lPupil: self.__lod500lPupil.show() self.__lod500rPupil.show() if self.__lod250lPupil: self.__lod250lPupil.show() self.__lod250rPupil.show() def exitEyelidsSurprised(self): if self.__muzzle: self.__muzzle.setTexture(ToonHead.Muzzle, 1) def setupMuzzles(self, style): self.__muzzles = [] self.__surpriseMuzzles = [] self.__angryMuzzles = [] self.__sadMuzzles = [] self.__smileMuzzles = [] self.__laughMuzzles = [] def hideAddNonEmptyItemToList(item, list): if not item.isEmpty(): item.hide() list.append(item) def hideNonEmptyItem(item): if not item.isEmpty(): item.hide() if self.hasLOD(): for lodName in self.getLODNames(): animal = style.getAnimal() if animal != 'dog': muzzle = self.find('**/' + lodName + '/**/muzzle*neutral') else: muzzle = self.find('**/' + lodName + '/**/muzzle*') if lodName == '1000' or lodName == '500': filePrefix = DogMuzzleDict[style.head] muzzles = loader.loadModel('phase_3' + filePrefix + lodName) if base.config.GetBool('want-new-anims', 1): if not self.find('**/' + lodName + '/**/__Actor_head/def_head').isEmpty(): muzzles.reparentTo(self.find('**/' + lodName + '/**/__Actor_head/def_head')) else: muzzles.reparentTo(self.find('**/' + lodName + '/**/joint_toHead')) elif self.find('**/' + lodName + '/**/joint_toHead'): muzzles.reparentTo(self.find('**/' + lodName + '/**/joint_toHead')) surpriseMuzzle = self.find('**/' + lodName + '/**/muzzle*surprise') angryMuzzle = self.find('**/' + lodName + '/**/muzzle*angry') sadMuzzle = self.find('**/' + lodName + '/**/muzzle*sad') smileMuzzle = self.find('**/' + lodName + '/**/muzzle*smile') laughMuzzle = self.find('**/' + lodName + '/**/muzzle*laugh') self.__muzzles.append(muzzle) hideAddNonEmptyItemToList(surpriseMuzzle, self.__surpriseMuzzles) hideAddNonEmptyItemToList(angryMuzzle, self.__angryMuzzles) hideAddNonEmptyItemToList(sadMuzzle, self.__sadMuzzles) hideAddNonEmptyItemToList(smileMuzzle, self.__smileMuzzles) hideAddNonEmptyItemToList(laughMuzzle, self.__laughMuzzles) else: if style.getAnimal() != 'dog': muzzle = self.find('**/muzzle*neutral') else: muzzle = self.find('**/muzzle*') filePrefix = DogMuzzleDict[style.head] muzzles = loader.loadModel('phase_3' + filePrefix + '1000') if base.config.GetBool('want-new-anims', 1): if not self.find('**/def_head').isEmpty(): muzzles.reparentTo(self.find('**/def_head')) else: muzzles.reparentTo(self.find('**/joint_toHead')) else: muzzles.reparentTo(self.find('**/joint_toHead')) surpriseMuzzle = self.find('**/muzzle*surprise') angryMuzzle = self.find('**/muzzle*angry') sadMuzzle = self.find('**/muzzle*sad') smileMuzzle = self.find('**/muzzle*smile') laughMuzzle = self.find('**/muzzle*laugh') self.__muzzles.append(muzzle) hideAddNonEmptyItemToList(surpriseMuzzle, self.__surpriseMuzzles) hideAddNonEmptyItemToList(angryMuzzle, self.__angryMuzzles) hideAddNonEmptyItemToList(sadMuzzle, self.__sadMuzzles) hideAddNonEmptyItemToList(smileMuzzle, self.__smileMuzzles) hideAddNonEmptyItemToList(laughMuzzle, self.__laughMuzzles) def getMuzzles(self): return self.__muzzles def getSurpriseMuzzles(self): return self.__surpriseMuzzles def getAngryMuzzles(self): return self.__angryMuzzles def getSadMuzzles(self): return self.__sadMuzzles def getSmileMuzzles(self): return self.__smileMuzzles def getLaughMuzzles(self): return self.__laughMuzzles def showNormalMuzzle(self): if self.isIgnoreCheesyEffect(): return for muzzleNum in range(len(self.__muzzles)): self.__muzzles[muzzleNum].show() def hideNormalMuzzle(self): if self.isIgnoreCheesyEffect(): return for muzzleNum in range(len(self.__muzzles)): self.__muzzles[muzzleNum].hide() def showAngryMuzzle(self): if self.isIgnoreCheesyEffect(): return for muzzleNum in range(len(self.__angryMuzzles)): self.__angryMuzzles[muzzleNum].show() self.__muzzles[muzzleNum].hide() def hideAngryMuzzle(self): if self.isIgnoreCheesyEffect(): return for muzzleNum in range(len(self.__angryMuzzles)): self.__angryMuzzles[muzzleNum].hide() self.__muzzles[muzzleNum].show() def showSadMuzzle(self): if self.isIgnoreCheesyEffect(): return for muzzleNum in range(len(self.__sadMuzzles)): self.__sadMuzzles[muzzleNum].show() self.__muzzles[muzzleNum].hide() def hideSadMuzzle(self): if self.isIgnoreCheesyEffect(): return for muzzleNum in range(len(self.__sadMuzzles)): self.__sadMuzzles[muzzleNum].hide() self.__muzzles[muzzleNum].show() def showSmileMuzzle(self): if self.isIgnoreCheesyEffect(): return for muzzleNum in range(len(self.__smileMuzzles)): self.__smileMuzzles[muzzleNum].show() self.__muzzles[muzzleNum].hide() def hideSmileMuzzle(self): if self.isIgnoreCheesyEffect(): return for muzzleNum in range(len(self.__smileMuzzles)): self.__smileMuzzles[muzzleNum].hide() self.__muzzles[muzzleNum].show() def showLaughMuzzle(self): if self.isIgnoreCheesyEffect(): return for muzzleNum in range(len(self.__laughMuzzles)): self.__laughMuzzles[muzzleNum].show() self.__muzzles[muzzleNum].hide() def hideLaughMuzzle(self): if self.isIgnoreCheesyEffect(): return for muzzleNum in range(len(self.__laughMuzzles)): self.__laughMuzzles[muzzleNum].hide() self.__muzzles[muzzleNum].show() def showSurpriseMuzzle(self): if self.isIgnoreCheesyEffect(): return for muzzleNum in range(len(self.__surpriseMuzzles)): self.__surpriseMuzzles[muzzleNum].show() self.__muzzles[muzzleNum].hide() def hideSurpriseMuzzle(self): if self.isIgnoreCheesyEffect(): return for muzzleNum in range(len(self.__surpriseMuzzles)): self.__surpriseMuzzles[muzzleNum].hide() self.__muzzles[muzzleNum].show() def isIgnoreCheesyEffect(self): if hasattr(self, 'savedCheesyEffect'): if self.savedCheesyEffect == 10 or self.savedCheesyEffect == 11 or self.savedCheesyEffect == 12 or self.savedCheesyEffect == 13 or self.savedCheesyEffect == 14: return True return False