Example #1
0
 def __init__(self, powerupType, sourceNode=bs.Node(None)):
     """
     Instantiate with given values.
     See bs.Powerup.powerupType for available type values.
     """
     self.powerupType = powerupType
     self.sourceNode = sourceNode
Example #2
0
 def set_fly_mode(self, val):
     self._fly_mode = val
     if self._fly_mode:
         PLAYER_SPAZ.onMoveUpDown(self, 0)
         PLAYER_SPAZ.onMoveLeftRight(self, 0)
         self.spawn_hold_node()
         node = getattr(self, 'hold_node', None)
         if node is None or not node.exists(): node = bs.Node(None)
         self.node.holdBody = 0
         self.node.holdNode = node
         #self.node.holdBody = 1
     else:
         self.node.holdBody = 0
         self.node.holdNode = bs.Node(None)
         self.delete_hold_node()
         PLAYER_SPAZ.onMoveUpDown(self, 0)
         PLAYER_SPAZ.onMoveLeftRight(self, 0)
    def __init__(self,
                 position=(0, 1, 0),
                 velocity=(0, 0, 0),
                 bombType='plague',
                 blastRadius=2.0,
                 sourcePlayer=None,
                 owner=None):
        bs.Actor.__init__(self)
        factory = self.getFactory()
        self.bombType = 'plague'
        self._exploded = False
        self.blastRadius = self.getActivity().settings["Blast Size"]
        self._explodeCallbacks = []
        self.sourcePlayer = sourcePlayer
        self.hitType = 'explosion'
        self.hitSubType = 'plague'
        if owner is None: owner = bs.Node(None)
        self.owner = owner
        fuseTime = 6000
        sticky = False
        model = factory.bombModel
        rType = 'sharper'
        rScale = 1.8
        materials = (factory.bombMaterial,
                     bs.getSharedObject('objectMaterial'))
        self.node = bs.newNode('bomb',
                               delegate=self,
                               attrs={
                                   'position': position,
                                   'velocity': velocity,
                                   'model': model,
                                   'shadowSize': 0.3,
                                   'colorTexture':
                                   bs.getTexture("powerupCurse"),
                                   'sticky': sticky,
                                   'owner': owner,
                                   'reflection': rType,
                                   'reflectionScale': [rScale],
                                   'materials': materials
                               })
        self.node.addDeathAction(
            bs.WeakCall(self.handleMessage, _BombDiedMessage()))

        sound = bs.newNode('sound',
                           owner=self.node,
                           attrs={
                               'sound': factory.fuseSound,
                               'volume': 0.25
                           })
        self.node.connectAttr('position', sound, 'position')
        bsUtils.animate(self.node, 'fuseLength', {0: 1, fuseTime: 0})
        bs.gameTimer(fuseTime, bs.Call(self.handleMessage, PlagueMessage()))
Example #4
0
    def __init__(self,
                 position=(0, 1, 0),
                 velocity=(0, 0, 0),
                 bombType='normal',
                 blastRadius=2.0,
                 sourcePlayer=None,
                 owner=None):
        bs.Actor.__init__(self)
        factory = self.getFactory()
        self.bombType = 'ball'
        self._exploded = False
        self.blastRadius = blastRadius
        self.blastRadius *= 1.45
        self._explodeCallbacks = []
        self.sourcePlayer = sourcePlayer
        self.hitType = 'explosion'
        self.hitSubType = self.bombType

        if owner is None:
            owner = bs.Node(None)

        self.owner = owner
        materials = (factory.bombMaterial,
                     bs.getSharedObject('footingMaterial'),
                     bs.getSharedObject('objectMaterial'))
        materials = materials + (factory.normalSoundMaterial, )

        self.node = bs.newNode('prop',
                               delegate=self,
                               attrs={
                                   'position': position,
                                   'velocity': velocity,
                                   'model': bs.getModel('frostyPelvis'),
                                   'body': 'sphere',
                                   'shadowSize': 0.5,
                                   'colorTexture': bs.getTexture('bunnyColor'),
                                   'reflection': 'soft',
                                   'reflectionScale': [0.25],
                                   'materials': materials
                               })
 def __init__(self,
              position=(0, 1, 0),
              velocity=(0, 0, 0),
              bombType='normal',
              blastRadius=2.0,
              sourcePlayer=None,
              owner=None):
     bs.Actor.__init__(self)
     self.up = False
     factory = BasketBallFactory()
     self.bombType = 'basketball'
     self._exploded = False
     self.blastRadius = blastRadius
     self._explodeCallbacks = []
     self.sourcePlayer = sourcePlayer
     self.hitType = 'impact'
     self.hitSubType = 'basketball'
     owner = bs.Node(None)
     self.owner = owner
     materials = (factory.bombMaterial,
                  bs.getSharedObject('objectMaterial'))
     materials = materials + (factory.normalSoundMaterial, )
     materials = materials + (factory.basketBallMaterial, )
     self.node = bs.newNode('prop',
                            delegate=self,
                            attrs={
                                'position': position,
                                'velocity': velocity,
                                'body': 'sphere',
                                'model': factory.bombModel,
                                'shadowSize': 0.3,
                                'colorTexture':
                                bs.getTexture('bonesColorMask'),
                                'reflection': 'soft',
                                'reflectionScale': [1.5],
                                'materials': materials
                            })
     bsUtils.animate(self.node, "modelScale", {0: 0, 200: 1.3, 260: 1})
    def __init__(self, powerupType, sourceNode=bs.Node(None)):

        self.powerupType = powerupType
        self.sourceNode = sourceNode
