def __init__(self, position: Sequence[float] = (0.0, 1.0, 0.0)): super().__init__() shared = SharedObjects.get() activity = self.getactivity() # Spawn just above the provided point. self._spawn_pos = (position[0], position[1] + 1.0, position[2]) self.last_players_to_touch: Dict[int, Player] = {} self.scored = False assert activity is not None assert isinstance(activity, HockeyGame) pmats = [shared.object_material, activity.puck_material] self.node = ba.newnode('prop', delegate=self, attrs={ 'model': activity.puck_model, 'color_texture': activity.puck_tex, 'body': 'puck', 'reflection': 'soft', 'reflection_scale': [0.2], 'shadow_size': 1.0, 'is_area_of_interest': True, 'position': self._spawn_pos, 'materials': pmats }) ba.animate(self.node, 'model_scale', {0: 0, 0.2: 1.3, 0.26: 1})
def lightning_bolt(position, radius=1): ba.camerashake(4) vignette_outer = self.activity.globalsnode.vignette_outer # if ba.getactivity().tint is None: # ba.getactivity().std_tint = ba.sharedobj('globals').vignette_outer # vignette_outer = ba.sharedobj('globals').vignette_outer # else: # vignette_outer = ba.getactivity().tint light = ba.newnode('light', attrs={ 'position': position, 'color': (0.4, 0.4, 0.8), 'volume_intensity_scale': 1.0, 'radius': radius }) ba.animate(light, 'intensity', { 0: 1, 50: radius, 150: radius / 2, 250: 0, 260: radius, 410: radius / 2, 510: 0 }, timeformat=ba.TimeFormat.MILLISECONDS, suppress_format_warning=True) ba.animate_array(self.activity.globalsnode, 'vignette_outer', 3, { 0: vignette_outer, 0.2: (0.2, 0.2, 0.2), 0.51: vignette_outer })
def spawn_wrapper(): if self.node.exists(): self.phrase_text_node = ba.newnode('text', owner=self.node, attrs={ 'text': random.choice( self.phrases), 'scale': 0.0, 'in_world': True, 'h_align': 'center' }) math.connectattr('output', self.phrase_text_node, 'position') ba.animate(self.phrase_text_node, 'scale', { 0: 0.0, 0.5: 0.01, 5: 0.01, 5.5: 0.0 })
def _handle_score(self) -> None: """A point has been scored.""" assert self._puck is not None assert self._score_regions is not None # Our puck might stick around for a second or two # we don't want it to be able to score again. if self._puck.scored: return region = ba.get_collision_info("source_node") index = 0 for index in range(len(self._score_regions)): if region == self._score_regions[index].node: break for team in self.teams: if team.get_id() == index: scoring_team = team team.gamedata['score'] += 1 # Tell all players to celebrate. for player in team.players: if player.actor: player.actor.handlemessage(ba.CelebrateMessage(2.0)) # If we've got the player from the scoring team that last # touched us, give them points. if (scoring_team.get_id() in self._puck.last_players_to_touch and self._puck.last_players_to_touch[ scoring_team.get_id()]): self.stats.player_scored(self._puck.last_players_to_touch[ scoring_team.get_id()], 100, big_message=True) # End game if we won. if team.gamedata['score'] >= self.settings['Score to Win']: self.end_game() ba.playsound(self._foghorn_sound) ba.playsound(self._cheer_sound) self._puck.scored = True # Kill the puck (it'll respawn itself shortly). ba.timer(1.0, self._kill_puck) light = ba.newnode('light', attrs={ 'position': ba.get_collision_info('position'), 'height_attenuated': False, 'color': (1, 0, 0) }) ba.animate(light, 'intensity', {0: 0, 0.5: 1, 1.0: 0}, loop=True) ba.timer(1.0, light.delete) ba.cameraflash(duration=10.0) self._update_scoreboard()
def set_score_text(self, text: str) -> None: """Show a message over the flag; handy for scores.""" if not self.node: return if not self._score_text: start_scale = 0.0 math = ba.newnode('math', owner=self.node, attrs={ 'input1': (0, 1.4, 0), 'operation': 'add' }) self.node.connectattr('position', math, 'input2') self._score_text = ba.newnode('text', owner=self.node, attrs={ 'text': text, 'in_world': True, 'scale': 0.02, 'shadow': 0.5, 'flatness': 1.0, 'h_align': 'center' }) math.connectattr('output', self._score_text, 'position') else: assert isinstance(self._score_text.scale, float) start_scale = self._score_text.scale self._score_text.text = text self._score_text.color = ba.safecolor(self.node.color) ba.animate(self._score_text, 'scale', {0: start_scale, 0.2: 0.02}) self._score_text_hide_timer = ba.Timer( 1.0, ba.WeakCall(self._hide_score_text))
def __init__(self, m, random_col): super().__init__() shared = SharedObjects.get() if random_col: col = (random.uniform(0, 1.2), random.uniform(0, 1.2), random.uniform(0, 1.2)) else: col = (0.9, 0.7, 0.0) self.mat = ba.Material() self.mat.add_actions(actions=( ('modify_part_collision', 'collide', False), ('modify_part_collision', 'physical', False), )) self.node = ba.newnode('prop', delegate=self, attrs={ 'model': ba.getmodel('bomb'), 'position': (2, 4, 2), 'body': 'capsule', 'shadow_size': 0.0, 'color_texture': ba.gettexture('coin'), 'reflection': 'soft', 'reflection_scale': [1.5], 'materials': [shared.object_material, self.mat] }) ba.animate(self.node, 'model_scale', { 0: 0, 1: 0.19, 5: 0.10, 10: 0.0 }, loop=True) ba.animate_array(self.node, 'position', 3, self.generateKeys(m), loop=True) self.light = ba.newnode('light', owner=self.node, attrs={ 'intensity': 0.6, 'height_attenuated': True, 'radius': 0.2, 'color': col }) ba.animate(self.light, 'radius', { 0: 0.0, 20: 0.4, 70: 0.1, 100: 0.3, 150: 0 }, loop=True) self.node.connectattr('position', self.light, 'position')
def init(self, actor: stdbomb.Bomb, position, velocity, materials): factory = stdbomb.BombFactory.get() actor.node = ba.newnode('prop', delegate=actor, attrs={ 'position': position, 'velocity': velocity, 'body': 'sphere', 'materials': materials }) actor.first_shield = ba.newnode( 'shield', owner=actor.node, attrs={ 'color': (1, 1, 1), 'radius': 0.6}) actor.node.connectattr( 'position', actor.first_shield, 'position') actor.second_shield = ba.newnode( 'shield', owner=actor.node, attrs={ 'color': (20, 0, 0), 'radius': 0.4}) actor.node.connectattr( 'position', actor.second_shield, 'position') ba.animate(actor.second_shield, 'radius', {0: 0.1, 0.05: 0.4, 0.2: 0.1, 0.25: 0.5, 0.4: 0.3, 0.7: 0.1}, True)
def _hide_score_text(self) -> None: assert self._score_text is not None assert isinstance(self._score_text.scale, float) ba.animate(self._score_text, 'scale', { 0: self._score_text.scale, 0.2: 0 })
def lightning_bolt(self, position=(0, 10, 0), radius=10): tint = self.activity.globalsnode.tint sounds = ('impactHard', 'impactHard2', 'impactHard3') ba.playsound(ba.getsound(random.choice(sounds)), volume=2) light = ba.newnode('light', attrs={ 'position': position, 'color': (0.2, 0.2, 0.4), 'volume_intensity_scale': 1.0, 'radius': radius }) intensity = { 0: 1, 0.05: radius, 0.15: radius / 2, 0.25: 0, 0.26: radius, 0.41: radius / 2, 0.51: 0 } ba.animate(light, 'intensity', intensity) ba.animate_array(self.activity.globalsnode, 'tint', 3, { 0: tint, 0.2: (0.2, 0.2, 0.2), 0.51: tint })
def __init__(self, position: Sequence[float] = (0, 3, 0), velocity: Sequence[float] = (0, -5, 0), amount: int = 15, bomb_type: str = 'impact', highlight: bool = True, source_player: ba.Player = None): ba.Actor.__init__(self) self.position = position self.velocity = velocity self.amount = amount self.bomb_type = bomb_type self._source_player = source_player self.drop_count = 0 # highlight the bombing zone if highlight: self.area_highlight = ba.newnode('light', attrs={ 'color': (1, 0, 0), 'position': position, 'volume_intensity_scale': 1.0 }) ba.animate(self.area_highlight, 'intensity', { 0: 0, 0.5: 1.0, 1: 0 }) def wrapper(): self.drop_timer = ba.Timer(0.25, self._drop_bomb, repeat=True) ba.timer(1, wrapper)
def __init__(self, position=(0, 5, 0), direction=(0, 2, 0), source_player=None, owner=None, color=(1, 1, 1)) -> None: super().__init__() self._color = color self.node = ba.newnode('light', delegate=self, attrs={ 'position': position, 'color': self._color }) ba.animate(self.node, 'radius', {0: 0, 0.1: 0.5, 0.5: 0}) self.source_player = source_player self.owner = owner self._life_timer = ba.Timer( 0.5, ba.WeakCall(self.handlemessage, ba.DieMessage())) pos = position vel = tuple(i / 5 for i in ba.Vec3(direction).normalized()) for _ in range(500): # Optimization :( ba.newnode('explosion', owner=self.node, attrs={ 'position': pos, 'radius': 0.2, 'color': self._color }) pos = (pos[0] + vel[0], pos[1] + vel[1], pos[2] + vel[2]) for node in _ba.getnodes(): if node and node.getnodetype() == 'spaz': # pylint: disable=invalid-name m3 = ba.Vec3(position) a = ba.Vec3(direction[2], direction[1], direction[0]) m1 = ba.Vec3(node.position) # pylint: enable=invalid-name # distance between node and line dist = (a * (m1 - m3)).length() / a.length() if dist < 0.3: if node and node != self.owner and node.getdelegate( PlayerSpaz, True).getplayer( ba.Player, True).team != self.owner.team: node.handlemessage(ba.FreezeMessage()) pos = self.node.position hit_dir = (0, 10, 0) node.handlemessage( ba.HitMessage(pos=pos, magnitude=50, velocity_magnitude=50, radius=0, srcnode=self.node, source_player=self.source_player, force_direction=hit_dir))
def _shift(self, position1: Tuple[float, float], position2: Tuple[float, float]) -> None: if not self.node: return cmb = ba.newnode('combine', owner=self.node, attrs={'size': 2}) ba.animate(cmb, 'input0', {0.0: position1[0], 0.25: position2[0]}) ba.animate(cmb, 'input1', {0.0: position1[1], 0.25: position2[1]}) cmb.connectattr('output', self.node, 'position')
def _handle_flag_entered_base(self, team: Team) -> None: try: flag = ba.getcollision().opposingnode.getdelegate( StickyStormCTFFlag, True) except ba.NotFoundError: # Don't think this should logically ever happen. print( 'Error getting StickyStormCTFFlag in entering-base callback.') return if flag.team is team: team.home_flag_at_base = True # If the enemy flag is already here, score! if team.enemy_flag_at_base: self._score(team) else: team.enemy_flag_at_base = True if team.home_flag_at_base: # Award points to whoever was carrying the enemy flag. player = flag.last_player_to_hold if player and player.team is team: assert self.stats self.stats.player_scored(player, 50, big_message=True) # Update score and reset flags. self._score(team) # If the home-team flag isn't here, print a message to that effect. else: # Don't want slo-mo affecting this curtime = ba.time(ba.TimeType.BASE) if curtime - self._last_home_flag_notice_print_time > 5.0: self._last_home_flag_notice_print_time = curtime bpos = team.base_pos tval = ba.Lstr(resource='ownFlagAtYourBaseWarning') tnode = ba.newnode('text', attrs={ 'text': tval, 'in_world': True, 'scale': 0.013, 'color': (1, 1, 0, 1), 'h_align': 'center', 'position': (bpos[0], bpos[1] + 3.2, bpos[2]) }) ba.timer(5.1, tnode.delete) ba.animate(tnode, 'scale', { 0.0: 0, 0.2: 0.013, 4.8: 0.013, 5.0: 0 })
def _flash_puck_spawn(self) -> None: light = ba.newnode('light', attrs={ 'position': self._puck_spawn_pos, 'height_attenuated': False, 'color': (1, 0, 0) }) ba.animate(light, 'intensity', {0.0: 0, 0.25: 1, 0.5: 0}, loop=True) ba.timer(1.0, light.delete)
def handlemessage(self, msg: Any) -> Any: """ handle high-level game messages """ if isinstance(msg, playerspaz.PlayerSpazDeathMessage): from bastd.actor import respawnicon # Respawn dead players. player = msg.spaz.player self.stats.player_was_killed(player) assert self.initial_player_info is not None respawn_time = 2.0 + len(self.initial_player_info) * 1.0 # Respawn them shortly. player.gamedata['respawn_timer'] = ba.Timer( respawn_time, ba.Call(self.spawn_player_if_exists, player)) player.gamedata['respawn_icon'] = respawnicon.RespawnIcon( player, respawn_time) # Augment standard behavior. super().handlemessage(msg) elif isinstance(msg, spazbot.SpazBotDeathMessage): # Every time a bad guy dies, spawn a new one. ba.timer(3.0, ba.Call(self._spawn_bot, (type(msg.badguy)))) elif isinstance(msg, spazbot.SpazBotPunchedMessage): if self._preset in ['rookie', 'rookie_easy']: if msg.damage >= 500: self._award_achievement('Super Punch') elif self._preset in ['pro', 'pro_easy']: if msg.damage >= 1000: self._award_achievement('Super Mega Punch') # Respawn dead flags. elif isinstance(msg, stdflag.FlagDeathMessage): assert isinstance(msg.flag, FootballFlag) msg.flag.respawn_timer = ba.Timer(3.0, self._spawn_flag) self._flag_respawn_light = ba.NodeActor( ba.newnode('light', attrs={ 'position': self._flag_spawn_pos, 'height_attenuated': False, 'radius': 0.15, 'color': (1.0, 1.0, 0.3) })) assert self._flag_respawn_light.node ba.animate(self._flag_respawn_light.node, 'intensity', { 0: 0, 0.25: 0.15, 0.5: 0 }, loop=True) ba.timer(3.0, self._flag_respawn_light.node.delete) else: super().handlemessage(msg)
def _handle_reached_end(self) -> None: spaz = ba.getcollision().opposingnode.getdelegate(SpazBot, True) if not spaz.is_alive(): return # Ignore bodies flying in. self._flawless = False pos = spaz.node.position ba.playsound(self._bad_guy_score_sound, position=pos) light = ba.newnode('light', attrs={ 'position': pos, 'radius': 0.5, 'color': (1, 0, 0) }) ba.animate(light, 'intensity', {0.0: 0, 0.1: 1, 0.5: 0}, loop=False) ba.timer(1.0, light.delete) spaz.handlemessage( ba.DieMessage(immediate=True, how=ba.DeathType.REACHED_GOAL)) if self._lives > 0: self._lives -= 1 if self._lives == 0: self._bots.stop_moving() self.continue_or_end_game() assert self._lives_text is not None assert self._lives_text.node self._lives_text.node.text = str(self._lives) delay = 0.0 def _safesetattr(node: ba.Node, attr: str, value: Any) -> None: if node: setattr(node, attr, value) for _i in range(4): ba.timer( delay, ba.Call(_safesetattr, self._lives_text.node, 'color', (1, 0, 0, 1.0))) assert self._lives_bg is not None assert self._lives_bg.node ba.timer( delay, ba.Call(_safesetattr, self._lives_bg.node, 'opacity', 0.5)) delay += 0.125 ba.timer( delay, ba.Call(_safesetattr, self._lives_text.node, 'color', (1.0, 1.0, 0.0, 1.0))) ba.timer( delay, ba.Call(_safesetattr, self._lives_bg.node, 'opacity', 1.0)) delay += 0.125 ba.timer( delay, ba.Call(_safesetattr, self._lives_text.node, 'color', (0.8, 0.8, 0.8, 1.0)))
def _flash_flag_spawn(self) -> None: light = ba.newnode('light', attrs={ 'position': self._flag_spawn_pos, 'color': (1, 1, 1), 'radius': 0.3, 'height_attenuated': False }) ba.animate(light, 'intensity', {0: 0, 0.25: 0.5, 0.5: 0}, loop=True) ba.timer(1.0, light.delete)
def _flash_base(self, team: Team, length: float = 2.0) -> None: light = ba.newnode('light', attrs={ 'position': team.base_pos, 'height_attenuated': False, 'radius': 0.3, 'color': team.color }) ba.animate(light, 'intensity', {0: 0, 0.25: 2.0, 0.5: 0}, loop=True) ba.timer(length, light.delete)
def _handle_flag_entered_base(self, team: ba.Team) -> None: node = ba.get_collision_info('opposing_node') assert isinstance(node, (ba.Node, type(None))) flag = CTFFlag.from_node(node) if not flag: print('Unable to get flag in _handle_flag_entered_base') return if flag.team is team: team.gamedata['home_flag_at_base'] = True # If the enemy flag is already here, score! if team.gamedata['enemy_flag_at_base']: self._score(team) else: team.gamedata['enemy_flag_at_base'] = True if team.gamedata['home_flag_at_base']: # Award points to whoever was carrying the enemy flag. player = flag.last_player_to_hold if player and player.team is team: assert self.stats self.stats.player_scored(player, 50, big_message=True) # Update score and reset flags. self._score(team) # If the home-team flag isn't here, print a message to that effect. else: # Don't want slo-mo affecting this curtime = ba.time(ba.TimeType.BASE) if curtime - self._last_home_flag_notice_print_time > 5.0: self._last_home_flag_notice_print_time = curtime bpos = team.gamedata['base_pos'] tval = ba.Lstr(resource='ownFlagAtYourBaseWarning') tnode = ba.newnode('text', attrs={ 'text': tval, 'in_world': True, 'scale': 0.013, 'color': (1, 1, 0, 1), 'h_align': 'center', 'position': (bpos[0], bpos[1] + 3.2, bpos[2]) }) ba.timer(5.1, tnode.delete) ba.animate(tnode, 'scale', { 0.0: 0, 0.2: 0.013, 4.8: 0.013, 5.0: 0 })
def _flash_flag(self, flag: ConquestFlag, length: float = 1.0) -> None: assert flag.node assert flag.light light = ba.newnode('light', attrs={ 'position': flag.node.position, 'height_attenuated': False, 'color': flag.light.color }) ba.animate(light, 'intensity', {0: 0, 0.25: 1, 0.5: 0}, loop=True) ba.timer(length, light.delete)
def _flash_mine(self, i: int) -> None: assert self._race_mines is not None rmine = self._race_mines[i] light = ba.newnode('light', attrs={ 'position': rmine.point[:3], 'color': (1, 0.2, 0.2), 'radius': 0.1, 'height_attenuated': False }) ba.animate(light, 'intensity', {0.0: 0, 0.1: 1.0, 0.2: 0}, loop=True) ba.timer(1.0, light.delete)
def _fade_in(self) -> None: for node in self._nodes: ba.animate(node, 'opacity', {0: 0.0, 2.0: 1.0}) # If we were given a lifespan, transition out after it. if self._lifespan is not None: ba.timer(self._lifespan, ba.WeakCall(self.handlemessage, ba.DieMessage())) self._update() self._update_timer = ba.Timer(1.0, ba.WeakCall(self._update), repeat=True)
def handlemessage(self, msg: Any) -> Any: assert not self.expired if isinstance(msg, ba.DieMessage): if msg.immediate: self._die() else: # If they don't need immediate, # fade out our nodes and die later. for node in self._nodes: ba.animate(node, 'opacity', {0: node.opacity, 3.0: 0.0}) ba.timer(3.1, ba.WeakCall(self._die)) return None return super().handlemessage(msg)
def _flash_player(self, player: ba.Player, scale: float) -> None: assert isinstance(player.actor, PlayerSpaz) assert player.actor.node pos = player.actor.node.position light = ba.newnode('light', attrs={ 'position': pos, 'color': (1, 1, 0), 'height_attenuated': False, 'radius': 0.4 }) ba.timer(0.5, light.delete) ba.animate(light, 'intensity', {0: 0, 0.1: 1.0 * scale, 0.5: 0})
def set_value(self, score: float, max_score: float = None, countdown: bool = False, flash: bool = True, show_value: bool = True) -> None: """Set the value for the scoreboard entry.""" # If we have no score yet, just set it.. otherwise compare # and see if we should flash. if self._score is None: self._score = score else: if score > self._score or (countdown and score < self._score): extra_flash = (max_score is not None and score >= max_score and not countdown) or (countdown and score == 0) if flash: self.flash(countdown, extra_flash) self._score = score if max_score is None: self._bar_width = 0.0 else: if countdown: self._bar_width = max( 2.0 * self._scale, self._width * (1.0 - (float(score) / max_score))) else: self._bar_width = max( 2.0 * self._scale, self._width * (min(1.0, float(score) / max_score))) cur_width = self._bar_scale.input0 ba.animate(self._bar_scale, 'input0', { 0.0: cur_width, 0.25: self._bar_width }) self._bar_scale.input1 = self._bar_height cur_x = self._bar_position.input0 assert self._pos is not None ba.animate(self._bar_position, 'input0', { 0.0: cur_x, 0.25: self._pos[0] + self._bar_width / 2 }) self._bar_position.input1 = self._pos[1] - self._bar_height / 2 assert self._score_text.node if show_value: self._score_text.node.text = str(score) else: self._score_text.node.text = ''
def handlemessage(self, msg: Any) -> Any: """ handle high-level game messages """ if isinstance(msg, ba.PlayerDiedMessage): # Augment standard behavior. super().handlemessage(msg) # Respawn them shortly. player = msg.getplayer(Player) assert self.initialplayerinfos is not None respawn_time = 2.0 + len(self.initialplayerinfos) * 1.0 player.respawn_timer = ba.Timer( respawn_time, ba.Call(self.spawn_player_if_exists, player)) player.respawn_icon = RespawnIcon(player, respawn_time) elif isinstance(msg, SpazBotDiedMessage): # Every time a bad guy dies, spawn a new one. ba.timer(3.0, ba.Call(self._spawn_bot, (type(msg.spazbot)))) elif isinstance(msg, SpazBotPunchedMessage): if self._preset in ['rookie', 'rookie_easy']: if msg.damage >= 500: self._award_achievement('Super Punch') elif self._preset in ['pro', 'pro_easy']: if msg.damage >= 1000: self._award_achievement('Super Mega Punch') # Respawn dead flags. elif isinstance(msg, FlagDiedMessage): assert isinstance(msg.flag, FootballFlag) msg.flag.respawn_timer = ba.Timer(3.0, self._spawn_flag) self._flag_respawn_light = ba.NodeActor( ba.newnode('light', attrs={ 'position': self._flag_spawn_pos, 'height_attenuated': False, 'radius': 0.15, 'color': (1.0, 1.0, 0.3) })) assert self._flag_respawn_light.node ba.animate(self._flag_respawn_light.node, 'intensity', { 0: 0, 0.25: 0.15, 0.5: 0 }, loop=True) ba.timer(3.0, self._flag_respawn_light.node.delete) else: return super().handlemessage(msg) return None
def _handle_score(self) -> None: """A point has been scored.""" # Our flag might stick around for a second or two # make sure it doesn't score again. assert self._flag is not None if self._flag.scored: return region = ba.getcollision().sourcenode i = None for i in range(len(self._score_regions)): if region == self._score_regions[i].node: break for team in self.teams: if team.id == i: team.score += 7 # Tell all players to celebrate. for player in team.players: if player.actor: player.actor.handlemessage(ba.CelebrateMessage(2.0)) # If someone on this team was last to touch it, # give them points. assert self._flag is not None if (self._flag.last_holding_player and team == self._flag.last_holding_player.team): self.stats.player_scored(self._flag.last_holding_player, 50, big_message=True) # End the game if we won. if team.score >= self._score_to_win: self.end_game() ba.playsound(self._score_sound) ba.playsound(self._cheer_sound) assert self._flag self._flag.scored = True # Kill the flag (it'll respawn shortly). ba.timer(1.0, self._kill_flag) light = ba.newnode('light', attrs={ 'position': ba.getcollision().position, 'height_attenuated': False, 'color': (1, 0, 0) }) ba.animate(light, 'intensity', {0.0: 0, 0.5: 1, 1.0: 0}, loop=True) ba.timer(1.0, light.delete) ba.cameraflash(duration=10.0) self._update_scoreboard()
def move_holding_node(self, move: str = '') -> None: if self._combine: t = [] if 'x' in move: t.append(0) if 'y' in move: t.append(1) if 'z' in move: t.append(2) for i in t: val = getattr(self._combine, 'input{}'.format(i), None) if val is not None: ba.animate(self._combine, 'input{}'.format(i), { 0: val, 0.5: val + self._offset[i] })
def _show_winner(self, team: ba.SessionTeam) -> None: from bastd.actor.image import Image from bastd.actor.zoomtext import ZoomText if not self._is_ffa: offs_v = 0.0 ZoomText(team.name, position=(0, 97), color=team.color, scale=1.15, jitter=1.0, maxwidth=250).autoretain() else: offs_v = -80.0 if len(team.players) == 1: i = Image(team.players[0].get_icon(), position=(0, 143), scale=(100, 100)).autoretain() assert i.node ba.animate(i.node, 'opacity', {0.0: 0.0, 0.25: 1.0}) ZoomText(ba.Lstr( value=team.players[0].getname(full=True, icon=False)), position=(0, 97 + offs_v), color=team.color, scale=1.15, jitter=1.0, maxwidth=250).autoretain() s_extra = 1.0 if self._is_ffa else 1.0 # Some languages say "FOO WINS" differently for teams vs players. if isinstance(self.session, ba.FreeForAllSession): wins_resource = 'seriesWinLine1PlayerText' else: wins_resource = 'seriesWinLine1TeamText' wins_text = ba.Lstr(resource=wins_resource) # Temp - if these come up as the english default, fall-back to the # unified old form which is more likely to be translated. ZoomText(wins_text, position=(0, -10 + offs_v), color=team.color, scale=0.65 * s_extra, jitter=1.0, maxwidth=250).autoretain() ZoomText(ba.Lstr(resource='seriesWinLine2Text'), position=(0, -110 + offs_v), scale=1.0 * s_extra, color=team.color, jitter=1.0, maxwidth=250).autoretain()
def __init__( self, data: Any = None, pt: Sequence[float] = (0, 0, 0), # pylint: disable=invalid-name spawn_time: float = 1.0, send_spawn_message: bool = True, spawn_callback: Callable[[], Any] = None): """Instantiate a Spawner. Requires some custom data, a position, and a spawn-time in seconds. """ self._spawn_callback = spawn_callback self._send_spawn_message = send_spawn_message self._spawner_sound = ba.getsound('swip2') self._data = data self._pt = pt # create a light where the spawn will happen self._light = ba.newnode('light', attrs={ 'position': tuple(pt), 'radius': 0.1, 'color': (1.0, 0.1, 0.1), 'lights_volumes': False }) scl = float(spawn_time) / 3.75 min_val = 0.4 max_val = 0.7 ba.playsound(self._spawner_sound, position=self._light.position) ba.animate( self._light, 'intensity', { 0.0: 0.0, 0.25 * scl: max_val, 0.500 * scl: min_val, 0.750 * scl: max_val, 1.000 * scl: min_val, 1.250 * scl: 1.1 * max_val, 1.500 * scl: min_val, 1.750 * scl: 1.2 * max_val, 2.000 * scl: min_val, 2.250 * scl: 1.3 * max_val, 2.500 * scl: min_val, 2.750 * scl: 1.4 * max_val, 3.000 * scl: min_val, 3.250 * scl: 1.5 * max_val, 3.500 * scl: min_val, 3.750 * scl: 2.0, 4.000 * scl: 0.0 }) ba.timer(spawn_time, self._spawn)