def _apply(name2: Lstr, score2: int, showpoints2: bool, color2: Tuple[float, float, float, float], scale2: float, sound2: Optional[ba.Sound]) -> None: from bastd.actor.popuptext import PopupText # Only award this if they're still alive and we can get # their pos. if self._player is not None and self._player.node: our_pos = self._player.node.position else: return # Jitter position a bit since these often come in clusters. our_pos = (our_pos[0] + (random.random() - 0.5) * 2.0, our_pos[1] + (random.random() - 0.5) * 2.0, our_pos[2] + (random.random() - 0.5) * 2.0) activity = self.getactivity() if activity is not None: PopupText(Lstr( value=(('+' + str(score2) + ' ') if showpoints2 else '') + '${N}', subs=[('${N}', name2)]), color=color2, scale=scale2, position=our_pos).autoretain() if sound2: _ba.playsound(sound2) self.score += score2 self.accumscore += score2 # Inform a running game of the score. if score2 != 0 and activity is not None: activity.handlemessage(PlayerScoredMessage(score=score2))
def _award_time_bonus(self, bonus: int) -> None: ba.playsound(self._cashregistersound) PopupText(ba.Lstr(value='+${A} ${B}', subs=[('${A}', str(bonus)), ('${B}', ba.Lstr(resource='timeBonusText'))]), color=(1, 1, 0.5, 1), scale=1.0, position=(0, 3, -1)).autoretain() self._score += self._time_bonus self._update_scores()
def _award_lives_bonus(self) -> None: bonus = self._lives * 30 ba.playsound(self._cashregistersound) PopupText(ba.Lstr(value='+${A} ${B}', subs=[('${A}', str(bonus)), ('${B}', ba.Lstr(resource='livesBonusText'))]), color=(0.7, 1.0, 0.3, 1), scale=1.3, position=(0, 1, -1)).autoretain() self._score += bonus self._update_scores()
def _award_flawless_bonus(self) -> None: ba.playsound(self._cashregistersound) PopupText(ba.Lstr(value='+${A} ${B}', subs=[('${A}', str(self._flawless_bonus)), ('${B}', ba.Lstr(resource='perfectWaveText')) ]), color=(1, 1, 0.2, 1), scale=1.2, position=(0, 2, -1)).autoretain() assert self._flawless_bonus is not None self._score += self._flawless_bonus self._update_scores()
def handle_hit(msg, hp, dmg, hit_by, msg_pos): #Check if not msg.hit_type: return #Record Out Data dmg = dmg / 10 if hit_by is not None: hit_by_id = None hit_by_id = hit_by.node.playerID if hit_by_id is not None: hit_by_account_id = None for c in _ba.get_foreground_host_session().sessionplayers: if (c.activityplayer) and (c.activityplayer.node.playerID == hit_by_id): hit_by_account_id = c.get_account_id() if hit_by_account_id in damage_data: damage_data[hit_by_account_id] += float(dmg) else: damage_data[hit_by_account_id] = float(dmg) #Send Screen Texts in enabled if our_settings['enableHitTexts']: try: if hp <= 0: PopupText("Rest In Peace !", color=(1, 0.2, 0.2), scale=1.6, position=msg_pos).autoretain() else: if dmg >= 800: PopupText("#PRO !", color=(1, 0.2, 0.2), scale=1.6, position=msg_pos).autoretain() elif dmg >= 600 and dmg < 800: PopupText("GOOD ONE!", color=(1, 0.3, 0.1), scale=1.6, position=msg_pos).autoretain() elif dmg >= 400 and dmg < 600: PopupText("OH! YEAH", color=(1, 0.5, 0.2), scale=1.6, position=msg_pos).autoretain() elif dmg >= 200 and dmg < 400: PopupText("WTF!", color=(0.7, 0.4, 0.2), scale=1.6, position=msg_pos).autoretain() elif dmg > 0 and dmg < 200: PopupText("!!!", color=(1, 1, 1), scale=1.6, position=msg_pos).autoretain() except: pass return
def handlemessage(self, msg: Any, returned: Any = None) -> Any: super(stdspaz.Spaz, self).handlemessage(msg) if isinstance(msg, ba.PowerupMessage): if not self.is_alive(): return for poweruptype, texture, callback in _callbacks: if msg.poweruptype == poweruptype: if ba.app.config.get('Powerup Popups', True): powerup_text = get_locale( 'powerup_names')[poweruptype] PopupText( ba.Lstr(translate=('gameDescriptions', powerup_text)), color=(1, 1, 1), scale=1, position=self.node.position).autoretain() callback(self, msg)
def player_scored(self, player: ba.Player, base_points: int = 1, target: Sequence[float] = None, kill: bool = False, victim_player: ba.Player = None, scale: float = 1.0, color: Sequence[float] = None, title: Union[str, ba.Lstr] = None, screenmessage: bool = True, display: bool = True, importance: int = 1, showpoints: bool = True, big_message: bool = False) -> int: """Register a score for the player. Return value is actual score with multipliers and such factored in. """ # FIXME: Tidy this up. # pylint: disable=cyclic-import # pylint: disable=too-many-branches # pylint: disable=too-many-locals # pylint: disable=too-many-statements from bastd.actor.popuptext import PopupText from ba import _math from ba._gameactivity import GameActivity from ba._lang import Lstr del victim_player # Currently unused. name = player.getname() s_player = self._player_records[name] if kill: s_player.submit_kill(showpoints=showpoints) display_color: Sequence[float] = (1.0, 1.0, 1.0, 1.0) if color is not None: display_color = color elif importance != 1: display_color = (1.0, 1.0, 0.4, 1.0) points = base_points # If they want a big announcement, throw a zoom-text up there. if display and big_message: try: assert self._activity is not None activity = self._activity() if isinstance(activity, GameActivity): name_full = player.getname(full=True, icon=False) activity.show_zoom_message( Lstr(resource='nameScoresText', subs=[('${NAME}', name_full)]), color=_math.normalized_color(player.team.color)) except Exception: print_exception('error showing big_message') # If we currently have a actor, pop up a score over it. if display and showpoints: our_pos = player.node.position if player.node else None if our_pos is not None: if target is None: target = our_pos # If display-pos is *way* lower than us, raise it up # (so we can still see scores from dudes that fell off cliffs). display_pos = (target[0], max(target[1], our_pos[1] - 2.0), min(target[2], our_pos[2] + 2.0)) activity = self.getactivity() if activity is not None: if title is not None: sval = Lstr(value='+${A} ${B}', subs=[('${A}', str(points)), ('${B}', title)]) else: sval = Lstr(value='+${A}', subs=[('${A}', str(points))]) PopupText(sval, color=display_color, scale=1.2 * scale, position=display_pos).autoretain() # Tally kills. if kill: s_player.accum_kill_count += 1 s_player.kill_count += 1 # Report non-kill scorings. try: if screenmessage and not kill: _ba.screenmessage(Lstr(resource='nameScoresText', subs=[('${NAME}', name)]), top=True, color=player.color, image=player.get_icon()) except Exception: print_exception('error announcing score') s_player.score += points s_player.accumscore += points # Inform a running game of the score. if points != 0: activity = self._activity() if self._activity is not None else None if activity is not None: activity.handlemessage(PlayerScoredMessage(score=points)) return points
def do_hit_at_position(self, pos: Sequence[float], player: Player) -> bool: """Handle a bomb hit at the given position.""" # pylint: disable=too-many-statements activity = self.activity # Ignore hits if the game is over or if we've already been hit if activity.has_ended() or self._hit or not self._nodes: return False diff = (ba.Vec3(pos) - self._position) # Disregard Y difference. Our target point probably isn't exactly # on the ground anyway. diff[1] = 0.0 dist = diff.length() bullseye = False if dist <= self._r3 + self._rfudge: # Inform our activity that we were hit self._hit = True activity.handlemessage(self.TargetHitMessage()) keys: Dict[float, Sequence[float]] = { 0.0: (1.0, 0.0, 0.0), 0.049: (1.0, 0.0, 0.0), 0.05: (1.0, 1.0, 1.0), 0.1: (0.0, 1.0, 0.0) } cdull = (0.3, 0.3, 0.3) popupcolor: Sequence[float] if dist <= self._r1 + self._rfudge: bullseye = True self._nodes[1].color = cdull self._nodes[2].color = cdull ba.animate_array(self._nodes[0], 'color', 3, keys, loop=True) popupscale = 1.8 popupcolor = (1, 1, 0, 1) streak = player.streak points = 10 + min(20, streak * 2) ba.playsound(ba.getsound('bellHigh')) if streak > 0: ba.playsound( ba.getsound( 'orchestraHit4' if streak > 3 else 'orchestraHit3' if streak > 2 else 'orchestraHit2' if streak > 1 else 'orchestraHit')) elif dist <= self._r2 + self._rfudge: self._nodes[0].color = cdull self._nodes[2].color = cdull ba.animate_array(self._nodes[1], 'color', 3, keys, loop=True) popupscale = 1.25 popupcolor = (1, 0.5, 0.2, 1) points = 4 ba.playsound(ba.getsound('bellMed')) else: self._nodes[0].color = cdull self._nodes[1].color = cdull ba.animate_array(self._nodes[2], 'color', 3, keys, loop=True) popupscale = 1.0 popupcolor = (0.8, 0.3, 0.3, 1) points = 2 ba.playsound(ba.getsound('bellLow')) # Award points/etc.. (technically should probably leave this up # to the activity). popupstr = '+' + str(points) # If there's more than 1 player in the game, include their # names and colors so they know who got the hit. if len(activity.players) > 1: popupcolor = ba.safecolor(player.color, target_intensity=0.75) popupstr += ' ' + player.getname() PopupText(popupstr, position=self._position, color=popupcolor, scale=popupscale).autoretain() # Give this player's team points and update the score-board. player.team.score += points assert isinstance(activity, TargetPracticeGame) activity.update_scoreboard() # Also give this individual player points # (only applies in teams mode). assert activity.stats is not None activity.stats.player_scored(player, points, showpoints=False, screenmessage=False) ba.animate_array(self._nodes[0], 'size', 1, { 0.8: self._nodes[0].size, 1.0: [0.0] }) ba.animate_array(self._nodes[1], 'size', 1, { 0.85: self._nodes[1].size, 1.05: [0.0] }) ba.animate_array(self._nodes[2], 'size', 1, { 0.9: self._nodes[2].size, 1.1: [0.0] }) ba.timer(1.1, ba.Call(self.handlemessage, ba.DieMessage())) return bullseye
def handlemessage(self, msg, returned): from bastd.actor.popuptext import PopupText if isinstance(msg, ba.HitMessage): if msg.hit_type == 'punch': if not self.node: return None if self.node.invincible: return True 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: damage = damage_scale * self.node.damage # 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 = stdspaz.get_factory( ).max_shield_spillover_damage # 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: damage = int(damage_scale * self.node.damage) if damage > 999: PopupText(get_locale('fatality_text'), color=(0.905, 0.298, 0.235), scale=2.0, position=self.node.position).autoretain() ba.emitfx(position=msg.pos, chunk_type='spark', velocity=(msg.force_direction[0] * 1.3, msg.force_direction[1] * 1.3 + 5.0, msg.force_direction[2] * 1.3), count=45, scale=1.0, spread=1.0) self.lightning_bolt(position=self.node.position, radius=3) gnode = self.activity.globalsnode if not gnode.slow_motion: gnode.slow_motion = True def off_sm(): if gnode: gnode.slow_motion = False ba.timer(0.5, off_sm) elif 800 < damage < 999: PopupText(get_locale('crazy_text'), color=(0.180, 0.800, 0.443), scale=1.5, position=self.node.position).autoretain() ba.emitfx(position=msg.pos, chunk_type='spark', velocity=(msg.force_direction[0] * 1.3, msg.force_direction[1] * 1.3 + 5.0, msg.force_direction[2] * 1.3), count=45, scale=1.0, spread=1.0) elif 750 < damage < 800: PopupText(get_locale('aggressive_text'), color=(0.231, 0.596, 0.858), scale=1.5, position=self.node.position).autoretain() return returned