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