def start(self) -> None:
     """Start the timer."""
     tval = ba.time(timeformat=ba.TimeFormat.MILLISECONDS)
     assert isinstance(tval, int)
     self._starttime = tval
     self.inputnode.time1 = self._starttime
     ba.sharedobj('globals').connectattr('time', self.inputnode, 'time2')
    def __init__(self) -> None:
        """Instantiate a PowerupBoxFactory.

        You shouldn't need to do this; call ba.Powerup.get_factory()
        to get a shared instance.
        """
        from ba.internal import get_default_powerup_distribution
        self._lastpoweruptype: Optional[str] = None
        self.model = ba.getmodel('powerup')
        self.model_simple = ba.getmodel('powerupSimple')
        self.tex_bomb = ba.gettexture('powerupBomb')
        self.tex_punch = ba.gettexture('powerupPunch')
        self.tex_ice_bombs = ba.gettexture('powerupIceBombs')
        self.tex_sticky_bombs = ba.gettexture('powerupStickyBombs')
        self.tex_shield = ba.gettexture('powerupShield')
        self.tex_impact_bombs = ba.gettexture('powerupImpactBombs')
        self.tex_health = ba.gettexture('powerupHealth')
        self.tex_land_mines = ba.gettexture('powerupLandMines')
        self.tex_curse = ba.gettexture('powerupCurse')
        self.health_powerup_sound = ba.getsound('healthPowerup')
        self.powerup_sound = ba.getsound('powerup01')
        self.powerdown_sound = ba.getsound('powerdown01')
        self.drop_sound = ba.getsound('boxDrop')

        # Material for powerups.
        self.powerup_material = ba.Material()

        # Material for anyone wanting to accept powerups.
        self.powerup_accept_material = ba.Material()

        # Pass a powerup-touched message to applicable stuff.
        self.powerup_material.add_actions(
            conditions=('they_have_material', self.powerup_accept_material),
            actions=(('modify_part_collision', 'collide',
                      True), ('modify_part_collision', 'physical', False),
                     ('message', 'our_node', 'at_connect', _TouchedMessage())))

        # We don't wanna be picked up.
        self.powerup_material.add_actions(
            conditions=('they_have_material', ba.sharedobj('pickup_material')),
            actions=('modify_part_collision', 'collide', False))

        self.powerup_material.add_actions(
            conditions=('they_have_material',
                        ba.sharedobj('footing_material')),
            actions=('impact_sound', self.drop_sound, 0.5, 0.1))

        self._powerupdist: List[str] = []
        for powerup, freq in get_default_powerup_distribution():
            for _i in range(int(freq)):
                self._powerupdist.append(powerup)
Exemple #3
0
    def __init__(self, settings: Dict[str, Any]):
        from bastd.actor.scoreboard import Scoreboard
        from bastd.actor import powerupbox
        super().__init__(settings)
        self._scoreboard = Scoreboard()
        self._cheer_sound = ba.getsound("cheer")
        self._chant_sound = ba.getsound("crowdChant")
        self._foghorn_sound = ba.getsound("foghorn")
        self._swipsound = ba.getsound("swip")
        self._whistle_sound = ba.getsound("refWhistle")
        self.puck_model = ba.getmodel("puck")
        self.puck_tex = ba.gettexture("puckColor")
        self._puck_sound = ba.getsound("metalHit")
        self.puck_material = ba.Material()
        self.puck_material.add_actions(actions=(("modify_part_collision",
                                                 "friction", 0.5)))
        self.puck_material.add_actions(
            conditions=("they_have_material", ba.sharedobj('pickup_material')),
            actions=("modify_part_collision", "collide", False))
        self.puck_material.add_actions(
            conditions=(("we_are_younger_than", 100),
                        'and', ("they_have_material",
                                ba.sharedobj('object_material'))),
            actions=("modify_node_collision", "collide", False))
        self.puck_material.add_actions(
            conditions=("they_have_material",
                        ba.sharedobj('footing_material')),
            actions=("impact_sound", self._puck_sound, 0.2, 5))

        # Keep track of which player last touched the puck
        self.puck_material.add_actions(
            conditions=("they_have_material", ba.sharedobj('player_material')),
            actions=(("call", "at_connect",
                      self._handle_puck_player_collide), ))

        # We want the puck to kill powerups; not get stopped by them
        self.puck_material.add_actions(
            conditions=("they_have_material",
                        powerupbox.get_factory().powerup_material),
            actions=(("modify_part_collision", "physical", False),
                     ("message", "their_node", "at_connect", ba.DieMessage())))
        self._score_region_material = ba.Material()
        self._score_region_material.add_actions(
            conditions=("they_have_material", self.puck_material),
            actions=(("modify_part_collision", "collide",
                      True), ("modify_part_collision", "physical", False),
                     ("call", "at_connect", self._handle_score)))
        self._puck_spawn_pos: Optional[Sequence[float]] = None
        self._score_regions: Optional[List[ba.NodeActor]] = None
        self._puck: Optional[Puck] = None
Exemple #4
0
    def on_begin(self) -> None:
        super().on_begin()
        self.setup_standard_time_limit(self._time_limit)
        self.setup_standard_powerup_drops()
        self._flag_spawn_pos = self.map.get_flag_position(None)
        self.project_flag_stand(self._flag_spawn_pos)
        self._set_chosen_one_player(None)

        pos = self._flag_spawn_pos
        ba.timer(1.0, call=self._tick, repeat=True)

        mat = self._reset_region_material = ba.Material()
        mat.add_actions(conditions=('they_have_material',
                                    ba.sharedobj('player_material')),
                        actions=(('modify_part_collision', 'collide', True),
                                 ('modify_part_collision', 'physical', False),
                                 ('call', 'at_connect',
                                  ba.WeakCall(self._handle_reset_collide))))

        self._reset_region = ba.newnode('region',
                                        attrs={
                                            'position':
                                            (pos[0], pos[1] + 0.75, pos[2]),
                                            'scale': (0.5, 0.5, 0.5),
                                            'type':
                                            'sphere',
                                            'materials': [mat]
                                        })
Exemple #5
0
    def __init__(self, settings: Dict[str, Any]):
        from bastd.actor.scoreboard import Scoreboard
        super().__init__(settings)
        self._scoreboard = Scoreboard()
        self._swipsound = ba.getsound('swip')
        self._tick_sound = ba.getsound('tick')
        self._countdownsounds = {
            10: ba.getsound('announceTen'),
            9: ba.getsound('announceNine'),
            8: ba.getsound('announceEight'),
            7: ba.getsound('announceSeven'),
            6: ba.getsound('announceSix'),
            5: ba.getsound('announceFive'),
            4: ba.getsound('announceFour'),
            3: ba.getsound('announceThree'),
            2: ba.getsound('announceTwo'),
            1: ba.getsound('announceOne')
        }
        self._flag_pos: Optional[Sequence[float]] = None
        self._flag_state: Optional[int] = None
        self._flag: Optional[stdflag.Flag] = None
        self._flag_light: Optional[ba.Node] = None
        self._scoring_team: Optional[ReferenceType[ba.Team]] = None

        self._flag_region_material = ba.Material()
        self._flag_region_material.add_actions(
            conditions=('they_have_material', ba.sharedobj('player_material')),
            actions=(('modify_part_collision', 'collide',
                      True), ('modify_part_collision', 'physical', False),
                     ('call', 'at_connect',
                      ba.Call(self._handle_player_flag_region_collide, True)),
                     ('call', 'at_disconnect',
                      ba.Call(self._handle_player_flag_region_collide,
                              False))))
Exemple #6
0
    def on_begin(self) -> None:
        super().on_begin()
        self.setup_standard_time_limit(self.settings['Time Limit'])
        self.setup_standard_powerup_drops()
        self._flag_pos = self.map.get_flag_position(None)
        ba.timer(1.0, self._tick, repeat=True)
        self._flag_state = self.FLAG_NEW
        self.project_flag_stand(self._flag_pos)

        self._flag = stdflag.Flag(position=self._flag_pos,
                                  touchable=False,
                                  color=(1, 1, 1))
        self._flag_light = ba.newnode('light',
                                      attrs={
                                          'position': self._flag_pos,
                                          'intensity': 0.2,
                                          'height_attenuated': False,
                                          'radius': 0.4,
                                          'color': (0.2, 0.2, 0.2)
                                      })

        # Flag region.
        flagmats = [
            self._flag_region_material,
            ba.sharedobj('region_material')
        ]
        ba.newnode('region',
                   attrs={
                       'position': self._flag_pos,
                       'scale': (1.8, 1.8, 1.8),
                       'type': 'sphere',
                       'materials': flagmats
                   })
        self._update_flag_state()
