bastd.activity.coopjoin
Functionality related to the co-op join screen.
1# Released under the MIT License. See LICENSE for details. 2# 3"""Functionality related to the co-op join screen.""" 4 5from __future__ import annotations 6 7from typing import TYPE_CHECKING 8 9import _ba 10import ba 11from ba.internal import JoinActivity 12 13if TYPE_CHECKING: 14 from typing import Any, Sequence 15 16 17class CoopJoinActivity(JoinActivity): 18 """Join-screen for co-op mode.""" 19 20 # We can assume our session is a CoopSession. 21 session: ba.CoopSession 22 23 def __init__(self, settings: dict): 24 super().__init__(settings) 25 session = self.session 26 assert isinstance(session, ba.CoopSession) 27 28 # Let's show a list of scores-to-beat for 1 player at least. 29 assert session.campaign is not None 30 level_name_full = (session.campaign.name + ':' + 31 session.campaign_level_name) 32 config_str = ('1p' + session.campaign.getlevel( 33 session.campaign_level_name).get_score_version_string().replace( 34 ' ', '_')) 35 _ba.get_scores_to_beat(level_name_full, config_str, 36 ba.WeakCall(self._on_got_scores_to_beat)) 37 38 def on_transition_in(self) -> None: 39 from bastd.actor.controlsguide import ControlsGuide 40 from bastd.actor.text import Text 41 super().on_transition_in() 42 assert isinstance(self.session, ba.CoopSession) 43 assert self.session.campaign 44 Text(self.session.campaign.getlevel( 45 self.session.campaign_level_name).displayname, 46 scale=1.3, 47 h_attach=Text.HAttach.CENTER, 48 h_align=Text.HAlign.CENTER, 49 v_attach=Text.VAttach.TOP, 50 transition=Text.Transition.FADE_IN, 51 transition_delay=4.0, 52 color=(1, 1, 1, 0.6), 53 position=(0, -95)).autoretain() 54 ControlsGuide(delay=1.0).autoretain() 55 56 def _on_got_scores_to_beat(self, 57 scores: list[dict[str, Any]] | None) -> None: 58 # pylint: disable=too-many-locals 59 # pylint: disable=too-many-statements 60 from efro.util import asserttype 61 from bastd.actor.text import Text 62 63 # Sort by originating date so that the most recent is first. 64 if scores is not None: 65 scores.sort(reverse=True, 66 key=lambda score: asserttype(score['time'], int)) 67 68 # We only show achievements and challenges for CoopGameActivities. 69 session = self.session 70 assert isinstance(session, ba.CoopSession) 71 gameinstance = session.get_current_game_instance() 72 if isinstance(gameinstance, ba.CoopGameActivity): 73 score_type = gameinstance.get_score_type() 74 if scores is not None: 75 achievement_challenges = [ 76 a for a in scores if a['type'] == 'achievement_challenge' 77 ] 78 score_challenges = [ 79 a for a in scores if a['type'] == 'score_challenge' 80 ] 81 else: 82 achievement_challenges = score_challenges = [] 83 84 delay = 1.0 85 vpos = -140.0 86 spacing = 25 87 delay_inc = 0.1 88 89 def _add_t( 90 text: str | ba.Lstr, 91 h_offs: float = 0.0, 92 scale: float = 1.0, 93 color: Sequence[float] = (1.0, 1.0, 1.0, 0.46) 94 ) -> None: 95 Text(text, 96 scale=scale * 0.76, 97 h_align=Text.HAlign.LEFT, 98 h_attach=Text.HAttach.LEFT, 99 v_attach=Text.VAttach.TOP, 100 transition=Text.Transition.FADE_IN, 101 transition_delay=delay, 102 color=color, 103 position=(60 + h_offs, vpos)).autoretain() 104 105 if score_challenges: 106 _add_t(ba.Lstr(value='${A}:', 107 subs=[('${A}', 108 ba.Lstr(resource='scoreChallengesText')) 109 ]), 110 scale=1.1) 111 delay += delay_inc 112 vpos -= spacing 113 for chal in score_challenges: 114 _add_t(str(chal['value'] if score_type == 'points' else ba. 115 timestring(int(chal['value']) * 10, 116 timeformat=ba.TimeFormat.MILLISECONDS 117 ).evaluate()) + ' (1 player)', 118 h_offs=30, 119 color=(0.9, 0.7, 1.0, 0.8)) 120 delay += delay_inc 121 vpos -= 0.6 * spacing 122 _add_t(chal['player'], 123 h_offs=40, 124 color=(0.8, 1, 0.8, 0.6), 125 scale=0.8) 126 delay += delay_inc 127 vpos -= 1.2 * spacing 128 vpos -= 0.5 * spacing 129 130 if achievement_challenges: 131 _add_t(ba.Lstr( 132 value='${A}:', 133 subs=[('${A}', 134 ba.Lstr(resource='achievementChallengesText'))]), 135 scale=1.1) 136 delay += delay_inc 137 vpos -= spacing 138 for chal in achievement_challenges: 139 _add_t(str(chal['value']), 140 h_offs=30, 141 color=(0.9, 0.7, 1.0, 0.8)) 142 delay += delay_inc 143 vpos -= 0.6 * spacing 144 _add_t(chal['player'], 145 h_offs=40, 146 color=(0.8, 1, 0.8, 0.6), 147 scale=0.8) 148 delay += delay_inc 149 vpos -= 1.2 * spacing 150 vpos -= 0.5 * spacing 151 152 # Now list our remaining achievements for this level. 153 assert self.session.campaign is not None 154 assert isinstance(self.session, ba.CoopSession) 155 levelname = (self.session.campaign.name + ':' + 156 self.session.campaign_level_name) 157 ts_h_offs = 60 158 159 if not (ba.app.demo_mode or ba.app.arcade_mode): 160 achievements = [ 161 a 162 for a in ba.app.ach.achievements_for_coop_level(levelname) 163 if not a.complete 164 ] 165 have_achievements = bool(achievements) 166 achievements = [a for a in achievements if not a.complete] 167 vrmode = ba.app.vr_mode 168 if have_achievements: 169 Text(ba.Lstr(resource='achievementsRemainingText'), 170 host_only=True, 171 position=(ts_h_offs - 10, vpos), 172 transition=Text.Transition.FADE_IN, 173 scale=1.1 * 0.76, 174 h_attach=Text.HAttach.LEFT, 175 v_attach=Text.VAttach.TOP, 176 color=(1, 1, 1.2, 1) if vrmode else (0.8, 0.8, 1, 1), 177 shadow=1.0, 178 flatness=1.0 if vrmode else 0.6, 179 transition_delay=delay).autoretain() 180 hval = ts_h_offs + 50 181 vpos -= 35 182 for ach in achievements: 183 delay += 0.05 184 ach.create_display(hval, vpos, delay, style='in_game') 185 vpos -= 55 186 if not achievements: 187 Text(ba.Lstr(resource='noAchievementsRemainingText'), 188 host_only=True, 189 position=(ts_h_offs + 15, vpos + 10), 190 transition=Text.Transition.FADE_IN, 191 scale=0.7, 192 h_attach=Text.HAttach.LEFT, 193 v_attach=Text.VAttach.TOP, 194 color=(1, 1, 1, 0.5), 195 transition_delay=delay + 0.5).autoretain()
18class CoopJoinActivity(JoinActivity): 19 """Join-screen for co-op mode.""" 20 21 # We can assume our session is a CoopSession. 22 session: ba.CoopSession 23 24 def __init__(self, settings: dict): 25 super().__init__(settings) 26 session = self.session 27 assert isinstance(session, ba.CoopSession) 28 29 # Let's show a list of scores-to-beat for 1 player at least. 30 assert session.campaign is not None 31 level_name_full = (session.campaign.name + ':' + 32 session.campaign_level_name) 33 config_str = ('1p' + session.campaign.getlevel( 34 session.campaign_level_name).get_score_version_string().replace( 35 ' ', '_')) 36 _ba.get_scores_to_beat(level_name_full, config_str, 37 ba.WeakCall(self._on_got_scores_to_beat)) 38 39 def on_transition_in(self) -> None: 40 from bastd.actor.controlsguide import ControlsGuide 41 from bastd.actor.text import Text 42 super().on_transition_in() 43 assert isinstance(self.session, ba.CoopSession) 44 assert self.session.campaign 45 Text(self.session.campaign.getlevel( 46 self.session.campaign_level_name).displayname, 47 scale=1.3, 48 h_attach=Text.HAttach.CENTER, 49 h_align=Text.HAlign.CENTER, 50 v_attach=Text.VAttach.TOP, 51 transition=Text.Transition.FADE_IN, 52 transition_delay=4.0, 53 color=(1, 1, 1, 0.6), 54 position=(0, -95)).autoretain() 55 ControlsGuide(delay=1.0).autoretain() 56 57 def _on_got_scores_to_beat(self, 58 scores: list[dict[str, Any]] | None) -> None: 59 # pylint: disable=too-many-locals 60 # pylint: disable=too-many-statements 61 from efro.util import asserttype 62 from bastd.actor.text import Text 63 64 # Sort by originating date so that the most recent is first. 65 if scores is not None: 66 scores.sort(reverse=True, 67 key=lambda score: asserttype(score['time'], int)) 68 69 # We only show achievements and challenges for CoopGameActivities. 70 session = self.session 71 assert isinstance(session, ba.CoopSession) 72 gameinstance = session.get_current_game_instance() 73 if isinstance(gameinstance, ba.CoopGameActivity): 74 score_type = gameinstance.get_score_type() 75 if scores is not None: 76 achievement_challenges = [ 77 a for a in scores if a['type'] == 'achievement_challenge' 78 ] 79 score_challenges = [ 80 a for a in scores if a['type'] == 'score_challenge' 81 ] 82 else: 83 achievement_challenges = score_challenges = [] 84 85 delay = 1.0 86 vpos = -140.0 87 spacing = 25 88 delay_inc = 0.1 89 90 def _add_t( 91 text: str | ba.Lstr, 92 h_offs: float = 0.0, 93 scale: float = 1.0, 94 color: Sequence[float] = (1.0, 1.0, 1.0, 0.46) 95 ) -> None: 96 Text(text, 97 scale=scale * 0.76, 98 h_align=Text.HAlign.LEFT, 99 h_attach=Text.HAttach.LEFT, 100 v_attach=Text.VAttach.TOP, 101 transition=Text.Transition.FADE_IN, 102 transition_delay=delay, 103 color=color, 104 position=(60 + h_offs, vpos)).autoretain() 105 106 if score_challenges: 107 _add_t(ba.Lstr(value='${A}:', 108 subs=[('${A}', 109 ba.Lstr(resource='scoreChallengesText')) 110 ]), 111 scale=1.1) 112 delay += delay_inc 113 vpos -= spacing 114 for chal in score_challenges: 115 _add_t(str(chal['value'] if score_type == 'points' else ba. 116 timestring(int(chal['value']) * 10, 117 timeformat=ba.TimeFormat.MILLISECONDS 118 ).evaluate()) + ' (1 player)', 119 h_offs=30, 120 color=(0.9, 0.7, 1.0, 0.8)) 121 delay += delay_inc 122 vpos -= 0.6 * spacing 123 _add_t(chal['player'], 124 h_offs=40, 125 color=(0.8, 1, 0.8, 0.6), 126 scale=0.8) 127 delay += delay_inc 128 vpos -= 1.2 * spacing 129 vpos -= 0.5 * spacing 130 131 if achievement_challenges: 132 _add_t(ba.Lstr( 133 value='${A}:', 134 subs=[('${A}', 135 ba.Lstr(resource='achievementChallengesText'))]), 136 scale=1.1) 137 delay += delay_inc 138 vpos -= spacing 139 for chal in achievement_challenges: 140 _add_t(str(chal['value']), 141 h_offs=30, 142 color=(0.9, 0.7, 1.0, 0.8)) 143 delay += delay_inc 144 vpos -= 0.6 * spacing 145 _add_t(chal['player'], 146 h_offs=40, 147 color=(0.8, 1, 0.8, 0.6), 148 scale=0.8) 149 delay += delay_inc 150 vpos -= 1.2 * spacing 151 vpos -= 0.5 * spacing 152 153 # Now list our remaining achievements for this level. 154 assert self.session.campaign is not None 155 assert isinstance(self.session, ba.CoopSession) 156 levelname = (self.session.campaign.name + ':' + 157 self.session.campaign_level_name) 158 ts_h_offs = 60 159 160 if not (ba.app.demo_mode or ba.app.arcade_mode): 161 achievements = [ 162 a 163 for a in ba.app.ach.achievements_for_coop_level(levelname) 164 if not a.complete 165 ] 166 have_achievements = bool(achievements) 167 achievements = [a for a in achievements if not a.complete] 168 vrmode = ba.app.vr_mode 169 if have_achievements: 170 Text(ba.Lstr(resource='achievementsRemainingText'), 171 host_only=True, 172 position=(ts_h_offs - 10, vpos), 173 transition=Text.Transition.FADE_IN, 174 scale=1.1 * 0.76, 175 h_attach=Text.HAttach.LEFT, 176 v_attach=Text.VAttach.TOP, 177 color=(1, 1, 1.2, 1) if vrmode else (0.8, 0.8, 1, 1), 178 shadow=1.0, 179 flatness=1.0 if vrmode else 0.6, 180 transition_delay=delay).autoretain() 181 hval = ts_h_offs + 50 182 vpos -= 35 183 for ach in achievements: 184 delay += 0.05 185 ach.create_display(hval, vpos, delay, style='in_game') 186 vpos -= 55 187 if not achievements: 188 Text(ba.Lstr(resource='noAchievementsRemainingText'), 189 host_only=True, 190 position=(ts_h_offs + 15, vpos + 10), 191 transition=Text.Transition.FADE_IN, 192 scale=0.7, 193 h_attach=Text.HAttach.LEFT, 194 v_attach=Text.VAttach.TOP, 195 color=(1, 1, 1, 0.5), 196 transition_delay=delay + 0.5).autoretain()
Join-screen for co-op mode.
24 def __init__(self, settings: dict): 25 super().__init__(settings) 26 session = self.session 27 assert isinstance(session, ba.CoopSession) 28 29 # Let's show a list of scores-to-beat for 1 player at least. 30 assert session.campaign is not None 31 level_name_full = (session.campaign.name + ':' + 32 session.campaign_level_name) 33 config_str = ('1p' + session.campaign.getlevel( 34 session.campaign_level_name).get_score_version_string().replace( 35 ' ', '_')) 36 _ba.get_scores_to_beat(level_name_full, config_str, 37 ba.WeakCall(self._on_got_scores_to_beat))
Creates an Activity in the current ba.Session.
The activity will not be actually run until ba.Session.setactivity is called. 'settings' should be a dict of key/value pairs specific to the activity.
Activities should preload as much of their media/etc as possible in their constructor, but none of it should actually be used until they are transitioned in.
The ba.Session this ba.Activity belongs go.
Raises a ba.SessionNotFoundError if the Session no longer exists.
39 def on_transition_in(self) -> None: 40 from bastd.actor.controlsguide import ControlsGuide 41 from bastd.actor.text import Text 42 super().on_transition_in() 43 assert isinstance(self.session, ba.CoopSession) 44 assert self.session.campaign 45 Text(self.session.campaign.getlevel( 46 self.session.campaign_level_name).displayname, 47 scale=1.3, 48 h_attach=Text.HAttach.CENTER, 49 h_align=Text.HAlign.CENTER, 50 v_attach=Text.VAttach.TOP, 51 transition=Text.Transition.FADE_IN, 52 transition_delay=4.0, 53 color=(1, 1, 1, 0.6), 54 position=(0, -95)).autoretain() 55 ControlsGuide(delay=1.0).autoretain()
Called when the Activity is first becoming visible.
Upon this call, the Activity should fade in backgrounds, start playing music, etc. It does not yet have access to players or teams, however. They remain owned by the previous Activity up until ba.Activity.on_begin() is called.
Inherited Members
- ba._activity.Activity
- is_joining_activity
- allow_kick_idle_players
- use_fixed_vr_overlay
- settings_raw
- teams
- players
- announce_player_deaths
- allow_pausing
- slow_motion
- inherits_slow_motion
- inherits_music
- inherits_vr_camera_offset
- inherits_vr_overlay_center
- inherits_tint
- allow_mid_activity_joins
- transition_time
- can_show_ad_on_death
- globalsnode
- stats
- on_expire
- customdata
- expired
- playertype
- teamtype
- retain_actor
- add_actor_weak_ref
- on_player_join
- on_player_leave
- on_team_join
- on_team_leave
- on_transition_out
- on_begin
- handlemessage
- has_transitioned_in
- has_begun
- has_ended
- is_transitioning_out
- transition_out
- end
- create_player
- create_team
- ba._dependency.DependencyComponent
- dep_is_present
- get_dynamic_deps