mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-01-22 23:15:49 +08:00
More modernizing and cleanup
This commit is contained in:
parent
08ea64bdc5
commit
e1f1cf0ed9
@ -4132,16 +4132,16 @@
|
||||
"assets/build/windows/x64/python.exe": "https://files.ballistica.net/cache/ba1/25/a7/dc87c1be41605eb6fefd0145144c",
|
||||
"assets/build/windows/x64/python37.dll": "https://files.ballistica.net/cache/ba1/b9/e4/d912f56e42e9991bcbb4c804cfcb",
|
||||
"assets/build/windows/x64/pythonw.exe": "https://files.ballistica.net/cache/ba1/6c/bb/b6f52c306aa4e88061510e96cefe",
|
||||
"build/prefab/linux-server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/ca/db/9c7cfd4e4f4a1f7a7adc980bca42",
|
||||
"build/prefab/linux-server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/4e/0b/231e38ff29d932df7552050891c5",
|
||||
"build/prefab/linux/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/f2/56/bb316ec28ee98ece5c0c3a04b77f",
|
||||
"build/prefab/linux/release/ballisticacore": "https://files.ballistica.net/cache/ba1/ef/92/d787c99db6cc85f70b7131ff2c0c",
|
||||
"build/prefab/mac-server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/97/b9/9c6c3c90f10d319250a9f3d287b3",
|
||||
"build/prefab/mac-server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/f0/2a/60bdf1c4d4e13bdbb5f4df121e3e",
|
||||
"build/prefab/mac/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/66/25/79ea606983dc91ac0cd79c1e7da6",
|
||||
"build/prefab/mac/release/ballisticacore": "https://files.ballistica.net/cache/ba1/70/c6/0ab2cdf222ffcadade37dd3b8462",
|
||||
"build/prefab/windows-server/debug/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/3c/65/450a67dab189c0832b6bf28a9e9c",
|
||||
"build/prefab/windows-server/release/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/7e/a9/e1ab6defb8bcf536dff46d0c62b2",
|
||||
"build/prefab/windows/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/ab/fc/d00336dae2b1c7323b31518b52aa",
|
||||
"build/prefab/windows/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/ed/98/dbea1af1da83bfa1a3283175b234"
|
||||
"build/prefab/linux-server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/95/a8/318c6db7a9c94989c601f9388211",
|
||||
"build/prefab/linux-server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/6c/53/dda3c28a824749358279d01d85a6",
|
||||
"build/prefab/linux/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/cb/5e/04efb608c6a0d3fc80baee7f2c0e",
|
||||
"build/prefab/linux/release/ballisticacore": "https://files.ballistica.net/cache/ba1/91/74/c92748de53d860aa936f969c4699",
|
||||
"build/prefab/mac-server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/b9/a0/202236991664bc72a33affee2911",
|
||||
"build/prefab/mac-server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/b3/1a/7f626564f3659f4cbd00d62cbd5a",
|
||||
"build/prefab/mac/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/94/b8/4f2c26af58e4386d58f2de2b8f3f",
|
||||
"build/prefab/mac/release/ballisticacore": "https://files.ballistica.net/cache/ba1/8e/f3/40da5e70872c27cb1716a0e7bc10",
|
||||
"build/prefab/windows-server/debug/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/a0/a9/9ca7e5a2a62c7198f6dccf29a1e2",
|
||||
"build/prefab/windows-server/release/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/54/e7/fd4f9d4af81fed229a1fd2d486f1",
|
||||
"build/prefab/windows/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/54/5f/90a09221a6cb5ca24cf2a6b0f4e7",
|
||||
"build/prefab/windows/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/c2/14/82ced0d7340340cd09a73987c82f"
|
||||
}
|
||||
@ -34,7 +34,7 @@ NOTE: This file was autogenerated by gendummymodule; do not edit by hand.
|
||||
"""
|
||||
|
||||
# (hash we can use to see if this file is out of date)
|
||||
# SOURCES_HASH=265401783818737452594582363319036908124
|
||||
# SOURCES_HASH=317793613698101603244532998583646381571
|
||||
|
||||
# I'm sorry Pylint. I know this file saddens you. Be strong.
|
||||
# pylint: disable=useless-suppression
|
||||
@ -2310,21 +2310,31 @@ def get_ui_input_device() -> ba.InputDevice:
|
||||
return ba.InputDevice()
|
||||
|
||||
|
||||
def getactivity(doraise: bool = True) -> ba.Activity:
|
||||
"""getactivity(doraise: bool = True) -> ba.Activity
|
||||
# Show that our return type varies based on "doraise" value:
|
||||
@overload
|
||||
def getactivity(doraise: Literal[True] = True) -> ba.Activity:
|
||||
...
|
||||
|
||||
Returns the current ba.Activity instance.
|
||||
|
||||
@overload
|
||||
def getactivity(doraise: Literal[False]) -> Optional[ba.Activity]:
|
||||
...
|
||||
|
||||
|
||||
def getactivity(doraise: bool = True) -> Optional[ba.Activity]:
|
||||
"""getactivity(doraise: bool = True) -> <varies>
|
||||
|
||||
Return the current ba.Activity instance.
|
||||
|
||||
Category: Gameplay Functions
|
||||
|
||||
Note that this is based on context; thus code run in a timer generated
|
||||
in Activity 'foo' will properly return 'foo' here, even if another
|
||||
Activity has since been created or is transitioning in.
|
||||
If there is no current Activity an Exception is raised, or if doraise is
|
||||
False then None is returned instead.
|
||||
If there is no current Activity, raises a ba.ActivityNotFoundError.
|
||||
If doraise is False, None will be returned instead in that case.
|
||||
"""
|
||||
import ba # pylint: disable=cyclic-import
|
||||
return ba.Activity(settings={})
|
||||
return None
|
||||
|
||||
|
||||
def getcollidemodel(name: str) -> ba.CollideModel:
|
||||
@ -2422,8 +2432,19 @@ def getnodes() -> list:
|
||||
return list()
|
||||
|
||||
|
||||
def getsession(doraise: bool = True) -> ba.Session:
|
||||
"""getsession(doraise: bool = True) -> ba.Session
|
||||
# Show that our return type varies based on "doraise" value:
|
||||
@overload
|
||||
def getsession(doraise: Literal[True] = True) -> ba.Session:
|
||||
...
|
||||
|
||||
|
||||
@overload
|
||||
def getsession(doraise: Literal[False]) -> Optional[ba.Session]:
|
||||
...
|
||||
|
||||
|
||||
def getsession(doraise: bool = True) -> Optional[ba.Session]:
|
||||
"""getsession(doraise: bool = True) -> <varies>
|
||||
|
||||
Category: Gameplay Functions
|
||||
|
||||
@ -2433,8 +2454,7 @@ def getsession(doraise: bool = True) -> ba.Session:
|
||||
exists, etc. If there is no current Session, an Exception is raised, or
|
||||
if doraise is False then None is returned instead.
|
||||
"""
|
||||
import ba # pylint: disable=cyclic-import
|
||||
return ba.Session([])
|
||||
return None
|
||||
|
||||
|
||||
def getsound(name: str) -> ba.Sound:
|
||||
|
||||
@ -39,7 +39,7 @@ from _ba import (CollideModel, Context, ContextCall, Data, InputDevice,
|
||||
open_url, widget)
|
||||
from ba._activity import Activity
|
||||
from ba._actor import Actor
|
||||
from ba._player import Player, playercast, playercast_o
|
||||
from ba._player import PlayerInfo, Player, playercast, playercast_o
|
||||
from ba._nodeactor import NodeActor
|
||||
from ba._app import App
|
||||
from ba._coopgame import CoopGameActivity
|
||||
@ -47,13 +47,12 @@ from ba._coopsession import CoopSession
|
||||
from ba._dependency import (Dependency, DependencyComponent, DependencySet,
|
||||
AssetPackage)
|
||||
from ba._enums import TimeType, Permission, TimeFormat, SpecialChar
|
||||
from ba._error import (print_exception, print_error, NotFoundError,
|
||||
PlayerNotFoundError, SessionPlayerNotFoundError,
|
||||
NodeNotFoundError, ActorNotFoundError,
|
||||
InputDeviceNotFoundError, WidgetNotFoundError,
|
||||
ActivityNotFoundError, TeamNotFoundError,
|
||||
SessionTeamNotFoundError, SessionNotFoundError,
|
||||
DelegateNotFoundError, DependencyError)
|
||||
from ba._error import (
|
||||
print_exception, print_error, ContextError, NotFoundError,
|
||||
PlayerNotFoundError, SessionPlayerNotFoundError, NodeNotFoundError,
|
||||
ActorNotFoundError, InputDeviceNotFoundError, WidgetNotFoundError,
|
||||
ActivityNotFoundError, TeamNotFoundError, SessionTeamNotFoundError,
|
||||
SessionNotFoundError, DelegateNotFoundError, DependencyError)
|
||||
from ba._freeforallsession import FreeForAllSession
|
||||
from ba._gameactivity import GameActivity
|
||||
from ba._gameresults import TeamGameResults
|
||||
|
||||
@ -373,6 +373,7 @@ class Achievement:
|
||||
# pylint: disable=cyclic-import
|
||||
from ba._lang import Lstr
|
||||
from ba._enums import SpecialChar
|
||||
from ba._coopsession import CoopSession
|
||||
from bastd.actor.image import Image
|
||||
from bastd.actor.text import Text
|
||||
|
||||
@ -404,12 +405,16 @@ class Achievement:
|
||||
hmo = False
|
||||
else:
|
||||
try:
|
||||
campaign = _ba.getsession().campaign
|
||||
assert campaign is not None
|
||||
hmo = (self._hard_mode_only and campaign.name == 'Easy')
|
||||
session = _ba.getsession()
|
||||
if isinstance(session, CoopSession):
|
||||
campaign = session.campaign
|
||||
assert campaign is not None
|
||||
hmo = (self._hard_mode_only and campaign.name == 'Easy')
|
||||
else:
|
||||
hmo = False
|
||||
except Exception:
|
||||
from ba import _error
|
||||
_error.print_exception('unable to determine campaign')
|
||||
_error.print_exception('Error determining campaign')
|
||||
hmo = False
|
||||
|
||||
objs: List[ba.Actor]
|
||||
@ -678,7 +683,7 @@ class Achievement:
|
||||
|
||||
# Just piggy-back onto any current activity
|
||||
# (should we use the session instead?..)
|
||||
activity: Optional[ba.Activity] = _ba.getactivity(doraise=False)
|
||||
activity = _ba.getactivity(doraise=False)
|
||||
|
||||
# If this gets called while this achievement is occupying a slot
|
||||
# already, ignore it. (probably should never happen in real
|
||||
|
||||
@ -351,7 +351,7 @@ class Activity(DependencyComponent, Generic[PlayerType, TeamType]):
|
||||
raise TypeError('non-actor passed to add_actor_weak_ref')
|
||||
if (self.has_transitioned_in()
|
||||
and _ba.time() - self._last_prune_dead_actors_time > 10.0):
|
||||
print_error('it looks like nodes/actors are '
|
||||
print_error('It looks like nodes/actors are '
|
||||
'not being pruned in your activity;'
|
||||
' did you call Activity.on_transition_in()'
|
||||
' from your subclass?; ' + str(self) + ' (loc. b)')
|
||||
|
||||
@ -73,7 +73,6 @@ def suppress_debug_reports() -> None:
|
||||
This should be called in devel/debug situations to avoid spamming
|
||||
the master server with spurious logs.
|
||||
"""
|
||||
# _ba.screenmessage("Suppressing debug reports.", color=(1, 0, 0))
|
||||
_ba.app.suppress_debug_reports = True
|
||||
|
||||
|
||||
@ -189,21 +188,23 @@ def print_live_object_warnings(when: Any,
|
||||
"""Print warnings for remaining objects in the current context."""
|
||||
# pylint: disable=cyclic-import
|
||||
import gc
|
||||
from ba import _session as bs_session
|
||||
from ba import _actor as bs_actor
|
||||
from ba import _activity as bs_activity
|
||||
from ba._session import Session
|
||||
from ba._actor import Actor
|
||||
from ba._activity import Activity
|
||||
sessions: List[ba.Session] = []
|
||||
activities: List[ba.Activity] = []
|
||||
actors = []
|
||||
actors: List[ba.Actor] = []
|
||||
|
||||
# Once we come across leaked stuff, printing again is probably
|
||||
# redundant.
|
||||
if _ba.app.printed_live_object_warning:
|
||||
# print 'skipping live obj check due to previous found live object(s)'
|
||||
return
|
||||
for obj in gc.get_objects():
|
||||
if isinstance(obj, bs_actor.Actor):
|
||||
if isinstance(obj, Actor):
|
||||
actors.append(obj)
|
||||
elif isinstance(obj, bs_session.Session):
|
||||
elif isinstance(obj, Session):
|
||||
sessions.append(obj)
|
||||
elif isinstance(obj, bs_activity.Activity):
|
||||
elif isinstance(obj, Activity):
|
||||
activities.append(obj)
|
||||
|
||||
# Complain about any remaining sessions.
|
||||
@ -211,66 +212,19 @@ def print_live_object_warnings(when: Any,
|
||||
if session is ignore_session:
|
||||
continue
|
||||
_ba.app.printed_live_object_warning = True
|
||||
print('ERROR: Session found', when, ':', session)
|
||||
# refs = list(gc.get_referrers(session))
|
||||
# i = 1
|
||||
# for ref in refs:
|
||||
# if type(ref) is types.FrameType: continue
|
||||
# print ' ref', i, ':', ref
|
||||
# i += 1
|
||||
# if type(ref) is list or type(ref) is tuple or type(ref) is dict:
|
||||
# refs2 = list(gc.get_referrers(ref))
|
||||
# j = 1
|
||||
# for ref2 in refs2:
|
||||
# if type(ref2) is types.FrameType: continue
|
||||
# print ' ref\'s ref', j, ':', ref2
|
||||
# j += 1
|
||||
print(f'ERROR: Session found {when}: {session}')
|
||||
|
||||
# Complain about any remaining activities.
|
||||
for activity in activities:
|
||||
if activity is ignore_activity:
|
||||
continue
|
||||
_ba.app.printed_live_object_warning = True
|
||||
print('ERROR: Activity found', when, ':', activity)
|
||||
# refs = list(gc.get_referrers(activity))
|
||||
# i = 1
|
||||
# for ref in refs:
|
||||
# if type(ref) is types.FrameType: continue
|
||||
# print ' ref', i, ':', ref
|
||||
# i += 1
|
||||
# if type(ref) is list or type(ref) is tuple or type(ref) is dict:
|
||||
# refs2 = list(gc.get_referrers(ref))
|
||||
# j = 1
|
||||
# for ref2 in refs2:
|
||||
# if type(ref2) is types.FrameType: continue
|
||||
# print ' ref\'s ref', j, ':', ref2
|
||||
# j += 1
|
||||
print(f'ERROR: Activity found {when}: {activity}')
|
||||
|
||||
# Complain about any remaining actors.
|
||||
for actor in actors:
|
||||
_ba.app.printed_live_object_warning = True
|
||||
print('ERROR: Actor found', when, ':', actor)
|
||||
# if isinstance(actor, bs_actor.Actor):
|
||||
# try:
|
||||
# if actor.node:
|
||||
# print(' - contains node:',
|
||||
# actor.node.getnodetype(), ';',
|
||||
# actor.node.get_name())
|
||||
# except Exception as exc:
|
||||
# print(' - exception checking actor node:', exc)
|
||||
# refs = list(gc.get_referrers(actor))
|
||||
# i = 1
|
||||
# for ref in refs:
|
||||
# if type(ref) is types.FrameType: continue
|
||||
# print ' ref', i, ':', ref
|
||||
# i += 1
|
||||
# if type(ref) is list or type(ref) is tuple or type(ref) is dict:
|
||||
# refs2 = list(gc.get_referrers(ref))
|
||||
# j = 1
|
||||
# for ref2 in refs2:
|
||||
# if type(ref2) is types.FrameType: continue
|
||||
# print ' ref\'s ref', j, ':', ref2
|
||||
# j += 1
|
||||
print(f'ERROR: Actor found {when}: {actor}')
|
||||
|
||||
|
||||
def print_corrupt_file_error() -> None:
|
||||
|
||||
@ -25,6 +25,7 @@ from typing import TYPE_CHECKING, TypeVar
|
||||
|
||||
import _ba
|
||||
from ba._gameactivity import GameActivity
|
||||
from ba._general import WeakCall
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Type, Dict, Any, Set, List, Sequence, Optional
|
||||
@ -41,10 +42,13 @@ class CoopGameActivity(GameActivity[PlayerType, TeamType]):
|
||||
Category: Gameplay Classes
|
||||
"""
|
||||
|
||||
# We can assume our session is a CoopSession.
|
||||
session: ba.CoopSession
|
||||
|
||||
@classmethod
|
||||
def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool:
|
||||
from ba import _coopsession
|
||||
return issubclass(sessiontype, _coopsession.CoopSession)
|
||||
from ba._coopsession import CoopSession
|
||||
return issubclass(sessiontype, CoopSession)
|
||||
|
||||
def __init__(self, settings: Dict[str, Any]):
|
||||
super().__init__(settings)
|
||||
@ -57,16 +61,14 @@ class CoopGameActivity(GameActivity[PlayerType, TeamType]):
|
||||
self._warn_beeps_sound = _ba.getsound('warnBeeps')
|
||||
|
||||
def on_begin(self) -> None:
|
||||
from ba import _general
|
||||
super().on_begin()
|
||||
|
||||
# Show achievements remaining.
|
||||
if not _ba.app.kiosk_mode:
|
||||
_ba.timer(3.8,
|
||||
_general.WeakCall(self._show_remaining_achievements))
|
||||
_ba.timer(3.8, WeakCall(self._show_remaining_achievements))
|
||||
|
||||
# Preload achievement images in case we get some.
|
||||
_ba.timer(2.0, _general.WeakCall(self._preload_achievements))
|
||||
_ba.timer(2.0, WeakCall(self._preload_achievements))
|
||||
|
||||
# Let's ask the server for a 'time-to-beat' value.
|
||||
levelname = self._get_coop_level_name()
|
||||
@ -76,7 +78,7 @@ class CoopGameActivity(GameActivity[PlayerType, TeamType]):
|
||||
self.settings_raw['name']).get_score_version_string().replace(
|
||||
' ', '_'))
|
||||
_ba.get_scores_to_beat(levelname, config_str,
|
||||
_general.WeakCall(self._on_got_scores_to_beat))
|
||||
WeakCall(self._on_got_scores_to_beat))
|
||||
|
||||
def _on_got_scores_to_beat(self, scores: List[Dict[str, Any]]) -> None:
|
||||
pass
|
||||
@ -153,18 +155,18 @@ class CoopGameActivity(GameActivity[PlayerType, TeamType]):
|
||||
|
||||
def _show_remaining_achievements(self) -> None:
|
||||
# pylint: disable=cyclic-import
|
||||
from ba import _achievement
|
||||
from ba import _lang
|
||||
from ba._achievement import get_achievements_for_coop_level
|
||||
from ba._lang import Lstr
|
||||
from bastd.actor.text import Text
|
||||
ts_h_offs = 30
|
||||
v_offs = -200
|
||||
achievements = [
|
||||
a for a in _achievement.get_achievements_for_coop_level(
|
||||
a for a in get_achievements_for_coop_level(
|
||||
self._get_coop_level_name()) if not a.complete
|
||||
]
|
||||
vrmode = _ba.app.vr_mode
|
||||
if achievements:
|
||||
Text(_lang.Lstr(resource='achievementsRemainingText'),
|
||||
Text(Lstr(resource='achievementsRemainingText'),
|
||||
host_only=True,
|
||||
position=(ts_h_offs - 10 + 40, v_offs - 10),
|
||||
transition=Text.Transition.FADE_IN,
|
||||
@ -208,12 +210,12 @@ class CoopGameActivity(GameActivity[PlayerType, TeamType]):
|
||||
Returns True if a banner will be shown;
|
||||
False otherwise
|
||||
"""
|
||||
from ba import _achievement
|
||||
from ba._achievement import get_achievement
|
||||
|
||||
if achievement_name in self._achievements_awarded:
|
||||
return
|
||||
|
||||
ach = _achievement.get_achievement(achievement_name)
|
||||
ach = get_achievement(achievement_name)
|
||||
|
||||
# If we're in the easy campaign and this achievement is hard-mode-only,
|
||||
# ignore it.
|
||||
@ -223,8 +225,8 @@ class CoopGameActivity(GameActivity[PlayerType, TeamType]):
|
||||
if ach.hard_mode_only and campaign.name == 'Easy':
|
||||
return
|
||||
except Exception:
|
||||
from ba import _error
|
||||
_error.print_exception()
|
||||
from ba._error import print_exception
|
||||
print_exception()
|
||||
|
||||
# If we haven't awarded this one, check to see if we've got it.
|
||||
# If not, set it through the game service *and* add a transaction
|
||||
@ -261,10 +263,9 @@ class CoopGameActivity(GameActivity[PlayerType, TeamType]):
|
||||
|
||||
def setup_low_life_warning_sound(self) -> None:
|
||||
"""Set up a beeping noise to play when any players are near death."""
|
||||
from ba import _general
|
||||
self._life_warning_beep = None
|
||||
self._life_warning_beep_timer = _ba.Timer(
|
||||
1.0, _general.WeakCall(self._update_life_warning), repeat=True)
|
||||
1.0, WeakCall(self._update_life_warning), repeat=True)
|
||||
|
||||
def _update_life_warning(self) -> None:
|
||||
# Beep continuously if anyone is close to death.
|
||||
|
||||
@ -42,11 +42,21 @@ class CoopSession(Session):
|
||||
These generally consist of 1-4 players against
|
||||
the computer and include functionality such as
|
||||
high score lists.
|
||||
|
||||
Attrs:
|
||||
|
||||
campaign
|
||||
The ba.Campaign instance this Session represents, or None if
|
||||
there is no associated Campaign.
|
||||
"""
|
||||
use_teams = True
|
||||
use_team_colors = False
|
||||
allow_mid_activity_joins = False
|
||||
|
||||
# Note: even though these are instance vars, we annotate them at the
|
||||
# class level so that docs generation can access their types.
|
||||
campaign: Optional[ba.Campaign]
|
||||
|
||||
def __init__(self) -> None:
|
||||
"""Instantiate a co-op mode session."""
|
||||
# pylint: disable=cyclic-import
|
||||
@ -77,16 +87,11 @@ class CoopSession(Session):
|
||||
max_players=max_players)
|
||||
|
||||
# Tournament-ID if we correspond to a co-op tournament (otherwise None)
|
||||
self.tournament_id = (app.coop_session_args['tournament_id']
|
||||
if 'tournament_id' in app.coop_session_args else
|
||||
None)
|
||||
self.tournament_id: Optional[str] = (
|
||||
app.coop_session_args.get('tournament_id'))
|
||||
|
||||
# FIXME: Could be nice to pass this in as actual args.
|
||||
self.campaign_state = {
|
||||
'campaign': (app.coop_session_args['campaign']),
|
||||
'level': app.coop_session_args['level']
|
||||
}
|
||||
self.campaign = get_campaign(self.campaign_state['campaign'])
|
||||
self.campaign = get_campaign(app.coop_session_args['campaign'])
|
||||
self.campaign_level_name: str = app.coop_session_args['level']
|
||||
|
||||
self._ran_tutorial_activity = False
|
||||
self._tutorial_activity: Optional[ba.Activity] = None
|
||||
@ -96,7 +101,7 @@ class CoopSession(Session):
|
||||
self.set_activity(_ba.new_activity(CoopJoinActivity))
|
||||
|
||||
self._next_game_instance: Optional[ba.GameActivity] = None
|
||||
self._next_game_name: Optional[str] = None
|
||||
self._next_game_level_name: Optional[str] = None
|
||||
self._update_on_deck_game_instances()
|
||||
|
||||
def get_current_game_instance(self) -> ba.GameActivity:
|
||||
@ -107,12 +112,11 @@ class CoopSession(Session):
|
||||
# pylint: disable=cyclic-import
|
||||
from ba._gameactivity import GameActivity
|
||||
|
||||
# Instantiates levels we might be running soon
|
||||
# so they have time to load.
|
||||
# Instantiate levels we may be running soon to let them load in the bg.
|
||||
|
||||
# Build an instance for the current level.
|
||||
assert self.campaign is not None
|
||||
level = self.campaign.get_level(self.campaign_state['level'])
|
||||
level = self.campaign.get_level(self.campaign_level_name)
|
||||
gametype = level.gametype
|
||||
settings = level.get_settings()
|
||||
|
||||
@ -128,7 +132,7 @@ class CoopSession(Session):
|
||||
|
||||
# Find the next level and build an instance for it too.
|
||||
levels = self.campaign.get_levels()
|
||||
level = self.campaign.get_level(self.campaign_state['level'])
|
||||
level = self.campaign.get_level(self.campaign_level_name)
|
||||
|
||||
nextlevel: Optional[ba.Level]
|
||||
if level.index < len(levels) - 1:
|
||||
@ -149,15 +153,15 @@ class CoopSession(Session):
|
||||
newactivity = _ba.new_activity(gametype, settings)
|
||||
assert isinstance(newactivity, GameActivity)
|
||||
self._next_game_instance = newactivity
|
||||
self._next_game_name = nextlevel.name
|
||||
self._next_game_level_name = nextlevel.name
|
||||
else:
|
||||
self._next_game_instance = None
|
||||
self._next_game_name = None
|
||||
self._next_game_level_name = None
|
||||
|
||||
# Special case:
|
||||
# If our current level is 'onslaught training', instantiate
|
||||
# our tutorial so its ready to go. (if we haven't run it yet).
|
||||
if (self.campaign_state['level'] == 'Onslaught Training'
|
||||
if (self.campaign_level_name == 'Onslaught Training'
|
||||
and self._tutorial_activity is None
|
||||
and not self._ran_tutorial_activity):
|
||||
from bastd.tutorial import TutorialActivity
|
||||
@ -248,6 +252,7 @@ class CoopSession(Session):
|
||||
from ba._coopgame import CoopGameActivity
|
||||
from ba._gameresults import TeamGameResults
|
||||
from ba._score import ScoreType
|
||||
from ba._player import PlayerInfo
|
||||
from bastd.tutorial import TutorialActivity
|
||||
from bastd.activity.coopscore import CoopScoreScreen
|
||||
|
||||
@ -278,9 +283,9 @@ class CoopSession(Session):
|
||||
|
||||
if outcome == 'next_level':
|
||||
if self._next_game_instance is None:
|
||||
raise Exception()
|
||||
assert self._next_game_name is not None
|
||||
self.campaign_state['level'] = self._next_game_name
|
||||
raise RuntimeError()
|
||||
assert self._next_game_level_name is not None
|
||||
self.campaign_level_name = self._next_game_level_name
|
||||
next_game = self._next_game_instance
|
||||
else:
|
||||
next_game = self._current_game_instance
|
||||
@ -289,10 +294,10 @@ class CoopSession(Session):
|
||||
# and will be going into onslaught-training, show the
|
||||
# tutorial first.
|
||||
if (isinstance(activity, JoinActivity)
|
||||
and self.campaign_state['level'] == 'Onslaught Training'
|
||||
and self.campaign_level_name == 'Onslaught Training'
|
||||
and not app.kiosk_mode):
|
||||
if self._tutorial_activity is None:
|
||||
raise RuntimeError('tutorial not preloaded properly')
|
||||
raise RuntimeError('Tutorial not preloaded properly.')
|
||||
self.set_activity(self._tutorial_activity)
|
||||
self._tutorial_activity = None
|
||||
self._ran_tutorial_activity = True
|
||||
@ -336,6 +341,8 @@ class CoopSession(Session):
|
||||
self.set_activity(_ba.new_activity(TransitionActivity))
|
||||
else:
|
||||
|
||||
player_info: List[ba.PlayerInfo]
|
||||
|
||||
# Generic team games.
|
||||
if isinstance(results, TeamGameResults):
|
||||
player_info = results.get_player_info()
|
||||
@ -364,8 +371,7 @@ class CoopSession(Session):
|
||||
|
||||
# Old coop-game-specific results; should migrate away from these.
|
||||
else:
|
||||
player_info = (results['player_info']
|
||||
if 'player_info' in results else None)
|
||||
player_info = results.get('player_info')
|
||||
score = results['score'] if 'score' in results else None
|
||||
fail_message = (results['fail_message']
|
||||
if 'fail_message' in results else None)
|
||||
@ -376,6 +382,11 @@ class CoopSession(Session):
|
||||
assert activity_score_type is not None
|
||||
score_type = activity_score_type
|
||||
|
||||
# Validate types.
|
||||
if player_info is not None:
|
||||
assert isinstance(player_info, list)
|
||||
assert (isinstance(i, PlayerInfo) for i in player_info)
|
||||
|
||||
# Looks like we were in a round - check the outcome and
|
||||
# go from there.
|
||||
if outcome == 'restart':
|
||||
@ -393,7 +404,7 @@ class CoopSession(Session):
|
||||
'score_type': score_type,
|
||||
'outcome': outcome,
|
||||
'campaign': self.campaign,
|
||||
'level': self.campaign_state['level']
|
||||
'level': self.campaign_level_name
|
||||
}))
|
||||
|
||||
# No matter what, get the next 2 levels ready to go.
|
||||
|
||||
@ -49,6 +49,16 @@ class DependencyError(Exception):
|
||||
return self._deps
|
||||
|
||||
|
||||
class ContextError(Exception):
|
||||
"""Exception raised when a call is made in an invalid context.
|
||||
|
||||
category: Exception Classes
|
||||
|
||||
Examples of this include calling UI functions within an Activity context
|
||||
or calling scene manipulation functions outside of a game context.
|
||||
"""
|
||||
|
||||
|
||||
class NotFoundError(Exception):
|
||||
"""Exception raised when a referenced object does not exist.
|
||||
|
||||
|
||||
@ -30,6 +30,7 @@ from ba._activity import Activity
|
||||
from ba._score import ScoreInfo
|
||||
from ba._lang import Lstr
|
||||
from ba._messages import PlayerDiedMessage
|
||||
from ba._error import NotFoundError, print_error, print_exception
|
||||
import _ba
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@ -273,15 +274,18 @@ class GameActivity(Activity[PlayerType, TeamType]):
|
||||
# Set some defaults.
|
||||
self.allow_pausing = True
|
||||
self.allow_kick_idle_players = True
|
||||
self._spawn_sound = _ba.getsound('spawn')
|
||||
|
||||
# Whether to show points for kills.
|
||||
self._show_kill_points = True
|
||||
self.show_kill_points = True
|
||||
|
||||
# If not None, the music type that should play in on_transition_in()
|
||||
# (unless overridden by the map).
|
||||
self.default_music: Optional[ba.MusicType] = None
|
||||
|
||||
# Holds some flattened info about the player set at the point
|
||||
# when on_begin() is called.
|
||||
self.initial_player_info: Optional[List[ba.PlayerInfo]] = None
|
||||
|
||||
# Go ahead and get our map loading.
|
||||
map_name: str
|
||||
if 'map' in settings:
|
||||
@ -298,13 +302,13 @@ class GameActivity(Activity[PlayerType, TeamType]):
|
||||
_ba.screenmessage(Lstr(resource='noValidMapsErrorText'))
|
||||
raise Exception('No valid maps')
|
||||
map_name = valid_maps[random.randrange(len(valid_maps))]
|
||||
self._spawn_sound = _ba.getsound('spawn')
|
||||
self._map_type = _map.get_map_class(map_name)
|
||||
self._map_type.preload()
|
||||
self._map: Optional[ba.Map] = None
|
||||
self._powerup_drop_timer: Optional[ba.Timer] = None
|
||||
self._tnt_spawners: Optional[Dict[int, TNTSpawner]] = None
|
||||
self._tnt_drop_timer: Optional[ba.Timer] = None
|
||||
self.initial_player_info: Optional[List[Dict[str, Any]]] = None
|
||||
self._game_scoreboard_name_text: Optional[ba.Actor] = None
|
||||
self._game_scoreboard_description_text: Optional[ba.Actor] = None
|
||||
self._standard_time_limit_time: Optional[int] = None
|
||||
@ -333,7 +337,6 @@ class GameActivity(Activity[PlayerType, TeamType]):
|
||||
Raises a ba.NotFoundError if the map does not currently exist.
|
||||
"""
|
||||
if self._map is None:
|
||||
from ba._error import NotFoundError
|
||||
raise NotFoundError
|
||||
return self._map
|
||||
|
||||
@ -355,10 +358,9 @@ class GameActivity(Activity[PlayerType, TeamType]):
|
||||
campaign = self.session.campaign
|
||||
assert campaign is not None
|
||||
return campaign.get_level(
|
||||
self.session.campaign_state['level']).displayname
|
||||
self.session.campaign_level_name).displayname
|
||||
except Exception:
|
||||
from ba import _error
|
||||
_error.print_error('error getting campaign level name')
|
||||
print_error('error getting campaign level name')
|
||||
return self.get_instance_display_string()
|
||||
|
||||
def get_instance_description(self) -> Union[str, Sequence]:
|
||||
@ -415,19 +417,15 @@ class GameActivity(Activity[PlayerType, TeamType]):
|
||||
return ''
|
||||
|
||||
def on_transition_in(self) -> None:
|
||||
|
||||
super().on_transition_in()
|
||||
|
||||
# Make our map.
|
||||
self._map = self._map_type()
|
||||
|
||||
music = self.default_music
|
||||
|
||||
# give our map a chance to override the music
|
||||
# (for happy-thoughts and other such themed maps)
|
||||
override_music = self._map_type.get_music_type()
|
||||
if override_music is not None:
|
||||
music = override_music
|
||||
# Give our map a chance to override the music
|
||||
# (for happy-thoughts and other such themed maps).
|
||||
map_music = self._map_type.get_music_type()
|
||||
music = map_music if map_music is not None else self.default_music
|
||||
|
||||
if music is not None:
|
||||
from ba import _music
|
||||
@ -470,9 +468,9 @@ class GameActivity(Activity[PlayerType, TeamType]):
|
||||
and calls either end_game or continue_game depending on the result"""
|
||||
# pylint: disable=too-many-nested-blocks
|
||||
# pylint: disable=cyclic-import
|
||||
from bastd.ui import continues
|
||||
from ba import _gameutils
|
||||
from ba import _general
|
||||
from bastd.ui.continues import ContinuesWindow
|
||||
from ba._gameutils import sharedobj
|
||||
from ba._general import WeakCall
|
||||
from ba._coopsession import CoopSession
|
||||
from ba._enums import TimeType
|
||||
|
||||
@ -490,7 +488,7 @@ class GameActivity(Activity[PlayerType, TeamType]):
|
||||
if isinstance(session, CoopSession):
|
||||
assert session.campaign is not None
|
||||
if session.campaign.sequential:
|
||||
gnode = _gameutils.sharedobj('globals')
|
||||
gnode = sharedobj('globals')
|
||||
|
||||
# Only attempt this if we're not currently paused
|
||||
# and there appears to be no UI.
|
||||
@ -501,19 +499,18 @@ class GameActivity(Activity[PlayerType, TeamType]):
|
||||
with _ba.Context('ui'):
|
||||
_ba.timer(
|
||||
0.5,
|
||||
lambda: continues.ContinuesWindow(
|
||||
lambda: ContinuesWindow(
|
||||
self,
|
||||
self._continue_cost,
|
||||
continue_call=_general.WeakCall(
|
||||
continue_call=WeakCall(
|
||||
self._continue_choice, True),
|
||||
cancel_call=_general.WeakCall(
|
||||
cancel_call=WeakCall(
|
||||
self._continue_choice, False)),
|
||||
timetype=TimeType.REAL)
|
||||
return
|
||||
|
||||
except Exception:
|
||||
from ba import _error
|
||||
_error.print_exception('error continuing game')
|
||||
print_exception('error continuing game')
|
||||
|
||||
self.end_game()
|
||||
|
||||
@ -525,8 +522,8 @@ class GameActivity(Activity[PlayerType, TeamType]):
|
||||
from ba._freeforallsession import FreeForAllSession
|
||||
from ba._coopsession import CoopSession
|
||||
session = self.session
|
||||
campaign = session.campaign
|
||||
if isinstance(session, CoopSession):
|
||||
campaign = session.campaign
|
||||
assert campaign is not None
|
||||
_ba.set_analytics_screen(
|
||||
'Coop Game: ' + campaign.name + ' ' +
|
||||
@ -576,13 +573,13 @@ class GameActivity(Activity[PlayerType, TeamType]):
|
||||
|
||||
def on_begin(self) -> None:
|
||||
from ba._general import WeakCall
|
||||
from ba._player import PlayerInfo
|
||||
super().on_begin()
|
||||
|
||||
try:
|
||||
self._game_begin_analytics()
|
||||
except Exception:
|
||||
from ba import _error
|
||||
_error.print_exception('error in game-begin-analytics')
|
||||
print_exception('error in game-begin-analytics')
|
||||
|
||||
# We don't do this in on_transition_in because it may depend on
|
||||
# players/teams which aren't available until now.
|
||||
@ -591,26 +588,27 @@ class GameActivity(Activity[PlayerType, TeamType]):
|
||||
_ba.timer(2.5, WeakCall(self._show_tip))
|
||||
|
||||
# Store some basic info about players present at start time.
|
||||
self.initial_player_info = [{
|
||||
'name': p.get_name(full=True),
|
||||
'character': p.character
|
||||
} for p in self.players]
|
||||
self.initial_player_info = [
|
||||
PlayerInfo(name=p.get_name(full=True), character=p.character)
|
||||
for p in self.players
|
||||
]
|
||||
|
||||
# Sort this by name so high score lists/etc will be consistent
|
||||
# regardless of player join order.
|
||||
self.initial_player_info.sort(key=lambda x: x['name'])
|
||||
self.initial_player_info.sort(key=lambda x: x.name)
|
||||
|
||||
# If this is a tournament, query info about it such as how much
|
||||
# time is left.
|
||||
tournament_id = self.session.tournament_id
|
||||
|
||||
if tournament_id is not None:
|
||||
_ba.tournament_query(args={
|
||||
'tournamentIDs': [tournament_id],
|
||||
'source': 'in-game time remaining query'
|
||||
},
|
||||
callback=WeakCall(
|
||||
self._on_tournament_query_response))
|
||||
_ba.tournament_query(
|
||||
args={
|
||||
'tournamentIDs': [tournament_id],
|
||||
'source': 'in-game time remaining query'
|
||||
},
|
||||
callback=WeakCall(self._on_tournament_query_response),
|
||||
)
|
||||
|
||||
def _on_tournament_query_response(self, data: Optional[Dict[str,
|
||||
Any]]) -> None:
|
||||
@ -670,7 +668,7 @@ class GameActivity(Activity[PlayerType, TeamType]):
|
||||
kill=True,
|
||||
victim_player=player,
|
||||
importance=importance,
|
||||
showpoints=self._show_kill_points)
|
||||
showpoints=self.show_kill_points)
|
||||
|
||||
def show_scoreboard_info(self) -> None:
|
||||
"""Create the game info display.
|
||||
@ -916,19 +914,19 @@ class GameActivity(Activity[PlayerType, TeamType]):
|
||||
force: bool = False) -> None:
|
||||
from ba._gameresults import TeamGameResults
|
||||
|
||||
# if results is a standard team-game-results, associate it with us
|
||||
# so it can grab our score prefs
|
||||
# If results is a standard team-game-results, associate it with us
|
||||
# so it can grab our score prefs.
|
||||
if isinstance(results, TeamGameResults):
|
||||
results.set_game(self)
|
||||
|
||||
# if we had a standard time-limit that had not expired, stop it so
|
||||
# it doesnt tick annoyingly
|
||||
# If we had a standard time-limit that had not expired, stop it so
|
||||
# it doesnt tick annoyingly.
|
||||
if (self._standard_time_limit_time is not None
|
||||
and self._standard_time_limit_time > 0):
|
||||
self._standard_time_limit_timer = None
|
||||
self._standard_time_limit_text = None
|
||||
|
||||
# ditto with tournament time limits
|
||||
# Ditto with tournament time limits.
|
||||
if (self._tournament_time_limit is not None
|
||||
and self._tournament_time_limit > 0):
|
||||
self._tournament_time_limit_timer = None
|
||||
|
||||
@ -57,7 +57,7 @@ class TeamGameResults:
|
||||
self._scores: Dict[int, Tuple[ReferenceType[ba.SessionTeam],
|
||||
Optional[int]]] = {}
|
||||
self._teams: Optional[List[ReferenceType[ba.SessionTeam]]] = None
|
||||
self._player_info: Optional[List[Dict[str, Any]]] = None
|
||||
self._player_info: Optional[List[ba.PlayerInfo]] = None
|
||||
self._lower_is_better: Optional[bool] = None
|
||||
self._score_label: Optional[str] = None
|
||||
self._none_is_winner: Optional[bool] = None
|
||||
@ -141,7 +141,7 @@ class TeamGameResults:
|
||||
return Lstr(value=str(score[1]))
|
||||
return Lstr(value='-')
|
||||
|
||||
def get_player_info(self) -> List[Dict[str, Any]]:
|
||||
def get_player_info(self) -> List[ba.PlayerInfo]:
|
||||
"""Get info about the players represented by the results."""
|
||||
if not self._game_set:
|
||||
raise RuntimeError("Can't get player-info until game is set.")
|
||||
|
||||
@ -97,7 +97,7 @@ def sharedobj(name: str) -> Any:
|
||||
|
||||
# We store these on the current context; whether its an activity or
|
||||
# session.
|
||||
activity: Optional[ba.Activity] = _ba.getactivity(doraise=False)
|
||||
activity = _ba.getactivity(doraise=False)
|
||||
if activity is not None:
|
||||
|
||||
# Grab shared-objs dict.
|
||||
@ -105,8 +105,8 @@ def sharedobj(name: str) -> Any:
|
||||
|
||||
# Grab item out of it.
|
||||
try:
|
||||
return sharedobjs[name]
|
||||
except Exception:
|
||||
return sharedobjs[name] # (pylint bug?) pylint: disable=E1136
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
obj: Any
|
||||
@ -141,7 +141,7 @@ def sharedobj(name: str) -> Any:
|
||||
"unrecognized shared object (activity context): '" + name +
|
||||
"'")
|
||||
else:
|
||||
session: Optional[ba.Session] = _ba.getsession(doraise=False)
|
||||
session = _ba.getsession(doraise=False)
|
||||
if session is not None:
|
||||
|
||||
# Grab shared-objs dict (creating if necessary).
|
||||
|
||||
@ -83,7 +83,7 @@ class ServerCallThread(threading.Thread):
|
||||
self._context = _ba.Context('current')
|
||||
|
||||
# Save and restore the context we were created from.
|
||||
activity: Optional[ba.Activity] = _ba.getactivity(doraise=False)
|
||||
activity = _ba.getactivity(doraise=False)
|
||||
self._activity = weakref.ref(
|
||||
activity) if activity is not None else None
|
||||
|
||||
|
||||
@ -22,6 +22,7 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import TYPE_CHECKING, TypeVar, Generic
|
||||
|
||||
import _ba
|
||||
@ -35,6 +36,16 @@ PlayerType = TypeVar('PlayerType', bound='ba.Player')
|
||||
TeamType = TypeVar('TeamType', bound='ba.Team')
|
||||
|
||||
|
||||
@dataclass
|
||||
class PlayerInfo:
|
||||
"""Holds basic info about a player.
|
||||
|
||||
Category: Gameplay Classes
|
||||
"""
|
||||
name: str
|
||||
character: str
|
||||
|
||||
|
||||
class Player(Generic[TeamType]):
|
||||
"""A player in a specific ba.Activity.
|
||||
|
||||
|
||||
@ -70,10 +70,6 @@ class Session:
|
||||
Be aware this value may be None if a Session does not allow
|
||||
any such selection.
|
||||
|
||||
campaign
|
||||
The ba.Campaign instance this Session represents, or None if
|
||||
there is no associated Campaign.
|
||||
|
||||
use_teams
|
||||
Whether this session groups players into an explicit set of
|
||||
teams. If this is off, a unique team is generated for each
|
||||
@ -95,7 +91,6 @@ class Session:
|
||||
|
||||
# Note: even though these are instance vars, we annotate them at the
|
||||
# class level so that docs generation can access their types.
|
||||
campaign: Optional[ba.Campaign]
|
||||
lobby: ba.Lobby
|
||||
max_players: int
|
||||
min_players: int
|
||||
@ -161,30 +156,28 @@ class Session:
|
||||
# print('Would set host-session asset-reqs to:',
|
||||
# required_asset_packages)
|
||||
|
||||
# Stuff in this section should be removed from this class if possible.
|
||||
# Init our C++ layer data.
|
||||
self._sessiondata = _ba.register_session(self)
|
||||
|
||||
# Stuff in this section should be removed from this class if possible.
|
||||
self.tournament_id: Optional[str] = None
|
||||
self.sharedobjs: Dict[str, Any] = {}
|
||||
self.have_shown_controls_help_overlay = False
|
||||
self.campaign = None
|
||||
self.campaign_state: Dict[str, str] = {}
|
||||
|
||||
self.teams = []
|
||||
self.players = []
|
||||
self.min_players = min_players
|
||||
self.max_players = max_players
|
||||
|
||||
self._in_set_activity = False
|
||||
self._next_team_id = 0
|
||||
self._activity_retained: Optional[ba.Activity] = None
|
||||
self._launch_end_session_activity_time: Optional[float] = None
|
||||
self._activity_end_timer: Optional[ba.Timer] = None
|
||||
self._activity_weak = empty_weakref(Activity)
|
||||
if self._activity_weak() is not None:
|
||||
raise Exception('Error creating empty activity weak ref.')
|
||||
|
||||
self._next_activity: Optional[ba.Activity] = None
|
||||
self.wants_to_end = False
|
||||
self._ending = False
|
||||
self.min_players = min_players
|
||||
self.max_players = max_players
|
||||
|
||||
# Create static teams if we're using them.
|
||||
if self.use_teams:
|
||||
|
||||
@ -35,17 +35,21 @@ if TYPE_CHECKING:
|
||||
class CoopJoinActivity(JoinActivity):
|
||||
"""Join-screen for co-op mode."""
|
||||
|
||||
# We can assume our session is a CoopSession.
|
||||
session: ba.CoopSession
|
||||
|
||||
def __init__(self, settings: Dict[str, Any]):
|
||||
super().__init__(settings)
|
||||
session = ba.getsession()
|
||||
session = self.session
|
||||
assert isinstance(session, ba.CoopSession)
|
||||
|
||||
# Let's show a list of scores-to-beat for 1 player at least.
|
||||
assert session.campaign is not None
|
||||
level_name_full = (session.campaign.name + ':' +
|
||||
session.campaign_state['level'])
|
||||
config_str = (
|
||||
'1p' + session.campaign.get_level(session.campaign_state['level']).
|
||||
get_score_version_string().replace(' ', '_'))
|
||||
session.campaign_level_name)
|
||||
config_str = ('1p' + session.campaign.get_level(
|
||||
session.campaign_level_name).get_score_version_string().replace(
|
||||
' ', '_'))
|
||||
_ba.get_scores_to_beat(level_name_full, config_str,
|
||||
ba.WeakCall(self._on_got_scores_to_beat))
|
||||
|
||||
@ -53,9 +57,10 @@ class CoopJoinActivity(JoinActivity):
|
||||
from bastd.actor.controlsguide import ControlsGuide
|
||||
from bastd.actor.text import Text
|
||||
super().on_transition_in()
|
||||
assert isinstance(self.session, ba.CoopSession)
|
||||
assert self.session.campaign
|
||||
Text(self.session.campaign.get_level(
|
||||
self.session.campaign_state['level']).displayname,
|
||||
self.session.campaign_level_name).displayname,
|
||||
scale=1.3,
|
||||
h_attach=Text.HAttach.CENTER,
|
||||
h_align=Text.HAlign.CENTER,
|
||||
@ -163,8 +168,9 @@ class CoopJoinActivity(JoinActivity):
|
||||
|
||||
# Now list our remaining achievements for this level.
|
||||
assert self.session.campaign is not None
|
||||
assert isinstance(self.session, ba.CoopSession)
|
||||
levelname = (self.session.campaign.name + ':' +
|
||||
self.session.campaign_state['level'])
|
||||
self.session.campaign_level_name)
|
||||
ts_h_offs = 60
|
||||
|
||||
if not ba.app.kiosk_mode:
|
||||
|
||||
@ -137,7 +137,10 @@ class CoopScoreScreen(ba.Activity[ba.Player, ba.Team]):
|
||||
self._tournament_time_remaining_text: Optional[Text] = None
|
||||
self._tournament_time_remaining_text_timer: Optional[ba.Timer] = None
|
||||
|
||||
self._player_info = settings['player_info']
|
||||
self._player_info: List[ba.PlayerInfo] = settings['player_info']
|
||||
assert isinstance(self._player_info, list)
|
||||
assert (isinstance(i, ba.PlayerInfo) for i in self._player_info)
|
||||
|
||||
self._score: Optional[int] = settings['score']
|
||||
assert isinstance(self._score, (int, type(None)))
|
||||
|
||||
@ -633,7 +636,7 @@ class CoopScoreScreen(ba.Activity[ba.Player, ba.Team]):
|
||||
ba.pushcall(ba.WeakCall(self._show_fail))
|
||||
|
||||
self._name_str = name_str = ', '.join(
|
||||
[p['name'] for p in self._player_info])
|
||||
[p.name for p in self._player_info])
|
||||
|
||||
if self._show_friend_scores:
|
||||
self._friends_loading_status = Text(
|
||||
@ -668,7 +671,10 @@ class CoopScoreScreen(ba.Activity[ba.Player, ba.Team]):
|
||||
if self._score is not None:
|
||||
our_score: Optional[list] = [
|
||||
self._score, {
|
||||
'players': self._player_info
|
||||
'players': [{
|
||||
'name': p.name,
|
||||
'character': p.character
|
||||
} for p in self._player_info]
|
||||
}
|
||||
]
|
||||
our_high_scores.append(our_score)
|
||||
|
||||
@ -37,6 +37,8 @@ class TeamVictoryScoreScreenActivity(MultiTeamScoreScreenActivity):
|
||||
|
||||
def __init__(self, settings: Dict[str, Any]):
|
||||
super().__init__(settings=settings)
|
||||
self._winner: ba.SessionTeam = settings['winner']
|
||||
assert isinstance(self._winner, ba.SessionTeam)
|
||||
|
||||
def on_begin(self) -> None:
|
||||
from ba.deprecated import get_resource
|
||||
@ -80,7 +82,7 @@ class TeamVictoryScoreScreenActivity(MultiTeamScoreScreenActivity):
|
||||
i * 0.2, shift_time - (i * 0.150 + 0.150)))
|
||||
ba.timer(i * 0.150 + 0.5,
|
||||
ba.Call(ba.playsound, self._score_display_sound_small))
|
||||
scored = (team is self.settings_raw['winner'])
|
||||
scored = (team is self._winner)
|
||||
delay = 0.2
|
||||
if scored:
|
||||
delay = 1.2
|
||||
|
||||
@ -999,7 +999,7 @@ class SpazBotSet:
|
||||
"""Immediately clear out any bots in the set."""
|
||||
|
||||
# Don't do this if the activity is shutting down or dead.
|
||||
activity: Optional[ba.Activity] = ba.getactivity(doraise=False)
|
||||
activity = ba.getactivity(doraise=False)
|
||||
if activity is None or activity.expired:
|
||||
return
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<!-- THIS FILE IS AUTO GENERATED; DO NOT EDIT BY HAND -->
|
||||
<h4><em>last updated on 2020-05-27 for Ballistica version 1.5.0 build 20030</em></h4>
|
||||
<h4><em>last updated on 2020-05-28 for Ballistica version 1.5.0 build 20031</em></h4>
|
||||
<p>This page documents the Python classes and functions in the 'ba' module,
|
||||
which are the ones most relevant to modding in Ballistica. If you come across something you feel should be included here or could be better explained, please <a href="mailto:support@froemling.net">let me know</a>. Happy modding!</p>
|
||||
<hr>
|
||||
@ -26,6 +26,7 @@
|
||||
<li><a href="#class_ba_Material">ba.Material</a></li>
|
||||
<li><a href="#class_ba_Node">ba.Node</a></li>
|
||||
<li><a href="#class_ba_Player">ba.Player</a></li>
|
||||
<li><a href="#class_ba_PlayerInfo">ba.PlayerInfo</a></li>
|
||||
<li><a href="#class_ba_PlayerRecord">ba.PlayerRecord</a></li>
|
||||
<li><a href="#class_ba_ScoreInfo">ba.ScoreInfo</a></li>
|
||||
<li><a href="#class_ba_Session">ba.Session</a></li>
|
||||
@ -185,6 +186,7 @@
|
||||
</ul>
|
||||
<h4><a name="class_category_Exception_Classes">Exception Classes</a></h4>
|
||||
<ul>
|
||||
<li><a href="#class_ba_ContextError">ba.ContextError</a></li>
|
||||
<li><a href="#class_ba_DependencyError">ba.DependencyError</a></li>
|
||||
<li><a href="#class_ba_NotFoundError">ba.NotFoundError</a></li>
|
||||
<ul>
|
||||
@ -1514,6 +1516,19 @@ start_some_long_action(callback_when_done=self.dosomething)</pre>
|
||||
<span><em><small># to our activity.</small></em></span>
|
||||
start_long_action(callback_when_done=<a href="#class_ba_ContextCall">ba.ContextCall</a>(self.mycallback))</pre>
|
||||
|
||||
<hr>
|
||||
<h2><strong><a name="class_ba_ContextError">ba.ContextError</a></strong></h3>
|
||||
<p>Inherits from: Exception, BaseException</p>
|
||||
<p>Exception raised when a call is made in an invalid context.</p>
|
||||
|
||||
<p>Category: <a href="#class_category_Exception_Classes">Exception Classes</a></p>
|
||||
|
||||
<p> Examples of this include calling UI functions within an Activity context
|
||||
or calling scene manipulation functions outside of a game context.
|
||||
</p>
|
||||
|
||||
<h3>Methods:</h3>
|
||||
<p><all methods inherited from <a href="#class_builtins_Exception">builtins.Exception</a>></p>
|
||||
<hr>
|
||||
<h2><strong><a name="class_ba_CoopGameActivity">ba.CoopGameActivity</a></strong></h3>
|
||||
<p>Inherits from: <a href="#class_ba_GameActivity">ba.GameActivity</a>, <a href="#class_ba_Activity">ba.Activity</a>, <a href="#class_ba_DependencyComponent">ba.DependencyComponent</a>, <a href="#class_typing_Generic">typing.Generic</a></p>
|
||||
@ -1639,11 +1654,19 @@ and it should begin its actual game logic.</p>
|
||||
|
||||
<p> These generally consist of 1-4 players against
|
||||
the computer and include functionality such as
|
||||
high score lists.
|
||||
</p>
|
||||
high score lists.</p>
|
||||
|
||||
<h3>Attributes Inherited:</h3>
|
||||
<h5><a href="#attr_ba_Session__allow_mid_activity_joins">allow_mid_activity_joins</a>, <a href="#attr_ba_Session__campaign">campaign</a>, <a href="#attr_ba_Session__lobby">lobby</a>, <a href="#attr_ba_Session__max_players">max_players</a>, <a href="#attr_ba_Session__min_players">min_players</a>, <a href="#attr_ba_Session__players">players</a>, <a href="#attr_ba_Session__teams">teams</a>, <a href="#attr_ba_Session__use_team_colors">use_team_colors</a>, <a href="#attr_ba_Session__use_teams">use_teams</a></h5>
|
||||
<h5><a href="#attr_ba_Session__allow_mid_activity_joins">allow_mid_activity_joins</a>, <a href="#attr_ba_Session__lobby">lobby</a>, <a href="#attr_ba_Session__max_players">max_players</a>, <a href="#attr_ba_Session__min_players">min_players</a>, <a href="#attr_ba_Session__players">players</a>, <a href="#attr_ba_Session__teams">teams</a>, <a href="#attr_ba_Session__use_team_colors">use_team_colors</a>, <a href="#attr_ba_Session__use_teams">use_teams</a></h5>
|
||||
<h3>Attributes Defined Here:</h3>
|
||||
<dl>
|
||||
<dt><h4><a name="attr_ba_CoopSession__campaign">campaign</a></h4></dt><dd>
|
||||
<p><span>Optional[<a href="#class_ba_Campaign">ba.Campaign</a>]</span></p>
|
||||
<p>The <a href="#class_ba_Campaign">ba.Campaign</a> instance this Session represents, or None if
|
||||
there is no associated Campaign.</p>
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Methods Inherited:</h3>
|
||||
<h5><a href="#method_ba_Session__begin_next_activity">begin_next_activity()</a>, <a href="#method_ba_Session__end">end()</a>, <a href="#method_ba_Session__end_activity">end_activity()</a>, <a href="#method_ba_Session__getactivity">getactivity()</a>, <a href="#method_ba_Session__handlemessage">handlemessage()</a>, <a href="#method_ba_Session__launch_end_session_activity">launch_end_session_activity()</a>, <a href="#method_ba_Session__on_player_request">on_player_request()</a>, <a href="#method_ba_Session__on_team_join">on_team_join()</a>, <a href="#method_ba_Session__on_team_leave">on_team_leave()</a>, <a href="#method_ba_Session__set_activity">set_activity()</a>, <a href="#method_ba_Session__transitioning_out_activity_was_freed">transitioning_out_activity_was_freed()</a></h5>
|
||||
<h3>Methods Defined or Overridden:</h3>
|
||||
@ -1986,7 +2009,7 @@ its time with lingering corpses, sound effects, etc.</p>
|
||||
</p>
|
||||
|
||||
<h3>Attributes Inherited:</h3>
|
||||
<h5><a href="#attr_ba_Session__allow_mid_activity_joins">allow_mid_activity_joins</a>, <a href="#attr_ba_Session__campaign">campaign</a>, <a href="#attr_ba_Session__lobby">lobby</a>, <a href="#attr_ba_Session__max_players">max_players</a>, <a href="#attr_ba_Session__min_players">min_players</a>, <a href="#attr_ba_Session__players">players</a>, <a href="#attr_ba_Session__teams">teams</a>, <a href="#attr_ba_Session__use_team_colors">use_team_colors</a>, <a href="#attr_ba_Session__use_teams">use_teams</a></h5>
|
||||
<h5><a href="#attr_ba_Session__allow_mid_activity_joins">allow_mid_activity_joins</a>, <a href="#attr_ba_Session__lobby">lobby</a>, <a href="#attr_ba_Session__max_players">max_players</a>, <a href="#attr_ba_Session__min_players">min_players</a>, <a href="#attr_ba_Session__players">players</a>, <a href="#attr_ba_Session__teams">teams</a>, <a href="#attr_ba_Session__use_team_colors">use_team_colors</a>, <a href="#attr_ba_Session__use_teams">use_teams</a></h5>
|
||||
<h3>Methods Inherited:</h3>
|
||||
<h5><a href="#method_ba_MultiTeamSession__announce_game_results">announce_game_results()</a>, <a href="#method_ba_MultiTeamSession__begin_next_activity">begin_next_activity()</a>, <a href="#method_ba_MultiTeamSession__end">end()</a>, <a href="#method_ba_MultiTeamSession__end_activity">end_activity()</a>, <a href="#method_ba_MultiTeamSession__get_custom_menu_entries">get_custom_menu_entries()</a>, <a href="#method_ba_MultiTeamSession__get_ffa_series_length">get_ffa_series_length()</a>, <a href="#method_ba_MultiTeamSession__get_game_number">get_game_number()</a>, <a href="#method_ba_MultiTeamSession__get_max_players">get_max_players()</a>, <a href="#method_ba_MultiTeamSession__get_next_game_description">get_next_game_description()</a>, <a href="#method_ba_MultiTeamSession__get_series_length">get_series_length()</a>, <a href="#method_ba_MultiTeamSession__getactivity">getactivity()</a>, <a href="#method_ba_MultiTeamSession__handlemessage">handlemessage()</a>, <a href="#method_ba_MultiTeamSession__launch_end_session_activity">launch_end_session_activity()</a>, <a href="#method_ba_MultiTeamSession__on_activity_end">on_activity_end()</a>, <a href="#method_ba_MultiTeamSession__on_player_leave">on_player_leave()</a>, <a href="#method_ba_MultiTeamSession__on_player_request">on_player_request()</a>, <a href="#method_ba_MultiTeamSession__on_team_join">on_team_join()</a>, <a href="#method_ba_MultiTeamSession__on_team_leave">on_team_leave()</a>, <a href="#method_ba_MultiTeamSession__set_activity">set_activity()</a>, <a href="#method_ba_MultiTeamSession__transitioning_out_activity_was_freed">transitioning_out_activity_was_freed()</a></h5>
|
||||
<h3>Methods Defined or Overridden:</h3>
|
||||
@ -2024,7 +2047,7 @@ its time with lingering corpses, sound effects, etc.</p>
|
||||
</p>
|
||||
|
||||
<h3>Attributes Inherited:</h3>
|
||||
<h5><a href="#attr_ba_Session__allow_mid_activity_joins">allow_mid_activity_joins</a>, <a href="#attr_ba_Session__campaign">campaign</a>, <a href="#attr_ba_Session__lobby">lobby</a>, <a href="#attr_ba_Session__max_players">max_players</a>, <a href="#attr_ba_Session__min_players">min_players</a>, <a href="#attr_ba_Session__players">players</a>, <a href="#attr_ba_Session__teams">teams</a>, <a href="#attr_ba_Session__use_team_colors">use_team_colors</a>, <a href="#attr_ba_Session__use_teams">use_teams</a></h5>
|
||||
<h5><a href="#attr_ba_Session__allow_mid_activity_joins">allow_mid_activity_joins</a>, <a href="#attr_ba_Session__lobby">lobby</a>, <a href="#attr_ba_Session__max_players">max_players</a>, <a href="#attr_ba_Session__min_players">min_players</a>, <a href="#attr_ba_Session__players">players</a>, <a href="#attr_ba_Session__teams">teams</a>, <a href="#attr_ba_Session__use_team_colors">use_team_colors</a>, <a href="#attr_ba_Session__use_teams">use_teams</a></h5>
|
||||
<h3>Methods Inherited:</h3>
|
||||
<h5><a href="#method_ba_MultiTeamSession__announce_game_results">announce_game_results()</a>, <a href="#method_ba_MultiTeamSession__begin_next_activity">begin_next_activity()</a>, <a href="#method_ba_MultiTeamSession__end">end()</a>, <a href="#method_ba_MultiTeamSession__end_activity">end_activity()</a>, <a href="#method_ba_MultiTeamSession__get_custom_menu_entries">get_custom_menu_entries()</a>, <a href="#method_ba_MultiTeamSession__get_ffa_series_length">get_ffa_series_length()</a>, <a href="#method_ba_MultiTeamSession__get_game_number">get_game_number()</a>, <a href="#method_ba_MultiTeamSession__get_max_players">get_max_players()</a>, <a href="#method_ba_MultiTeamSession__get_next_game_description">get_next_game_description()</a>, <a href="#method_ba_MultiTeamSession__get_series_length">get_series_length()</a>, <a href="#method_ba_MultiTeamSession__getactivity">getactivity()</a>, <a href="#method_ba_MultiTeamSession__handlemessage">handlemessage()</a>, <a href="#method_ba_MultiTeamSession__launch_end_session_activity">launch_end_session_activity()</a>, <a href="#method_ba_MultiTeamSession__on_activity_end">on_activity_end()</a>, <a href="#method_ba_MultiTeamSession__on_player_leave">on_player_leave()</a>, <a href="#method_ba_MultiTeamSession__on_player_request">on_player_request()</a>, <a href="#method_ba_MultiTeamSession__on_team_join">on_team_join()</a>, <a href="#method_ba_MultiTeamSession__on_team_leave">on_team_leave()</a>, <a href="#method_ba_MultiTeamSession__set_activity">set_activity()</a>, <a href="#method_ba_MultiTeamSession__transitioning_out_activity_was_freed">transitioning_out_activity_was_freed()</a></h5>
|
||||
<h3>Methods Defined or Overridden:</h3>
|
||||
@ -3328,7 +3351,7 @@ Use <a href="#function_ba_getmodel">ba.getmodel</a>() to instantiate one.</p>
|
||||
</p>
|
||||
|
||||
<h3>Attributes Inherited:</h3>
|
||||
<h5><a href="#attr_ba_Session__allow_mid_activity_joins">allow_mid_activity_joins</a>, <a href="#attr_ba_Session__campaign">campaign</a>, <a href="#attr_ba_Session__lobby">lobby</a>, <a href="#attr_ba_Session__max_players">max_players</a>, <a href="#attr_ba_Session__min_players">min_players</a>, <a href="#attr_ba_Session__players">players</a>, <a href="#attr_ba_Session__teams">teams</a>, <a href="#attr_ba_Session__use_team_colors">use_team_colors</a>, <a href="#attr_ba_Session__use_teams">use_teams</a></h5>
|
||||
<h5><a href="#attr_ba_Session__allow_mid_activity_joins">allow_mid_activity_joins</a>, <a href="#attr_ba_Session__lobby">lobby</a>, <a href="#attr_ba_Session__max_players">max_players</a>, <a href="#attr_ba_Session__min_players">min_players</a>, <a href="#attr_ba_Session__players">players</a>, <a href="#attr_ba_Session__teams">teams</a>, <a href="#attr_ba_Session__use_team_colors">use_team_colors</a>, <a href="#attr_ba_Session__use_teams">use_teams</a></h5>
|
||||
<h3>Methods Inherited:</h3>
|
||||
<h5><a href="#method_ba_Session__begin_next_activity">begin_next_activity()</a>, <a href="#method_ba_Session__end">end()</a>, <a href="#method_ba_Session__end_activity">end_activity()</a>, <a href="#method_ba_Session__get_custom_menu_entries">get_custom_menu_entries()</a>, <a href="#method_ba_Session__getactivity">getactivity()</a>, <a href="#method_ba_Session__handlemessage">handlemessage()</a>, <a href="#method_ba_Session__launch_end_session_activity">launch_end_session_activity()</a>, <a href="#method_ba_Session__on_player_leave">on_player_leave()</a>, <a href="#method_ba_Session__on_player_request">on_player_request()</a>, <a href="#method_ba_Session__on_team_leave">on_team_leave()</a>, <a href="#method_ba_Session__set_activity">set_activity()</a>, <a href="#method_ba_Session__transitioning_out_activity_was_freed">transitioning_out_activity_was_freed()</a></h5>
|
||||
<h3>Methods Defined or Overridden:</h3>
|
||||
@ -3956,6 +3979,22 @@ If False, they left the game or the round ended.</p>
|
||||
<p>The type of player for the current activity should be passed so that
|
||||
the type-checker properly identifies the returned value as one.</p>
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
<hr>
|
||||
<h2><strong><a name="class_ba_PlayerInfo">ba.PlayerInfo</a></strong></h3>
|
||||
<p><em><top level class></em>
|
||||
</p>
|
||||
<p>Holds basic info about a player.</p>
|
||||
|
||||
<p>Category: <a href="#class_category_Gameplay_Classes">Gameplay Classes</a>
|
||||
</p>
|
||||
|
||||
<h3>Methods:</h3>
|
||||
<dl>
|
||||
<dt><h4><a name="method_ba_PlayerInfo____init__"><constructor></a></dt></h4><dd>
|
||||
<p><span>ba.PlayerInfo(name: str, character: str)</span></p>
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
<hr>
|
||||
@ -4256,19 +4295,13 @@ Pass 0 or a negative number for no ban time.</p>
|
||||
maintaining state between them (players, teams, score tallies, etc).</p>
|
||||
|
||||
<h3>Attributes:</h3>
|
||||
<h5><a href="#attr_ba_Session__allow_mid_activity_joins">allow_mid_activity_joins</a>, <a href="#attr_ba_Session__campaign">campaign</a>, <a href="#attr_ba_Session__lobby">lobby</a>, <a href="#attr_ba_Session__max_players">max_players</a>, <a href="#attr_ba_Session__min_players">min_players</a>, <a href="#attr_ba_Session__players">players</a>, <a href="#attr_ba_Session__teams">teams</a>, <a href="#attr_ba_Session__use_team_colors">use_team_colors</a>, <a href="#attr_ba_Session__use_teams">use_teams</a></h5>
|
||||
<h5><a href="#attr_ba_Session__allow_mid_activity_joins">allow_mid_activity_joins</a>, <a href="#attr_ba_Session__lobby">lobby</a>, <a href="#attr_ba_Session__max_players">max_players</a>, <a href="#attr_ba_Session__min_players">min_players</a>, <a href="#attr_ba_Session__players">players</a>, <a href="#attr_ba_Session__teams">teams</a>, <a href="#attr_ba_Session__use_team_colors">use_team_colors</a>, <a href="#attr_ba_Session__use_teams">use_teams</a></h5>
|
||||
<dl>
|
||||
<dt><h4><a name="attr_ba_Session__allow_mid_activity_joins">allow_mid_activity_joins</a></h4></dt><dd>
|
||||
<p><span>bool</span></p>
|
||||
<p>Whether players should be allowed to join in the middle of
|
||||
activities.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="attr_ba_Session__campaign">campaign</a></h4></dt><dd>
|
||||
<p><span>Optional[<a href="#class_ba_Campaign">ba.Campaign</a>]</span></p>
|
||||
<p>The <a href="#class_ba_Campaign">ba.Campaign</a> instance this Session represents, or None if
|
||||
there is no associated Campaign.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="attr_ba_Session__lobby">lobby</a></h4></dt><dd>
|
||||
<p><span><a href="#class_ba_Lobby">ba.Lobby</a></span></p>
|
||||
@ -5081,7 +5114,7 @@ Results for a completed <a href="#class_ba_TeamGameActivity">ba.TeamGameActivity
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="method_ba_TeamGameResults__get_player_info">get_player_info()</a></dt></h4><dd>
|
||||
<p><span>get_player_info(self) -> List[Dict[str, Any]]</span></p>
|
||||
<p><span>get_player_info(self) -> List[<a href="#class_ba_PlayerInfo">ba.PlayerInfo</a>]</span></p>
|
||||
|
||||
<p>Get info about the players represented by the results.</p>
|
||||
|
||||
@ -5804,17 +5837,17 @@ version of the game are ignored.</p>
|
||||
|
||||
<hr>
|
||||
<h2><strong><a name="function_ba_getactivity">ba.getactivity()</a></strong></h3>
|
||||
<p><span>getactivity(doraise: bool = True) -> <a href="#class_ba_Activity">ba.Activity</a></span></p>
|
||||
<p><span>getactivity(doraise: bool = True) -> <varies></span></p>
|
||||
|
||||
<p>Returns the current <a href="#class_ba_Activity">ba.Activity</a> instance.</p>
|
||||
<p>Return the current <a href="#class_ba_Activity">ba.Activity</a> instance.</p>
|
||||
|
||||
<p>Category: <a href="#function_category_Gameplay_Functions">Gameplay Functions</a></p>
|
||||
|
||||
<p>Note that this is based on context; thus code run in a timer generated
|
||||
in Activity 'foo' will properly return 'foo' here, even if another
|
||||
Activity has since been created or is transitioning in.
|
||||
If there is no current Activity an Exception is raised, or if doraise is
|
||||
False then None is returned instead.</p>
|
||||
If there is no current Activity, raises a <a href="#class_ba_ActivityNotFoundError">ba.ActivityNotFoundError</a>.
|
||||
If doraise is False, None will be returned instead in that case.</p>
|
||||
|
||||
<hr>
|
||||
<h2><strong><a name="function_ba_getcollidemodel">ba.getcollidemodel()</a></strong></h3>
|
||||
@ -5908,7 +5941,7 @@ Category: <a href="#function_category_Gameplay_Functions">Gameplay Functions</a>
|
||||
|
||||
<hr>
|
||||
<h2><strong><a name="function_ba_getsession">ba.getsession()</a></strong></h3>
|
||||
<p><span>getsession(doraise: bool = True) -> <a href="#class_ba_Session">ba.Session</a></span></p>
|
||||
<p><span>getsession(doraise: bool = True) -> <varies></span></p>
|
||||
|
||||
<p>Category: <a href="#function_category_Gameplay_Functions">Gameplay Functions</a></p>
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user