Example #7
0
    def __init__(self, position=(0,1,0), velocity=(0,0,0), bombType='normal',
                 blastRadius=1.8, sourcePlayer=None, owner=None):
        """
        Create a new Bomb.
        
        bombType can be 'ice','impact','landMine','normal','sticky', or 'tnt'.
        Note that for impact or landMine bombs you have to call arm()
        before they will go off.
        """
        bs.Actor.__init__(self)

        factory = self.getFactory()

        if not bombType in ('ice','impact','landMine','normal','sticky','tnt', 'atom'): raise Exception("invalid bomb type: " + bombType)
        self.bombType = bombType

        self._exploded = False

        if self.bombType == 'sticky': self._lastStickySoundTime = 0

        self.blastRadius = blastRadius
        if self.bombType == 'ice': self.blastRadius *= 1.0
        elif self.bombType == 'impact': self.blastRadius *= 1.2
        elif self.bombType == 'landMine': self.blastRadius *= 0.7
        elif self.bombType == 'tnt': self.blastRadius *= 1.75
        elif self.bombType == 'atom' : self.blastRadius *= 3.0
        self._explodeCallbacks = []
        
        # the player this came from
        self.sourcePlayer = sourcePlayer

        # by default our hit type/subtype is our own, but we pick up types of whoever
        # sets us off so we know what caused a chain reaction
        self.hitType = 'explosion'
        self.hitSubType = self.bombType

        # if no owner was provided, use an unconnected node ref
        if owner is None: owner = bs.Node(None)

        # the node this came from
        self.owner = owner

        # adding footing-materials to things can screw up jumping and flying since players carrying those things
        # and thus touching footing objects will think they're on solid ground..
        # perhaps we don't wanna add this even in the tnt case?..
        if self.bombType == 'tnt':
            materials = (factory.bombMaterial, bs.getSharedObject('footingMaterial'), bs.getSharedObject('objectMaterial'))
        else:
            materials = (factory.bombMaterial, bs.getSharedObject('objectMaterial'))
            
        if self.bombType == 'impact': materials = materials + (factory.impactBlastMaterial,)
        elif self.bombType == 'landMine': materials = materials + (factory.landMineNoExplodeMaterial,)

        if self.bombType == 'sticky': materials = materials + (factory.stickyMaterial,)
        else: materials = materials + (factory.normalSoundMaterial,)

        if self.bombType == 'landMine':
            self.node = bs.newNode('prop',
                                   delegate=self,
                                   attrs={'position':position,
                                          'velocity':velocity,
                                          'model':factory.landMineModel,
                                          'lightModel':factory.landMineModel,
                                          'body':'landMine',
                                          'shadowSize':0.44,
                                          'colorTexture':factory.landMineTex,
                                          'reflection':'powerup',
                                          'reflectionScale':[1.0],
                                          'materials':materials})

        elif self.bombType == 'tnt':
            self.node = bs.newNode('prop',
                                   delegate=self,
                                   attrs={'position':position,
                                          'velocity':velocity,
                                          'model':factory.tntModel,
                                          'lightModel':factory.tntModel,
                                          'body':'crate',
                                          'shadowSize':0.5,
                                          'colorTexture':factory.tntTex,
                                          'reflection':'soft',
                                          'reflectionScale':[0.23],
                                          'materials':materials})
            
        elif self.bombType == 'impact':
            fuseTime = 20000
            self.node = bs.newNode('prop',
                                   delegate=self,
                                   attrs={'position':position,
                                          'velocity':velocity,
                                          'body':'sphere',
                                          'model':factory.impactBombModel,
                                          'shadowSize':0.3,
                                          'colorTexture':factory.impactTex,
                                          'reflection':'powerup',
                                          'reflectionScale':[1.5],
                                          'materials':materials})
            self.armTimer = bs.Timer(200,bs.WeakCall(self.handleMessage, ArmMessage()))
            self.warnTimer = bs.Timer(fuseTime-1700,bs.WeakCall(self.handleMessage, WarnMessage()))
        elif self.bombType == 'atom':
            fuseTime = 20000
            self.node = bs.newNode('prop',
                                   delegate=self,
                                   attrs={'position':position,
                                          'velocity':velocity,
                                          'body':'sphere',
                                          'model':factory.impactBombModel,
                                          'shadowSize':1.0,
                                          'colorTexture':factory.atomTex,
                                          'reflection':'powerup',
                                          'reflectionScale':[2.5],
                                          'materials':materials})
            self.armTimer = bs.Timer(200,bs.WeakCall(self.handleMessage, ArmMessage()))
            self.warnTimer = bs.Timer(fuseTime-1700,bs.WeakCall(self.handleMessage, WarnMessage()))
        else:
            fuseTime = 3000
            if self.bombType == 'sticky':
                sticky = True
                model = factory.stickyBombModel
                rType = 'sharper'
                rScale = 1.8
            else:
                sticky = False
                model = factory.bombModel
                rType = 'sharper'
                rScale = 1.8
            if self.bombType == 'ice': tex = factory.iceTex
            elif self.bombType == 'sticky': tex = factory.stickyTex
            else: tex = factory.regularTex
            self.node = bs.newNode('bomb',
                                   delegate=self,
                                   attrs={'position':position,
                                          'velocity':velocity,
                                          'model':model,
                                          'shadowSize':0.3,
                                          'colorTexture':tex,
                                          'sticky':sticky,
                                          'owner':owner,
                                          'reflection':rType,
                                          'reflectionScale':[rScale],
                                          'materials':materials})

            sound = bs.newNode('sound',owner=self.node,attrs={'sound':factory.fuseSound,'volume':0.25})
            self.node.connectAttr('position',sound,'position')
            bsUtils.animate(self.node,'fuseLength',{0:1,fuseTime:0})

        # light the fuse!!!
        if self.bombType not in ('landMine','tnt'):
            bs.gameTimer(fuseTime,bs.WeakCall(self.handleMessage, ExplodeMessage()))

        bsUtils.animate(self.node,"modelScale",{0:0, 200:1.3, 260:1})