Exemple #7
0
    def __init__(self, position: Sequence[float] = (0.0, 1.0, 0.0)):
        super().__init__()
        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, ba.Player] = {}
        self.scored = False
        assert activity is not None
        assert isinstance(activity, HockeyGame)
        pmats = [ba.sharedobj('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})
Exemple #8
0
    def __init__(self, position: Tuple[float, float, float] = (0.0, 1.0, 0.0)):
        super().__init__()
        activity = self.activity
        assert isinstance(activity, EasterEggHuntGame)

        # Spawn just above the provided point.
        self._spawn_pos = (position[0], position[1] + 1.0, position[2])
        ctex = (activity.egg_tex_1, activity.egg_tex_2,
                activity.egg_tex_3)[random.randrange(3)]
        mats = [ba.sharedobj('object_material'), activity.egg_material]
        self.node = ba.newnode("prop",
                               delegate=self,
                               attrs={
                                   'model': activity.egg_model,
                                   'color_texture': ctex,
                                   'body': 'capsule',
                                   'reflection': 'soft',
                                   'model_scale': 0.5,
                                   'bodyScale': 0.6,
                                   'density': 4.0,
                                   'reflection_scale': [0.15],
                                   'shadow_size': 0.6,
                                   'position': self._spawn_pos,
                                   'materials': mats
                               })
 def start(self) -> None:
     """Start the timer."""
     globalsnode = ba.sharedobj('globals')
     globalsnode.connectattr('time', self.inputnode, 'time1')
     self.inputnode.time2 = (globalsnode.time +
                             (self._timeremaining + 1) * 1000)
     self._timer = ba.Timer(1.0, self._update, repeat=True)
Exemple #10
0
 def on_transition_in(self) -> None:
     super().on_transition_in()
     pts = self.map.get_def_points('race_point')
     mat = self.race_region_material = ba.Material()
     mat.add_actions(conditions=('they_have_material',
                                 ba.sharedobj('player_material')),
                     actions=(('modify_part_collision', 'collide', True),
                              ('modify_part_collision', 'physical',
                               False), ('call', 'at_connect',
                                        self._handle_race_point_collide)))
     for rpt in pts:
         self._regions.append(RaceRegion(rpt, len(self._regions)))
Exemple #11
0
    def __init__(self, settings: Dict[str, Any]):
        from bastd.actor.scoreboard import Scoreboard
        super().__init__(settings)
        if self.settings_raw['Epic Mode']:
            self.slow_motion = True
        self._scoreboard = Scoreboard()
        self._score_sound = ba.getsound('score')
        self._swipsound = ba.getsound('swip')
        self._extraflagmat = ba.Material()
        self._flags: List[ConquestFlag] = []

        # We want flags to tell us they've been hit but not react physically.
        self._extraflagmat.add_actions(
            conditions=('they_have_material', ba.sharedobj('player_material')),
            actions=(('modify_part_collision', 'collide', True),
                     ('call', 'at_connect', self._handle_flag_player_collide)))
Exemple #12
0
    def on_begin(self) -> None:
        from bastd.actor.flag import Flag
        super().on_begin()
        self.setup_standard_time_limit(self.settings_raw['Time Limit'])
        self.setup_standard_powerup_drops()
        for team in self.teams:
            mat = self._base_region_materials[team.get_id()] = ba.Material()
            mat.add_actions(conditions=('they_have_material',
                                        ba.sharedobj('player_material')),
                            actions=(('modify_part_collision', 'collide',
                                      True), ('modify_part_collision',
                                              'physical', False),
                                     ('call', 'at_connect',
                                      ba.Call(self._handle_base_collide,
                                              team))))

        # Create a score region and flag for each team.
        for team in self.teams:
            team.gamedata['base_pos'] = self.map.get_flag_position(
                team.get_id())

            ba.newnode('light',
                       attrs={
                           'position': team.gamedata['base_pos'],
                           'intensity': 0.6,
                           'height_attenuated': False,
                           'volume_intensity_scale': 0.1,
                           'radius': 0.1,
                           'color': team.color
                       })

            self.project_flag_stand(team.gamedata['base_pos'])
            team.gamedata['flag'] = Flag(touchable=False,
                                         position=team.gamedata['base_pos'],
                                         color=team.color)
            basepos = team.gamedata['base_pos']
            ba.newnode('region',
                       owner=team.gamedata['flag'].node,
                       attrs={
                           'position':
                           (basepos[0], basepos[1] + 0.75, basepos[2]),
                           'scale': (0.5, 0.5, 0.5),
                           'type':
                           'sphere',
                           'materials':
                           [self._base_region_materials[team.get_id()]]
                       })
Exemple #13
0
    def __init__(self) -> None:
        """Instantiate a FlagFactory.

        You shouldn't need to do this; call bastd.actor.flag.get_factory() to
        get a shared instance.
        """

        self.flagmaterial = ba.Material()
        self.flagmaterial.add_actions(
            conditions=(('we_are_younger_than', 100),
                        'and', ('they_have_material',
                                ba.sharedobj('object_material'))),
            actions=('modify_node_collision', 'collide', False))

        self.flagmaterial.add_actions(
            conditions=('they_have_material',
                        ba.sharedobj('footing_material')),
            actions=(('message', 'our_node', 'at_connect', 'footing', 1),
                     ('message', 'our_node', 'at_disconnect', 'footing', -1)))

        self.impact_sound = ba.getsound('metalHit')
        self.skid_sound = ba.getsound('metalSkid')
        self.flagmaterial.add_actions(
            conditions=('they_have_material',
                        ba.sharedobj('footing_material')),
            actions=(('impact_sound', self.impact_sound, 2, 5),
                     ('skid_sound', self.skid_sound, 2, 5)))

        self.no_hit_material = ba.Material()
        self.no_hit_material.add_actions(
            conditions=(('they_have_material',
                         ba.sharedobj('pickup_material')),
                        'or', ('they_have_material',
                               ba.sharedobj('attack_material'))),
            actions=('modify_part_collision', 'collide', False))

        # We also don't want anything moving it.
        self.no_hit_material.add_actions(
            conditions=(('they_have_material',
                         ba.sharedobj('object_material')), 'or',
                        ('they_dont_have_material',
                         ba.sharedobj('footing_material'))),
            actions=(('modify_part_collision', 'collide', False),
                     ('modify_part_collision', 'physical', False)))

        self.flag_texture = ba.gettexture('flagColor')
Exemple #14
0
 def __init__(self, settings: Dict[str, Any]):
     from bastd.actor.scoreboard import Scoreboard
     super().__init__(settings)
     self._last_player_death_time = None
     self._scoreboard = Scoreboard()
     self.egg_model = ba.getmodel('egg')
     self.egg_tex_1 = ba.gettexture('eggTex1')
     self.egg_tex_2 = ba.gettexture('eggTex2')
     self.egg_tex_3 = ba.gettexture('eggTex3')
     self._collect_sound = ba.getsound('powerup01')
     self._pro_mode = settings.get('Pro Mode', False)
     self._max_eggs = 1.0
     self.egg_material = ba.Material()
     self.egg_material.add_actions(
         conditions=("they_have_material", ba.sharedobj('player_material')),
         actions=(("call", "at_connect", self._on_egg_player_collide), ))
     self._eggs: List[Egg] = []
     self._update_timer: Optional[ba.Timer] = None
     self._countdown: Optional[OnScreenCountdown] = None
     self._bots: Optional[spazbot.BotSet] = None
Exemple #15
0
    def __init__(self, settings: Dict[str, Any]):
        from bastd.actor.scoreboard import Scoreboard
        super().__init__(settings)
        self._scoreboard = Scoreboard()
        self._score_sound = ba.getsound('score')
        self._swipsound = ba.getsound('swip')
        self._extraflagmat = ba.Material()
        self._flags: List[ConquestFlag] = []
        self._epic_mode = bool(settings['Epic Mode'])
        self._time_limit = float(settings['Time Limit'])

        # Base class overrides.
        self.slow_motion = self._epic_mode
        self.default_music = (ba.MusicType.EPIC
                              if self._epic_mode else ba.MusicType.GRAND_ROMP)

        # We want flags to tell us they've been hit but not react physically.
        self._extraflagmat.add_actions(
            conditions=('they_have_material', ba.sharedobj('player_material')),
            actions=(('modify_part_collision', 'collide', True),
                     ('call', 'at_connect', self._handle_flag_player_collide)))
Exemple #16
0
    def __init__(self, settings: Dict[str, Any]):
        super().__init__(settings)
        self._last_player_death_time = None
        self._scoreboard = Scoreboard()
        self.egg_model = ba.getmodel('egg')
        self.egg_tex_1 = ba.gettexture('eggTex1')
        self.egg_tex_2 = ba.gettexture('eggTex2')
        self.egg_tex_3 = ba.gettexture('eggTex3')
        self._collect_sound = ba.getsound('powerup01')
        self._pro_mode = settings.get('Pro Mode', False)
        self._max_eggs = 1.0
        self.egg_material = ba.Material()
        self.egg_material.add_actions(
            conditions=('they_have_material', ba.sharedobj('player_material')),
            actions=(('call', 'at_connect', self._on_egg_player_collide), ))
        self._eggs: List[Egg] = []
        self._update_timer: Optional[ba.Timer] = None
        self._countdown: Optional[OnScreenCountdown] = None
        self._bots: Optional[BotSet] = None

        # Base class overrides
        self.default_music = ba.MusicType.FORWARD_MARCH
Exemple #17
0
    def create_team(self, sessionteam: ba.SessionTeam) -> Team:
        base_pos = self.map.get_flag_position(sessionteam.id)
        ba.newnode('light',
                   attrs={
                       'position': base_pos,
                       'intensity': 0.6,
                       'height_attenuated': False,
                       'volume_intensity_scale': 0.1,
                       'radius': 0.1,
                       'color': sessionteam.color
                   })
        self.project_flag_stand(base_pos)
        flag = Flag(touchable=False,
                    position=base_pos,
                    color=sessionteam.color)
        team = Team(base_pos=base_pos, flag=flag)

        mat = self._base_region_materials[sessionteam.id] = ba.Material()
        mat.add_actions(
            conditions=('they_have_material', ba.sharedobj('player_material')),
            actions=(
                ('modify_part_collision', 'collide', True),
                ('modify_part_collision', 'physical', False),
                ('call', 'at_connect', ba.Call(self._handle_base_collide,
                                               team)),
            ),
        )

        ba.newnode(
            'region',
            owner=flag.node,
            attrs={
                'position': (base_pos[0], base_pos[1] + 0.75, base_pos[2]),
                'scale': (0.5, 0.5, 0.5),
                'type': 'sphere',
                'materials': [self._base_region_materials[sessionteam.id]]
            })

        return team
Exemple #18
0
    def __init__(self, settings: Dict[str, Any]):
        super().__init__(settings)
        self._scoreboard = Scoreboard()
        self._swipsound = ba.getsound('swip')
        self._tick_sound = ba.getsound('tick')
        self._countdownsounds = {
            10: ba.getsound('announceTen'),
            9: ba.getsound('announceNine'),
            8: ba.getsound('announceEight'),
            7: ba.getsound('announceSeven'),
            6: ba.getsound('announceSix'),
            5: ba.getsound('announceFive'),
            4: ba.getsound('announceFour'),
            3: ba.getsound('announceThree'),
            2: ba.getsound('announceTwo'),
            1: ba.getsound('announceOne')
        }
        self._flag_pos: Optional[Sequence[float]] = None
        self._flag_state: Optional[FlagState] = None
        self._flag: Optional[Flag] = None
        self._flag_light: Optional[ba.Node] = None
        self._scoring_team: Optional[ReferenceType[Team]] = None
        self._hold_time = int(settings['Hold Time'])
        self._time_limit = float(settings['Time Limit'])
        self._flag_region_material = ba.Material()
        self._flag_region_material.add_actions(
            conditions=('they_have_material', ba.sharedobj('player_material')),
            actions=(
                ('modify_part_collision', 'collide', True),
                ('modify_part_collision', 'physical', False),
                ('call', 'at_connect',
                 ba.Call(self._handle_player_flag_region_collide, True)),
                ('call', 'at_disconnect',
                 ba.Call(self._handle_player_flag_region_collide, False)),
            ))

        # Base class overrides.
        self.default_music = ba.MusicType.SCARY
Exemple #19
0
    def __init__(self,
                 position: Sequence[float] = (0.0, 1.0, 0.0),
                 velocity: Sequence[float] = (0.0, 0.0, 0.0),
                 bomb_type: str = 'normal',
                 blast_radius: float = 2.0,
                 source_player: ba.Player = None,
                 owner: ba.Node = None):
        """Create a new Bomb.

        bomb_type can be 'ice','impact','land_mine','normal','sticky', or
        'tnt'. Note that for impact or land_mine bombs you have to call arm()
        before they will go off.
        """
        super().__init__()

        factory = get_factory()

        if bomb_type not in ('ice', 'impact', 'land_mine', 'normal', 'sticky',
                             'tnt'):
            raise ValueError('invalid bomb type: ' + bomb_type)
        self.bomb_type = bomb_type

        self._exploded = False

        self.texture_sequence: Optional[ba.Node] = None

        if self.bomb_type == 'sticky':
            self._last_sticky_sound_time = 0.0

        self.blast_radius = blast_radius
        if self.bomb_type == 'ice':
            self.blast_radius *= 1.2
        elif self.bomb_type == 'impact':
            self.blast_radius *= 0.7
        elif self.bomb_type == 'land_mine':
            self.blast_radius *= 0.7
        elif self.bomb_type == 'tnt':
            self.blast_radius *= 1.45

        self._explode_callbacks: List[Callable[[Bomb, Blast], Any]] = []

        # the player this came from
        self.source_player = source_player

        # 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.hit_type = 'explosion'
        self.hit_subtype = self.bomb_type

        # if no owner was provided, use an unconnected node ref
        # (nevermind; trying to use None in these type cases instead)
        # if owner is None:
        #     owner = ba.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?..
        materials: Tuple[ba.Material, ...]
        if self.bomb_type == 'tnt':
            materials = (factory.bomb_material,
                         ba.sharedobj('footing_material'),
                         ba.sharedobj('object_material'))
        else:
            materials = (factory.bomb_material,
                         ba.sharedobj('object_material'))

        if self.bomb_type == 'impact':
            materials = materials + (factory.impact_blast_material, )
        elif self.bomb_type == 'land_mine':
            materials = materials + (factory.land_mine_no_explode_material, )

        if self.bomb_type == 'sticky':
            materials = materials + (factory.sticky_material, )
        else:
            materials = materials + (factory.normal_sound_material, )

        if self.bomb_type == 'land_mine':
            fuse_time = None
            self.node = ba.newnode('prop',
                                   delegate=self,
                                   attrs={
                                       'position': position,
                                       'velocity': velocity,
                                       'model': factory.land_mine_model,
                                       'light_model': factory.land_mine_model,
                                       'body': 'landMine',
                                       'shadow_size': 0.44,
                                       'color_texture': factory.land_mine_tex,
                                       'reflection': 'powerup',
                                       'reflection_scale': [1.0],
                                       'materials': materials
                                   })

        elif self.bomb_type == 'tnt':
            fuse_time = None
            self.node = ba.newnode('prop',
                                   delegate=self,
                                   attrs={
                                       'position': position,
                                       'velocity': velocity,
                                       'model': factory.tnt_model,
                                       'light_model': factory.tnt_model,
                                       'body': 'crate',
                                       'shadow_size': 0.5,
                                       'color_texture': factory.tnt_tex,
                                       'reflection': 'soft',
                                       'reflection_scale': [0.23],
                                       'materials': materials
                                   })

        elif self.bomb_type == 'impact':
            fuse_time = 20.0
            self.node = ba.newnode('prop',
                                   delegate=self,
                                   attrs={
                                       'position': position,
                                       'velocity': velocity,
                                       'body': 'sphere',
                                       'model': factory.impact_bomb_model,
                                       'shadow_size': 0.3,
                                       'color_texture': factory.impact_tex,
                                       'reflection': 'powerup',
                                       'reflection_scale': [1.5],
                                       'materials': materials
                                   })
            self.arm_timer = ba.Timer(
                0.2, ba.WeakCall(self.handlemessage, ArmMessage()))
            self.warn_timer = ba.Timer(
                fuse_time - 1.7, ba.WeakCall(self.handlemessage,
                                             WarnMessage()))

        else:
            fuse_time = 3.0
            if self.bomb_type == 'sticky':
                sticky = True
                model = factory.sticky_bomb_model
                rtype = 'sharper'
                rscale = 1.8
            else:
                sticky = False
                model = factory.bomb_model
                rtype = 'sharper'
                rscale = 1.8
            if self.bomb_type == 'ice':
                tex = factory.ice_tex
            elif self.bomb_type == 'sticky':
                tex = factory.sticky_tex
            else:
                tex = factory.regular_tex
            self.node = ba.newnode('bomb',
                                   delegate=self,
                                   attrs={
                                       'position': position,
                                       'velocity': velocity,
                                       'model': model,
                                       'shadow_size': 0.3,
                                       'color_texture': tex,
                                       'sticky': sticky,
                                       'owner': owner,
                                       'reflection': rtype,
                                       'reflection_scale': [rscale],
                                       'materials': materials
                                   })

            sound = ba.newnode('sound',
                               owner=self.node,
                               attrs={
                                   'sound': factory.fuse_sound,
                                   'volume': 0.25
                               })
            self.node.connectattr('position', sound, 'position')
            ba.animate(self.node, 'fuse_length', {0.0: 1.0, fuse_time: 0.0})

        # Light the fuse!!!
        if self.bomb_type not in ('land_mine', 'tnt'):
            assert fuse_time is not None
            ba.timer(fuse_time,
                     ba.WeakCall(self.handlemessage, ExplodeMessage()))

        ba.animate(self.node, 'model_scale', {0: 0, 0.2: 1.3, 0.26: 1})
Exemple #20
0
    def __init__(self,
                 position: Sequence[float] = (0.0, 1.0, 0.0),
                 velocity: Sequence[float] = (0.0, 0.0, 0.0),
                 blast_radius: float = 2.0,
                 blast_type: str = 'normal',
                 source_player: ba.Player = None,
                 hit_type: str = 'explosion',
                 hit_subtype: str = 'normal'):
        """Instantiate with given values."""

        # bah; get off my lawn!
        # pylint: disable=too-many-locals
        # pylint: disable=too-many-statements

        super().__init__()

        factory = get_factory()

        self.blast_type = blast_type
        self.source_player = source_player
        self.hit_type = hit_type
        self.hit_subtype = hit_subtype
        self.radius = blast_radius

        # set our position a bit lower so we throw more things upward
        rmats = (factory.blast_material, ba.sharedobj('attack_material'))
        self.node = ba.newnode('region',
                               delegate=self,
                               attrs={
                                   'position': (position[0], position[1] - 0.1,
                                                position[2]),
                                   'scale':
                                   (self.radius, self.radius, self.radius),
                                   'type':
                                   'sphere',
                                   'materials':
                                   rmats
                               })

        ba.timer(0.05, self.node.delete)

        # throw in an explosion and flash
        evel = (velocity[0], max(-1.0, velocity[1]), velocity[2])
        explosion = ba.newnode('explosion',
                               attrs={
                                   'position': position,
                                   'velocity': evel,
                                   'radius': self.radius,
                                   'big': (self.blast_type == 'tnt')
                               })
        if self.blast_type == 'ice':
            explosion.color = (0, 0.05, 0.4)

        ba.timer(1.0, explosion.delete)

        if self.blast_type != 'ice':
            ba.emitfx(position=position,
                      velocity=velocity,
                      count=int(1.0 + random.random() * 4),
                      emit_type='tendrils',
                      tendril_type='thin_smoke')
        ba.emitfx(position=position,
                  velocity=velocity,
                  count=int(4.0 + random.random() * 4),
                  emit_type='tendrils',
                  tendril_type='ice' if self.blast_type == 'ice' else 'smoke')
        ba.emitfx(position=position,
                  emit_type='distortion',
                  spread=1.0 if self.blast_type == 'tnt' else 2.0)

        # and emit some shrapnel..
        if self.blast_type == 'ice':

            def emit() -> None:
                ba.emitfx(position=position,
                          velocity=velocity,
                          count=30,
                          spread=2.0,
                          scale=0.4,
                          chunk_type='ice',
                          emit_type='stickers')

            # looks better if we delay a bit
            ba.timer(0.05, emit)

        elif self.blast_type == 'sticky':

            def emit() -> None:
                ba.emitfx(position=position,
                          velocity=velocity,
                          count=int(4.0 + random.random() * 8),
                          spread=0.7,
                          chunk_type='slime')
                ba.emitfx(position=position,
                          velocity=velocity,
                          count=int(4.0 + random.random() * 8),
                          scale=0.5,
                          spread=0.7,
                          chunk_type='slime')
                ba.emitfx(position=position,
                          velocity=velocity,
                          count=15,
                          scale=0.6,
                          chunk_type='slime',
                          emit_type='stickers')
                ba.emitfx(position=position,
                          velocity=velocity,
                          count=20,
                          scale=0.7,
                          chunk_type='spark',
                          emit_type='stickers')
                ba.emitfx(position=position,
                          velocity=velocity,
                          count=int(6.0 + random.random() * 12),
                          scale=0.8,
                          spread=1.5,
                          chunk_type='spark')

            # looks better if we delay a bit
            ba.timer(0.05, emit)

        elif self.blast_type == 'impact':  # regular bomb shrapnel

            def emit() -> None:
                ba.emitfx(position=position,
                          velocity=velocity,
                          count=int(4.0 + random.random() * 8),
                          scale=0.8,
                          chunk_type='metal')
                ba.emitfx(position=position,
                          velocity=velocity,
                          count=int(4.0 + random.random() * 8),
                          scale=0.4,
                          chunk_type='metal')
                ba.emitfx(position=position,
                          velocity=velocity,
                          count=20,
                          scale=0.7,
                          chunk_type='spark',
                          emit_type='stickers')
                ba.emitfx(position=position,
                          velocity=velocity,
                          count=int(8.0 + random.random() * 15),
                          scale=0.8,
                          spread=1.5,
                          chunk_type='spark')

            # looks better if we delay a bit
            ba.timer(0.05, emit)

        else:  # regular or land mine bomb shrapnel

            def emit() -> None:
                if self.blast_type != 'tnt':
                    ba.emitfx(position=position,
                              velocity=velocity,
                              count=int(4.0 + random.random() * 8),
                              chunk_type='rock')
                    ba.emitfx(position=position,
                              velocity=velocity,
                              count=int(4.0 + random.random() * 8),
                              scale=0.5,
                              chunk_type='rock')
                ba.emitfx(position=position,
                          velocity=velocity,
                          count=30,
                          scale=1.0 if self.blast_type == 'tnt' else 0.7,
                          chunk_type='spark',
                          emit_type='stickers')
                ba.emitfx(position=position,
                          velocity=velocity,
                          count=int(18.0 + random.random() * 20),
                          scale=1.0 if self.blast_type == 'tnt' else 0.8,
                          spread=1.5,
                          chunk_type='spark')

                # tnt throws splintery chunks
                if self.blast_type == 'tnt':

                    def emit_splinters() -> None:
                        ba.emitfx(position=position,
                                  velocity=velocity,
                                  count=int(20.0 + random.random() * 25),
                                  scale=0.8,
                                  spread=1.0,
                                  chunk_type='splinter')

                    ba.timer(0.01, emit_splinters)

                # every now and then do a sparky one
                if self.blast_type == 'tnt' or random.random() < 0.1:

                    def emit_extra_sparks() -> None:
                        ba.emitfx(position=position,
                                  velocity=velocity,
                                  count=int(10.0 + random.random() * 20),
                                  scale=0.8,
                                  spread=1.5,
                                  chunk_type='spark')

                    ba.timer(0.02, emit_extra_sparks)

            # looks better if we delay a bit
            ba.timer(0.05, emit)

        lcolor = ((0.6, 0.6, 1.0) if self.blast_type == 'ice' else
                  (1, 0.3, 0.1))
        light = ba.newnode('light',
                           attrs={
                               'position': position,
                               'volume_intensity_scale': 10.0,
                               'color': lcolor
                           })

        scl = random.uniform(0.6, 0.9)
        scorch_radius = light_radius = self.radius
        if self.blast_type == 'tnt':
            light_radius *= 1.4
            scorch_radius *= 1.15
            scl *= 3.0

        iscale = 1.6
        ba.animate(
            light, 'intensity', {
                0: 2.0 * iscale,
                scl * 0.02: 0.1 * iscale,
                scl * 0.025: 0.2 * iscale,
                scl * 0.05: 17.0 * iscale,
                scl * 0.06: 5.0 * iscale,
                scl * 0.08: 4.0 * iscale,
                scl * 0.2: 0.6 * iscale,
                scl * 2.0: 0.00 * iscale,
                scl * 3.0: 0.0
            })
        ba.animate(
            light, 'radius', {
                0: light_radius * 0.2,
                scl * 0.05: light_radius * 0.55,
                scl * 0.1: light_radius * 0.3,
                scl * 0.3: light_radius * 0.15,
                scl * 1.0: light_radius * 0.05
            })
        ba.timer(scl * 3.0, light.delete)

        # make a scorch that fades over time
        scorch = ba.newnode('scorch',
                            attrs={
                                'position': position,
                                'size': scorch_radius * 0.5,
                                'big': (self.blast_type == 'tnt')
                            })
        if self.blast_type == 'ice':
            scorch.color = (1, 1, 1.5)

        ba.animate(scorch, 'presence', {3.000: 1, 13.000: 0})
        ba.timer(13.0, scorch.delete)

        if self.blast_type == 'ice':
            ba.playsound(factory.hiss_sound, position=light.position)

        lpos = light.position
        ba.playsound(factory.random_explode_sound(), position=lpos)
        ba.playsound(factory.debris_fall_sound, position=lpos)

        ba.camerashake(intensity=5.0 if self.blast_type == 'tnt' else 1.0)

        # tnt is more epic..
        if self.blast_type == 'tnt':
            ba.playsound(factory.random_explode_sound(), position=lpos)

            def _extra_boom() -> None:
                ba.playsound(factory.random_explode_sound(), position=lpos)

            ba.timer(0.25, _extra_boom)

            def _extra_debris_sound() -> None:
                ba.playsound(factory.debris_fall_sound, position=lpos)
                ba.playsound(factory.wood_debris_fall_sound, position=lpos)

            ba.timer(0.4, _extra_debris_sound)
Exemple #21
0
    def __init__(self) -> None:
        """Instantiate a BombFactory.

        You shouldn't need to do this; call bastd.actor.bomb.get_factory()
        to get a shared instance.
        """

        self.bomb_model = ba.getmodel('bomb')
        self.sticky_bomb_model = ba.getmodel('bombSticky')
        self.impact_bomb_model = ba.getmodel('impactBomb')
        self.land_mine_model = ba.getmodel('landMine')
        self.tnt_model = ba.getmodel('tnt')

        self.regular_tex = ba.gettexture('bombColor')
        self.ice_tex = ba.gettexture('bombColorIce')
        self.sticky_tex = ba.gettexture('bombStickyColor')
        self.impact_tex = ba.gettexture('impactBombColor')
        self.impact_lit_tex = ba.gettexture('impactBombColorLit')
        self.land_mine_tex = ba.gettexture('landMine')
        self.land_mine_lit_tex = ba.gettexture('landMineLit')
        self.tnt_tex = ba.gettexture('tnt')

        self.hiss_sound = ba.getsound('hiss')
        self.debris_fall_sound = ba.getsound('debrisFall')
        self.wood_debris_fall_sound = ba.getsound('woodDebrisFall')

        self.explode_sounds = (ba.getsound('explosion01'),
                               ba.getsound('explosion02'),
                               ba.getsound('explosion03'),
                               ba.getsound('explosion04'),
                               ba.getsound('explosion05'))

        self.freeze_sound = ba.getsound('freeze')
        self.fuse_sound = ba.getsound('fuse01')
        self.activate_sound = ba.getsound('activateBeep')
        self.warn_sound = ba.getsound('warnBeep')

        # set up our material so new bombs don't collide with objects
        # that they are initially overlapping
        self.bomb_material = ba.Material()
        self.normal_sound_material = ba.Material()
        self.sticky_material = ba.Material()

        self.bomb_material.add_actions(
            conditions=((('we_are_younger_than', 100), 'or',
                         ('they_are_younger_than', 100)),
                        'and', ('they_have_material',
                                ba.sharedobj('object_material'))),
            actions=('modify_node_collision', 'collide', False))

        # we want pickup materials to always hit us even if we're currently not
        # colliding with their node (generally due to the above rule)
        self.bomb_material.add_actions(
            conditions=('they_have_material', ba.sharedobj('pickup_material')),
            actions=('modify_part_collision', 'use_node_collide', False))

        self.bomb_material.add_actions(actions=('modify_part_collision',
                                                'friction', 0.3))

        self.land_mine_no_explode_material = ba.Material()
        self.land_mine_blast_material = ba.Material()
        self.land_mine_blast_material.add_actions(
            conditions=(('we_are_older_than',
                         200), 'and', ('they_are_older_than',
                                       200), 'and', ('eval_colliding', ),
                        'and', (('they_dont_have_material',
                                 self.land_mine_no_explode_material), 'and',
                                (('they_have_material',
                                  ba.sharedobj('object_material')), 'or',
                                 ('they_have_material',
                                  ba.sharedobj('player_material'))))),
            actions=('message', 'our_node', 'at_connect', ImpactMessage()))

        self.impact_blast_material = ba.Material()
        self.impact_blast_material.add_actions(
            conditions=(('we_are_older_than',
                         200), 'and', ('they_are_older_than',
                                       200), 'and', ('eval_colliding', ),
                        'and', (('they_have_material',
                                 ba.sharedobj('footing_material')), 'or',
                                ('they_have_material',
                                 ba.sharedobj('object_material')))),
            actions=('message', 'our_node', 'at_connect', ImpactMessage()))

        self.blast_material = ba.Material()
        self.blast_material.add_actions(
            conditions=(('they_have_material',
                         ba.sharedobj('object_material'))),
            actions=(('modify_part_collision', 'collide', True),
                     ('modify_part_collision', 'physical',
                      False), ('message', 'our_node', 'at_connect',
                               ExplodeHitMessage())))

        self.dink_sounds = (ba.getsound('bombDrop01'),
                            ba.getsound('bombDrop02'))
        self.sticky_impact_sound = ba.getsound('stickyImpact')
        self.roll_sound = ba.getsound('bombRoll01')

        # collision sounds
        self.normal_sound_material.add_actions(
            conditions=('they_have_material',
                        ba.sharedobj('footing_material')),
            actions=(('impact_sound', self.dink_sounds, 2, 0.8),
                     ('roll_sound', self.roll_sound, 3, 6)))

        self.sticky_material.add_actions(actions=(('modify_part_collision',
                                                   'stiffness', 0.1),
                                                  ('modify_part_collision',
                                                   'damping', 1.0)))

        self.sticky_material.add_actions(
            conditions=(('they_have_material',
                         ba.sharedobj('player_material')),
                        'or', ('they_have_material',
                               ba.sharedobj('footing_material'))),
            actions=('message', 'our_node', 'at_connect', SplatMessage()))
Exemple #22
0
    def __init__(self,
                 position: Sequence[float] = (0.0, 1.0, 0.0),
                 poweruptype: str = 'triple_bombs',
                 expire: bool = True):
        """Create a powerup-box of the requested type at the given position.

        see ba.Powerup.poweruptype for valid type strings.
        """

        super().__init__()

        factory = get_factory()
        self.poweruptype = poweruptype
        self._powersgiven = False

        if poweruptype == 'triple_bombs':
            tex = factory.tex_bomb
        elif poweruptype == 'punch':
            tex = factory.tex_punch
        elif poweruptype == 'ice_bombs':
            tex = factory.tex_ice_bombs
        elif poweruptype == 'impact_bombs':
            tex = factory.tex_impact_bombs
        elif poweruptype == 'land_mines':
            tex = factory.tex_land_mines
        elif poweruptype == 'sticky_bombs':
            tex = factory.tex_sticky_bombs
        elif poweruptype == 'shield':
            tex = factory.tex_shield
        elif poweruptype == 'health':
            tex = factory.tex_health
        elif poweruptype == 'curse':
            tex = factory.tex_curse
        else:
            raise ValueError('invalid poweruptype: ' + str(poweruptype))

        if len(position) != 3:
            raise ValueError('expected 3 floats for position')

        self.node = ba.newnode(
            'prop',
            delegate=self,
            attrs={
                'body': 'box',
                'position': position,
                'model': factory.model,
                'light_model': factory.model_simple,
                'shadow_size': 0.5,
                'color_texture': tex,
                'reflection': 'powerup',
                'reflection_scale': [1.0],
                'materials': (factory.powerup_material,
                              ba.sharedobj('object_material'))
            })  # yapf: disable

        # Animate in.
        curve = ba.animate(self.node, 'model_scale', {0: 0, 0.14: 1.6, 0.2: 1})
        ba.timer(0.2, curve.delete)

        if expire:
            ba.timer(DEFAULT_POWERUP_INTERVAL - 2.5,
                     ba.WeakCall(self._start_flashing))
            ba.timer(DEFAULT_POWERUP_INTERVAL - 1.0,
                     ba.WeakCall(self.handlemessage, ba.DieMessage()))
Exemple #23
0
    def __init__(self,
                 position: Sequence[float] = (0.0, 1.0, 0.0),
                 color: Sequence[float] = (1.0, 1.0, 1.0),
                 materials: Sequence[ba.Material] = None,
                 touchable: bool = True,
                 dropped_timeout: int = None):
        """Instantiate a flag.

        If 'touchable' is False, the flag will only touch terrain;
        useful for things like king-of-the-hill where players should
        not be moving the flag around.

        'materials can be a list of extra ba.Materials to apply to the flag.

        If 'dropped_timeout' is provided (in seconds), the flag will die
        after remaining untouched for that long once it has been moved
        from its initial position.
        """

        super().__init__()

        self._initial_position: Optional[Sequence[float]] = None
        self._has_moved = False
        factory = get_factory()

        if materials is None:
            materials = []
        elif not isinstance(materials, list):
            # In case they passed a tuple or whatnot.
            materials = list(materials)
        if not touchable:
            materials = [factory.no_hit_material] + materials

        finalmaterials = (
            [ba.sharedobj('object_material'), factory.flagmaterial] +
            materials)
        self.node = ba.newnode("flag",
                               attrs={
                                   'position':
                                   (position[0], position[1] + 0.75,
                                    position[2]),
                                   'color_texture':
                                   factory.flag_texture,
                                   'color':
                                   color,
                                   'materials':
                                   finalmaterials
                               },
                               delegate=self)

        if dropped_timeout is not None:
            dropped_timeout = int(dropped_timeout)
        self._dropped_timeout = dropped_timeout
        self._counter: Optional[ba.Node]
        if self._dropped_timeout is not None:
            self._count = self._dropped_timeout
            self._tick_timer = ba.Timer(1.0,
                                        call=ba.WeakCall(self._tick),
                                        repeat=True)
            self._counter = ba.newnode('text',
                                       owner=self.node,
                                       attrs={
                                           'in_world': True,
                                           'color': (1, 1, 1, 0.7),
                                           'scale': 0.015,
                                           'shadow': 0.5,
                                           'flatness': 1.0,
                                           'h_align': 'center'
                                       })
        else:
            self._counter = None

        self._held_count = 0
        self._score_text: Optional[ba.Node] = None
        self._score_text_hide_timer: Optional[ba.Timer] = None
Exemple #24
0
    def __init__(self) -> None:
        """Instantiate a factory object."""
        self.impact_sounds_medium = (ba.getsound('impactMedium'),
                                     ba.getsound('impactMedium2'))
        self.impact_sounds_hard = (ba.getsound('impactHard'),
                                   ba.getsound('impactHard2'),
                                   ba.getsound('impactHard3'))
        self.impact_sounds_harder = (ba.getsound('bigImpact'),
                                     ba.getsound('bigImpact2'))
        self.single_player_death_sound = ba.getsound('playerDeath')
        self.punch_sound = ba.getsound('punch01')
        self.punch_sound_strong = (ba.getsound('punchStrong01'),
                                   ba.getsound('punchStrong02'))
        self.punch_sound_stronger = ba.getsound('superPunch')
        self.swish_sound = ba.getsound('punchSwish')
        self.block_sound = ba.getsound('block')
        self.shatter_sound = ba.getsound('shatter')
        self.splatter_sound = ba.getsound('splatter')
        self.spaz_material = ba.Material()
        self.roller_material = ba.Material()
        self.punch_material = ba.Material()
        self.pickup_material = ba.Material()
        self.curse_material = ba.Material()

        footing_material = ba.sharedobj('footing_material')
        object_material = ba.sharedobj('object_material')
        player_material = ba.sharedobj('player_material')
        region_material = ba.sharedobj('region_material')

        # send footing messages to spazzes so they know when they're on solid
        # ground.
        # eww this should really just be built into the spaz node
        self.roller_material.add_actions(
            conditions=('they_have_material', footing_material),
            actions=(('message', 'our_node', 'at_connect', 'footing', 1),
                     ('message', 'our_node', 'at_disconnect', 'footing', -1)))

        self.spaz_material.add_actions(
            conditions=('they_have_material', footing_material),
            actions=(('message', 'our_node', 'at_connect', 'footing', 1),
                     ('message', 'our_node', 'at_disconnect', 'footing', -1)))
        # punches
        self.punch_material.add_actions(
            conditions=('they_are_different_node_than_us', ),
            actions=(('modify_part_collision', 'collide',
                      True), ('modify_part_collision', 'physical', False),
                     ('message', 'our_node', 'at_connect',
                      basespaz.PunchHitMessage())))
        # pickups
        self.pickup_material.add_actions(
            conditions=(('they_are_different_node_than_us', ), 'and',
                        ('they_have_material', object_material)),
            actions=(('modify_part_collision', 'collide',
                      True), ('modify_part_collision', 'physical', False),
                     ('message', 'our_node', 'at_connect',
                      basespaz.PickupMessage())))
        # curse
        self.curse_material.add_actions(
            conditions=(('they_are_different_node_than_us', ), 'and',
                        ('they_have_material', player_material)),
            actions=('message', 'our_node', 'at_connect',
                     basespaz.CurseExplodeMessage()))

        self.foot_impact_sounds = (ba.getsound('footImpact01'),
                                   ba.getsound('footImpact02'),
                                   ba.getsound('footImpact03'))

        self.foot_skid_sound = ba.getsound('skid01')
        self.foot_roll_sound = ba.getsound('scamper01')

        self.roller_material.add_actions(
            conditions=('they_have_material', footing_material),
            actions=(('impact_sound', self.foot_impact_sounds, 1,
                      0.2), ('skid_sound', self.foot_skid_sound, 20, 0.3),
                     ('roll_sound', self.foot_roll_sound, 20, 3.0)))

        self.skid_sound = ba.getsound('gravelSkid')

        self.spaz_material.add_actions(
            conditions=('they_have_material', footing_material),
            actions=(('impact_sound', self.foot_impact_sounds, 20,
                      6), ('skid_sound', self.skid_sound, 2.0, 1),
                     ('roll_sound', self.skid_sound, 2.0, 1)))

        self.shield_up_sound = ba.getsound('shieldUp')
        self.shield_down_sound = ba.getsound('shieldDown')
        self.shield_hit_sound = ba.getsound('shieldHit')

        # we don't want to collide with stuff we're initially overlapping
        # (unless its marked with a special region material)
        self.spaz_material.add_actions(
            conditions=((('we_are_younger_than', 51), 'and',
                         ('they_are_different_node_than_us', )), 'and',
                        ('they_dont_have_material', region_material)),
            actions=('modify_node_collision', 'collide', False))

        self.spaz_media: Dict[str, Any] = {}

        # lets load some basic rules (allows them to be tweaked from the
        # master server)
        self.shield_decay_rate = _ba.get_account_misc_read_val('rsdr', 10.0)
        self.punch_cooldown = _ba.get_account_misc_read_val('rpc', 400)
        self.punch_cooldown_gloves = (_ba.get_account_misc_read_val(
            'rpcg', 300))
        self.punch_power_scale = _ba.get_account_misc_read_val('rpp', 1.2)
        self.punch_power_scale_gloves = (_ba.get_account_misc_read_val(
            'rppg', 1.4))
        self.max_shield_spillover_damage = (_ba.get_account_misc_read_val(
            'rsms', 500))
Exemple #25
0
    def on_begin(self) -> None:
        # FIXME: Split this up a bit.
        # pylint: disable=too-many-statements
        from bastd.actor import controlsguide
        super().on_begin()

        # Show controls help in kiosk mode.
        if ba.app.kiosk_mode:
            controlsguide.ControlsGuide(delay=3.0, lifespan=10.0,
                                        bright=True).autoretain()
        assert self.initial_player_info is not None
        abot: Type[spazbot.SpazBot]
        bbot: Type[spazbot.SpazBot]
        cbot: Type[spazbot.SpazBot]
        if self._preset in ['rookie', 'rookie_easy']:
            self._exclude_powerups = ['curse']
            self._have_tnt = False
            abot = (spazbot.BrawlerBotLite
                    if self._preset == 'rookie_easy' else spazbot.BrawlerBot)
            self._bot_types_initial = [abot] * len(self.initial_player_info)
            bbot = (spazbot.BomberBotLite
                    if self._preset == 'rookie_easy' else spazbot.BomberBot)
            self._bot_types_7 = (
                [bbot] * (1 if len(self.initial_player_info) < 3 else 2))
            cbot = (spazbot.BomberBot
                    if self._preset == 'rookie_easy' else spazbot.TriggerBot)
            self._bot_types_14 = (
                [cbot] * (1 if len(self.initial_player_info) < 3 else 2))
        elif self._preset == 'tournament':
            self._exclude_powerups = []
            self._have_tnt = True
            self._bot_types_initial = (
                [spazbot.BrawlerBot] *
                (1 if len(self.initial_player_info) < 2 else 2))
            self._bot_types_7 = (
                [spazbot.TriggerBot] *
                (1 if len(self.initial_player_info) < 3 else 2))
            self._bot_types_14 = (
                [spazbot.ChargerBot] *
                (1 if len(self.initial_player_info) < 4 else 2))
        elif self._preset in ['pro', 'pro_easy', 'tournament_pro']:
            self._exclude_powerups = ['curse']
            self._have_tnt = True
            self._bot_types_initial = [spazbot.ChargerBot] * len(
                self.initial_player_info)
            abot = (spazbot.BrawlerBot
                    if self._preset == 'pro' else spazbot.BrawlerBotLite)
            typed_bot_list: List[Type[spazbot.SpazBot]] = []
            self._bot_types_7 = (
                typed_bot_list + [abot] + [spazbot.BomberBot] *
                (1 if len(self.initial_player_info) < 3 else 2))
            bbot = (spazbot.TriggerBotPro
                    if self._preset == 'pro' else spazbot.TriggerBot)
            self._bot_types_14 = (
                [bbot] * (1 if len(self.initial_player_info) < 3 else 2))
        elif self._preset in ['uber', 'uber_easy']:
            self._exclude_powerups = []
            self._have_tnt = True
            abot = (spazbot.BrawlerBotPro
                    if self._preset == 'uber' else spazbot.BrawlerBot)
            bbot = (spazbot.TriggerBotPro
                    if self._preset == 'uber' else spazbot.TriggerBot)
            typed_bot_list_2: List[Type[spazbot.SpazBot]] = []
            self._bot_types_initial = (typed_bot_list_2 + [spazbot.StickyBot] +
                                       [abot] * len(self.initial_player_info))
            self._bot_types_7 = (
                [bbot] * (1 if len(self.initial_player_info) < 3 else 2))
            self._bot_types_14 = (
                [spazbot.ExplodeyBot] *
                (1 if len(self.initial_player_info) < 3 else 2))
        else:
            raise Exception()

        self.setup_low_life_warning_sound()

        self._drop_powerups(standard_points=True)
        ba.timer(4.0, self._start_powerup_drops)

        # Make a bogus team for our bots.
        bad_team_name = self.get_team_display_string('Bad Guys')
        self._bot_team = ba.Team(1, bad_team_name, (0.5, 0.4, 0.4))

        for team in [self.teams[0], self._bot_team]:
            team.gamedata['score'] = 0

        self.update_scores()

        # Time display.
        starttime_ms = ba.time(timeformat=ba.TimeFormat.MILLISECONDS)
        assert isinstance(starttime_ms, int)
        self._starttime_ms = starttime_ms
        self._time_text = ba.NodeActor(
            ba.newnode('text',
                       attrs={
                           'v_attach': 'top',
                           'h_attach': 'center',
                           'h_align': 'center',
                           'color': (1, 1, 0.5, 1),
                           'flatness': 0.5,
                           'shadow': 0.5,
                           'position': (0, -50),
                           'scale': 1.3,
                           'text': ''
                       }))
        self._time_text_input = ba.NodeActor(
            ba.newnode('timedisplay', attrs={'showsubseconds': True}))
        ba.sharedobj('globals').connectattr('time', self._time_text_input.node,
                                            'time2')
        assert self._time_text_input.node
        assert self._time_text.node
        self._time_text_input.node.connectattr('output', self._time_text.node,
                                               'text')

        # Our TNT spawner (if applicable).
        if self._have_tnt:
            self._tntspawner = stdbomb.TNTSpawner(position=(0, 1, -1))

        self._bots = spazbot.BotSet()
        self._bot_spawn_timer = ba.Timer(1.0, self._update_bots, repeat=True)

        for bottype in self._bot_types_initial:
            self._spawn_bot(bottype)
Exemple #26
0
    def on_transition_in(self) -> None:
        super().on_transition_in()
        random.seed(123)
        self._logo_node: Optional[ba.Node] = None
        self._custom_logo_tex_name: Optional[str] = None
        self._word_actors: List[ba.Actor] = []
        app = ba.app

        # FIXME: We shouldn't be doing things conditionally based on whether
        #  the host is VR mode or not (clients may differ in that regard).
        #  Any differences need to happen at the engine level so everyone
        #  sees things in their own optimal way.
        vr_mode = ba.app.vr_mode

        if not ba.app.toolbar_test:
            color = ((1.0, 1.0, 1.0, 1.0) if vr_mode else (0.5, 0.6, 0.5, 0.6))
            # FIXME: Need a node attr for vr-specific-scale.
            scale = (0.9 if
                     (app.interface_type == 'small' or vr_mode) else 0.7)
            self.my_name = ba.NodeActor(
                ba.newnode('text',
                           attrs={
                               'v_attach': 'bottom',
                               'h_align': 'center',
                               'color': color,
                               'flatness': 1.0,
                               'shadow': 1.0 if vr_mode else 0.5,
                               'scale': scale,
                               'position': (0, 10),
                               'vr_depth': -10,
                               'text': '\xa9 2011-2020 Eric Froemling'
                           }))

        # Throw up some text that only clients can see so they know that the
        # host is navigating menus while they're just staring at an
        # empty-ish screen.
        tval = ba.Lstr(resource='hostIsNavigatingMenusText',
                       subs=[('${HOST}', _ba.get_account_display_string())])
        self._host_is_navigating_text = ba.NodeActor(
            ba.newnode('text',
                       attrs={
                           'text': tval,
                           'client_only': True,
                           'position': (0, -200),
                           'flatness': 1.0,
                           'h_align': 'center'
                       }))
        if not ba.app.main_menu_did_initial_transition and hasattr(
                self, 'my_name'):
            assert self.my_name.node
            ba.animate(self.my_name.node, 'opacity', {2.3: 0, 3.0: 1.0})

        # FIXME: We shouldn't be doing things conditionally based on whether
        #  the host is vr mode or not (clients may not be or vice versa).
        #  Any differences need to happen at the engine level so everyone sees
        #  things in their own optimal way.
        vr_mode = app.vr_mode
        interface_type = app.interface_type

        # In cases where we're doing lots of dev work lets always show the
        # build number.
        force_show_build_number = False

        if not ba.app.toolbar_test:
            if app.debug_build or app.test_build or force_show_build_number:
                if app.debug_build:
                    text = ba.Lstr(value='${V} (${B}) (${D})',
                                   subs=[
                                       ('${V}', app.version),
                                       ('${B}', str(app.build_number)),
                                       ('${D}', ba.Lstr(resource='debugText')),
                                   ])
                else:
                    text = ba.Lstr(value='${V} (${B})',
                                   subs=[
                                       ('${V}', app.version),
                                       ('${B}', str(app.build_number)),
                                   ])
            else:
                text = ba.Lstr(value='${V}', subs=[('${V}', app.version)])
            scale = 0.9 if (interface_type == 'small' or vr_mode) else 0.7
            color = (1, 1, 1, 1) if vr_mode else (0.5, 0.6, 0.5, 0.7)
            self.version = ba.NodeActor(
                ba.newnode('text',
                           attrs={
                               'v_attach': 'bottom',
                               'h_attach': 'right',
                               'h_align': 'right',
                               'flatness': 1.0,
                               'vr_depth': -10,
                               'shadow': 1.0 if vr_mode else 0.5,
                               'color': color,
                               'scale': scale,
                               'position': (-260, 10) if vr_mode else
                               (-10, 10),
                               'text': text
                           }))
            if not ba.app.main_menu_did_initial_transition:
                assert self.version.node
                ba.animate(self.version.node, 'opacity', {2.3: 0, 3.0: 1.0})

        # Throw in test build info.
        self.beta_info = self.beta_info_2 = None
        if app.test_build and not app.kiosk_mode:
            pos = (230, 125) if app.kiosk_mode else (230, 35)
            self.beta_info = ba.NodeActor(
                ba.newnode('text',
                           attrs={
                               'v_attach': 'center',
                               'h_align': 'center',
                               'color': (1, 1, 1, 1),
                               'shadow': 0.5,
                               'flatness': 0.5,
                               'scale': 1,
                               'vr_depth': -60,
                               'position': pos,
                               'text': ba.Lstr(resource='testBuildText')
                           }))
            if not ba.app.main_menu_did_initial_transition:
                assert self.beta_info.node
                ba.animate(self.beta_info.node, 'opacity', {1.3: 0, 1.8: 1.0})

        model = ba.getmodel('thePadLevel')
        trees_model = ba.getmodel('trees')
        bottom_model = ba.getmodel('thePadLevelBottom')
        color_texture = ba.gettexture('thePadLevelColor')
        trees_texture = ba.gettexture('treesColor')
        bgtex = ba.gettexture('menuBG')
        bgmodel = ba.getmodel('thePadBG')

        # Load these last since most platforms don't use them.
        vr_bottom_fill_model = ba.getmodel('thePadVRFillBottom')
        vr_top_fill_model = ba.getmodel('thePadVRFillTop')

        gnode = ba.sharedobj('globals')
        gnode.camera_mode = 'rotate'

        tint = (1.14, 1.1, 1.0)
        gnode.tint = tint
        gnode.ambient_color = (1.06, 1.04, 1.03)
        gnode.vignette_outer = (0.45, 0.55, 0.54)
        gnode.vignette_inner = (0.99, 0.98, 0.98)

        self.bottom = ba.NodeActor(
            ba.newnode('terrain',
                       attrs={
                           'model': bottom_model,
                           'lighting': False,
                           'reflection': 'soft',
                           'reflection_scale': [0.45],
                           'color_texture': color_texture
                       }))
        self.vr_bottom_fill = ba.NodeActor(
            ba.newnode('terrain',
                       attrs={
                           'model': vr_bottom_fill_model,
                           'lighting': False,
                           'vr_only': True,
                           'color_texture': color_texture
                       }))
        self.vr_top_fill = ba.NodeActor(
            ba.newnode('terrain',
                       attrs={
                           'model': vr_top_fill_model,
                           'vr_only': True,
                           'lighting': False,
                           'color_texture': bgtex
                       }))
        self.terrain = ba.NodeActor(
            ba.newnode('terrain',
                       attrs={
                           'model': model,
                           'color_texture': color_texture,
                           'reflection': 'soft',
                           'reflection_scale': [0.3]
                       }))
        self.trees = ba.NodeActor(
            ba.newnode('terrain',
                       attrs={
                           'model': trees_model,
                           'lighting': False,
                           'reflection': 'char',
                           'reflection_scale': [0.1],
                           'color_texture': trees_texture
                       }))
        self.bgterrain = ba.NodeActor(
            ba.newnode('terrain',
                       attrs={
                           'model': bgmodel,
                           'color': (0.92, 0.91, 0.9),
                           'lighting': False,
                           'background': True,
                           'color_texture': bgtex
                       }))

        self._ts = 0.86

        self._language: Optional[str] = None
        self._update_timer = ba.Timer(1.0, self._update, repeat=True)
        self._update()

        # Hopefully this won't hitch but lets space these out anyway.
        _ba.add_clean_frame_callback(ba.WeakCall(self._start_preloads))

        random.seed()

        # On the main menu, also show our news.
        class News:
            """Wrangles news display."""
            def __init__(self, activity: ba.Activity):
                self._valid = True
                self._message_duration = 10.0
                self._message_spacing = 2.0
                self._text: Optional[ba.NodeActor] = None
                self._activity = weakref.ref(activity)

                # If we're signed in, fetch news immediately.
                # Otherwise wait until we are signed in.
                self._fetch_timer: Optional[ba.Timer] = ba.Timer(
                    1.0, ba.WeakCall(self._try_fetching_news), repeat=True)
                self._try_fetching_news()

            # We now want to wait until we're signed in before fetching news.
            def _try_fetching_news(self) -> None:
                if _ba.get_account_state() == 'signed_in':
                    self._fetch_news()
                    self._fetch_timer = None

            def _fetch_news(self) -> None:
                ba.app.main_menu_last_news_fetch_time = time.time()

                # UPDATE - We now just pull news from MRVs.
                news = _ba.get_account_misc_read_val('n', None)
                if news is not None:
                    self._got_news(news)

            def _change_phrase(self) -> None:
                from bastd.actor.text import Text

                # If our news is way out of date, lets re-request it;
                # otherwise, rotate our phrase.
                assert ba.app.main_menu_last_news_fetch_time is not None
                if time.time() - ba.app.main_menu_last_news_fetch_time > 600.0:
                    self._fetch_news()
                    self._text = None
                else:
                    if self._text is not None:
                        if not self._phrases:
                            for phr in self._used_phrases:
                                self._phrases.insert(0, phr)
                        val = self._phrases.pop()
                        if val == '__ACH__':
                            vrmode = app.vr_mode
                            Text(ba.Lstr(resource='nextAchievementsText'),
                                 color=((1, 1, 1, 1) if vrmode else
                                        (0.95, 0.9, 1, 0.4)),
                                 host_only=True,
                                 maxwidth=200,
                                 position=(-300, -35),
                                 h_align=Text.HAlign.RIGHT,
                                 transition=Text.Transition.FADE_IN,
                                 scale=0.9 if vrmode else 0.7,
                                 flatness=1.0 if vrmode else 0.6,
                                 shadow=1.0 if vrmode else 0.5,
                                 h_attach=Text.HAttach.CENTER,
                                 v_attach=Text.VAttach.TOP,
                                 transition_delay=1.0,
                                 transition_out_delay=self._message_duration
                                 ).autoretain()
                            achs = [
                                a for a in app.achievements if not a.complete
                            ]
                            if achs:
                                ach = achs.pop(
                                    random.randrange(min(4, len(achs))))
                                ach.create_display(
                                    -180,
                                    -35,
                                    1.0,
                                    outdelay=self._message_duration,
                                    style='news')
                            if achs:
                                ach = achs.pop(
                                    random.randrange(min(8, len(achs))))
                                ach.create_display(
                                    180,
                                    -35,
                                    1.25,
                                    outdelay=self._message_duration,
                                    style='news')
                        else:
                            spc = self._message_spacing
                            keys = {
                                spc: 0.0,
                                spc + 1.0: 1.0,
                                spc + self._message_duration - 1.0: 1.0,
                                spc + self._message_duration: 0.0
                            }
                            assert self._text.node
                            ba.animate(self._text.node, "opacity", keys)
                            # {k: v
                            #  for k, v in list(keys.items())})
                            self._text.node.text = val

            def _got_news(self, news: str) -> None:
                # Run this stuff in the context of our activity since we
                # need to make nodes and stuff.. should fix the serverget
                # call so it.
                activity = self._activity()
                if activity is None or activity.is_expired():
                    return
                with ba.Context(activity):

                    self._phrases: List[str] = []

                    # Show upcoming achievements in non-vr versions
                    # (currently too hard to read in vr).
                    self._used_phrases = (
                        ['__ACH__'] if not ba.app.vr_mode else
                        []) + [s for s in news.split('<br>\n') if s != '']
                    self._phrase_change_timer = ba.Timer(
                        (self._message_duration + self._message_spacing),
                        ba.WeakCall(self._change_phrase),
                        repeat=True)

                    scl = 1.2 if (ba.app.interface_type == 'small'
                                  or ba.app.vr_mode) else 0.8

                    color2 = ((1, 1, 1, 1) if ba.app.vr_mode else
                              (0.7, 0.65, 0.75, 1.0))
                    shadow = (1.0 if ba.app.vr_mode else 0.4)
                    self._text = ba.NodeActor(
                        ba.newnode('text',
                                   attrs={
                                       'v_attach': 'top',
                                       'h_attach': 'center',
                                       'h_align': 'center',
                                       'vr_depth': -20,
                                       'shadow': shadow,
                                       'flatness': 0.8,
                                       'v_align': 'top',
                                       'color': color2,
                                       'scale': scl,
                                       'maxwidth': 900.0 / scl,
                                       'position': (0, -10)
                                   }))
                    self._change_phrase()

        if not app.kiosk_mode and not app.toolbar_test:
            self._news = News(self)

        # Bring up the last place we were, or start at the main menu otherwise.
        with ba.Context('ui'):
            from bastd.ui import specialoffer
            if bool(False):
                uicontroller = ba.app.uicontroller
                assert uicontroller is not None
                uicontroller.show_main_menu()
            else:
                main_window = ba.app.main_window

                # When coming back from a kiosk-mode game, jump to
                # the kiosk start screen.
                if ba.app.kiosk_mode:
                    # pylint: disable=cyclic-import
                    from bastd.ui.kiosk import KioskWindow
                    ba.app.main_menu_window = KioskWindow().get_root_widget()
                # ..or in normal cases go back to the main menu
                else:
                    main_window = ba.app.main_window
                    if main_window == 'Gather':
                        # pylint: disable=cyclic-import
                        from bastd.ui.gather import GatherWindow
                        ba.app.main_menu_window = (GatherWindow(
                            transition=None).get_root_widget())
                    elif main_window == 'Watch':
                        # pylint: disable=cyclic-import
                        from bastd.ui.watch import WatchWindow
                        ba.app.main_menu_window = WatchWindow(
                            transition=None).get_root_widget()
                    elif main_window == 'Team Game Select':
                        # pylint: disable=cyclic-import
                        from bastd.ui.playlist.browser import (
                            PlaylistBrowserWindow)
                        ba.app.main_menu_window = PlaylistBrowserWindow(
                            sessiontype=ba.TeamsSession,
                            transition=None).get_root_widget()
                    elif main_window == 'Free-for-All Game Select':
                        # pylint: disable=cyclic-import
                        from bastd.ui.playlist.browser import (
                            PlaylistBrowserWindow)
                        ba.app.main_menu_window = PlaylistBrowserWindow(
                            sessiontype=ba.FreeForAllSession,
                            transition=None).get_root_widget()
                    elif main_window == 'Coop Select':
                        # pylint: disable=cyclic-import
                        from bastd.ui.coop.browser import CoopBrowserWindow
                        ba.app.main_menu_window = CoopBrowserWindow(
                            transition=None).get_root_widget()
                    else:
                        # pylint: disable=cyclic-import
                        from bastd.ui.mainmenu import MainMenuWindow
                        ba.app.main_menu_window = MainMenuWindow(
                            transition=None).get_root_widget()

                # attempt to show any pending offers immediately.
                # If that doesn't work, try again in a few seconds
                # (we may not have heard back from the server)
                # ..if that doesn't work they'll just have to wait
                # until the next opportunity.
                if not specialoffer.show_offer():

                    def try_again() -> None:
                        if not specialoffer.show_offer():
                            # Try one last time..
                            ba.timer(2.0,
                                     specialoffer.show_offer,
                                     timetype=ba.TimeType.REAL)

                    ba.timer(2.0, try_again, timetype=ba.TimeType.REAL)
        ba.app.main_menu_did_initial_transition = True