def _preload3() -> None: from bastd.actor.spazfactory import SpazFactory for mname in ['bomb', 'bombSticky', 'impactBomb']: ba.getmodel(mname) for tname in [ 'bombColor', 'bombColorIce', 'bombStickyColor', 'impactBombColor', 'impactBombColorLit' ]: ba.gettexture(tname) for sname in ['freeze', 'fuse01', 'activateBeep', 'warnBeep']: ba.getsound(sname) SpazFactory.get() ba.timer(0.2, _preload4)
def handlemessage(self, msg: Any) -> Any: if isinstance(msg, ba.PlayerDiedMessage): # Augment standard behavior. super().handlemessage(msg) player: Player = msg.getplayer(Player) player.lives -= 1 if player.lives < 0: ba.print_error( "Got lives < 0 in Elim; this shouldn't happen. duo: True") player.lives = 0 # If we have any icons, update their state. for icon in player.icons: icon.handle_player_died() # Play big death sound on our last death # or for every one in solo mode. if player.lives == 0: ba.playsound(SpazFactory.get().single_player_death_sound) # If we hit zero lives, we're dead (and our team might be too). if player.lives == 0: # If the whole team is now dead, mark their survival time. if self._get_total_team_lives(player.team) == 0: assert self._start_time is not None player.team.survival_seconds = int(ba.time() - self._start_time) # In solo, put ourself at the back of the spawn order. if self._duo_mode: player.team.spawn_order.remove(player) player.team.spawn_order.append(player)
def handlemessage(self, msg: Any) -> Any: if isinstance(msg, ba.PlayerDiedMessage): #== losingPlayer = msg.getplayer(Player) if len(self.myPlayers) > 1: if self.playerFromName(self.myPlayers[self.count - 2]) == losingPlayer: winningPlayer = self.playerFromName( self.myPlayers[self.count - 1]) else: winningPlayer = self.playerFromName( self.myPlayers[self.count - 2]) if str(losingPlayer.getname()) in self.myPlayers: self.myPlayers.remove(str(losingPlayer.getname())) if winningPlayer.team.survival_seconds <= losingPlayer.team.survival_seconds: winningPlayer.team.survival_seconds = losingPlayer.team.survival_seconds + 1 else: winningPlayer.team.survival_seconds += 1 winningPlayer.wins += 1 if winningPlayer.is_alive() and not len(self.myPlayers) == 1: winningPlayer.actor.handlemessage( ba.DieMessage(immediate=True)) self.count -= 1 self.spawnPlayer() #== # Augment standard behavior. super().handlemessage(msg) player: Player = msg.getplayer(Player) player.lives -= 1 if player.lives < 0: ba.print_error("Got lives < 0 in Elim; this shouldn't happen.") player.lives = 0 # If we have any icons, update their state. # Play big death sound on our last death # or for every one in solo mode. if player.lives == 0: ba.playsound(SpazFactory.get().single_player_death_sound) # If we hit zero lives, we're dead (and our team might be too). if player.lives == 0: pass else: self.respawn_player(player)
def handlemessage(self, msg): if isinstance(msg, ba.HitMessage): if not self.node: return None if self.node.invincible: ba.playsound(SpazFactory.get().block_sound, 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) local_time = ba.time(timeformat=ba.TimeFormat.MILLISECONDS) assert isinstance(local_time, int) if (self._last_hit_time is None or local_time - self._last_hit_time > 1000): self._num_times_hit += 1 self._last_hit_time = local_time mag = msg.magnitude * self.impact_scale velocity_mag = msg.velocity_magnitude * self.impact_scale damage_scale = 0.22 # If they've got a shield, deliver it to that instead. if self.shield: if msg.flat_damage: damage = msg.flat_damage * self.impact_scale else: # Hit our spaz with an impulse but tell it to only return # theoretical damage; not apply the impulse. assert msg.force_direction is not None self.node.handlemessage( 'impulse', msg.pos[0], msg.pos[1], msg.pos[2], msg.velocity[0], msg.velocity[1], msg.velocity[2], mag, velocity_mag, msg.radius, 1, msg.force_direction[0], msg.force_direction[1], msg.force_direction[2]) damage = damage_scale * self.node.damage assert self.shield_hitpoints is not None self.shield_hitpoints -= int(damage) self.shield.hurt = ( 1.0 - float(self.shield_hitpoints) / self.shield_hitpoints_max) # 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. max_spillover = SpazFactory.get().max_shield_spillover_damage if self.shield_hitpoints <= 0: # FIXME: Transition out perhaps? self.shield.delete() self.shield = None ba.playsound(SpazFactory.get().shield_down_sound, 1.0, position=self.node.position) # Emit some cool looking sparks when the shield dies. npos = self.node.position ba.emitfx(position=(npos[0], npos[1] + 0.9, npos[2]), velocity=self.node.velocity, count=random.randrange(20, 30), scale=1.0, spread=0.6, chunk_type='spark') else: ba.playsound(SpazFactory.get().shield_hit_sound, 0.5, position=self.node.position) # Emit some cool looking sparks on shield hit. assert msg.force_direction is not None ba.emitfx(position=msg.pos, velocity=(msg.force_direction[0] * 1.0, msg.force_direction[1] * 1.0, msg.force_direction[2] * 1.0), count=min(30, 5 + int(damage * 0.005)), scale=0.5, spread=0.3, chunk_type='spark') # If they passed our spillover threshold, # pass damage along to spaz. if self.shield_hitpoints <= -max_spillover: leftover_damage = -max_spillover - self.shield_hitpoints shield_leftover_ratio = leftover_damage / damage # Scale down the magnitudes applied to spaz accordingly. mag *= shield_leftover_ratio velocity_mag *= shield_leftover_ratio else: return True # Good job shield! else: shield_leftover_ratio = 1.0 if msg.flat_damage: damage = int(msg.flat_damage * self.impact_scale * shield_leftover_ratio) else: # Hit it with an impulse and get the resulting damage. assert msg.force_direction is not None if self.multiplyer > 3.0: # at about 8.0 the physics glitch out velocity_mag *= min((3.0 + (self.multiplyer - 3.0) / 4), 7.5)**1.9 else: velocity_mag *= self.multiplyer**1.9 self.node.handlemessage( 'impulse', msg.pos[0], msg.pos[1], msg.pos[2], msg.velocity[0], msg.velocity[1], msg.velocity[2], mag, velocity_mag, msg.radius, 0, msg.force_direction[0], msg.force_direction[1], msg.force_direction[2]) damage = int(damage_scale * self.node.damage) self.node.handlemessage('hurt_sound') # Play punch impact sound based on damage if it was a punch. if msg.hit_type == 'punch': self.on_punched(damage) # If damage was significant, lets show it. if damage > 350: assert msg.force_direction is not None ba.show_damage_count('-' + str(int(damage / 10)) + '%', msg.pos, msg.force_direction) # Let's always add in a super-punch sound with boxing # gloves just to differentiate them. if msg.hit_subtype == 'super_punch': ba.playsound(SpazFactory.get().punch_sound_stronger, 1.0, position=self.node.position) if damage > 500: sounds = SpazFactory.get().punch_sound_strong sound = sounds[random.randrange(len(sounds))] else: sound = SpazFactory.get().punch_sound ba.playsound(sound, 1.0, position=self.node.position) # Throw up some chunks. assert msg.force_direction is not None ba.emitfx(position=msg.pos, velocity=(msg.force_direction[0] * 0.5, msg.force_direction[1] * 0.5, msg.force_direction[2] * 0.5), count=min(10, 1 + int(damage * 0.0025)), scale=0.3, spread=0.03) ba.emitfx(position=msg.pos, chunk_type='sweat', velocity=(msg.force_direction[0] * 1.3, msg.force_direction[1] * 1.3 + 5.0, msg.force_direction[2] * 1.3), count=min(30, 1 + int(damage * 0.04)), scale=0.9, spread=0.28) # Momentary flash. hurtiness = damage * 0.003 punchpos = (msg.pos[0] + msg.force_direction[0] * 0.02, msg.pos[1] + msg.force_direction[1] * 0.02, msg.pos[2] + msg.force_direction[2] * 0.02) flash_color = (1.0, 0.8, 0.4) light = ba.newnode('light', attrs={ 'position': punchpos, 'radius': 0.12 + hurtiness * 0.12, 'intensity': 0.3 * (1.0 + 1.0 * hurtiness), 'height_attenuated': False, 'color': flash_color }) ba.timer(0.06, light.delete) flash = ba.newnode('flash', attrs={ 'position': punchpos, 'size': 0.17 + 0.17 * hurtiness, 'color': flash_color }) ba.timer(0.06, flash.delete) if msg.hit_type == 'impact': assert msg.force_direction is not None ba.emitfx(position=msg.pos, velocity=(msg.force_direction[0] * 2.0, msg.force_direction[1] * 2.0, msg.force_direction[2] * 2.0), count=min(10, 1 + int(damage * 0.01)), scale=0.4, spread=0.1) if self.hitpoints > 0: self.multiplyer += min(damage / 2000, 0.15) self.set_score_text( str(int((self.multiplyer - 1) * 100)) + "%") # It's kinda crappy to die from impacts, so lets reduce # impact damage by a reasonable amount *if* it'll keep us alive if msg.hit_type == '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.hold_node: self.node.hold_node = None # self.hitpoints -= damage self.node.hurt = 1.0 - float( self.hitpoints) / self.hitpoints_max # If we're cursed, *any* damage blows us up. if self._cursed and damage > 0: ba.timer( 0.05, ba.WeakCall(self.curse_explode, msg.get_source_player(ba.Player))) # 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( ba.DieMessage(how=ba.DeathType.IMPACT)) # If we're dead, take a look at the smoothed damage value # (which gives us a smoothed average of recent damage) and shatter # us if its grown high enough. if self.hitpoints <= 0: damage_avg = self.node.damage_smoothed * damage_scale if damage_avg > 1000: self.shatter() return None elif isinstance(msg, ba.PowerupMessage): if msg.poweruptype == 'health': if self.multiplyer > 2: self.multiplyer *= 0.5 else: self.multiplyer *= 0.75 self.multiplyer = max(1, self.multiplyer) self.set_score_text( str(int((self.multiplyer - 1) * 100)) + "%") super().handlemessage(msg) return None