Example #8
0
    def handleMessage(self, m):
        if isinstance(m, bs.HitMessage):
            if not self.node.exists():
                return
            if self.node.invincible == True:
                bs.playSound(self.getFactory().blockSound,
                             1.0,
                             position=self.node.position)
                return True

            # if we were recently hit, don't count this as another
            # (so punch flurries and bomb pileups essentially count as 1 hit)
            gameTime = bs.getGameTime()
            if self._lastHitTime is None or gameTime - self._lastHitTime > 1000:
                self._numTimesHit += 1
                self._lastHitTime = gameTime

            mag = m.magnitude * self._impactScale
            velocityMag = m.velocityMagnitude * self._impactScale

            damageScale = 0.22

            # if they've got a shield, deliver it to that instead..
            if self.shield is not None:
                if m.flatDamage:
                    damage = m.flatDamage * self._impactScale
                else:
                    # hit our spaz with an impulse but tell it to only return theoretical damage; not apply the impulse..
                    self.node.handleMessage(
                        "impulse", m.pos[0], m.pos[1], m.pos[2], m.velocity[0],
                        m.velocity[1], m.velocity[2], mag, velocityMag,
                        m.radius, 1, m.forceDirection[0], m.forceDirection[1],
                        m.forceDirection[2])
                    damage = damageScale * self.node.damage

                self.shieldHitPoints -= damage

                self.shield.hurt = 1.0 - self.shieldHitPoints / self.shieldHitPointsMax
                # its a cleaner event if a hit just kills the shield without damaging the player..
                # however, massive damage events should still be able to damage the player..
                # this hopefully gives us a happy medium.
                maxSpillover = 500
                if self.shieldHitPoints <= 0:
                    # fixme - transition out perhaps?..
                    self.shield.delete()
                    self.shield = None
                    bs.playSound(self.getFactory().shieldDownSound,
                                 1.0,
                                 position=self.node.position)
                    # emit some cool lookin sparks when the shield dies
                    t = self.node.position
                    bs.emitBGDynamics(position=(t[0], t[1] + 0.9, t[2]),
                                      velocity=self.node.velocity,
                                      count=random.randrange(20, 30),
                                      scale=1.0,
                                      spread=0.6,
                                      chunkType='spark')

                else:
                    bs.playSound(self.getFactory().shieldHitSound,
                                 0.5,
                                 position=self.node.position)

                # emit some cool lookin sparks on shield hit
                bs.emitBGDynamics(position=m.pos,
                                  velocity=(m.forceDirection[0] * 1.0,
                                            m.forceDirection[1] * 1.0,
                                            m.forceDirection[2] * 1.0),
                                  count=min(30, 5 + int(damage * 0.005)),
                                  scale=0.5,
                                  spread=0.3,
                                  chunkType='spark')

                # if they passed our spillover threshold, pass damage along to spaz
                if self.shieldHitPoints <= -maxSpillover:
                    leftoverDamage = -maxSpillover - self.shieldHitPoints
                    shieldLeftoverRatio = leftoverDamage / damage

                    # scale down the magnitudes applied to spaz accordingly..
                    mag *= shieldLeftoverRatio
                    velocityMag *= shieldLeftoverRatio
                else:
                    return True  # good job shield!
            else:
                shieldLeftoverRatio = 1.0

            if m.flatDamage:
                damage = m.flatDamage * self._impactScale * shieldLeftoverRatio
            else:
                # hit it with an impulse and get the resulting damage
                #bs.screenMessage(str(velocityMag))
                if self.multiplyer > 3.0:
                    # at about 8.0 the physics glitch out
                    velocityMag *= min((3.0 + (self.multiplyer - 3.0) / 4),
                                       7.5)**1.9
                else:
                    velocityMag *= self.multiplyer**1.9
                self.node.handleMessage("impulse", m.pos[0], m.pos[1],
                                        m.pos[2], m.velocity[0], m.velocity[1],
                                        m.velocity[2], mag, velocityMag,
                                        m.radius, 0, m.forceDirection[0],
                                        m.forceDirection[1],
                                        m.forceDirection[2])

                damage = damageScale * self.node.damage
            self.node.handleMessage("hurtSound")

            # play punch impact sound based on damage if it was a punch
            if m.hitType == 'punch' or m.hitType == 'kick':

                self.onPunched(damage)

                # if damage was significant, lets show it
                #if damage > 350: bsUtils.showDamageCount('-'+str(int(damage/10))+"%",m.pos,m.forceDirection)

                # lets always add in a super-punch sound with boxing gloves just to differentiate them
                if m.hitSubType == 'superPunch':
                    bs.playSound(self.getFactory().punchSoundStronger,
                                 1.0,
                                 position=self.node.position)

                if damage > 500:
                    sounds = self.getFactory().punchSoundsStrong
                    sound = sounds[random.randrange(len(sounds))]
                else:
                    sound = self.getFactory().punchSound
                bs.playSound(sound, 1.0, position=self.node.position)

                # throw up some chunks
                bs.emitBGDynamics(position=m.pos,
                                  velocity=(m.forceDirection[0] * 0.5,
                                            m.forceDirection[1] * 0.5,
                                            m.forceDirection[2] * 0.5),
                                  count=min(10, 1 + int(damage * 0.0025)),
                                  scale=0.3,
                                  spread=0.03)

                bs.emitBGDynamics(position=m.pos,
                                  chunkType='sweat',
                                  velocity=(m.forceDirection[0] * 1.3,
                                            m.forceDirection[1] * 1.3 + 5.0,
                                            m.forceDirection[2] * 1.3),
                                  count=min(30, 1 + int(damage * 0.04)),
                                  scale=0.9,
                                  spread=0.28)
                # momentary flash
                hurtiness = damage * 0.003
                hurtiness = min(hurtiness, 750 * 0.003)
                punchPos = (m.pos[0] + m.forceDirection[0] * 0.02,
                            m.pos[1] + m.forceDirection[1] * 0.02,
                            m.pos[2] + m.forceDirection[2] * 0.02)
                flashColor = (1.0, 0.8, 0.4)
                light = bs.newNode("light",
                                   attrs={
                                       'position': punchPos,
                                       'radius': 0.12 + hurtiness * 0.12,
                                       'intensity':
                                       0.3 * (1.0 + 1.0 * hurtiness),
                                       'heightAttenuated': False,
                                       'color': flashColor
                                   })
                bs.gameTimer(60, light.delete)

                flash = bs.newNode("flash",
                                   attrs={
                                       'position': punchPos,
                                       'size': 0.17 + 0.17 * hurtiness,
                                       'color': flashColor
                                   })
                bs.gameTimer(60, flash.delete)

            if m.hitType == 'impact':
                bs.emitBGDynamics(position=m.pos,
                                  velocity=(m.forceDirection[0] * 2.0,
                                            m.forceDirection[1] * 2.0,
                                            m.forceDirection[2] * 2.0),
                                  count=min(10, 1 + int(damage * 0.01)),
                                  scale=0.4,
                                  spread=0.1)

            if self.hitPoints > 0:

                # its kinda crappy to die from impacts, so lets reduce impact damage
                # by a reasonable amount if it'll keep us alive
                if m.hitType == 'impact' and damage > self.hitPoints:
                    # drop damage to whatever puts us at 10 hit points, or 200 less than it used to be
                    # whichever is greater (so it *can* still kill us if its high enough)
                    newDamage = max(damage - 200, self.hitPoints - 10)
                    damage = newDamage

                self.node.handleMessage("flash")
                # if we're holding something, drop it
                if damage > 0.0 and self.node.holdNode.exists():
                    self.node.holdNode = bs.Node(None)
                #self.hitPoints -= damage
                self.multiplyer += min(damage / 2000, 0.15)
                if damage / 2000 > 0.05:
                    self.setScoreText(
                        str(int((self.multiplyer - 1) * 100)) + "%")
                #self.node.hurt = 1.0 - self.hitPoints/self.hitPointsMax
                self.node.hurt = 0.0
                # if we're cursed, *any* damage blows us up
                if self._cursed and damage > 0:
                    bs.gameTimer(
                        50, bs.WeakCall(self.curseExplode, m.sourcePlayer))
                # if we're frozen, shatter.. otherwise die if we hit zero
                #if self.frozen and (damage > 200 or self.hitPoints <= 0):
                #	self.shatter()
                #elif self.hitPoints <= 0:
                #	self.node.handleMessage(bs.DieMessage(how='impact'))

            # if we're dead, take a look at the smoothed damage val
            # (which gives us a smoothed average of recent damage) and shatter
            # us if its grown high enough
            #if self.hitPoints <= 0:
            #	damageAvg = self.node.damageSmoothed * damageScale
            #	if damageAvg > 1000:
            #		self.shatter()
        elif isinstance(m, bs.DieMessage):
            self.oob_effect()
            super(self.__class__, self).handleMessage(m)
        elif isinstance(m, bs.PowerupMessage):
            if m.powerupType == 'health':
                if self.multiplyer > 2:
                    self.multiplyer *= 0.5
                else:
                    self.multiplyer *= 0.75
                self.multiplyer = max(1, self.multiplyer)
                self.setScoreText(str(int((self.multiplyer - 1) * 100)) + "%")
            super(self.__class__, self).handleMessage(m)
        else:
            super(self.__class__, self).handleMessage(m)
