class GameObject():
    def __init__(self, pos, modelName, modelAnims, maxHealth, maxSpeed,
                 colliderName):
        self.actor = Actor(modelName, modelAnims)
        self.actor.reparentTo(render)
        self.actor.setPos(pos)

        self.maxHealth = maxHealth
        self.health = maxHealth

        self.maxSpeed = maxSpeed

        self.velocity = Vec3(0, 0, 0)
        self.acceleration = 300.0

        self.walking = False

        colliderNode = CollisionNode(colliderName)
        colliderNode.addSolid(CollisionSphere(0, 0, 0, 0.3))
        self.collider = self.actor.attachNewNode(colliderNode)
        self.collider.setPythonTag("owner", self)

    def update(self, dt):
        speed = self.velocity.length()
        if speed > self.maxSpeed:
            self.velocity.normalize()
            self.velocity *= self.maxSpeed
            speed = self.maxSpeed

        if not self.walking:
            frictionVal = FRICTION * dt
            if frictionVal > speed:
                self.velocity.set(0, 0, 0)
            else:
                frictionVec = -self.velocity
                frictionVec.normalize()
                frictionVec *= frictionVal

                self.velocity += frictionVec

        self.actor.setPos(self.actor.getPos() + self.velocity * dt)

    def alterHealth(self, dHealth):
        self.health += dHealth

        if self.health > self.maxHealth:
            self.health = self.maxHealth

    def cleanup(self):
        if self.collider is not None and not self.collider.isEmpty():
            self.collider.clearPythonTag("owner")
            base.cTrav.removeCollider(self.collider)
            base.pusher.removeCollider(self.collider)

        if self.actor is not None:
            self.actor.cleanup()
            self.actor.removeNode()
            self.actor = None

        self.collider = None
Beispiel #2
0
class HealthGoblet():

    healthGivenFactor = 8
    minHealthGiven = 5

    def __init__(self, mainRef, enemyRef):
        print 'HealthGoblet instantiated'
        self._enemyRef = enemyRef
        self._playerRef = mainRef.player

        self.healthGobletNode = mainRef.mainNode.attachNewNode(
            'healthGobletNode')

        self.initAttributes()
        self.initModel()

        taskMgr.doMethodLater(1.5, self.updateHealthGoblet,
                              'updateHealthGobletTask')

    def initAttributes(self):
        self.healthGiven = utils.getDXY(
            self.minHealthGiven, self._enemyRef.level * self.healthGivenFactor)
        self.perceptionRange = 0.5

        self.healthGobletNode.setPos(self._enemyRef.enemyNode.getPos())

    def initModel(self):
        self.healthGobletModel = Actor('models/HealthGoblet',
                                       {'float': 'models/HealthGoblet-anim'})
        self.healthGobletModel.reparentTo(self.healthGobletNode)

        self.healthGobletModel.setCollideMask(BitMask32.allOff())
        self.healthGobletModel.setScale(0.5)

        self.healthGobletModel.loop('float')

    def updateHealthGoblet(self, task):
        playerNode = self._playerRef.playerNode
        if utils.getIsInRange(playerNode.getPos(),
                              self.healthGobletNode.getPos(),
                              self.perceptionRange):
            print 'healed player for:', self.healthGiven
            self._playerRef.heal(self.healthGiven)

            self.healthGobletModel.stop()

            self.suicide()
            return task.done

        return task.again

    def suicide(self):
        # Cleanup the healthGobletModel
        self.healthGobletModel.cleanup()
        self.healthGobletModel.delete()

        self.healthGobletNode.removeNode()

        self._enemyRef = None
        self._playerRef = None
Beispiel #3
0
class Splat(DirectObject):
    
    def __init__(self, pos, color, scale):
        self.pos = pos
        self.color = color
        self.scale = scale
        
    def generate(self):
        self.splat = Actor('phase_3.5/models/props/splat-mod.bam', {'chan' : 'phase_3.5/models/props/splat-chan.bam'})
        self.splat.setBillboardPointEye()
        self.splat.setColor(self.color)
        self.splat.setScale(self.scale)
        self.splat.setPos(self.pos)
        self.splat.play('chan')
        self.splat.reparentTo(render)
        Sequence(
          Wait(0.5),
          Func(self.destroy)
        ).start()
        
    def destroy(self):
        self.splat.cleanup()
        self.splat.removeNode()
        del self.splat
        del self
        
        
        
Beispiel #4
0
class GameObject:
    def __init__(self,
                 modelName,
                 model_anims,
                 max_health,
                 speed,
                 collider_name,
                 base,
                 pos,
                 hpr=Vec3(0, 0, 0),
                 scale=1.0):
        self.actor = Actor(modelName, model_anims)
        self.actor.reparentTo(base.render)
        self.actor.setPos(pos)
        self.actor.setHpr(hpr)
        self.actor.setScale(Vec3(scale, scale, scale))
        self.base = base
        self.max_health = max_health
        self.health = max_health

        self.speed = speed

        colliderNode = CollisionNode(collider_name)
        colliderNode.addSolid(
            CollisionCapsule(
                Vec3(0, 0, 2) * 1 / scale,
                Vec3(0, 0, 9) * 1 / scale, 6 * 1 / scale))
        # colliderNode.addSolid(CollisionSphere(0, 0, 0, 0.3))
        self.collider = self.actor.attachNewNode(colliderNode)
        self.collider.setPythonTag("owner", self)
        # self.collider.show()

    def get_position(self):
        return self.actor.getPos()

    def rotate(self, angle):
        self.actor.setHpr(self.actor, angle)

    def change_health(self, dHealth):
        self.health += dHealth

        if self.health > self.max_health:
            self.health = self.max_health
        elif self.health < 0:
            self.health = 0
        print(self.health)

    def cleanup(self):
        # Remove various nodes, and clear the Python-tag--see below!
        if self.collider is not None and not self.collider.isEmpty():
            # self.collider.clearPythonTag("owner")
            self.base.cTrav.removeCollider(self.collider)
            self.base.pusher.removeCollider(self.collider)

        if self.actor is not None:
            self.actor.cleanup()
            self.actor.removeNode()
            self.actor = None

        self.collider = None
Beispiel #5
0
    def disable(self):
        try:
            self.Avatar_disabled
        except:
            self.Avatar_disabled = 1
            if self.ragdoll:
                self.ragdoll.cleanup()
            self.ragdoll = None
            self.clearFadeTrack()
            if self in base.avatars:
                base.avatars.remove(self)
            if self.dmgFadeIval:
                self.dmgFadeIval.finish()
            self.stopActivity()
            self.dmgFadeIval = None
            self.stopMovingHealthLabel()
            if self.healthLabel:
                self.healthLabel.removeNode()
            self.healthLabel = None
            self.healthLabelTrack = None
            if self.floorTask:
                self.floorTask.remove()
            self.floorTask = None
            self.disableRay()
            self.deleteNametag3d()
            self.nametag.destroy()
            del self.nametag
            self.nametag3d.removeNode()
            self.nametag3d = None
            self.deleteShadow()
            self.removeLoopTask()
            self.mat = None
            self.tag = None
            self.chat = None
            self.avatarType = None
            self.charName = None
            self.nameTag = None
            self.cleanupPhysics()
            self.moveAnimProperties = None
            self.chatSoundTable = None

            self.lastWakeTime = None
            self.prevPos = None

            if self.wake:
                self.wake.destroy()
                self.wake = None

            if self.splashEffect:
                self.splashEffect.destroy()
                self.splashEffect = None

            self.splashSound = None

            self.avatarFloorToggle = None
            self.shadowFloorToggle = None

            Actor.cleanup(self)
Beispiel #6
0
class DistributedTNT(DistributedPhysicsEntity):
    def __init__(self, cr):
        DistributedPhysicsEntity.__init__(self, cr)
        self.tnt = None
        self.tntSound = None
        self.particle = None

    def explode(self):
        self.tntSound.stop()
        self.hide()
        self.particle.softStop()
        self.cleanupPhysics()
        CIGlobals.makeExplosion(self.getPos(render) + (0, 0, 5.0), 0.7, True)

    def doSetupPhysics(self):
        self.setupPhysics(self.getPhysBody(), True)

    def getPhysBody(self):
        shape = BulletCylinderShape(0.3925, 1.4, ZUp)
        body = BulletRigidBodyNode('tntBody')
        body.addShape(shape)
        body.setKinematic(True)
        body.setCcdMotionThreshold(1e-7)
        body.setCcdSweptSphereRadius(0.3925)
        return body

    def announceGenerate(self):
        self.tnt = Actor('phase_14/models/props/tnt.bam',
                         {'chan': 'phase_5/models/props/tnt-chan.bam'})
        self.tnt.reparentTo(self)
        self.tnt.play('chan')
        self.tnt.setP(97.492)
        self.tnt.setY(0.38)
        self.tntSound = base.audio3d.loadSfx(
            "phase_14/audio/sfx/dynamite_loop.ogg")
        self.tntSound.setLoop(True)
        base.audio3d.attachSoundToObject(self.tntSound, self.tnt)
        self.particle = ParticleLoader.loadParticleEffect(
            "phase_14/etc/tnt_spark.ptf")
        self.particle.start(self.tnt.find('**/joint_attachEmitter'),
                            CIGlobals.getParticleRender())

        DistributedPhysicsEntity.announceGenerate(self)

        self.tntSound.play()

    def disable(self):
        if self.tnt:
            self.tnt.cleanup()
            self.tnt.removeNode()
        self.tnt = None
        if self.tntSound:
            self.tntSound.stop()
        self.tntSound = None
        if self.particle:
            self.particle.softStop()
        self.particle = None
        DistributedPhysicsEntity.disable(self)
Beispiel #7
0
 def delete(self):
     try:
         self.Avatar_deleted
     except:
         Actor.cleanup(self)
         self.Avatar_deleted = 1
         del self.__font
         del self.style
         Actor.delete(self)
Beispiel #8
0
class HealthGoblet():

    healthGivenFactor = 8
    minHealthGiven = 5

    def __init__(self, mainRef, enemyRef):
        print 'HealthGoblet instantiated'
        self._enemyRef = enemyRef
        self._playerRef = mainRef.player

        self.healthGobletNode = mainRef.mainNode.attachNewNode('healthGobletNode')

        self.initAttributes()
        self.initModel()

        taskMgr.doMethodLater(1.5, self.updateHealthGoblet, 'updateHealthGobletTask')


    def initAttributes(self):
        self.healthGiven = utils.getDXY(self.minHealthGiven, self._enemyRef.level * self.healthGivenFactor)
        self.perceptionRange = 0.5

        self.healthGobletNode.setPos(self._enemyRef.enemyNode.getPos())

    def initModel(self):
        self.healthGobletModel = Actor('models/HealthGoblet',
                                    {'float':'models/HealthGoblet-anim'})
        self.healthGobletModel.reparentTo(self.healthGobletNode)

        self.healthGobletModel.setCollideMask(BitMask32.allOff())
        self.healthGobletModel.setScale(0.5)

        self.healthGobletModel.loop('float')

    def updateHealthGoblet(self, task):
        playerNode = self._playerRef.playerNode
        if utils.getIsInRange(playerNode.getPos(), self.healthGobletNode.getPos(), self.perceptionRange):
            print 'healed player for:', self.healthGiven
            self._playerRef.heal(self.healthGiven)

            self.healthGobletModel.stop()

            self.suicide()
            return task.done

        return task.again

    def suicide(self):
        # Cleanup the healthGobletModel
        self.healthGobletModel.cleanup()
        self.healthGobletModel.delete()

        self.healthGobletNode.removeNode()

        self._enemyRef = None
        self._playerRef = None
    def cleanup(self):
        if self.flyTrack is not None:
            self.flyTrack.finish()
            self.flyTrack = None

        if self.television is not None:
            self.television.delete()
            self.television = None

        Actor.cleanup(self)
    def cleanup(self):
        if self.flyTrack is not None:
            self.flyTrack.finish()
            self.flyTrack = None

        if self.television is not None:
            self.television.delete()
            self.television = None

        Actor.cleanup(self)
Beispiel #11
0
 def delete(self):
     try:
         self.Avatar_deleted
     except:
         Actor.cleanup(self)
         self.Avatar_deleted = 1
         self.style = None
         self.collTube = None
         self.hpText = None
         self.hpTextGenerator = None
         ShadowCaster.delete(self)
         Actor.delete(self)
Beispiel #12
0
def precacheToons():
    """
    Precaches all Toon models and animations!
    """
    
    from src.coginvasion.base.Precache import precacheActor, precacheModel
    from direct.actor.Actor import Actor
    
    for legType in LegHeightDict.keys():
        toon = Actor()
        generateBodyPart(toon, 'legs', legType, 3, 'shorts')
        precacheActor(toon)
        toon.cleanup()
        toon.removeNode()
        
    for torsoType in TorsoHeightDict.keys():
        toon = Actor()
        generateBodyPart(toon, 'torso', torsoType, 3, '')
        precacheActor(toon)
        toon.cleanup()
        toon.removeNode()
        
    for animal in HeadScales.keys():
        if animal != "dog":
            precacheModel("phase_3/models/char/%s-heads-1000.bam" % animal)
        else:
            for headType in DogHeads:
                # precache all dog head models and animations
                
                mdl = "phase_3/models/char/tt_a_chr_%s_head_1000.bam" % headType
                partAnimations = {}

                # Load the body part animations.
                for animName in ANIMATIONS:
                    animationData = list(ANIMATIONS[animName])
                    animPath = None

                    if len(animationData) == 2:
                        animPhase = animationData[0]
                        animFile = animationData[1]

                        # Let's create the path for the animation.
                        animPath = BASE_MODEL % (animPhase, headType, '',
                            'head', animFile)

                        if '_-' in animPath:
                            animPath = animPath.replace('_-', '-')

                        if '__' in animPath:
                            animPath = animPath.replace('__', '_')

                    partAnimations[animName] = animPath
                precacheActor([mdl, partAnimations])
Beispiel #13
0
 def stopPlayer(self):
     logging.debug("stop player...")
     logging.debug("...stop control...")
     self.stopControl()
     self.walk_sound.stop()
     logging.debug("...stop camera...")
     self.stopCamera()
     logging.debug("...stop base...")
     self.freeCursor()
     # remove the actor
     Actor.cleanup(self)
     self.removeNode()
     logging.debug("...player stop")
Beispiel #14
0
 def stopPlayer(self):
     logging.debug("stop player...")
     logging.debug("...stop control...")
     self.stopControl()
     self.walk_sound.stop()
     logging.debug("...stop camera...")
     self.stopCamera()
     logging.debug("...stop base...")
     self.freeCursor()
     # remove the actor
     Actor.cleanup(self)
     self.removeNode()
     logging.debug("...player stop")
Beispiel #15
0
 def delete(self):
     try:
         self.Avatar_deleted
     except:
         self.deleteNametag3d()
         Actor.cleanup(self)
         self.Avatar_deleted = 1
         del self.__font
         del self.style
         del self.soundChatBubble
         self.nametag.destroy()
         del self.nametag
         self.nametag3d.removeNode()
         ShadowCaster.delete(self)
         Actor.delete(self)
Beispiel #16
0
 def delete(self):
     try:
         self.Avatar_deleted
     except:
         self.deleteNametag3d()
         Actor.cleanup(self)
         if self.ManagesNametagAmbientLightChanged:
             self.ignoreNametagAmbientLightChange()
         self.Avatar_deleted = 1
         del self.__font
         del self.style
         del self.soundChatBubble
         del self.nametag
         self.nametag3d.removeNode()
         ShadowCaster.delete(self)
         Actor.delete(self)
Beispiel #17
0
 def delete(self):
     try:
         self.Avatar_deleted
     except:
         self.deleteNametag3d()
         Actor.cleanup(self)
         if self.ManagesNametagAmbientLightChanged:
             self.ignoreNametagAmbientLightChange()
         self.Avatar_deleted = 1
         del self.__font
         del self.style
         del self.soundChatBubble
         del self.nametag
         self.nametag3d.removeNode()
         ShadowCaster.delete(self)
         Actor.delete(self)
Beispiel #18
0
    def disable(self):
        try:
            self.Avatar_disabled
        except:
            self.Avatar_disabled = 1
            self.deleteShadow()
            self.deleteNameTag()
            self.removeLoopTask()
            self.mat = None
            self.tag = None
            self.chat = None
            self.height = None
            self.avatarType = None
            self.charName = None
            self.nameTag = None
            self.name = None
            Actor.cleanup(self)

        return
Beispiel #19
0
    def delete(self):
        try:
            self.Avatar_deleted
            return
        except:
            self.Avatar_deleted = 1

        self.setBlend(frameBlend=False)
        self.deleteNametag3d()
        Actor.cleanup(self)
        if self.ManagesNametagAmbientLightChanged:
            self.ignoreNametagAmbientLightChange()
        del self.__font
        del self.style
        del self.soundChatBubble
        self.nametag.destroy()
        del self.nametag
        self.nametag3d.removeNode()
        ShadowCaster.delete(self)
        Actor.delete(self)
Beispiel #20
0
class BonusGfx(GfxColleague):

    def __init__(self, mediator, pos, model_path, anim_suff):
        self.model = None
        self.pos = pos
        self.model_path = model_path
        self.anim_suff = anim_suff
        GfxColleague.__init__(self, mediator)
        path = self.model_path
        self.model = Actor(path, {'anim': path + '-' + self.anim_suff})
        self.model.reparent_to(render)
        self.model.set_pos(self.pos)
        self.model.loop('anim')
        self.model.setPlayRate(.5, 'anim')
        self.model.set_depth_offset(1)

    def destroy(self):
        self.model.cleanup()
        self.model = self.model.remove_node()
        GfxColleague.destroy(self)
Beispiel #21
0
    def disable(self):
        try:
            self.Avatar_disabled
        except:
            self.Avatar_disabled = 1
            self.deleteNametag3d()
            self.nametag.destroy()
            del self.nametag
            self.nametag3d.removeNode()
            self.deleteShadow()
            self.removeLoopTask()
            self.mat = None
            self.tag = None
            self.chat = None
            self.height = None
            self.avatarType = None
            self.charName = None
            self.nameTag = None
            self._name = None

            Actor.cleanup(self)
Beispiel #22
0
class Splat(DirectObject):
    def __init__(self, pos, color, scale):
        self.pos = pos
        self.color = color
        self.scale = scale

    def generate(self):
        self.splat = Actor('phase_3.5/models/props/splat-mod.bam',
                           {'chan': 'phase_3.5/models/props/splat-chan.bam'})
        self.splat.setBillboardPointEye()
        self.splat.setColor(self.color)
        self.splat.setScale(self.scale)
        self.splat.setPos(self.pos)
        self.splat.play('chan')
        self.splat.reparentTo(render)
        Sequence(Wait(0.5), Func(self.destroy)).start()

    def destroy(self):
        self.splat.cleanup()
        self.splat.removeNode()
        del self.splat
        del self
Beispiel #23
0
class EquippedObject(MapObject):
    def __init__(self, npc, modelPath, texturePath=None):
        self.npc = npc
        self.modelPath = modelPath
        self.texturePath = texturePath

        self.model = Actor(self.modelPath, self.npc.animDic)
        #self.model.setTransparency(True)

        self.model.reparentTo(self.npc.model)
        if texturePath is not None:
            self.tex = loader.loadTexture(texturePath)
            self.model.clearTexture(TextureStage.getDefault())
            self.model.clearTexture()
            self.model.setTexture(TextureStage.getDefault(), self.tex)
            #print "Adding object with texture : %s" % texturePath

    def loop(self, animName):
        self.model.loop(animName)

    def destroy(self):
        self.model.cleanup()
        self.model.remove()
Beispiel #24
0
class EquippedObject(MapObject):
	def __init__(self, npc, modelPath, texturePath=None):
		self.npc = npc
		self.modelPath = modelPath
		self.texturePath = texturePath
		
		self.model = Actor(self.modelPath, self.npc.animDic)
		#self.model.setTransparency(True)
		
		self.model.reparentTo(self.npc.model)
		if texturePath is not None:
			self.tex = loader.loadTexture(texturePath)
			self.model.clearTexture(TextureStage.getDefault())
			self.model.clearTexture()
			self.model.setTexture(TextureStage.getDefault(), self.tex)
			#print "Adding object with texture : %s" % texturePath
			
	def loop(self, animName):
		self.model.loop(animName)
		
	def destroy(self):
		self.model.cleanup()
		self.model.remove()	
Beispiel #25
0
class ToonFPS(DirectObject):
    notify = directNotify.newCategory('ToonFPS')
    WeaponName2DamageData = {'pistol': (36.0, 10.0, 150.0, 0.25),
     'shotgun': (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
        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.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.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()
        return

    def movementTask(self, task):
        if not inputState.isSet('jump') and not base.localAvatar.walkControls.isAirborne and inputState.isSet('forward') or inputState.isSet('reverse') or inputState.isSet('slideLeft') or inputState.isSet('slideRight'):
            if base.localAvatar.getAnimState() != 'run':
                base.localAvatar.setAnimState('run')
                base.localAvatar.playMovementSfx('run')
                self.mg.sendUpdate('runningAvatar', [base.localAvatar.doId])
        elif 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])
        elif base.localAvatar.getAnimState() != 'neutral':
            base.localAvatar.setAnimState('neutral')
            base.localAvatar.playMovementSfx(None)
            self.mg.sendUpdate('standingAvatar', [base.localAvatar.doId])
        return Task.cont

    def enterAlive(self):
        if self.mg.fsm.getCurrentState().getName() not in ('gameOver', 'announceGameOver', 'finalScores'):
            base.localAvatar.disableChatInput()
            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()
        base.localAvatar.createChatInput()

    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.wav')
        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)
        return

    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):
        base.camera.lookAt(killer, 0, 0, 3)
        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.wav')
            self.shoot = base.loadSfx('phase_4/audio/sfx/pistol_shoot.wav')
            self.reload = base.loadSfx('phase_4/audio/sfx/pistol_worldreload.wav')
        elif self.weaponName == 'shotgun':
            self.draw = base.loadSfx('phase_4/audio/sfx/draw_primary.wav')
            self.shoot = base.loadSfx('phase_4/audio/sfx/shotgun_shoot.wav')
            self.cockBack = base.loadSfx('phase_4/audio/sfx/shotgun_cock_back.wav')
            self.cockFwd = base.loadSfx('phase_4/audio/sfx/shotgun_cock_forward.wav')
        self.empty = base.loadSfx('phase_4/audio/sfx/shotgun_empty.wav')
        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 == '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)
            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.weapon.setColorScale(color)
        self.gui.load()
        return

    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 == 'shotgun':
            self.v_model_root.setPos(-0.42, -0.81, -1.7)
            self.v_model_root.setHpr(359, 352.87, 0.0)
        self.gui.start()
        self.firstPerson.disableMouse()
        self.aliveFSM.request('draw')

    def reallyStart(self):
        self.firstPerson.reallyStart()
        taskMgr.add(self.movementTask, 'toonBattleMovement')

    def end(self):
        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):
        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)
        return

    def cleanup(self):
        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
        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()
        return

    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()
        return

    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')
        self.track.setDoneEvent(self.track.getName())
        self.acceptOnce(self.track.getDoneEvent(), self.aliveFSM.request, ['idle'])
        self.track.start()

    def exitDraw(self):
        if self.track:
            self.ignore(self.track.getDoneEvent())
            self.track.finish()
            self.track = None
        return

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

    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)))
        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.ignore('shootTrack')
        if self.track:
            self.track.finish()
            self.track = None
        return

    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')
        self.track.setDoneEvent('reloadTrack')
        self.acceptOnce(self.track.getDoneEvent(), self.aliveFSM.request, ['idle'])
        self.track.start()

    def exitReload(self):
        self.ignore('reloadTrack')
        if self.track:
            self.track.finish()
            self.track = None
        return

    def resetAmmo(self):
        if self.weaponName == 'pistol':
            self.ammo = 14
        elif self.weaponName == 'shotgun':
            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
Beispiel #26
0
class FountainPenAttack(Attack):
    notify = directNotify.newCategory('FountainPenAttack')
    attack = 'fountainpen'

    def __init__(self, attacksClass, suit):
        Attack.__init__(self, attacksClass, suit)
        self.pen = None
        self.spray = None
        self.splat = None
        self.spraySfx = None
        self.sprayParticle = None
        self.sprayScaleIval = None
        self.wsnp = None
        return

    def loadAttack(self):
        self.pen = loader.loadModel('phase_5/models/props/pen.bam')
        self.pen.reparentTo(self.suit.find('**/joint_Rhold'))
        self.sprayParticle = ParticleLoader.loadParticleEffect('phase_5/etc/penSpill.ptf')
        self.spray = loader.loadModel('phase_3.5/models/props/spray.bam')
        self.spray.setColor(VBase4(0, 0, 0, 1))
        self.splat = Actor('phase_3.5/models/props/splat-mod.bam', {'chan': 'phase_3.5/models/props/splat-chan.bam'})
        self.splat.setColor(VBase4(0, 0, 0, 1))
        self.sprayScaleIval = LerpScaleInterval(self.spray, duration=0.3, scale=(1, 20, 1), startScale=(1, 1, 1))
        sphere = CollisionSphere(0, 0, 0, 0.5)
        sphere.setTangible(0)
        if hasattr(self.suit, 'uniqueName'):
            collName = self.suit.uniqueName('fountainPenCollNode')
        else:
            collName = 'fountainPenCollNode'
        collNode = CollisionNode(collName)
        collNode.addSolid(sphere)
        collNode.setCollideMask(CIGlobals.WallBitmask)
        self.wsnp = self.spray.attachNewNode(collNode)
        self.wsnp.setY(1)

    def doAttack(self, ts = 0):
        self.loadAttack()
        if hasattr(self.suit, 'uniqueName'):
            name = self.suit.uniqueName('doFountainPenAttack')
        else:
            name = 'doFountainPenAttack'
        self.suitTrack = Parallel(name=name)
        self.suitTrack.append(ActorInterval(self.suit, 'fountainpen'))
        self.suitTrack.append(Sequence(Wait(1.2), Func(self.acceptOnce, 'enter' + self.wsnp.node().getName(), self.handleSprayCollision), Func(self.playWeaponSound), Func(self.attachSpray), Func(self.sprayParticle.start, self.pen.find('**/joint_toSpray'), self.pen.find('**/joint_toSpray')), self.sprayScaleIval, Wait(0.5), Func(self.sprayParticle.cleanup), Func(self.spray.setScale, 1), Func(self.spray.reparentTo, hidden), Func(self.ignore, 'enter' + self.wsnp.node().getName())))
        self.suitTrack.setDoneEvent(self.suitTrack.getName())
        self.acceptOnce(self.suitTrack.getDoneEvent(), self.finishedAttack)
        self.suitTrack.delayDelete = DelayDelete.DelayDelete(self.suit, name)
        self.suitTrack.start(ts)

    def attachSpray(self):
        self.spray.reparentTo(self.pen.find('**/joint_toSpray'))
        pos = self.spray.getPos(render)
        hpr = self.spray.getHpr(render)
        self.spray.reparentTo(render)
        self.spray.setPos(pos)
        self.spray.setHpr(hpr)
        self.spray.setP(0)
        if self.suit.type == 'C':
            self.spray.setH(self.spray.getH() + 7.5)
        self.spray.setTwoSided(True)

    def handleSprayCollision(self, entry):
        if self.suit:
            self.suit.sendUpdate('toonHitByWeapon', [self.getAttackId(self.attack), base.localAvatar.doId])
            base.localAvatar.b_handleSuitAttack(self.getAttackId(self.attack), self.suit.doId)
        self.sprayScaleIval.pause()

    def playWeaponSound(self):
        self.spraySfx = base.audio3d.loadSfx('phase_5/audio/sfx/SA_fountain_pen.mp3')
        base.audio3d.attachSoundToObject(self.spraySfx, self.pen)
        self.spraySfx.play()

    def cleanup(self):
        Attack.cleanup(self)
        if self.wsnp:
            self.wsnp.node().clearSolids()
            self.wsnp.removeNode()
            self.wsnp = None
        if self.pen:
            self.pen.removeNode()
            self.pen = None
        if self.sprayParticle:
            self.sprayParticle.cleanup()
            self.sprayParticle = None
        if self.spray:
            self.spray.removeNode()
            self.spray = None
        if self.splat:
            self.splat.cleanup()
            self.splat = None
        if self.sprayScaleIval:
            self.sprayScaleIval.pause()
            self.sprayScaleIval = None
        self.spraySfx = None
        return
Beispiel #27
0
class CogAI(DirectObject):
    
    cancelStep = False
    
    def __init__(self, cog, spawn, support = False):
        self.cog = cog
        self.spawn = spawn
        self.attack = True
        self.support = support
        self.flyIn()
        
    def setAI(self):
        collisions = render.getPythonTag('WorldCollisions')
        collisions.addCogGroundCollision(self.cog)
        self.AIWorld = AIWorld(render)
        self.AIChar = AICharacter('Cog', self.cog.getCog(), -125, 90, -14)
        self.AIWorld.addAiChar(self.AIChar)
        self.AIBehaviors = self.AIChar.getAiBehaviors()
        if self.support == False:
            self.AIBehaviors.pathFollow(8)
            self.AIBehaviors.addToPath(VBase3(110.60, -0.32, 4.57))
            checkpoints = self.spawn.getPath().getCheckpoints()
            for checkpoint in xrange(len(checkpoints)):
                self.AIBehaviors.addToPath(checkpoints[checkpoint].getPos())
            self.AIBehaviors.startFollow()
        else:
            self.AIBehaviors.pursue(render.find('**/Toon'))
        self.cog.getCog().loop('walk')
        base.taskMgr.add(self.AIUpdate, "AIUpdate")
        
    def calcChance(self, percent):
        if(random.randint(0, 100) < percent):
            return True
        else:
            return False
        
    def toggleAttack(self):
        if(self.attack):
            self.attack = False
        else:
            self.attack = True
        
    def AIUpdate(self, task):
        if(self.AIBehaviors.behaviorStatus('pathfollow') == 'done'):
            self.cog.getCog().loop('neutral')
            self.AIBehaviors.removeAi('pathfollow')
            toonHall = render.getPythonTag("ToonHall")
            toonHall.startCogEnter(self.cog)
            return Task.done
        else:
            if(self.cog.getHealth() > 0):
                if(self.calcChance(40) and self.attack):
                    def resumeAI(task):
                        self.AIBehaviors.resumeAi('pathfollow')
                        self.cog.getCog().loop('walk')
                        return Task.done
                    def enableAttacks(task):
                        return Task.done
                    avatar = render.find('**/Toon')
                    if(self.cog.getCog().getDistance(avatar) <= 20):
                        self.AIBehaviors.pauseAi('pathfollow')
                        self.cog.getCog().stop()
                        self.attack = False
                        self.cog.getCog().lookAt(avatar)
                        self.cog.getCog().play('throw-object')
                        attack = CogAttacks().getRandomAttack(self.cog.getLevel() * 2)
                        attack.execute(self.cog)
                        base.taskMgr.doMethodLater(10, enableAttacks, 'Toggle Attack')
                        base.taskMgr.doMethodLater(3, resumeAI, 'Resume AI')
                self.AIWorld.update()
                return Task.cont
            else:
                self.AIBehaviors.removeAi('pathfollow')
                return Task.done
        
    def flyIn(self):
        phase_4 = "phase_4/models/props"
        cog = self.cog.getCog()

        collisions = render.getPythonTag('WorldCollisions')
        collisions.addCogCollision(self.cog)
        self.propeller = Actor(loader.loadModel(phase_4 + "/propeller-mod.bam"), {'chan' : loader.loadModel(phase_4 + "/propeller-chan.bam")})
        self.propeller.reparentTo(cog.find('**/joint_head'))
        propSound = SoundBank.getSound('propeller')
        propSound.setLoop(True)
        propSound.setVolume(0.8)
        propSound.play()
        pos = cog.getPos()
        cog.setPos(pos.getX(), pos.getY(), pos.getZ() + 20)
        cog.pose('landing', 1)
        cog.colorScaleInterval(4.8, Vec4(1, 1, 1, 1), startColorScale=Vec4(0.2509803921568627, 0.2509803921568627, 0.2509803921568627, 0.25), blendType='easeInOut').start()
        path = cog.posInterval(5, pos, startPos = cog.getPos())
        path.start()
        self.propeller.loop('chan', fromFrame=0, toFrame=3)
        base.taskMgr.add(self.handleCogDead, 'Handle Cog Death')
        base.taskMgr.doMethodLater(4, self.playInSound, 'Play In Sound', extraArgs = [propSound], appendTask = True)
        base.taskMgr.doMethodLater(5, self.landCog, 'Land Cog')
        
    def handleCogDead(self, task):
        if(self.cog.isDefeated):
            self.cancelStep = True
            collisions = render.getPythonTag('WorldCollisions')
            collisions.addCogGroundCollision(cog = self.cog)
            return Task.done
        else:
            return Task.cont
        
        
    def landCog(self, task):
        if not self.cancelStep:
            base.taskMgr.remove('Handle Cog Death')
            self.propeller.play('chan', fromFrame=35, toFrame=87)
            self.cog.getCog().play('landing')
            base.taskMgr.doMethodLater(3, self.removePropeller, 'Remove Propeller')
        return Task.done
    
    def removePropeller(self, task):
        self.propeller.cleanup()
        self.propeller.removeNode()
        self.setAI()
        return Task.done
        
    def playInSound(self, sound, task):
        if not self.cancelStep:
            sound.stop()
            SoundBank.getSound('propeller_in').play()
        return Task.done
        
class Monster():
    def __init__(self, id, parent, type, pos):
        self.id = id
        self.parent = parent
        self.hp = 100
        self.speed = 1
        self.can_move = True
        
        if type == 'baby':
            self.node = Actor('models/baby', {'walk':'models/baby-walk', 
                                              'stand':'models/baby-stand',
                                              'idle':'models/baby-idle',
                                              'jump':'models/baby-jump',
                                              'bite1':'models/baby-bite1',
                                              'bite2':'models/baby-bite2',
                                              'head_attack':'models/baby-head_attack',                                
                                              'hit1':'models/baby-hit1',                                
                                              'hit2':'models/baby-hit2', 
                                              'die':'models/baby-die'})
            self.head_node = self.node.exposeJoint(None,"modelRoot","Bip01_Head")
            self.body_node = self.node.exposeJoint(None,"modelRoot","Bip01_Pelvis")
            self.node.setH(180)
            self.node.setScale(0.03)
            self.node.flattenLight()
            self.zpos = 0
            self.node.setPos(pos[0]*TILE_SIZE,pos[1]*TILE_SIZE,self.zpos)
            self.node.setTexture(loader.loadTexture('models/Zomby_D.png'))
            self.ts_normal = TextureStage('ts_normal')
            self.tex_normal = loader.loadTexture('models/Zomby_N.png')
            self.ts_normal.setMode(TextureStage.MNormal)
            self.node.setTexture(self.ts_normal, self.tex_normal)
            self.ts_gloss = TextureStage('ts_gloss')
            self.tex_gloss = loader.loadTexture('models/Zomby_S1.png')
            self.ts_gloss.setMode(TextureStage.MGloss)
            self.node.setTexture(self.ts_gloss, self.tex_gloss)   
            self.ts_glow = TextureStage('ts_glow')
            self.tex_glow = loader.loadTexture('models/Zomby_I.png')
            self.ts_glow.setMode(TextureStage.MGlow)
            self.node.setTexture(self.ts_glow, self.tex_glow)         
            self.node.reparentTo(render)
            self.node.loop('walk')
        elif type == 'nos':
            self.node = loader.loadModel('models/nos')
            self.zpos = 5
            self.node.setPos(pos[0]*TILE_SIZE,pos[1]*TILE_SIZE,self.zpos)
            self.node.setScale(2)
            if self.id == 1:
                self.node.setColor(1,0,0)
            elif self.id == 2:
                self.node.setColor(0,1,0)
            elif self.id == 3:
                self.node.setColor(0,0,1)
            else:
                self.node.setColor(1,1,1)
            self.node.reparentTo(render)


        #self.patrol_points = [(1,1), (4,11), (12,20), (18,4), (19,17)]
        
        #initialize 3d sound
        self.audio3d = Audio3DManager.Audio3DManager(base.sfxManagerList[0], base.camera)
        self.shot_head = self.audio3d.loadSfx('audio/Zombie In Pain-SoundBible.com-134322253.wav')
        self.shot_body = self.audio3d.loadSfx('audio/Zombie Moan-SoundBible.com-565291980.wav')
        self.moan1 = self.audio3d.loadSfx('audio/Mindless Zombie Awakening-SoundBible.com-255444348.wav')
        self.moan2 = self.audio3d.loadSfx('audio/Zombie Brain Eater-SoundBible.com-1076387080.wav')
        self.aggro_sound = self.audio3d.loadSfx('audio/Mummy Zombie-SoundBible.com-1966938763.wav')
        self.attack_sound = self.audio3d.loadSfx('audio/Chopping Off Limb-SoundBible.com-884800545.wav')
        self.audio3d.attachSoundToObject(self.moan1, self.node)
        self.audio3d.attachSoundToObject(self.moan2, self.node)
        self.audio3d.attachSoundToObject(self.shot_head, self.node)
        self.audio3d.attachSoundToObject(self.shot_body, self.node)
        self.audio3d.attachSoundToObject(self.aggro_sound, self.node)
        self.audio3d.attachSoundToObject(self.attack_sound, self.node)
        delay0 = Wait(d(35))
        delay1 = Wait(25+d(35))
        delay2 = Wait(25+d(35))
        self.moan_sequence = Sequence(delay0, SoundInterval(self.moan1), delay1, SoundInterval(self.moan2), delay2)
        self.moan_sequence.loop()
        
        self.parent.collision_manager.createMonsterCollision(self)

        self.aggro_sound_last_played = 0
        #--------------------------brain-------------------------
        self.node.setH( 160 )
        
        self.pause = False

        self.action = ACTION_IDLE

        if percent(20):
            self.orders = ORDERS_PATROL
        else:
            self.orders = ORDERS_IDLE

        self.last_melee = 0
        
        self.player_last_seen_abs = None

        self.idle_timer = time.time()
        self.idle_value = 1

        self.current_waypoint = None

        #self.wait_until = None
        self.herding_timer = None

        self.path = None

        taskMgr.doMethodLater(1, self.behaviourTask, 'MonsterBehaviourTask'+str(self.id) )
        taskMgr.doMethodLater(1, self.debugMoveTask, 'MonsterMoveTask'+str(self.id))


    def getLOS(self):
        return self.parent.collision_manager.checkMonsterPlayerLos(self)


    def sensePlayer(self):
        """Return True if player sensed, and his last known coordinates are stored in self.player_last_seen_abs"""
        
        # if the player is dead, do not sense him
        if self.parent.player.health <= 0:
            return False

        #get player's position
        p_pos_abs = self.parent.player.node.getPos()
        my_pos_abs = self.node.getPos()


        #--------------------------------SENSE---------------------------------
        #if player is within SENSING_RANGE we know he is there
        if self.distanceToPlayer() < SENSING_RANGE:
            #print "TOO CLOSE LOOSER!"
            self.player_last_seen_abs = p_pos_abs
            return True


        #---------------------------------HEAR----------------------------------
        #if player is within HEARING_RANGE we know he is there
        effective_hearing_range = HEARING_RANGE
        
        if self.parent.player.gunshot_at:
            effective_hearing_range *= 3
        else:
            if self.parent.player.sprint:
                effective_hearing_range *= 2
            if not self.parent.player.moving:
                effective_hearing_range = 0
                
        if self.distanceToPlayer() < effective_hearing_range:
            print "I HEAR U!"
            self.parent.player.adrenaline()
            #if we can see go chase him
            if self.getLOS():
                self.player_last_seen_abs = p_pos_abs
                return True
                
            #we cannot see him, build new path to that tile
            else:
                dest = getTile( p_pos_abs )
                path = pathFind(self.parent.level, getTile( self.node.getPos()), dest)
                if path:
                    self.path = path 
                    self.orders = ORDERS_PATROL
                    self.action = ACTION_FOLLOW_PATH
                    return False
                

        #-------------------------------SEE---------------------------------
        #if player is in front of us
        if self.angleToPlayerAbs() <= 45:
            #if he is close enough to see and we can see him
            if self.distanceToPlayer() <= VIEW_RANGE and self.getLOS():
                self.player_last_seen_abs = p_pos_abs
                #print "vidim!"
                return True
            
            #if player has a flashlight lit, and we can see him go after him
            if self.parent.player.flashlight and self.getLOS():
                self.player_last_seen_abs = p_pos_abs
                #print "vidim flashlight"
                return True
                
                
        #---------------------SEE MY OWN SHADOW---------------------------
        #if player is behind us and has a lit up flashlight and we have LOS to him
        if self.angleToPlayerAbs() > 135 and self.angleToPlayerAbs() < 225:
            if self.parent.player.flashlight and self.getLOS():
            
                #if he is looking at us
                my_pos_rel = self.node.getPos( self.parent.player.node )
                forward = Vec2( 0, 1 )
                if math.fabs( forward.signedAngleDeg( Vec2( my_pos_rel[0], my_pos_rel[1] ) ) ) <= 30:
                    #go after my own shadow
                    print "herding"
                    self.orders = ORDERS_HERDING
                    self.node.setH( self.parent.player.node.getH() )
                    self.herding_timer = time.time()
                
        return False        


    def distanceToPlayer(self):
        p_pos_abs = self.parent.player.node.getPos()
        my_pos_abs = self.node.getPos()
        return math.sqrt( math.pow( p_pos_abs[0] - my_pos_abs[0], 2) +  math.pow( p_pos_abs[1] - my_pos_abs[1], 2) )
        
        
    def angleToPlayer(self):
        p_pos_rel = self.parent.player.node.getPos( self.node )        
        forward = Vec2( 0, 1 )
        return forward.signedAngleDeg( Vec2( p_pos_rel[0], p_pos_rel[1] ) )
        
        
    def angleToPlayerAbs(self):
        return math.fabs( self.angleToPlayer() )


    def behaviourTask(self, task):
        if self.pause:
            return task.again
        
        #top priority, if we sense a player, go after him!
        if self.sensePlayer():
            if time.time() - self.aggro_sound_last_played > 5:
                self.aggro_sound.play()
                self.aggro_sound_last_played = time.time()
            
            self.action = ACTION_CHASE
            return task.again

        
        elif self.orders == ORDERS_IDLE:
            #percent chance to go on patrol
            if percent( 10 ):
                self.orders = ORDERS_PATROL
                return task.again
            self.action = ACTION_IDLE
            
        
        elif self.orders == ORDERS_PATROL:
            #percent chance to get idle
            if percent( 5 ):
                self.orders = ORDERS_IDLE
                return task.again
                      
            #if we are already patroling, dont change anything 
            if self.action == ACTION_FOLLOW_PATH:
                return task.again

            #build a new path for patrol
            dest = self.getNewPatrolPoint()
            self.path = pathFind(self.parent.level, getTile(self.node.getPos()), dest)
            self.action = ACTION_FOLLOW_PATH
                

        elif self.orders == ORDERS_HERDING:
            self.action = ACTION_MOVE
            if time.time() - self.herding_timer > HERDING_TIMEOUT:
                self.orders = ORDERS_IDLE
                
             
        return task.again
    
    
    def debugMoveTask(self, task):
        if self.pause:
            return task.cont

        #print "orders:", self.orders
        
        if self.action == ACTION_CHASE:
            self.parent.player.adrenaline()
            look_pos = Point3(self.player_last_seen_abs.getX(), self.player_last_seen_abs.getY(), self.zpos)
            self.node.lookAt( look_pos )
            self.node.setFluidPos(self.node, 0, CHASE_SPEED*globalClock.getDt(), 0)
                        
            if self.distanceToPlayer() <= MELEE_RANGE and self.angleToPlayerAbs() <= 45 and self.getLOS():
                if time.time() - self.last_melee >= MELEE_TIME:
                    self.attack_sound.play()
                    att = random.randint(0,2)
                    if att == 0:
                        animname = 'bite1'
                    elif att == 1:
                        animname = 'bite2'
                    else:
                        animname = 'head_attack'
                    self.node.play(animname)
                    duration = self.node.getNumFrames(animname) / 24  # animation play rate
                    taskMgr.doMethodLater(duration, self.finishedAnim, 'FinishedAnim', extraArgs = [])
                    self.parent.player.getDamage()
                    self.last_melee = time.time()
        
 
        elif self.action == ACTION_IDLE:
            if time.time() - self.idle_timer > IDLE_TIME:
                #we are standing still and rotating, see on whic side we will rotate now
                self.idle_timer = time.time()
                if percent(20):
                    self.idle_value *= -1
            self.rotateBy( self.idle_value * IDLE_ROTATE_SPEED )


        elif self.action == ACTION_FOLLOW_PATH:
            #if we dont have a waypoint, calculate one
            if not self.current_waypoint:
                try:
                    #get next tile from path
                    tile = self.path[0]
                    self.path = self.path[1:]
                    
                    #calculate waypoint
                    varx= 5 - (d(4) + d(4))
                    vary= 5 - (d(4) + d(4))
                    self.current_waypoint = (Point3( tile[0] * TILE_SIZE + varx, tile[1] * TILE_SIZE + vary, self.zpos ), time.time() )
                    #print "waypoint:", self.current_waypoint 
                    self.node.lookAt( self.current_waypoint[0] )
                    
                except (IndexError, TypeError):
                    #we have reached the end of path
                    self.orders = ORDERS_IDLE
                    self.current_waypoint = None
                    
            #if we have a waypoint move forward towards it, and check if we arrived at it
            else:
                self.node.setFluidPos(self.node, 0, NORMAL_SPEED*globalClock.getDt(), 0)
                my_pos = self.node.getPos() 
                
                #if we are close enough to the waypoint or if we didnt get to waypoint in time, delete it so we know we need a new one
                if math.fabs( my_pos[0] - self.current_waypoint[0][0] ) < 1 and math.fabs( my_pos[1] - self.current_waypoint[0][1] ) < 2 \
                        or time.time() - self.current_waypoint[1] > WAYPOINT_TIMER:
                    self.current_waypoint = None 


        elif self.action == ACTION_MOVE:
            self.node.setFluidPos(self.node, 0, NORMAL_SPEED*globalClock.getDt(), 0)            
 
 
        return task.cont

    def finishedAnim(self):
        if not self.pause:
            self.node.loop('walk')
        

    def rotateBy(self, value):
        self.node.setH( (self.node.getH() + value) % 360  )
        

    def getNewPatrolPoint(self):
        lvl = self.parent.level
        allTiles = lvl.getFloorTiles()
        while True:
            t = ( d(lvl.getMaxX()), d(lvl.getMaxY()) )
            if t in allTiles:
                return t
            

    def hitWall(self):
        
        if self.action == ACTION_CHASE:
            return
    
        #print "lupio!"
        """self.moan1.play()
        self.rotateBy( 180 )
        self.node.setFluidPos(self.node, 0, CHASE_SPEED*globalClock.getDt(), 0)            
        #self.action = IDLE
        """
        """
        old = self.node.getH()
        rnd = 80 + random.randint( 0, 20 )

        forward = Vec2( 0, 1 )
        impact = Vec2( pos[0], pos[1] )

        angle = forward.signedAngleDeg( impact )
        #print "angle:", angle
        
        if angle < 0:
            #+ cause angle is negative
            rnd = 91 + angle
            self.node.setH( (self.node.getH() + rnd)%360 )            
        elif angle > 0:
            rnd = -91 + angle
            self.node.setH( (self.node.getH() + rnd)%360 )
        
        #print "stari:", old, "  novi:", self.node.getH()    
        """ 
        pass

    def pauze(self):
        if self.moan_sequence:
            self.moan_sequence.pause()
        self.pause = True

        
    def resume(self):
        if self.moan_sequence:
            self.moan_sequence.resume()
        self.pause = False
        
        
    def destroy(self):
        self.audio3d.detachSound(self.moan1)
        self.audio3d.detachSound(self.moan2)
        self.audio3d.detachSound(self.shot_head)
        self.audio3d.detachSound(self.shot_body)
        self.audio3d.detachSound(self.aggro_sound)
        self.audio3d.detachSound(self.attack_sound)
        if self.moan_sequence != None:
            self.moan_sequence.pause()
            self.moan_sequence = None
        taskMgr.remove('MonsterBehaviourTask'+str(self.id))
        taskMgr.remove('MonsterMoveTask'+str(self.id))
        self.cn_head.node().clearPythonTag('node')
        self.cn_body.node().clearPythonTag('node')
        self.cn_pusher.node().clearPythonTag('node')  
        self.cn_ray.node().clearPythonTag('node')
        self.node.delete()
        self.node.cleanup()
        self.node.removeNode()
    
    """
Beispiel #29
0
class Monster():
    def __init__(self, setup_data, common, level=1.0, start_pos=(0,0,0)):
        common['monsterList'].append(self)
        id=len(common['monsterList'])-1
        self.monsterList=common['monsterList']
        self.waypoints_data=common['waypoints_data']
        self.waypoints=common['waypoints']
        self.audio3d=common['audio3d']
        self.common=common

        #root node
        self.node=render.attachNewNode("monster")
        self.sound_node=None
        self.soundset=None

        self.actor=Actor(setup_data["model"],setup_data["anim"] )
        self.actor.setBlend(frameBlend = True)
        self.actor.reparentTo(self.node)
        self.actor.setScale(setup_data["scale"]*random.uniform(0.9, 1.1))
        self.actor.setH(setup_data["heading"])
        self.actor.setBin("opaque", 10)

        self.rootBone=self.actor.exposeJoint(None, 'modelRoot', setup_data["root_bone"])

        #sounds
        self.soundID=self.common['soundPool'].get_id()
        self.common['soundPool'].set_target(self.soundID, self.node)
        self.sound_names={"hit":setup_data["hit_sfx"],
                          "arrow_hit":setup_data["arrowhit_sfx"],
                          "attack":setup_data["attack_sfx"],
                          "die":setup_data["die_sfx"]}

        self.vfx=setup_data["hit_vfx"]

        self.stats={"speed":setup_data["speed"],
                    "hp":setup_data["hp"]*level,
                    "armor":setup_data["armor"]*level,
                    "dmg":setup_data["dmg"]*level
                    }
        if self.stats['hp']>300:
            self.stats['hp']=300
        self.maxHP=self.stats['hp']
        self.HPring=Actor("models/ring_morph", {'anim' : 'models/ring_anim'})
        self.HPring.setScale(0.07)
        self.HPring.setZ(0.4)
        self.HPring.setLightOff()
        self.HPring.reparentTo(self.node)
        self.HPvis=self.HPring.controlJoint(None, 'modelRoot', 'morph01')
        self.HPvis.setX(self.stats['hp']/300)
        self.HPring.hide(BitMask32.bit(1))
        self.HPring.hide()
        #self.HPring.setColorScale(0.0, 1.0, 0.0, 1.0)

        #gamestate variables
        self.attack_pattern=setup_data["attack_pattern"]
        self.damage=setup_data["dmg"]
        #self.HP=setup_data["hp"]
        self.state="STOP"
        self.id=id
        self.nextWaypoint=None
        self.canSeePC=False
        self.PCisInRange=False
        self.PC=common['PC']
        self.speed_mode=random.randrange(0+int(level),42+int(level), 7)/100.0
        self.totalSpeed=self.stats['speed']+self.speed_mode
        self.sparkSum=0
        self.lastMagmaDmg=0
        self.DOT=0
        self.arrows=set()
        self.traverser=CollisionTraverser("Trav"+str(self.id))
        #self.traverser.showCollisions(render)
        self.queue = CollisionHandlerQueue()

        #bit masks:
        # 1  visibility polygons & coll-rays
        # 2  walls & radar-ray
        # 3  spheres

        #collision ray for testing visibility polygons
        coll=self.node.attachNewNode(CollisionNode('collRay'))
        coll.node().addSolid(CollisionRay(0, 0, 2, 0,0,-180))
        coll.setTag("id", str(id))
        coll.node().setIntoCollideMask(BitMask32.allOff())
        coll.node().setFromCollideMask(BitMask32.bit(1))
        self.traverser.addCollider(coll, self.queue)

        #radar collision ray
        self.radar=self.node.attachNewNode(CollisionNode('radarRay'))
        self.radar.node().addSolid(CollisionRay(0, 0, 1, 0,90,0))
        self.radar.node().setIntoCollideMask(BitMask32.allOff())
        self.radar.node().setFromCollideMask(BitMask32.bit(2))
        self.radar.setTag("radar", str(id))
        #self.radar.show()
        self.traverser.addCollider(self.radar, self.queue)

        #collision sphere
        self.coll_sphere=self.node.attachNewNode(CollisionNode('monsterSphere'))
        self.coll_sphere.node().addSolid(CollisionSphere(0, 0, 0.8, 0.8))
        self.coll_sphere.setTag("id", str(id))
        self.coll_sphere.node().setIntoCollideMask(BitMask32.bit(3))
        #coll_sphere.show()

        #other monster blocking
        self.coll_quad=loader.loadModel("models/plane")
        self.coll_quad.reparentTo(self.node)

        #coll_quad=render.attachNewNode(CollisionNode('monsterSphere'))
        #coll_quad.node().addSolid(CollisionPolygon(Point3(-.5, -.5, 2), Point3(-.5, .5, 0), Point3(.5, .5, 0), Point3(.5, .5, 2)))
        #coll_quad.setTag("id", str(id))
        #coll_quad.node().setIntoCollideMask(BitMask32.bit(2))
        #coll_quad.reparentTo(self.node)
        #coll_quad.show()

        Sequence(Wait(random.uniform(.6, .8)), Func(self.restart)).start()
        self.node.setPos(render,start_pos)
        taskMgr.add(self.runAI, "AIfor"+str(self.id))
        taskMgr.doMethodLater(.6, self.runCollisions,'collFor'+str(self.id))
        taskMgr.doMethodLater(1.0, self.damageOverTime,'DOTfor'+str(self.id))

    def damageOverTime(self, task):
        if self.state=="DIE":
            return task.done
        if self.DOT>0:
            self.doDamage(self.DOT)
            self.DOT=int((self.DOT*0.9)-1.0)
            if self.stats['hp']<1:
                self.actor.play("die")
                #self.common['soundPool'].play(self.soundID, self.sound_names["hit"])
                self.common['soundPool'].play(self.soundID, self.sound_names["die"])
                self.state="DIE"
            vfx(self.node, texture=self.vfx,scale=.5, Z=1.0, depthTest=True, depthWrite=True).start(0.016, 24)
        return task.again

    def restart(self):
        self.state="SEEK"

    def check_stacking(self):
        for monster in self.monsterList:
            if monster and monster.id!=self.id :
                if self.node.getDistance(monster.node)< .8:
                    if monster.state!="STOP" and self.state=="SEEK":
                        if self.totalSpeed <= monster.totalSpeed:
                            self.state="STOP"
                            self.actor.stop()
                            Sequence(Wait(1.5), Func(self.restart)).start()
                            return True

    def doDamage(self, damage, igoreArmor=False):
        if self.state=="DIE":
            return
        if not igoreArmor:
            damage-=self.stats['armor']
        if damage<1:
            damage=1
        #print damage
        self.stats['hp']-=damage
        scale=self.stats['hp']/self.maxHP
        self.HPvis.setX(self.stats['hp']/300.0)
        #self.HPring.setColor(0.8*(1.0-scale), 0.8*scale, 0.0, 1.0)
        self.HPring.show()
        self.HPring.setColorScale((1.0-scale), scale, 0.0, 1.0)
        if self.stats['hp']<1:
            self.HPring.hide()

    def attack(self, pattern):
        if self.state=="DIE":
            return
        if not self.PC.node:
            return
        if pattern:
            next=pattern.pop()
        else:
            self.state="SEEK"
            self.PCisInRange=False
            return
        if self.PC.node and self.node:
            range= self.node.getDistance(self.PC.node)
        else:
            return
        #print range
        if range<1.8:
            self.PC.hit(self.damage)
        Sequence(Wait(next), Func(self.attack, pattern)).start()

    def onMagmaHit(self):
        if self.state=="DIE":
            return
        damage=self.lastMagmaDmg
        self.doDamage(damage)
        self.common['soundPool'].play(self.soundID, "onFire")
        vfx(self.node, texture="vfx/small_flame.png",scale=.6, Z=.7, depthTest=False, depthWrite=False).start(0.016, stopAtFrame=24) 
        if self.stats['hp']<1:
            self.actor.play("die")
            self.common['soundPool'].play(self.soundID, "die3")
            self.state="DIE"
            vfx(self.node, texture=self.vfx,scale=.5, Z=1.0, depthTest=True, depthWrite=True).start(0.016)

    def onPlasmaHit(self, damage):
        if self.state=="DIE":
            return
        self.doDamage(damage*1.5, True)
        #self.soundset["spark"].play()
        #self.common['soundPool'].play(self.soundID, "spark")
        if self.stats['hp']<1:
            self.actor.play("die")
            #self.soundset["die3"].play()
            self.common['soundPool'].play(self.soundID, "die3")
            self.state="DIE"
            vfx(self.node, texture=self.vfx,scale=.5, Z=1.0, depthTest=True, depthWrite=True).start(0.016)
        #else:
        #    short_vfx(self.node, texture="vfx/short_spark.png",scale=.5, Z=1.0, depthTest=True, depthWrite=True).start(0.03)

    def onSparkHit(self, damage):
        if self.state=="DIE":
            return
        #print damage
        self.doDamage(damage)
        #self.soundset["spark"].play()
        self.common['soundPool'].play(self.soundID, "spark")
        if self.stats['hp']<1:
            self.actor.play("die")
            #self.soundset["die3"].play()
            self.common['soundPool'].play(self.soundID, "die3")
            self.state="DIE"
            vfx(self.node, texture=self.vfx,scale=.5, Z=1.0, depthTest=True, depthWrite=True).start(0.016) 
        else:
            short_vfx(self.node, texture="vfx/short_spark.png",scale=.5, Z=1.0, depthTest=True, depthWrite=True).start(0.03) 

    def onHit(self, damage, sound="hit"):
        if self.state=="DIE":
            return
        self.doDamage(damage)
        #print damage
        vfx(self.node, texture=self.vfx,scale=.5, Z=1.0, depthTest=True, depthWrite=True).start(0.016)         

        if self.stats['hp']<1:
            self.actor.play("die")
            #self.sounds["die"].play()
            if sound:
                self.common['soundPool'].play(self.soundID, self.sound_names[sound])
            self.common['soundPool'].play(self.soundID, self.sound_names["die"])
            self.state="DIE"
        else:
            #self.sounds["hit"].play()
            if sound:
                self.common['soundPool'].play(self.soundID, self.sound_names[sound])

    def findFirstWaypoint(self):
        min=100000
        nearest=None
        for waypoint in self.waypoints:
            dist=self.node.getDistance(waypoint)
            if dist<min:
                min=dist
                nearest=waypoint
        return nearest

    def runCollisions(self, task):
        if self.state=="DIE":
            return task.done
        if self.node.getDistance(self.PC.node) >50.0:
            self.nextWaypoint=None
            return task.again
        if self.check_stacking():
            return task.again
        self.radar.lookAt(self.PC.node)
        valid_waypoints=[]
        isFirstTest=True
        self.canSeePC=False
        self.traverser.traverse(render)
        self.queue.sortEntries()
        for entry in self.queue.getEntries():
            if entry.getFromNodePath().hasTag("id"): #it's the monsters collRay
                valid_waypoints.append(int(entry.getIntoNodePath().getTag("index"))) #visibility polygons
            elif entry.getFromNodePath().hasTag("radar"): #it's the radar-ray
                #print "radar hit", entry.getIntoNodePath()
                if isFirstTest:
                    isFirstTest=False
                    #print "first hit!"
                    #print "radar hit", entry.getIntoNodePath()
                    if entry.getIntoNodePath().hasTag("player"):
                        self.canSeePC=True
        '''distance={}
        for target in self.PC.myWaypoints:
            for waypoint in valid_waypoints:
                distance[target]=self.waypoints_data[target][waypoint]                
                print(target, distance[target])
        if distance:
            self.nextWaypoint=self.waypoints[min(distance, key=distance.get)]
        #print self.canSeePC'''
        if not valid_waypoints:
            #self.nextWaypoint=self.findFirstWaypoint()
            print(self.id, ": I'm lost!")
            valid_waypoints=[self.findFirstWaypoint()]
            #return task.again
        if self.state=="STOP":
            self.nextWaypoint=self.waypoints[random.choice(valid_waypoints)]
            return task.again
        best_distance=9000000
        target_node=None
        for target in self.PC.myWaypoints:
            for valid in valid_waypoints:
                distance=self.waypoints_data[target][valid]
                #print "target->valid=",target, valid, distance
                if distance<best_distance:
                    best_distance=distance
                    target_node=valid
        if target_node:
            self.nextWaypoint=self.waypoints[target_node]
        else:
            #print "no target", valid_waypoints
            self.nextWaypoint=self.findFirstWaypoint()
            #self.waypoints[random.choice(valid_waypoints)]
            #print self.nextWaypoint
        return task.again

    def runAI(self, task):
        #print self.state
        if self.state=="DIE":
            self.coll_sphere.node().setIntoCollideMask(BitMask32.allOff())
            self.coll_quad.removeNode()
            self.actor.play("die")
            self.common["kills"]-=1
            if self.common["kills"]==0:
                Interactive(self.common, data.items['key'], self.node.getPos(render))                    
            elif random.randrange(10)==0:
                Interactive(self.common, data.items['potion'], self.node.getPos(render))                 
            Sequence(Wait(2.0),LerpPosInterval(self.node, 2.0, VBase3(self.node.getX(),self.node.getY(),self.node.getZ()-5)),Func(self.destroy)).start()
            return task.done
        elif self.state=="STOP":
            target=self.nextWaypoint
            if not target:
                return task.again
            self.node.headsUp(target)
            if self.node.getDistance(target)>0.3:
               self.node.setY(self.node, self.totalSpeed*globalClock.getDt())
               if(self.actor.getCurrentAnim()!="walk"):
                   self.actor.loop("walk")
            return task.again
        elif self.state=="ATTACK":
            self.node.headsUp(self.PC.node)
            if(self.actor.getCurrentAnim()!="attack"):
                self.actor.play("attack")
                #Sequence(Wait(self.attack_pattern[-1]+self.speed_mode), Func(self.attack, list(self.attack_pattern))).start()
                Sequence(Wait(self.attack_pattern[-1]), Func(self.attack, list(self.attack_pattern))).start()
            return task.again
        elif self.state=="SEEK":
            if self.PCisInRange:
                self.state="ATTACK"
                return task.again
            target=self.nextWaypoint
            if self.canSeePC and self.PC.HP>0:
                target=self.PC.node
                #print "target pc!"
            if not target:
                return task.again
            self.node.headsUp(target)
            if self.node.getDistance(target)>0.3:
               self.node.setY(self.node, self.totalSpeed*globalClock.getDt())
               if(self.actor.getCurrentAnim()!="walk"):
                   self.actor.loop("walk")
               return task.again
            else:
                #print "I'm stuck?"
                #print target
                #print self.canSeePC
                self.nextWaypoint=self.PC.node
                return task.again

    def destroy(self):
        #for sound in self.soundset:
        #    self.soundset[sound].stop()
        #print  "destroy:",
        #self.sound_node.reparentTo(render)
        #self.common['soundPool'].append([self.sound_node,self.soundset])        
        self.common['soundPool'].set_free(self.soundID)
        #self.sounds=None
        #print  " sounds",
        self.arrows=None
        if self.actor:
            self.actor.cleanup()
            self.actor.removeNode()
            #print  " actor",
        if taskMgr.hasTaskNamed("AIfor"+str(self.id)):
            taskMgr.remove("AIfor"+str(self.id))
            #print  " AI",
        if taskMgr.hasTaskNamed('collFor'+str(self.id)):
            taskMgr.remove('collFor'+str(self.id))
            #print  " collision",
        if taskMgr.hasTaskNamed('DOTfor'+str(self.id)):
            taskMgr.remove('DOTfor'+str(self.id))
        if self.node:
            self.node.removeNode()
            #print  " node",
        self.monsterList[self.id]=None
        self.traverser=None
        self.queue=None
class Digger(enemy.Enemy):

    def __init__(self, mainRef):
        enemy.Enemy.__init__(self, mainRef, enemy.koboldSkirmisher) # Change to correct kobold

        self.holeModel = None

    def initAttributes(self, attributes):
        super(Digger, self).initAttributes(attributes)

        rangeMultiplier = 1.5
        self.combatRange *= rangeMultiplier
        self.perceptionRange *= rangeMultiplier

    def loadEnemyModel(self, modelName):
        modelPrefix = 'models/digger-'
        self.enemyModel = Actor(modelPrefix + 'model', {
                'attack1':modelPrefix+'attack1',
                'attack2':modelPrefix+'attack2',
                'attack3':modelPrefix+'attack3',
                'attack4':modelPrefix+'attack4',
                'special-attack':modelPrefix+'special-attack',

                'pursue':modelPrefix+'pursue',
                'pursue-to-idle':modelPrefix+'pursue-stop',

                'idle-walk':modelPrefix+'idle-walk',
                'idle-walk-to-pursue':modelPrefix+'idle-walk-to-pursue',
                'idle-walk-to-dig':modelPrefix+'idle-walk-to-dig',
                'idle-walk-to-dig-to-sleep':modelPrefix+'idle-walk-to-dig-to-sleep',

                'hit1':modelPrefix+'hit1',
                'hit2':modelPrefix+'hit2',

                'death1':modelPrefix+'death1',
                'death2':modelPrefix+'death2',
                'death3':modelPrefix+'death3'
            })
        self.enemyModel.reparentTo(self.enemyNode)

        self.enemyNode.setPos(Point3.zero())

        self.enemyNode.setDepthOffset(-1)

    def enterIdle(self):
        #print 'enemy enterIdle'
        #idleTime = 60.0 * 3.0

        stopEnemy = self.enemyModel.actorInterval('pursue-to-idle', startFrame=0, endFrame=12)
        idleEnemy = self.enemyModel.actorInterval('idle-walk-to-dig', startFrame=0, endFrame=60)
        digHole = Parallel(Func(self.createHole), self.enemyModel.actorInterval('idle-walk-to-dig-to-sleep', startFrame=0, endFrame=120))
        #hideEnemy = Func(self.enemyNode.hide)
        #suicide = Func(self.suicide)

        self.stopSequence = Sequence(stopEnemy, idleEnemy,  digHole)
        self.stopSequence.start()

        self.isSleeping = True

        #taskMgr.doMethodLater(3, self.showEnemy, 'showEnemyTask')

    def showEnemy(self, task):
        if self.state == 'Idle':
            self.enemyNode.show()
        return task.done

    def enterPursue(self):
        #print('enemy enterPursue')
        loopWalkEnemy = Func(self.enemyModel.loop, 'pursue', fromFrame=0, toFrame=24)

        # Only awake enemy if it comes from idle
        if self.isSleeping:
            self.isSleeping = False

            awakeEnemy = self.enemyModel.actorInterval('idle-walk-to-pursue', startFrame=0, endFrame=24)
            self.awakeSequence = Sequence(awakeEnemy, loopWalkEnemy, Func(self.pursuePlayer))
        else:
            self.awakeSequence = Sequence(loopWalkEnemy, Func(self.pursuePlayer))

        self.awakeSequence.start()

    def enterDeath(self):
        #print('enemy enterDeath')
        self.enemyAIBehaviors.removeAi('all')
        randomDeathAnim = 'death' + str(utils.getDX(3))
        self.enemyModel.play(randomDeathAnim, fromFrame=0, toFrame=12)

    def playAttackAnimation(self):
        randomAttackAnim = 'attack' + str(utils.getD4())
        self.enemyModel.play(randomAttackAnim, fromFrame=0, toFrame=12)

    def playHitAnimation(self):
        randomHitAnim = 'hit' + str(utils.getDX(2))
        self.enemyModel.play(randomHitAnim, fromFrame=0, toFrame=12)

    def createHole(self):
        if self.holeModel == None:
            self.holeModel = Actor('models/hole-model',
                                    {'anim':'models/hole-anim'})
            self.holeModel.reparentTo(self._mainRef.mainNode)

            self.holeModel.setPos(self.enemyNode, 0, -.1, 0)

            self.holeModel.play('anim', fromFrame=0, toFrame=120)

            removeHoleDelay = 12
            taskMgr.doMethodLater(removeHoleDelay, self.removeHole, 'removeHoleTask')

    def removeHole(self, task):
        if self.holeModel != None:
            self.holeModel.cleanup()
            self.holeModel.delete()

            self.holeModel = None

        return task.done
Beispiel #31
0
class DistributedEagleSuit(DistributedSuit):
    notify = directNotify.newCategory('DistributedEagleSuit')

    def __init__(self, cr):
        DistributedSuit.__init__(self, cr)
        self.eagleCry = base.audio3d.loadSfx('phase_5/audio/sfx/tt_s_ara_cfg_eagleCry.mp3')
        base.audio3d.attachSoundToObject(self.eagleCry, self)
        self.fallWhistle = base.audio3d.loadSfx('phase_5/audio/sfx/incoming_whistleALT.mp3')
        base.audio3d.attachSoundToObject(self.fallWhistle, self)
        self.explode = base.audio3d.loadSfx('phase_3.5/audio/sfx/ENC_cogfall_apart.mp3')
        base.audio3d.attachSoundToObject(self.explode, self)
        self.eventSphereNodePath = None
        self.fallingPropeller = None
        self.fallingPropProjectile = None
        self.mg = None
        self.flySpeed = 0.0
        return

    def enterNeutral(self, ts = 0):
        self.show()
        self.timestampAnimTrack = Sequence(Wait(ts), Func(self.loop, 'flyNeutral'))
        self.timestampAnimTrack.start()

    def makeStateDict(self):
        self.suitFSM.addState(State('eagleFly', self.enterEagleFly, self.exitEagleFly))
        self.suitFSM.addState(State('eagleFall', self.enterEagleFall, self.exitEagleFall))
        self.stateIndex2suitState = {0: self.suitFSM.getStateNamed('off'),
         1: self.suitFSM.getStateNamed('walking'),
         2: self.suitFSM.getStateNamed('flyingDown'),
         3: self.suitFSM.getStateNamed('flyingUp'),
         4: self.suitFSM.getStateNamed('lured'),
         5: self.suitFSM.getStateNamed('eagleFly'),
         6: self.suitFSM.getStateNamed('eagleFall')}
        self.suitState2stateIndex = {}
        for stateId, state in self.stateIndex2suitState.items():
            self.suitState2stateIndex[state.getName()] = stateId

    def setFlySpeed(self, value):
        self.flySpeed = value

    def getFlySpeed(self):
        return self.flySpeed

    def enterEagleFly(self, startIndex, endIndex, ts = 0.0):
        durationFactor = self.getFlySpeed()
        if startIndex > -1:
            startPos = EGG.EAGLE_FLY_POINTS[startIndex]
        else:
            startPos = self.getPos(render)
        endPos = EGG.EAGLE_FLY_POINTS[endIndex]
        if self.moveIval:
            self.moveIval.pause()
            self.moveIval = None
        self.moveIval = NPCWalkInterval(self, endPos, durationFactor=durationFactor, startPos=startPos, fluid=1)
        self.moveIval.start(ts)
        return

    def exitEagleFly(self):
        if self.moveIval:
            self.moveIval.pause()
            self.moveIval = None
        return

    def enterEagleFall(self, startIndex, endIndex, ts = 0.0):
        self.moveIval = LerpPosInterval(self, duration=4.0, pos=self.getPos(render) - (0, 0, 75), startPos=self.getPos(render), blendType='easeIn')
        self.moveIval.start(ts)

    def exitEagleFall(self):
        if self.moveIval:
            self.moveIval.finish()
            self.moveIval = None
        return

    def fallAndExplode(self):
        self.cleanupPropeller()
        self.fallingPropeller = Actor('phase_4/models/props/propeller-mod.bam', {'chan': 'phase_4/models/props/propeller-chan.bam'})
        self.fallingPropeller.reparentTo(render)
        self.fallingPropeller.loop('chan', fromFrame=0, toFrame=3)
        parentNode = self.attachNewNode('fallingPropParentNode')
        h = random.randint(0, 359)
        parentNode.setH(h)
        dummyNode = parentNode.attachNewNode('dummyNode')
        dummyNode.setPos(0, 10, -50)
        self.fallingPropProjectile = FlightProjectileInterval(self.fallingPropeller, startPos=self.find('**/joint_head').getPos(render), endPos=dummyNode.getPos(render), duration=5.0, gravityMult=0.25)
        self.fallingPropProjectile.start()
        dummyNode.removeNode()
        del dummyNode
        parentNode.removeNode()
        del parentNode
        self.updateHealthBar(0)
        self.ignoreHit()
        self.fallWhistle.play()
        taskMgr.doMethodLater(4.0, self.doExplodeSound, self.uniqueName('DEagleSuit-doExplodeSound'))

    def doExplodeSound(self, task):
        self.explode.play()
        return Task.done

    def __initializeEventSphere(self):
        sphere = CollisionSphere(0, 0, 0, 2)
        sphere.setTangible(0)
        node = CollisionNode(self.uniqueName('DEagleSuit-eventSphere'))
        node.addSolid(sphere)
        node.setCollideMask(CIGlobals.WallBitmask)
        np = self.attachNewNode(node)
        np.setSz(2.5)
        np.setZ(5.5)
        self.eventSphereNodePath = np

    def removeEventSphere(self):
        if self.eventSphereNodePath:
            self.eventSphereNodePath.removeNode()
            self.eventSphereNodePath = None
        return

    def acceptHit(self):
        self.acceptOnce('enter' + self.eventSphereNodePath.node().getName(), self.__handleHit)

    def ignoreHit(self):
        self.ignore('enter' + self.eventSphereNodePath.node().getName())

    def __handleHit(self, entry):
        messenger.send(EGG.EAGLE_HIT_EVENT, [self.doId])

    def setSuit(self, arg, variant):
        DistributedSuit.setSuit(self, arg, 3)
        self.deleteShadow()
        self.disableBodyCollisions()
        self.disableRay()
        self.__initializeEventSphere()
        self.show()
        self.setAnimState('flyNeutral')

    def __doEagleCry(self, task):
        self.eagleCry.play()
        task.delayTime = random.uniform(3, 30)
        return Task.again

    def announceGenerate(self):
        DistributedSuit.announceGenerate(self)
        taskMgr.doMethodLater(random.uniform(5, 25), self.__doEagleCry, self.uniqueName('DEagleSuit-doEagleCry'))
        self.acceptHit()

    def disable(self):
        self.ignoreHit()
        self.removeEventSphere()
        taskMgr.remove(self.uniqueName('DEagleSuit-doExplodeSound'))
        taskMgr.remove(self.uniqueName('DEagleSuit-doEagleCry'))
        if self.fallingPropProjectile:
            self.fallingPropProjectile.finish()
            self.fallingPropProjectile = None
        if self.fallingPropeller:
            self.fallingPropeller.cleanup()
            self.fallingPropeller = None
        base.audio3d.detachSound(self.fallWhistle)
        del self.fallWhistle
        base.audio3d.detachSound(self.explode)
        del self.explode
        base.audio3d.detachSound(self.eagleCry)
        del self.eagleCry
        self.mg = None
        DistributedSuit.disable(self)
        return
Beispiel #32
0
class PartyCog(FSM):
    notify = directNotify.newCategory("PartyCog")

    HpTextGenerator = TextNode("HpTextGenerator")
    hpText = None
    height = 7

    def __init__(self,
                 parentNode,
                 id,
                 bounceSpeed=3,
                 bounceHeight=1,
                 rotateSpeed=1,
                 heightShift=1,
                 xMoveSpeed=0,
                 xMoveDistance=0,
                 bounceOffset=0):
        self.id = id

        FSM.__init__(self, "PartyCogFSM-%d" % self.id)

        self.showFacingStatus = False
        self.xMoveSpeed = xMoveSpeed
        self.xMoveDistance = xMoveDistance
        self.heightShift = heightShift
        self.bounceSpeed = bounceSpeed
        self.bounceHeight = bounceHeight
        self.rotateSpeed = rotateSpeed
        self.parentNode = parentNode
        self.bounceOffset = bounceOffset
        self.hitInterval = None
        self.kaboomTrack = None
        self.resetRollIval = None
        self.netTimeSentToStartByHit = 0

        self.load()
        self.request("Down")

    def load(self):
        self.root = NodePath("PartyCog-%d" % self.id)
        self.root.reparentTo(self.parentNode)

        path = "phase_13/models/parties/cogPinata_"
        self.actor = Actor(
            path + "actor", {
                "idle": path + "idle_anim",
                "down": path + "down_anim",
                "up": path + "up_anim",
                "bodyHitBack": path + "bodyHitBack_anim",
                "bodyHitFront": path + "bodyHitFront_anim",
                "headHitBack": path + "headHitBack_anim",
                "headHitFront": path + "headHitFront_anim",
            })
        self.actor.reparentTo(self.root)

        self.temp_transform = Mat4()
        self.head_locator = self.actor.attachNewNode("temphead")

        self.bodyColl = CollisionTube(0, 0, 1, 0, 0, 5.75, 0.75)
        self.bodyColl.setTangible(1)
        self.bodyCollNode = CollisionNode("PartyCog-%d-Body-Collision" %
                                          self.id)
        self.bodyCollNode.setCollideMask(ToontownGlobals.PieBitmask)
        self.bodyCollNode.addSolid(self.bodyColl)
        self.bodyCollNodePath = self.root.attachNewNode(self.bodyCollNode)

        self.headColl = CollisionTube(0, 0, 3, 0, 0, 3.0, 1.5)
        self.headColl.setTangible(1)
        self.headCollNode = CollisionNode("PartyCog-%d-Head-Collision" %
                                          self.id)
        self.headCollNode.setCollideMask(ToontownGlobals.PieBitmask)
        self.headCollNode.addSolid(self.headColl)
        self.headCollNodePath = self.root.attachNewNode(self.headCollNode)

        # Cog's Left Arm
        self.arm1Coll = CollisionSphere(1.65, 0, 3.95, 1.0)
        self.arm1Coll.setTangible(1)
        self.arm1CollNode = CollisionNode("PartyCog-%d-Arm1-Collision" %
                                          self.id)
        self.arm1CollNode.setCollideMask(ToontownGlobals.PieBitmask)
        self.arm1CollNode.addSolid(self.arm1Coll)
        self.arm1CollNodePath = self.root.attachNewNode(self.arm1CollNode)

        # Cog's Right Arm
        self.arm2Coll = CollisionSphere(-1.65, 0, 3.45, 1.0)
        self.arm2Coll.setTangible(1)
        self.arm2CollNode = CollisionNode("PartyCog-%d-Arm2-Collision" %
                                          self.id)
        self.arm2CollNode.setCollideMask(ToontownGlobals.PieBitmask)
        self.arm2CollNode.addSolid(self.arm2Coll)
        self.arm2CollNodePath = self.root.attachNewNode(self.arm2CollNode)

        splatName = 'splat-creampie'
        self.splat = globalPropPool.getProp(splatName)
        self.splat.setBillboardPointEye()
        self.splatType = globalPropPool.getPropType(splatName)

        self.pieHitSound = globalBattleSoundCache.getSound(
            'AA_wholepie_only.mp3')
        self.upSound = globalBattleSoundCache.getSound('AV_jump_to_side.mp3')

        self.hole = loader.loadModel("phase_13/models/parties/cogPinataHole")
        self.hole.setTransparency(True)
        self.hole.setP(-90.0)
        self.hole.setScale(3)
        self.hole.setBin("ground", 3)
        self.hole.reparentTo(self.parentNode)

    def unload(self):
        self.request("Off")
        self.clearHitInterval()

        if self.hole is not None:
            self.hole.removeNode()
            self.hole = None

        if self.actor is not None:
            self.actor.cleanup()
            self.actor.removeNode()
            self.actor = None

        if self.root is not None:
            self.root.removeNode()
            self.root = None

        if self.kaboomTrack is not None and self.kaboomTrack.isPlaying():
            self.kaboomTrack.finish()
        self.kaboomTrack = None

        if self.resetRollIval is not None and self.resetRollIval.isPlaying():
            self.resetRollIval.finish()
        self.resetRollIval = None

        if self.hitInterval is not None and self.hitInterval.isPlaying():
            self.hitInterval.finish()
        self.hitInterval = None

        del self.upSound
        del self.pieHitSound

#===============================================================================
# FSM States
#===============================================================================

    def enterStatic(self):
        pass

    def exitStatic(self):
        pass

    def enterActive(self, startTime):
        self.root.setR(0.0)

        updateTask = Task.Task(self.updateTask)
        updateTask.startTime = startTime

        taskMgr.add(updateTask, "PartyCog.update-%d" % self.id)

    def exitActive(self):
        taskMgr.remove("PartyCog.update-%d" % self.id)
        taskMgr.remove("PartyCog.bounceTask-%d" % self.id)

        self.clearHitInterval()
        self.resetRollIval = self.root.hprInterval(0.5,
                                                   Point3(
                                                       self.root.getH(), 0.0,
                                                       0.0),
                                                   blendType="easeInOut")
        self.resetRollIval.start()

        self.actor.stop()

    def enterDown(self):
        if self.oldState == "Off":
            self.actor.pose("down", self.actor.getNumFrames("down") - 1)
            return

        self.clearHitInterval()
        startScale = self.hole.getScale()
        endScale = Point3(5, 5, 5)
        self.hitInterval = Sequence(
            LerpFunc(self.setAlongSpline,
                     duration=1.0,
                     fromData=self.currentT,
                     toData=0.0),
            LerpScaleInterval(self.hole,
                              duration=0.175,
                              scale=endScale,
                              startScale=startScale,
                              blendType="easeIn"),
            Parallel(
                SoundInterval(self.upSound,
                              volume=0.6,
                              node=self.actor,
                              cutOff=PartyGlobals.PARTY_COG_CUTOFF),
                ActorInterval(self.actor, "down", loop=0),
            ),
            LerpScaleInterval(self.hole,
                              duration=0.175,
                              scale=Point3(3, 3, 3),
                              startScale=endScale,
                              blendType="easeOut"),
        )
        self.hitInterval.start()

    def exitDown(self):
        self.root.setR(0.0)
        self.root.setH(0.0)
        self.targetDistance = 0.0
        self.targetFacing = 0.0
        self.currentT = 0.0
        self.setAlongSpline(0.0)
        self.clearHitInterval()
        startScale = self.hole.getScale()
        endScale = Point3(5, 5, 5)
        self.hitInterval = Sequence(
            LerpScaleInterval(self.hole,
                              duration=0.175,
                              scale=endScale,
                              startScale=startScale,
                              blendType="easeIn"),
            Parallel(
                SoundInterval(self.upSound,
                              volume=0.6,
                              node=self.actor,
                              cutOff=PartyGlobals.PARTY_COG_CUTOFF),
                ActorInterval(self.actor, "up", loop=0),
            ),
            Func(self.actor.loop, "idle"),
            LerpScaleInterval(self.hole,
                              duration=0.175,
                              scale=Point3(3, 3, 3),
                              startScale=endScale,
                              blendType="easeOut"),
        )
        self.hitInterval.start()

    def filterDown(self, request, args):
        if request == "Down":
            return None
        else:
            return self.defaultFilter(request, args)

#------------------------------------------------------------------------------

    def setEndPoints(self, start, end, amplitude=1.7):
        self.sinAmplitude = amplitude
        self.sinPeriod = (end.getX() - start.getX()) / 2
        self.sinDisplacement = start.getY()
        self.startPoint = start
        self.endPoint = end
        self.currentT = 0.0
        self.targetDistance = 0.0
        self.currentFacing = 0.0
        self.targetFacing = 0.0
        self.setAlongSpline(self.currentT)
        self.hole.setPos(self.root.getPos())
        self.hole.setZ(0.02)

    def rockBackAndForth(self, task):
        t = task.startTime + task.time
        angle = math.sin(t) * 20.0

        self.root.setR(angle)

        #        if self.id == 0:
        #            print angle

        return task.cont

    def updateDistance(self, distance):
        self.targetDistance = clamp(distance, -1.0, 1.0)

    def updateTask(self, task):
        self.rockBackAndForth(task)

        if self.targetDistance > self.currentT:
            self.currentT += min(0.01, self.targetDistance - self.currentT)
            self.setAlongSpline(self.currentT)
        elif self.targetDistance < self.currentT:
            self.currentT += max(-0.01, self.targetDistance - self.currentT)
            self.setAlongSpline(self.currentT)

        if self.currentT < 0.0:
            self.targetFacing = -90.0
        elif self.currentT > 0.0:
            self.targetFacing = 90.0
        else:
            self.targetFacing = 0.0

        if self.targetFacing > self.currentFacing:
            self.currentFacing += min(10,
                                      self.targetFacing - self.currentFacing)
        elif self.targetFacing < self.currentFacing:
            self.currentFacing += max(-10,
                                      self.targetFacing - self.currentFacing)

        self.root.setH(self.currentFacing)

        return task.cont

    def setAlongSpline(self, t):
        t = t + 1.0
        dist = (self.endPoint.getX() - self.startPoint.getX()) / 2.0
        x = self.startPoint.getX() + t * dist
        y = self.startPoint.getY() - math.sin(
            t * 2 * math.pi) * self.sinAmplitude
        self.root.setPos(x, y, 0)

    def startBounce(self):
        taskMgr.add(self.bounce, "PartyCog.bounceTask-%d" % self.id)

    def bounce(self, task):
        #self.root.setH(self.root.getH() - self.rotateSpeed)
        self.root.setZ((math.sin((self.bounceOffset + task.time) *
                                 self.bounceSpeed) * self.bounceHeight) +
                       self.heightShift)

        return task.cont

    def setPos(self, position):
        self.root.setPos(position)

    def respondToPieHit(self, timestamp, position, hot=False, direction=1.0):
        """The toon hit us, react appropriately."""
        assert (self.notify.debugStateCall(self))

        if self.netTimeSentToStartByHit < timestamp:
            self.__showSplat(position, direction, hot)

            if self.netTimeSentToStartByHit < timestamp:
                self.netTimeSentToStartByHit = timestamp
        else:
            #self.notify.debug('localStamp = %s, lastLocalTimeStampFromAI=%s, ignoring respondToPieHit' % (localStamp, self.lastLocalTimeStampFromAI))
            self.notify.debug(
                'respondToPieHit self.netTimeSentToStartByHit = %s' %
                self.netTimeSentToStartByHit)

    def clearHitInterval(self):
        if self.hitInterval is not None and self.hitInterval.isPlaying():
            self.hitInterval.clearToInitial()

    def __showSplat(self, position, direction, hot=False):
        """Show the splat graphic and sound."""
        if self.kaboomTrack is not None and self.kaboomTrack.isPlaying():
            self.kaboomTrack.finish()

        self.clearHitInterval()
        splatName = 'splat-creampie'
        self.splat = globalPropPool.getProp(splatName)
        self.splat.setBillboardPointEye()

        self.splat.reparentTo(render)
        self.splat.setPos(self.root, position)
        self.splat.setAlphaScale(1.0)

        if not direction == 1.0:
            #self.splat.setColorScale(Vec4(0.0, 0.0, 50.0, 1.0))
            self.splat.setColorScale(PartyGlobals.CogActivitySplatColors[0])
            if self.currentFacing > 0.0:
                facing = "HitFront"
            else:
                facing = "HitBack"
        else:
            self.splat.setColorScale(PartyGlobals.CogActivitySplatColors[1])
            #self.splat.setColorScale(Vec4(1.0, 0.6, 0.08, 1.0))
            if self.currentFacing > 0.0:
                facing = "HitBack"
            else:
                facing = "HitFront"

        if hot:
            targetscale = 0.75
            part = "head"
        else:
            targetscale = 0.5
            part = "body"

        def setSplatAlpha(amount):
            self.splat.setAlphaScale(amount)

        self.hitInterval = Sequence(
            ActorInterval(self.actor, part + facing, loop=0),
            Func(self.actor.loop, "idle"),
        )
        self.hitInterval.start()

        self.kaboomTrack = Parallel(
            SoundInterval(self.pieHitSound,
                          volume=1.0,
                          node=self.actor,
                          cutOff=PartyGlobals.PARTY_COG_CUTOFF),
            Sequence(
                Func(self.splat.showThrough),
                Parallel(
                    Sequence(
                        LerpScaleInterval(self.splat,
                                          duration=0.175,
                                          scale=targetscale,
                                          startScale=Point3(0.1, 0.1, 0.1),
                                          blendType="easeOut"),
                        Wait(0.175),
                    ),
                    Sequence(
                        Wait(0.1),
                        LerpFunc(
                            setSplatAlpha,
                            duration=1.0,  #0.4,
                            fromData=1.0,
                            toData=0.0,
                            blendType="easeOut"))),
                Func(self.splat.cleanup),
                Func(self.splat.removeNode),
            ))
        self.kaboomTrack.start()

    def showHitScore(self, number, scale=1):
        """
        Shows the hit score.
        Borrowed from otp.avatar.DistributedAvatar.showHpText
        """
        if number <= 0:
            return

        # Get rid of the number if it is already there.
        if self.hpText:
            self.hideHitScore()

        # Set the font
        self.HpTextGenerator.setFont(ToontownGlobals.getSignFont())

        # Show both negative and positive signs
        if number < 0:
            self.HpTextGenerator.setText(str(number))
        else:
            self.HpTextGenerator.setText("+" + str(number))

        # No shadow
        self.HpTextGenerator.clearShadow()

        # Center the number
        self.HpTextGenerator.setAlign(TextNode.ACenter)

        # Red, always
        #if number < 0:
        r = 1  #0.9
        g = 1  #0
        b = 0
        a = 1

        self.HpTextGenerator.setTextColor(r, g, b, a)

        self.hpTextNode = self.HpTextGenerator.generate()

        # Put the hpText over the head of the avatar
        self.hpText = render.attachNewNode(self.hpTextNode)
        self.hpText.setScale(scale)
        # Make sure it is a billboard
        self.hpText.setBillboardPointEye()
        # Render it after other things in the scene.
        self.hpText.setBin('fixed', 100)

        # Initial position ... Center of the body... the "tan tien"
        self.hpText.setPos(self.root, 0, 0, self.height / 2)

        # Black magic from the early days of Panda3D, later replaced by a Sequence
        seq = Task.sequence(
            # Fly the number out of the character
            self.hpText.lerpPos(Point3(
                self.root.getX(render), self.root.getY(render),
                self.root.getZ(render) + self.height + 1.0),
                                0.25,
                                blendType='easeOut'),
            Task.pause(0.25),
            # Fade the number
            self.hpText.lerpColor(Vec4(r, g, b, a), Vec4(r, g, b, 0), 0.1),
            # Get rid of the number
            Task.Task(self.__hideHitScoreTask))

        taskMgr.add(seq, "PartyCogHpText" + str(self.id))

    def __hideHitScoreTask(self, task):
        self.hideHitScore()

        return Task.done

    def hideHitScore(self):
        if self.hpText:
            taskMgr.remove("PartyCogHpText" + str(self.id))
            self.hpText.removeNode()
            self.hpText = None

    def getHeadLocation(self):
        (self.actor.getJoints(jointName="head")[0]).getNetTransform(
            self.temp_transform)
        self.head_locator.setMat(self.temp_transform)
        #print self.head_locator.getZ()

        return self.head_locator.getZ(self.root)
Beispiel #33
0
class Weapon(DirectObject):
	def __init__(self, x, y, z, angle, bullets, id, projZ):
		self.keyMap = {"firing":0}
		self.prevtime = 0
		#id will be 0 for player, 1 - whatever for ai's
		self.playerid = id
		
		#print(players.players[1])
		
		if str(self.playerid) == "0":
			self.accept("space", self.setKey, ["firing", 1] )
			self.accept("space-up", self.setKey, ["firing", 0] )
		#note - projectiles should be an empty list the first time you create the weapon
		self.bullets = bullets
		
		#set weapon cooldown and how long it slows a player down for
		self.cooldown = 1.0
		self.penalty = 0.5
		self.ammo = 1000
		self.range = 30
		self.idLim = 1000
		self.projId = 0
		
		
		self.angle = angle
		self.xpos = x
		self.ypos = y
		self.zpos = z
		self.projZ = projZ

		self.pistolSound = loader.loadSfx("Sound/FX/pistol.wav")

		
		#for debugging purposes only
		#taskMgr.add(self.testing, "TESTING_WEAPON")
		self.prevtime = 0
		
		self.LoadModel()
		
	#DEBUGGING PURPOSES ONLY
	#def testing(self, task):
		#camera.lookAt(self.form)
	#	self.update(0, 0, 3, 0, task.time - self.prevtime)

		
	#	self.prevtime = task.time
		
	#	return Task.cont
		
	def LoadModel(self):
		#self.form = loader.loadModel("models/weapons/revolverProxy")
		#self.form.setScale(.9)

		self.form = Actor("animations/gentlemanPistol_idle", {"idle":"animations/gentlemanPistol_idle", "shoot":"animations/gentlemanPistol_idle"})
		self.form.setPos(self.xpos, self.ypos, self.zpos)
		self.form.loop('idle')
		#self.form.setScale(5)
		#self.form.setPos(self.xpos,self.ypos,self.zpos+3)
		#self.form.setH(self.angle)

		#self.form.reparentTo(render)
	
	def setKey(self, key, value):
		self.keyMap[key] = value
	
	#note: angle is the angle that the player is facing
	#x, y, is the horizontal plane
	def update(self, x, y, z, angle, elapsed):
		"""you need to call update on the weapon every time you update player"""
		self.angle = angle
		self.xpos = x
		self.ypos = y
		self.zpos = z
		
		self.cooldown = self.cooldown - elapsed
		if self.cooldown < 0.0:
			self.cooldown = 0.0
		
		if self.keyMap["firing"] and self.cooldown == 0 and self.ammo > 0 and not players.players[self.playerid].invincible:
			self.fire()
		else:
			if self.form.getCurrentAnim() == "shoot":
				self.form.stop()
				self.form.loop('idle')
		
		for i, projectile in enumerate(self.bullets):
			#update all projectiles belonging to this weapon,
			if not projectile.update(elapsed):
				#if the projectile was destroyed, get rid of it
				self.bullets.pop(i)

		# if the player runs out of ammo (this will only happen on inherited classes, 
		# kill the thing and revert back to the pistol
		if self.ammo <= 0:
			self.kill()
			return False
		#note, when update returns false, you need to pass the weapon's projecitles
		#to the new pistol before destroying it
			
		return True
	
	def fire(self):
		"""pulls the trigger"""

		#print(len(players.players))
		#self.pistolSound.play()
		if(self.projId >= self.idLim):
			self.projId = 0
		new_projectile = Projectile(100, self.xpos, self.ypos, self.projZ, self.angle, 100, self.playerid, self.projId, len(self.bullets), players)
		self.bullets.append(new_projectile)
		self.projId = self.projId + 1
		
		#if self.playerid != 0:
		#	self.accept("projectile:" + str(self.playerid) + ":" + str(len(self.bullets)-1) + "-collision-player", self.address_bullet)
		#for i in range(1, 4):
		#	if str(i) != self.playerid:
		#		self.accept("projectile:" + str(self.playerid) + ":" + str(len(self.bullets)-1) + "-collision-ai"+str(i), self.address_bullet)
		
		if self.form.getCurrentAnim() == "idle":
			self.form.loop('shoot')
		self.cooldown = 1.0

	#occurs when there is a bullet collision
	def address_bullet(self, cEntry):
		"""called when a projectile collides with a player or ai"""
		print "bullet collision detected"
		#have the injured party incur a penalty
		handle = cEntry.getIntoNodePath().getName() #will be either ai<num> or player
		if handle == "player":
			players[0].take_damage(1)
		else:
			players[int(handle[2])].take_damage(1)
		
		#remove the bullet object
		cEntry.getFromNodePath().getParent().remove()
		
		
	def kill(self):
		"""removes the weapon from the scene"""
		self.form.cleanup()
		self.form.removeNode()
Beispiel #34
0
class KlobWorld(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)
        ## wp = WindowProperties(base.win.getProperties())
        ## wp.setSize(1280,720)
        ## base.win.requestProperties(wp)
        base.setBackgroundColor(255,250,250)
               
        self.listAudio3d = []
        self.allSounds()
        
        self.energyTime = 0
        self.collHandQue = CollisionHandlerQueue()
        self.collHandQueEne = CollisionHandlerQueue()
        
        self.SPEED = .5
        self.speedv = 4
        base.cTrav = CollisionTraverser()
        self.bossLvl = False
        self.bossDead = False
        self.isMoving = False
        self.pause = True
        self.floater = NodePath(PandaNode("floater"))
        self.floater.reparentTo(render)
        
        self.currentLevel = "start"
        
        self.keyMap = {"left":0, "right":0, "forward":0, "backward":0,
                        "cam-left":0, "cam-right":0, "cam-up":0, "cam-down":0,
                        "fire-down":0, "p":0}
        
        
        ###Disable the default camera controls###
        base.disableMouse()
        
        self.pusher = CollisionHandlerPusher()
        base.cTrav.setRespectPrevTransform(True)
        
        #Uncomment to show collisions with environment
        #base.cTrav.showCollisions(render)
        
        self.setAcceptKeys()
        self.MainMenu()

        ## List to keep track of all actors added in each level
        ## to make it easier to cleanup level when destroyed
        self.crAct = []
        self.extraElements = []
        self.laserAmo = []
        self.beamC = []
        self.laserAmoCount = 0
        self.enemyTimer = 0
        self.gunAmmoCount = 0
        self.loaded = []
        self.bulletC = []

    def allSounds(self):
    
        self.audio = Audio3DManager(self.sfxManagerList[0])
        
        self.audio.attachListener(base.camera)
        
        self.heartBeat = base.loadMusic("sounds/heartbeat.wav")
        self.cheer = base.loadMusic("sounds/cheer.wav")
        
        
        self.intro = base.loadMusic("sounds/Mario.wav")
        self.bulletSound = base.loadMusic("sounds/gun_shot.wav")
        self.laserSound = base.loadMusic("sounds/gun_shot.wav")
        self.deadSound = base.loadMusic("sounds/pacman_death.wav")
        self.sound = self.audio.loadSfx("sounds/forest.wav")
        self.gust = base.loadMusic("sounds/gust.wav")
        self.siren = base.loadMusic("sounds/siren_2.wav")
        self.waterfallSound = self.audio.loadSfx("sounds/waterfall.wav")
        self.etSound = base.loadMusic("sounds/et-sound.wav")
        self.walking = base.loadMusic("sounds/running.wav")
        self.mainMenuMusic = base.loadMusic("sounds/intro.wav")
        self.rainforestMusic = self.loader.loadSfx("sounds/rainforest.wav")
        self.egyptMusic = self.loader.loadSfx("sounds/egypt.wav")
        self.asiaMusic = self.loader.loadSfx("sounds/asia.wav")
        self.newyorkMusic = self.loader.loadSfx("sounds/newyork.wav")
        
        self.mainMenuMusic.setLoop(True)
        self.rainforestMusic.setLoop(True)
        self.egyptMusic.setLoop(True)
        self.asiaMusic.setLoop(True)
        self.newyorkMusic.setLoop(True)
        
        self.gust.setLoop(True)
        self.sound.setLoop(True)
        self.siren.setLoop(True)
        
        self.walking.setVolume(5)
        self.heartBeat.setVolume(5)
        self.deadSound.setVolume(.5)
        self.laserSound.setVolume(.2)
        self.bulletSound.setVolume(.2)
        self.sound.setVolume(2)
        self.rainforestMusic.setVolume(.6)
        self.egyptMusic.setVolume(2)
        self.siren.setVolume(.3)
    
    def stopAllSounds(self):
        self.audio.detachSound(self.waterfallSound)
        self.audio.detachSound(self.sound)
        self.audio.detachSound(self.rainforestMusic)
        self.audio.detachSound(self.egyptMusic)
        self.audio.detachSound(self.newyorkMusic)
        
        self.intro.stop()
        self.bulletSound.stop()
        self.laserSound.stop()
        self.deadSound.stop()
        self.sound.stop()
        self.gust.stop()
        self.siren.stop()
        self.waterfallSound.stop()
        self.etSound.stop()
        self.walking.stop()
        self.mainMenuMusic.stop()
        self.rainforestMusic.stop()
        self.egyptMusic.stop()
        self.asiaMusic.stop()
        self.newyorkMusic.stop()
        
        
       
    def MainMenuLevels(self):
        if(self.currentLevel != "start"):
            self.destroyLevel()
            self.stopAllSounds()
            
        self.level1Btn = DirectButton(
                                scale = (0.27,0.1,0.1),
                                command = self.loadRainforestLevel,
                                pos = Vec3(0, 0, 0.4),
                                image = 'GUI/southamericabutton.png', 
                                relief = None)
        self.level2Btn = DirectButton(
                                scale = (0.27,0.1,0.1),
                                command = self.loadAfricaLevel,
                                pos = Vec3(0, 0, 0.15),
                                image = 'GUI/africabutton.png', 
                                relief = None)
        self.level3Btn = DirectButton(
                                scale = (0.27,0.1,0.1),
                                command = self.loadAsiaLevel,
                                pos = Vec3(0, 0, -0.1),
                                image = 'GUI/asiabutton.png', 
                                relief = None)
        self.level4Btn = DirectButton(
                                scale = (0.27,0.1,0.1),
                                command = self.loadNewYorkLevel,
                                pos = Vec3(0, 0, -0.35),
                                image = 'GUI/americabutton.png', 
                                relief = None)    
       
        self.level2Btn.setTransparency(TransparencyAttrib.MAlpha)
        self.level3Btn.setTransparency(TransparencyAttrib.MAlpha)
        self.level4Btn.setTransparency(TransparencyAttrib.MAlpha)
        self.level1Btn.setTransparency(TransparencyAttrib.MAlpha)
    

    def destroyMainMenuLevels(self):
        self.level1Btn.destroy()
        self.level2Btn.destroy()
        self.level3Btn.destroy()
        self.level4Btn.destroy()
        self.mainMenuBtn = DirectButton(
                        text="Main Menu",
                        scale = (0.1,0.1,0.1),
                        command = self.MainMenuLevels,
                        pos = Vec3(0.8, 0, -0.9))
        
    def MainMenu(self):
        if(self.currentLevel == "help"):
            self.destroyHelpMenu()
        elif(self.currentLevel != "start"):
            self.destroyLevel()
            self.mainMenuBtn.destroy()
            self.stopAllSounds()
            
        self.currentLevel="start"
        self.mainMenuImage = OnscreenImage("GUI/mainmenu.png",pos = Vec3(0, 0.0,-0.8), scale=(1.8, 0, 1.8))
        self.mainMenuImage.reparentTo(aspect2d)
        self.mainMenuImage.setTransparency(1)
        self.mainMenuMusic.play()
        mapStart = loader.loadModel('GUI/button_maps.egg') 
        self.startBtn = DirectButton(geom =
                        (mapStart.find('**/start_but'),
                         mapStart.find('**/start_but_click'),
                         mapStart.find('**/start_but_roll'),
                         mapStart.find('**/start_but_disabled')),
                         relief = None,
                         command = self.introScreen,
                         scale = (0.7,0.7,0.7),
                         pos = Vec3(0.6, 0, -0.35))
        self.startBtn.setTransparency(TransparencyAttrib.MAlpha)
        mapHelp = loader.loadModel('GUI/helpbutton_maps.egg') 
        self.helpBtn = DirectButton(geom =
                        (mapHelp.find('**/help_but'),
                         mapHelp.find('**/help_but_click'),
                         mapHelp.find('**/help_but_roll'),
                         mapHelp.find('**/help_but_disabled')),
                         relief = None,
                         command = self.HelpMenu,
                         scale = (0.8,0.65,0.65),
                         pos = Vec3(0.6, 0,-0.65))
        self.helpBtn.setTransparency(TransparencyAttrib.MAlpha)
        
    def destroyMainMenu(self):
        self.startBtn.destroy()
        self.helpBtn.destroy()
        self.mainMenuImage.destroy()
        self.stopAllSounds()
        
    def HelpMenu(self):
        self.destroyMainMenu()
        self.currentLevel="help"
        self.helpMenuImage = OnscreenImage("GUI/helpmenu.png",pos = Vec3(0, 0.0,-0.8), scale=(1.8, 0, 1.8))
        self.helpMenuImage.reparentTo(aspect2d)
        self.helpMenuImage.setTransparency(1)
        
        mapHelp = loader.loadModel('GUI/backbutton_maps.egg') 
        self.backBtn = DirectButton(geom =
                        (mapHelp.find('**/backBtn'),
                         mapHelp.find('**/backBtn_click'),
                         mapHelp.find('**/backBtn_roll'),
                         mapHelp.find('**/backBtn_disabled')),
                         relief = None,
                         command = self.MainMenu,
                         scale = (0.7,0.7,0.7),
                         pos = Vec3(-1.4, 0, 0.8))
        self.backBtn.setTransparency(TransparencyAttrib.MAlpha)
      ###......
      #code missing.
     ### ....
        
    ##Records the state of the arrow keys###
    def setKey(self, key, value):
        if(self.pause is False):
            self.keyMap[key] = value
    
            
            if(self.keyMap["fire-down"] != 0 ):
                if( self.energy['value'] != 0 ):
    
                    if(self.bossDead is False):
                        self.beamC.append( self.loadLaser() )
                        self.laserAmo.append( self.laser() )
                    if(self.laserAmo):    
                        self.laserAmo[self.laserAmoCount].start()
                    self.energy['value'] -= 3
                    self.laserAmoCount = self.laserAmoCount + 1
                    
        
            
    def loadEnviron(self, filename, scale):
        
        self.environ = self.loader.loadModel(filename)
        self.environ.setScale(scale)
        self.environ.reparentTo(self.render)
        self.environ.setPos(0, 0, 0)
        self.environ.setTag('wall','1')
        self.environ.setCollideMask(BitMask32(0x01))
        
        alight = AmbientLight('alight')
        alight.setColor(VBase4(0.8, 0.8, 0.8, 1))
        alnp = render.attachNewNode(alight)
        render.setLight(alnp)
    
    
    def loadAlien(self, point):

        ###Load alien actor###
        self.alien = Actor("models/alien/slugrocket-model",
                           {"walk":"models/alien/slugrocket-anim"})
                           
        self.alien.reparentTo(render)
        self.alien.setScale(3)
        self.alien.setPos(point)
        self.alien.setPlayRate(1.2, "walk")
        self.alien.setBlend(frameBlend = True)
        
        self.dlight = DirectionalLight('my dlight')
        self.dlnp = render.attachNewNode(self.dlight)
        self.dlnp.reparentTo(base.camera)
        self.dlnp.lookAt(self.alien)
        self.dlight.setColor(VBase4(0.8, 0.8, 0.5, 1))
        render.setLight(self.dlnp)
        
        base.camera.setPos(0,-10,2)
        base.camera.reparentTo(self.alien)
        

        self.camGroundRay = CollisionRay()
        self.camGroundRay.setOrigin(0,0,1000)
        self.camGroundRay.setDirection(0,0,-1)
        self.camGroundCol = CollisionNode('camRay')
        self.camGroundCol.addSolid(self.camGroundRay)
        self.camGroundCol.setFromCollideMask(BitMask32.bit(2))
        self.camGroundCol.setIntoCollideMask(BitMask32.allOff())
        self.camGroundColNp = base.camera.attachNewNode(self.camGroundCol)
        self.camGroundHandler = CollisionHandlerQueue()
        base.cTrav.addCollider(self.camGroundColNp, self.camGroundHandler)
        
        
        csAlien = CollisionSphere(0,0,0.6,0.6)
        cnodeAlienPath = self.alien.attachNewNode(CollisionNode('csAlien'))
        cnodeAlienPath.node().addSolid(csAlien)
        self.pusher.addCollider(cnodeAlienPath, self.alien)
        base.cTrav.addCollider(cnodeAlienPath, self.pusher)
        
        ### Uncomment the following comment to show 
        ### the Collision Sphere on the alien
        ## cnodeAlienPath.show()

        self.health = DirectWaitBar(scale = 0.5,
                            range = 100,
                            value = 100,
                            barColor = (0,1,0,1),
                            pos = Vec3(0.75, 0, 0.9))
                                    
        self.energy = DirectWaitBar(scale = 0.5,
                                    range = 100,
                                    value = 100,
                                    barColor = (1,1,0,1),
                                    pos = Vec3(-0.75, 0, 0.9))
        self.energy.reparentTo(aspect2d)
        self.health.reparentTo(aspect2d)
        self.hud = OnscreenImage("GUI/hud.png",scale = Vec3(1.43, 1.0, 1.03),pos = Vec3(0, 0.0,0.045))
        self.hud.reparentTo(aspect2d)
        self.hud.setTransparency(1)
        self.extraElements.append(self.energy)
        self.extraElements.append(self.health)
        self.extraElements.append(self.hud)

        
        
    def alienDie(self, currLvl):
        self.alien.stop()
        self.pause=True
        temp = NodePath(PandaNode("temp"))
        
        base.camera.reparentTo(self.floater)
        base.camera.setZ(base.camera.getZ()+1)
        base.camera.setY(base.camera.getY()-25)
        self.deadSound.play()
        
        fall = LerpHprInterval(nodePath=self.alien, duration=1.5, hpr=(self.alien.getH(),self.alien.getP(), self.alien.getR()-80))
        fall.start()
        
        
        taskMgr.remove("moveTask")
        taskMgr.remove("laterFc")
        transition = Transitions(loader) 
        transition.setFadeColor(0, 0, 0)
        self.dieImage = OnscreenImage("GUI/died.png",scale = Vec3(0.7, 0, 0.2),pos = Vec3(0, 0,-0.5))
        self.dieImage.reparentTo(aspect2d)
        self.dieImage.setTransparency(1)
        if(self.currentLevel == "rainforest"):
            Sequence(Wait(2.0),Func(transition.fadeOut),Wait(2.0),Func(self.destroyLevel),Func(self.loadRainforestLevel),Func(self.dieImage.destroy),Func(transition.fadeIn)).start()
        elif(self.currentLevel == "africa"):
            Sequence(Wait(2.0),Func(transition.fadeOut),Wait(2.0),Func(self.destroyLevel),Func(self.loadAfricaLevel),Func(self.dieImage.destroy),Func(transition.fadeIn)).start()
        elif(self.currentLevel == "asia"):
            Sequence(Wait(2.0),Func(transition.fadeOut),Wait(2.0),Func(self.destroyLevel),Func(self.loadAsiaLevel),Func(self.dieImage.destroy),Func(transition.fadeIn)).start()
        elif(self.currentLevel == "newyork"):
            Sequence(Wait(2.0),Func(transition.fadeOut),Wait(2.0),Func(self.destroyLevel),Func(self.loadNewYorkLevel),Func(self.dieImage.destroy),Func(transition.fadeIn)).start()
        
        
    def collide(self, collEntry):
        collEntry.getFromNodePath().getParent().removeNode()
        
        
        
    def setAcceptKeys(self):
        
        ###Accept the control keys for movement and rotation###
        self.accept("escape", sys.exit)
        self.accept("p", self.setKey, ["p",1])
        
        
        self.accept("arrow_up", self.setKey, ["forward",1])
        self.accept("arrow_up-up", self.setKey, ["forward",0])
        
        self.accept("arrow_down", self.setKey, ["backward", 1])
        self.accept("arrow_down-up", self.setKey, ["backward", 0])
        
        self.accept("arrow_left", self.setKey, ["left",1])
        self.accept("arrow_left-up", self.setKey, ["left",0])
        
        self.accept("arrow_right", self.setKey, ["right",1])
        self.accept("arrow_right-up", self.setKey, ["right",0])

        self.accept("a", self.setKey, ["cam-left",1])
        self.accept("a-up", self.setKey, ["cam-left",0])
        
        self.accept("s", self.setKey, ["cam-right",1])    
        self.accept("s-up", self.setKey, ["cam-right",0])
        
        self.accept("z", self.setKey, ["cam-up",1])
        self.accept("z-up", self.setKey, ["cam-up",0])
        
        self.accept("x", self.setKey, ["cam-down", 1])
        self.accept("x-up", self.setKey, ["cam-down", 0])
        
        # Accept f to fire 
        self.accept("f", self.setKey, ["fire-down",1])
        self.accept("f-up", self.setKey, ["fire-down",0])
        self.cTrav.traverse(render)
    
        
    
    
    #gun / laser code ommitted
    
    def getDistance(self, actor):
       self.vecAlien = Vec3(self.alien.getPos())
       self.vecObj = Vec3(actor.getPos())
       disVec = self.vecObj - self.vecAlien

       return disVec.length()    

    def myFunction(self,task):
        
        self.walking.play()
        
        if(self.pause is False):
            for r in range(0, len(self.crAct)):
                self.crAct[r].setTarget(self.alien)     
                self.bulletC.append( self.createBullet(self.crAct[r]) )
                self.loaded.append( self.loadBullet( self.crAct[r]) )                        
                self.loaded[self.gunAmmoCount].start()
                self.gunAmmoCount += 1
                self.bulletSound.play()
            return task.again    
        
        
    def bossLvlTask(self, dec, task):
        self.crAct[0].setAiPursue(self.alien)
                
        if(self.pause is False):
            self.deleteProjectiles()
            
            self.charcMoveKeys()
            startpos = self.alien.getPos()
            
            self.floater.setPos(self.alien.getPos())
            self.floater.setZ(self.alien.getZ() + 2.0)
            base.camera.lookAt(self.floater)
            
            self.collHandQueEne.sortEntries()
            
            if(self.collHandQueEne.getNumEntries() > 0):
                entryb = self.collHandQueEne.getEntry(0)
              
                if( entryb.getIntoNodePath().getName() == "csAlien"):
                    
                    self.health['value'] -=5
                    if(self.bulletC):
                        self.bulletC[self.gunAmmoCount-1].remove()
                        self.bulletC.pop(self.gunAmmoCount-1)
                        self.loaded.pop(self.gunAmmoCount-1)
                        self.gunAmmoCount -= 1
                    if( self.health['value'] < 20 ):
                        self.heartBeat.play()
                    if(self.health['value'] == 0):
                        self.alienDie(self.currentLevel)
                else:
                    self.bulletC[self.gunAmmoCount-1].remove()
                    self.bulletC.pop(self.gunAmmoCount-1)
                    self.loaded.pop(self.gunAmmoCount-1)
                    self.gunAmmoCount -= 1
                    
                    
            self.collHandQue.sortEntries()
            if( self.collHandQue.getNumEntries() > 0 ):
                
                entry = self.collHandQue.getEntry(0)   
                

                if( entry.getIntoNodePath().getName() == self.crAct[0].getCNP()):
                            
                    self.crAct[0].runAround(self.alien)
                            
                    self.crAct[0].setHitCount(1)
                    self.crAct[0].decreaseHealth(dec)
                            
                    if( self.beamC):
                        self.beamC[self.laserAmoCount-1].remove()
                        self.beamC.pop(self.laserAmoCount-1)
                        if(self.laserAmo):
                            self.laserAmo.pop(self.laserAmoCount-1)
                        self.laserAmoCount -= 1

                    if( self.crAct[0].getHealth()%4 == 0):
                        self.crAct[0].jumpAway(self.alien)
                                
                    if( self.crAct[0].getHealth() == 0 ):
                        ## print x.getDeaths()
                        ## if( x.canRespawn() ):
                            ## x.setDeaths(1)
                            ## x.resetHitCount(0)
                
                                    
                            ## x.setX(random.randint(0, 50))
                            ## x.setY(self.alien.getY()+15)
                        ## else:
                        self.crAct[0].cleanup()
                        self.crAct[0].remove()
                        self.crAct.pop(0)
                        self.cutScene()
                           
        if( self.crAct ):
            self.crAct[0].AIworld.update()
                                
        if( self.keyMap["p"]!= 0):
            self.cutScene()
                    
        return task.cont
    
    
    def move(self, task):
        ##ommmitted
        
               
            return task.cont

    
    def deleteProjectiles(self):
        ## if(self.pause is False):
        if(self.laserAmo):
            for i, x in enumerate(self.laserAmo):
                if( not x.isPlaying() ):
                        
                    self.beamC[i].remove()
                    self.beamC.pop(i)
                    self.laserAmo.pop(i)
                    self.laserAmoCount = self.laserAmoCount -1
                        
        if(self.loaded):
            for i, x in enumerate(self.loaded):
                if(not x.isPlaying()):
                    #self.crAct[i].setTarget(self.alien)
                    self.bulletC[i].remove()
                    self.bulletC.pop(i)
                    self.loaded.pop(i)
                    self.gunAmmoCount = self.gunAmmoCount -1
                        
        self.energyTime = self.energyTime + globalClock.getDt()
            
        if(self.energyTime > 2 ):
            if(self.energy['value'] != 100):
                self.energy['value'] +=5
                self.energyTime = 0
                    

    def charcMoveKeys(self):
        if (self.keyMap["cam-left"]!=0):
            base.camera.setX(base.camera, -20 * globalClock.getDt())
                
        if (self.keyMap["cam-right"]!=0):
            base.camera.setX(base.camera, +20 * globalClock.getDt())
                
        if (self.keyMap["cam-up"]!=0):
            base.camera.setY(base.camera, -20 * globalClock.getDt())
                
        if (self.keyMap["cam-down"]!=0):
            base.camera.setY(base.camera, +20 * globalClock.getDt())
                
        if (self.keyMap["forward"]!=0):
            self.alien.setY(self.alien, 10 * globalClock.getDt())
                
                
        if (self.keyMap["backward"]!=0):
            self.alien.setY(self.alien, -10 * globalClock.getDt())
        
                    
        if (self.keyMap["left"]!=0):
                self.alien.setH(self.alien.getH() + 40 * globalClock.getDt())

                
        if (self.keyMap["right"]!=0):
                self.alien.setH(self.alien.getH() - 40 * globalClock.getDt())

        if (self.keyMap["forward"]!=0) or (self.keyMap["left"]!=0) or (self.keyMap["right"]!=0) or (self.keyMap["backward"] != 0):
            if self.isMoving is False:
                self.alien.loop("walk")
                self.isMoving = True
        else:
            if self.isMoving:
                self.alien.stop()
                self.alien.pose("walk",5)
                self.isMoving = False
                

    def loadingScreen(self):
        self.intro.play()
        transition = Transitions(loader) 
        transition.setFadeColor(0, 0, 0)
        text = TextNode('node name')
        dummy = NodePath(PandaNode("dummy"))
        black = OnscreenImage(image="GUI/black.png",pos=(0,0,0), scale=100)
        black.reparentTo(dummy)
        textNodePath = aspect2d.attachNewNode(text)
        textNodePath.reparentTo(aspect2d, 2)
        textNodePath.setScale(0.07)
        text.setTextColor(1, 1, 1, 1)
        
        if(self.currentLevel=="newyork"):
            Sequence(Func(transition.fadeOut),Func(black.reparentTo, aspect2d),Func(transition.fadeIn),Func(textNodePath.reparentTo,aspect2d, 10),Func(text.setText, "loading"),Wait(1.0),Func(text.setText, "loading."), 
                    Wait(1.0),Func(text.setText, "loading.."), Wait(1.0), Func(text.setText, "loading..."), Func(self.loadNextLevel),Wait(3.0),Func(transition.fadeIn),Func(textNodePath.remove), Func(black.destroy)).start()
        elif(self.currentLevel=="asia"):
            Sequence(Func(transition.fadeOut),Func(black.reparentTo, aspect2d),Func(transition.fadeIn),Func(textNodePath.reparentTo,aspect2d, 10),Func(text.setText, "loading"),Wait(1.0),Func(text.setText, "loading."), 
                    Wait(1.0),Func(text.setText, "loading.."), Wait(1.0), Func(text.setText, "loading..."), Func(self.loadNextLevel),Wait(3.0),Func(transition.fadeIn),Func(textNodePath.remove), Func(black.destroy)).start()
        else:
            Sequence(Func(transition.fadeOut),Func(black.reparentTo, aspect2d),Func(transition.fadeIn),Func(textNodePath.reparentTo,aspect2d, 10),Func(text.setText, "loading"),Wait(0.5),Func(text.setText, "loading."), 
                    Wait(0.5),Func(text.setText, "loading.."), Wait(0.5), Func(text.setText, "loading..."), Func(self.loadNextLevel),Wait(1.5),Func(transition.fadeIn),Func(textNodePath.remove), Func(black.destroy)).start()
        
        
    def cutScene(self):
        self.destroyLevel()
        self.stopAllSounds()
        
        self.cut = OnscreenImage("GUI/bossKilled.png",scale = Vec3(1.6, 0, 1.0),pos = Vec3(0, 0,0))
        self.cut.reparentTo(aspect2d)
        self.cut.setTransparency(1)
        transition = Transitions(loader) 
        transition.setFadeColor(0, 0, 0)
        self.cheer.play()
        if(self.currentLevel=="rainforest"):
            Sequence(Wait(2.0),Func(transition.fadeOut),Wait(1.0),Func(transition.fadeIn),Func(self.cut.setImage,"GUI/map_11.png"),
                     Wait(1.5),Func(self.cut.setImage, "GUI/map_12.png"),Wait(0.5),Func(self.cut.setImage,"GUI/map_13.png"),
                     Wait(0.5),Func(self.cut.setImage,"GUI/map_14.png"),Wait(0.5),Func(self.cut.setImage,"GUI/map_15.png"),
                     Wait(0.5),Func(self.cut.setImage,"GUI/map_16.png"),Wait(3.5),Func(self.cut.destroy), Func(transition.fadeOut), Func(self.loadingScreen), Wait(1.0),Func(transition.fadeIn)).start()
        elif(self.currentLevel=="africa"):
            Sequence(Wait(2.0),Func(transition.fadeOut),Wait(1.0),Func(transition.fadeIn),Func(self.cut.setImage,"GUI/map_21.png"),
                     Wait(1.5),Func(self.cut.setImage, "GUI/map_22.png"),Wait(0.5),Func(self.cut.setImage,"GUI/map_23.png"),
                     Wait(0.5),Func(self.cut.setImage,"GUI/map_24.png"),Wait(0.5),Func(self.cut.setImage,"GUI/map_25.png"),
                     Wait(0.5),Func(self.cut.setImage,"GUI/map_26.png"), Wait(3.5),Func(self.cut.destroy), Func(transition.fadeOut),Func(self.loadingScreen), Wait(1.0),Func(transition.fadeIn)).start()
        elif(self.currentLevel=="asia"):
            Sequence(Wait(2.0),Func(transition.fadeOut),Wait(1.0),Func(transition.fadeIn),Func(self.cut.setImage,"GUI/map_31.png"),
                     Wait(1.5),Func(self.cut.setImage, "GUI/map_32.png"),Wait(0.5),Func(self.cut.setImage,"GUI/map_33.png"),
                     Wait(0.5),Func(self.cut.setImage,"GUI/map_34.png"),Wait(0.5),Func(self.cut.setImage,"GUI/map_35.png"),
                     Wait(0.5),Func(self.cut.setImage,"GUI/map_36.png"),Wait(3.5),Func(self.cut.destroy), Func(transition.fadeOut),Func(self.loadingScreen), Wait(1.0),Func(transition.fadeIn)).start()
        elif(self.currentLevel=="newyork"):
            Sequence(Wait(2.0),Func(transition.fadeOut),Wait(1.0),Func(transition.fadeIn),Func(self.cut.setImage,"GUI/win.png"),
                     Wait(6.5),Func(self.cut.destroy), Func(transition.fadeOut),Func(self.loadingScreen), Wait(1.0),Func(transition.fadeIn)).start()
            
     
    def loadNextLevel(self):
        if(self.currentLevel=="start"):
            self.loadRainforestLevel()
        elif(self.currentLevel=="rainforest"):
            self.loadAfricaLevel()
        elif(self.currentLevel=="africa"):
            self.loadAsiaLevel()
        elif(self.currentLevel=="asia"):
            self.loadNewYorkLevel()
        else:
            self.MainMenu()
  
    def destroyLevel(self):
        self.mainMenuBtn.destroy()
        taskMgr.remove("moveTask")
        taskMgr.remove("bossTask")
        taskMgr.remove("myFunction")
        self.alien.cleanup()
        for enemy in self.crAct:
            enemy.cleanup()
            enemy.remove()
        self.alien.cleanup()
        self.alien.remove()    
        for element in self.extraElements:
            element.removeNode()
        for beam in self.beamC:
            beam.removeNode()
        self.render.clearFog    
        self.laserBeam2.removeNode()
        
        self.environ.removeNode()
        self.crAct[:] = []
        self.extraElements[:] = []

        self.laserAmo[:] =[]
        self.laserAmoCount = 0

        
    def loadBossActor(self):
        self.bossLvl = True
        ###Load Ralph Boss actor###
        difficult = 10
        taskMgr.remove("moveTask")
        taskMgr.remove("myFunction")
        self.health['value'] = 100
        self.energy['value'] = 100
        
        if(self.bossDead is False):
            self.bossImage = OnscreenImage("GUI/bossLoad.png",scale = Vec3(1.6, 0, 1.0),pos = Vec3(0, 0,0))
            self.bossImage.reparentTo(aspect2d)
            self.bossImage.setTransparency(1)
            self.ralphBoss = EnemyActor(1,difficult,True)
            self.ralphBoss.enemy.setScale(2.0)
            self.crAct.append(self.ralphBoss)
            Sequence(Wait(3.0), Func(self.bossImage.destroy), Func(self.crAct[0].showHealthBar)).start()
            
            self.extraElements.append(self.crAct[0].bossHud)
            self.extraElements.append(self.crAct[0].health)
            self.crAct[0].setAiPursue(self.alien)
            self.pusher.addCollider(self.crAct[0].getFromObj(), self.crAct[0].enemy)
            base.cTrav.addCollider(self.crAct[0].getFromObj(), self.pusher)
            gunTex = loader.loadTexture('models/gun_tex.png')
            if(self.currentLevel == "rainforest"):
                dec = 5
                self.ralphBoss.enemy.setPos(0,90,0)
                ralphTex = loader.loadTexture('models/ralph2rainforest.png')
                self.ralphBoss.enemy.setTexture(ralphTex, 1)
                self.ralphBoss.gunPos.setTexture(gunTex, 1)
            elif(self.currentLevel == "africa"):
                dec = 4
                self.ralphBoss.enemy.setPos(-100,-90,0)
                ralphTex = loader.loadTexture('models/ralph2egypt.png')
                self.ralphBoss.enemy.setTexture(ralphTex, 1)
                self.ralphBoss.gunPos.setTexture(gunTex, 1)
            elif(self.currentLevel == "asia"):
                dec = 3
                self.ralphBoss.enemy.setPos(0,0,0)
                ralphTex = loader.loadTexture('models/ralph2asia.png')
                self.ralphBoss.enemy.setTexture(ralphTex, 1)
                self.ralphBoss.gunPos.setTexture(gunTex, 1)
            elif(self.currentLevel == "newyork"):
                dec = 2
                self.ralphBoss.enemy.setPos(120,10,0)
         
        taskMgr.add(self.bossLvlTask,"bossTask", extraArgs = [dec], appendTask=True)
        taskMgr.doMethodLater(1,self.myFunction,"myFunction")
            
    
    
    def loadRainforestLevel(self):
        self.keyMap = {"left":0, "right":0, "forward":0, "backward":0,
                        "cam-left":0, "cam-right":0, "cam-up":0, "cam-down":0,
                        "fire-down":0,  "p":0}
        self.pause = False
        self.currentLevel = "rainforest"
        self.destroyIntro()
        difficulty = 2
        self.bossLvl = False
        self.bossDead = False
        ###Load alien###
        startPos = Point3(0,0,0)
        self.loadAlien(startPos)
        self.rainforestMusic.play()
        ###Load the enemies###
        ralphTex = loader.loadTexture('models/ralph2rainforest.png')
        gunTex = loader.loadTexture('models/gun_tex.png')
        for i in range(0,2):
            enemy = EnemyActor(i, difficulty, False)
            enemy.enemy.setTexture(ralphTex, 1)
            enemy.gunPos.setTexture(gunTex, 1)
            
            enemy.setX(random.randint(-50,50))
            enemy.setY(random.randint(-50,50))
            enemy.setZ(0)
            
            self.crAct.append(enemy)
            self.crAct[i].setAiPursue(self.alien)
            
            self.pusher.addCollider(self.crAct[i].getFromObj(), self.crAct[i].enemy)
            base.cTrav.addCollider(self.crAct[i].getFromObj(), self.pusher)
        
            
        taskMgr.add(self.move,"moveTask")
        taskMgr.doMethodLater(3,self.myFunction,"myFunction")
        self.loadLaser2()
        self.loadLaser()
        
        ###Load the environment###
        self.loadEnviron("models/south_america/rainforest", 5)
        self.plants = self.loader.loadModel("models/south_america/rainforest-nocollision")
        self.plants.reparentTo(self.render)
        self.plants.setScale(4)
        self.plants.setTwoSided(True)
        self.extraElements.append(self.plants)
        
        self.myFog = Fog("FOG")
        self.myFog.setColor(0.5,0.6,0.5)
        self.myFog.setExpDensity(0.005)
        render.setFog(self.myFog)
        self.audio.attachSoundToObject(self.sound, self.environ)
        self.audio.setSoundVelocityAuto(self.sound)
        self.audio.setListenerVelocityAuto()
        
        self.sound.play()
        
    
    def loadAfricaLevel(self):
        self.keyMap = {"left":0, "right":0, "forward":0, "backward":0,
                        "cam-left":0, "cam-right":0, "cam-up":0, "cam-down":0,
                        "fire-down":0, "p":0}
        self.pause = False
        self.currentLevel="africa"
        
        difficulty = 3
        self.bossLvl = False
        self.bossDead = False
        ###Load alien###
        startPos = Point3(-130,-130,0)
        self.loadAlien(startPos)
        self.alien.setH(-40)
        
        ###Load the enemies###
        ralphTex = loader.loadTexture('models/ralph2egypt.png')
        gunTex = loader.loadTexture('models/gun_tex.png')
        for i in range(0,3):
            enemy = EnemyActor(i, difficulty, False)
            enemy.enemy.setTexture(ralphTex, 1)
            enemy.gunPos.setTexture(gunTex, 1)
            enemy.setX(random.randint(-170,-50))
            enemy.setY(random.randint(-170,-50))
            enemy.setZ(0)
        
            self.crAct.append(enemy)
            
            self.crAct[i].setAiPursue(self.alien)
            
            self.pusher.addCollider(self.crAct[i].getFromObj(), self.crAct[i].enemy)
            base.cTrav.addCollider(self.crAct[i].getFromObj(), self.pusher)

        taskMgr.add(self.move,"moveTask")
        taskMgr.doMethodLater(3,self.myFunction,"myFunction")
        
        self.loadLaser2()
        self.loadLaser()
       
        ###Load environment###
        self.loadEnviron("models/africa/egypt", 7)
        self.egypt_nc = self.loader.loadModel("models/africa/egypt-nocollision")
        self.egypt_nc.reparentTo(self.render)
        self.egypt_nc.setPos(0,0,0)
        self.egypt_nc.setScale(7)
        self.extraElements.append(self.egypt_nc)
        self.sphinx = self.loader.loadModel("models/africa/sphinx")
        self.sphinx.setPos(0,80,0)
        self.sphinx.setH(180)
        self.sphinx.setScale(0.12)
        self.sphinx.reparentTo(self.render)
        self.extraElements.append(self.sphinx)
        
        cs = CollisionSphere(0,0,0,200)
        nodePath = self.sphinx.attachNewNode(CollisionNode('nodePath'))
        nodePath.node().addSolid(cs)
        self.gust.play()
        self.audio.attachSoundToObject(self.egyptMusic, self.environ)
        self.audio.setSoundVelocityAuto(self.egyptMusic)
        self.audio.setListenerVelocityAuto()
        self.egyptMusic.play()
        
        
    def loadAsiaLevel(self):
        self.keyMap = {"left":0, "right":0, "forward":0, "backward":0,
                        "cam-left":0, "cam-right":0, "cam-up":0, "cam-down":0,
                        "fire-down":0, "p":0}
        self.pause = False
        self.currentLevel = "asia"

        difficulty = 4
        self.bossLvl = False
        self.bossDead = False
        ###Load alien###
        startPos = Point3(190,-140,0)
        self.loadAlien(startPos)
        ###Load the enemies###
        ralphTex = loader.loadTexture('models/ralph2asia.png')
        gunTex = loader.loadTexture('models/gun_tex.png')
        for i in range(0,4):
            enemy = EnemyActor(i, difficulty, False)
            enemy.enemy.setTexture(ralphTex, 1)
            enemy.gunPos.setTexture(gunTex, 1)
            enemy.setX(random.randint(0,100))
            enemy.setY(random.randint(-150,-50))
            enemy.setZ(0)
      
            self.crAct.append(enemy)
            self.crAct[i].setAiPursue(self.alien)
            
            self.pusher.addCollider(self.crAct[i].getFromObj(), self.crAct[i].enemy)
            base.cTrav.addCollider(self.crAct[i].getFromObj(), self.pusher)
            
        taskMgr.add(self.move,"moveTask")
        taskMgr.doMethodLater(3,self.myFunction,"myFunction")
        
        self.loadLaser2()
        self.loadLaser()
        
        ###Load the environment###
        self.loadEnviron("models/asia/asia2", 5)
        self.asia_nc = self.loader.loadModel("models/asia/asia-nocollision")
        self.asia_nc.reparentTo(self.render)
        self.asia_nc.setPos(0,0,0)
        self.asia_nc.setScale(5)
        self.extraElements.append(self.asia_nc)
        
        self.myFog = Fog("FOG")
        self.myFog.setColor(0.8,0.8,0.8)
        self.myFog.setExpDensity(0.002)
        render.setFog(self.myFog)
        
        self.bonzai = self.loader.loadModel("models/asia/bonzai")
        self.bonzai.reparentTo(self.render)
        self.bonzai.setPos(170,20,0)
        self.bonzai.setScale(0.015)
        self.bonzai.setH(90)
        self.extraElements.append(self.bonzai)
        cs = CollisionSphere(0,0,200,200)
        nodePath = self.bonzai.attachNewNode(CollisionNode('nodePath'))
        nodePath.node().addSolid(cs)
        self.pusher.addCollider(nodePath, self.bonzai)
        
        self.waterfall = self.loader.loadModel("models/asia/waterFall")
        self.waterfall.reparentTo(self.render)
        self.waterfall.setPos(200,80,-.5)
        self.waterfall.setScale(0.25)
        self.waterfall.setH(180)
        self.extraElements.append(self.waterfall)
        cs = CollisionSphere(0,15,-5,130)
        nodePath = self.waterfall.attachNewNode(CollisionNode('nodePath'))
        nodePath.node().addSolid(cs)
        self.pusher.addCollider(nodePath, self.waterfall)
        
        self.waterfallSound.setLoop(True)
        self.audio.attachSoundToObject(self.waterfallSound,self.waterfall)
        self.audio.setSoundVelocityAuto(self.waterfallSound)
        self.audio.setListenerVelocityAuto()
        self.audio.setDistanceFactor(1.5)
        self.waterfallSound.play()
        
        self.tree1 = self.loader.loadModel("models/asia/bamboo")
        self.tree1.reparentTo(self.render)
        self.tree1.setPos(-50,-50,0)
        self.tree1.setScale(0.6,0.6,0.6)
        self.tree1.setBillboardAxis()
        self.extraElements.append(self.tree1)
        
        #Child bamboos scattered around
        placeholder = render.attachNewNode("Bamboo-Placeholder")
        placeholder.setPos(180,-40,0)
        placeholder.setScale(0.8)
        self.tree1.instanceTo(placeholder)
        self.extraElements.append(placeholder)
        
        placeholder = render.attachNewNode("Babmboo-Placeholder")
        placeholder.setPos(-20,-120,0)
        placeholder.setScale(1.0)
        self.tree1.instanceTo(placeholder)
        self.extraElements.append(placeholder)
                
        placeholder = render.attachNewNode("Bamboo-Placeholder")
        placeholder.setPos(-50,180,0)
        placeholder.setScale(1.0)
        self.tree1.instanceTo(placeholder)
        self.extraElements.append(placeholder)
        
        placeholder = render.attachNewNode("Bamboo-Placeholder")
        placeholder.setPos(-60,165,0)
        placeholder.setScale(0.6)
        self.tree1.instanceTo(placeholder)
        self.extraElements.append(placeholder)
        
        placeholder = render.attachNewNode("Bamboo-Placeholder")
        placeholder.setPos(-110,70,0)
        placeholder.setScale(1.0)
        self.tree1.instanceTo(placeholder)
        self.extraElements.append(placeholder)
        
        placeholder = render.attachNewNode("Bamboo-Placeholder")
        placeholder.setPos(-100,-50,0)
        placeholder.setScale(1.6)
        self.tree1.instanceTo(placeholder)
        self.extraElements.append(placeholder)
        
        self.asiaMusic.play()

    
    def loadNewYorkLevel(self):
        self.keyMap = {"left":0, "right":0, "forward":0, "backward":0,
                        "cam-left":0, "cam-right":0, "cam-up":0, "cam-down":0,
                        "fire-down":0,"p":0}
        self.pause = False
        self.currentLevel = "newyork"
        #self.destroyMainMenuLevels()
        difficulty = 5
        ###Load alien###
        startPos = Point3(20,10,0)
        self.loadAlien(startPos)
        self.alien.setH(90)
        
        base.camera.setH(90)
        self.bossLvl = False
        self.bossDead = False
        ###Load the enemies###
        for i in range(0,5):
            enemy = EnemyActor(i, difficulty, False)      
            enemy.setX(random.randint(-100,100))
            enemy.setY(random.randint(8,12))
            enemy.setZ(0)
            
            self.crAct.append(enemy)
            self.crAct[i].setAiPursue(self.alien)
            
            self.pusher.addCollider(self.crAct[i].getFromObj(), self.crAct[i].enemy)
            base.cTrav.addCollider(self.crAct[i].getFromObj(), self.pusher)
            
        taskMgr.add(self.move,"moveTask")
        taskMgr.doMethodLater(2,self.myFunction, "myFunction")
     
        self.loadLaser2()
        self.loadLaser()
        
        ###Load the environment###
        self.loadEnviron("models/america/newyork", 4)
        self.ny_nc = self.loader.loadModel("models/america/newyork-nocollision")
        self.ny_nc.reparentTo(self.render)
        self.ny_nc.setScale(4)
        self.extraElements.append(self.ny_nc)
        
        self.statue = self.loader.loadModel("models/america/statue")
        self.statue.reparentTo(self.render)
        self.statue.setPos(270,-100,13)
        self.statue.setScale(1)
        self.statue.setBillboardAxis()
        self.statue.setTwoSided(True)
        self.extraElements.append(self.statue)
        
        self.myFog = Fog("FOG")
        self.myFog.setColor(0.3,0.3,0.3)
        self.myFog.setExpDensity(0.005)
        render.setFog(self.myFog)
        self.siren.play()
        self.newyorkMusic.play()
Beispiel #35
0
class GameObject():
    def __init__(self, pos, modelName, modelAnims, maxHealth, maxSpeed,
                 colliderName, height, weaponIntoMask):
        self.root = render.attachNewNode(PandaNode("obj"))

        self.colliderName = colliderName

        self.modelName = modelName

        if modelName is None:
            self.actor = NodePath(PandaNode("actor"))
        elif modelAnims is None:
            self.actor = loader.loadModel(modelName)
        else:
            self.actor = Actor(modelName, modelAnims)
        self.actor.reparentTo(self.root)

        if pos is not None:
            self.root.setPos(pos)

        self.height = height

        self.maxHealth = maxHealth
        self.health = maxHealth

        self.maxSpeed = maxSpeed

        self.terminalVelocity = 15

        self.flinchCounter = 0

        self.velocity = Vec3(0, 0, 0)
        self.acceleration = 300.0

        self.inControl = True

        self.walking = False

        self.noZVelocity = True

        if colliderName is not None:
            colliderNode = CollisionNode(colliderName)
            colliderNode.addSolid(CollisionCapsule(0, 0, 0, 0, 0, height, 0.3))
            self.weaponCollider = self.root.attachNewNode(colliderNode)
            self.weaponCollider.setPythonTag(TAG_OWNER, self)
            colliderNode.setFromCollideMask(0)
            colliderNode.setIntoCollideMask(weaponIntoMask)
            #self.weaponCollider.show()
        else:
            self.weaponCollider = self.root.attachNewNode(
                PandaNode("stand-in"))

        self.deathSound = None

        self.currentWeapon = None

    def update(self, dt, fluid=False):
        speed = self.velocity.length()
        if self.noZVelocity:
            self.velocity.setZ(0)

        if self.inControl:
            if self.walking and speed > self.maxSpeed:
                self.velocity.normalize()
                self.velocity *= self.maxSpeed
                speed = self.maxSpeed
        else:
            if speed > self.terminalVelocity:
                self.velocity.normalize()
                self.velocity *= self.terminalVelocity
                speed = self.terminalVelocity

        if not self.walking:
            perc = speed / self.maxSpeed
            frictionVal = FRICTION * dt / (max(1, perc * perc))
            if not self.inControl:
                frictionVal *= 0.8
            if frictionVal > speed:
                self.velocity.set(0, 0, 0)
            else:
                frictionVec = -self.velocity
                frictionVec.normalize()
                frictionVec *= frictionVal

                self.velocity += frictionVec

        if not self.inControl and speed < 0.1:
            self.inControl = True

        if fluid:
            self.root.setFluidPos(self.root.getPos() + self.velocity * dt)
        else:
            self.root.setPos(self.root.getPos() + self.velocity * dt)

    def alterHealth(self,
                    dHealth,
                    incomingImpulse,
                    flinchValue,
                    overcharge=False):
        previousHealth = self.health

        self.health += dHealth

        if incomingImpulse is not None and incomingImpulse.lengthSquared(
        ) > 0.1:
            self.velocity += incomingImpulse
            self.inControl = False
            self.walking = False

        if flinchValue > 0:
            self.flinchCounter -= flinchValue

        if dHealth > 0 and self.health > self.maxHealth and not overcharge:
            self.health = self.maxHealth
        if previousHealth > 0 and self.health <= 0 and self.deathSound is not None:
            self.deathSound.play()

    def turnTowards(self, target, turnRate, dt):
        if isinstance(target, NodePath):
            target = target.getPos(render)
        elif isinstance(target, GameObject):
            target = target.root.getPos(render)
        diff = target - self.root.getPos(render)

        angle = self.getAngleWithVec(diff)

        if abs(angle) < 1:
            return angle

        maxTurn = turnRate * dt
        if angle < 0:
            maxTurn = -maxTurn
            if angle > maxTurn:
                self.root.setH(self.root, angle)
                return 0
            else:
                self.root.setH(self.root, maxTurn)
                return angle - maxTurn
        else:
            if angle < maxTurn:
                self.root.setH(self.root, angle)
                return 0
            else:
                self.root.setH(self.root, maxTurn)
                return angle - maxTurn

    def getAngleWithVec(self, vec):
        forward = self.actor.getQuat(render).getForward()
        forward2D = Vec2(forward.x, forward.y)
        vec = Vec2(vec.x, vec.y)
        vec.normalize()
        angle = forward2D.signedAngleDeg(vec)
        return angle

    def cleanup(self):
        if self.weaponCollider is not None and not self.weaponCollider.isEmpty(
        ):
            self.weaponCollider.clearPythonTag(TAG_OWNER)
            self.weaponCollider.removeNode()
        self.weaponCollider = None

        if self.actor is not None:
            if isinstance(self.actor, Actor):
                self.actor.cleanup()
            self.actor.removeNode()
            self.actor = None

        if self.root is not None:
            self.root.removeNode()
            self.root = None
Beispiel #36
0
class Golem(FSM, DirectObject):
    def __init__(self):
        FSM.__init__(self, "FSM-Golem")
        random.seed()
        self.golem = loader.loadModel("Golem")
        self.golem = Actor("Golem", {
            "Idle":"Golem-Idle",
            "Walk":"Golem-Walk",
            "Attack":"Golem-Attack",
            "Destroyed":"Golem-Destroyed"})
        self.golem.setBlend(frameBlend = True)
        golemViewSphere = CollisionSphere(0, 0, 0.5, 6)
        golemViewSphere.setTangible(False)
        golemViewColNP = self.golem.attachNewNode(CollisionNode('golemViewField'))
        golemViewColNP.node().addSolid(golemViewSphere)
        golemHitSphere = CollisionSphere(0, 0, 0.5, 1)
        golemHitColNP = self.golem.attachNewNode(CollisionNode('golemHitField'))
        golemHitColNP.node().addSolid(golemHitSphere)

        # a collision segment to check attacks
        self.attackCheckSegment = CollisionSegment(0, 0, 1, 0, -1.3, 1)
        self.golemAttackRay = self.golem.attachNewNode(CollisionNode("golemAttackCollision"))
        self.golemAttackRay.node().addSolid(self.attackCheckSegment)
        self.golemAttackRay.node().setIntoCollideMask(0)
        self.attackqueue = CollisionHandlerQueue()
        base.cTrav.addCollider(self.golemAttackRay, self.attackqueue)

        attackAnim = self.golem.actorInterval("Attack", playRate = 2)
        self.AttackSeq = Parallel(
            attackAnim,
            Sequence(
                Wait(0.5),
                Func(self.ceckAttack)
            ))

        self.lookatFloater = NodePath(PandaNode("golemTracker"))
        self.lookatFloater.setPos(self.golem, 0, 0, 3.4)
        self.lookatFloater.hide()
        self.lookatFloater.reparentTo(render)
        self.trackerObject = loader.loadModel("misc/Pointlight")
        self.trackerObject.setColor(0, 1, 0)
        self.trackerObject.setScale(0.25)
        self.trackerObject.reparentTo(self.lookatFloater)

    def start(self, startPos):
        self.golem.setPos(startPos.getPos())
        self.golem.setHpr(startPos.getHpr())
        self.golem.reparentTo(render)
        self.trackedEnemy = None
        self.health = 5
        self.accept("playerCollision-in-golemViewField",
                    lambda extraArgs: base.messenger.send("golemSeesPlayer", [self.golem]))

    def stop(self):
        self.trackedEnemy = None
        taskMgr.remove("GolemAI_task")
        self.golem.hide()
        self.ignoreAll()

    def cleanup(self):
        self.stop()
        self.lookatFloater.removeNode()
        self.golem.cleanup()
        self.golem.removeNode()

    def activate(self, trackedEnemy):
        self.trackedEnemy = trackedEnemy
        taskMgr.add(self.aiTask, "GolemAI_task")
        self.lookatFloater.show()

    def aiTask(self, task):
        dt = globalClock.getDt()
        if self.AttackSeq.isPlaying(): return task.cont

        self.lookatFloater.setPos(self.golem, 0, 0, 3.4)
        self.lookatFloater.lookAt(self.trackedEnemy)
        self.lookatFloater.setH(self.lookatFloater.getH() + 180)
        self.lookatFloater.setP(0)
        self.lookatFloater.setR(0)

        self.golem.lookAt(self.trackedEnemy)
        self.golem.setH(self.golem.getH() + 180)

        distanceVec = self.golem.getPos() - self.trackedEnemy.getPos()
        enemyDist = distanceVec.length()

        if enemyDist < 2.0:
            # close enough for combat
            action = random.choice(["Attack", "Idle"])
            if action == "Attack":
                self.request("Attack")
            else:
                if self.state != "Idle":
                    self.request("Idle")
        else:
            self.golem.setY(self.golem, -0.5 * dt)
            if self.state != "Walk":
                self.request("Walk")

        return task.cont

    def hit(self):
        hitInterval = Sequence(
            Func(self.golem.setColorScale, 1, 0, 0, 0.75),
            Wait(0.15),
            Func(self.golem.clearColorScale),
            Wait(0.15),
            Func(self.golem.setColorScale, 1, 0, 0, 0.75),
            Wait(0.15),
            Func(self.golem.clearColorScale),
            Wait(0.15),
            Func(self.golem.setColorScale, 1, 0, 0, 0.75),
            Wait(0.15),
            Func(self.golem.clearColorScale),
            Wait(0.15),
            Func(self.golem.setColorScale, 1, 0, 0, 0.75),
            Wait(0.15),
            Func(self.golem.clearColorScale),
            Wait(0.15))
        self.health -= 1
        if self.health == 4:
            self.trackerObject.setColor(0, 1, 0)
            hitInterval.start()
        elif self.health == 3:
            self.trackerObject.setColor(0.25, 0.75, 0)
            hitInterval.start()
        elif self.health == 2:
            self.trackerObject.setColor(0.5, .5, 0)
            hitInterval.start()
        elif self.health == 1:
            self.trackerObject.setColor(0.75, 0.25, 0)
            hitInterval.start()
        elif self.health == 0:
            self.trackerObject.setColor(0, 0, 0)
            self.request("Destroyed")

    def ceckAttack(self):
        for i in range(self.attackqueue.getNumEntries()):
            entry = self.attackqueue.getEntry(i)
            into = entry.getIntoNode()
            if "playerCollision" in into.getName():
                if random.random() > .5:
                    base.messenger.send("HitPlayer")

    def enterIdle(self):
        self.golem.loop("Idle")

    def enterWalk(self):
        self.golem.setPlayRate(2, "Walk")
        self.golem.loop("Walk")

    def enterAttack(self):
        self.AttackSeq.start()

    def enterDestroyed(self):
        self.ignoreAll()
        taskMgr.remove("GolemAI_task")
        self.AttackSeq.finish()
        self.golem.play("Destroyed")
        self.lookatFloater.hide()
        base.messenger.send("GolemDestroyed")
class Player(FSM, DirectObject):
    def __init__(self, charId, charNr, controls):
        FSM.__init__(self, "FSM-Player{}".format(charNr))
        self.charId = charId
        charPath = "characters/character{}/".format(charNr)
        self.character = Actor(
            charPath + "char",
            {
                "Idle": charPath + "idle",
                "Walk": charPath + "walk",
                "Walk_back": charPath + "walk_back",
                "Punch_l": charPath + "punch_l",
                "Punch_r": charPath + "punch_r",
                "Kick_l": charPath + "kick_l",
                "Kick_r": charPath + "kick_r",
                "Defend": charPath + "defend",
                "Hit": charPath + "hit",
                "Defeated": charPath + "defeated",
            },
        )
        self.character.reparentTo(render)
        self.character.hide()
        self.walkSpeed = 2.0  # units per second
        if controls == "p1":
            self.character.setH(90)
            self.leftButton = KeyboardButton.asciiKey("d")
            self.rightButton = KeyboardButton.asciiKey("f")
            self.punchLButton = KeyboardButton.asciiKey("q")
            self.punchRButton = KeyboardButton.asciiKey("w")
            self.kickLButton = KeyboardButton.asciiKey("a")
            self.kickRButton = KeyboardButton.asciiKey("s")
            self.defendButton = KeyboardButton.asciiKey("e")
        elif controls == "p2":
            self.character.setH(-90)
            self.leftButton = KeyboardButton.right()
            self.rightButton = KeyboardButton.left()
            self.punchLButton = KeyboardButton.asciiKey("i")
            self.punchRButton = KeyboardButton.asciiKey("o")
            self.kickLButton = KeyboardButton.asciiKey("k")
            self.kickRButton = KeyboardButton.asciiKey("l")
            self.defendButton = KeyboardButton.asciiKey("p")

        self.getPos = self.character.getPos
        self.getX = self.character.getX

        characterSphere = CollisionSphere(0, 0, 1.0, 0.5)
        self.collisionNodeName = "character{}Collision".format(charId)
        characterColNode = CollisionNode(self.collisionNodeName)
        characterColNode.addSolid(characterSphere)
        self.characterCollision = self.character.attachNewNode(characterColNode)
        # Uncomment this line to show collision solids
        # self.characterCollision.show()
        base.pusher.addCollider(self.characterCollision, self.character)
        base.cTrav.addCollider(self.characterCollision, base.pusher)

        characterHitRay = CollisionSegment(0, -0.5, 1.0, 0, -0.8, 1.0)
        characterColNode.addSolid(characterHitRay)

        self.audioStep = base.audio3d.loadSfx("assets/audio/step.ogg")
        self.audioStep.setLoop(True)
        base.audio3d.attachSoundToObject(self.audioStep, self.character)

        self.audioHit = base.audio3d.loadSfx("assets/audio/hit.ogg")
        self.audioHit.setLoop(False)
        base.audio3d.attachSoundToObject(self.audioStep, self.character)

    def setEnemy(self, enemyColName):
        self.enemyColName = enemyColName
        inEvent = "{}-into-{}".format(enemyColName, self.collisionNodeName)
        base.pusher.addInPattern(inEvent)
        self.accept(inEvent, self.setCanBeHit, [True])
        outEvent = "{}-out-{}".format(enemyColName, self.collisionNodeName)
        base.pusher.addOutPattern(outEvent)
        self.accept(outEvent, self.setCanBeHit, [False])

    def setCanBeHit(self, yes, collission):
        eventName = "hitEnemy{}".format(self.collisionNodeName)
        if yes:
            self.accept(eventName, self.gotHit)
        else:
            self.ignore(eventName)
        self.canBeHit = yes

    def gotHit(self):
        if not self.canBeHit or self.isDefending:
            return

        self.bloodsplat = ParticleEffect()
        self.bloodsplat.loadConfig("assets/fx/BloodSplat.ptf")
        floater = self.character.attachNewNode("particleFloater")
        if self.character.getH() == 90:
            floater.setPos(-1, 0, 1)
        if self.character.getH() == -90:
            floater.setPos(1, 0, 1)
        self.bloodsplat.start(parent=floater, renderParent=render)
        taskMgr.doMethodLater(0.5, self.bloodsplat.cleanup, "stop Particle", extraArgs=[])

        self.health -= 10
        base.messenger.send("lifeChanged", [self.charId, self.health])
        if self.health <= 0:
            self.gotDefeated = True
            self.request("Defeated")
            base.messenger.send("gameOver", [self.charId])
        else:
            self.request("Hit")

    def attackAnimationPlaying(self):
        actionAnimations = ["Punch_l", "Punch_r", "Kick_l", "Kick_r", "Hit"]
        if self.character.getCurrentAnim() in actionAnimations:
            return True

    def start(self, startPos):
        self.character.setPos(startPos)
        self.character.show()
        self.request("Idle")
        self.canBeHit = False
        self.isDefending = False
        self.gotDefeated = False
        self.health = 100
        taskMgr.add(self.moveTask, "move task {}".format(self.charId))

    def stop(self):
        taskMgr.remove("move task {}".format(self.charId))
        self.ignoreAll()
        base.audio3d.detachSound(self.audioStep)
        base.audio3d.detachSound(self.audioHit)
        self.character.cleanup()
        self.character.removeNode()

    def moveTask(self, task):
        if self.gotDefeated:
            base.messenger.send("GameOver")
            return task.done
        if self.attackAnimationPlaying():
            return task.cont
        speed = 0.0
        isDown = base.mouseWatcherNode.isButtonDown

        if isDown(self.defendButton):
            if self.state != "Defend":
                self.isDefending = True
                self.request("Defend")
            return task.cont
        self.isDefending = False

        # Check for attack keys
        isAction = False
        if isDown(self.punchLButton):
            isAction = True
            self.request("Punch_l")
        elif isDown(self.punchRButton):
            isAction = True
            self.request("Punch_r")
        elif isDown(self.kickLButton):
            isAction = True
            self.request("Kick_l")
        elif isDown(self.kickRButton):
            isAction = True
            self.request("Kick_r")
        if isAction:
            base.messenger.send("hitEnemy{}".format(self.enemyColName))
            return task.cont

        if isDown(self.leftButton):
            speed += self.walkSpeed
        if isDown(self.rightButton):
            speed -= self.walkSpeed
        yDelta = speed * globalClock.getDt()
        self.character.setY(self.character, yDelta)
        if speed != 0.0 and self.state != "Walk" and self.state != "Walk_back":
            if speed < 0:
                self.request("Walk")
            else:
                self.request("Walk_back")
        elif speed == 0.0 and self.state != "Idle":
            self.request("Idle")
        return task.cont

    def enterIdle(self):
        self.character.loop("Idle")

    def exitIdle(self):
        self.character.stop()

    def enterWalk(self):
        self.character.loop("Walk")
        if self.audioStep.status() != AudioSound.PLAYING:
            self.audioStep.play()

    def exitWalk(self):
        self.character.stop()
        if self.audioStep.status() == AudioSound.PLAYING:
            self.audioStep.stop()

    def enterWalk_back(self):
        self.character.loop("Walk_back")
        if self.audioStep.status() != AudioSound.PLAYING:
            self.audioStep.play()

    def exitWalk_back(self):
        self.character.stop()
        if self.audioStep.status() == AudioSound.PLAYING:
            self.audioStep.stop()

    def enterPunch_l(self):
        self.character.play("Punch_l")

    def exitPunch_l(self):
        self.character.stop()

    def enterPunch_r(self):
        self.character.play("Punch_r")

    def exitPunch_r(self):
        self.character.stop()

    def enterKick_l(self):
        self.character.play("Kick_l")

    def exitKick_l(self):
        self.character.stop()

    def enterKick_r(self):
        self.character.play("Kick_r")

    def exitKick_r(self):
        self.character.stop()

    def enterDefend(self):
        self.character.play("Defend")

    def exitDefend(self):
        self.character.stop()

    def enterHit(self):
        self.character.play("Hit")
        self.audioHit.play()

    def exitHit(self):
        self.character.stop()

    def enterDefeated(self):
        self.character.play("Defeated")

    def exitDefeated(self):
        self.character.stop()
Beispiel #38
0
class Boss2():
    def __init__(self, common, pos=(0,0,0)):
        self.common = common
        common['monsterList'].append(self)
        id=len(common['monsterList'])-1
        self.id=id
        self.stats={"speed":9,
            "hp":400,
            "armor":0
            }
        self.totalSpeed=1
        self.sparkSum=0
        self.lastMagmaDmg=0
        self.DOT=0
        self.arrows=set()
        self.isSolid=True
        #self.bullet.hide()
        self.node=render.attachNewNode("monster")
        self.boss=Actor("models/boss2/boss2.bam", {"die":"models/boss2/boss2_die.bam",
                                            "attack1":"models/boss2/boss2_attack1.bam",
                                            "hit":"models/boss2/boss2_hit.bam",
                                            "idle":"models/boss2/boss2_idle.bam",
                                            "attack2":"models/boss2/boss2_attack2.bam",
                                            "fly":"models/boss2/boss2_flyforward.bam"})
        self.boss.setBlend(frameBlend = True)
        self.boss.setPlayRate(2, "attack1")
        self.boss.reparentTo(self.node)
        self.boss.setScale(0.01,0.01,0.01)
        self.boss.setP(10)
        self.boss.setH(180)
        self.boss.setBin("opaque", 10)
        #tex = loader.loadTexture('models/boss1-monster/creature1Normal.png')
        #boss1.setTexture(tex, 1)
        #self.boss.setColor(0.2, 0.0, 0.9, 0.5)
        self.node.setPos(render,pos)
        self.rootBone=self.boss.exposeJoint(None, 'modelRoot', 'Hips')

        self.ambientLight=AmbientLight('ambientLight')
        self.ambientLight.setColor(VBase4(.7, .7, .7, 1))
        self.ambientLightNode = render.attachNewNode(self.ambientLight)
        self.boss.setLight(self.ambientLightNode)


        self.maxHP=self.stats['hp']
        self.healthBar=DirectFrame(frameSize=(37, 0, 0, 6),
                                    frameColor=(0, 0, 1, 1),
                                    frameTexture='icon/glass4.png',
                                    parent=pixel2d)
        self.healthBar.setTransparency(TransparencyAttrib.MDual)
        self.healthBar.setScale(10,1, 1)
        #self.healthBar.reparentTo(self.node)
        wp = base.win.getProperties()
        winX = wp.getXSize()
        winY = wp.getYSize()
        self.healthBar.setPos(71-256+winX/2,0,34-winY)
        self.healthBar.hide()
        self.waitfor = 0 # time to wait before to pursue the player
        self.soundID=self.common['soundPool'].get_id()
        self.common['soundPool'].set_target(self.soundID, self.node)

        self.traverser=CollisionTraverser("BossTrav"+str(id))
        #self.traverser.showCollisions(render)
        self.queue = CollisionHandlerQueue()

        #radar collision ray
#        self.radar=self.node.attachNewNode(CollisionNode('radarRay'))
#        self.radar.node().addSolid(CollisionRay(0, 0, 1, 0, 90, 0))
#        self.radar.node().setIntoCollideMask(BitMask32.allOff())
#        self.radar.node().setFromCollideMask(BitMask32.bit(2))
#        self.radar.setTag("radar", str(id))
#        self.radar.show()
#        self.traverser.addCollider(self.radar, self.queue)

        self.coll_body=self.node.attachNewNode(CollisionNode('bossmonsterCollisionNode'))
        self.coll_body.node().addSolid(CollisionCapsule(0, 0, 0.3, 0, 0.2, 1.5, 0.3))
        self.coll_body.setTag("id", str(id))
        self.coll_body.node().setIntoCollideMask(BitMask32.bit(3))
        #self.coll_body.show()
        #self.right_foot = self.boss.exposeJoint(None, "modelRoot", "R_foot")
        #self.coll_attack2=self.node.attachNewNode(CollisionNode('bossattack2CollisionNode'))
        #self.coll_attack2.node().addSolid(CollisionSphere(0, 0, 0, 0.2))
        ##self.coll_attack2.setTag("id", str(id))
        #self.coll_attack2.node().setIntoCollideMask(BitMask32.bit(3))
        #self.coll_attack2.show()

        #other monster blocking
        self.coll_quad=loader.loadModel("models/plane")
        self.coll_quad.reparentTo(self.node)
        self.state="IDLE"
        self.previous_state=self.state
        #self.PC = self.common['PC']
        #taskMgr.doMethodLater(.6, self.runCollisions,'collFor'+str(self.id))
        #taskMgr.doMethodLater(1.0, self.damageOverTime,'DOTfor'+str(self.id))
        self.boss.setTransparency(True)
        self.visible = True
        self.bullet=loader.loadModel("models/ball.egg")
        self.bullet.setScale(0.5)
        self.bullet.reparentTo(render)
        self.bullet.setPos(0,0,-5)
        mat = Material()
        mat.setShininess(0)
        mat.setAmbient((0.7, 0.1, 0, 0.8))
        self.ambientLightBullet=AmbientLight('ambientLight')
        self.ambientLightBullet.setColor(VBase4(.5, .5, .5, 1))
        self.ambientLightBulletNode = render.attachNewNode(self.ambientLightBullet)
        self.bullet.setLight(self.ambientLightBulletNode)
        self.bullet.setMaterial(mat)
        self.bullet.setBin("opaque", 10)
        self.bullet.hide()
        self.bullet_radius = 0
        # Our model is rotated of 180°, thus we need to move the collision sphere to the opposite directions
        #self.bullet.setPos(-1*x, -1*y, z)
        self.fog = Fog("Fog")
        self.fog.setColor(0.5, 0.5, 0.5)
        self.fog.setExpDensity(0.1)

#        self.node.setColorScale(1,1,1,1)
#        self.node.clearFog()

        #Sequence(Wait(2),LerpColorScaleInterval(self.node, 2.0, VBase4(1,1,1,0.1))).start()
        #Sequence(Wait(6),LerpColorScaleInterval(self.node, 2.0, VBase4(1,1,1,1))).start()
        #Sequence(Wait(10),LerpColorScaleInterval(self.node, 2.0, VBase4(1,1,1,0.1))).start()
        taskMgr.add(self.runAI, "BossAIfor"+str(id))

    def toggleVisibility(self):
        if (self.visible):
            #Sequence(Wait(0),LerpColorScaleInterval(self.node, 2.0, VBase4(1,1,1,0.1))).start()
            self.node.setFog(self.fog)
            self.node.setColorScale(1,1,1,0.1)
        else:
            #Sequence(Wait(0),LerpColorScaleInterval(self.node, 2.0, VBase4(1,1,1,1))).start()
            self.node.setColorScale(1,1,1,1)
            self.node.clearFog()
        self.visible = not self.visible


    def runAI(self, task):
        #print(self.stats['hp'])
        #(x,y,z) = self.right_foot.getPos()
        ## Our model is rotated of 180°, thus we need to move the collision sphere to the opposite directions
        #self.coll_attack2.setPos(-1*x, -1*y, z)
        target = self.common['PC'].node
        if self.state=="DIE":
            if(self.boss.getCurrentAnim()!="die"):
                self.common['soundPool'].attachAndPlay(self.boss, "argh-woman.ogg")
                self.boss.play("die")
                Sequence(Wait(0),LerpPosInterval(self.node, 0.4, VBase3(self.node.getX(),self.node.getY(),self.node.getZ()-1))).start()
            #Check if we have finished the animation
            if (self.boss.getCurrentFrame() < self.boss.getNumFrames()-1):
                return task.again
            else:
                id = len(self.common["random-objects"])
                object = RandomObject(id, self.common, self.node, render, moneyamount=5)
                self.common["random-objects"].append(object)

                self.coll_body.node().setIntoCollideMask(BitMask32.allOff())
                self.coll_quad.removeNode()
                Interactive(self.common, data.items['key'], self.node.getPos(render))
                Sequence(Wait(1.0),LerpPosInterval(self.node, 2.0, VBase3(self.node.getX(),self.node.getY(),self.node.getZ()-5)),Func(self.destroy)).start()
                return task.done

        if (self.state == "HIT") and (self.previous_state == "IDLE"):
            if(self.boss.getCurrentAnim()!="hit"):
                self.boss.play("hit")
                self.common['soundPool'].attachAndPlay(self.boss, "argh-woman.ogg")
            if (self.boss.getCurrentFrame() == self.boss.getNumFrames()-1):
                self.state = self.previous_state
            return task.again

        #Check if the player is colliding with the bullet
        if (self.bullet_radius > 0) and (self.bullet.getDistance(target)<1):
            self.boss.attackdamage = 10 * self.bullet_radius
            self.common['PC'].hit(self.boss.attackdamage)
            self.bullet_radius = 0

        if self.state == "IDLE":
            if(self.boss.getCurrentAnim()!="idle"):
                self.boss.play("idle")
            if (self.waitfor > 0):
                self.waitfor -= 1
                return task.again

        if self.common['PC'].HP <= 0 or self.node.getDistance(target)>25:
            self.state="IDLE"
            self.common['spawner'].monster_limit = 4
        else:
            self.common['spawner'].monster_limit = 2
            if (random.random() < 0.003) and (self.state == "PURSUING"):
                self.state="IDLE"
                self.waitfor = random.randrange(200)
                return task.again
            if (random.random() < 0.008) or (self.state == "ATTACKING"):
                self.state="ATTACKING"
                if(self.boss.getCurrentAnim()!="attack2") and (self.boss.getCurrentAnim()!="attack1"):
                    if (random.random() < 0.5):
                        self.boss.play("attack2")
                        self.common['soundPool'].attachAndPlay(self.boss, "beam-sound.wav", volume=3)
                        self.boss.attackdamage = 0
                    else:
                        self.boss.play("attack1")
                        self.boss.attackdamage = 0
                        (x,y,z)=self.node.getPos()
                        self.bullet.setPos(x,y,z+0.75)
                        self.bullet.show()
                        self.bullet_radius = random.randrange(2, 4)
                        Sequence(Wait(0),LerpScaleInterval(self.bullet, 1.0, VBase3(self.bullet_radius,self.bullet_radius,self.bullet_radius), VBase3(0.5,0.5,0.5))).start()
                        Sequence(Wait(0),LerpPosInterval(self.bullet, 4.0, VBase3(self.common['PC'].node.getPos()))).start()
                        #The sound must be played only when the boss hit the floor (it's in the mid of the animation)
                        self.common['soundPool'].attachAndPlay(self.boss, "energy1.wav", volume=3)
                        # Get position of the joint respect to render (i.e. absolute position)
                        #(x,y,_) = self.left_thumb.getPos(render)
                        #vfx(None, texture='vfx/dust.png',scale=1, Z=0, depthTest=True, depthWrite=True,pos=(x,y,0)).start(0.016)

                # Inflict damage only when we played half of the animation (it should be the moment when the attack hits the player)
                # This function could be called multiple times even if we are at the same frame (probably depends on the frame rate of the animation)
                # Thus, we should also check if we are seeing the same previous hit (based on the last frame, it must not be the same)
                elif (self.boss.getCurrentFrame() == int(self.boss.getNumFrames()/2)) and (self.boss.getCurrentFrame() != self.boss.lastFrame):
                    if (self.boss.getCurrentAnim() == "attack2"):
                        self.toggleVisibility()
                        if (self.visible == False):
                            self.stats['hp'] += 10
                            self.healthBar.setScale(10*self.stats['hp']/self.maxHP,1, 1)

                elif (self.boss.getCurrentFrame() == self.boss.getNumFrames()-1):
                    #When the animation is finished return to pursuing the player
                    self.state = "PURSUING"

                self.boss.lastFrame = self.boss.getCurrentFrame()
                return task.again

            self.state = "PURSUING"
            self.node.headsUp(target) #Look at the player
            if(self.boss.getCurrentAnim()!="fly"):
                self.boss.loop("fly")
            if self.node.getDistance(target)>5:
                self.node.setY(self.node, self.totalSpeed*globalClock.getDt())
            else:
                self.node.setX(self.node, self.totalSpeed*globalClock.getDt())

        self.previous_state = self.state
        return task.again

    def doDamage(self, damage, igoreArmor=False):
        if self.state=="DIE":
            return
        if not igoreArmor:
            damage-=self.stats['armor']
        if damage<1:
            damage=1
        #print damage
        self.stats['hp']-=damage
        self.healthBar.show()
        self.healthBar.setScale(10*self.stats['hp']/self.maxHP,1, 1)
        if self.stats['hp']<1:
            self.healthBar.hide()

    def die(self, soundname):
        #self.common['soundPool'].play(self.soundID, self.sound_names["hit"])
        #self.common['soundPool'].play(self.soundID, soundname)
        self.state="DIE"

    def onHit(self, damage, sound="hit", weapon=None):
        if self.state=="DIE" or self.visible == False:
            return
        self.state="HIT"
        self.doDamage(damage)

        if self.stats['hp']<1:
            self.die("die")

    def damageOverTime(self, task):
        if self.state=="DIE":
            return task.done
        if self.DOT>0:
            self.doDamage(self.DOT)
            self.DOT=int((self.DOT*0.9)-1.0)
            vfx(self.node, texture='vfx/blood_dark.png',scale=.5, Z=1.0, depthTest=True, depthWrite=True).start(0.016)
        return task.again

    def destroy(self):
        self.arrows=None
        if self.boss:
            self.boss.cleanup()
            self.boss.removeNode()
        if taskMgr.hasTaskNamed("BossAIfor"+str(self.id)):
            taskMgr.remove("BossAIfor"+str(self.id))
#        if taskMgr.hasTaskNamed('collFor'+str(self.id)):
#            taskMgr.remove('collFor'+str(self.id))
        if taskMgr.hasTaskNamed('DOTfor'+str(self.id)):
            taskMgr.remove('DOTfor'+str(self.id))
        if taskMgr.hasTaskNamed('AIUpdate'):
            taskMgr.remove('AIUpdate')
        if self.node:
            self.node.removeNode()
        self.common['monsterList'][self.id]=None
        self.traverser=None
        self.queue=None
        #self.common['traverser'].removeCollider(self.coll_sphere)
        self.coll_body.removeNode()
        self.coll_quad.removeNode()
        self.healthBar.removeNode()
        self.ambientLightNode.removeNode()
        self.ambientLightBulletNode.removeNode()
        self.ambientLightBulletNode.removeNode()
class PartyCog(FSM):
    notify = directNotify.newCategory('PartyCog')
    HpTextGenerator = TextNode('HpTextGenerator')
    hpText = None
    height = 7

    def __init__(self, parentNode, id, bounceSpeed = 3, bounceHeight = 1, rotateSpeed = 1, heightShift = 1, xMoveSpeed = 0, xMoveDistance = 0, bounceOffset = 0):
        self.id = id
        FSM.__init__(self, 'PartyCogFSM-%d' % self.id)
        self.showFacingStatus = False
        self.xMoveSpeed = xMoveSpeed
        self.xMoveDistance = xMoveDistance
        self.heightShift = heightShift
        self.bounceSpeed = bounceSpeed
        self.bounceHeight = bounceHeight
        self.rotateSpeed = rotateSpeed
        self.parentNode = parentNode
        self.bounceOffset = bounceOffset
        self.hitInterval = None
        self.kaboomTrack = None
        self.resetRollIval = None
        self.netTimeSentToStartByHit = 0
        self.load()
        self.request('Down')
        return

    def load(self):
        self.root = NodePath('PartyCog-%d' % self.id)
        self.root.reparentTo(self.parentNode)
        path = 'phase_13/models/parties/cogPinata_'
        self.actor = Actor(path + 'actor', {'idle': path + 'idle_anim',
         'down': path + 'down_anim',
         'up': path + 'up_anim',
         'bodyHitBack': path + 'bodyHitBack_anim',
         'bodyHitFront': path + 'bodyHitFront_anim',
         'headHitBack': path + 'headHitBack_anim',
         'headHitFront': path + 'headHitFront_anim'})
        self.actor.reparentTo(self.root)
        self.temp_transform = Mat4()
        self.head_locator = self.actor.attachNewNode('temphead')
        self.bodyColl = CollisionTube(0, 0, 1, 0, 0, 5.75, 0.75)
        self.bodyColl.setTangible(1)
        self.bodyCollNode = CollisionNode('PartyCog-%d-Body-Collision' % self.id)
        self.bodyCollNode.setCollideMask(ToontownGlobals.PieBitmask)
        self.bodyCollNode.addSolid(self.bodyColl)
        self.bodyCollNodePath = self.root.attachNewNode(self.bodyCollNode)
        self.headColl = CollisionTube(0, 0, 3, 0, 0, 3.0, 1.5)
        self.headColl.setTangible(1)
        self.headCollNode = CollisionNode('PartyCog-%d-Head-Collision' % self.id)
        self.headCollNode.setCollideMask(ToontownGlobals.PieBitmask)
        self.headCollNode.addSolid(self.headColl)
        self.headCollNodePath = self.root.attachNewNode(self.headCollNode)
        self.arm1Coll = CollisionSphere(1.65, 0, 3.95, 1.0)
        self.arm1Coll.setTangible(1)
        self.arm1CollNode = CollisionNode('PartyCog-%d-Arm1-Collision' % self.id)
        self.arm1CollNode.setCollideMask(ToontownGlobals.PieBitmask)
        self.arm1CollNode.addSolid(self.arm1Coll)
        self.arm1CollNodePath = self.root.attachNewNode(self.arm1CollNode)
        self.arm2Coll = CollisionSphere(-1.65, 0, 3.45, 1.0)
        self.arm2Coll.setTangible(1)
        self.arm2CollNode = CollisionNode('PartyCog-%d-Arm2-Collision' % self.id)
        self.arm2CollNode.setCollideMask(ToontownGlobals.PieBitmask)
        self.arm2CollNode.addSolid(self.arm2Coll)
        self.arm2CollNodePath = self.root.attachNewNode(self.arm2CollNode)
        splatName = 'splat-creampie'
        self.splat = globalPropPool.getProp(splatName)
        self.splat.setBillboardPointEye()
        self.splatType = globalPropPool.getPropType(splatName)
        self.pieHitSound = globalBattleSoundCache.getSound('AA_wholepie_only.ogg')
        self.upSound = globalBattleSoundCache.getSound('AV_jump_to_side.ogg')
        self.hole = loader.loadModel('phase_13/models/parties/cogPinataHole')
        self.hole.setTransparency(True)
        self.hole.setP(-90.0)
        self.hole.setScale(3)
        self.hole.setBin('ground', 3)
        self.hole.reparentTo(self.parentNode)

    def unload(self):
        self.request('Off')
        self.clearHitInterval()
        if self.hole is not None:
            self.hole.removeNode()
            self.hole = None
        if self.actor is not None:
            self.actor.cleanup()
            self.actor.removeNode()
            self.actor = None
        if self.root is not None:
            self.root.removeNode()
            self.root = None
        if self.kaboomTrack is not None and self.kaboomTrack.isPlaying():
            self.kaboomTrack.finish()
        self.kaboomTrack = None
        if self.resetRollIval is not None and self.resetRollIval.isPlaying():
            self.resetRollIval.finish()
        self.resetRollIval = None
        if self.hitInterval is not None and self.hitInterval.isPlaying():
            self.hitInterval.finish()
        self.hitInterval = None
        del self.upSound
        del self.pieHitSound
        return

    def enterStatic(self):
        pass

    def exitStatic(self):
        pass

    def enterActive(self, startTime):
        self.root.setR(0.0)
        updateTask = Task.Task(self.updateTask)
        updateTask.startTime = startTime
        taskMgr.add(updateTask, 'PartyCog.update-%d' % self.id)

    def exitActive(self):
        taskMgr.remove('PartyCog.update-%d' % self.id)
        taskMgr.remove('PartyCog.bounceTask-%d' % self.id)
        self.clearHitInterval()
        self.resetRollIval = self.root.hprInterval(0.5, Point3(self.root.getH(), 0.0, 0.0), blendType='easeInOut')
        self.resetRollIval.start()
        self.actor.stop()

    def enterDown(self):
        if self.oldState == 'Off':
            downAnimControl = self.actor.getAnimControl('down')
            self.actor.pose('down', downAnimControl.getNumFrames() - 1)
            return
        self.clearHitInterval()
        startScale = self.hole.getScale()
        endScale = Point3(5, 5, 5)
        self.hitInterval = Sequence(LerpFunc(self.setAlongSpline, duration=1.0, fromData=self.currentT, toData=0.0), LerpScaleInterval(self.hole, duration=0.175, scale=endScale, startScale=startScale, blendType='easeIn'), Parallel(SoundInterval(self.upSound, volume=0.6, node=self.actor, cutOff=PartyGlobals.PARTY_COG_CUTOFF), ActorInterval(self.actor, 'down', loop=0)), LerpScaleInterval(self.hole, duration=0.175, scale=Point3(3, 3, 3), startScale=endScale, blendType='easeOut'))
        self.hitInterval.start()

    def exitDown(self):
        self.root.setR(0.0)
        self.root.setH(0.0)
        self.targetDistance = 0.0
        self.targetFacing = 0.0
        self.currentT = 0.0
        self.setAlongSpline(0.0)
        self.clearHitInterval()
        startScale = self.hole.getScale()
        endScale = Point3(5, 5, 5)
        self.hitInterval = Sequence(LerpScaleInterval(self.hole, duration=0.175, scale=endScale, startScale=startScale, blendType='easeIn'), Parallel(SoundInterval(self.upSound, volume=0.6, node=self.actor, cutOff=PartyGlobals.PARTY_COG_CUTOFF), ActorInterval(self.actor, 'up', loop=0)), Func(self.actor.loop, 'idle'), LerpScaleInterval(self.hole, duration=0.175, scale=Point3(3, 3, 3), startScale=endScale, blendType='easeOut'))
        self.hitInterval.start()

    def filterDown(self, request, args):
        if request == 'Down':
            return None
        else:
            return self.defaultFilter(request, args)
        return None

    def setEndPoints(self, start, end, amplitude = 1.7):
        self.sinAmplitude = amplitude
        self.sinPeriod = (end.getX() - start.getX()) / 2
        self.sinDisplacement = start.getY()
        self.startPoint = start
        self.endPoint = end
        self.currentT = 0.0
        self.targetDistance = 0.0
        self.currentFacing = 0.0
        self.targetFacing = 0.0
        self.setAlongSpline(self.currentT)
        self.hole.setPos(self.root.getPos())
        self.hole.setZ(0.02)

    def rockBackAndForth(self, task):
        t = task.startTime + task.time
        angle = math.sin(t) * 20.0
        self.root.setR(angle)
        return task.cont

    def updateDistance(self, distance):
        self.targetDistance = clamp(distance, -1.0, 1.0)

    def updateTask(self, task):
        self.rockBackAndForth(task)
        if self.targetDistance > self.currentT:
            self.currentT += min(0.01, self.targetDistance - self.currentT)
            self.setAlongSpline(self.currentT)
        elif self.targetDistance < self.currentT:
            self.currentT += max(-0.01, self.targetDistance - self.currentT)
            self.setAlongSpline(self.currentT)
        if self.currentT < 0.0:
            self.targetFacing = -90.0
        elif self.currentT > 0.0:
            self.targetFacing = 90.0
        else:
            self.targetFacing = 0.0
        if self.targetFacing > self.currentFacing:
            self.currentFacing += min(10, self.targetFacing - self.currentFacing)
        elif self.targetFacing < self.currentFacing:
            self.currentFacing += max(-10, self.targetFacing - self.currentFacing)
        self.root.setH(self.currentFacing)
        return task.cont

    def setAlongSpline(self, t):
        t = t + 1.0
        dist = (self.endPoint.getX() - self.startPoint.getX()) / 2.0
        x = self.startPoint.getX() + t * dist
        y = self.startPoint.getY() - math.sin(t * 2 * math.pi) * self.sinAmplitude
        self.root.setPos(x, y, 0)

    def startBounce(self):
        taskMgr.add(self.bounce, 'PartyCog.bounceTask-%d' % self.id)

    def bounce(self, task):
        self.root.setZ(math.sin((self.bounceOffset + task.time) * self.bounceSpeed) * self.bounceHeight + self.heightShift)
        return task.cont

    def setPos(self, position):
        self.root.setPos(position)

    def respondToPieHit(self, timestamp, position, hot = False, direction = 1.0):
        if self.netTimeSentToStartByHit < timestamp:
            self.__showSplat(position, direction, hot)
            if self.netTimeSentToStartByHit < timestamp:
                self.netTimeSentToStartByHit = timestamp
        else:
            self.notify.debug('respondToPieHit self.netTimeSentToStartByHit = %s' % self.netTimeSentToStartByHit)

    def clearHitInterval(self):
        if self.hitInterval is not None and self.hitInterval.isPlaying():
            self.hitInterval.clearToInitial()
        return

    def __showSplat(self, position, direction, hot = False):
        if self.kaboomTrack is not None and self.kaboomTrack.isPlaying():
            self.kaboomTrack.finish()
        self.clearHitInterval()
        splatName = 'splat-creampie'
        self.splat = globalPropPool.getProp(splatName)
        self.splat.setBillboardPointEye()
        self.splat.reparentTo(render)
        self.splat.setPos(self.root, position)
        self.splat.setAlphaScale(1.0)
        if not direction == 1.0:
            self.splat.setColorScale(PartyGlobals.CogActivitySplatColors[0])
            if self.currentFacing > 0.0:
                facing = 'HitFront'
            else:
                facing = 'HitBack'
        else:
            self.splat.setColorScale(PartyGlobals.CogActivitySplatColors[1])
            if self.currentFacing > 0.0:
                facing = 'HitBack'
            else:
                facing = 'HitFront'
        if hot:
            targetscale = 0.75
            part = 'head'
        else:
            targetscale = 0.5
            part = 'body'

        def setSplatAlpha(amount):
            self.splat.setAlphaScale(amount)

        self.hitInterval = Sequence(ActorInterval(self.actor, part + facing, loop=0), Func(self.actor.loop, 'idle'))
        self.hitInterval.start()
        self.kaboomTrack = Parallel(SoundInterval(self.pieHitSound, volume=1.0, node=self.actor, cutOff=PartyGlobals.PARTY_COG_CUTOFF), Sequence(Func(self.splat.showThrough), Parallel(Sequence(LerpScaleInterval(self.splat, duration=0.175, scale=targetscale, startScale=Point3(0.1, 0.1, 0.1), blendType='easeOut'), Wait(0.175)), Sequence(Wait(0.1), LerpFunc(setSplatAlpha, duration=1.0, fromData=1.0, toData=0.0, blendType='easeOut'))), Func(self.splat.cleanup), Func(self.splat.removeNode)))
        self.kaboomTrack.start()
        return

    def showHitScore(self, number, scale = 1):
        if number <= 0:
            return
        if self.hpText:
            self.hideHitScore()
        self.HpTextGenerator.setFont(ToontownGlobals.getSignFont())
        if number < 0:
            self.HpTextGenerator.setText(str(number))
        else:
            self.HpTextGenerator.setText('+' + str(number))
        self.HpTextGenerator.clearShadow()
        self.HpTextGenerator.setAlign(TextNode.ACenter)
        r = 1
        g = 1
        b = 0
        a = 1
        self.HpTextGenerator.setTextColor(r, g, b, a)
        self.hpTextNode = self.HpTextGenerator.generate()
        self.hpText = render.attachNewNode(self.hpTextNode)
        self.hpText.setScale(scale)
        self.hpText.setBillboardPointEye()
        self.hpText.setBin('fixed', 100)
        self.hpText.setPos(self.root, 0, 0, self.height / 2)
        seq = Sequence(self.hpText.posInterval(0.25, Point3(self.root.getX(render), self.root.getY(render), self.root.getZ(render) + self.height + 1.0), blendType='easeOut'), Wait(0.25), self.hpText.colorInterval(0.1, Vec4(r, g, b, 0)), Func(self.__hideHitScore))
        seq.start()

    def hideHitScore(self):
        if self.hpText:
            taskMgr.remove('PartyCogHpText' + str(self.id))
            self.hpText.removeNode()
            self.hpText = None
        return

    def getHeadLocation(self):
        self.actor.getJoints(jointName='head')[0].getNetTransform(self.temp_transform)
        self.head_locator.setMat(self.temp_transform)
        return self.head_locator.getZ(self.root)
Beispiel #40
0
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()
Beispiel #41
0
class Player(FSM, DirectObject):
    NormalMode = "Normal"
    FightMode = "Fight"

    GAMEPADMODE = "Gamepad"
    MOUSEANDKEYBOARD = "MouseAndKeyboard"

    def __init__(self):
        FSM.__init__(self, "FSM-Player")
        random.seed()

        #
        # PLAYER CONTROLS AND CAMERA
        #
        self.player = Actor(
            "Character",
            {
                "Idle": "Character-Idle",
                "Run": "Character-Run",
                "Activate": "Character-Activate",
                "Death": "Character-Death",
                "Jump": "Character-Jump",
                "Hit": "Character-Hit",
                "Fight_Attack": "Character-FightAttack",
                "Fight_Idle": "Character-FightIdle",
                "Fight_Left": "Character-FightLeft",
                "Fight_Right": "Character-FightRight",
            },
        )
        self.player.setBlend(frameBlend=True)
        # the initial cam distance
        self.fightCamDistance = 3.0
        # the next two vars will set the min and max distance the cam can have
        # to the node it is attached to
        self.maxCamDistance = 4.0
        self.minCamDistance = 1.2
        # the initial cam distance
        self.camDistance = (self.maxCamDistance - self.minCamDistance) / 2.0 + self.minCamDistance
        # the next two vars set the min and max distance on the Z-Axis to the
        # node the cam is attached to
        self.maxCamHeightDist = 3.0
        self.minCamHeightDist = 1.5
        # the average camera height
        self.camHeightAvg = (self.maxCamHeightDist - self.minCamHeightDist) / 2.0 + self.minCamHeightDist
        # an invisible object which will fly above the player and will be used to
        # track the camera on it
        self.camFloater = NodePath(PandaNode("playerCamFloater"))
        self.camFloater.setPos(0, 0, 1.5)
        self.camFloater.reparentTo(self.player)
        # screen sizes
        self.winXhalf = base.win.getXSize() / 2
        self.winYhalf = base.win.getYSize() / 2
        # Interval for the jump animation
        self.jumpInterval = None
        self.jumpstartFloater = NodePath(PandaNode("jumpstartFloater"))
        self.jumpstartFloater.reparentTo(render)
        self.deathComplete = None
        # Joystick/Gamepad support
        self.hasJoystick = False
        if gamepadSupport:
            # initialize controls
            joysticks = [pygame.joystick.Joystick(x) for x in range(pygame.joystick.get_count())]
            if len(joysticks) > 0:
                self.mainJoystick = joysticks[0]
                self.mainJoystick.init()
                self.hasJoystick = True

        #
        # WEAPONS AND ACCESSORIES
        #
        self.RightHandAttach = self.player.exposeJoint(None, "modelRoot", "HandAttach_R")
        self.spear = loader.loadModel("Spear")
        self.spear.setP(90)
        self.spear.setR(180)
        self.spear.reparentTo(self.RightHandAttach)
        self.LeftHandAttach = self.player.exposeJoint(None, "modelRoot", "HandAttach_L")
        self.shield = loader.loadModel("Shield")
        self.shield.setZ(0.05)
        self.shield.setH(-90)
        self.shield.reparentTo(self.LeftHandAttach)

        #
        # PLAYER COLLISION DETECTION AND PHYSICS
        #
        self.playerSphere = CollisionSphere(0, 0, 0.8, 0.7)
        self.playerCollision = self.player.attachNewNode(CollisionNode("playerCollision"))
        self.playerCollision.node().addSolid(self.playerSphere)
        base.pusher.addCollider(self.playerCollision, self.player)
        base.cTrav.addCollider(self.playerCollision, base.pusher)
        # The foot collision checks
        self.footRay = CollisionRay(0, 0, 0, 0, 0, -1)
        self.playerFootRay = self.player.attachNewNode(CollisionNode("playerFootCollision"))
        self.playerFootRay.node().addSolid(self.footRay)
        self.playerFootRay.node().setIntoCollideMask(0)
        self.lifter = CollisionHandlerFloor()
        self.lifter.addCollider(self.playerFootRay, self.player)
        self.lifter.setMaxVelocity(5)
        base.cTrav.addCollider(self.playerFootRay, self.lifter)
        # a collision segment slightly in front of the player to check for jump ledges
        self.jumpCheckSegment = CollisionSegment(0, -0.2, 0.5, 0, -0.2, -2)
        self.playerJumpRay = self.player.attachNewNode(CollisionNode("playerJumpCollision"))
        self.playerJumpRay.node().addSolid(self.jumpCheckSegment)
        self.playerJumpRay.node().setIntoCollideMask(0)
        self.jumper = CollisionHandlerEvent()
        self.jumper.addOutPattern("%fn-out")
        base.cTrav.addCollider(self.playerJumpRay, self.jumper)
        # a collision segment to check attacks
        self.attackCheckSegment = CollisionSegment(0, 0, 1, 0, -1.3, 1)
        self.playerAttackRay = self.player.attachNewNode(CollisionNode("playerAttackCollision"))
        self.playerAttackRay.node().addSolid(self.attackCheckSegment)
        self.playerAttackRay.node().setIntoCollideMask(0)
        self.attackqueue = CollisionHandlerQueue()
        base.cTrav.addCollider(self.playerAttackRay, self.attackqueue)

        #
        # SOUNDEFFECTS
        #
        self.footstep = loader.loadSfx("Footstep.ogg")
        self.footstep.setLoop(True)
        self.footstep.setPlayRate(1.5)
        self.footstep.setVolume(0.5)
        self.spearAttackSfx = loader.loadSfx("SpearAttack.ogg")
        self.spearAttackSfx.setVolume(0.5)

    #
    # START/STOP
    #
    def start(self, startPoint):
        self.player.setPos(startPoint.getPos())
        self.player.setHpr(startPoint.getHpr())
        self.player.reparentTo(render)
        self.jumpstartFloater.setPos(self.player.getPos())

        self.keyMap = {"horizontal": 0, "vertical": 0}

        self.health = 3
        self.trackedEnemy = None
        # this mode will be used to determine in which move mode the player currently is
        self.mode = Player.NormalMode
        # the initial cam height
        self.camHeight = self.camHeightAvg
        # a time to keep the cam zoom at a specific speed independent of
        # current framerate
        self.camElapsed = 0.0
        self.mouseSpeedX = 15.0 * base.mouseSensitivity
        self.mouseSpeedY = 0.2 * base.mouseSensitivity
        self.speed = 1.0

        self.camCenterEvents = ["centerCam", "home", "q"]
        self.camZoomInEvents = ["zoomIn", "+", "wheel_up"]
        self.camZoomOutEvents = ["zoomOut", "-", "wheel_down"]
        self.actionEvents = ["doAction", "enter", "e"]

        self.accept("arrow_left", self.setKey, ["horizontal", 1])
        self.accept("arrow_right", self.setKey, ["horizontal", -1])
        self.accept("arrow_up", self.setKey, ["vertical", -1])
        self.accept("arrow_down", self.setKey, ["vertical", 1])
        self.accept("arrow_left-up", self.setKey, ["horizontal", 0])
        self.accept("arrow_right-up", self.setKey, ["horizontal", 0])
        self.accept("arrow_up-up", self.setKey, ["vertical", 0])
        self.accept("arrow_down-up", self.setKey, ["vertical", 0])
        self.accept("a", self.setKey, ["horizontal", 1])
        self.accept("d", self.setKey, ["horizontal", -1])
        self.accept("w", self.setKey, ["vertical", -1])
        self.accept("s", self.setKey, ["vertical", 1])
        self.accept("a-up", self.setKey, ["horizontal", 0])
        self.accept("d-up", self.setKey, ["horizontal", 0])
        self.accept("w-up", self.setKey, ["vertical", 0])
        self.accept("s-up", self.setKey, ["vertical", 0])
        for event in self.camCenterEvents:
            self.acceptOnce(event, self.center)
        for event in self.camZoomInEvents:
            self.acceptOnce(event, self.zoom, [True])
        for event in self.camZoomOutEvents:
            self.acceptOnce(event, self.zoom, [False])
        for event in self.actionEvents:
            self.acceptOnce(event, self.request, ["Action"])
        self.accept("ActionDone", self.request, ["Idle"])

        self.accept("playerJumpCollision-out", self.jump)

        taskMgr.add(self.move, "task_movement", priority=-10)
        taskMgr.add(self.updateCam, "task_camActualisation", priority=-4)

        if self.hasJoystick:
            taskMgr.add(self.gamepadLoop, "task_gamepad_loop", priority=-5)

        camera.setPos(self.player, 0, self.camDistance, self.camHeightAvg)

        self.hasJumped = False
        self.isActionmove = False

        self.request("Idle")

    def stop(self):
        taskMgr.remove("task_movement")
        taskMgr.remove("task_camActualisation")
        taskMgr.remove("task_gamepad_loop")
        self.ignoreAll()
        self.player.hide()

    def cleanup(self):
        self.stop()
        if self.deathComplete is not None:
            self.deathComplete.finish()
        if self.jumpInterval is not None:
            self.jumpInterval.finish()
        self.spear.removeNode()
        self.shield.removeNode()
        self.player.cleanup()
        self.player.removeNode()
        self.jumpstartFloater.removeNode()
        self.camFloater.removeNode()

    #
    # BASIC FUNCTIONS
    #
    def die(self):
        self.health -= 1
        base.messenger.send("setHealth", [self.health])
        self.request("Death")

    def heal(self):
        if self.health >= 3:
            return
        self.health += 1
        base.messenger.send("setHealth", [self.health])

    def hit(self):
        self.health -= 1
        base.messenger.send("setHealth", [self.health])
        if self.health == 0:
            self.request("Death")
        else:
            self.request("Hit")

    def resetPlayerPos(self):
        self.player.setPos(self.jumpstartFloater.getPos())
        self.jumper.clear()
        self.request("Idle")

    def gameOver(self):
        base.messenger.send("GameOver", ["loose"])

    def enterFightMode(self, trackedEnemy):
        self.trackedEnemy = trackedEnemy
        self.mode = Player.FightMode
        base.messenger.send("EnterFightMode")

    def exitFightMode(self):
        self.trackedEnemy = None
        self.mode = Player.NormalMode
        base.messenger.send("ExitFightMode")

    def gamepadLoop(self, task):
        joymap = {0: "doAction", 5: "centerCam", 6: "zoomIn", 4: "zoomOut", 9: "escape"}
        for event in pygame.event.get():
            for button in range(self.mainJoystick.get_numbuttons()):
                if button in joymap and self.mainJoystick.get_button(button):
                    base.messenger.send(joymap[button])
            if event.type == pygame.JOYAXISMOTION:
                for axis in range(self.mainJoystick.get_numaxes()):
                    axisChange = 0.0
                    axisChange = self.mainJoystick.get_axis(axis)
                    if axis == 0:
                        self.setKey("horizontal", -axisChange)
                    if axis == 1:
                        self.setKey("vertical", axisChange)
        return task.cont

    def setAnimationSpeed(self, requestedState):
        if requestedState == "Run":
            self.player.setPlayRate(3 * self.speed, "Run")
        elif requestedState == "RunReverse":
            self.player.setPlayRate(-3 * self.speed, "Run")
        elif requestedState == "FightLeft":
            self.player.setPlayRate(2 * self.speed, "Fight_Left")
        elif requestedState == "FightRight":
            self.player.setPlayRate(2 * self.speed, "Fight_Right")

    #
    # MOVE FUNCTIONS
    #
    def setKey(self, key, value):
        self.keyMap[key] = value

    def move(self, task):
        dt = globalClock.getDt()
        resetMouse = False

        def resetMouse():
            if base.controlType == Player.MOUSEANDKEYBOARD:
                base.win.movePointer(0, self.winXhalf, self.winYhalf)

        if self.player.getAnimControl("Hit").isPlaying() or self.player.getAnimControl("Death").isPlaying():
            resetMouse()
            return task.cont
        if self.deathComplete is not None:
            if self.deathComplete.isPlaying():
                resetMouse()
                return task.cont
        if self.jumpInterval is not None:
            if self.jumpInterval.isPlaying():
                resetMouse()
                return task.cont
        if self.isActionmove:
            resetMouse()
            return task.cont

        if self.mode == Player.NormalMode:
            self.__normalMove(dt)
        else:
            self.__fightMove(dt)
        return task.cont

    def __normalMove(self, dt):
        requestState = "Idle"
        move = False
        if self.keyMap["horizontal"] != 0:
            requestState = "Run"
            move = True
        if self.keyMap["vertical"] != 0:
            requestState = "Run"
            move = True
        if move and base.controlType == Player.GAMEPADMODE:
            movementVec = Vec3(self.keyMap["horizontal"], self.keyMap["vertical"], 0)
            self.speed = max(abs(self.keyMap["horizontal"]), abs(self.keyMap["vertical"]))
            angle = math.atan2(-movementVec.getX(), movementVec.getY())
            rotation = angle * (180.0 / math.pi)
            self.player.setH(camera, rotation)
            self.player.setP(0)
            self.player.setR(0)
            self.player.setPos(self.player, (0, -2 * self.speed * dt, 0))
        elif base.controlType == Player.MOUSEANDKEYBOARD:
            if not base.mouseWatcherNode.hasMouse():
                return
            self.pointer = base.win.getPointer(0)
            mouseX = self.pointer.getX()
            mouseY = self.pointer.getY()

            if base.win.movePointer(0, self.winXhalf, self.winYhalf):
                z = camera.getZ() + (mouseY - self.winYhalf) * self.mouseSpeedY * dt
                camera.setZ(z)

                h = self.player.getH() - (mouseX - self.winXhalf) * self.mouseSpeedX * dt
                if h < -360:
                    h = 360
                elif h > 360:
                    h = -360
                self.player.setH(h)
                if move:
                    self.player.setPos(
                        self.player, (2 * dt * self.keyMap["horizontal"], 2 * dt * self.keyMap["vertical"], 0)
                    )
                self.center()
        if self.state != requestState:
            self.request(requestState)
        self.setAnimationSpeed(requestState)

    def __fightMove(self, dt):
        if self.trackedEnemy == None:
            return
        requestState = "Idle"
        self.player.lookAt(self.trackedEnemy)
        self.player.setH(self.player, 180)
        if self.keyMap["horizontal"] > 0:
            self.player.setX(self.player, 2 * self.speed * dt)
            requestState = "FightLeft"
        elif self.keyMap["horizontal"] < 0:
            self.player.setX(self.player, -2 * self.speed * dt)
            requestState = "FightRight"
        elif self.keyMap["vertical"] < 0:
            self.player.setY(self.player, -2 * self.speed * dt)
            requestState = "Run"
        elif self.keyMap["vertical"] > 0:
            self.player.setY(self.player, 2 * self.speed * dt)
            requestState = "RunReverse"
        if self.state != requestState:
            self.request(requestState)
        self.setAnimationSpeed(requestState)

    def jump(self, extraArg):
        intoName = extraArg.getIntoNode().getName().lower()
        if not "floor" in intoName and not "plate" in intoName:
            return
        # setup the projectile interval
        startPos = self.player.getPos()
        self.jumpstartFloater.setPos(self.player, 0, 0.5, 0)
        tempFloater = NodePath(PandaNode("tempJumpFloater"))
        tempFloater.setPos(self.player, 0, -3.2, 0.1)
        endPos = tempFloater.getPos()
        tempFloater.removeNode()
        self.jumpInterval = ProjectileInterval(
            self.player, startPos=startPos, endPos=endPos, duration=1.5, gravityMult=0.25
        )
        self.request("Jump")
        self.jumpInterval.start()

    #
    # CAMERA FUNCTIONS
    #
    def updateCam(self, task):
        if self.mode == Player.NormalMode:
            self.__normalCam()
        else:
            self.__fightCam()
        return task.cont

    def zoom(self, zoomIn):

        # Camera Movement Updates
        camvec = self.player.getPos() - camera.getPos()
        camvec.setZ(0)
        camdist = camvec.length()

        zoom = 0
        if zoomIn:
            if camdist > self.minCamDistance + 0.5:
                zoom = 0.5
            for event in self.camZoomInEvents:
                self.acceptOnce(event, self.zoom, [True])
        else:
            if camdist < self.maxCamDistance - 0.5:
                zoom = -0.5
            for event in self.camZoomOutEvents:
                self.acceptOnce(event, self.zoom, [False])
        camera.setPos(camera, 0, zoom, 0)

    def center(self):
        # Camera Movement Updates
        camvec = self.player.getPos() - camera.getPos()
        camvec.setZ(0)
        camdist = camvec.length()
        # get the cameras current offset to the player model on the z-axis
        offsetZ = camera.getZ() - self.player.getZ()
        camera.setPos(self.player, 0, camdist, offsetZ)
        for event in self.camCenterEvents:
            self.acceptOnce(event, self.center)

    def __normalCam(self):
        """This function will check the min and max distance of the camera to
        the defined model and will correct the position if the cam is to close
        or to far away"""

        # Camera Movement Updates
        camvec = self.player.getPos() - camera.getPos()
        camvec.setZ(0)
        camdist = camvec.length()
        camvec.normalize()

        # If far from player start following
        if camdist > self.maxCamDistance:
            camera.setPos(camera.getPos() + camvec * (camdist - self.maxCamDistance))
            camdist = self.maxCamDistance

        # If player to close move cam backwards
        if camdist < self.minCamDistance:
            camera.setPos(camera.getPos() - camvec * (self.minCamDistance - camdist))
            camdist = self.minCamDistance

        # get the cameras current offset to the player model on the z-axis
        offsetZ = camera.getZ() - self.player.getZ()
        # check if the camera is within the min and max z-axis offset
        if offsetZ < self.minCamHeightDist:
            camera.setZ(self.player.getZ() + self.minCamHeightDist)
            offsetZ = self.minCamHeightDist
        elif offsetZ > self.maxCamHeightDist:
            camera.setZ(self.player.getZ() + self.maxCamHeightDist)
            offsetZ = self.maxCamHeightDist

        if offsetZ != self.camHeightAvg and not base.controlType == Player.MOUSEANDKEYBOARD:
            # if we are not moving up or down, set the cam to an average position
            if offsetZ != self.camHeightAvg:
                if offsetZ > self.camHeightAvg:
                    # the cam is higher then the average cam height above the player
                    # so move it slowly down
                    camera.setZ(camera.getZ() - 5 * globalClock.getDt())
                    newOffsetZ = camera.getZ() - self.player.getZ()
                    # check if the cam has reached the desired offset
                    if newOffsetZ < self.camHeightAvg:
                        # set the cam z position to exactly the desired offset
                        camera.setZ(self.player.getZ() + self.camHeightAvg)
                else:
                    # the cam is lower then the average cam height above the player
                    # so move it slowly up
                    camera.setZ(camera.getZ() + 5 * globalClock.getDt())
                    newOffsetZ = camera.getZ() - self.player.getZ()
                    # check if the cam has reached the desired offset
                    if newOffsetZ > self.camHeightAvg:
                        # set the cam z position to exactly the desired offset
                        camera.setZ(self.player.getZ() + self.camHeightAvg)

        camera.lookAt(self.camFloater)

    def __fightCam(self):
        """This function will check the min and max distance of the camera to
        the defined model and will correct the position if the cam is to close
        or to far away"""
        camera.setX(self.player, 0)
        camera.setY(self.player, self.fightCamDistance)
        camera.setZ(0.5)

        camera.lookAt(self.camFloater)

    #
    # FSM FUNCTIONS
    #
    def enterIdle(self):
        if self.mode == Player.NormalMode:
            self.player.loop("Idle")
            self.footstep.stop()
        elif self.mode == Player.FightMode:
            self.player.loop("Fight_Idle")
            self.footstep.stop()

    def enterRun(self):
        self.player.loop("Run")
        self.footstep.play()

    def enterRunReverse(self):
        self.player.loop("Run")
        self.footstep.play()

    def enterAction(self):
        if self.player.getAnimControl("Hit").isPlaying() or self.player.getAnimControl("Death").isPlaying():
            self.__exitAction()
            return
        self.isActionmove = True
        if self.mode == Player.NormalMode:
            self.__enterActivate()
        elif self.mode == Player.FightMode:
            self.__enterFightAttack()
        self.accept("ActionDone", self.__exitAction)

    def __exitAction(self):
        self.isActionmove = False
        for event in self.actionEvents:
            self.acceptOnce(event, self.request, ["Action"])

    def __enterActivate(self):
        activateAnim = self.player.actorInterval("Activate", playRate=3)
        activateAnim.setDoneEvent("ActionDone")
        activateAnim.start()
        base.messenger.send("Player_Activate")
        self.footstep.stop()

    def enterDeath(self):
        self.footstep.stop()
        deathAnim = self.player.actorInterval("Death")
        deathComplete = None
        if self.health == 0:
            self.deathComplete = Sequence(deathAnim, Wait(2), Func(self.gameOver))
        else:
            self.deathComplete = Sequence(deathAnim, Wait(2), Func(self.resetPlayerPos))
        self.deathComplete.start()

    def enterJump(self):
        self.player.play("Jump")
        self.footstep.stop()

    def enterHit(self):
        self.player.setPlayRate(4, "Hit")
        self.player.play("Hit")
        self.footstep.stop()

    def __enterFightAttack(self):
        attackAnim = self.player.actorInterval("Fight_Attack", playRate=3)
        attackAnim.setDoneEvent("ActionDone")
        attackAnim.start()
        self.spearAttackSfx.play()
        for i in range(self.attackqueue.getNumEntries()):
            entry = self.attackqueue.getEntry(i)
            into = entry.getIntoNode()
            if "golemHitField" in into.getName():
                if random.random() > 0.15:
                    base.messenger.send("HitEnemy")
        self.footstep.stop()

    def enterFightLeft(self):
        self.player.loop("Fight_Left")
        self.footstep.play()

    def enterFightRight(self):
        self.player.loop("Fight_Right")
        self.footstep.play()
Beispiel #42
0
class HL2Pistol(BaseHitscan, HL2PistolShared):

    #ModelPath = "phase_14/hl2/w_pistol/w_pistol.bam"
    ModelOrigin = (-0.03, 1.19, -0.14)
    ModelAngles = (2.29, 347.01, 45)
    ModelScale = 2

    Name = GagGlobals.HL2Pistol
    ID = ATTACK_HL2PISTOL
    Hold = ATTACK_HOLD_RIGHT

    sgDir = 'phase_14/hl2/v_pistol/'
    sgActorDef = [
        sgDir + 'v_pistol.bam', {
            'draw': sgDir + 'v_pistol-draw.egg',
            'idle': sgDir + 'v_pistol-idle01.egg',
            'fire': sgDir + 'v_pistol-fire.egg',
            'reload': sgDir + 'v_pistol-reload.egg'
        }
    ]
    sgFirePath = 'phase_14/hl2/v_pistol/pistol_fire2.wav'
    sgEmptyPath = 'phase_14/hl2/v_pistol/pistol_empty.wav'
    sgReloadPath = 'phase_14/hl2/v_pistol/pistol_reload1.wav'

    SpecialVM = True

    def __init__(self):
        BaseHitscan.__init__(self)

        self.sgViewModel = None
        self.fireSound = None
        self.emptySound = None
        self.reloadSound = None
        self.fpMuzzleAttach = None

    @classmethod
    def doPrecache(cls):
        super(HL2Pistol, cls).doPrecache()

        precacheActor(cls.sgActorDef)

        precacheSound(cls.sgFirePath)
        precacheSound(cls.sgEmptyPath)
        precacheSound(cls.sgReloadPath)

    def load(self):
        self.fireSound = base.audio3d.loadSfx(self.sgFirePath)
        self.emptySound = base.audio3d.loadSfx(self.sgEmptyPath)
        self.reloadSound = base.audio3d.loadSfx(self.sgReloadPath)
        base.audio3d.attachSoundToObject(self.fireSound, self.avatar)
        base.audio3d.attachSoundToObject(self.emptySound, self.avatar)
        base.audio3d.attachSoundToObject(self.reloadSound, self.avatar)

        if self.isLocal():
            self.sgViewModel = Actor(self.sgActorDef[0], self.sgActorDef[1])
            self.sgViewModel.setPlayRate(self.Speed, "idle")
            self.sgViewModel.node().setBounds(OmniBoundingVolume())
            self.sgViewModel.node().setFinal(1)
            self.sgViewModel.setBlend(
                frameBlend=base.config.GetBool('interpolate-frames', False))
            self.sgViewModel.setH(180)
            self.fpMuzzleAttach = self.sgViewModel.exposeJoint(
                None, "modelRoot", "ValveBiped.muzzle")

    def cleanup(self):
        if self.sgViewModel:
            self.sgViewModel.cleanup()
            self.sgViewModel.removeNode()
        self.sgViewModel = None

        self.fpMuzzleAttach = None

        if self.fireSound:
            base.audio3d.detachSound(self.fireSound)
        self.fireSound = None

        if self.emptySound:
            base.audio3d.detachSound(self.emptySound)
        self.emptySound = None

        if self.reloadSound:
            base.audio3d.detachSound(self.reloadSound)
        self.reloadSound = None

        BaseHitscan.cleanup(self)

    def equip(self):
        if not BaseHitscan.equip(self):
            return False

        if self.isFirstPerson():
            fpsCam = self.getFPSCam()
            fpsCam.swapViewModel(self.sgViewModel, 54.0)
            self.getViewModel().show()

        self.doDrawAndHold('squirt', 0, 43, 1.0, 43, 43)

        return True

    def unEquip(self):
        if not BaseHitscan.unEquip(self):
            return False

        if self.isFirstPerson():
            self.getFPSCam().restoreViewModel()
            self.getViewModel().hide()

        return True

    def onSetAction(self, action):
        if action == self.StateReload:
            self.reloadSound.play()
        elif action == self.StateFire:
            self.fireSound.play()

    def onSetAction_firstPerson(self, action):
        track = Sequence()
        vm = self.getViewModel()
        fpsCam = self.getFPSCam()
        if action == self.StateIdle:
            track.append(Func(vm.loop, "idle"))
        elif action == self.StateDraw:
            track.append(ActorInterval(vm, "draw", playRate=self.Speed))
        elif action == self.StateReload:
            track.append(Func(self.reloadSound.play))
            track.append(ActorInterval(vm, "reload", playRate=self.Speed))
        elif action == self.StateFire:
            CIGlobals.makeMuzzleFlash(self.fpMuzzleAttach, (0, 0, 0),
                                      (-90, 0, 0), 7)
            fpsCam.resetViewPunch()
            fpsCam.addViewPunch(
                Vec3(random.uniform(-0.6, 0.6), random.uniform(-0.25, -0.5),
                     0.0))
            track.append(Func(self.fireSound.play))
            track.append(ActorInterval(vm, "fire", playRate=self.Speed))
        fpsCam.setVMAnimTrack(track)
Beispiel #43
0
class Gag(object):

    def __init__(self, name, model, damage, gagType, hitSfx, playRate = 1.0, anim = None, scale = 1, autoRelease = False):
        __metaclass__ = ABCMeta
        self.name = name
        self.model = model
        self.anim = anim
        self.scale = scale
        self.damage = damage
        self.gagType = gagType
        self.playRate = playRate
        self.avatar = None
        self.gag = None
        self.splat = None
        self.splatPos = None
        self.state = GagState.LOADED
        self.woosh = None
        self.handJoint = None
        self.equipped = False
        self.autoRelease = autoRelease
        self.index = None
        self.target = None
        self.health = 0
        self.id = GagGlobals.getIDByName(name)
        self.image = None
        if game.process == 'client':
            if gagType == GagType.THROW:
                self.woosh = base.audio3d.loadSfx(GagGlobals.PIE_WOOSH_SFX)
            self.hitSfx = base.audio3d.loadSfx(hitSfx)
        return

    @abc.abstractmethod
    def start(self):
        if not self.avatar:
            return
        backpack = self.avatar.getBackpack()
        if not backpack:
            return
        if self not in backpack.getGags():
            return
        if backpack.getSupply(self.getName()) == 0:
            return
        try:
            base.audio3d.detachSound(self.woosh)
            self.track.pause()
            self.cleanupGag()
        except:
            pass

        self.state = GagState.START
        self.avatar.getBackpack().setActiveGag(self.getName())

    @abc.abstractmethod
    def reset(self):
        self.state = GagState.LOADED
        self.target = None
        if self.avatar:
            backpack = self.avatar.getBackpack()
            if backpack.getActiveGag():
                if backpack.getActiveGag() == self:
                    backpack.setActiveGag(None)
        return

    @abc.abstractmethod
    def throw(self):
        pass

    @abc.abstractmethod
    def release(self):
        self.state = GagState.RELEASED

    @abc.abstractmethod
    def buildCollisions(self):
        pass

    @abc.abstractmethod
    def onCollision(self):
        pass

    def setAvatar(self, avatar):
        self.avatar = avatar

    def getAvatar(self):
        return self.avatar

    def setState(self, paramState):
        self.state = paramState

    def getState(self):
        return self.state

    def setTarget(self, target):
        self.target = target

    def getTarget(self):
        return self.target

    def getType(self):
        return self.gagType

    def build(self):
        if self.anim:
            self.gag = Actor(self.model, {'chan': self.anim})
        else:
            self.gag = loader.loadModel(self.model)
        self.setHandJoint()
        self.gag.setScale(self.scale)
        self.gag.setName(self.getName())

    def setHandJoint(self):
        if self.avatar:
            self.handJoint = self.avatar.find('**/def_joint_right_hold')

    def equip(self):
        if not self.avatar or not self.avatar.getBackpack() or self.avatar.getBackpack() and self.avatar.getBackpack().getSupply(self.getName()) == 0:
            return
        self.setHandJoint()
        if not self.gag:
            self.build()
        self.gag.reparentTo(self.handJoint)
        self.equipped = True

    @abc.abstractmethod
    def unEquip(self):
        if game.process != 'client':
            return
        if self.equipped and self.handJoint:
            inHand = self.handJoint.getChildren()
            for item in inHand:
                if item.getName() == self.getName():
                    item.removeNode()

            self.equipped = False
            self.reset()
            base.localAvatar.enablePieKeys()

    def setHealth(self, health):
        self.health = health

    def getHealth(self):
        return self.health

    def setImage(self, image):
        self.image = image

    def getImage(self):
        return self.image

    def getDamage(self):
        return self.damage

    def getName(self):
        return self.name

    def delete(self):
        self.unEquip()
        self.handJoint = None
        self.avatar = None
        self.state = None
        self.cleanupGag()
        self.cleanupSplat()
        if self.woosh:
            self.woosh.stop()
            self.woosh = None
        if self.hitSfx:
            self.hitSfx.stop()
            self.hitSfx = None
        return

    def cleanupGag(self):
        try:
            self.track.pause()
        except:
            pass

        if self.gag and self.state == GagState.LOADED:
            name = self.gag.getName()
            if self.anim:
                self.gag.cleanup()
            if self.avatar:
                copies = self.avatar.findAllMatches('**/%s' % name)
                for copy in copies:
                    copy.removeNode()

            if self.gag and not self.gag.isEmpty():
                self.gag.removeNode()
            self.gag = None
        return

    def getGag(self):
        return self.gag

    def placeProp(self, handJoint, prop, pos = None, hpr = None, scale = None):
        prop.reparentTo(handJoint)
        if pos:
            prop.setPos(pos)
        if hpr:
            prop.setHpr(hpr)
        if scale:
            prop.setScale(scale)

    def getScaleTrack(self, props, duration, startScale, endScale):
        track = Parallel()
        if not isinstance(props, list):
            props = [props]
        for prop in props:
            track.append(LerpScaleInterval(prop, duration, endScale, startScale=startScale))

        return track

    def getSoundTrack(self, delay, node, duration = None):
        soundTrack = Sequence()
        soundTrack.append(Wait(delay))
        if duration:
            soundTrack.append(SoundInterval(self.hitSfx, duration=duration, node=node))
        else:
            soundTrack.append(SoundInterval(self.hitSfx, node=node))
        return soundTrack

    def getScaleIntervals(self, props, duration, startScale, endScale):
        tracks = Parallel()
        if not isinstance(props, list):
            props = [props]
        for prop in props:
            tracks.append(LerpScaleInterval(prop, duration, endScale, startScale=startScale))

        return tracks

    def getScaleBlendIntervals(self, props, duration, startScale, endScale, blendType):
        tracks = Parallel()
        if not isinstance(props, list):
            props = [props]
        for prop in props:
            tracks.append(LerpScaleInterval(prop, duration, endScale, startScale=startScale, blendType=blendType))

        return tracks

    def buildSplat(self, scale, color):
        self.cleanupSplat()
        self.splat = Actor(GagGlobals.SPLAT_MDL, {'chan': GagGlobals.SPLAT_CHAN})
        self.splat.setScale(scale)
        self.splat.setColor(color)
        self.splat.setBillboardPointEye()
        self.splat.play('chan')
        return self.splat

    def setSplatPos(self, x, y, z):
        self.cleanupGag()
        self.splatPos = Point3(x, y, z)
        self.handleSplat()

    def cleanupSplat(self):
        if self.splat:
            self.splat.cleanup()
            self.splat

    def setEndPos(self, x, y, z):
        pass

    def handleSplat(self):
        pass

    def delSplat(self, task):
        self.cleanupSplat()
        return Task.done

    def getAudio3D(self):
        return base.audio3d

    def doesAutoRelease(self):
        return self.autoRelease

    def isLocal(self):
        if not self.avatar:
            return False
        return self.avatar.doId == base.localAvatar.doId

    def getID(self):
        return self.id
Beispiel #44
0
class Item(DirectObject, object):
    '''
    道具类的虚基类
    '''

    num = 0  # use to identify item collition node

    def __init__(self, itemName):
        super(Item, self).__init__()
        self.number = Item.num
        self.itemName = itemName
        Item.num += 1

    def initModel(self, pos, scale, player, buffState, parent=None):
        '''
        初始化道具模型和设置碰撞检测
        #pos 道具模型的放置位置 (世界坐标系)
        #scale 模型缩放比例
        #player 英雄实例
        '''

        # 加载并设置模型
        try:
            modelName = ModelPath + "model_" + self.itemName
            self.item = Actor(modelName, {'revolve': modelName})
            self.item.loop('revolve')
        except Exception:
            self.item = Actor()
            self.item.setScale(0.3)

        self.item.setPos(pos)
        self.item.setScale(scale)
        if parent == None:
            self.item.reparentTo(base.render)
        else:
            self.item.reparentTo(parent)
        # 设置碰撞检测
        collisionSphere = CollisionSphere(0, 0, 0, 1)
        self.collisionNodeName = "{}CollisionNode{}".format(
            self.itemName, self.number)
        itemColNode = CollisionNode(self.collisionNodeName)
        itemColNode.addSolid(collisionSphere)
        itemColNode.setIntoCollideMask(CollideMask.bit(DefaultHeroMaskVal))
        itemColNode.setFromCollideMask(CollideMask.allOff())
        self.itemCollision = self.item.attachNewNode(itemColNode)
        self.itemCollision.setPythonTag("Item", self)
        ##显示包围体   用于粗略模拟道具盒
        # self.itemCollision.show()
        base.cTrav.addCollider(self.itemCollision, base.cHandler)

        inEvent = "{}-into-{}".format(player.colliderName,
                                      self.collisionNodeName)
        self.accept(inEvent, self.action)
        buffState.accept(inEvent, buffState.addBuff)

    @print_func_time
    def action(self, entry):
        '''
        碰撞处理事件
        将道具效果应用到英雄对象
        不同类型道具有不同实现方式
        '''
        #print self.itemName,self.collisionNodeName
        player = entry.getFromNodePath().getPythonTag("Hero")
        player.sounds["GetItem"].play()

    @print_func_time
    def _destroy(self):
        '''
        道具使用后立即销毁
        '''
        self.ignoreAll()
        if not self.item.isEmpty():
            self.item.cleanup()
            self.item.removeNode()
Beispiel #45
0
class Enemy(FSM, Unit):

    # Declare private variables
    _enemyActive = False
    _removeCorpseDelay = 2 # seconds before corpse is cleaned

    def __init__(self, mainRef, attributes):
        print("Enemy instantiated")
        Unit.__init__(self)
        FSM.__init__(self, 'playerFSM')

        self._mainRef = mainRef
        self._playerRef = mainRef.player
        self._AIworldRef = mainRef.AIworld
        self._enemyListRef = mainRef.enemyList
        self._ddaHandlerRef = mainRef.DDAHandler
        self._stateHandlerRef = mainRef.stateHandler
        self._scenarioHandlerRef = mainRef.scenarioHandler

        #self.topEnemyNode = mainRef.mainNode.attachNewNode('topEnemyNode')
        self.initEnemyNode(mainRef.mainNode)

        utils.enemyDictionary[self.enemyNode.getName()] = self

        self.loadEnemyModel(attributes.modelName)
        self.initAttributes(attributes)
        self.initEnemyAi()

        self.initEnemyDDA()

        self.initEnemyCollisionHandlers()
        self.initEnemyCollisionSolids()

        #self.request('Idle')
        self.request('Disabled')

        # Start enemy updater task
        self.enemyUpdaterTask = taskMgr.add(self.enemyUpdater, 'enemyUpdaterTask')

    def initEnemyNode(self, parentNode):
        enemyName = 'enemy' + str(len(self._enemyListRef))
        self.enemyNode = parentNode.attachNewNode(enemyName)
        self._enemyListRef.append(self)

    def loadEnemyModel(self, modelName):
        modelPrefix = 'models/' + modelName
        self.enemyModel = Actor(modelPrefix + '-model', {
                'walk':modelPrefix+'-walk',
                'attack':modelPrefix+'-attack',
                'idle':modelPrefix+'-idle',
                'awake':modelPrefix+'-awake',
                'stop':modelPrefix+'-stop',
                'hit':modelPrefix+'-hit',
                'death1':modelPrefix+'-death1',
                'death2':modelPrefix+'-death2'
            })
        self.enemyModel.reparentTo(self.enemyNode)

        self.enemyNode.setPos(Point3.zero())

        self.enemyNode.setDepthOffset(-1)

    def initAttributes(self, attributes):
        perceptionRangeMultiplier = 1.2
        combatRangeMultiplier = .3
        speedMultiplier = .1

        self.strength = attributes.strength
        self.constitution = attributes.constitution
        self.dexterity = attributes.dexterity

        self.mass = attributes.mass
        self.movementSpeed = speedMultiplier * attributes.movementSpeed
        self.perceptionRange = perceptionRangeMultiplier * attributes.perceptionRange
        self.combatRange = combatRangeMultiplier * attributes.combatRange
        self.attackBonus = attributes.attackBonus
        self.damageBonus = attributes.damageBonus
        self.damageRange = attributes.damageRange
        self.initiativeBonus = attributes.initiativeBonus
        self.fixedHealthPoints = attributes.fixedHealthPoints
        self.armorClass = attributes.armorClass

        if attributes.startLevel > 1:
            for i in range(attributes.startLevel-1):
                self.increaseLevel()

        self.expAward = attributes.expAward

        self.initHealth()

    def initEnemyDDA(self):
        if self._scenarioHandlerRef.getHasDDA():
            maxLevelDifference = self._ddaHandlerRef.maxLevelDifference

            # Level enemy up to player's level minus maxLevelDifference
            levelDifference = self._playerRef.level - self.level
            if levelDifference >= maxLevelDifference:
                for i in range (levelDifference-maxLevelDifference):
                    self.increaseLevel()

    def getAttackBonus(self):
        modifier = self.getStrengthModifier() if self.getStrengthModifier() > self.getDexterityModifier() else self.getDexterityModifier()
        ab = self.attackBonus + (self.level / 2) + modifier# + utils.getD20()

        if self._scenarioHandlerRef.getHasDDA():
            attackBonusModifier = self._ddaHandlerRef.attackBonusModifier
            if attackBonusModifier < 0:
                ab -= attackBonusModifier
                if ab < 1:
                    ab = 1

        return ab + utils.getD20()

    def initEnemyAi(self):
        self.enemyAI = AICharacter('enemy',
                                self.enemyNode,
                                self.mass, # Mass
                                0.1, # Movt force
                                self.movementSpeed) # Max force
        self._AIworldRef.addAiChar(self.enemyAI)

        self.enemyAIBehaviors = self.enemyAI.getAiBehaviors()
        #self.enemyAIBehaviors.obstacleAvoidance(1.0)

    def initEnemyCollisionHandlers(self):
        self.groundHandler = CollisionHandlerQueue()
        self.collPusher = CollisionHandlerPusher()

    def initEnemyCollisionSolids(self):
        # Enemy ground ray
        groundRay = CollisionRay(0, 0, 2, 0, 0, -1)
        groundColl = CollisionNode('enemyGroundRay')
        groundColl.addSolid(groundRay)

        groundColl.setIntoCollideMask(BitMask32.allOff())
        groundColl.setFromCollideMask(BitMask32.bit(1))

        self.groundRayNode = self.enemyNode.attachNewNode(groundColl)
        #self.groundRayNode.show()

        base.cTrav.addCollider(self.groundRayNode, self.groundHandler)

        # Enemy collision sphere
        collSphereNode = CollisionNode('enemyCollSphere')
        collSphere = CollisionSphere(0, 0, 0.1, 0.2)
        collSphereNode.addSolid(collSphere)

        collSphereNode.setIntoCollideMask(BitMask32.allOff())
        collSphereNode.setFromCollideMask(BitMask32.bit(2))
        
        self.sphereNode = self.enemyNode.attachNewNode(collSphereNode)
        #sphereNode.show()

        base.cTrav.addCollider(self.sphereNode, self.collPusher)
        self.collPusher.addCollider(self.sphereNode, self.enemyNode)

        # Enemy picker collision sphere
        pickerSphereCollNode = CollisionNode(self.enemyNode.getName())
        pickerCollSphere = CollisionSphere(0, 0, 0, 0.5)
        pickerSphereCollNode.addSolid(pickerCollSphere)

        pickerSphereCollNode.setFromCollideMask(BitMask32.allOff())
        pickerSphereCollNode.setIntoCollideMask(BitMask32.bit(1))

        self.pickerNode = self.enemyNode.attachNewNode(pickerSphereCollNode)
        #sphereNodePath.show()

        # Enemy attack collision sphere
        attackCollSphereNode = CollisionNode(self.enemyNode.getName()+'atkSph')
        attackCollSphere = CollisionSphere(0, 0, 0.1, 0.15)
        attackCollSphereNode.addSolid(attackCollSphere)

        attackCollSphereNode.setIntoCollideMask(BitMask32.bit(3))
        attackCollSphereNode.setFromCollideMask(BitMask32.allOff())

        attackSphereNode = self.enemyNode.attachNewNode(attackCollSphereNode)
        #attackSphereNode.show()

    def slowMovementByPercentage(self, percentage=30, slowDuration=20):
        #print self.enemyNode.getName(), ' slowed by ', percentage, ' %'
        oldSpeed = self.movementSpeed
        newSpeed = ((100.0 - percentage) / 100.0) * oldSpeed

        if newSpeed < 1.0:
            newSpeed = 1.0

        self.movementSpeed = newSpeed

        taskMgr.doMethodLater(slowDuration, self.removeSlowMovement, 'removeSlowMovementTask', extraArgs=[oldSpeed], appendTask=True)

    def removeSlowMovement(self, oldSpeed, task):
        self.movementSpeed = oldSpeed
        return task.done

    def checkGroundCollisions(self):
        if self.groundHandler.getNumEntries() > 0:
            self.groundHandler.sortEntries()
            entries = []
            for i in range(self.groundHandler.getNumEntries()):
                entry = self.groundHandler.getEntry(i)
                #print('entry:', entry)
                entries.append(entry)

            entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(),
                                         x.getSurfacePoint(render).getZ()))

            for i in range(len(entries)):
                if entries[i].getIntoNode().getName()[:6] == 'ground':
                    #print('entryFound:', entries[0])
                    newZ = entries[i].getSurfacePoint(base.render).getZ()
                    self.enemyNode.setZ(newZ)
                    #print('enemyZ:', newZ)
                    break;

    def enemyUpdater(self, task):
        if self._stateHandlerRef.state != self._stateHandlerRef.PLAY or not self._enemyActive:
            self.enemyModel.stop()
            # Do not do anything when paused
            return task.cont

        self.checkGroundCollisions()

        if self.getIsDead():
            self.onDeath()
            return task.done

        if self._playerRef.getIsDead():
            return task.cont

        playerPos = self._playerRef.playerNode.getPos()
        enemyPos = self.enemyNode.getPos()

        # If player is within enemy perception range
        if utils.getIsInRange(playerPos, enemyPos, self.perceptionRange):

            # If enemy is not doing anything
            if self.state == 'Idle':
                # Start pursuing
                if self.state != 'Pursue':
                    self.request('Pursue')

            # If enemy is already pursueing
            elif self.state == 'Pursue':
                # If player is within combat range
                if utils.getIsInRange(playerPos, enemyPos, self.combatRange):
                    #print 'enemy go to combat'
                    # Go to combat
                    if self.state != 'Combat':
                        self.request('Combat')

            # If enemy is already in combat
            elif self.state == 'Combat':
                # If player has moved out of combat range
                if not utils.getIsInRange(playerPos, enemyPos, self.combatRange):
                    # Start pursuing
                    if self.state != 'Pursue':
                        self.request('Pursue')

            # If enemy is disabled
            elif self.state == 'Disabled':
                if self.enemyAI.getMaxForce() != self.movementSpeed:
                    self.enemyAI.setMaxForce(self.movementSpeed)

        # If player is not within perception range
        else:
            if self.state != 'Idle':
                self.request('Idle')

        return task.cont

    def pursuePlayer(self):
        taskMgr.add(self.pursue, 'pursueTask')

    def pursue(self, task):
        if self.state == 'Pursue' and not self.getIsDead():
            pitchRoll = self.enemyNode.getP(), self.enemyNode.getR()
            self.enemyNode.headsUp(self._playerRef.playerNode)
            self.enemyNode.setHpr(self.enemyNode.getH()-180, *pitchRoll)

            speed = -self.movementSpeed * globalClock.getDt()
            self.enemyNode.setFluidPos(self.enemyNode, 0, speed, 0)

            return task.cont
        else:
            task.done

    def enterIdle(self):
        #print 'enemy enterIdle'
        stopEnemy = self.enemyModel.actorInterval('stop', loop=0)
        idleEnemy = self.enemyModel.actorInterval('idle', startFrame=0, endFrame=1, loop=0)

        self.stopSequence = Sequence(stopEnemy, idleEnemy)
        self.stopSequence.start()

        self.isSleeping = True

    def exitIdle(self):
        #print('enemy exitIdle')
        self.stopSequence.finish()

    def enterPursue(self):
        #print('enemy enterPursue')
        loopWalkEnemy = Func(self.enemyModel.loop, 'walk', fromFrame=0, toFrame=12)

        # Only awake enemy if it comes from idle
        if self.isSleeping: 
            self.isSleeping = False

            awakeEnemy = self.enemyModel.actorInterval('awake', loop=0)
            self.awakeSequence = Sequence(awakeEnemy, loopWalkEnemy, Func(self.pursuePlayer))
        else:
            self.awakeSequence = Sequence(loopWalkEnemy, Func(self.pursuePlayer))

        self.awakeSequence.start()

    def exitPursue(self):
        #print('enemy exitPursue')
        self.awakeSequence.finish()

    def enterCombat(self):
        #print('enemy enterCombat')
        self.enemyModel.stop()

        attackDelay = self.getInitiativeRoll()
        self.attackTask = taskMgr.doMethodLater(attackDelay, self.attackPlayer, 'attackPlayerTask')

    def enterDisabled(self):
        #print 'enterDisable'
        pass

    def exitDisabled(self):
        #print 'exitDisable'
        pass

    def exitCombat(self):
        #print('enemy exitCombat')
        taskMgr.remove(self.attackTask)

    def enterDeath(self):
        #print('enemy enterDeath')
        self.enemyAIBehaviors.removeAi('all')
        randomDeathAnim = 'death' + str(utils.getD2())
        self.enemyModel.play(randomDeathAnim)


    def attack(self, other):
        if not self.getIsDead() and not other.getIsDead():
            if self.getAttackBonus() >= other.getArmorClass():
                dmg = self.getDamageBonus()
                #print(self.getName(), ' damaged ', other.getName(), ' for ', dmg, ' damage')
                other.receiveDamage(dmg)

                return 2 # Returns 2 when self damages other

            return 1 # Returns 1 when self attacks other, but misses

        return 0 # Returns 0 when either self or other is dead

    def attackPlayer(self, task):
        if self._stateHandlerRef.state != self._stateHandlerRef.PLAY or not self._enemyActive:
            # Do not do anything when paused
            return task.again

        if self._playerRef.getIsDead():
            print('player is already dead')
            self.request('Idle')
            return task.done

        elif self.getIsDead():
            return task.done

        else:
            #print('Attack player!')
            # Make sure enemy is facing player when attacking
            pitchRoll = self.enemyNode.getP(), self.enemyNode.getR()
            self.enemyNode.headsUp(self._playerRef.playerNode)
            self.enemyNode.setHpr(self.enemyNode.getH()-180, *pitchRoll)

            attacked = self.attack(self._playerRef)
            if attacked != 0:
                self.playAttackAnimation()
                if attacked == 2:
                    self._playerRef.playerModel.play('hit')

            return task.again

    def playAttackAnimation(self):
        self.enemyModel.play('attack', fromFrame=0, toFrame=12)

    def playHitAnimation(self):
        self.enemyModel.play('hit')

    def moveEnemy(self, x, y):
        self.enemyNode.setPos(x, y, .01)

    def handleHealthGlobe(self):
        global dropChanceFactor
        global dropChance
        global maxDropChance

        # if we drop, create health goblet
        chance = dropChanceFactor + dropChance
        if self._scenarioHandlerRef.getHasDDA():
            chance *= self._ddaHandlerRef.healthGobletModifier

        if utils.getD100() <= chance:
            HealthGoblet(self._mainRef, self)
            print 'dropping health goblet'
        # Otherwise, increase dropChance
        else:
            if dropChance+dropChanceFactor <= maxDropChance:
                dropChance += dropChanceFactor

    def suicide(self):
        print('suicide: ', self)
        # Remove AI behavior
        self.enemyAIBehaviors.removeAi('all')

        # Remove enemy picker sphere (handlerQueue)
        self.pickerNode.removeNode()

        taskMgr.add(self.removeCorpse, 'removeCorpseTask')

    def onDeath(self):
        if self.getIsDead():
            # Remove AI behavior
            self.enemyAIBehaviors.removeAi('all')

            # Award the player exp
            self._playerRef.receiveEXP(self.expAward)

            # Remove enemy picker sphere (handlerQueue)
            self.pickerNode.removeNode()

            # Change state
            self.request('Death')

            # Increase DDA death count
            if self._scenarioHandlerRef.getHasDDA():
                self._ddaHandlerRef.enemyDeathCount += 1

            # Handle health globe
            self.handleHealthGlobe()

            # Remove enemy corpse and clean up
            taskMgr.doMethodLater(self._removeCorpseDelay, self.removeCorpse, 'removeCorpseTask')

    def removeCorpse(self, task):
        # Remove enemy collision sphere (pusher)
        self.sphereNode.removeNode()

        # Stop the collision pusher
        self.collPusher = None

        # Remove enemy from enemyList
        self._enemyListRef.remove(self)

        # Cleanup the enemy model
        self.enemyModel.cleanup()
        self.enemyModel.delete()

        # Cleanup FSM
        self.cleanup()

        # Remove the enemy node
        self.enemyNode.removeNode()
        #self.topEnemyNode.removeNode()

        # Remove enemy updater tasks
        taskMgr.remove(self.enemyUpdaterTask)

        # Remove the passive regeneration task (from Unit class)
        self.removePassiveRegeneration()

        # Remove references
        self._mainRef = None
        self._playerRef = None
        self._AIworldRef = None
        self._enemyListRef = None
        self._stateHandlerRef = None

        return task.done
Beispiel #46
0
class DynObject():

    def __init__(self, render, objid, start_pos, gameclient):
        self.client = gameclient
        self.id = objid
        self.motion_controller = None
        self.is_player = False
        
        # state  management
        self.isAnimating = False
        self.state = state.IDLE
        
        self.render = render    # scene graph root
        
        #  create the panda3d actor: just load a default model for now
        self.actor = Actor("models/ralph",
                            {"run":"models/ralph-run",
                             "walk":"models/ralph-walk"})
                             
        self.actor.reparentTo(render)
        self.actor.setScale(.2)
        self.actor.setPos(start_pos)

        # prepare collision handling
        self.cTrav = CollisionTraverser()
        self.GroundRay = CollisionRay()
        self.GroundRay.setOrigin(0,0,1000)
        self.GroundRay.setDirection(0,0,-1)
        self.GroundCol = CollisionNode('actorRay')
        self.GroundCol.addSolid(self.GroundRay)
        self.GroundCol.setFromCollideMask(BitMask32.bit(0))
        self.GroundCol.setIntoCollideMask(BitMask32.allOff())
        self.GroundColNp = self.actor.attachNewNode(self.GroundCol)
        self.GroundHandler = CollisionHandlerQueue()
        self.cTrav.addCollider(self.GroundColNp, self.GroundHandler)

    def destroy(self):
        if self.actor != None:
            self.actor.cleanup()
            self.actor.removeNode()
            self.actor = None
            
    # called reqularly from a Panda3 task
    # move the object according to its current state
    def move(self):
        actor = self.actor

        # save our initial position so that we can restore it,
        # in case we fall off the map or run into something.
        startpos = actor.getPos()
        
        # let the motion_controller determine our new state
        self.motion_controller.processMove()
        
        # evaluate state and  move/rotate the actor accordingly
        if (self.state & state.LEFT):
            actor.setH(actor.getH() + 300 * globalClock.getDt())
        if (self.state & state.RIGHT):
            actor.setH(actor.getH() - 300 * globalClock.getDt())
        if (self.state & state.FORWARD):
            actor.setY(actor, -25 * globalClock.getDt())

        # Simplistic animation control: 
        # If we are moving, loop the run animation.
        # If we are standing still, stop the animation.
        if (self.state != state.IDLE):
            if self.isAnimating is False:
                actor.loop("run")
                self.isAnimating = True
        else:
            if self.isAnimating:
                actor.stop()
                actor.pose("walk", 5)
                self.isAnimating = False
    
        # Now check for collisions.
        self.cTrav.traverse(render)

        # Adjust Z coordinate.  If the ray hit terrain,
        # update Z. If it hit anything else, or didn't hit anything, put
        # us back where we were last frame.
        entries = []
        for i in range(self.GroundHandler.getNumEntries()):
            entry = self.GroundHandler.getEntry(i)
            entries.append(entry)
        entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(),
                                     x.getSurfacePoint(render).getZ()))
        if (len(entries)>0) and (entries[0].getIntoNode().getName() == "terrain"):
            self.actor.setZ(entries[0].getSurfacePoint(render).getZ())
        else:
            self.actor.setPos(startpos)

        # if this is the player avatar: make the camera follow us
        if self.is_player is True:
            self.client.world.moveCamera()

    # convenience getter/setters
    def setPos(self, pos):
        self.actor.setPos(pos)
    def getPos(self):
        return self.actor.getPos()
    def getH(self):
        return self.actor.getH()
    def getX(self):
        return self.actor.getX()
    def getY(self):
        return self.actor.getY()
    def getZ(self):
        return self.actor.getZ()
class DistributedScienceFair(DistributedObject):
    def announceGenerate(self):
        DistributedObject.announceGenerate(self)

        self.tent = loader.loadModel('phase_4/models/events/event_tent.bam')
        self.tent.reparentTo(render)
        self.tent.setPosHpr(0, 0, 0, 270, 0, 0)

        self.redFlag = Actor(loader.loadModel('phase_4/models/events/event-flag-mod.bam'))
        self.redFlag.loadAnims({'waving': 'phase_4/models/events/event-flag-anim.bam'})
        self.redFlag.reparentTo(self.tent.find('**/flag1_jnt'))
        self.redFlag.loop('waving')

        self.blueFlag = Actor(loader.loadModel('phase_4/models/events/event-flag-mod.bam'))
        self.blueFlag.loadAnims({'waving': 'phase_4/models/events/event-flag-anim.bam'})
        self.blueFlag.reparentTo(self.tent.find('**/flag2_jnt'))
        self.blueFlag.loop('waving')

        self.tent2 = loader.loadModel('phase_4/models/events/event_tent.bam')
        self.tent2.reparentTo(render)
        self.tent2.setPosHpr(85.91, 149.76, 2.61, 327.99, 0, 0)

        self.balloonArchway = loader.loadModel('phase_4/models/events/balloon_archway_spiraled.bam')
        self.balloonArchway.reparentTo(render)
        self.balloonArchway.setPosHpr(-24.25, 17.24, 0, 0, 0, 0)
        self.balloonArchway.flattenStrong()

        self.balloonArchway2 = loader.loadModel('phase_4/models/events/balloon_archway_spiraled.bam')
        self.balloonArchway2.reparentTo(render)
        self.balloonArchway2.setPosHpr(-24.25, -31.03, 0, 0, 0, 0)
        self.balloonArchway2.flattenStrong()

        self.balloonArchway3 = loader.loadModel('phase_4/models/events/balloon_archway_spiraled.bam')
        self.balloonArchway3.reparentTo(render)
        self.balloonArchway3.setPosHpr(99.6, 0.65, 4, 272.39, 0, 0)
        self.balloonArchway3.setScale(1.21)
        self.balloonArchway3.flattenStrong()

        self.balloontowerCake = loader.loadModel('phase_4/models/events/balloon_set_cake.bam')
        self.balloontowerCake.reparentTo(render)
        self.balloontowerCake.setPosHpr(95.65, 6.75, 4, 270, 0, 0)
        self.balloontowerCake.flattenStrong()

        self.balloontowerStar = loader.loadModel('phase_4/models/events/balloon_set_star.bam')
        self.balloontowerStar.reparentTo(render)
        self.balloontowerStar.setPosHpr(95.70, -5.56, 4, 270, 0, 0)
        self.balloontowerStar.flattenStrong()

        self.barrierCircle = loader.loadModel('phase_4/models/events/barrier_circle_sf.bam')
        self.barrierCircle.reparentTo(render)
        self.barrierCircle.setPosHpr(-14.67, 51.93, 0.025, 287.10, 0, 0)
        self.barrierCircle.flattenStrong()

        #self.tent3 = Actor(loader.loadModel('phase_4/models/events/tele_anim02_repaired.bam'))
        #self.tent3.reparentTo(render)
        #self.tent3.setPosHpr(0, 0, 0, 0, 0, 0)
        #CHAN TRY AND FIGURE THIS BULL SHIT OUT! IT'S A SINGLE BAM FILE WITH AN ANIMATION AND A MODEL. IT DOESN'T LOAD THE ANIMATION IN GAME! ;-;

    def delete(self):
        if self.tent2 is not None:
            self.tent2.removeNode()
            self.tent2 = None

        if self.blueFlag is not None:
            self.blueFlag.cleanup()
            self.blueFlag = None

        if self.redFlag is not None:
            self.redFlag.cleanup()
            self.redFlag = None

        if self.balloonArchway is not None:
            self.balloonArchway.removeNode()
            self.balloonArchway = None

        if self.balloonArchway2 is not None:
            self.balloonArchway2.removeNode()
            self.balloonArchway2 = None

        if self.balloonArchway3 is not None:
            self.balloonArchway3.removeNode()
            self.balloonArchway3 = None

        if self.barrierCircle is not None:
             self.barrierCircle.removeNode()
             self.barrierCircle = None

        if self.balloontowerCake is not None:
            self.balloontowerCake.removeNode()
            self.balloontowerCake = None

        if self.balloontowerStar is not None:
             self.balloontowerStar.removeNode()
             self.balloontowerStar = None

        if self.tent is not None:
            self.tent.removeNode()
            self.tent = None

        DistributedObject.delete(self)
Beispiel #48
0
class BaseAttack(Precacheable, BaseAttackShared):
    notify = directNotify.newCategory("BaseAttack")

    ModelPath = None
    ModelAnimPath = None
    ModelScale = 1
    ModelAngles = Vec3(0, 0, 0)
    ModelOrigin = Point3(0, 0, 0)
    AttackType = ATTACKTYPE_NONE
    Hold = ATTACK_HOLD_NONE

    ModelVMOrigin = Point3(0, 0, 0)
    ModelVMAngles = Point3(0, 0, 0)
    ModelVMScale = 1
    ModelVMAnimate = True

    SpecialVM = False
    SpecialVMCull = True
    SpecialVMActor = None
    SpecialVMFov = 54.0
    SpecialVMOrigin = Point3(0)
    SpecialVMAngles = Vec3(0)
    SpecialVMScale = 1

    def __init__(self, sharedMetadata=None):
        BaseAttackShared.__init__(self, sharedMetadata)
        self.model = None
        self.specialViewModel = None
        self.crosshair = CrosshairData()
        self.animTrack = None

    def hasSpecialViewModel(self):
        return self.SpecialVM and (self.specialViewModel
                                   is not None) and self.isFirstPerson()

    def unloadViewModel(self):
        if self.specialViewModel:
            self.specialViewModel.cleanup()
        self.specialViewModel = None

    def loadViewModel(self):
        self.unloadViewModel()

        if self.SpecialVM and self.SpecialVMActor:
            modelName, anims = self.SpecialVMActor
            self.specialViewModel = Actor(modelName, anims)
            self.specialViewModel.setPos(self.SpecialVMOrigin)
            self.specialViewModel.setHpr(self.SpecialVMAngles)
            self.specialViewModel.setScale(self.SpecialVMScale)
            self.specialViewModel.setBlend(
                frameBlend=base.config.GetBool('interpolate-frames', False))
            if not self.SpecialVMCull:
                self.specialViewModel.node().setBounds(OmniBoundingVolume())
                self.specialViewModel.node().setFinal(1)

    def doDrawNoHold(self,
                     drawAnim,
                     drawAnimStart=None,
                     drawAnimEnd=None,
                     drawAnimSpeed=1.0):

        self.setAnimTrack(Sequence(
            Func(self.avatar.setForcedTorsoAnim, drawAnim),
            self.getAnimationTrack(drawAnim, drawAnimStart, drawAnimEnd,
                                   drawAnimSpeed)),
                          startNow=True)

    def doHold(self, anim, bobStart, bobEnd, bobSpeed):
        self.setAnimTrack(self.getBobSequence(anim, bobStart, bobEnd,
                                              bobSpeed),
                          startNow=True,
                          looping=True)

    def doDrawAndHold(self,
                      drawAnim,
                      drawAnimStart=None,
                      drawAnimEnd=None,
                      drawAnimSpeed=1.0,
                      bobStart=None,
                      bobEnd=None,
                      bobSpeed=1.0,
                      holdCallback=None):
        def __doHold():
            if holdCallback:
                holdCallback()
            self.doHold(drawAnim, bobStart, bobEnd, bobSpeed)

        self.setAnimTrack(Sequence(
            Func(self.avatar.setForcedTorsoAnim, drawAnim),
            self.getAnimationTrack(drawAnim, drawAnimStart, drawAnimEnd,
                                   drawAnimSpeed), Func(__doHold)),
                          startNow=True)

    # This should be called to change the 'animTrack' variable.
    def setAnimTrack(self, track, startNow=False, looping=False):
        """ Sets the animation track for this gag. """
        if track is None:
            # If we try to set the animation track to None, we should
            # just call clearAnimTrack.
            self.clearAnimTrack()
            return

        # Stop the one that was playing before.
        self.clearAnimTrack()

        self.animTrack = track

        if startNow:
            if looping:
                self.animTrack.loop()
            else:
                self.animTrack.start()

    # This should be called whenever we want to clear the 'animTrack' variable.
    def clearAnimTrack(self):
        if self.animTrack is not None:
            self.animTrack.pause()
            self.animTrack = None

    def playAnimThatShouldBePlaying(self):
        if self.avatar and hasattr(self.avatar, 'playingAnim'):
            self.avatar.loop(self.avatar.playingAnim)

    def getAnimationTrack(self,
                          animName,
                          startFrame=None,
                          endFrame=None,
                          playRate=1.0,
                          startTime=None,
                          endTime=None,
                          fullBody=False):
        seq = Parallel()

        def __animTrack(partName):
            return ActorInterval(self.avatar,
                                 animName,
                                 startFrame=startFrame,
                                 endFrame=endFrame,
                                 partName=partName,
                                 playRate=playRate,
                                 startTime=startTime,
                                 endTime=endTime)

        if not fullBody:
            uppers = self.avatar.getUpperBodySubpart()
            for part in uppers:
                seq.append(__animTrack(part))
        else:
            seq.append(__animTrack(None))

        return seq

    def getBobSequence(self, animName, startFrame, endFrame, playRate):
        def __animTrack_bobUp(partName):
            return ActorInterval(self.avatar,
                                 animName,
                                 startFrame=startFrame,
                                 endFrame=endFrame,
                                 partName=partName,
                                 playRate=playRate)

        def __animTrack_bobDown(partName):
            return ActorInterval(self.avatar,
                                 animName,
                                 startFrame=endFrame,
                                 endFrame=startFrame,
                                 partName=partName,
                                 playRate=playRate)

        uppers = self.avatar.getUpperBodySubpart()

        seq = Sequence()

        bobUp = Parallel()
        for part in uppers:
            bobUp.append(__animTrack_bobUp(part))

        bobDown = Parallel()
        for part in uppers:
            bobDown.append(__animTrack_bobDown(part))

        seq.append(bobUp)
        seq.append(bobDown)

        return seq

    def getCrosshair(self):
        return self.crosshair

    # ===========================================
    # These functions are to be overridden by child classes
    # to add any arbitrary data when we send these fire
    # events to the server.

    def addPrimaryPressData(self, dg):
        pass

    def addPrimaryReleaseData(self, dg):
        pass

    def addSecondaryPressData(self, dg):
        pass

    def addSecondaryReleaseData(self, dg):
        pass

    def addReloadPressData(self, dg):
        pass

    def addReloadReleaseData(self, dg):
        pass

    # ===========================================

    def primaryFirePress(self, data=None):
        dg = PyDatagram()
        self.addPrimaryPressData(dg)
        self.avatar.sendUpdate('primaryFirePress', [dg.getMessage()])

    def primaryFireRelease(self, data=None):
        dg = PyDatagram()
        self.addPrimaryReleaseData(dg)
        self.avatar.sendUpdate('primaryFireRelease', [dg.getMessage()])

    def secondaryFirePress(self, data=None):
        dg = PyDatagram()
        self.addSecondaryPressData(dg)
        self.avatar.sendUpdate('secondaryFirePress', [dg.getMessage()])

    def secondaryFireRelease(self, data=None):
        dg = PyDatagram()
        self.addSecondaryReleaseData(dg)
        self.avatar.sendUpdate('secondaryFireRelease', [dg.getMessage()])

    def reloadPress(self, data=None):
        dg = PyDatagram()
        self.addReloadPressData(dg)
        self.avatar.sendUpdate('reloadPress', [dg.getMessage()])

    def reloadRelease(self, data=None):
        dg = PyDatagram()
        self.addReloadReleaseData(dg)
        self.avatar.sendUpdate('reloadRelease', [dg.getMessage()])

    @classmethod
    def doPrecache(cls):
        print("BaseAttack(%s).doPrecache()" % cls.ModelPath)
        if cls.ModelAnimPath:
            precacheActor([
                cls.ModelPath, {
                    'chan': cls.ModelAnimPath,
                    'zero': cls.ModelPath
                }
            ])
        elif cls.ModelPath:
            precacheModel(cls.ModelPath)

        if cls.SpecialVM and cls.SpecialVMActor:
            precacheActor(cls.SpecialVMActor)

    def getName(self):
        return self.Name

    def isLocal(self):
        return self.avatar == base.localAvatar

    def isFirstPerson(self):
        return self.isLocal() and base.localAvatar.isFirstPerson()

    def getViewModel(self):
        return base.localAvatar.getViewModel()

    def getFPSCam(self):
        return base.localAvatar.getFPSCam()

    def getVMGag(self):
        return base.localAvatar.getFPSCam().vmGag

    def getViewPunch(self):
        """
        Return the angles of the view "punch" that is applied to the camera when this
        attack is used by the local avatar.
        """
        return Vec3.zero()

    def load(self):
        BaseAttackShared.load(self)
        if self.isLocal():
            self.loadViewModel()

    def __loadAttackModel(self):
        if self.model:
            self.model.removeNode()
            self.model = None

        if self.ModelPath:
            if self.ModelAnimPath:
                self.model = Actor(self.ModelPath, {
                    'chan': self.ModelAnimPath,
                    'zero': self.ModelPath
                })
            else:
                self.model = loader.loadModel(self.ModelPath)
            self.model.setPos(self.ModelOrigin)
            self.model.setHpr(self.ModelAngles)
            self.model.setScale(self.ModelScale)
            self.model.setName(self.Name + "-model")

        # copy the attack model to first person
        if self.isFirstPerson():

            if self.hasSpecialViewModel():
                self.getFPSCam().swapViewModel(self.specialViewModel,
                                               self.SpecialVMFov)
            elif self.model:
                self.getFPSCam().setVMGag(
                    self.model, self.ModelVMOrigin, self.ModelVMAngles,
                    self.ModelVMScale, self.Hold,
                    self.ModelAnimPath is not None and self.ModelVMAnimate)

            if not self.getViewModel().isEmpty(
            ) and self.action != self.StateOff:
                self.getViewModel().show()

    def __holdAttackModel(self):
        if not self.hasAvatar():
            self.notify.warning(
                "Tried to hold attack model, but no valid avatar.")
            return

        if not CIGlobals.isNodePathOk(self.model):
            return

        if self.Hold == ATTACK_HOLD_LEFT:
            self.model.reparentTo(self.avatar.getLeftHandNode())
        elif self.Hold == ATTACK_HOLD_RIGHT:
            self.model.reparentTo(self.avatar.getRightHandNode())
        else:
            self.model.reparentTo(NodePath())

    def equip(self):
        if not BaseAttackShared.equip(self):
            return False

        if not self.hasAvatar():
            self.notify.warning("Tried to equip attack, but no valid avatar.")
            return False

        self.__loadAttackModel()
        self.__holdAttackModel()

        return True

    def unEquip(self):
        if not BaseAttackShared.unEquip(self):
            return False

        if self.model:
            if isinstance(self.model, Actor):
                self.model.cleanup()
            self.model.removeNode()
            self.model = None
        self.clearAnimTrack()
        if self.hasAvatar():
            self.avatar.clearForcedTorsoAnim()
        if self.isFirstPerson():
            self.getFPSCam().clearVMGag()
            self.getFPSCam().clearVMAnimTrack()
            self.getFPSCam().restoreViewModelFOV()
            if self.hasSpecialViewModel():
                self.getFPSCam().restoreViewModel()
            if not self.getViewModel().isEmpty():
                self.getViewModel().hide()

        return True

    def cleanup(self):
        BaseAttackShared.cleanup(self)
        self.unloadViewModel()
        self.crosshair.cleanup()
        del self.crosshair
        del self.model
Beispiel #49
0
class Bot(object):

    def __init__(self, team, position, direction):
        self._orders = Actions.DoNothing
        self._hp = 5
        self._death_played = False
        self._interval = None
        self.kills = 0

        self.team = team

        self._model = NodePath('bot')
        self._model.reparentTo(render)

        self._model.setPos(position)
        self._model.setHpr(direction, 0, 0)
        self._model.setColorScale(*self.team)
        self._model.setScale(.2, .2, .2)

        # Load the animations
        self._actor = Actor("models/RockGolem", {
            'idle': 'models/RockGolem-idle',
            'walk': 'models/RockGolem-walk',
            'reverse-walk': 'models/RockGolem-walk',
            'punch': 'models/RockGolem-punch',
            'death': 'models/RockGolem-death',
            'throw': 'models/RockGolem-throw',
        })
        self._actor.setPlayRate(2.65, 'walk')
        self._actor.setPlayRate(-2.65, 'reverse-walk')
        self._actor.setPlayRate(4, 'punch')
        self._actor.setPlayRate(5.25, 'throw')
        self._actor.setBlend(frameBlend=True)
        self._actor.reparentTo(self._model)
        self._actor.loop('idle')
        self._actor.setH(180)

        # Floating Label
        text = TextNode('node name')
        text.setText(self.__class__.__name__)
        text.setAlign(TextNode.ACenter)
        self._name_label = self._model.attachNewNode(text)
        self._name_label.setBillboardPointEye()
        self._name_label.setPos(Vec3(0, 0, 6))
        self._name_label.setScale(3, 3, 3)

        # Debug Field of View Cones
        # fov = make_fov()
        # fov.reparentTo(self._model)

    def update(self, tick_number, visible_objects):
        return Actions.DoNothing

    def get_position(self):
        """Return a rounded version of the position vector."""
        p = self._model.getPos()
        return Vec3(round(p.x, 0), round(p.y, 0), round(p.z, 0))

    def get_direction(self):
        """Return a rounded version of the direction vector."""
        v = render.getRelativeVector(self._model, Vec3(0, 1, 0))
        v.normalize()
        return Vec3(round(v.x, 0), round(v.y, 0), round(v.z, 0))

    def get_name(self):
        return self.__class__.__name__

    def _get_orders(self, tick_number, visible_objects):
        # If the health is too low, die.
        if self._hp <= 0:
            self._orders = Actions.Suicide
            return

        # noinspection PyBroadException
        try:
            self._orders = self.update(tick_number, visible_objects)
        except Exception as e:
            print(type(self), e)
            self._orders = None

    def _execute_orders(self, tick_length, battle):
        # Pre-calculate some useful things
        new_pos = self.get_position()
        new_dir = self._model.getHpr()  # TODO: Getting rounding errors here
        velocity = self.get_direction()

        # If we're outside of the arena, take damage
        ARENA_SIZE = 13
        if new_pos.length() > ARENA_SIZE:
            battle.announce("{} fled the battle!".format(self.get_name()))
            self.take_damage(999)

        # Execute the order
        if self._orders == Actions.MoveForward:
            new_pos += velocity
            self.safe_loop('walk')

        elif self._orders == Actions.MoveBackward:
            new_pos -= velocity
            self.safe_loop('reverse-walk')

        elif self._orders == Actions.StrafeLeft:
            v = render.getRelativeVector(self._model, Vec3(-1, 0, 0))
            v.normalize()
            v = Vec3(round(v.x, 0), round(v.y, 0), round(v.z, 0))
            new_pos += v
            self.safe_loop('walk')

        elif self._orders == Actions.StrafeRight:
            v = render.getRelativeVector(self._model, Vec3(1, 0, 0))
            v.normalize()
            v = Vec3(round(v.x, 0), round(v.y, 0), round(v.z, 0))
            new_pos += v
            self.safe_loop('walk')

        elif self._orders == Actions.TurnLeft:
            new_dir.x += 90
            self.safe_loop('walk')

        elif self._orders == Actions.TurnAround:
            new_dir.x += 180
            self.safe_loop('walk')

        elif self._orders == Actions.TurnRight:
            new_dir.x -= 90
            self.safe_loop('walk')

        elif self._orders == Actions.Punch:
            self.punch(battle)

        elif self._orders == Actions.DoNothing:
            self.safe_loop('idle')

        elif self._orders == Actions.Suicide:
            self._hp = 0
            battle.announce("{} killed itself.".format(self.get_name()))
            self.take_damage(999)

        else:  # Bad orders detected! Kill this bot.
            self._hp = 0
            battle.announce("{} made an illegal move and died.".format(self.get_name()))
            self.take_damage(999)

        # Animate the motion
        if self._hp <= 0:
            return
        self._interval = LerpPosHprInterval(
            self._model, tick_length-0.05, new_pos, new_dir)
        self._interval.start()

    def safe_loop(self, animation):
        if self._death_played:
            return
        if self._actor.getCurrentAnim() != animation:
            self._actor.loop(animation)

    def punch(self, battle):
        if not self._death_played:
            self._actor.play('punch')
        hazard = self.get_direction() + self.get_position()
        bot = battle.get_object_at_position(hazard)
        if isinstance(bot, Bot):
            bot.take_damage(5)  # TODO: This is fun as 1
            if bot._hp > 0:
                return
            if bot.team == self.team:
                message = "{self} killed its teammate {target}!"
                self.kills -= 1
            else:
                message = "{self} just pwned {target}!"
                self.kills += 1
            battle.announce(message.format(self=self.get_name(),
                                           target=bot.get_name()),
                            color=self.team,
                            sfx="Ownage" if self.kills == 1 else None)
            if self.kills == 2:
                battle.announce("{} is ON FIRE!".format(self.get_name()),
                                color=(1.0, 0.5, 0.0, 1.0), sfx="DoubleKill")
            elif self.kills == 3:
                battle.announce("{} is UNSTOPPABLE!".format(self.get_name()),
                                color=(1.0, 0.5, 0.0, 1.0), sfx="TripleKill")
            elif self.kills == 4:
                battle.announce("{} is DOMINATING!".format(self.get_name()),
                                color=(1.0, 0.5, 0.0, 1.0), sfx="Dominating")
            elif self.kills > 4:
                battle.announce("{} is GODLIKE!".format(self.get_name()),
                                color=(1.0, 0.5, 0.0, 1.0), sfx="Godlike")

    def take_damage(self, amount):
        self._hp -= amount
        if self._hp <= 0:
            self._name_label.hide()
            if self._interval:
                self._interval.pause()
            if not self._death_played:
                self._actor.play('death')
                self._death_played = True

    def delete(self):
        self._model.removeNode()
        self._actor.cleanup()
        self._name_label.removeNode()
class DistributedEagleSuit(DistributedSuit):
    notify = directNotify.newCategory('DistributedEagleSuit')

    def __init__(self, cr):
        DistributedSuit.__init__(self, cr)
        self.eagleCry = base.audio3d.loadSfx(
            'phase_5/audio/sfx/tt_s_ara_cfg_eagleCry.ogg')
        base.audio3d.attachSoundToObject(self.eagleCry, self)
        self.fallWhistle = base.audio3d.loadSfx(
            'phase_5/audio/sfx/incoming_whistleALT.ogg')
        base.audio3d.attachSoundToObject(self.fallWhistle, self)
        self.explode = base.audio3d.loadSfx(
            'phase_3.5/audio/sfx/ENC_cogfall_apart.ogg')
        base.audio3d.attachSoundToObject(self.explode, self)
        self.eventSphereNodePath = None
        self.fallingPropeller = None
        self.fallingPropProjectile = None
        self.mg = None
        self.flySpeed = 0.0
        return

    def enterNeutral(self, ts=0):
        self.show()
        self.timestampAnimTrack = Sequence(Wait(ts),
                                           Func(self.loop, 'flyNeutral'))
        self.timestampAnimTrack.start()

    def makeStateDict(self):
        self.suitFSM.addState(
            State('eagleFly', self.enterEagleFly, self.exitEagleFly))
        self.suitFSM.addState(
            State('eagleFall', self.enterEagleFall, self.exitEagleFall))
        self.stateIndex2suitState = {
            0: self.suitFSM.getStateNamed('off'),
            1: self.suitFSM.getStateNamed('walking'),
            2: self.suitFSM.getStateNamed('flyingDown'),
            3: self.suitFSM.getStateNamed('flyingUp'),
            4: self.suitFSM.getStateNamed('lured'),
            5: self.suitFSM.getStateNamed('eagleFly'),
            6: self.suitFSM.getStateNamed('eagleFall')
        }
        self.suitState2stateIndex = {}
        for stateId, state in self.stateIndex2suitState.items():
            self.suitState2stateIndex[state.getName()] = stateId

    def setFlySpeed(self, value):
        self.flySpeed = value

    def getFlySpeed(self):
        return self.flySpeed

    def enterEagleFly(self, startIndex, endIndex, ts=0.0):
        durationFactor = self.getFlySpeed()
        if startIndex > -1:
            startPos = EGG.EAGLE_FLY_POINTS[startIndex]
        else:
            startPos = self.getPos(render)
        endPos = EGG.EAGLE_FLY_POINTS[endIndex]
        if self.moveIval:
            self.moveIval.pause()
            self.moveIval = None
        self.moveIval = NPCWalkInterval(self,
                                        endPos,
                                        durationFactor=durationFactor,
                                        startPos=startPos,
                                        fluid=1)
        self.moveIval.start(ts)
        return

    def exitEagleFly(self):
        if self.moveIval:
            self.moveIval.pause()
            self.moveIval = None
        return

    def enterEagleFall(self, startIndex, endIndex, ts=0.0):
        self.moveIval = LerpPosInterval(self,
                                        duration=4.0,
                                        pos=self.getPos(render) - (0, 0, 75),
                                        startPos=self.getPos(render),
                                        blendType='easeIn')
        self.moveIval.start(ts)

    def exitEagleFall(self):
        if self.moveIval:
            self.moveIval.finish()
            self.moveIval = None
        return

    def fallAndExplode(self):
        self.cleanupPropeller()
        self.fallingPropeller = Actor(
            'phase_4/models/props/propeller-mod.bam',
            {'chan': 'phase_4/models/props/propeller-chan.bam'})
        self.fallingPropeller.reparentTo(render)
        self.fallingPropeller.loop('chan', fromFrame=0, toFrame=3)
        parentNode = self.attachNewNode('fallingPropParentNode')
        h = random.randint(0, 359)
        parentNode.setH(h)
        dummyNode = parentNode.attachNewNode('dummyNode')
        dummyNode.setPos(0, 10, -50)
        self.fallingPropProjectile = FlightProjectileInterval(
            self.fallingPropeller,
            startPos=self.find('**/joint_head').getPos(render),
            endPos=dummyNode.getPos(render),
            duration=5.0,
            gravityMult=0.25)
        self.fallingPropProjectile.start()
        dummyNode.removeNode()
        del dummyNode
        parentNode.removeNode()
        del parentNode
        self.updateHealthBar(0)
        self.ignoreHit()
        base.playSfx(self.fallWhistle, node=self)
        taskMgr.doMethodLater(4.0, self.doExplodeSound,
                              self.uniqueName('DEagleSuit-doExplodeSound'))

    def doExplodeSound(self, task):
        base.playSfx(self.explode, node=self)
        return Task.done

    def __initializeEventSphere(self):
        sphere = CollisionSphere(0, 0, 0, 2)
        sphere.setTangible(0)
        node = CollisionNode(self.uniqueName('DEagleSuit-eventSphere'))
        node.addSolid(sphere)
        node.setCollideMask(CIGlobals.WallBitmask)
        np = self.attachNewNode(node)
        np.setSz(2.5)
        np.setZ(5.5)
        self.eventSphereNodePath = np

    def removeEventSphere(self):
        if self.eventSphereNodePath:
            self.eventSphereNodePath.removeNode()
            self.eventSphereNodePath = None
        return

    def acceptHit(self):
        self.acceptOnce('enter' + self.eventSphereNodePath.node().getName(),
                        self.__handleHit)

    def ignoreHit(self):
        self.ignore('enter' + self.eventSphereNodePath.node().getName())

    def __handleHit(self, entry):
        messenger.send(EGG.EAGLE_HIT_EVENT, [self.doId])

    def setSuit(self, arg, variant):
        DistributedSuit.setSuit(self, arg, 3)
        self.deleteShadow()
        self.disableBodyCollisions()
        self.disableRay()
        self.__initializeEventSphere()
        self.show()
        self.setAnimState('flyNeutral')

    def __doEagleCry(self, task):
        base.playSfx(self.eagleCry, node=self)
        task.delayTime = random.uniform(3, 30)
        return Task.again

    def announceGenerate(self):
        DistributedSuit.announceGenerate(self)
        taskMgr.doMethodLater(random.uniform(5, 25), self.__doEagleCry,
                              self.uniqueName('DEagleSuit-doEagleCry'))
        self.acceptHit()

    def disable(self):
        self.ignoreHit()
        self.removeEventSphere()
        taskMgr.remove(self.uniqueName('DEagleSuit-doExplodeSound'))
        taskMgr.remove(self.uniqueName('DEagleSuit-doEagleCry'))
        if self.fallingPropProjectile:
            self.fallingPropProjectile.finish()
            self.fallingPropProjectile = None
        if self.fallingPropeller:
            self.fallingPropeller.cleanup()
            self.fallingPropeller = None
        base.audio3d.detachSound(self.fallWhistle)
        del self.fallWhistle
        base.audio3d.detachSound(self.explode)
        del self.explode
        base.audio3d.detachSound(self.eagleCry)
        del self.eagleCry
        self.mg = None
        DistributedSuit.disable(self)
        return
Beispiel #51
0
class Monster():
    def __init__(self, setup_data, common, start_pos=(0, 0, 0)):
        level = common[
            'max_level'] + 1  # max_level is the current level starting from 0
        common['monsterList'].append(self)
        id = len(common['monsterList']) - 1
        self.monsterList = common['monsterList']
        self.waypoints_data = common['waypoints_data']
        self.waypoints = common['waypoints']
        self.audio3d = common['audio3d']
        self.common = common

        #root node
        self.node = render.attachNewNode("monster")
        self.sound_node = None
        self.soundset = None

        self.actor = Actor(setup_data["model"], setup_data["anim"])
        self.actor.setBlend(frameBlend=True)
        self.actor.reparentTo(self.node)
        self.actor.setScale(setup_data["scale"] * random.uniform(0.9, 1.1))
        self.actor.setH(setup_data["heading"])
        self.actor.setBin("opaque", 10)

        self.rootBone = self.actor.exposeJoint(None, 'modelRoot',
                                               setup_data["root_bone"])

        #sounds
        self.soundID = self.common['soundPool'].get_id()
        self.common['soundPool'].set_target(self.soundID, self.node)
        self.sound_names = {
            "hit": setup_data["hit_sfx"],
            "arrow_hit": setup_data["arrowhit_sfx"],
            "attack": setup_data["attack_sfx"],
            "die": setup_data["die_sfx"]
        }

        self.vfx = setup_data["hit_vfx"]

        self.stats = {
            "speed": setup_data["speed"],
            "hp": setup_data["hp"] * (level**0.15),
            "armor": setup_data["armor"] * (level**0.2),
            "dmg": setup_data["dmg"] * (level**0.8)
        }
        if self.stats['hp'] > 500:
            self.stats['hp'] = 500
        self.maxHP = self.stats['hp']
        self.healthBar = DirectFrame(frameSize=(-0.05, 0.05, 0, 0.05),
                                     frameColor=(1, 0, 0, 1),
                                     frameTexture='icon/glass4.png',
                                     parent=self.node)
        self.healthBar.setTransparency(TransparencyAttrib.MDual)
        self.healthBar.setScale(10, 1, 1)
        self.healthBar.setZ(2)
        self.healthBar.setBillboardPointEye(
        )  #Make it flat in front of the camera
        self.ambientLight = AmbientLight('ambientLight')
        self.ambientLight.setColor(VBase4(.3, .3, .3, 1))
        self.ambientLightNode = render.attachNewNode(self.ambientLight)
        self.healthBar.setLight(self.ambientLightNode)
        self.healthBar.hide()
        wp = base.win.getProperties()
        winX = wp.getXSize()
        winY = wp.getYSize()

        #self.HPring.setColorScale(0.0, 1.0, 0.0, 1.0)

        #gamestate variables
        self.attack_pattern = setup_data["attack_pattern"]
        self.damage = setup_data["dmg"]
        #self.HP=setup_data["hp"]
        self.state = "STOP"
        self.id = id
        self.nextWaypoint = None
        self.canSeePC = False
        self.PCisInRange = False
        self.PC = common['PC']
        self.speed_mode = random.randrange(0 + int(level), 42 + int(level),
                                           7) / 100.0
        self.totalSpeed = self.stats['speed'] + self.speed_mode
        self.sparkSum = 0
        self.lastMagmaDmg = 0
        self.DOT = 0
        self.arrows = set()
        self.isSolid = True
        self.traverser = CollisionTraverser("Trav" + str(self.id))
        #self.traverser.showCollisions(render)
        self.queue = CollisionHandlerQueue()

        #bit masks:
        # 1  visibility polygons & coll-rays
        # 2  walls & radar-ray
        # 3  spheres

        #collision ray for testing visibility polygons
        coll = self.node.attachNewNode(CollisionNode('collRay'))
        coll.node().addSolid(CollisionRay(0, 0, 2, 0, 0, -180))
        coll.setTag("id", str(id))
        coll.node().setIntoCollideMask(BitMask32.allOff())
        coll.node().setFromCollideMask(BitMask32.bit(1))
        self.traverser.addCollider(coll, self.queue)

        #radar collision ray
        self.radar = self.node.attachNewNode(CollisionNode('radarRay'))
        self.radar.node().addSolid(CollisionRay(0, 0, 1, 0, 90, 0))
        self.radar.node().setIntoCollideMask(BitMask32.allOff())
        self.radar.node().setFromCollideMask(BitMask32.bit(2))
        self.radar.setTag("radar", str(id))
        #self.radar.show()
        self.traverser.addCollider(self.radar, self.queue)

        #collision sphere
        self.coll_sphere = self.node.attachNewNode(
            CollisionNode('monsterSphere'))
        self.coll_sphere.node().addSolid(CollisionSphere(0, 0, 0.8, 0.6))
        self.coll_sphere.setTag("id", str(id))
        self.coll_sphere.node().setIntoCollideMask(BitMask32.bit(3))
        #self.coll_sphere.show()

        #other monster blocking
        self.coll_quad = loader.loadModel("models/plane")
        self.coll_quad.reparentTo(self.node)

        #self.coll_quad=render.attachNewNode(CollisionNode('monsterSphere'))
        #self.coll_quad.node().addSolid(CollisionPolygon(Point3(-.5, -.5, 2), Point3(-.5, .5, 0), Point3(.5, .5, 0), Point3(.5, .5, 2)))
        #self.coll_quad.setTag("id", str(id))
        #self.coll_quad.node().setIntoCollideMask(BitMask32.bit(2))
        #self.coll_quad.reparentTo(self.node)
        #self.coll_quad.show()

        Sequence(Wait(random.uniform(.6, .8)), Func(self.restart)).start()
        self.node.setPos(render, start_pos)
        taskMgr.add(self.runAI, "AIfor" + str(self.id))
        taskMgr.doMethodLater(.6, self.runCollisions, 'collFor' + str(self.id))
        taskMgr.doMethodLater(1.0, self.damageOverTime,
                              'DOTfor' + str(self.id))

    def die(self, soundname):
        n = random.random()
        if n < self.common["random-objects-freq"]:
            id = len(self.common["random-objects"])
            object = RandomObject(id, self.common, self.node, render)
            self.common["random-objects"].append(object)
        self.actor.play("die")
        #self.common['soundPool'].play(self.soundID, self.sound_names["hit"])
        self.common['soundPool'].play(self.soundID, soundname)
        self.state = "DIE"

    def damageOverTime(self, task):
        if self.state == "DIE":
            return task.done
        if self.DOT > 0:
            self.doDamage(self.DOT)
            self.DOT = int((self.DOT * 0.9) - 1.0)
            if self.stats['hp'] < 1:
                self.die(self.sound_names["die"])
            vfx(self.node,
                texture=self.vfx,
                scale=.5,
                Z=1.0,
                depthTest=True,
                depthWrite=True).start(0.016, 24)
        return task.again

    def restart(self):
        self.state = "SEEK"

    def check_stacking(self):
        for monster in self.monsterList:
            if monster and monster.id != self.id:
                if self.node.getDistance(monster.node) < .8:
                    if monster.state != "STOP" and self.state == "SEEK":
                        if self.totalSpeed <= monster.totalSpeed:
                            self.state = "STOP"
                            self.actor.stop()
                            Sequence(Wait(1.5), Func(self.restart)).start()
                            return True

    def hideHealthbarTask(self, task):
        self.healthBar.hide()

    def doDamage(self, damage, ignoreArmor=False):
        if self.state == "DIE":
            return
        if not ignoreArmor:
            damage -= self.stats['armor']
        if damage < 1:
            damage = 1
        #print damage
        self.stats['hp'] -= damage
        self.healthBar.show()
        self.healthBar.setScale(10 * self.stats['hp'] / self.maxHP, 1, 1)
        taskMgr.doMethodLater(7.0, self.hideHealthbarTask, 'hideHealthbar')
        if self.stats['hp'] < 1:
            self.healthBar.hide()

    def attack(self, pattern):
        if self.state == "DIE":
            return
        if not self.PC.node:
            return
        if pattern:
            next = pattern.pop()
        else:
            self.state = "SEEK"
            self.PCisInRange = False
            return
        if self.PC.node and self.node:
            range = self.node.getDistance(self.PC.node)
        else:
            return
        #print range
        if range < 1.8:
            self.PC.hit(self.damage)
        Sequence(Wait(next), Func(self.attack, pattern)).start()

    def onHit(self, damage, sound="hit", weapon=None):
        if self.state == "DIE":
            return

        if weapon == "magma":
            damage = self.lastMagmaDmg
            self.common['soundPool'].play(self.soundID, "onFire")
            vfx(self.node,
                texture="vfx/small_flame.png",
                scale=.6,
                Z=.7,
                depthTest=False,
                depthWrite=False).start(0.016, stopAtFrame=24)
        elif weapon == "spark":
            self.common['soundPool'].play(self.soundID, "spark")
            short_vfx(self.node,
                      texture="vfx/short_spark.png",
                      scale=.5,
                      Z=1.0,
                      depthTest=True,
                      depthWrite=True).start(0.03)
        else:
            vfx(self.node,
                texture=self.vfx,
                scale=.5,
                Z=1.0,
                depthTest=True,
                depthWrite=True).start(0.016)

        self.doDamage(damage)

        if self.stats['hp'] < 1:
            if sound:
                self.common['soundPool'].play(self.soundID,
                                              self.sound_names[sound])
            self.die(self.sound_names["die"])
        else:
            if sound:
                self.common['soundPool'].play(self.soundID,
                                              self.sound_names[sound])

    def findFirstWaypoint(self):
        min = 100000
        nearest = None
        for waypoint in self.waypoints:
            dist = self.node.getDistance(waypoint)
            if dist < min:
                min = dist
                nearest = waypoint
        return nearest

    def runCollisions(self, task):
        if self.state == "DIE":
            return task.done
        if self.node.getDistance(self.PC.node) > 50.0:
            self.nextWaypoint = None
            return task.again
        if self.check_stacking():
            return task.again
        self.radar.lookAt(self.PC.node)
        valid_waypoints = []
        isFirstTest = True
        self.canSeePC = False
        self.traverser.traverse(render)
        self.queue.sortEntries()
        for entry in self.queue.getEntries():
            if entry.getFromNodePath().hasTag(
                    "id"):  #it's the monsters collRay
                valid_waypoints.append(
                    int(entry.getIntoNodePath().getTag(
                        "index")))  #visibility polygons
            elif entry.getFromNodePath().hasTag("radar"):  #it's the radar-ray
                #print "radar hit", entry.getIntoNodePath()
                if isFirstTest:
                    isFirstTest = False
                    #print "first hit!"
                    #print "radar hit", entry.getIntoNodePath()
                    if entry.getIntoNodePath().hasTag("player"):
                        self.canSeePC = True
        '''distance={}
        for target in self.PC.myWaypoints:
            for waypoint in valid_waypoints:
                distance[target]=self.waypoints_data[target][waypoint]
                print(target, distance[target])
        if distance:
            self.nextWaypoint=self.waypoints[min(distance, key=distance.get)]
        #print self.canSeePC'''
        if not valid_waypoints:
            #self.nextWaypoint=self.findFirstWaypoint()
            print(self.id, ": I'm lost!")
            valid_waypoints = [self.findFirstWaypoint()]
            #return task.again
        if self.state == "STOP":
            self.nextWaypoint = self.waypoints[random.choice(valid_waypoints)]
            return task.again
        best_distance = 9000000
        target_node = None
        for target in self.PC.myWaypoints:
            for valid in valid_waypoints:
                distance = self.waypoints_data[target][valid]
                #print "target->valid=",target, valid, distance
                if distance < best_distance:
                    best_distance = distance
                    target_node = valid
        if target_node:
            self.nextWaypoint = self.waypoints[target_node]
        else:
            #print "no target", valid_waypoints
            self.nextWaypoint = self.findFirstWaypoint()
            #self.waypoints[random.choice(valid_waypoints)]
            #print self.nextWaypoint
        return task.again

    def runAI(self, task):
        #print self.state
        if self.state == "DIE":
            self.coll_sphere.node().setIntoCollideMask(BitMask32.allOff())
            self.coll_quad.removeNode()
            #self.actor.play("die")
            self.common["kills"] -= 1
            if self.common["kills"] == 0:
                Interactive(self.common, data.items['key'],
                            self.node.getPos(render))
            Sequence(
                Wait(2.0),
                LerpPosInterval(
                    self.node, 2.0,
                    VBase3(self.node.getX(), self.node.getY(),
                           self.node.getZ() - 5)), Func(self.destroy)).start()
            return task.done
        elif self.state == "STOP":
            target = self.nextWaypoint
            if not target:
                return task.again
            self.node.headsUp(target)
            if self.node.getDistance(target) > 0.3:
                self.node.setY(self.node,
                               self.totalSpeed * globalClock.getDt())
                if (self.actor.getCurrentAnim() != "walk"):
                    self.actor.loop("walk")
            return task.again
        elif self.state == "ATTACK":
            self.node.headsUp(self.PC.node)
            if (self.actor.getCurrentAnim() != "attack"):
                self.actor.play("attack")
                #Sequence(Wait(self.attack_pattern[-1]+self.speed_mode), Func(self.attack, list(self.attack_pattern))).start()
                Sequence(Wait(self.attack_pattern[-1]),
                         Func(self.attack, list(self.attack_pattern))).start()
            return task.again
        elif self.state == "SEEK":
            if self.PCisInRange:
                self.state = "ATTACK"
                return task.again
            target = self.nextWaypoint
            if self.canSeePC and self.PC.HP > 0:
                target = self.PC.node
                #print "target pc!"
            if not target:
                return task.again
            self.node.headsUp(target)
            if self.node.getDistance(target) > 0.3:
                self.node.setY(self.node,
                               self.totalSpeed * globalClock.getDt())
                if (self.actor.getCurrentAnim() != "walk"):
                    self.actor.loop("walk")
                return task.again
            else:
                #print "I'm stuck?"
                #print target
                #print self.canSeePC
                self.nextWaypoint = self.PC.node
                return task.again

    def destroy(self):
        #for sound in self.soundset:
        #    self.soundset[sound].stop()
        #print  "destroy:",
        #self.sound_node.reparentTo(render)
        #self.common['soundPool'].append([self.sound_node,self.soundset])
        self.common['soundPool'].set_free(self.soundID)
        #self.sounds=None
        #print  " sounds",
        self.arrows = None
        if self.actor:
            self.actor.cleanup()
            self.actor.removeNode()
            #print  " actor",
        if taskMgr.hasTaskNamed("hideHealthbar"):
            taskMgr.remove("hideHealthbar")
        if taskMgr.hasTaskNamed("AIfor" + str(self.id)):
            taskMgr.remove("AIfor" + str(self.id))
            #print  " AI",
        if taskMgr.hasTaskNamed('collFor' + str(self.id)):
            taskMgr.remove('collFor' + str(self.id))
            #print  " collision",
        if taskMgr.hasTaskNamed('DOTfor' + str(self.id)):
            taskMgr.remove('DOTfor' + str(self.id))
        if self.node:
            self.node.removeNode()
            #print  " node",
        self.monsterList[self.id] = None
        self.traverser = None
        self.queue = None
        self.healthBar.removeNode()
        self.ambientLightNode.removeNode()
Beispiel #52
0
class Toon:
    notify = DirectNotifyGlobal.directNotify.newCategory("Toon")
    def __init__(self):
        self.name = "Flippy"

        legsAnimDict = {'right-hand-start': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_right-hand-start.bam', 'firehose': 'phase_5/models/char/tt_a_chr_dgs_shorts_legs_firehose.bam', 'rotateL-putt': 'phase_6/models/char/tt_a_chr_dgs_shorts_legs_rotateL-putt.bam', 'slip-forward': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_slip-forward.bam', 'catch-eatnrun': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_eatnrun.bam', 'tickle': 'phase_5/models/char/tt_a_chr_dgs_shorts_legs_tickle.bam', 'water-gun': 'phase_5/models/char/tt_a_chr_dgs_shorts_legs_water-gun.bam', 'leverNeutral': 'phase_10/models/char/tt_a_chr_dgs_shorts_legs_leverNeutral.bam', 'swim': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_swim.bam', 'catch-run': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_gamerun.bam', 'sad-neutral': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_sad-neutral.bam', 'pet-loop': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_petloop.bam', 'jump-squat': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_jump-zstart.bam', 'wave': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_wave.bam', 'reel-neutral': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_reelneutral.bam', 'pole-neutral': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_poleneutral.bam', 'bank': 'phase_5.5/models/char/tt_a_chr_dgs_shorts_legs_jellybeanJar.bam', 'scientistGame': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_scientistGame.bam', 'right-hand': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_right-hand.bam', 'lookloop-putt': 'phase_6/models/char/tt_a_chr_dgs_shorts_legs_lookloop-putt.bam', 'victory': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_victory-dance.bam', 'lose': 'phase_5/models/char/tt_a_chr_dgs_shorts_legs_lose.bam', 'cringe': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_cringe.bam', 'right': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_right.bam', 'headdown-putt': 'phase_6/models/char/tt_a_chr_dgs_shorts_legs_headdown-putt.bam', 'conked': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_conked.bam', 'jump': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_jump.bam', 'into-putt': 'phase_6/models/char/tt_a_chr_dgs_shorts_legs_into-putt.bam', 'fish-end': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_fishEND.bam', 'running-jump-land': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_leap_zend.bam', 'shrug': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_shrug.bam', 'sprinkle-dust': 'phase_5/models/char/tt_a_chr_dgs_shorts_legs_sprinkle-dust.bam', 'hold-bottle': 'phase_5/models/char/tt_a_chr_dgs_shorts_legs_hold-bottle.bam', 'takePhone': 'phase_5.5/models/char/tt_a_chr_dgs_shorts_legs_takePhone.bam', 'melt': 'phase_5/models/char/tt_a_chr_dgs_shorts_legs_melt.bam', 'pet-start': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_petin.bam', 'look-putt': 'phase_6/models/char/tt_a_chr_dgs_shorts_legs_look-putt.bam', 'loop-putt': 'phase_6/models/char/tt_a_chr_dgs_shorts_legs_loop-putt.bam', 'good-putt': 'phase_6/models/char/tt_a_chr_dgs_shorts_legs_good-putt.bam', 'juggle': 'phase_5/models/char/tt_a_chr_dgs_shorts_legs_juggle.bam', 'run': 'phase_3/models/char/tt_a_chr_dgs_shorts_legs_run.bam', 'pushbutton': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_press-button.bam', 'sidestep-right': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_jump-back-right.bam', 'water': 'phase_5.5/models/char/tt_a_chr_dgs_shorts_legs_water.bam', 'right-point-start': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_right-point-start.bam', 'bad-putt': 'phase_6/models/char/tt_a_chr_dgs_shorts_legs_bad-putt.bam', 'struggle': 'phase_5/models/char/tt_a_chr_dgs_shorts_legs_struggle.bam', 'running-jump': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_running-jump.bam', 'callPet': 'phase_5.5/models/char/tt_a_chr_dgs_shorts_legs_callPet.bam', 'throw': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_pie-throw.bam', 'catch-eatneutral': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_eat_neutral.bam', 'tug-o-war': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_tug-o-war.bam', 'bow': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_bow.bam', 'swing': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_swing.bam', 'climb': 'phase_5/models/char/tt_a_chr_dgs_shorts_legs_climb.bam', 'scientistWork': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_scientistWork.bam', 'think': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_think.bam', 'catch-intro-throw': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_gameThrow.bam', 'walk': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_walk.bam', 'down': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_down.bam', 'pole': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_pole.bam', 'periscope': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_periscope.bam', 'duck': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_duck.bam', 'curtsy': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_curtsy.bam', 'jump-land': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_jump-zend.bam', 'loop-dig': 'phase_5.5/models/char/tt_a_chr_dgs_shorts_legs_loop_dig.bam', 'angry': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_angry.bam', 'bored': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_bored.bam', 'swing-putt': 'phase_6/models/char/tt_a_chr_dgs_shorts_legs_swing-putt.bam', 'pet-end': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_petend.bam', 'spit': 'phase_5/models/char/tt_a_chr_dgs_shorts_legs_spit.bam', 'right-point': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_right-point.bam', 'start-dig': 'phase_5.5/models/char/tt_a_chr_dgs_shorts_legs_into_dig.bam', 'castlong': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_castlong.bam', 'confused': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_confused.bam', 'neutral': 'phase_3/models/char/tt_a_chr_dgs_shorts_legs_neutral.bam', 'jump-idle': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_jump-zhang.bam', 'reel': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_reel.bam', 'slip-backward': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_slip-backward.bam', 'sound': 'phase_5/models/char/tt_a_chr_dgs_shorts_legs_shout.bam', 'sidestep-left': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_sidestep-left.bam', 'up': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_up.bam', 'fish-again': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_fishAGAIN.bam', 'cast': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_cast.bam', 'phoneBack': 'phase_5.5/models/char/tt_a_chr_dgs_shorts_legs_phoneBack.bam', 'phoneNeutral': 'phase_5.5/models/char/tt_a_chr_dgs_shorts_legs_phoneNeutral.bam', 'scientistJealous': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_scientistJealous.bam', 'battlecast': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_fish.bam', 'sit-start': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_intoSit.bam', 'toss': 'phase_5/models/char/tt_a_chr_dgs_shorts_legs_toss.bam', 'happy-dance': 'phase_5/models/char/tt_a_chr_dgs_shorts_legs_happy-dance.bam', 'running-jump-squat': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_leap_zstart.bam', 'teleport': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_teleport.bam', 'sit': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_sit.bam', 'sad-walk': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_losewalk.bam', 'give-props-start': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_give-props-start.bam', 'book': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_book.bam', 'running-jump-idle': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_leap_zhang.bam', 'scientistEmcee': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_scientistEmcee.bam', 'leverPull': 'phase_10/models/char/tt_a_chr_dgs_shorts_legs_leverPull.bam', 'tutorial-neutral': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_tutorial-neutral.bam', 'badloop-putt': 'phase_6/models/char/tt_a_chr_dgs_shorts_legs_badloop-putt.bam', 'give-props': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_give-props.bam', 'hold-magnet': 'phase_5/models/char/tt_a_chr_dgs_shorts_legs_hold-magnet.bam', 'hypnotize': 'phase_5/models/char/tt_a_chr_dgs_shorts_legs_hypnotize.bam', 'left-point': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_left-point.bam', 'leverReach': 'phase_10/models/char/tt_a_chr_dgs_shorts_legs_leverReach.bam', 'feedPet': 'phase_5.5/models/char/tt_a_chr_dgs_shorts_legs_feedPet.bam', 'reel-H': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_reelH.bam', 'applause': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_applause.bam', 'smooch': 'phase_5/models/char/tt_a_chr_dgs_shorts_legs_smooch.bam', 'rotateR-putt': 'phase_6/models/char/tt_a_chr_dgs_shorts_legs_rotateR-putt.bam', 'fish-neutral': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_fishneutral.bam', 'push': 'phase_9/models/char/tt_a_chr_dgs_shorts_legs_push.bam', 'catch-neutral': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_gameneutral.bam', 'left': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_left.bam'}
         
        torsoAnimDict = {'right-hand-start': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_right-hand-start.bam', 'firehose': 'phase_5/models/char/tt_a_chr_dgl_shorts_torso_firehose.bam', 'rotateL-putt': 'phase_6/models/char/tt_a_chr_dgl_shorts_torso_rotateL-putt.bam', 'slip-forward': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_slip-forward.bam', 'catch-eatnrun': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_eatnrun.bam', 'tickle': 'phase_5/models/char/tt_a_chr_dgl_shorts_torso_tickle.bam', 'water-gun': 'phase_5/models/char/tt_a_chr_dgl_shorts_torso_water-gun.bam', 'leverNeutral': 'phase_10/models/char/tt_a_chr_dgl_shorts_torso_leverNeutral.bam', 'swim': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_swim.bam', 'catch-run': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_gamerun.bam', 'sad-neutral': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_sad-neutral.bam', 'pet-loop': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_petloop.bam', 'jump-squat': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_jump-zstart.bam', 'wave': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_wave.bam', 'reel-neutral': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_reelneutral.bam', 'pole-neutral': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_poleneutral.bam', 'bank': 'phase_5.5/models/char/tt_a_chr_dgl_shorts_torso_jellybeanJar.bam', 'scientistGame': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_scientistGame.bam', 'right-hand': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_right-hand.bam', 'lookloop-putt': 'phase_6/models/char/tt_a_chr_dgl_shorts_torso_lookloop-putt.bam', 'victory': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_victory-dance.bam', 'lose': 'phase_5/models/char/tt_a_chr_dgl_shorts_torso_lose.bam', 'cringe': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_cringe.bam', 'right': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_right.bam', 'headdown-putt': 'phase_6/models/char/tt_a_chr_dgl_shorts_torso_headdown-putt.bam', 'conked': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_conked.bam', 'jump': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_jump.bam', 'into-putt': 'phase_6/models/char/tt_a_chr_dgl_shorts_torso_into-putt.bam', 'fish-end': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_fishEND.bam', 'running-jump-land': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_leap_zend.bam', 'shrug': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_shrug.bam', 'sprinkle-dust': 'phase_5/models/char/tt_a_chr_dgl_shorts_torso_sprinkle-dust.bam', 'hold-bottle': 'phase_5/models/char/tt_a_chr_dgl_shorts_torso_hold-bottle.bam', 'takePhone': 'phase_5.5/models/char/tt_a_chr_dgl_shorts_torso_takePhone.bam', 'melt': 'phase_5/models/char/tt_a_chr_dgl_shorts_torso_melt.bam', 'pet-start': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_petin.bam', 'look-putt': 'phase_6/models/char/tt_a_chr_dgl_shorts_torso_look-putt.bam', 'loop-putt': 'phase_6/models/char/tt_a_chr_dgl_shorts_torso_loop-putt.bam', 'good-putt': 'phase_6/models/char/tt_a_chr_dgl_shorts_torso_good-putt.bam', 'juggle': 'phase_5/models/char/tt_a_chr_dgl_shorts_torso_juggle.bam', 'run': 'phase_3/models/char/tt_a_chr_dgl_shorts_torso_run.bam', 'pushbutton': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_press-button.bam', 'sidestep-right': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_jump-back-right.bam', 'water': 'phase_5.5/models/char/tt_a_chr_dgl_shorts_torso_water.bam', 'right-point-start': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_right-point-start.bam', 'bad-putt': 'phase_6/models/char/tt_a_chr_dgl_shorts_torso_bad-putt.bam', 'struggle': 'phase_5/models/char/tt_a_chr_dgl_shorts_torso_struggle.bam', 'running-jump': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_running-jump.bam', 'callPet': 'phase_5.5/models/char/tt_a_chr_dgl_shorts_torso_callPet.bam', 'throw': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_pie-throw.bam', 'catch-eatneutral': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_eat_neutral.bam', 'tug-o-war': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_tug-o-war.bam', 'bow': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_bow.bam', 'swing': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_swing.bam', 'climb': 'phase_5/models/char/tt_a_chr_dgl_shorts_torso_climb.bam', 'scientistWork': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_scientistWork.bam', 'think': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_think.bam', 'catch-intro-throw': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_gameThrow.bam', 'walk': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_walk.bam', 'down': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_down.bam', 'pole': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_pole.bam', 'periscope': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_periscope.bam', 'duck': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_duck.bam', 'curtsy': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_curtsy.bam', 'jump-land': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_jump-zend.bam', 'loop-dig': 'phase_5.5/models/char/tt_a_chr_dgl_shorts_torso_loop_dig.bam', 'angry': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_angry.bam', 'bored': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_bored.bam', 'swing-putt': 'phase_6/models/char/tt_a_chr_dgl_shorts_torso_swing-putt.bam', 'pet-end': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_petend.bam', 'spit': 'phase_5/models/char/tt_a_chr_dgl_shorts_torso_spit.bam', 'right-point': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_right-point.bam', 'start-dig': 'phase_5.5/models/char/tt_a_chr_dgl_shorts_torso_into_dig.bam', 'castlong': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_castlong.bam', 'confused': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_confused.bam', 'neutral': 'phase_3/models/char/tt_a_chr_dgl_shorts_torso_neutral.bam', 'jump-idle': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_jump-zhang.bam', 'reel': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_reel.bam', 'slip-backward': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_slip-backward.bam', 'sound': 'phase_5/models/char/tt_a_chr_dgl_shorts_torso_shout.bam', 'sidestep-left': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_sidestep-left.bam', 'up': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_up.bam', 'fish-again': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_fishAGAIN.bam', 'cast': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_cast.bam', 'phoneBack': 'phase_5.5/models/char/tt_a_chr_dgl_shorts_torso_phoneBack.bam', 'phoneNeutral': 'phase_5.5/models/char/tt_a_chr_dgl_shorts_torso_phoneNeutral.bam', 'scientistJealous': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_scientistJealous.bam', 'battlecast': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_fish.bam', 'sit-start': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_intoSit.bam', 'toss': 'phase_5/models/char/tt_a_chr_dgl_shorts_torso_toss.bam', 'happy-dance': 'phase_5/models/char/tt_a_chr_dgl_shorts_torso_happy-dance.bam', 'running-jump-squat': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_leap_zstart.bam', 'teleport': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_teleport.bam', 'sit': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_sit.bam', 'sad-walk': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_losewalk.bam', 'give-props-start': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_give-props-start.bam', 'book': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_book.bam', 'running-jump-idle': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_leap_zhang.bam', 'scientistEmcee': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_scientistEmcee.bam', 'leverPull': 'phase_10/models/char/tt_a_chr_dgl_shorts_torso_leverPull.bam', 'tutorial-neutral': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_tutorial-neutral.bam', 'badloop-putt': 'phase_6/models/char/tt_a_chr_dgl_shorts_torso_badloop-putt.bam', 'give-props': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_give-props.bam', 'hold-magnet': 'phase_5/models/char/tt_a_chr_dgl_shorts_torso_hold-magnet.bam', 'hypnotize': 'phase_5/models/char/tt_a_chr_dgl_shorts_torso_hypnotize.bam', 'left-point': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_left-point.bam', 'leverReach': 'phase_10/models/char/tt_a_chr_dgl_shorts_torso_leverReach.bam', 'feedPet': 'phase_5.5/models/char/tt_a_chr_dgl_shorts_torso_feedPet.bam', 'reel-H': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_reelH.bam', 'applause': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_applause.bam', 'smooch': 'phase_5/models/char/tt_a_chr_dgl_shorts_torso_smooch.bam', 'rotateR-putt': 'phase_6/models/char/tt_a_chr_dgl_shorts_torso_rotateR-putt.bam', 'fish-neutral': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_fishneutral.bam', 'push': 'phase_9/models/char/tt_a_chr_dgl_shorts_torso_push.bam', 'catch-neutral': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_gameneutral.bam', 'left': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_left.bam'}
         
        self.toonHead = loader.loadModel('phase_3/models/char/horse-heads-1000.bam')
        otherParts = self.toonHead.findAllMatches('**/*long*')
        for partNum in range(0, otherParts.getNumPaths()):
            if not 'muzzle' in str(otherParts.getPath(partNum)):
                otherParts.getPath(partNum).removeNode()
        ntrlMuzzle = self.toonHead.find('**/*muzzle*neutral')
        otherParts = self.toonHead.findAllMatches('**/*muzzle*')
        for partNum in range(0, otherParts.getNumPaths()):
            part = otherParts.getPath(partNum)
            if part != ntrlMuzzle:
                otherParts.getPath(partNum).removeNode()
        self.toonTorso = loader.loadModel('phase_3/models/char/tt_a_chr_dgl_shorts_torso_1000.bam')
        self.toonLegs  = loader.loadModel('phase_3/models/char/tt_a_chr_dgs_shorts_legs_1000.bam')
        otherParts = self.toonLegs.findAllMatches('**/boots*')+self.toonLegs.findAllMatches('**/shoes')
        for partNum in range(0, otherParts.getNumPaths()):
            otherParts.getPath(partNum).removeNode()

        self.toonActor = Actor({'head':self.toonHead, 'torso':self.toonTorso, 'legs':self.toonLegs},
                        {'torso':torsoAnimDict, 'legs':legsAnimDict})
        self.toonActor.setBlend(frameBlend = True)
        self.toonActor.attach('head', 'torso', 'def_head')
        self.toonActor.attach('torso', 'legs', 'joint_hips')

        gloves = self.toonActor.findAllMatches('**/hands')
        ears = self.toonActor.findAllMatches('**/*ears*')
        head = self.toonActor.findAllMatches('**/head-*')
        sleeves = self.toonActor.findAllMatches('**/sleeves')
        shirt = self.toonActor.findAllMatches('**/torso-top')
        shorts = self.toonActor.findAllMatches('**/torso-bot')
        neck = self.toonActor.findAllMatches('**/neck')
        arms = self.toonActor.findAllMatches('**/arms')
        legs = self.toonActor.findAllMatches('**/legs')
        feet = self.toonActor.findAllMatches('**/feet')
 
        self.bodyNodes = []
        self.bodyNodes += [gloves]
        self.bodyNodes += [head, ears]
        self.bodyNodes += [sleeves, shirt, shorts]
        self.bodyNodes += [neck, arms, legs, feet]
        self.bodyNodes[0].setColor(1, 1, 1, 1)
        self.bodyNodes[1].setColor(0.18, 0.54, 0.34, 1)
        self.bodyNodes[2].setColor(0.18, 0.54, 0.34, 1)
        self.bodyNodes[3].setColor(1, 1, 1, 1)
        self.bodyNodes[4].setColor(1, 1, 1, 1)
        self.bodyNodes[5].setColor(1, 1, 1, 1)
        self.bodyNodes[6].setColor(0.18, 0.54, 0.34, 1)
        self.bodyNodes[7].setColor(0.18, 0.54, 0.34, 1)
        self.bodyNodes[8].setColor(0.18, 0.54, 0.34, 1)
        self.bodyNodes[9].setColor(0.18, 0.54, 0.34, 1)

        topTex = loader.loadTexture('phase_4/maps/ContestfishingVestShirt2.jpg')
        botTex = loader.loadTexture('phase_4/maps/CowboyShorts1.jpg')
        sleeveTex = loader.loadTexture('phase_4/maps/ContestfishingVestSleeve1.jpg')

        self.bodyNodes[3].setTexture(sleeveTex, 1)
        self.bodyNodes[4].setTexture(topTex, 1)
        self.bodyNodes[5].setTexture(botTex, 1)
        self.height = 3.2375

        self.runNoise = loader.loadSfx('phase_3.5/audio/sfx/AV_footstep_runloop' + base.sfxExt2)
        self.runNoise.setLoop(True)
        self.walkNoise = loader.loadSfx('phase_3.5/audio/sfx/AV_footstep_walkloop' + base.sfxExt2)
        self.walkNoise.setLoop(True)

        self.loop('neutral')
        self.toonActor.reparentTo(render)


    def loop(self, anim):
        self.runNoise.stop()
        self.walkNoise.stop()
        self.toonActor.loop(anim)
        if anim == 'run':
            self.runNoise.play()
        elif anim == 'walk':
            self.walkNoise.play()

    def remove(self):
        self.toonActor.cleanup()
        self.toonActor.removeNode()
        del self
Beispiel #53
0
class Hobot:
    max_speed = 0.25
    acceleration = 0.5
    deceleration = 0.5

    def __init__(self, anim_root):
        self.move_root = base.render.attach_new_node('hobot')
        self.anim_root = anim_root

        self.model = Actor('hobot/hobot.bam')

        self.hand = self.model.expose_joint(None, 'modelRoot', 'hand')
        head = self.model.expose_joint(None, 'modelRoot', 'head')

        self.model.reparent_to(self.anim_root)
        self.model.set_two_sided(True)
        self.model.find("**/+GeomNode").set_transform(
            self.model.get_joint_transform_state('modelRoot',
                                                 'hobot root').get_inverse())
        self.model.set_z(0.1)
        self.facing = 1.0

        self.move_control = self.model.get_anim_control('move_forward')

        self.speed = 0.0
        self.locked = True

        self.model.wrt_reparent_to(self.move_root)
        self.model.hide()

        light_texture = loader.load_texture('hobot/light_on.png')
        light_texture.set_wrap_u(core.SamplerState.WM_clamp)
        light_texture.set_wrap_v(core.SamplerState.WM_clamp)
        cm = core.CardMaker('card')
        cm.set_frame(-0.15, 0.15, 0.15, 0.45)
        self.lightbulb = head.attach_new_node(cm.generate())
        self.lightbulb.set_texture(light_texture)
        self.lightbulb.set_attrib(
            core.ColorBlendAttrib.make(core.ColorBlendAttrib.M_add,
                                       core.ColorBlendAttrib.O_incoming_alpha,
                                       core.ColorBlendAttrib.O_one))
        self.lightbulb.set_depth_test(False)
        self.lightbulb.set_bin('fixed', 0)
        self.lightbulb.set_p(-90)
        self.lightbulb.set_billboard_point_eye()
        self.lightbulb.set_two_sided(True)
        self.lightbulb.hide()

        shadow_texture = loader.load_texture('hobot/drop_shadow.png')
        shadow_texture.set_wrap_u(core.SamplerState.WM_clamp)
        shadow_texture.set_wrap_v(core.SamplerState.WM_clamp)
        cm = core.CardMaker('card')
        cm.set_frame(-0.35, 0.35, -0.45, -0.1)
        self.shadow = self.model.attach_new_node(cm.generate())
        self.shadow.set_texture(shadow_texture)
        self.shadow.set_attrib(
            core.ColorBlendAttrib.make(
                core.ColorBlendAttrib.M_add, core.ColorBlendAttrib.O_zero,
                core.ColorBlendAttrib.O_one_minus_incoming_alpha))
        self.shadow.set_p(-90)
        self.shadow.set_depth_write(False)
        self.shadow.set_x(0.2)
        self.shadow.set_billboard_point_eye()
        self.shadow.set_two_sided(True)
        self.shadow.set_bin('transparent', 0)
        self.shadow.set_alpha_scale(0)
        self.shadow_fade = None

        self.ding_sfx = loader.load_sfx('hobot/sfx/ding.wav')
        self.ding_sfx.set_volume(0.5)
        self.move_sfx = loader.load_sfx('hobot/sfx/move.wav')
        self.move_sfx.set_loop(True)

        self.action_callback = None

    def destroy(self):
        if self.move_control.playing:
            self.move_control.stop()
            self.move_sfx.stop()

        # RIP hobot :-(
        self.model.cleanup()

    def set_action(self, callback):
        self.action_callback = callback
        if self.lightbulb.is_hidden():
            self.ding_sfx.play()
            self.lightbulb.show()

    def clear_action(self):
        self.action_callback = None
        self.lightbulb.hide()

    def do_action(self):
        if self.action_callback:
            self.action_callback()

    def lock(self):
        #self.model.wrt_reparent_to(self.anim_root)
        self.locked = True
        self.speed = 0.0

    def unlock(self):
        self.model.set_pos(self.anim_root.get_pos())
        self.locked = False
        self.model.set_hpr(0, 0, -90)
        self.model.show()

    def face(self, dir):
        if dir:
            self.facing = 1 if dir > 0 else -1
            self.model.set_sz(self.facing * -self.model.get_sx())

    def process_input(self, input, dt, level):
        if self.locked:
            return

        if input.get_action('interact'):
            self.do_action()

        move_x = input.get_axis('move-horizontal')
        move_y = input.get_axis('move-vertical')

        if move_x:
            self.speed += move_x * self.acceleration * dt
            self.face(move_x)
        elif self.speed > 0:
            self.speed = max(0, self.speed - self.deceleration * dt)
        elif self.speed < 0:
            self.speed = min(0, self.speed + self.deceleration * dt)

        delta = core.Vec2(0, 0)

        if move_y:
            delta.y = move_y * dt * MOVE_Y_SPEED

        if self.speed != 0:
            if self.speed > self.max_speed:
                self.speed = self.max_speed
            elif self.speed < -self.max_speed:
                self.speed = -self.max_speed

            delta.x = self.speed * dt
            pos_changed = True

            self.move_control.set_play_rate(self.speed * self.facing * 4.0)

            if not self.move_control.playing:
                self.move_control.loop(False)
                self.move_sfx.play()

        elif self.move_control.playing:
            self.move_control.stop()
            self.move_sfx.stop()

        if delta.length_squared() > 0:
            old_pos = self.model.get_pos()
            new_pos = level.adjust_move(old_pos.xy, delta)
            self.model.set_pos(core.LPoint3(new_pos, old_pos.z))
Beispiel #54
0
class Boss1():
    def __init__(self, common, pos=(0,0,0)):
        self.common = common
        common['monsterList'].append(self)
        id=len(common['monsterList'])-1
        self.id=id
        self.stats={"speed":9,
            "hp":500,
            "armor":5
            }
        self.totalSpeed=10
        self.sparkSum=0
        self.lastMagmaDmg=0
        self.DOT=0
        self.arrows=set()
        self.isSolid=True
        self.node=render.attachNewNode("monster")
        self.boss=Actor("models/boss1-monster/monster", {"die":"models/boss1-monster/monster-die",
                                            "attack1":"models/boss1-monster/monster-doublepunch",
                                            "hit":"models/boss1-monster/monster-hit",
                                            "idle":"models/boss1-monster/monster-idle",
                                            "attack2":"models/boss1-monster/monster-kick",
                                            "run":"models/boss1-monster/monster-run",
                                            "scream":"models/boss1-monster/monster-scream",
                                            "walk":"models/boss1-monster/monster-walk",
                                            "rwalk":"models/boss1-monster/monster-walk-right",
                                            "lwalk":"models/boss1-monster/monster-walk-left"})
        self.boss.setBlend(frameBlend = True)
        self.boss.setPlayRate(0.8, "walk")
        self.boss.reparentTo(self.node)
        self.boss.setScale(1)
        #self.boss.setH(180.0)
        #self.boss.setBin("opaque", 10)
        #tex = loader.loadTexture('models/boss1-monster/creature1Normal.png')
        #boss1.setTexture(tex, 1)
        #self.boss.setColor(0.2, 0.0, 0.9, 0.5)
        self.node.setPos(render,pos)
        self.rootBone=self.boss.exposeJoint(None, 'modelRoot', 'hips')

        self.maxHP=self.stats['hp']
        self.healthBar=DirectFrame(frameSize=(37, 0, 0, 6),
                                    frameColor=(0, 0, 1, 1),
                                    frameTexture='icon/glass4.png',
                                    parent=pixel2d)
        self.healthBar.setTransparency(TransparencyAttrib.MDual)
        self.healthBar.setScale(10,1, 1)
        #self.healthBar.reparentTo(self.node)
        wp = base.win.getProperties()
        winX = wp.getXSize()
        winY = wp.getYSize()
        self.healthBar.setPos(71-256+winX/2,0,34-winY)
        self.healthBar.hide()

        self.soundID=self.common['soundPool'].get_id()
        self.common['soundPool'].set_target(self.soundID, self.node)

        self.traverser=CollisionTraverser("BossTrav"+str(id))
        #self.traverser.showCollisions(render)
        self.queue = CollisionHandlerQueue()

        #radar collision ray
#        self.radar=self.node.attachNewNode(CollisionNode('radarRay'))
#        self.radar.node().addSolid(CollisionRay(0, 0, 1, 0, 90, 0))
#        self.radar.node().setIntoCollideMask(BitMask32.allOff())
#        self.radar.node().setFromCollideMask(BitMask32.bit(2))
#        self.radar.setTag("radar", str(id))
#        self.radar.show()
#        self.traverser.addCollider(self.radar, self.queue)

        self.coll_body=self.node.attachNewNode(CollisionNode('bossmonsterCollisionNode'))
        self.coll_body.node().addSolid(CollisionCapsule(0, 0, 0.3, 0, 0, 2, 0.6))
        self.coll_body.setTag("id", str(id))
        self.coll_body.node().setIntoCollideMask(BitMask32.bit(3))
        #self.coll_body.show()
        self.left_thumb=self.boss.exposeJoint(None, 'modelRoot', 'L_thumb1')
        #self.right_foot = self.boss.exposeJoint(None, "modelRoot", "R_foot")
        #self.coll_attack2=self.node.attachNewNode(CollisionNode('bossattack2CollisionNode'))
        #self.coll_attack2.node().addSolid(CollisionSphere(0, 0, 0, 0.2))
        ##self.coll_attack2.setTag("id", str(id))
        #self.coll_attack2.node().setIntoCollideMask(BitMask32.bit(3))
        #self.coll_attack2.show()

        #other monster blocking
        self.coll_quad=loader.loadModel("models/plane")
        self.coll_quad.reparentTo(self.node)
        self.state="IDLE"
        self.previous_state=self.state
        #self.PC = self.common['PC']
        #taskMgr.doMethodLater(.6, self.runCollisions,'collFor'+str(self.id))
        taskMgr.doMethodLater(1.0, self.setAI, 'setAITask')
        taskMgr.doMethodLater(1.0, self.damageOverTime,'DOTfor'+str(self.id))
        #taskMgr.add(self.runAI, "BossAIfor"+str(id))

    def setAI(self, task):
        #Creating AI World
        self.AIworld = AIWorld(render)

        self.AIchar = AICharacter("pursuer",self.node, 140, 0.05, 7)
        self.AIworld.addAiChar(self.AIchar)
        self.AIbehaviors = self.AIchar.getAiBehaviors()

        self.AIbehaviors.pursue(self.common['PC'].node)
        # Obstacle avoidance (FIXME)
        #self.AIbehaviors.obstacleAvoidance(0.0001)
        #self.AIworld.addObstacle(self.common['map_walls'])
        #self.AIworld.addObstacle(self.common['map_black'])

        #AI World update
        taskMgr.add(self.runAI,"AIUpdate")
        return task.done

    def runAI(self, task):
        #print(self.stats['hp'])
        #(x,y,z) = self.right_foot.getPos()
        ## Our model is rotated of 180°, thus we need to move the collision sphere to the opposite directions
        #self.coll_attack2.setPos(-1*x, -1*y, z)
        target = self.common['PC'].node
        if self.state=="DIE":
            if(self.boss.getCurrentAnim()!="die"):
                self.common['soundPool'].attachAndPlay(self.boss, "creature_roar_01.ogg")
                self.boss.play("die")
            #Check if we have finished the animation
            if (self.boss.getCurrentFrame() < self.boss.getNumFrames()-1):
                return task.again
            else:
                id = len(self.common["random-objects"])
                object = RandomObject(id, self.common, self.node, render, moneyamount=5)
                self.common["random-objects"].append(object)
                Interactive(self.common, data.items['key'], self.node.getPos(render))
                self.coll_body.node().setIntoCollideMask(BitMask32.allOff())
                self.coll_quad.removeNode()
                Sequence(Wait(2.0),LerpPosInterval(self.node, 2.0, VBase3(self.node.getX(),self.node.getY(),self.node.getZ()-5)),Func(self.destroy)).start()
                return task.done

        if self.stats['hp'] < 50:
            self.AIchar.setMass(self.AIchar.getMass()-20)

        if (self.state == "HIT"):
            rn = 0.005
            if (type(self.common['PC']).__name__ == "Knight"):
                rn = 0.4
            if (random.random() < rn):
                if(self.boss.getCurrentAnim()!="hit"):
                    self.boss.play("hit")
                    self.common['soundPool'].attachAndPlay(self.boss, "creature_roar_01.ogg")
                    self.state = "PLAYINGHIT"

        if (self.state == "PLAYINGHIT"):
            if (self.boss.getCurrentFrame() == None) or (self.boss.getCurrentFrame() == self.boss.getNumFrames()-1):
                self.state = self.previous_state
            return task.again

        if self.state == "IDLE":
            if(self.boss.getCurrentAnim()!="idle"):
                self.boss.play("idle")

        if self.common['PC'].HP <= 0 or self.node.getDistance(target)>14:
            self.state="IDLE"
            self.common['spawner'].monster_limit = 4
        else:
            self.common['spawner'].monster_limit = 2
            if self.boss.getAnimControl('scream').isPlaying():
                #we must wait until the animation is finished
                return task.again
            if (random.random() < 0.001):
                self.state="SCREAMING"
                if(self.boss.getCurrentAnim()!="scream"):
                    self.boss.play("scream")
                    self.common['soundPool'].attachAndPlay(self.boss, "awake-the-beast.wav")
            else:
                if self.node.getDistance(target)>2:
                    #If the boss is idle or has finished to play an animation (e.g. an attack) he must pursue the player
                    if self.state == "HIT" or self.state == "IDLE" or self.boss.getCurrentAnim() == None:
                        self.state="PURSUING"
                    if self.state == "PURSUING":
                        self.AIworld.update()
                        #self.node.setY(self.node, 1*globalClock.getDt())
                        if(self.boss.getCurrentAnim()!="walk"):
                            self.common['soundPool'].attachAndPlay(self.boss, "creature_slime_01-2.ogg", 0.7)
                            self.boss.play("walk")
                else:
                    self.state="ATTACKING"
                    if(self.boss.getCurrentAnim()!="attack2") and (self.boss.getCurrentAnim()!="attack1"):
                        if (type(self.common['PC']).__name__ == "Knight") and (random.random() > 0.1):
                            self.state="IDLE"
                            self.previous_state = self.state
                            return task.again
                        if (random.random() < 0.5):
                            self.boss.play("attack2")
                            self.common['soundPool'].attachAndPlay(self.boss, "Whoosh4.ogg")
                            self.boss.attackdamage = 20
                        else:
                            self.common['soundPool'].attachAndPlay(self.boss, "explodemini.wav", delay=1)
                            self.boss.play("attack1")
                            self.boss.attackdamage = 30
                    # Inflict damage only when we played half of the animation (it should be the moment when the attack hits the player)
                    # This function could be called multiple times even if we are at the same frame (probably depends on the frame rate of the animation)
                    # Thus, we should also check if we are seeing the same previous hit (based on the last frame, it must not be the same)
                    elif (self.boss.getCurrentFrame() == int(self.boss.getNumFrames()/2)) and (self.boss.getCurrentFrame() != self.boss.lastFrame):
                        if (self.boss.getCurrentAnim() == "attack1"):
                            #The sound must be played only when the boss hit the floor (it's in the mid of the animation)
                            # Get position of the joint respect to render (i.e. absolute position)
                            (x,y,_) = self.left_thumb.getPos(render)
                            vfx(None, texture='vfx/dust.png',scale=1, Z=0, depthTest=True, depthWrite=True,pos=(x,y,0)).start(0.016)
                        self.common['PC'].hit(self.boss.attackdamage)
                    self.boss.lastFrame = self.boss.getCurrentFrame()
        self.previous_state = self.state
        return task.again

    def doDamage(self, damage, igoreArmor=False):
        if self.state=="DIE":
            return
        if not igoreArmor:
            damage-=self.stats['armor']
        if damage<1:
            damage=1
        #print damage
        self.stats['hp']-=damage
        self.healthBar.show()
        self.healthBar.setScale(10*self.stats['hp']/self.maxHP,1, 1)
        if self.stats['hp']<1:
            self.healthBar.hide()

    def die(self, soundname):
        #self.common['soundPool'].play(self.soundID, self.sound_names["hit"])
        #self.common['soundPool'].play(self.soundID, soundname)
        self.state="DIE"

    def onHit(self, damage, sound="hit", weapon=None):
        if self.state=="DIE":
            return
        self.state="HIT"
        self.doDamage(damage)

        if self.stats['hp']<1:
            self.die("die")

    def damageOverTime(self, task):
        if self.state=="DIE":
            return task.done
        if self.DOT>0:
            self.doDamage(self.DOT)
            self.DOT=int((self.DOT*0.9)-1.0)
            vfx(self.node, texture='vfx/blood_dark.png',scale=.5, Z=1.0, depthTest=True, depthWrite=True).start(0.016)
        return task.again

    def destroy(self):
        self.arrows=None
        if self.boss:
            self.boss.cleanup()
            self.boss.removeNode()
        if taskMgr.hasTaskNamed("BossAIfor"+str(self.id)):
            taskMgr.remove("BossAIfor"+str(self.id))
#        if taskMgr.hasTaskNamed('collFor'+str(self.id)):
#            taskMgr.remove('collFor'+str(self.id))
        if taskMgr.hasTaskNamed('DOTfor'+str(self.id)):
            taskMgr.remove('DOTfor'+str(self.id))
        if taskMgr.hasTaskNamed('AIUpdate'):
            taskMgr.remove('AIUpdate')
        if self.node:
            self.node.removeNode()
        self.common['monsterList'][self.id]=None
        self.traverser=None
        self.queue=None
        #self.common['traverser'].removeCollider(self.coll_sphere)
        self.coll_body.removeNode()
        self.coll_quad.removeNode()
        self.healthBar.removeNode()
Beispiel #55
0
class Suit(Avatar.Avatar):
	healthColors = (Vec4(0, 1, 0, 1),
		Vec4(1, 1, 0, 1),
		Vec4(1, 0.5, 0, 1),
		Vec4(1, 0, 0, 1),
		Vec4(0.3, 0.3, 0.3, 1))
	healthGlowColors = (Vec4(0.25, 1, 0.25, 0.5),
		Vec4(1, 1, 0.25, 0.5),
		Vec4(1, 0.5, 0.25, 0.5),
		Vec4(1, 0.25, 0.25, 0.5),
		Vec4(0.3, 0.3, 0.3, 0))
	medallionColors = {'c': Vec4(0.863, 0.776, 0.769, 1.0),
		's': Vec4(0.843, 0.745, 0.745, 1.0),
		'l': Vec4(0.749, 0.776, 0.824, 1.0),
		'm': Vec4(0.749, 0.769, 0.749, 1.0)}
	health2DmgMultiplier = 2.5
	
	def __init__(self):
		try:
			self.Suit_initialized
			return
		except:
			self.Suit_initialized = 1
		
		Avatar.Avatar.__init__(self)
		self.avatarType = CIGlobals.Suit
		self.name = ''
		self.chat = ''
		self.suit = None
		self.suitHeads = None
		self.suitHead = None
		self.loserSuit = None
		self.healthMeterGlow = None
		self.healthMeter = None
		self.weapon = None
		self.weapon_sfx = None
		self.anim = None
		self.suit_dial = None
		self.shadow = None
		self.balloon_sfx = None
		self.add_sfx = None
		self.explosion = None
		self.largeExp = None
		self.smallExp = None
		self.death_sfx = None
		self.attack = None
		self.wtrajectory = None
		self.throwObjectId = None
		self.hasSpawned = False
		self.condition = 0
		self.type = ""
		self.head = ""
		self.team = ""
		self.isSkele = 0
		self.animFSM = ClassicFSM('Suit', [State('off', self.enterOff, self.exitOff),
								State('neutral', self.enterNeutral, self.exitNeutral),
								State('walk', self.enterWalk, self.exitWalk),
								State('die', self.enterDie, self.exitDie),
								State('attack', self.enterAttack, self.exitAttack),
								State('flydown', self.enterFlyDown, self.exitFlyDown),
								State('pie', self.enterPie, self.exitPie),
								State('win', self.enterWin, self.exitWin),
								State('flyaway', self.enterFlyAway, self.exitFlyAway),
								State('rollodex', self.enterRollodex, self.exitRollodex)], 'off', 'off')
		animStateList = self.animFSM.getStates()
		self.animFSM.enterInitialState()
		
		self.initializeBodyCollisions()
		
	def delete(self):
		try:
			self.Suit_deleted
		except:
			self.Suit_deleted = 1
			if self.suit:
				self.cleanupSuit()
			if self.loserSuit:
				self.cleanupLoserSuit()
			if self.suitHeads:
				self.suitHeads.remove()
				self.suitHeads = None
			if self.suitHead:
				self.suitHead.remove()
				self.suitHead = None
			if self.healthMeterGlow:
				self.healthMeterGlow.remove()
				self.healthMeterGlow = None
			if self.healthMeter:
				self.healthMeter.remove()
				self.healthMeter = None
			if self.shadow:
				self.shadow.remove()
				self.shadow = None
			self.weapon = None
			self.weapon_sfx = None
			self.suit_dial = None
			del self.shadowPlacer
			
	def generateSuit(self, suitType, suitHead, suitTeam, suitHealth, skeleton):
		self.health = suitHealth
		self.maxHealth = suitHealth
		self.generateBody(suitType, suitTeam, suitHead, skeleton)
		self.generateHealthMeter()
		self.generateHead(suitType, suitHead)
		self.setupNameTag()
		Avatar.Avatar.initShadow(self)
		
	def generateBody(self, suitType, suitTeam, suitHead, skeleton):
		if self.suit:
			self.cleanupSuit()
			
		self.team = suitTeam
		self.type = suitType
		self.head = suitHead
		self.isSkele = skeleton
		
		if suitType == "A":
			if skeleton:
				self.suit = Actor("phase_5/models/char/cogA_robot-zero.bam")
			else:
				self.suit = Actor("phase_3.5/models/char/suitA-mod.bam")
			self.suit.loadAnims({"neutral": "phase_4/models/char/suitA-neutral.bam",
							"walk": "phase_4/models/char/suitA-walk.bam",
							"pie": "phase_4/models/char/suitA-pie-small.bam",
							"land": "phase_5/models/char/suitA-landing.bam",
							"throw-object": "phase_5/models/char/suitA-throw-object.bam",
							"throw-paper": "phase_5/models/char/suitA-throw-paper.bam",
							"glower": "phase_5/models/char/suitA-glower.bam",
							"win": "phase_4/models/char/suitA-victory.bam",
							"rollodex": "phase_5/models/char/suitA-roll-o-dex.bam"})
		if suitType == "B":
			if skeleton:
				self.suit = Actor("phase_5/models/char/cogB_robot-zero.bam")
			else:
				self.suit = Actor("phase_3.5/models/char/suitB-mod.bam")
			self.suit.loadAnims({"neutral": "phase_4/models/char/suitB-neutral.bam",
							"walk": "phase_4/models/char/suitB-walk.bam",
							"pie": "phase_4/models/char/suitB-pie-small.bam",
							"land": "phase_5/models/char/suitB-landing.bam",
							"throw-object": "phase_5/models/char/suitB-throw-object.bam",
							"throw-paper": "phase_5/models/char/suitB-throw-paper.bam",
							"glower": "phase_5/models/char/suitB-magic1.bam",
							"win": "phase_4/models/char/suitB-victory.bam",
							"rollodex": "phase_5/models/char/suitB-roll-o-dex.bam"})
		if suitType == "C":
			if skeleton:
				self.suit = Actor("phase_5/models/char/cogC_robot-zero.bam")
			else:
				self.suit = Actor("phase_3.5/models/char/suitC-mod.bam")
			self.suit.loadAnims({"neutral": "phase_3.5/models/char/suitC-neutral.bam",
						"walk": "phase_3.5/models/char/suitC-walk.bam",
						"pie": "phase_3.5/models/char/suitC-pie-small.bam",
						"land": "phase_5/models/char/suitC-landing.bam",
						"throw-object": "phase_3.5/models/char/suitC-throw-paper.bam",
						"throw-paper": "phase_3.5/models/char/suitC-throw-paper.bam",
						"glower": "phase_5/models/char/suitC-glower.bam",
						"win": "phase_4/models/char/suitC-victory.bam"})
		if skeleton:
			self.suit.setTwoSided(1)
		self.suit.getGeomNode().setScale(CIGlobals.SuitScales[suitHead] / CIGlobals.SuitScaleFactors[suitType])
		
		if skeleton:
			if suitTeam == "s":
				self.suit_tie = loader.loadTexture("phase_5/maps/cog_robot_tie_sales.jpg")
			elif suitTeam == "m":
				self.suit_tie = loader.loadTexture("phase_5/maps/cog_robot_tie_money.jpg")
			elif suitTeam == "l":
				self.suit_tie = loader.loadTexture("phase_5/maps/cog_robot_tie_legal.jpg")
			elif suitTeam == "c":
				self.suit_tie = loader.loadTexture("phase_5/maps/cog_robot_tie_boss.jpg")
			self.suit.find('**/tie').setTexture(self.suit_tie, 1)
		else:
			self.suit_blazer = loader.loadTexture("phase_3.5/maps/" + suitTeam + "_blazer.jpg")
			self.suit_leg = loader.loadTexture("phase_3.5/maps/" + suitTeam + "_leg.jpg")
			self.suit_sleeve = loader.loadTexture("phase_3.5/maps/" + suitTeam + "_sleeve.jpg")
			
			self.suit.find('**/legs').setTexture(self.suit_leg, 1)
			self.suit.find('**/arms').setTexture(self.suit_sleeve, 1)
			self.suit.find('**/torso').setTexture(self.suit_blazer, 1)
		
			if suitHead == "coldcaller":
				self.suit.find('**/hands').setColor(0.55, 0.65, 1.0, 1.0)
			elif suitHead == "corporateraider":
				self.suit.find('**/hands').setColor(0.85, 0.55, 0.55, 1.0)
			elif suitHead == "bigcheese":
				self.suit.find('**/hands').setColor(0.75, 0.95, 0.75, 1.0)
			elif suitHead == "bloodsucker":
				self.suit.find('**/hands').setColor(0.95, 0.95, 1.0, 1.0)
			elif suitHead == "spindoctor":
				self.suit.find('**/hands').setColor(0.5, 0.8, 0.75, 1.0)
			elif suitHead == "legaleagle":
				self.suit.find('**/hands').setColor(0.25, 0.25, 0.5, 1.0)
			elif suitHead == "pennypincher":
				self.suit.find('**/hands').setColor(1.0, 0.5, 0.6, 1.0)
			elif suitHead == "loanshark":
				self.suit.find('**/hands').setColor(0.5, 0.85, 0.75, 1.0)
			else:
				self.suit.find('**/hands').setColor(CIGlobals.SuitHandColors[suitTeam])
		
		self.suit.reparentTo(self)
		
	def generateHead(self, suitType, suitHead):
		if self.suitHead:
			self.cleanupSuitHead()
			
		self.type = suitType
		self.head = suitHead
		
		if suitHead == "vp":
			self.suitHead = Actor("phase_9/models/char/sellbotBoss-head-zero.bam",
								{"neutral": "phase_9/models/char/bossCog-head-Ff_neutral.bam"})
			self.suitHead.setTwoSided(True)
			self.suitHead.loop("neutral")
			self.suitHead.setScale(0.35)
			self.suitHead.setHpr(270, 0, 270)
			self.suitHead.setZ(-0.10)
		else:
			if suitType == "A" or suitType == "B":
				self.suitHeads = loader.loadModel("phase_4/models/char/suit" + suitType + "-heads.bam")
			else:
				self.suitHeads = loader.loadModel("phase_3.5/models/char/suit" + suitType + "-heads.bam")
			self.suitHead = self.suitHeads.find('**/' + CIGlobals.SuitHeads[suitHead])
			if suitHead == "flunky":
				glasses = self.suitHeads.find('**/glasses')
				glasses.reparentTo(self.suitHead)
				glasses.setTwoSided(True)
			if suitHead in CIGlobals.SuitSharedHeads:
				if suitHead == "coldcaller":
					self.suitHead.setColor(0.25, 0.35, 1.0, 1.0)
				else:
					headTexture = loader.loadTexture("phase_3.5/maps/" + suitHead + ".jpg")
					self.suitHead.setTexture(headTexture, 1)
		if not self.isSkele:
			self.suitHead.reparentTo(self.suit.find('**/joint_head'))
			
	def cleanupSuit(self):
		if self.shadow:
			self.shadow.remove()
			self.shadow = None
		self.removeHealthBar()
		self.suit.cleanup()
		self.suit = None
		
	def cleanupSuitHead(self):
		if self.suitHeads:
			self.suitHeads.remove()
			self.suitHeads = None
		if self.suitHead:
			self.suitHead.remove()
			self.suitHead = None
		
	def cleanupLoserSuit(self):
		if self.explosion:
			self.explosion.remove()
			self.explosion = None
		if self.smallExp:
			self.smallExp = None
		if self.largeExp:
			self.largeExp.cleanup()
			self.largeExp = None
		if self.loserSuit:
			self.loserSuit.cleanup()
			self.loserSuit = None
		
	def setName(self, nameString, charName):
		Avatar.Avatar.setName(self, nameString, avatarType=self.avatarType, charName=charName)
		
	def setChat(self, chatString):
		self.chat = chatString
		if self.isSkele:
			if "?" in chatString:
				self.suit_dial = audio3d.loadSfx("phase_5/audio/sfx/Skel_COG_VO_question.ogg")
			elif "!" in chatString:
				self.suit_dial = audio3d.loadSfx("phase_5/audio/sfx/Skel_COG_VO_grunt.ogg")
			else:
				self.suit_dial = audio3d.loadSfx("phase_5/audio/sfx/Skel_COG_VO_statement.ogg")
		elif self.head == "vp":
			if "?" in chatString:
				self.suit_dial = audio3d.loadSfx("phase_9/audio/sfx/Boss_COG_VO_question.ogg")
			elif "!" in chatString:
				self.suit_dial = audio3d.loadSfx("phase_9/audio/sfx/Boss_COG_VO_grunt.ogg")
			else:
				self.suit_dial = audio3d.loadSfx("phase_9/audio/sfx/Boss_COG_VO_statement.ogg")
		else:
			if "?" in chatString:
				self.suit_dial = audio3d.loadSfx("phase_3.5/audio/dial/COG_VO_question.ogg")
			elif "!" in chatString:
				self.suit_dial = audio3d.loadSfx("phase_3.5/audio/dial/COG_VO_grunt.ogg")
			else:
				self.suit_dial = audio3d.loadSfx("phase_3.5/audio/dial/COG_VO_statement.ogg")
		if self.isSkele:
			audio3d.attachSoundToObject(self.suit_dial, self.suit)
		else:
			audio3d.attachSoundToObject(self.suit_dial, self.suitHead)
		self.suit_dial.play()
		Avatar.Avatar.setChat(self, chatString)
		
	def generateHealthMeter(self):
		self.removeHealthBar()
		model = loader.loadModel("phase_3.5/models/gui/matching_game_gui.bam")
		button = model.find('**/minnieCircle')
		button.setScale(3.0)
		button.setH(180)
		button.setColor(self.healthColors[0])
		chestNull = self.suit.find('**/def_joint_attachMeter')
		if chestNull.isEmpty():
			chestNull = self.suit.find('**/joint_attachMeter')
		button.reparentTo(chestNull)
		self.healthBar = button
		glow = loader.loadModel("phase_3.5/models/props/glow.bam")
		glow.reparentTo(self.healthBar)
		glow.setScale(0.28)
		glow.setPos(-0.005, 0.01, 0.015)
		glow.setColor(self.healthGlowColors[0])
		button.flattenLight()
		self.healthBarGlow = glow
		self.condition = 0
		
	def updateHealthBar(self, hp):
		if hp > self.hp:
			self.hp = hp
		self.hp -= hp
		health = float(self.health) / float(self.maxHP)
		if health > 0.95:
			condition = 0
		elif health > 0.7:
			condition = 1
		elif health > 0.3:
			condition = 2
		elif health > 0.05:
			condition = 3
		elif health > 0.0:
			condition = 4
		else:
			condition = 5
			
		if self.condition != condition:
			if condition == 4:
				blinkTask = Task.loop(Task(self.__blinkRed), Task.pause(0.75), Task(self.__blinkGray), Task.pause(0.1))
				taskMgr.add(blinkTask, self.taskName('blink-task'))
			elif condition == 5:
				if self.condition == 4:
					taskMgr.remove(self.taskName('blink-task'))
				blinkTask = Task.loop(Task(self.__blinkRed), Task.pause(0.25), Task(self.__blinkGray), Task.pause(0.1))
				taskMgr.add(blinkTask, self.taskName('blink-task'))
			else:
				self.healthBar.setColor(self.healthColors[condition], 1)
				self.healthBarGlow.setColor(self.healthGlowColors[condition], 1)
			self.condition = condition
			
	def __blinkRed(self, task):
		self.healthBar.setColor(self.healthColors[3], 1)
		self.healthBarGlow.setColor(self.healthGlowColors[3], 1)
		if self.condition == 5:
			self.healthBar.setScale(1.17)
		return Task.done
		
	def __blinkGray(self, task):
		if not self.healthBar:
			return
		self.healthBar.setColor(self.healthColors[4], 1)
		self.healthBarGlow.setColor(self.healthGlowColors[4], 1)
		if self.condition == 5:
			self.healthBar.setScale(1.0)
		return Task.done
		
	def removeHealthBar(self):
		if self.healthMeter:
			self.healthBar.removeNode()
			self.healthBar = None
		if self.condition == 4 or self.condition == 5:
			taskMgr.remove(self.taskName('blink-task'))
		self.healthCondition = 0
		return
			
	def enterOff(self):
		self.anim = None
		return
		
	def exitOff(self):
		pass
		
	def exitGeneral(self):
		self.suit.stop()
		
	def enterNeutral(self):
		self.suit.loop("neutral")
		
	def exitNeutral(self):
		self.exitGeneral()
		
	def enterRollodex(self):
		self.suit.play("rollodex")
		
	def exitRollodex(self):
		self.exitGeneral()
		
	def enterWalk(self):
		self.suit.loop("walk")
		
	def exitWalk(self):
		self.exitGeneral()
		
	def generateLoserSuit(self):
		self.cleanupLoserSuit()
		if self.type == "A":
			if self.isSkele:
				self.loserSuit = Actor("phase_5/models/char/cogA_robot-lose-mod.bam")
			else:
				self.loserSuit = Actor("phase_4/models/char/suitA-lose-mod.bam")
			self.loserSuit.loadAnims({"lose": "phase_4/models/char/suitA-lose.bam"})
		if self.type == "B":
			if self.isSkele:
				self.loserSuit = Actor("phase_5/models/char/cogB_robot-lose-mod.bam")
			else:
				self.loserSuit = Actor("phase_4/models/char/suitB-lose-mod.bam")
			self.loserSuit.loadAnims({"lose": "phase_4/models/char/suitB-lose.bam"})
		if self.type == "C":
			if self.isSkele:
				self.loserSuit = Actor("phase_5/models/char/cogC_robot-lose-mod.bam")
			else:
				self.loserSuit = Actor("phase_3.5/models/char/suitC-lose-mod.bam")
			self.loserSuit.loadAnims({"lose": "phase_3.5/models/char/suitC-lose.bam"})
		if self.isSkele:
			self.loserSuit.find('**/tie').setTexture(self.suit_tie, 1)
			self.loserSuit.setTwoSided(1)
		else:
			self.loserSuit.find('**/hands').setColor(self.suit.find('**/hands').getColor())
			self.loserSuit.find('**/legs').setTexture(self.suit_leg, 1)
			self.loserSuit.find('**/arms').setTexture(self.suit_sleeve, 1)
			self.loserSuit.find('**/torso').setTexture(self.suit_blazer, 1)
		self.loserSuit.getGeomNode().setScale(self.suit.getScale())
		self.loserSuit.reparentTo(self)
		if not self.isSkele:
			self.suitHead.reparentTo(self.loserSuit.find('**/joint_head'))
		self.loserSuit.setPos(self.suit.getPos(render))
		self.loserSuit.setHpr(self.suit.getHpr(render))
		self.cleanupSuit()
		Avatar.Avatar.initShadow(self, self.avatarType)
		self.loserSuit.reparentTo(render)
		
	def enterDie(self):
		self.generateLoserSuit()
		self.state = "dead"
		self.loserSuit.play("lose")
		spinningSound = base.loadSfx("phase_3.5/audio/sfx/Cog_Death.ogg")
		deathSound = base.loadSfx("phase_3.5/audio/sfx/ENC_cogfall_apart.ogg")
		#audio3d.attachSoundToObject(spinningSound, self.loserSuit)
		#audio3d.attachSoundToObject(deathSound, self.loserSuit)
		Sequence(Wait(0.8), SoundInterval(spinningSound, duration=1.2, startTime=1.5, volume=0.4, node=self.loserSuit),
			SoundInterval(spinningSound, duration=3.0, startTime=0.6, volume=2.0, node=self.loserSuit),
			SoundInterval(deathSound, volume=0.32, node=self.loserSuit)).start()
		Sequence(Wait(0.8), Func(self.smallDeathParticles), Wait(4.2), Func(self.suitExplode),
				Wait(1.0), Func(self.delSuit)).start()
		
	def smallDeathParticles(self):
		self.smallExp = ParticleLoader.loadParticleEffect("phase_3.5/etc/gearExplosionSmall.ptf")
		self.smallExp.start(self.loserSuit)
		
	def suitExplode(self):
		self.smallExp.cleanup()
		self.largeExp = ParticleLoader.loadParticleEffect("phase_3.5/etc/gearExplosion.ptf")
		self.largeExp.start(self.loserSuit)
		self.explosion = loader.loadModel("phase_3.5/models/props/explosion.bam")
		self.explosion.setScale(0.5)
		self.explosion.reparentTo(render)
		self.explosion.setBillboardPointEye()
		if self.isSkele:
			self.explosion.setPos(self.loserSuit.find('**/joint_head').getPos(render) + (0, 0, 2))
		else:
			self.explosion.setPos(self.suitHead.getPos(render) + (0,0,2))
		
	def delSuit(self):
		self.cleanupLoserSuit()
		self.disableBodyCollisions()
		
	def exitDie(self):
		pass
		
	def enterFlyDown(self):
		self.fd_sfx = audio3d.loadSfx("phase_5/audio/sfx/ENC_propeller_in.ogg")
		self.prop = Actor("phase_4/models/props/propeller-mod.bam",
						{"chan": "phase_4/models/props/propeller-chan.bam"})
		audio3d.attachSoundToObject(self.fd_sfx, self.prop)
		self.fd_sfx.play()
		self.prop.reparentTo(self.suit.find('**/joint_head'))
		propTrack = Sequence(Func(self.prop.loop, 'chan', fromFrame=0, toFrame=3),
							Wait(1.75),
							Func(self.prop.play, 'chan', fromFrame=3))
		propTrack.start()
		if not self.hasSpawned:
			showSuit = Task.sequence(Task(self.hideSuit), Task.pause(0.3), Task(self.showSuit))
			taskMgr.add(showSuit, "showsuit")
			self.hasSpawned = True
		dur = self.suit.getDuration('land')
		suitTrack = Sequence(Func(self.suit.pose, 'land', 0),
							Wait(1.9),
							ActorInterval(self.suit, 'land', duration=dur))
		suitTrack.start()
		
	def hideSuit(self, task):
		self.hide()
		return Task.done
	
	def showSuit(self, task):
		self.show()
		fadeIn = Sequence(Func(self.setTransparency, 1), self.colorScaleInterval(0.6, colorScale=Vec4(1,1,1,1), startColorScale=Vec4(1,1,1,0)), Func(self.clearColorScale), Func(self.clearTransparency), Func(self.reparentTo, render))
		fadeIn.start()
		return Task.done
		
	def initializeLocalCollisions(self, name):
		Avatar.Avatar.initializeLocalCollisions(self, 1, 3, name)
		
	def initializeBodyCollisions(self):
		Avatar.Avatar.initializeBodyCollisions(self, self.avatarType, 2.25, 1, 4, 2)
		self.initializeRay(self.avatarType)
		self.collTube.setTangible(0)
		
	def deleteBean(self):
		if self.bean:
			self.bean.remove_node()
			self.bean = None
			
	def createJellyBean(self):
		self.deleteBean()
		money = int(self.maxHP / CIGlobals.SuitAttackDamageFactors['clipontie'])
		if money == 1:
			self.bean = loader.loadModel("phase_5.5/models/estate/jellyBean.bam")
			self.bean.set_two_sided(True)
			random_r = random.uniform(0, 1)
			random_g = random.uniform(0, 1)
			random_b = random.uniform(0, 1)
			self.bean.set_color(random_r, random_g, random_b, 1)
		else:
			self.bean = loader.loadModel("phase_5.5/models/estate/jellybeanJar.bam")
		self.bean.reparent_to(render)
		self.bean.set_pos(self.get_pos(render) + (0, 0, 1))
		bean_int = self.bean.hprInterval(1,
										Point3(360, 0, 0),
										startHpr=(0, 0, 0))
		bean_int.loop()
		
	def exitFlyDown(self):
		audio3d.detachSound(self.fd_sfx)
		self.prop.cleanup()
		self.prop = None
		
	def enterFlyAway(self):
		self.fa_sfx = audio3d.loadSfx("phase_5/audio/sfx/ENC_propeller_out.ogg")
		self.prop = Actor("phase_4/models/props/propeller-mod.bam",
						{"chan": "phase_4/models/props/propeller-chan.bam"})
		audio3d.attachSoundToObject(self.fa_sfx, self.prop)
		self.fa_sfx.play()
		self.prop.reparentTo(self.suit.find('**/joint_head'))
		self.prop.setPlayRate(-1.0, "chan")
		propTrack = Sequence(Func(self.prop.play, 'chan', fromFrame=3),
							Wait(1.75),
							Func(self.prop.play, 'chan', fromFrame=0, toFrame=3))
		propTrack.start()
		self.suit.setPlayRate(-1.0, 'land')
		self.suit.play('land')
		
	def exitFlyAway(self):
		audio3d.detachSound(self.fa_sfx)
		self.prop.cleanup()
		self.prop = None
		
	def enterAttack(self, attack):
		self.attack = attack
		
		self.weapon_state = 'start'
		
		if attack == "canned":
			self.weapon = loader.loadModel("phase_5/models/props/can.bam")
			self.weapon.setScale(15)
			self.weapon.setR(180)
			self.wss = CollisionSphere(0,0,0,0.05)
		elif attack == "clipontie":
			self.weapon = loader.loadModel("phase_5/models/props/power-tie.bam")
			self.weapon.setScale(4)
			self.weapon.setR(180)
			self.wss = CollisionSphere(0,0,0,0.2)
		elif attack == "sacked":
			self.weapon = loader.loadModel("phase_5/models/props/sandbag-mod.bam")
			self.weapon.setScale(2)
			self.weapon.setR(180)
			self.weapon.setP(90)
			self.weapon.setY(-2.8)
			self.weapon.setZ(-0.3)
			self.wss = CollisionSphere(0,0,0,1)
		elif attack == "playhardball":
			self.weapon = loader.loadModel("phase_5/models/props/baseball.bam")
			self.weapon.setScale(10)
			self.wss = CollisionSphere(0,0,0,0.1)
			self.weapon.setZ(-0.5)
		elif attack == "marketcrash":
			self.weapon = loader.loadModel("phase_5/models/props/newspaper.bam")
			self.weapon.setScale(3)
			self.weapon.setPos(0.41, -0.06, -0.06)
			self.weapon.setHpr(90, 0, 270)
			self.wss = CollisionSphere(0,0,0,0.35)
		elif attack == "glowerpower":
			self.weapon = loader.loadModel("phase_5/models/props/dagger.bam")
			self.wss = CollisionSphere(0,0,0,1)
		else:
			notify.warning("unknown attack!")
			
		self.throwObjectId = random.uniform(0, 101010101010)
		
		if attack == "canned" or attack == "playhardball":
			self.weapon.reparentTo(self.suit.find('**/joint_Rhold'))
			if self.type == "C":
				taskMgr.doMethodLater(2.2, self.throwObject, "throwObject" + str(self.throwObjectId))
			else:
				taskMgr.doMethodLater(3, self.throwObject, "throwObject" + str(self.throwObjectId))
			self.suit.play("throw-object")
		elif attack == "clipontie" or attack == "marketcrash" or attack == "sacked":
			self.weapon.reparentTo(self.suit.find('**/joint_Rhold'))
			if self.type == "C":
				taskMgr.doMethodLater(2.2, self.throwObject, "throwObject" + str(self.throwObjectId))
			else:
				taskMgr.doMethodLater(3, self.throwObject, "throwObject" + str(self.throwObjectId))
			self.suit.play("throw-paper")
		elif attack == "glowerpower":
			taskMgr.doMethodLater(1, self.throwObject, "throwObject" + str(self.throwObjectId))
			self.suit.play("glower")
		self.weaponSensorId = random.uniform(0, 1010101010101001)
		wsnode = CollisionNode('weaponSensor' + str(self.weaponSensorId))
		wsnode.addSolid(self.wss)
		self.wsnp = self.weapon.attachNewNode(wsnode)
		if attack == "sacked":
			self.wsnp.setZ(1)
		elif attack == "marketcrash":
			self.wsnp.setPos(-0.25, 0.3, 0)
			
	def delWeapon(self, task):
		if self.weapon:
			self.weapon.removeNode()
			self.weapon = None
		return task.done
		
	def interruptAttack(self):
		if self.wtrajectory:
			if self.wtrajectory.isStopped():
				if self.weapon:
					self.weapon.removeNode()
					self.weapon = None
		if self.throwObjectId:
			taskMgr.remove("throwObject" + str(self.throwObjectId))
		
	def handleWeaponTouch(self):
		if not self.attack == "glowerpower" or not self.attack == "clipontie":
			if self.weapon_sfx:
				self.weapon_sfx.stop()
		try: self.wtrajectory.pause()
		except: pass
		if self.weapon:
			self.weapon.removeNode()
			self.weapon = None
		
	def weaponCollisions(self):
		self.wsnp.setCollideMask(BitMask32(0))
		self.wsnp.node().setFromCollideMask(CIGlobals.EventBitmask)
			
		event = CollisionHandlerEvent()
		event.setInPattern("%fn-into")
		event.setOutPattern("%fn-out")
		base.cTrav.addCollider(self.wsnp, event)
		
	def throwObject(self, task):
		self.playWeaponSound()
		
		self.weaponNP = NodePath("weaponNP")
		self.weaponNP.setScale(render, 1)
		try: self.weaponNP.reparentTo(self.find('**/joint_nameTag'))
		except: return task.done
		self.weaponNP.setPos(0, 50, 0)
		self.weaponNP.setHpr(0, 0, 0)
		
		if self.weapon:
			self.weapon.setScale(self.weapon.getScale(render))
		try: self.weapon.reparentTo(render)
		except: return task.done
		
		self.weapon.setPos(0,0,0)
		self.weapon.setHpr(0,0,0)
		
		if self.attack == "glowerpower":
			self.weapon.setH(self.weaponNP.getH(render))
			self.wtrajectory = self.weapon.posInterval(0.5,
										Point3(self.weaponNP.getPos(render)),
										startPos=(self.getX(render), self.getY(render) + 3, self.find('**/joint_head').getZ(render)))
			self.wtrajectory.start()
		else:
			self.wtrajectory = ProjectileInterval(self.weapon,
										startPos = (self.suit.find('**/joint_Rhold').getPos(render)),
										endPos = self.weaponNP.getPos(render),
										gravityMult = 0.7, duration = 1)
			self.wtrajectory.start()
		if self.attack == "glowerpower":
			taskMgr.doMethodLater(0.5, self.delWeapon, "delWeapon")
		else:
			taskMgr.doMethodLater(1, self.delWeapon, "delWeapon")
		self.weapon_state = 'released'
		
	def playWeaponSound(self):
		if self.attack == "glowerpower":
			self.weapon_sfx = audio3d.loadSfx("phase_5/audio/sfx/SA_glower_power.ogg")
		elif self.attack == "canned":
			self.weapon_sfx = audio3d.loadSfx("phase_5/audio/sfx/SA_canned_tossup_only.ogg")
		elif self.attack == "clipontie":
			self.weapon_sfx = audio3d.loadSfx("phase_5/audio/sfx/SA_powertie_throw.ogg")
		elif self.attack == "sacked":
			self.weapon_sfx = audio3d.loadSfx("phase_5/audio/sfx/SA_canned_tossup_only.ogg")
		elif self.attack == "playhardball":
			self.weapon_sfx = audio3d.loadSfx("phase_5/audio/sfx/SA_canned_tossup_only.ogg")
		elif self.attack == "marketcrash":
			self.weapon_sfx = audio3d.loadSfx("phase_5/audio/sfx/SA_canned_tossup_only.ogg")
		if self.weapon:
			audio3d.attachSoundToObject(self.weapon_sfx, self.weapon)
			self.weapon_sfx.play()
			
	def exitAttack(self):
		pass
		
	def enterPie(self):
		self.suit.play("pie")
		
	def exitPie(self):
		self.exitGeneral()
		
	def enterWin(self):
		self.suit.play("win")
		
	def exitWin(self):
		self.exitGeneral()
Beispiel #56
0
class PartyCog(FSM):
    notify = directNotify.newCategory('PartyCog')
    HpTextGenerator = TextNode('HpTextGenerator')
    hpText = None
    height = 7

    def __init__(self,
                 parentNode,
                 id,
                 bounceSpeed=3,
                 bounceHeight=1,
                 rotateSpeed=1,
                 heightShift=1,
                 xMoveSpeed=0,
                 xMoveDistance=0,
                 bounceOffset=0):
        self.id = id
        FSM.__init__(self, 'PartyCogFSM-%d' % self.id)
        self.showFacingStatus = False
        self.xMoveSpeed = xMoveSpeed
        self.xMoveDistance = xMoveDistance
        self.heightShift = heightShift
        self.bounceSpeed = bounceSpeed
        self.bounceHeight = bounceHeight
        self.rotateSpeed = rotateSpeed
        self.parentNode = parentNode
        self.bounceOffset = bounceOffset
        self.hitInterval = None
        self.kaboomTrack = None
        self.resetRollIval = None
        self.netTimeSentToStartByHit = 0
        self.load()
        self.request('Down')
        return

    def load(self):
        self.root = NodePath('PartyCog-%d' % self.id)
        self.root.reparentTo(self.parentNode)
        path = 'phase_13/models/parties/cogPinata_'
        self.actor = Actor(
            path + 'actor', {
                'idle': path + 'idle_anim',
                'down': path + 'down_anim',
                'up': path + 'up_anim',
                'bodyHitBack': path + 'bodyHitBack_anim',
                'bodyHitFront': path + 'bodyHitFront_anim',
                'headHitBack': path + 'headHitBack_anim',
                'headHitFront': path + 'headHitFront_anim'
            })
        self.actor.reparentTo(self.root)
        self.temp_transform = Mat4()
        self.head_locator = self.actor.attachNewNode('temphead')
        self.bodyColl = CollisionTube(0, 0, 1, 0, 0, 5.75, 0.75)
        self.bodyColl.setTangible(1)
        self.bodyCollNode = CollisionNode('PartyCog-%d-Body-Collision' %
                                          self.id)
        self.bodyCollNode.setCollideMask(ToontownGlobals.PieBitmask)
        self.bodyCollNode.addSolid(self.bodyColl)
        self.bodyCollNodePath = self.root.attachNewNode(self.bodyCollNode)
        self.headColl = CollisionTube(0, 0, 3, 0, 0, 3.0, 1.5)
        self.headColl.setTangible(1)
        self.headCollNode = CollisionNode('PartyCog-%d-Head-Collision' %
                                          self.id)
        self.headCollNode.setCollideMask(ToontownGlobals.PieBitmask)
        self.headCollNode.addSolid(self.headColl)
        self.headCollNodePath = self.root.attachNewNode(self.headCollNode)
        self.arm1Coll = CollisionSphere(1.65, 0, 3.95, 1.0)
        self.arm1Coll.setTangible(1)
        self.arm1CollNode = CollisionNode('PartyCog-%d-Arm1-Collision' %
                                          self.id)
        self.arm1CollNode.setCollideMask(ToontownGlobals.PieBitmask)
        self.arm1CollNode.addSolid(self.arm1Coll)
        self.arm1CollNodePath = self.root.attachNewNode(self.arm1CollNode)
        self.arm2Coll = CollisionSphere(-1.65, 0, 3.45, 1.0)
        self.arm2Coll.setTangible(1)
        self.arm2CollNode = CollisionNode('PartyCog-%d-Arm2-Collision' %
                                          self.id)
        self.arm2CollNode.setCollideMask(ToontownGlobals.PieBitmask)
        self.arm2CollNode.addSolid(self.arm2Coll)
        self.arm2CollNodePath = self.root.attachNewNode(self.arm2CollNode)
        splatName = 'splat-creampie'
        self.splat = globalPropPool.getProp(splatName)
        self.splat.setBillboardPointEye()
        self.splatType = globalPropPool.getPropType(splatName)
        self.pieHitSound = globalBattleSoundCache.getSound(
            'AA_wholepie_only.ogg')
        self.upSound = globalBattleSoundCache.getSound('AV_jump_to_side.ogg')
        self.hole = loader.loadModel('phase_13/models/parties/cogPinataHole')
        self.hole.setTransparency(True)
        self.hole.setP(-90.0)
        self.hole.setScale(3)
        self.hole.setBin('ground', 3)
        self.hole.reparentTo(self.parentNode)

    def unload(self):
        self.request('Off')
        self.clearHitInterval()
        if self.hole is not None:
            self.hole.removeNode()
            self.hole = None
        if self.actor is not None:
            self.actor.cleanup()
            self.actor.removeNode()
            self.actor = None
        if self.root is not None:
            self.root.removeNode()
            self.root = None
        if self.kaboomTrack is not None and self.kaboomTrack.isPlaying():
            self.kaboomTrack.finish()
        self.kaboomTrack = None
        if self.resetRollIval is not None and self.resetRollIval.isPlaying():
            self.resetRollIval.finish()
        self.resetRollIval = None
        if self.hitInterval is not None and self.hitInterval.isPlaying():
            self.hitInterval.finish()
        self.hitInterval = None
        del self.upSound
        del self.pieHitSound
        return

    def enterStatic(self):
        pass

    def exitStatic(self):
        pass

    def enterActive(self, startTime):
        self.root.setR(0.0)
        updateTask = Task.Task(self.updateTask)
        updateTask.startTime = startTime
        taskMgr.add(updateTask, 'PartyCog.update-%d' % self.id)

    def exitActive(self):
        taskMgr.remove('PartyCog.update-%d' % self.id)
        taskMgr.remove('PartyCog.bounceTask-%d' % self.id)
        self.clearHitInterval()
        self.resetRollIval = self.root.hprInterval(0.5,
                                                   Point3(
                                                       self.root.getH(), 0.0,
                                                       0.0),
                                                   blendType='easeInOut')
        self.resetRollIval.start()
        self.actor.stop()

    def enterDown(self):
        if self.oldState == 'Off':
            downAnimControl = self.actor.getAnimControl('down')
            self.actor.pose('down', downAnimControl.getNumFrames() - 1)
            return
        self.clearHitInterval()
        startScale = self.hole.getScale()
        endScale = Point3(5, 5, 5)
        self.hitInterval = Sequence(
            LerpFunc(self.setAlongSpline,
                     duration=1.0,
                     fromData=self.currentT,
                     toData=0.0),
            LerpScaleInterval(self.hole,
                              duration=0.175,
                              scale=endScale,
                              startScale=startScale,
                              blendType='easeIn'),
            Parallel(
                SoundInterval(self.upSound,
                              volume=0.6,
                              node=self.actor,
                              cutOff=PartyGlobals.PARTY_COG_CUTOFF),
                ActorInterval(self.actor, 'down', loop=0)),
            LerpScaleInterval(self.hole,
                              duration=0.175,
                              scale=Point3(3, 3, 3),
                              startScale=endScale,
                              blendType='easeOut'))
        self.hitInterval.start()

    def exitDown(self):
        self.root.setR(0.0)
        self.root.setH(0.0)
        self.targetDistance = 0.0
        self.targetFacing = 0.0
        self.currentT = 0.0
        self.setAlongSpline(0.0)
        self.clearHitInterval()
        startScale = self.hole.getScale()
        endScale = Point3(5, 5, 5)
        self.hitInterval = Sequence(
            LerpScaleInterval(self.hole,
                              duration=0.175,
                              scale=endScale,
                              startScale=startScale,
                              blendType='easeIn'),
            Parallel(
                SoundInterval(self.upSound,
                              volume=0.6,
                              node=self.actor,
                              cutOff=PartyGlobals.PARTY_COG_CUTOFF),
                ActorInterval(self.actor, 'up', loop=0)),
            Func(self.actor.loop, 'idle'),
            LerpScaleInterval(self.hole,
                              duration=0.175,
                              scale=Point3(3, 3, 3),
                              startScale=endScale,
                              blendType='easeOut'))
        self.hitInterval.start()

    def filterDown(self, request, args):
        if request == 'Down':
            return None
        else:
            return self.defaultFilter(request, args)
        return None

    def setEndPoints(self, start, end, amplitude=1.7):
        self.sinAmplitude = amplitude
        self.sinPeriod = (end.getX() - start.getX()) / 2
        self.sinDisplacement = start.getY()
        self.startPoint = start
        self.endPoint = end
        self.currentT = 0.0
        self.targetDistance = 0.0
        self.currentFacing = 0.0
        self.targetFacing = 0.0
        self.setAlongSpline(self.currentT)
        self.hole.setPos(self.root.getPos())
        self.hole.setZ(0.02)

    def rockBackAndForth(self, task):
        t = task.startTime + task.time
        angle = math.sin(t) * 20.0
        self.root.setR(angle)
        return task.cont

    def updateDistance(self, distance):
        self.targetDistance = clamp(distance, -1.0, 1.0)

    def updateTask(self, task):
        self.rockBackAndForth(task)
        if self.targetDistance > self.currentT:
            self.currentT += min(0.01, self.targetDistance - self.currentT)
            self.setAlongSpline(self.currentT)
        elif self.targetDistance < self.currentT:
            self.currentT += max(-0.01, self.targetDistance - self.currentT)
            self.setAlongSpline(self.currentT)
        if self.currentT < 0.0:
            self.targetFacing = -90.0
        elif self.currentT > 0.0:
            self.targetFacing = 90.0
        else:
            self.targetFacing = 0.0
        if self.targetFacing > self.currentFacing:
            self.currentFacing += min(10,
                                      self.targetFacing - self.currentFacing)
        elif self.targetFacing < self.currentFacing:
            self.currentFacing += max(-10,
                                      self.targetFacing - self.currentFacing)
        self.root.setH(self.currentFacing)
        return task.cont

    def setAlongSpline(self, t):
        t = t + 1.0
        dist = (self.endPoint.getX() - self.startPoint.getX()) / 2.0
        x = self.startPoint.getX() + t * dist
        y = self.startPoint.getY() - math.sin(
            t * 2 * math.pi) * self.sinAmplitude
        self.root.setPos(x, y, 0)

    def startBounce(self):
        taskMgr.add(self.bounce, 'PartyCog.bounceTask-%d' % self.id)

    def bounce(self, task):
        self.root.setZ(
            math.sin((self.bounceOffset + task.time) * self.bounceSpeed) *
            self.bounceHeight + self.heightShift)
        return task.cont

    def setPos(self, position):
        self.root.setPos(position)

    def respondToPieHit(self, timestamp, position, hot=False, direction=1.0):
        if self.netTimeSentToStartByHit < timestamp:
            self.__showSplat(position, direction, hot)
            if self.netTimeSentToStartByHit < timestamp:
                self.netTimeSentToStartByHit = timestamp
        else:
            self.notify.debug(
                'respondToPieHit self.netTimeSentToStartByHit = %s' %
                self.netTimeSentToStartByHit)

    def clearHitInterval(self):
        if self.hitInterval is not None and self.hitInterval.isPlaying():
            self.hitInterval.clearToInitial()
        return

    def __showSplat(self, position, direction, hot=False):
        if self.kaboomTrack is not None and self.kaboomTrack.isPlaying():
            self.kaboomTrack.finish()
        self.clearHitInterval()
        splatName = 'splat-creampie'
        self.splat = globalPropPool.getProp(splatName)
        self.splat.setBillboardPointEye()
        self.splat.reparentTo(render)
        self.splat.setPos(self.root, position)
        self.splat.setAlphaScale(1.0)
        if not direction == 1.0:
            self.splat.setColorScale(PartyGlobals.CogActivitySplatColors[0])
            if self.currentFacing > 0.0:
                facing = 'HitFront'
            else:
                facing = 'HitBack'
        else:
            self.splat.setColorScale(PartyGlobals.CogActivitySplatColors[1])
            if self.currentFacing > 0.0:
                facing = 'HitBack'
            else:
                facing = 'HitFront'
        if hot:
            targetscale = 0.75
            part = 'head'
        else:
            targetscale = 0.5
            part = 'body'

        def setSplatAlpha(amount):
            self.splat.setAlphaScale(amount)

        self.hitInterval = Sequence(
            ActorInterval(self.actor, part + facing, loop=0),
            Func(self.actor.loop, 'idle'))
        self.hitInterval.start()
        self.kaboomTrack = Parallel(
            SoundInterval(self.pieHitSound,
                          volume=1.0,
                          node=self.actor,
                          cutOff=PartyGlobals.PARTY_COG_CUTOFF),
            Sequence(
                Func(self.splat.showThrough),
                Parallel(
                    Sequence(
                        LerpScaleInterval(self.splat,
                                          duration=0.175,
                                          scale=targetscale,
                                          startScale=Point3(0.1, 0.1, 0.1),
                                          blendType='easeOut'), Wait(0.175)),
                    Sequence(
                        Wait(0.1),
                        LerpFunc(setSplatAlpha,
                                 duration=1.0,
                                 fromData=1.0,
                                 toData=0.0,
                                 blendType='easeOut'))),
                Func(self.splat.cleanup), Func(self.splat.removeNode)))
        self.kaboomTrack.start()
        return

    def showHitScore(self, number, scale=1):
        if number <= 0:
            return
        if self.hpText:
            self.hideHitScore()
        self.HpTextGenerator.setFont(ToontownGlobals.getSignFont())
        if number < 0:
            self.HpTextGenerator.setText(str(number))
        else:
            self.HpTextGenerator.setText('+' + str(number))
        self.HpTextGenerator.clearShadow()
        self.HpTextGenerator.setAlign(TextNode.ACenter)
        r = 1
        g = 1
        b = 0
        a = 1
        self.HpTextGenerator.setTextColor(r, g, b, a)
        self.hpTextNode = self.HpTextGenerator.generate()
        self.hpText = render.attachNewNode(self.hpTextNode)
        self.hpText.setScale(scale)
        self.hpText.setBillboardPointEye()
        self.hpText.setBin('fixed', 100)
        self.hpText.setPos(self.root, 0, 0, self.height / 2)
        seq = Task.sequence(
            self.hpText.lerpPos(Point3(
                self.root.getX(render), self.root.getY(render),
                self.root.getZ(render) + self.height + 1.0),
                                0.25,
                                blendType='easeOut'), Task.pause(0.25),
            self.hpText.lerpColor(Vec4(r, g, b, a), Vec4(r, g, b, 0), 0.1),
            Task.Task(self.__hideHitScoreTask))
        taskMgr.add(seq, 'PartyCogHpText' + str(self.id))

    def __hideHitScoreTask(self, task):
        self.hideHitScore()
        return Task.done

    def hideHitScore(self):
        if self.hpText:
            taskMgr.remove('PartyCogHpText' + str(self.id))
            self.hpText.removeNode()
            self.hpText = None
        return

    def getHeadLocation(self):
        self.actor.getJoints(jointName='head')[0].getNetTransform(
            self.temp_transform)
        self.head_locator.setMat(self.temp_transform)
        return self.head_locator.getZ(self.root)
Beispiel #57
0
class Enemy3(object):
    def __init__(self,game,spawnloc = (0,0,0),name = "Enemy-0-0"):
        self.health = 20
        self.value = 2000
        self.maxspeed = 10
        
        self.name = name
        
        # Load the enemy model and set the initial position of it
        self.loadModel()
        self.actor.setPos(spawnloc)
        self.enemy_start_pos = spawnloc
        self.safepos = (0,0,0)
        
        #Set the clock stuff
        self.dt = game.player.dt
        
        self.cTrav = CollisionTraverser()
        
        # Enemy Rays
        self.ralphGroundRay = CollisionRay()
        self.ralphGroundRay.setOrigin(0,0,100)
        self.ralphGroundRay.setDirection(0,0,-1)
        self.ralphGroundCol = CollisionNode('ralphRay')
        self.ralphGroundCol.addSolid(self.ralphGroundRay)
        self.ralphGroundCol.setFromCollideMask(BitMask32.bit(0))
        self.ralphGroundCol.setIntoCollideMask(BitMask32.allOff())
        self.ralphGroundColNp = self.actor.attachNewNode(self.ralphGroundCol)
        self.ralphGroundHandler = CollisionHandlerQueue()
        self.cTrav.addCollider(self.ralphGroundColNp, self.ralphGroundHandler)
        #self.ralphGroundColNp.show()
        
        self.pursue_start = False
        self.evade_start = False
        self.timer = 300
        self.fire_rate = 60
        
        # Collision stuff for bullets
        #self.cTrav = CollisionTraverser()
        self.cHandler = CollisionHandlerQueue()
        self.cSphere = CollisionSphere(0,0,4, 8)
        self.cNode = CollisionNode("Enemy")
        self.cNodePath = self.actor.attachNewNode(self.cNode)
        self.cNodePath.node().addSolid(self.cSphere)
        #self.cNodePath.show()
        self.cTrav.addCollider(self.cNodePath, self.cHandler)
        
        #self.heightTask = taskMgr.add(self.updateHeight,'EnemyHeight',extraArgs=[game])
    
    def take_damage(self, damage):
        """
            Cause an enemy to take damage.
            Negative health means object is immortal (negative damage kills anything instantly)
        """
        if damage < 0:
            self.health = 0
            return self.value
        if self.health > 0:
            self.health -= damage
            if self.health <= 0:
                self.health = 0
                return self.value
        return 0
        
    def loadModel(self):
        self.actor = Actor("models/hummer",{'tread':'models/hummer'})
        self.actor.setPlayRate(2.0,'tread')
        self.actor.setH(self.actor.getH() - 90)
        self.actor.reparentTo(render)
        self.actor.setScale(0.25)
        
    def distanceToTarget(self):
        return math.sqrt((self.actor.getX() - self.target.getX())**2 + (self.actor.getY() - self.target.getY())**2 )#+ (self.actor.getZ() - self.target.getZ()))
     
    def setupAI(self, target):
        """ Start the enemy's AI """
        self.target = target
        self.AIchar = AICharacter(self.name,self.actor,100,0.5,self.maxspeed)
        self.AIbehaviors = self.AIchar.getAiBehaviors()
        self.AIbehaviors.evade(self.target,2,10,1.0)
        self.AIbehaviors.pursue(self.target,1.0)
        self.AIbehaviors.wander(4,3,100,0.5)
        self.pause_e()
        self.resume_e()
        self.actor.loop("tread")
        return self.AIchar
        
    def updateAI(self,game):
        self.pause_e()
        if self.distanceToTarget() > 40 or self.pursue_start:
            self.pursue_start = True
            self.evade_start = False
            self.AIbehaviors.pursue(game.player.actor,1.0)
        else:
            self.pursue_start = False
            self.evade_start = True
            self.AIbehaviors.flee(game.player.actor,30,10,0.5)
            
        if self.distanceToTarget() <= 14:
            self.pursue_start = False
        if self.distanceToTarget() > 100:
            self.evade_start = False
            
        self.resume_e()
            
    def updateHeight(self,game):
        startpos = self.actor.getPos()
        self.updateAI(game)
        self.fire(game)
        self.cTrav.traverse(render)
        entries = []
        for i in range(self.ralphGroundHandler.getNumEntries()):
            entry = self.ralphGroundHandler.getEntry(i)
            if entry.getIntoNode().getName() != "Enemy":
                entries.append(entry)
        entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(),
                                     x.getSurfacePoint(render).getZ()))
        if (len(entries)>0) and (entries[0].getIntoNode().getName() == "terrain"):
            self.actor.setZ(entries[0].getSurfacePoint(render).getZ()+0)
            self.safepos = self.actor.getPos()
        else:
            self.actor.setPos(self.safepos)
        
        self.actor.setHpr(self.actor.getH(),0,0)
        self.actor.setH(self.actor.getH() - 90)
        
        # Check boundaries and bullets
        for i in range(self.cHandler.getNumEntries()):
            entry = self.cHandler.getEntry(i)
            if entry.getIntoNode().getName() == "fence_c" or entry.getIntoNode().getName() == "debris":
                self.actor.setPos(self.safepos)
                self.pause_e()
                self.resume_e()
            if entry.getIntoNode().getName() == "ball":
                #print "hit: ball"
                self.health -= 10
            if entry.getIntoNode().getName() == "shotgun_bullet":
                #print "hit: shotgun"
                self.health -= 12
            if entry.getIntoNode().getName() == "mortar":
                #print "hit: mortar"
                self.health -= 20
                
        # Keep enemy within bounds (HACK)
        edge = 43
        if self.actor.getX() > edge:
            self.actor.setPos(edge,self.actor.getY(),self.actor.getZ())
        if self.actor.getX() < -edge:
            self.actor.setPos(-edge,self.actor.getY(),self.actor.getZ())
        if self.actor.getY() < -edge:
            self.actor.setPos(self.actor.getX(),-edge,self.actor.getZ())
        if self.actor.getY() > edge:
            self.actor.setPos(self.actor.getX(),edge,self.actor.getZ())
            
        if self.health <= 0:
            game.score += self.value
            game.explosions_handler.Small_Explosion(self.actor.getPos())
            #self.die()
        
    #AI Controls
    def pause_e(self):
        self.AIbehaviors.pauseAi("pursue")
        self.AIbehaviors.pauseAi("evade")
        self.AIbehaviors.pauseAi("flee")
        self.AIbehaviors.pauseAi("wander")
        
    def resume_e(self):
        self.AIbehaviors.resumeAi("wander")
    
    def fire(self,game):
        # Get the angle between current heading and that looking directly at the player
        h1 = self.actor.getH()
        self.actor.lookAt(game.player.actor)
        h2 = self.actor.getH()
        h = math.fabs(h1 - h2) - 180
        
        # Firing angle and fire rate code
        if math.fabs(h) < 20 and self.timer <= 0:
            ## Put firing code here
            b1 = bullets.Bullet(self,game,True,manoffset=(5,11,2))
            b2 = bullets.Bullet(self,game,True,manoffset=(5,11,2))
            b3 = bullets.Bullet(self,game,True,manoffset=(5,11,2))
            b4 = bullets.Bullet(self,game,True,manoffset=(5,11,2))
            b5 = bullets.Bullet(self,game,True,manoffset=(5,11,2))
            b1.bulletNP.setH(b1.bulletNP.getH() + 90)
            b2.bulletNP.setH(b2.bulletNP.getH() + 90)
            b3.bulletNP.setH(b3.bulletNP.getH() + 90)
            b4.bulletNP.setH(b4.bulletNP.getH() + 90)
            b5.bulletNP.setH(b5.bulletNP.getH() + 90)
            self.timer = self.fire_rate
        else:
            self.timer -= 1
        self.actor.setH(h1)
        hpr = self.actor.getHpr()
        
    def die(self,game):
        game.AIworld.removeAiChar(self.name)
        self.actor.cleanup()
        self.actor.removeNode()
Beispiel #58
0
class GameObject():

    def __init__(self, pos, modelName, modelAnims, maxHealth, maxSpeed, colliderName):
        self.actor = Actor(modelName, modelAnims)
        self.actor.reparentTo(render)
        self.actor.setPos(pos)
        self.maxHealth = maxHealth
        self.health = maxHealth
        self.maxSpeed = maxSpeed
        self.velocity = Vec3(0, 0, 0)
        self.acceleration = 300.0
        self.walking = False
        colliderNode = CollisionNode(colliderName)
        colliderNode.addSolid(CollisionSphere(0, 0, 0, 0.3))
        self.collider = self.actor.attachNewNode(colliderNode)
        self.collider.setPythonTag("owner", self)


    def update(self, dt):
        # If we're going faster than our maximum speed,
        # set the velocity-vector's length to that maximum
        speed = self.velocity.length()

        if speed > self.maxSpeed:
            self.velocity.normalize()
            self.velocity *= self.maxSpeed
            speed = self.maxSpeed

        # If we're walking, don't worry about friction.
        # Otherwise, use friction to slow us down.
        if not self.walking:
            frictionVal = FRICTION*dt
            if frictionVal > speed:
                self.velocity.set(0, 0, 0)
            else:
                frictionVec = -self.velocity
                frictionVec.normalize()
                frictionVec *= frictionVal
                self.velocity += frictionVec

        # Move the character, using our velocity and
        # the time since the last update.
        self.actor.setPos(self.actor.getPos() + self.velocity*dt)



    def alterHealth(self, dHealth):
        self.health += dHealth

        if self.health > self.maxHealth:
            self.health = self.maxHealth

    # Remove various nodes, and clear the Python-tag--see below!
    def cleanup(self):
        if self.collider is not None and not self.collider.isEmpty():
            self.collider.clearPythonTag("owner")
            base.cTrav.removeCollider(self.collider)
            base.pusher.removeCollider(self.collider)

        if self.actor is not None:
            self.actor.cleanup()
            self.actor.removeNode()
            self.actor = None

        self.collider = None
Beispiel #59
0
class Enemy(Creature):
    
    def __init__(self, mainReference, name, position, regionID):
        
        super(Enemy, self).__init__(mainReference)
        
        # unique enemy name
        self.name = name
        
        # If enemy is alive
        self.alive = True
        
        # enemy's pursue speed P-units/s
        self.speed = 2.9
        
        # enemy's rotation speed angles/s
        self.rotSpeed = 10
        
        # enemy's current convex region; for pursue purposes
        self.currentRegionID = regionID
        
        # Hit Points of each part of zombie
        self.hitPoints = {'leg_lr':2, 'leg_ll':2, 'arm_lr':2, 'arm_ll':2}
        self.lifePoints = 100
        
        # enemy NodePath
        self.enemyNP = self.mainRef.render.attachNewNode(self.name)
        self.enemyNP.setPos(position)
        
        # the name of the task the zombie is currently performing
        self.enemyActiveState = ""
        
        self.isEnemyAttacking = False
        
        # the cross point of the portal that the zombie is trying to cross
        self.currentCrossPointGoal = None
        
        # the time that the enemy will spend confused
        self.lostTargetTotalTime = 1.0
        self.lostTargetTimer = self.lostTargetTotalTime
        
        # load our zombie
        self.enemyModel = Actor("../../models/model_zombie/zombie",{
                                'walk':'../../models/model_zombie/zombie-walk',
                                'attack':'../../models/model_zombie/zombie-attack',
})
        # ****SCALE****
        self.enemyModel.setScale(0.55)
        # ****SCALE****
        
        #enemy's character controller
        self.enemyBody = CharacterBody(self.mainRef, self.enemyNP.getPos(), 0.38, 0.5 )
        self.enemyBody.charBodyNP.reparentTo(self.enemyNP)
        
        # load the zombie's bounding boxes
        self.enemyBB = loader.loadModel("../../models/model_zombie/zombieBB")
        
        global bodyParts      
        bodyParts = ['head', 'leg_ur', 'leg_ul', 'leg_lr', 'leg_ll', 'torso', 'arm_ur', 'arm_ul', 'arm_lr', 'arm_ll']
        
        # List of the bullet nodes for this enemy, to be removed later
        self.bulletNodes = {}
        self.partNodes = {}
        # Get Joints
        self.joints = {}
        
        #for bodyPart in ['leg_lr', 'leg_ll', 'arm_lr', 'arm_ll']:
        #    # Get joint control structure
        #    self.joints[bodyPart] = self.enemyModel.controlJoint(None, 'modelRoot', bodyPart)
        
        # getting 1 by 1 and attaching them to their corresponding bones     
        for bodyPart in bodyParts:
            
            self.bodyPartShape = BulletConvexHullShape()
            self.bodyPartShape.addGeom(self.enemyBB.getChild(0).find(bodyPart).node().getGeom(0))
            
            self.bulletbodyPartNode = BulletRigidBodyNode(bodyPart+"_"+name)
            self.bulletbodyPartNode.addShape(self.bodyPartShape)
            self.bodyPartNode = self.mainRef.render.attachNewNode(self.bulletbodyPartNode)
            # ****SCALE****
            self.bodyPartNode.setScale(0.55)
            # ****SCALE****
            
            self.mainRef.world.attachRigidBody(self.bulletbodyPartNode)
            self.bodyPartNode.setCollideMask( BitMask32.bit( 2 ) )
       
            self.bodyPartNode.wrtReparentTo(self.enemyModel.exposeJoint(None,"modelRoot",bodyPart))
            
            self.bulletNodes[bodyPart] = self.bulletbodyPartNode
            self.partNodes[bodyPart] = self.bodyPartNode
            # uncomment to use triangleMesh instead of convexHull
#            mesh = BulletTriangleMesh()
#            mesh.addGeom(self.enemyBB.getChild(0).find(bodyPart).node().getGeom(0))
#            self.bodyPartShape = BulletTriangleMeshShape(mesh, dynamic=True)
#            
#            self.bulletbodyPartNode = BulletRigidBodyNode(bodyPart)
#            self.bulletbodyPartNode.addShape(self.bodyPartShape)
#            
#            self.bodyPartNode = self.mainRef.render.attachNewNode(self.bulletbodyPartNode)
#            self.mainRef.world.attachRigidBody(self.bulletbodyPartNode)
#       
#            self.bodyPartNode.wrtReparentTo(self.enemyModel.exposeJoint(None,"modelRoot",bodyPart))

        # initial path must be calculated
        self.updatePath()
        
        # adding a task to check if the enemy is leaving their region
        self.checkIfChangedRegionName = self.name + "cicr"
        self.oldPosition = self.enemyNP.getPos()
        taskMgr.add(self.checkIfChangedRegion, self.checkIfChangedRegionName)
        
        # walk loop
#        self.enemyModel.loop("walk")
        self.enemyModel.loop("walk")
        
        # attaching to render
        self.enemyModel.reparentTo(self.enemyNP)
        self.enemyModel.setPos(0,0,-0.51)
        
        # loading enemy roar sound
        zombieRoar = [None,None,None,None]
        for i in range( len(zombieRoar) ):
            zombieRoar[i] = self.mainRef.audio3d.loadSfx('../../sounds/zombie_roar_' + str(i+1) + '.mp3')
        # initialize first zombie roar
        self.zombieRoarFX = zombieRoar[0] 
        self.mainRef.audio3d.attachSoundToObject(self.zombieRoarFX, self.enemyNP)
        self.zombieRoarFX.play()
        # random zombie roar
        def roarSort(task):
            if(self.zombieRoarFX.status() != self.zombieRoarFX.PLAYING):
                random.seed()
                value = random.choice(range(3))
                self.zombieRoarFX = zombieRoar[value]
                self.mainRef.audio3d.attachSoundToObject(self.zombieRoarFX, self.enemyNP)
                self.zombieRoarFX.play()
            return task.again
        self.mainRef.taskMgr.doMethodLater(2, roarSort,self.name+'roar sort')
        
    def hide(self):
        self.enemyModel.hide()
        
    def show(self):
        self.mainRef.world.attachRigidBody(self.enemyBulletNode)
        self.enemyModel.show()
        self.enemyModel.loop("walk")
        
    
    def setNewCourse(self):
        # Simply follow the player
        if (len(self.portalsPathList) == 0):
            taskMgr.remove( self.enemyActiveState )
            self.enemyActiveState = self.name + "pt"
            taskMgr.add(self.pursueTargetStep, self.enemyActiveState)

        
        # Go to the cross point that makes you closer to your target
        elif (self.portalsPathList[0].connectedRegionsIDs[0] == self.mainRef.player.currentRegionID or
              self.portalsPathList[0].connectedRegionsIDs[1] == self.mainRef.player.currentRegionID):
            
            self.setOptimalCrossPoint()
            
            taskMgr.remove( self.enemyActiveState )
            self.enemyActiveState = self.name + "htp"
            taskMgr.add(self.headToPortalStep, self.enemyActiveState)
        
        
        # Go to the middle cross point
        else:
            
            self.currentCrossPointGoal = self.portalsPathList[0].middleCrossPoint
            
            taskMgr.remove( self.enemyActiveState )
            self.enemyActiveState = self.name + "htp"
            taskMgr.add(self.headToPortalStep, self.enemyActiveState)
            
    #                 ======================================================================== 
    #                 ======================== STATE MACHINE METHODS ==========================        
    def pursueTargetStep(self, task):
        if (self.mainRef.player.currentRegionID == self.currentRegionID):
            
            if ( self.mainRef.player.playerNP.getPos(self.enemyNP).length() < 4.0):
                if (not self.isEnemyAttacking):
                    self.speed += 1.0
                    self.isEnemyAttacking = True
                    self.enemyModel.loop("attack")     
                                   
            elif (self.isEnemyAttacking):
                self.speed -= 1.0
                self.isEnemyAttacking = False
                self.enemyModel.loop("walk") 
            
            targetDirection = Vec2( self.mainRef.player.playerNP.getPos(self.enemyNP).getXy() )
            targetDirectionAngle = Vec2(-sin(radians(self.enemyModel.getH())), 
                                         cos(radians(self.enemyModel.getH())) ).signedAngleDeg(targetDirection)

            rotationAngle = targetDirectionAngle * self.rotSpeed * globalClock.getDt()
            self.enemyModel.setH(self.enemyModel.getH() + rotationAngle)

            targetDirection.normalize()
            playerMoveSpeedVec = targetDirection * self.speed * globalClock.getDt()
            self.enemyNP.setPos( self.enemyBody.move(Vec3(playerMoveSpeedVec.getX(), playerMoveSpeedVec.getY(), 0) ) )                
            
            if (abs(rotationAngle) > 120 * globalClock.getDt()):
                self.lostTargetTimer = self.lostTargetTotalTime
                self.enemyActiveState = self.name + "lt"
                taskMgr.add(self.lostTargetStep, self.enemyActiveState)
                return task.done
             
        return task.cont
    
    def lostTargetStep(self, task):
        self.enemyNP.setPos( self.enemyBody.move(Vec3(-sin(radians(self.enemyModel.getH())),
                                                       cos(radians(self.enemyModel.getH())),
                                                        0) * self.speed * globalClock.getDt() ) )
        self.lostTargetTimer -= globalClock.getDt()
        
        if (self.lostTargetTimer < 0):
            self.enemyActiveState = self.name + "rt"
            taskMgr.add(self.recoverTargetStep, self.enemyActiveState) 
            return task.done
        
        return task.cont
        
    def recoverTargetStep(self, task):
        targetDirection = Vec2( self.mainRef.player.playerNP.getPos(self.enemyNP).getXy() )
        targetDirectionAngle = Vec2(-sin(radians(self.enemyModel.getH())), 
                                     cos(radians(self.enemyModel.getH())) ).signedAngleDeg(targetDirection)

        rotationAngle = targetDirectionAngle * self.rotSpeed * globalClock.getDt()
        self.enemyModel.setH(self.enemyModel.getH() + rotationAngle)

        if (abs(targetDirectionAngle) < 5):
            self.enemyActiveState = self.name + "pt"
            taskMgr.add(self.pursueTargetStep, self.enemyActiveState) 
            return task.done
        
        return task.cont
    
    def headToPortalStep(self, task):
        directionVec = Vec3(self.currentCrossPointGoal.getX() - self.enemyNP.getX(),
                            self.currentCrossPointGoal.getY() - self.enemyNP.getY(), 0)
        directionVec.normalize()
        
        targetDirection = Vec2( self.currentCrossPointGoal - self.enemyNP.getPos().getXy() )
        targetDirectionAngle = Vec2(-sin(radians(self.enemyModel.getH())), 
                                     cos(radians(self.enemyModel.getH())) ).signedAngleDeg(targetDirection)

        rotationAngle = targetDirectionAngle * self.rotSpeed * globalClock.getDt()
        self.enemyModel.setH(self.enemyModel.getH() + rotationAngle)
        
        self.enemyNP.setPos( self.enemyBody.move( directionVec * self.speed * globalClock.getDt() ) )
        
        return task.cont    
    #              ====================== END OF STATE MACHINE METHODS ========================  
    #              ============================================================================
        
    def destroy(self):
        self.alive = False
        taskMgr.remove(self.name+'roar sort') # removing sound
        for node in self.bulletNodes.keys():
            self.mainRef.world.removeRigidBody(self.bulletNodes[node])
            self.partNodes[node].removeNode()
        taskMgr.remove( self.enemyActiveState ) # removing state machine task 
        self.enemyModel.cleanup()
        self.enemyBB.removeNode()
        self.enemyBody.destroy()

    def detachLimb(self,limb):
        # Detaches a limb from the enemy and makes it drop on the floor
        print "[Detach] Detach %s" % limb
        
#        self.partNodes[limb].wrtReparentTo(self.mainRef.render)
#
#        shape = BulletSphereShape(10.0)
#        node = BulletRigidBodyNode('Sphere')
#        node.setMass(1.0)
#        node.addShape(shape)
#        playerNP = self.mainRef.render.attachNewNode(node)
#        playerNP.setPos(self.enemyModel.exposeJoint(None,"modelRoot",limb).getPos())
#        playerNP.setPos(playerNP.getRelativePoint(self.partNodes[limb],self.partNodes[limb].getPos()))
#        playerNP.setPos(60,0,-60)
#        print playerNP.getRelativePoint(self.partNodes[limb],self.partNodes[limb].getPos())
#        print self.partNodes[limb].getPos()
#        self.mainRef.world.attachRigidBody(node)
#        
#        self.bulletNodes[limb].applyCentralForce(Vec3(0, 0, -5))
#        self.mainRef.world.removeRigidBody(self.bulletNodes[limb])

    def updatePath(self):
        
        convexRegionsList = self.mainRef.map.convexRegions      
        self.portalsPathList = []        # this is what we want for enemy's correct pursue path
        discoveredRegionsList = []     # part of the BFS algorithm
        visitedRegionsList = [False for item in range( len(convexRegionsList))]
        regionFatherList = [None for item in range( len(convexRegionsList))]       # this list keeps track of a region's father AND the portalEntrance connecting them
        
        # from now, we'll execute a BFS to find each region that enemy will cross to reach player's position
        discoveredRegionsList.append( convexRegionsList[self.currentRegionID] )
        visitedRegionsList[self.currentRegionID] = True
        regionFatherList[self.currentRegionID] = [-1, None]
        
        while(discoveredRegionsList):
            
            analisedRegion = discoveredRegionsList.pop(0)
            for portalEntrance in analisedRegion.portalEntrancesList:
                neighbourRegionID = portalEntrance.connectedRegionID
                
                if (not visitedRegionsList[neighbourRegionID]):
                    regionFatherList[neighbourRegionID] = [analisedRegion.regionID, portalEntrance.portal]
                    
                    if (neighbourRegionID == self.mainRef.player.currentRegionID):
                        discoveredRegionsList = [] # break while statement trick          
                        break
                    
                    visitedRegionsList[neighbourRegionID] = True
                    discoveredRegionsList.append( convexRegionsList[neighbourRegionID] )
        
        # now that we have all regions necessary , we'll just put all portals on the correct order
        lastRegionFatherID = self.mainRef.player.currentRegionID
        while (lastRegionFatherID != -1):
            lastRegionFather = regionFatherList[lastRegionFatherID]
            lastRegionFatherID = lastRegionFather[0]
            self.portalsPathList.append(lastRegionFather[1])
        
        # putting portals path on the right order for enemy pursuing algorithm
        self.portalsPathList.pop()  
        self.portalsPathList.reverse()
        
        # Debug
#        print "lista de portais:"
#        for portal in self.portalsPathList:
#            print portal.connectedRegionsIDs

        self.setNewCourse()

    def checkIfChangedRegion(self, task, lastRegion=0):
        
        for portalEntrance in self.mainRef.map.convexRegions[self.currentRegionID].portalEntrancesList:
            
            if ( self.intersect( self.oldPosition, self.enemyNP.getPos(), 
                                 portalEntrance.portal.frontiers[0], portalEntrance.portal.frontiers[1] )
                                 and portalEntrance.portal.connectedRegionsIDs[0] != lastRegion 
                                 and portalEntrance.portal.connectedRegionsIDs[1] != lastRegion ):
                
                oldRegion = self.mainRef.player.currentRegionID
                self.currentRegionID = portalEntrance.connectedRegionID

                
                # Debug
#                print self.name + " region changed: ", oldRegion, ">", self.currentRegionID
                
                # erase last item of portalsPathList (if it isn't empty)
                if (len(self.portalsPathList) != 0):
                    self.portalsPathList.pop(0)
                
                # new course must be calculated if the enemy changed it's region
                self.setNewCourse()
        
        self.oldPosition = self.enemyNP.getPos()
        
        return task.cont        

    def ccw(self, A,B,C):
        return (C.getY()-A.getY())*(B.getX()-A.getX()) > (B.getY()-A.getY())*(C.getX()-A.getX())
    
    def intersect(self, A,B,C,D):
        return self.ccw(A,C,D) != self.ccw(B,C,D) and self.ccw(A,B,C) != self.ccw(A,B,D)



    def setOptimalCrossPoint(self):
        
        deltaPositionVec = self.mainRef.player.playerNP.getPos() - self.enemyNP.getPos()
        positionPoint = self.enemyNP.getPos()
        
        deltaFrontiersVec = self.portalsPathList[0].frontiersVec
        frontierPoint = self.portalsPathList[0].frontiers[0]
        
        if (deltaPositionVec.getX() == 0):
            tang2 = deltaFrontiersVec.getY() / deltaFrontiersVec.getX()
            b2 = frontierPoint.getY() - tang2 * frontierPoint.getX()
            
            xRes = positionPoint.getX()
            yRes = tang2 * xRes + b2
            
            
        if (deltaFrontiersVec.getX() == 0):
            tang1 = deltaPositionVec.getY() / deltaPositionVec.getX()
            b1 = positionPoint.getY() - tang1 * positionPoint.getX()
            
            xRes = frontierPoint.getX()
            yRes = tang1 * xRes + b1
            
        
        else:
            tang1 = deltaPositionVec.getY() / deltaPositionVec.getX()
            tang2 = deltaFrontiersVec.getY() / deltaFrontiersVec.getX()
            
            b1 = positionPoint.getY() - tang1 * positionPoint.getX()
            b2 = frontierPoint.getY() - tang2 * frontierPoint.getX()
            
            xRes = (b1 - b2) / (tang1 - tang2)
            yRes = tang1 * xRes + b1
            
            
        if (deltaFrontiersVec.getX() == 0):
            if ( ( yRes > self.portalsPathList[0].crossPoints[0].getY() and yRes < self.portalsPathList[0].crossPoints[1].getY() ) or
                 ( yRes < self.portalsPathList[0].crossPoints[0].getY() and yRes > self.portalsPathList[0].crossPoints[1].getY() ) ) :
                self.currentCrossPointGoal = Vec2(xRes, yRes)
                
            elif (yRes > self.portalsPathList[0].crossPoints[0].getY() and
                  yRes > self.portalsPathList[0].crossPoints[1].getY() ):
                if ( self.portalsPathList[0].crossPoints[0].getY() > 
                     self.portalsPathList[0].crossPoints[1].getY()):
                    self.currentCrossPointGoal = self.portalsPathList[0].crossPoints[0]
                else:
                    self.currentCrossPointGoal = self.portalsPathList[0].crossPoints[1]
        
            else:
                if ( self.portalsPathList[0].crossPoints[0].getY() < 
                     self.portalsPathList[0].crossPoints[1].getY()):
                    self.currentCrossPointGoal = self.portalsPathList[0].crossPoints[0]
                else:
                    self.currentCrossPointGoal = self.portalsPathList[0].crossPoints[1]
         
         
        else:
            if ( ( xRes > self.portalsPathList[0].crossPoints[0].getX() and xRes < self.portalsPathList[0].crossPoints[1].getX() ) or
                 ( xRes < self.portalsPathList[0].crossPoints[0].getX() and xRes > self.portalsPathList[0].crossPoints[1].getX() ) ) :
                self.currentCrossPointGoal = Vec2(xRes, yRes)
                
            elif (xRes > self.portalsPathList[0].crossPoints[0].getX() and
                  xRes > self.portalsPathList[0].crossPoints[1].getX()):
                if ( self.portalsPathList[0].crossPoints[0].getX() > 
                     self.portalsPathList[0].crossPoints[1].getX()):
                    self.currentCrossPointGoal = self.portalsPathList[0].crossPoints[0]
                else:
                    self.currentCrossPointGoal = self.portalsPathList[0].crossPoints[1]
        
            else:
                if ( self.portalsPathList[0].crossPoints[0].getX() < 
                     self.portalsPathList[0].crossPoints[1].getX()):
                    self.currentCrossPointGoal = self.portalsPathList[0].crossPoints[0]
                else:
                    self.currentCrossPointGoal = self.portalsPathList[0].crossPoints[1]