Source code for bascenev1._activitytypes

# Released under the MIT License. See LICENSE for details.
#
"""Some handy base class and special purpose Activity types."""
from __future__ import annotations

from typing import TYPE_CHECKING, override

import babase

import _bascenev1
from bascenev1._activity import Activity

from bascenev1._player import EmptyPlayer
from bascenev1._team import EmptyTeam
from bascenev1._music import MusicType, setmusic


if TYPE_CHECKING:
    import bascenev1
    from bascenev1._lobby import JoinInfo


class EndSessionActivity(Activity[EmptyPlayer, EmptyTeam]):
    """Special Activity to fade out and end the current Session."""

    def __init__(self, settings: dict):
        super().__init__(settings)

        # Keeps prev activity alive while we fade out.
        self.transition_time = 0.25
        self.inherits_tint = True
        self.inherits_slow_motion = True
        self.inherits_vr_camera_offset = True
        self.inherits_vr_overlay_center = True

    @override
    def on_transition_in(self) -> None:
        super().on_transition_in()
        babase.fade_screen(False)
        babase.lock_all_input()

    @override
    def on_begin(self) -> None:
        # pylint: disable=cyclic-import

        assert babase.app.classic is not None

        main_menu_session = babase.app.classic.get_main_menu_session()

        super().on_begin()
        babase.unlock_all_input()
        assert babase.app.classic is not None
        babase.app.classic.ads.call_after_ad(
            babase.Call(_bascenev1.new_host_session, main_menu_session)
        )


[docs] class JoinActivity(Activity[EmptyPlayer, EmptyTeam]): """Standard activity for waiting for players to join. It shows tips and other info and waits for all players to check ready. """ def __init__(self, settings: dict): super().__init__(settings) # This activity is a special 'joiner' activity. # It will get shut down as soon as all players have checked ready. self.is_joining_activity = True # Players may be idle waiting for joiners; lets not kick them for it. self.allow_kick_idle_players = False # In vr mode we don't want stuff moving around. self.use_fixed_vr_overlay = True self._background: bascenev1.Actor | None = None self._tips_text: bascenev1.Actor | None = None self._join_info: JoinInfo | None = None
[docs] @override def on_transition_in(self) -> None: # pylint: disable=cyclic-import from bascenev1lib.actor.tipstext import TipsText from bascenev1lib.actor.background import Background super().on_transition_in() self._background = Background( fade_time=0.5, start_faded=True, show_logo=True ) self._tips_text = TipsText() setmusic(MusicType.CHAR_SELECT) self._join_info = self.session.lobby.create_join_info() babase.set_analytics_screen('Joining Screen')
class TransitionActivity(Activity[EmptyPlayer, EmptyTeam]): """A simple overlay to fade out/in. Useful as a bare minimum transition between two level based activities. """ # Keep prev activity alive while we fade in. transition_time = 0.5 inherits_slow_motion = True # Don't change. inherits_tint = True # Don't change. inherits_vr_camera_offset = True # Don't change. inherits_vr_overlay_center = True use_fixed_vr_overlay = True def __init__(self, settings: dict): super().__init__(settings) self._background: bascenev1.Actor | None = None @override def on_transition_in(self) -> None: # pylint: disable=cyclic-import from bascenev1lib.actor.background import Background super().on_transition_in() self._background = Background( fade_time=0.5, start_faded=False, show_logo=False ) @override def on_begin(self) -> None: super().on_begin() # Die almost immediately. _bascenev1.timer(0.1, self.end)
[docs] class ScoreScreenActivity(Activity[EmptyPlayer, EmptyTeam]): """A standard score screen that fades in and shows stuff for a while. After a specified delay, player input is assigned to end the activity. """ transition_time = 0.5 inherits_tint = True inherits_vr_camera_offset = True use_fixed_vr_overlay = True default_music: MusicType | None = MusicType.SCORES def __init__(self, settings: dict): super().__init__(settings) self._birth_time = babase.apptime() self._min_view_time = 5.0 self._allow_server_transition = False self._background: bascenev1.Actor | None = None self._tips_text: bascenev1.Actor | None = None self._kicked_off_server_shutdown = False self._kicked_off_server_restart = False self._default_show_tips = True self._custom_continue_message: babase.Lstr | None = None self._server_transitioning: bool | None = None
[docs] @override def on_player_join(self, player: EmptyPlayer) -> None: super().on_player_join(player) time_till_assign = max( 0, self._birth_time + self._min_view_time - babase.apptime() ) # If we're still kicking at the end of our assign-delay, assign this # guy's input to trigger us. _bascenev1.timer( time_till_assign, babase.WeakCall(self._safe_assign, player) )
[docs] @override def on_transition_in(self) -> None: from bascenev1lib.actor.tipstext import TipsText from bascenev1lib.actor.background import Background super().on_transition_in() self._background = Background( fade_time=0.5, start_faded=False, show_logo=True ) if self._default_show_tips: self._tips_text = TipsText() setmusic(self.default_music)
[docs] @override def on_begin(self) -> None: # pylint: disable=cyclic-import from bascenev1lib.actor.text import Text super().on_begin() # Pop up a 'press any button to continue' statement after our # min-view-time show a 'press any button to continue..' # thing after a bit. assert babase.app.classic is not None if babase.app.ui_v1.uiscale is babase.UIScale.LARGE: # FIXME: Need a better way to determine whether we've probably # got a keyboard. sval = babase.Lstr(resource='pressAnyKeyButtonText') else: sval = babase.Lstr(resource='pressAnyButtonText') Text( ( self._custom_continue_message if self._custom_continue_message is not None else sval ), v_attach=Text.VAttach.BOTTOM, h_align=Text.HAlign.CENTER, flash=True, vr_depth=50, position=(0, 10), scale=0.8, color=(0.5, 0.7, 0.5, 0.5), transition=Text.Transition.IN_BOTTOM_SLOW, transition_delay=self._min_view_time, ).autoretain()
def _player_press(self) -> None: # If this activity is a good 'end point', ask server-mode just once if # it wants to do anything special like switch sessions or kill the app. if ( self._allow_server_transition and babase.app.classic is not None and babase.app.classic.server is not None and self._server_transitioning is None ): self._server_transitioning = ( babase.app.classic.server.handle_transition() ) assert isinstance(self._server_transitioning, bool) # If server-mode is handling this, don't do anything ourself. if self._server_transitioning is True: return # Otherwise end the activity normally. self.end() def _safe_assign(self, player: EmptyPlayer) -> None: # Just to be extra careful, don't assign if we're transitioning out. # (though theoretically that should be ok). if not self.is_transitioning_out() and player: player.assigninput( ( babase.InputType.JUMP_PRESS, babase.InputType.PUNCH_PRESS, babase.InputType.BOMB_PRESS, babase.InputType.PICK_UP_PRESS, ), self._player_press, )
# Docs-generation hack; import some stuff that we likely only forward-declared # in our actual source code so that docs tools can find it. from typing import (Coroutine, Any, Literal, Callable, Generator, Awaitable, Sequence, Self) import asyncio from concurrent.futures import Future from pathlib import Path from enum import Enum