Example #9
0
    def __init__(self,
                 position=(0, 1, 0),
                 velocity=(0, 0, 0),
                 bombType='normal',
                 blastRadius=2,
                 sourcePlayer=None,
                 owner=None):
        if not sourcePlayer.isAlive(): return
        bs.Actor.__init__(self)
        factory = self.getFactory()
        if not bombType in ('ice', 'impact', 'landMine', 'normal', 'sticky',
                            'tnt'):
            raise Exception("invalid bomb type: " + bombType)
        self.bombType = bombType
        self._exploded = False
        self.blastRadius = blastRadius
        self._explodeCallbacks = []
        self.sourcePlayer = sourcePlayer
        self.hitType = 'explosion'
        self.hitSubType = self.bombType
        if owner is None: owner = bs.Node(None)
        self.owner = owner
        materials = (factory.bombMaterial,
                     bs.getSharedObject('objectMaterial'))
        materials = materials + (factory.impactBlastMaterial, )
        players = self.getActivity().players
        i = 0
        # This gives each player a unique orb color, made possible by the powerup textures within the game.
        while players[i] != sourcePlayer:
            i += 1
        color = ("powerupIceBombs", "powerupPunch", "powerupStickyBombs",
                 "powerupBomb", "powerupCurse", "powerupHealth",
                 "powerupShield", "powerupLandMines")[i]
        if isinstance(
                self.getActivity().getSession(), bs.TeamsSession
        ):  # unless we're on teams, so we'll overide the color to be the team's color
            if sourcePlayer in self.getActivity().teams[0].players:
                color = "powerupIceBombs"  # for blue
            else:
                color = "powerupPunch"  # for red
        self.node = bs.newNode('prop',
                               delegate=self,
                               attrs={
                                   'position': position,
                                   'velocity': velocity,
                                   'body': 'sphere',
                                   'model': bs.getModel("shield"),
                                   'shadowSize': 0.3,
                                   'density': 1,
                                   'bodyScale': 3,
                                   'colorTexture': bs.getTexture(color),
                                   'reflection': 'soft',
                                   'reflectionScale': [1.5],
                                   'materials': materials
                               })
        self.armTimer = bs.Timer(200,
                                 bs.WeakCall(self.handleMessage, ArmMessage()))
        self.node.addDeathAction(
            bs.WeakCall(self.handleMessage, _BombDiedMessage()))

        bsUtils.animate(self.node, "modelScale", {0: 0, 200: 1.3, 260: 1})
Example #10
0
	def __init__(self, position=(0, 0, 0), velocity=(0, 0, 0), bombType='impact', blastRadius=0.0, sourcePlayer=None, owner=None):
		"""
		Create a new Bomb.

		bombType can be 'ice','impact','landMine','normal','sticky', or 'tnt'.
		Note that for impact or landMine bombs you have to call arm()
		before they will go off.
		"""
		bs.Actor.__init__(self)

		factory = self.getFactory()

		self.bombType = 'impactBomb'

		self._exploded = False

		self.blastRadius = blastRadius

		# TNT
		self.blastRadius *= 0.00

		self._explodeCallbacks = []

		# the player this came from
		self.sourcePlayer = sourcePlayer

		# by default our hit type/subtype is our own, but we pick up types of whoever
		# sets us off so we know what caused a chain reaction
		self.hitType = 'explosion'
		self.hitSubType = self.bombType

		# if no owner was provided, use an unconnected node ref
		if owner is None:
			owner = bs.Node(None)

		# the node this came from
		self.owner = owner


		# TNT
		materials = (factory.bombMaterial, bs.getSharedObject('footingMaterial'), bs.getSharedObject('objectMaterial'))
		materials = materials + (factory.normalSoundMaterial,)
		self._spawnPos = (position[0],position[1]+1.0,position[2])


		self.node = bs.newNode('prop',
							   delegate=self,
							   attrs={'position':self._spawnPos,
									  'velocity':velocity,
									  'model':bs.getModel("shield"),
									  'lightModel':factory.impactBombModel,
									  'body':'sphere',
									  'shadowSize':0.5,
                                      'density':1.0,
                                      'bodyScale':1.0,
									  'colorTexture':bs.getTexture("eggTex2"),
									  'reflection':'soft',
									  'reflectionScale':[0.5],
									  'materials':materials})


		#self.node.extraAcceleration = (0, 40, 0)
		self.heldBy = 0
		self._isDead = False


		bsUtils.animate(self.node, "modelScale", {0:0, 200:0.5, 260:0.27})
    def handleMessage(self, m):
        #print(m)
        #First we copy almost the whole HitMessage handling from bsSpaz, but just to calculate the "damage".
        if isinstance(m, bs.HitMessage):
            boxDamage = 0
            if not self.node.exists(): return
            if self.node.invincible == True:
                bs.playSound(self.getFactory().blockSound,
                             1.0,
                             position=self.node.position)
                return True

            # if we were recently hit, don't count this as another
            # (so punch flurries and bomb pileups essentially count as 1 hit)
            gameTime = bs.getGameTime()
            if self._lastHitTime is None or gameTime - self._lastHitTime > 1000:
                self._numTimesHit += 1
                self._lastHitTime = gameTime

            mag = m.magnitude * self._impactScale
            velocityMag = m.velocityMagnitude * self._impactScale

            damageScale = 0.22

            # if they've got a shield, deliver it to that instead..
            if self.shield is not None:

                if m.flatDamage: damage = m.flatDamage * self._impactScale
                else:
                    # hit our spaz with an impulse but tell it to only return theoretical damage; not apply the impulse..
                    self.node.handleMessage(
                        "impulse", m.pos[0], m.pos[1], m.pos[2], m.velocity[0],
                        m.velocity[1], m.velocity[2], mag, velocityMag,
                        m.radius, 1, m.forceDirection[0], m.forceDirection[1],
                        m.forceDirection[2])
                    damage = damageScale * self.node.damage

                self.shieldHitPoints -= damage

                self.shield.hurt = 1.0 - float(
                    self.shieldHitPoints) / self.shieldHitPointsMax
                # its a cleaner event if a hit just kills the shield without damaging the player..
                # however, massive damage events should still be able to damage the player..
                # this hopefully gives us a happy medium.
                # maxSpillover = 500
                maxSpillover = self.getFactory().maxShieldSpilloverDamage
                if self.shieldHitPoints <= 0:
                    # fixme - transition out perhaps?..
                    self.shield.delete()
                    self.shield = None
                    bs.playSound(self.getFactory().shieldDownSound,
                                 1.0,
                                 position=self.node.position)
                    # emit some cool lookin sparks when the shield dies
                    t = self.node.position
                    bs.emitBGDynamics(position=(t[0], t[1] + 0.9, t[2]),
                                      velocity=self.node.velocity,
                                      count=random.randrange(20, 30),
                                      scale=1.0,
                                      spread=0.6,
                                      chunkType='spark')

                else:
                    bs.playSound(self.getFactory().shieldHitSound,
                                 0.5,
                                 position=self.node.position)

                # emit some cool lookin sparks on shield hit
                bs.emitBGDynamics(position=m.pos,
                                  velocity=(m.forceDirection[0] * 1.0,
                                            m.forceDirection[1] * 1.0,
                                            m.forceDirection[2] * 1.0),
                                  count=min(30, 5 + int(damage * 0.005)),
                                  scale=0.5,
                                  spread=0.3,
                                  chunkType='spark')

                # if they passed our spillover threshold, pass damage along to spaz
                if self.shieldHitPoints <= -maxSpillover:
                    leftoverDamage = -maxSpillover - self.shieldHitPoints
                    shieldLeftoverRatio = leftoverDamage / damage

                    # scale down the magnitudes applied to spaz accordingly..
                    mag *= shieldLeftoverRatio
                    velocityMag *= shieldLeftoverRatio
                else:
                    return True  # good job shield!
            else:
                shieldLeftoverRatio = 1.0

            if m.flatDamage:
                damage = m.flatDamage * self._impactScale * shieldLeftoverRatio
            else:
                # hit it with an impulse and get the resulting damage
                self.node.handleMessage("impulse", m.pos[0], m.pos[1],
                                        m.pos[2], m.velocity[0], m.velocity[1],
                                        m.velocity[2], mag, velocityMag,
                                        m.radius, 0, m.forceDirection[0],
                                        m.forceDirection[1],
                                        m.forceDirection[2])

                damage = damageScale * self.node.damage
            self.node.handleMessage("hurtSound")

            # play punch impact sound based on damage if it was a punch
            if m.hitType == 'punch':

                self.onPunched(damage)

                # if damage was significant, lets show it
                if damage > 350:
                    bsUtils.showDamageCount('-' + str(int(damage / 10)) + "%",
                                            m.pos, m.forceDirection)

                # lets always add in a super-punch sound with boxing gloves just to differentiate them
                if m.hitSubType == 'superPunch':
                    bs.playSound(self.getFactory().punchSoundStronger,
                                 1.0,
                                 position=self.node.position)

                if damage > 500:
                    sounds = self.getFactory().punchSoundsStrong
                    sound = sounds[random.randrange(len(sounds))]
                else:
                    sound = self.getFactory().punchSound
                bs.playSound(sound, 1.0, position=self.node.position)

                # throw up some chunks
                bs.emitBGDynamics(position=m.pos,
                                  velocity=(m.forceDirection[0] * 0.5,
                                            m.forceDirection[1] * 0.5,
                                            m.forceDirection[2] * 0.5),
                                  count=min(10, 1 + int(damage * 0.0025)),
                                  scale=0.3,
                                  spread=0.03)

                bs.emitBGDynamics(position=m.pos,
                                  chunkType='sweat',
                                  velocity=(m.forceDirection[0] * 1.3,
                                            m.forceDirection[1] * 1.3 + 5.0,
                                            m.forceDirection[2] * 1.3),
                                  count=min(30, 1 + int(damage * 0.04)),
                                  scale=0.9,
                                  spread=0.28)
                # momentary flash
                hurtiness = damage * 0.003
                punchPos = (m.pos[0] + m.forceDirection[0] * 0.02,
                            m.pos[1] + m.forceDirection[1] * 0.02,
                            m.pos[2] + m.forceDirection[2] * 0.02)
                flashColor = (1.0, 0.8, 0.4)
                light = bs.newNode("light",
                                   attrs={
                                       'position': punchPos,
                                       'radius': 0.12 + hurtiness * 0.12,
                                       'intensity':
                                       0.3 * (1.0 + 1.0 * hurtiness),
                                       'heightAttenuated': False,
                                       'color': flashColor
                                   })
                bs.gameTimer(60, light.delete)

                flash = bs.newNode("flash",
                                   attrs={
                                       'position': punchPos,
                                       'size': 0.17 + 0.17 * hurtiness,
                                       'color': flashColor
                                   })
                bs.gameTimer(60, flash.delete)

            if m.hitType == 'impact':
                bs.emitBGDynamics(position=m.pos,
                                  velocity=(m.forceDirection[0] * 2.0,
                                            m.forceDirection[1] * 2.0,
                                            m.forceDirection[2] * 2.0),
                                  count=min(10, 1 + int(damage * 0.01)),
                                  scale=0.4,
                                  spread=0.1)

            if self.hitPoints > 0:
                # its kinda crappy to die from impacts, so lets reduce impact damage
                # by a reasonable amount if it'll keep us alive
                if m.hitType == 'impact' and damage > self.hitPoints:
                    # drop damage to whatever puts us at 10 hit points, or 200 less than it used to be
                    # whichever is greater (so it *can* still kill us if its high enough)
                    newDamage = max(damage - 200, self.hitPoints - 10)
                    damage = newDamage

                self.node.handleMessage("flash")
                # if we're holding something, drop it
                if damage > 0.0 and self.node.holdNode.exists():
                    self.node.holdNode = bs.Node(None)
                #################################
                boxDamage = damage
                if bs.getActivity().settings['Hits damage players']:
                    if damage > self.hitPoints:
                        boxDamage = self.hitPoints  #Only take boxes for the remaining health
                        if boxDamage < 0:
                            boxDamage = 0  #might be hitting a corpse
                    self.hitPoints -= damage  #Only take hit points for damage if settings allow
                    self.node.hurt = 1.0 - float(
                        self.hitPoints) / self.hitPointsMax
                # if we're cursed, *any* damage blows us up
                if self._cursed and damage > 0:
                    bs.gameTimer(
                        50, bs.WeakCall(self.curseExplode, m.sourcePlayer))
                # if we're frozen, shatter.. otherwise die if we hit zero
                if self.frozen and (damage > 200 or self.hitPoints <= 0):
                    self.shatter()
                elif self.hitPoints <= 0:
                    self.node.handleMessage(bs.DieMessage(how='impact'))
            # if we're dead, take a look at the smoothed damage val
            # (which gives us a smoothed average of recent damage) and shatter
            # us if its grown high enough
            if self.hitPoints <= 0:
                damageAvg = self.node.damageSmoothed * damageScale
                if damageAvg > 1000:
                    self.shatter()

            #Now calculate the number of boxes to spew.  Idea is to spew half of boxes if damage is 1000 (basically one0shot kill)
            player = self.getPlayer()
            if player.exists():  #Don't spew boxes for hitting a corpse!
                ptot = 0
                for p2 in player.getTeam().players:
                    if p2.exists():
                        ptot += 1
                if (player.getTeam().gameData['score'] / ptot <=
                        2) and boxDamage >= 800:
                    boxes = 1
                else:
                    boxes = int(player.getTeam().gameData['score'] / ptot *
                                boxDamage / 2000)
                if boxes >= player.getTeam().gameData[
                        'score']:  #somehow the team loses more than all theri boxes?
                    boxes = player.getTeam().gameData['score']
                #print([damage, boxes])
                if boxes > 0:
                    player.getTeam().gameData['score'] -= boxes
                    self.setScoreText(str(player.getTeam().gameData['score']),
                                      player.color)
                    bs.gameTimer(
                        50,
                        bs.WeakCall(self.getActivity().spewBoxes,
                                    self.node.position, boxes))
                    if player.getTeam().gameData['score'] == 0:
                        self.handleMessage(bs.DieMessage())
                    self.getActivity()._updateScoreBoard()
            return
        if isinstance(
                m,
                bs.PowerupMessage):  #Have to handle health powerups ourselves
            if m.powerupType == 'health':
                if self._dead: return True
                if self.pickUpPowerupCallback is not None:
                    self.pickUpPowerupCallback(self)
                player = self.getPlayer()
                if player.exists():
                    player.getTeam().gameData['score'] += 1
                    self.getActivity()._updateScoreBoard()
                    self.setScoreText(str(player.getTeam().gameData['score']),
                                      player.color)
                self.node.handleMessage("flash")
                if m.sourceNode.exists():
                    m.sourceNode.handleMessage(bs.PowerupAcceptMessage())
                return True
            else:
                super(self.__class__, self).handleMessage(m)
        else:
            super(self.__class__, self).handleMessage(m)
Example #12
0
    def __init__(self, position=(0,1,0), velocity=(0,0,0), bombType='normal',
                 blastRadius=2.0, sourcePlayer=None, owner=None):
        bs.Actor.__init__(self)

        factory = self.getFactory()

        settings = bs.get_settings()

        if not bombType in ('ice','impact','landMine','normal','sticky','tnt', 'firework', 'killLaKill', 'qq', 'tp', 'poison', 'dirt'):
            raise Exception("invalid bomb type: " + bombType)
        self.bombType = bombType
        self._exploded = False

        if self.bombType == 'sticky': self._lastStickySoundTime = 0

        self.blastRadius = blastRadius
        if self.bombType == 'ice': self.blastRadius *= 1.2
        elif self.bombType == 'qq': self.blastRadius *= 0.9
        elif self.bombType == 'firework': self.blastRadius *= 1.75
        elif self.bombType == 'impact': self.blastRadius *= 0.7
        elif self.bombType == 'killLaKill': self.blastRadius *= 0.945
        elif self.bombType == 'landMine': self.blastRadius *= 0.7
        elif self.bombType == 'tnt': self.blastRadius *= 1.45
        elif self.bombType == 'poison': self.blastRadius *= 1.2

        self._explodeCallbacks = []
        
        # the player this came from
        self.sourcePlayer = sourcePlayer

        # by default our hit type/subtype is our own, but we pick up types of
        # whoever sets us off so we know what caused a chain reaction
        self.hitType = 'explosion'
        self.hitSubType = self.bombType

        # if no owner was provided, use an unconnected node ref
        if owner is None: owner = bs.Node(None)

        # the node this came from
        self.owner = owner

        # adding footing-materials to things can screw up jumping and flying
        # since players carrying those things
        # and thus touching footing objects will think they're on solid ground..
        # perhaps we don't wanna add this even in the tnt case?..
        if self.bombType == 'tnt':
            materials = (factory.bombMaterial,
                         bs.getSharedObject('footingMaterial'),
                         bs.getSharedObject('objectMaterial'))
        else:
            materials = (factory.bombMaterial,
                         bs.getSharedObject('objectMaterial'))
            
        if self.bombType == 'impact':
            materials = materials + (factory.impactBlastMaterial,)
        elif self.bombType == 'qq':
            materials = materials + (factory.impactBlastMaterial,)
        elif self.bombType == 'landMine':
            materials = materials + (factory.landMineNoExplodeMaterial,)

        if self.bombType == 'sticky':
            materials = materials + (factory.stickyMaterial,)
        elif self.bombType not in ['dirt']:
            materials = materials + (factory.normalSoundMaterial,)

        if self.bombType == 'landMine':
            self.node = bs.newNode('prop', delegate=self, attrs={
                'position':position,
                'velocity':velocity,
                'model':factory.landMineModel,
                'lightModel':factory.landMineModel,
                'body':'landMine',
                'shadowSize':0.44,
                'colorTexture':factory.landMineTex,
                'reflection':'powerup',
                'reflectionScale':[1.0],
                'materials':materials})

        elif self.bombType == 'tnt':
            self.node = bs.newNode('prop', delegate=self, attrs={
                'position':position,
                'velocity':velocity,
                'model':factory.tntModel,
                'lightModel':factory.tntModel,
                'body':'crate',
                'shadowSize':0.5,
                'colorTexture':factory.tntTex,
                'reflection':'soft',
                'reflectionScale':[0.23],
                'materials':materials})
            
        elif self.bombType == 'impact':
            fuseTime = 20000
            self.node = bs.newNode('prop', delegate=self, attrs={
                'position':position,
                'velocity':velocity,
                'body':'sphere',
                'model':factory.impactBombModel,
                'shadowSize':0.3,
                'colorTexture':factory.impactTex,
                'reflection':'powerup',
                'reflectionScale':[1.5],
                'materials':materials})
            self.armTimer = bs.Timer(200, bs.WeakCall(self.handleMessage,
                                                      ArmMessage()))
            self.warnTimer = bs.Timer(fuseTime-1700,
                                      bs.WeakCall(self.handleMessage,
                                                  WarnMessage()))

        elif self.bombType == 'dirt':
            fuseTime = 4500
            self.node = bs.newNode('bomb', delegate=self, attrs={
                'position':position,
                'velocity':velocity,
                'body':'sphere',
                'model':factory.stickyBombModel,
                'shadowSize':0.3,
                'colorTexture':factory.poisonTex,
                'reflection':'soft',
                'reflectionScale':(1, 0.4, 0.16),
                'materials':materials})
            sound = bs.newNode('sound', owner=self.node, attrs={
                'sound':factory.fuseSound,
                'volume':0.25})
            self.node.connectAttr('position', sound, 'position')
            bsUtils.animate(self.node, 'fuseLength', {0:1.0, fuseTime:0.0})
            
        elif self.bombType == 'firework':
            fuseTime = 4500
            self.node = bs.newNode('prop', delegate=self, attrs={
                'position':position,
                'velocity':velocity,
                'body':'crate',
                'bodyScale':0.9,
                'model':factory.fireworkModel,
                'shadowSize':0.3,
                'colorTexture':factory.fireworkTex,
                'reflection':'soft',
                'reflectionScale':[0.23],
                'materials':materials})

        elif self.bombType == 'killLaKill':
            fuseTime = 3000
            self.node = bs.newNode('bomb', delegate=self, attrs={
                'position':position,
                'velocity':velocity,
                'body':'sphere',
                'model':factory.killLaKillModel,
                'shadowSize':0.3,
                'colorTexture':factory.killLaKillTex,
                'reflection':'sharper',
                'reflectionScale':[1.8],
                'materials':materials})
            sound = bs.newNode('sound', owner=self.node, attrs={
                'sound':factory.fuseSound,
                'volume':0.25})
            self.node.connectAttr('position', sound, 'position')
            bsUtils.animate(self.node, 'fuseLength', {0:1.0, fuseTime:0.0})

        elif self.bombType == 'poison':
            fuseTime = 4500
            self.node = bs.newNode('bomb', delegate=self, attrs={
                'position':position,
                'velocity':velocity,
                'body':'sphere',
                'model':factory.poisonModel,
                'shadowSize':0.3,
                'colorTexture':factory.poisonTex,
                'reflection':'soft',
                'reflectionScale':(1,1.5,1),
                'materials':materials})
            sound = bs.newNode('sound', owner=self.node, attrs={
                'sound':factory.fuseSound,
                'volume':0.25})
            self.node.connectAttr('position', sound, 'position')
            bsUtils.animate(self.node, 'fuseLength', {0:1.0, fuseTime:0.0})
              
        elif self.bombType == 'tp':
            fuseTime = 3000
            self.node = bs.newNode('bomb', delegate=self, attrs={
                'position':position,
                'velocity':velocity,
                'body':'sphere',
                'model':factory.tpModel,
                'shadowSize':0.3,
                'colorTexture':factory.tpTex,
                'reflection':'sharper',
                'reflectionScale':(0,1.8,0.68),
                'materials':materials})
            sound = bs.newNode('sound', owner=self.node, attrs={
                'sound':factory.fuseSound,
                'volume':0.25})
            self.node.connectAttr('position', sound, 'position')
            bsUtils.animate(self.node, 'fuseLength', {0:1.0, fuseTime:0.0})

        elif self.bombType == 'qq':
            fuseTime = 4500
            self.node = bs.newNode('bomb', delegate=self, attrs={
                'position':position,
                'velocity':velocity,
                'body':'sphere',
                'bodyScale':0.775,
                'density':1.772,
                'model':factory.qqModel,
                'shadowSize':0.3,
                'colorTexture':factory.qqTex,
                'owner':owner,
                'reflection':'sharper',
                'reflectionScale':[1.2],
                'materials':materials})
            sound = bs.newNode('sound', owner=self.node, attrs={
                'sound':factory.fuseSound,
                'volume':0.25})
            self.node.connectAttr('position', sound, 'position')
            bsUtils.animate(self.node, 'fuseLength', {0:1.0, fuseTime:0.0})
            bs.gameTimer(4320, bs.WeakCall(self.handleMessage, bs.DieMessage()))
            bs.gameTimer(4319, bs.Call(self.explode))
        else:
            fuseTime = 3000
            if self.bombType == 'sticky':
                sticky = True
                model = factory.stickyBombModel
                rType = 'sharper'
                rScale = 1.8
            else:
                sticky = False
                model = factory.bombModel
                rType = 'sharper'
                rScale = 1.8
            if self.bombType == 'ice': tex = factory.iceTex
            elif self.bombType == 'sticky': tex = factory.stickyTex
            else: tex = factory.regularTex
            self.node = bs.newNode('bomb', delegate=self, attrs={
                'position':position,
                'velocity':velocity,
                'model':model,
                'shadowSize':0.3,
                'colorTexture':tex,
                'sticky':sticky,
                'owner':owner,
                'reflection':rType,
                'reflectionScale':[rScale],
                'materials':materials})

            sound = bs.newNode('sound', owner=self.node, attrs={
                'sound':factory.fuseSound,
                'volume':0.25})
            self.node.connectAttr('position', sound, 'position')
            bsUtils.animate(self.node, 'fuseLength', {0:1.0, fuseTime:0.0})

        # light the fuse!!!
        if (self.bombType not in ('landMine','tnt')):
            bs.gameTimer(fuseTime, bs.WeakCall(self.handleMessage, ExplodeMessage()))
            if settings.get("timer_before_the_bomb_explode", True):
                m = bs.newNode('math', attrs={'input1': (0, 0.45, 0), 'operation': 'add'})
                self.node.connectAttr('position', m, 'input2')
                self._timer = bs.newNode('text', owner=self.node, attrs={
                    'text': '( )',
                    'position': (0, 0, 0),
                    'color': (0,3,0),
                    'scale': 0,
                    'inWorld': True,
                    'hAlign': 'center'})
                m.connectAttr('output', self._timer, 'position')        
                bsUtils.animate(self._timer, 'scale', {0: 0.0, 240: 0.009})
                bsUtils.animateArray(self._timer, 'color',3, {0: (0,3,0), fuseTime: (3,0,0)}, False)
        if self.bombType == 'firework': bsUtils.animate(self.node,"modelScale",{0:0, 200:0.85, 260:0.8})
        else: bsUtils.animate(self.node,"modelScale",{0:0, 200:1.3, 260:1})