mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-01-28 10:03:15 +08:00
Cleaned up player and team lifecycle logic
This commit is contained in:
parent
1c0e4896fa
commit
a2bb5b9751
@ -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/36/5a/025457e87759c13a5067617816cd",
|
||||
"build/prefab/linux-server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/66/49/fb5663472ab1f4bd32f5748ba4d7",
|
||||
"build/prefab/linux/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/44/3e/6eb652f11d24c22f87ae8aab399b",
|
||||
"build/prefab/linux/release/ballisticacore": "https://files.ballistica.net/cache/ba1/f4/57/7e48692454b644a7111902f12b58",
|
||||
"build/prefab/mac-server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/18/55/246021de09b021993e8bdbdb19a6",
|
||||
"build/prefab/mac-server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/3f/ea/079aa2649359d2024b7c20dd19d0",
|
||||
"build/prefab/mac/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/05/5d/2608f732d75799cfe09c6947736a",
|
||||
"build/prefab/mac/release/ballisticacore": "https://files.ballistica.net/cache/ba1/ef/20/4f2abb279d24dced1f11f83fbe78",
|
||||
"build/prefab/windows-server/debug/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/f9/36/28081d9962d3f91c286663357e80",
|
||||
"build/prefab/windows-server/release/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/51/55/83ceb6ffb806c75815e5f9e88008",
|
||||
"build/prefab/windows/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/46/ea/461f76e113d3a02da3c61ea04bdb",
|
||||
"build/prefab/windows/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/83/af/a8ce32760e4dc300ac861f745615"
|
||||
"build/prefab/linux-server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/cd/cc/837483543f1d6b184f64b5e6a950",
|
||||
"build/prefab/linux-server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/38/e6/d372324c7c08b5b300490fa5594e",
|
||||
"build/prefab/linux/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/0e/11/3dda0974b64f51be4961628f572c",
|
||||
"build/prefab/linux/release/ballisticacore": "https://files.ballistica.net/cache/ba1/cc/76/3f6356dd599091f5955ce349593b",
|
||||
"build/prefab/mac-server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/e1/23/3fe78cdef456a99140837ede7e49",
|
||||
"build/prefab/mac-server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/1c/bd/4c73637ee172630ee00145032ce7",
|
||||
"build/prefab/mac/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/7a/a7/342bea2a6ec2f94d5de7bb52a59f",
|
||||
"build/prefab/mac/release/ballisticacore": "https://files.ballistica.net/cache/ba1/aa/24/5426cb7e6ca01b9e5d67ad3217b0",
|
||||
"build/prefab/windows-server/debug/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/cb/73/469fe3eb016f1e9c7f5c7811b182",
|
||||
"build/prefab/windows-server/release/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/7c/fb/7e0880c1ab90b0484cdedc41c8ae",
|
||||
"build/prefab/windows/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/f3/f2/097e861cf6ca981b18191e4c43b5",
|
||||
"build/prefab/windows/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/6b/7c/8407f4a7326b8b19f3e187d3ffcb"
|
||||
}
|
||||
13
.idea/dictionaries/ericf.xml
generated
13
.idea/dictionaries/ericf.xml
generated
@ -105,6 +105,7 @@
|
||||
<w>assetpath</w>
|
||||
<w>assettype</w>
|
||||
<w>assettypestr</w>
|
||||
<w>assigninput</w>
|
||||
<w>astc</w>
|
||||
<w>astcenc</w>
|
||||
<w>astroid</w>
|
||||
@ -765,6 +766,7 @@
|
||||
<w>getlog</w>
|
||||
<w>getmaps</w>
|
||||
<w>getmodel</w>
|
||||
<w>getname</w>
|
||||
<w>getnodes</w>
|
||||
<w>getnodetype</w>
|
||||
<w>getopt</w>
|
||||
@ -1382,6 +1384,7 @@
|
||||
<w>posixpath</w>
|
||||
<w>posixsubprocess</w>
|
||||
<w>postinit</w>
|
||||
<w>postinited</w>
|
||||
<w>poststr</w>
|
||||
<w>powerdown</w>
|
||||
<w>powersgiven</w>
|
||||
@ -1539,6 +1542,7 @@
|
||||
<w>reqtype</w>
|
||||
<w>reqtypes</w>
|
||||
<w>resample</w>
|
||||
<w>resetinput</w>
|
||||
<w>resourcetypeinfo</w>
|
||||
<w>respawn</w>
|
||||
<w>respawnable</w>
|
||||
@ -1557,6 +1561,7 @@
|
||||
<w>rfudge</w>
|
||||
<w>rgba</w>
|
||||
<w>rlcompleter</w>
|
||||
<w>rlock</w>
|
||||
<w>rmats</w>
|
||||
<w>rmine</w>
|
||||
<w>robotparser</w>
|
||||
@ -1580,6 +1585,7 @@
|
||||
<w>rval</w>
|
||||
<w>safecolor</w>
|
||||
<w>safesetattr</w>
|
||||
<w>safesetcolor</w>
|
||||
<w>saitek</w>
|
||||
<w>samsung</w>
|
||||
<w>sandboxing</w>
|
||||
@ -1641,12 +1647,18 @@
|
||||
<w>sessionglobalsnode</w>
|
||||
<w>sessionname</w>
|
||||
<w>sessionplayer</w>
|
||||
<w>sessionplayers</w>
|
||||
<w>sessionteam</w>
|
||||
<w>sessionteams</w>
|
||||
<w>sessiontype</w>
|
||||
<w>setactivity</w>
|
||||
<w>setalpha</w>
|
||||
<w>setbuild</w>
|
||||
<w>setdata</w>
|
||||
<w>setlanguage</w>
|
||||
<w>setmusic</w>
|
||||
<w>setname</w>
|
||||
<w>setnode</w>
|
||||
<w>setsticky</w>
|
||||
<w>settingname</w>
|
||||
<w>setversion</w>
|
||||
@ -2053,6 +2065,7 @@
|
||||
<w>webpages</w>
|
||||
<w>whatevs</w>
|
||||
<w>wheee</w>
|
||||
<w>whos</w>
|
||||
<w>widgetdeathtime</w>
|
||||
<w>wiimote</w>
|
||||
<w>wiimotes</w>
|
||||
|
||||
@ -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=33373537027192610824913965080968605548
|
||||
# SOURCES_HASH=172645630847706592745162067676099526148
|
||||
|
||||
# I'm sorry Pylint. I know this file saddens you. Be strong.
|
||||
# pylint: disable=useless-suppression
|
||||
@ -76,13 +76,6 @@ def _uninferrable() -> Any:
|
||||
class ActivityData:
|
||||
"""(internal)"""
|
||||
|
||||
def destroy(self) -> None:
|
||||
"""destroy() -> None
|
||||
|
||||
Destroys the internal data for the activity
|
||||
"""
|
||||
return None
|
||||
|
||||
def exists(self) -> bool:
|
||||
"""exists() -> bool
|
||||
|
||||
@ -91,6 +84,13 @@ class ActivityData:
|
||||
"""
|
||||
return bool()
|
||||
|
||||
def expire(self) -> None:
|
||||
"""expire() -> None
|
||||
|
||||
Expires the internal data for the activity
|
||||
"""
|
||||
return None
|
||||
|
||||
def make_foreground(self) -> None:
|
||||
"""make_foreground() -> None
|
||||
|
||||
@ -832,11 +832,6 @@ class SessionPlayer:
|
||||
storing data associated with this player.
|
||||
This persists for the duration of the session.
|
||||
|
||||
gamedata: Dict
|
||||
A dict for use by the current ba.Activity for
|
||||
storing data associated with this Player.
|
||||
This gets cleared for each new ba.Activity.
|
||||
|
||||
inputdevice: ba.InputDevice
|
||||
The input device associated with the player.
|
||||
|
||||
@ -860,16 +855,15 @@ class SessionPlayer:
|
||||
in_game: bool
|
||||
team: ba.SessionTeam
|
||||
sessiondata: Dict
|
||||
gamedata: Dict
|
||||
inputdevice: ba.InputDevice
|
||||
color: Sequence[float]
|
||||
highlight: Sequence[float]
|
||||
character: str
|
||||
gameplayer: Optional[ba.Player]
|
||||
|
||||
def assign_input_call(self, type: Union[str, Tuple[str, ...]],
|
||||
call: Callable) -> None:
|
||||
"""assign_input_call(type: Union[str, Tuple[str, ...]],
|
||||
def assigninput(self, type: Union[str, Tuple[str, ...]],
|
||||
call: Callable) -> None:
|
||||
"""assigninput(type: Union[str, Tuple[str, ...]],
|
||||
call: Callable) -> None
|
||||
|
||||
Set the python callable to be run for one or more types of input.
|
||||
@ -930,36 +924,13 @@ class SessionPlayer:
|
||||
"""
|
||||
return None
|
||||
|
||||
def reset(self) -> None:
|
||||
"""reset() -> None
|
||||
|
||||
(internal)
|
||||
"""
|
||||
return None
|
||||
|
||||
def reset_input(self) -> None:
|
||||
"""reset_input() -> None
|
||||
def resetinput(self) -> None:
|
||||
"""resetinput() -> None
|
||||
|
||||
Clears out the player's assigned input actions.
|
||||
"""
|
||||
return None
|
||||
|
||||
def set_activity(self, activity: Optional[ba.Activity]) -> None:
|
||||
"""set_activity(activity: Optional[ba.Activity]) -> None
|
||||
|
||||
(internal)
|
||||
"""
|
||||
return None
|
||||
|
||||
def set_data(self, team: ba.SessionTeam, character: str,
|
||||
color: Sequence[float], highlight: Sequence[float]) -> None:
|
||||
"""set_data(team: ba.SessionTeam, character: str,
|
||||
color: Sequence[float], highlight: Sequence[float]) -> None
|
||||
|
||||
(internal)
|
||||
"""
|
||||
return None
|
||||
|
||||
def set_icon_info(self, texture: str, tint_texture: str,
|
||||
tint_color: Sequence[float],
|
||||
tint2_color: Sequence[float]) -> None:
|
||||
@ -970,11 +941,27 @@ class SessionPlayer:
|
||||
"""
|
||||
return None
|
||||
|
||||
def set_name(self,
|
||||
name: str,
|
||||
full_name: str = None,
|
||||
real: bool = True) -> None:
|
||||
"""set_name(name: str, full_name: str = None, real: bool = True)
|
||||
def setactivity(self, activity: Optional[ba.Activity]) -> None:
|
||||
"""setactivity(activity: Optional[ba.Activity]) -> None
|
||||
|
||||
(internal)
|
||||
"""
|
||||
return None
|
||||
|
||||
def setdata(self, team: ba.SessionTeam, character: str,
|
||||
color: Sequence[float], highlight: Sequence[float]) -> None:
|
||||
"""setdata(team: ba.SessionTeam, character: str,
|
||||
color: Sequence[float], highlight: Sequence[float]) -> None
|
||||
|
||||
(internal)
|
||||
"""
|
||||
return None
|
||||
|
||||
def setname(self,
|
||||
name: str,
|
||||
full_name: str = None,
|
||||
real: bool = True) -> None:
|
||||
"""setname(name: str, full_name: str = None, real: bool = True)
|
||||
-> None
|
||||
|
||||
Set the player's name to the provided string.
|
||||
@ -983,8 +970,8 @@ class SessionPlayer:
|
||||
"""
|
||||
return None
|
||||
|
||||
def set_node(self, node: Optional[Node]) -> None:
|
||||
"""set_node(node: Optional[Node]) -> None
|
||||
def setnode(self, node: Optional[Node]) -> None:
|
||||
"""setnode(node: Optional[Node]) -> None
|
||||
|
||||
(internal)
|
||||
"""
|
||||
|
||||
@ -27,10 +27,10 @@ from typing import TYPE_CHECKING, Generic, TypeVar
|
||||
from ba._team import Team
|
||||
from ba._player import Player
|
||||
from ba._error import (print_exception, SessionTeamNotFoundError,
|
||||
NodeNotFoundError)
|
||||
SessionPlayerNotFoundError, NodeNotFoundError)
|
||||
from ba._dependency import DependencyComponent
|
||||
from ba._general import Call, verify_object_death
|
||||
from ba._messages import UNHANDLED, DieMessage, DeathType
|
||||
from ba._messages import UNHANDLED
|
||||
import _ba
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@ -143,7 +143,7 @@ class Activity(DependencyComponent, Generic[PlayerType, TeamType]):
|
||||
def __init__(self, settings: Dict[str, Any]):
|
||||
"""Creates an Activity in the current ba.Session.
|
||||
|
||||
The activity will not be actually run until ba.Session.set_activity()
|
||||
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.
|
||||
|
||||
@ -189,6 +189,10 @@ class Activity(DependencyComponent, Generic[PlayerType, TeamType]):
|
||||
self._has_ended = False
|
||||
self._activity_death_check_timer: Optional[ba.Timer] = None
|
||||
self._expired = False
|
||||
self._delay_delete_players: List[PlayerType] = []
|
||||
self._delay_delete_teams: List[TeamType] = []
|
||||
self._players_that_left: List[ReferenceType[PlayerType]] = []
|
||||
self._teams_that_left: List[ReferenceType[TeamType]] = []
|
||||
|
||||
# This gets set once another activity has begun transitioning in but
|
||||
# before this one is killed. The on_transition_out() method is also
|
||||
@ -208,8 +212,10 @@ class Activity(DependencyComponent, Generic[PlayerType, TeamType]):
|
||||
# This stuff gets filled in just before on_begin() is called.
|
||||
self.teams = []
|
||||
self.players = []
|
||||
|
||||
self.lobby = None
|
||||
self._stats: Optional[ba.Stats] = None
|
||||
self._gamedata: Optional[dict] = {}
|
||||
|
||||
def __del__(self) -> None:
|
||||
|
||||
@ -258,6 +264,17 @@ class Activity(DependencyComponent, Generic[PlayerType, TeamType]):
|
||||
can begin.
|
||||
"""
|
||||
|
||||
@property
|
||||
def gamedata(self) -> dict:
|
||||
"""Entities needing to store simple data with an activity can put it
|
||||
here. This dict will be deleted when the activity expires, so contained
|
||||
objects generally do not need to worry about handling expired
|
||||
activities.
|
||||
"""
|
||||
assert not self._expired
|
||||
assert isinstance(self._gamedata, dict)
|
||||
return self._gamedata
|
||||
|
||||
@property
|
||||
def expired(self) -> bool:
|
||||
"""Whether the activity is expired.
|
||||
@ -282,7 +299,7 @@ class Activity(DependencyComponent, Generic[PlayerType, TeamType]):
|
||||
"""(internal)"""
|
||||
self._has_ended = val
|
||||
|
||||
def destroy(self) -> None:
|
||||
def expire(self) -> None:
|
||||
"""Begin the process of tearing down the activity.
|
||||
|
||||
(internal)
|
||||
@ -424,7 +441,6 @@ class Activity(DependencyComponent, Generic[PlayerType, TeamType]):
|
||||
|
||||
(internal)
|
||||
"""
|
||||
from ba._general import WeakCall
|
||||
assert not self._has_transitioned_in
|
||||
self._has_transitioned_in = True
|
||||
|
||||
@ -457,10 +473,13 @@ class Activity(DependencyComponent, Generic[PlayerType, TeamType]):
|
||||
glb.vignette_outer = prev_globals.vignette_outer
|
||||
glb.vignette_inner = prev_globals.vignette_inner
|
||||
|
||||
# Start pruning our transient actors periodically.
|
||||
self._prune_dead_actors_timer = _ba.Timer(
|
||||
5.17, WeakCall(self._prune_dead_actors), repeat=True)
|
||||
# Start pruning our various things periodically.
|
||||
self._prune_dead_actors()
|
||||
self._prune_dead_actors_timer = _ba.Timer(5.17,
|
||||
self._prune_dead_actors,
|
||||
repeat=True)
|
||||
|
||||
_ba.timer(13.3, self._prune_delay_deletes, repeat=True)
|
||||
|
||||
# Also start our low-level scene running.
|
||||
self._activity_data.start()
|
||||
@ -556,12 +575,12 @@ class Activity(DependencyComponent, Generic[PlayerType, TeamType]):
|
||||
def add_player(self, sessionplayer: ba.SessionPlayer) -> None:
|
||||
"""(internal)"""
|
||||
assert sessionplayer.team is not None
|
||||
sessionplayer.reset_input()
|
||||
sessionplayer.resetinput()
|
||||
sessionteam = sessionplayer.team
|
||||
assert sessionplayer in sessionteam.players
|
||||
team = sessionteam.gameteam
|
||||
assert team is not None
|
||||
sessionplayer.set_activity(self)
|
||||
sessionplayer.setactivity(self)
|
||||
with _ba.Context(self):
|
||||
sessionplayer.gameplayer = player = self.create_player(
|
||||
sessionplayer)
|
||||
@ -581,10 +600,10 @@ class Activity(DependencyComponent, Generic[PlayerType, TeamType]):
|
||||
print_exception('Error in on_player_join for', self)
|
||||
|
||||
def remove_player(self, sessionplayer: ba.SessionPlayer) -> None:
|
||||
"""(internal)"""
|
||||
"""Remove a player from the Activity while it is running.
|
||||
|
||||
# This should only be called on unexpired activities
|
||||
# the player has been added to.
|
||||
(internal)
|
||||
"""
|
||||
assert not self.expired
|
||||
|
||||
player: Any = sessionplayer.gameplayer
|
||||
@ -605,30 +624,29 @@ class Activity(DependencyComponent, Generic[PlayerType, TeamType]):
|
||||
# verify_object_death(player)
|
||||
|
||||
with _ba.Context(self):
|
||||
# Make a decent attempt to persevere if user code breaks.
|
||||
try:
|
||||
self.on_player_leave(player)
|
||||
except Exception:
|
||||
print_exception(f'Error in on_player_leave for {self}')
|
||||
try:
|
||||
# If they have an actor, kill it.
|
||||
if player.actor:
|
||||
player.actor.handlemessage(
|
||||
DieMessage(how=DeathType.LEFT_GAME))
|
||||
player.actor = None
|
||||
player.leave()
|
||||
except Exception:
|
||||
print_exception(
|
||||
f'Error killing player actor on leave for {self}')
|
||||
try:
|
||||
player.reset()
|
||||
sessionplayer.reset()
|
||||
sessionplayer.set_node(None)
|
||||
sessionplayer.set_activity(None)
|
||||
except Exception:
|
||||
print_exception(f'Error resetting player for {self}')
|
||||
print_exception(f'Error on leave for {player} in {self}')
|
||||
|
||||
self._reset_session_player_for_no_activity(sessionplayer)
|
||||
|
||||
# Add the player to a list to keep it around for a while. This is
|
||||
# to discourage logic from firing on player object death, which
|
||||
# may not happen until activity end if something is holding refs
|
||||
# to it.
|
||||
self._delay_delete_players.append(player)
|
||||
self._players_that_left.append(weakref.ref(player))
|
||||
|
||||
def add_team(self, sessionteam: ba.SessionTeam) -> None:
|
||||
"""(internal)"""
|
||||
"""Add a team to the Activity
|
||||
|
||||
(internal)
|
||||
"""
|
||||
assert not self.expired
|
||||
|
||||
with _ba.Context(self):
|
||||
@ -641,25 +659,20 @@ class Activity(DependencyComponent, Generic[PlayerType, TeamType]):
|
||||
print_exception(f'Error in on_team_join for {self}')
|
||||
|
||||
def remove_team(self, sessionteam: ba.SessionTeam) -> None:
|
||||
"""(internal)"""
|
||||
"""Remove a team from a Running Activity
|
||||
|
||||
# This should only be called on unexpired activities the team has
|
||||
# been added to.
|
||||
(internal)
|
||||
"""
|
||||
assert not self.expired
|
||||
assert sessionteam.gameteam is not None
|
||||
assert sessionteam.gameteam in self.teams
|
||||
|
||||
team = sessionteam.gameteam
|
||||
team: Any = sessionteam.gameteam
|
||||
assert isinstance(team, self._teamtype)
|
||||
|
||||
assert team in self.teams
|
||||
self.teams.remove(team)
|
||||
assert team not in self.teams
|
||||
|
||||
# This should allow our ba.Team instance to die. Complain
|
||||
# if that doesn't happen.
|
||||
# verify_object_death(team)
|
||||
|
||||
with _ba.Context(self):
|
||||
# Make a decent attempt to persevere if user code breaks.
|
||||
try:
|
||||
@ -667,12 +680,42 @@ class Activity(DependencyComponent, Generic[PlayerType, TeamType]):
|
||||
except Exception:
|
||||
print_exception(f'Error in on_team_leave for {self}')
|
||||
try:
|
||||
sessionteam.reset_gamedata()
|
||||
team.leave()
|
||||
except Exception:
|
||||
print_exception(f'Error in reset_gamedata for {self}')
|
||||
print_exception(f'Error on leave for {team} in {self}')
|
||||
|
||||
sessionteam.gameteam = None
|
||||
|
||||
# Add the team to a list to keep it around for a while. This is
|
||||
# to discourage logic from firing on team object death, which
|
||||
# may not happen until activity end if something is holding refs
|
||||
# to it.
|
||||
self._delay_delete_teams.append(team)
|
||||
self._teams_that_left.append(weakref.ref(team))
|
||||
|
||||
def _reset_session_player_for_no_activity(
|
||||
self, sessionplayer: ba.SessionPlayer) -> None:
|
||||
|
||||
# Let's be extra-defensive here: killing a node/input-call/etc
|
||||
# could trigger user-code resulting in errors, but we would still
|
||||
# like to complete the reset if possible.
|
||||
try:
|
||||
sessionplayer.setnode(None)
|
||||
except Exception:
|
||||
print_exception(
|
||||
f'Error resetting SessionPlayer node on {sessionplayer}'
|
||||
f' for {self}')
|
||||
try:
|
||||
sessionplayer.resetinput()
|
||||
except Exception:
|
||||
print_exception(
|
||||
f'Error resetting SessionPlayer input on {sessionplayer}'
|
||||
f' for {self}')
|
||||
|
||||
# These should never fail I think...
|
||||
sessionplayer.setactivity(None)
|
||||
sessionplayer.gameplayer = None
|
||||
|
||||
def _setup_player_and_team_types(self) -> None:
|
||||
"""Pull player and team types from our typing.Generic params."""
|
||||
|
||||
@ -682,7 +725,7 @@ class Activity(DependencyComponent, Generic[PlayerType, TeamType]):
|
||||
# to no generic params being passed) we automatically use the
|
||||
# base class types, but also warn the user since this will mean
|
||||
# less type safety for that class. (its better to pass the base
|
||||
# types explicitly vs. having them be Any)
|
||||
# player/team types explicitly vs. having them be Any)
|
||||
if not TYPE_CHECKING:
|
||||
self._playertype = type(self).__orig_bases__[-1].__args__[0]
|
||||
if not isinstance(self._playertype, type):
|
||||
@ -749,9 +792,31 @@ class Activity(DependencyComponent, Generic[PlayerType, TeamType]):
|
||||
try:
|
||||
self.on_expire()
|
||||
except Exception:
|
||||
print_exception(f'Error in Activity on_expire() for {self}')
|
||||
print_exception(f'Error in Activity on_expire() for {self}.')
|
||||
|
||||
# Send expire notices to all remaining actors.
|
||||
try:
|
||||
self._gamedata = None
|
||||
except Exception:
|
||||
print_exception(f'Error clearing gamedata for {self}.')
|
||||
|
||||
# Don't want to be holding any delay-delete refs at this point.
|
||||
self._prune_delay_deletes()
|
||||
|
||||
self._expire_actors()
|
||||
self._expire_players()
|
||||
self._expire_teams()
|
||||
|
||||
# This will kill all low level stuff: Timers, Nodes, etc., which
|
||||
# should clear up any remaining refs to our Activity and allow us
|
||||
# to die peacefully.
|
||||
try:
|
||||
self._activity_data.expire()
|
||||
except Exception:
|
||||
print_exception(
|
||||
'Error during ba.Activity._expire() destroying data:')
|
||||
|
||||
def _expire_actors(self) -> None:
|
||||
# Expire all Actors.
|
||||
for actor_ref in self._actor_weak_refs:
|
||||
actor = actor_ref()
|
||||
if actor is not None:
|
||||
@ -760,35 +825,58 @@ class Activity(DependencyComponent, Generic[PlayerType, TeamType]):
|
||||
actor.on_expire()
|
||||
except Exception:
|
||||
print_exception(f'Error in Actor.on_expire()'
|
||||
f' for {actor_ref()}')
|
||||
f' for {actor_ref()}.')
|
||||
|
||||
def _expire_players(self) -> None:
|
||||
|
||||
# Issue warnings for any players that left the game but don't
|
||||
# get freed soon.
|
||||
for ex_player in (p() for p in self._players_that_left):
|
||||
if ex_player is not None:
|
||||
verify_object_death(ex_player)
|
||||
|
||||
# Reset all Players.
|
||||
# (releases any attached actors, clears game-data, etc)
|
||||
for player in self.players:
|
||||
# This should allow our ba.Player instance to be freed.
|
||||
# Complain if that doesn't happen.
|
||||
verify_object_death(player)
|
||||
|
||||
try:
|
||||
# This should allow our ba.Player instance to die.
|
||||
# Complain if that doesn't happen.
|
||||
# verify_object_death(player)
|
||||
sessionplayer = player.sessionplayer
|
||||
player.reset()
|
||||
sessionplayer.set_node(None)
|
||||
sessionplayer.set_activity(None)
|
||||
|
||||
sessionplayer.gameplayer = None
|
||||
sessionplayer.reset()
|
||||
player.expire()
|
||||
except Exception:
|
||||
print_exception(f'Error resetting Player {player}')
|
||||
print_exception(f'Error expiring {player}')
|
||||
|
||||
# Reset the SessionPlayer to a not-in-an-activity state.
|
||||
try:
|
||||
sessionplayer = player.sessionplayer
|
||||
self._reset_session_player_for_no_activity(sessionplayer)
|
||||
except SessionPlayerNotFoundError:
|
||||
# Conceivably, someone could have held on to a Player object
|
||||
# until now whos underlying SessionPlayer left long ago...
|
||||
pass
|
||||
except Exception:
|
||||
print_exception(f'Error expiring {player}')
|
||||
|
||||
def _expire_teams(self) -> None:
|
||||
|
||||
# Issue warnings for any teams that left the game but don't
|
||||
# get freed soon.
|
||||
for ex_team in (p() for p in self._teams_that_left):
|
||||
if ex_team is not None:
|
||||
verify_object_death(ex_team)
|
||||
|
||||
# Ditto with Teams.
|
||||
for team in self.teams:
|
||||
# This should allow our ba.Team instance to die.
|
||||
# Complain if that doesn't happen.
|
||||
verify_object_death(team)
|
||||
|
||||
try:
|
||||
team.expire()
|
||||
except Exception:
|
||||
print_exception(f'Error expiring {team}')
|
||||
|
||||
try:
|
||||
sessionteam = team.sessionteam
|
||||
|
||||
# This should allow our ba.Team instance to die.
|
||||
# Complain if that doesn't happen.
|
||||
# verify_object_death(sessionteam.gameteam)
|
||||
sessionteam.gameteam = None
|
||||
sessionteam.reset_gamedata()
|
||||
except SessionTeamNotFoundError:
|
||||
# It is expected that Team objects may last longer than
|
||||
# the SessionTeam they came from (game objects may hold
|
||||
@ -796,17 +884,19 @@ class Activity(DependencyComponent, Generic[PlayerType, TeamType]):
|
||||
# player/team has left the game)
|
||||
pass
|
||||
except Exception:
|
||||
print_exception(f'Error resetting Team {team}')
|
||||
print_exception(f'Error expiring Team {team}')
|
||||
|
||||
# Regardless of what happened here, we want to destroy our data, as
|
||||
# our activity might not go down if we don't. This will kill all
|
||||
# Timers, Nodes, etc, which should clear up any remaining refs to our
|
||||
# Actors and Activity and allow us to die peacefully.
|
||||
try:
|
||||
self._activity_data.destroy()
|
||||
except Exception:
|
||||
print_exception(
|
||||
'Error during ba.Activity._expire() destroying data:')
|
||||
def _prune_delay_deletes(self) -> None:
|
||||
self._delay_delete_players.clear()
|
||||
self._delay_delete_teams.clear()
|
||||
|
||||
# Clear out any dead weak-refs.
|
||||
self._teams_that_left = [
|
||||
t for t in self._teams_that_left if t() is not None
|
||||
]
|
||||
self._players_that_left = [
|
||||
p for p in self._players_that_left if p() is not None
|
||||
]
|
||||
|
||||
def _prune_dead_actors(self) -> None:
|
||||
self._last_prune_dead_actors_time = _ba.time()
|
||||
|
||||
@ -229,6 +229,6 @@ class ScoreScreenActivity(Activity[Player, Team]):
|
||||
# Just to be extra careful, don't assign if we're transitioning out.
|
||||
# (though theoretically that would be ok).
|
||||
if not self.is_transitioning_out() and player:
|
||||
player.assign_input_call(
|
||||
player.assigninput(
|
||||
('jumpPress', 'punchPress', 'bombPress', 'pickUpPress'),
|
||||
self._player_press)
|
||||
|
||||
@ -53,7 +53,7 @@ def run_cpu_benchmark() -> None:
|
||||
cfg['Graphics Quality'] = 'Low'
|
||||
cfg.apply()
|
||||
self.benchmark_type = 'cpu'
|
||||
self.set_activity(_ba.new_activity(tutorial.TutorialActivity))
|
||||
self.setactivity(_ba.new_activity(tutorial.TutorialActivity))
|
||||
|
||||
def __del__(self) -> None:
|
||||
|
||||
@ -91,7 +91,7 @@ def run_stress_test(playlist_type: str = 'Random',
|
||||
Call(_ba.screenmessage,
|
||||
('stats will be written to ' +
|
||||
_modutils.get_human_readable_user_scripts_path() +
|
||||
'/stressTestStats.csv')),
|
||||
'/stress_test_stats.csv')),
|
||||
timetype=TimeType.REAL)
|
||||
|
||||
|
||||
|
||||
@ -98,7 +98,7 @@ class CoopSession(Session):
|
||||
self._custom_menu_ui: List[Dict[str, Any]] = []
|
||||
|
||||
# Start our joining screen.
|
||||
self.set_activity(_ba.new_activity(CoopJoinActivity))
|
||||
self.setactivity(_ba.new_activity(CoopJoinActivity))
|
||||
|
||||
self._next_game_instance: Optional[ba.GameActivity] = None
|
||||
self._next_game_level_name: Optional[str] = None
|
||||
@ -298,7 +298,7 @@ class CoopSession(Session):
|
||||
and not app.kiosk_mode):
|
||||
if self._tutorial_activity is None:
|
||||
raise RuntimeError('Tutorial not preloaded properly.')
|
||||
self.set_activity(self._tutorial_activity)
|
||||
self.setactivity(self._tutorial_activity)
|
||||
self._tutorial_activity = None
|
||||
self._ran_tutorial_activity = True
|
||||
self._custom_menu_ui = []
|
||||
@ -313,10 +313,10 @@ class CoopSession(Session):
|
||||
# Skip players that are still choosing a team.
|
||||
if player.in_game:
|
||||
self.stats.register_player(player)
|
||||
self.stats.set_activity(next_game)
|
||||
self.stats.setactivity(next_game)
|
||||
|
||||
# Now flip the current activity.
|
||||
self.set_activity(next_game)
|
||||
self.setactivity(next_game)
|
||||
|
||||
if not app.kiosk_mode:
|
||||
if self.tournament_id is not None:
|
||||
@ -338,7 +338,7 @@ class CoopSession(Session):
|
||||
# If we were in a tutorial, just pop a transition to get to the
|
||||
# actual round.
|
||||
elif isinstance(activity, TutorialActivity):
|
||||
self.set_activity(_ba.new_activity(TransitionActivity))
|
||||
self.setactivity(_ba.new_activity(TransitionActivity))
|
||||
else:
|
||||
|
||||
player_info: List[ba.PlayerInfo]
|
||||
@ -392,9 +392,9 @@ class CoopSession(Session):
|
||||
if outcome == 'restart':
|
||||
|
||||
# This will pop up back in the same round.
|
||||
self.set_activity(_ba.new_activity(TransitionActivity))
|
||||
self.setactivity(_ba.new_activity(TransitionActivity))
|
||||
else:
|
||||
self.set_activity(
|
||||
self.setactivity(
|
||||
_ba.new_activity(
|
||||
CoopScoreScreen, {
|
||||
'player_info': player_info,
|
||||
|
||||
@ -56,7 +56,7 @@ class DualTeamSession(MultiTeamSession):
|
||||
|
||||
# If everyone has the same score, call it a draw.
|
||||
if len(winners) < 2:
|
||||
self.set_activity(_ba.new_activity(DrawScoreScreenActivity))
|
||||
self.setactivity(_ba.new_activity(DrawScoreScreenActivity))
|
||||
else:
|
||||
winner = winners[0].teams[0]
|
||||
winner.sessiondata['score'] += 1
|
||||
@ -64,10 +64,10 @@ class DualTeamSession(MultiTeamSession):
|
||||
# If a team has won, show final victory screen.
|
||||
if winner.sessiondata['score'] >= (self._series_length -
|
||||
1) / 2 + 1:
|
||||
self.set_activity(
|
||||
self.setactivity(
|
||||
_ba.new_activity(TeamSeriesVictoryScoreScreenActivity,
|
||||
{'winner': winner}))
|
||||
else:
|
||||
self.set_activity(
|
||||
self.setactivity(
|
||||
_ba.new_activity(TeamVictoryScoreScreenActivity,
|
||||
{'winner': winner}))
|
||||
|
||||
@ -81,7 +81,7 @@ class FreeForAllSession(MultiTeamSession):
|
||||
# If there's multiple players and everyone has the same score,
|
||||
# call it a draw.
|
||||
if len(self.players) > 1 and len(winners) < 2:
|
||||
self.set_activity(
|
||||
self.setactivity(
|
||||
_ba.new_activity(DrawScoreScreenActivity,
|
||||
{'results': results}))
|
||||
else:
|
||||
@ -105,10 +105,10 @@ class FreeForAllSession(MultiTeamSession):
|
||||
or (len(series_winners) > 1
|
||||
and series_winners[0].sessiondata['score'] !=
|
||||
series_winners[1].sessiondata['score'])):
|
||||
self.set_activity(
|
||||
self.setactivity(
|
||||
_ba.new_activity(TeamSeriesVictoryScoreScreenActivity,
|
||||
{'winner': series_winners[0]}))
|
||||
else:
|
||||
self.set_activity(
|
||||
self.setactivity(
|
||||
_ba.new_activity(FreeForAllVictoryScoreScreenActivity,
|
||||
{'results': results}))
|
||||
|
||||
@ -55,7 +55,7 @@ class JoinInfo:
|
||||
self._press_to_bomb: Union[str, ba.Lstr] = _ba.charstr(
|
||||
SpecialChar.RIGHT_BUTTON)
|
||||
self._joinmsg = Lstr(resource='pressAnyButtonToJoinText')
|
||||
can_switch_teams = (len(lobby.teams) > 1)
|
||||
can_switch_teams = (len(lobby.sessionteams) > 1)
|
||||
|
||||
# If we have a keyboard, grab keys for punch and pickup.
|
||||
# FIXME: This of course is only correct on the local device;
|
||||
@ -151,7 +151,7 @@ class Chooser:
|
||||
if self._text_node:
|
||||
self._text_node.delete()
|
||||
|
||||
def __init__(self, vpos: float, player: _ba.SessionPlayer,
|
||||
def __init__(self, vpos: float, sessionplayer: _ba.SessionPlayer,
|
||||
lobby: 'Lobby') -> None:
|
||||
self._deek_sound = _ba.getsound('deek')
|
||||
self._click_sound = _ba.getsound('click01')
|
||||
@ -161,7 +161,7 @@ class Chooser:
|
||||
self._mask_texture = _ba.gettexture('characterIconMask')
|
||||
self._vpos = vpos
|
||||
self._lobby = weakref.ref(lobby)
|
||||
self._player = player
|
||||
self._sessionplayer = sessionplayer
|
||||
self._inited = False
|
||||
self._dead = False
|
||||
self._text_node: Optional[ba.Node] = None
|
||||
@ -174,13 +174,8 @@ class Chooser:
|
||||
|
||||
app = _ba.app
|
||||
|
||||
# try:
|
||||
# print(player.inputdevice)
|
||||
# except Exception as exc:
|
||||
# print('GOT EXC', type(exc))
|
||||
|
||||
# Load available profiles either from the local config or from the
|
||||
# remote device.
|
||||
# Load available player profiles either from the local config or
|
||||
# from the remote device.
|
||||
self.reload_profiles()
|
||||
|
||||
# Note: this is just our local index out of available teams; *not*
|
||||
@ -199,7 +194,7 @@ class Chooser:
|
||||
# list.
|
||||
char_index_offset = app.lobby_random_char_index_offset
|
||||
self._random_character_index = (
|
||||
(player.inputdevice.id + char_index_offset) %
|
||||
(sessionplayer.inputdevice.id + char_index_offset) %
|
||||
len(self._character_names))
|
||||
|
||||
# Attempt to set an initial profile based on what was used previously
|
||||
@ -231,8 +226,8 @@ class Chooser:
|
||||
animate_array(self.icon, 'scale', 2, {0: (0, 0), 0.1: (45, 45)})
|
||||
|
||||
# Set our initial name to '<choosing player>' in case anyone asks.
|
||||
self._player.set_name(Lstr(resource='choosingPlayerText').evaluate(),
|
||||
real=False)
|
||||
self._sessionplayer.setname(
|
||||
Lstr(resource='choosingPlayerText').evaluate(), real=False)
|
||||
|
||||
# Init these to our rando but they should get switched to the
|
||||
# selected profile (if any) right after.
|
||||
@ -249,7 +244,7 @@ class Chooser:
|
||||
def _select_initial_profile(self) -> int:
|
||||
app = _ba.app
|
||||
profilenames = self._profilenames
|
||||
inputdevice = self._player.inputdevice
|
||||
inputdevice = self._sessionplayer.inputdevice
|
||||
|
||||
# If we've got a set profile name for this device, work backwards
|
||||
# from that to get our index.
|
||||
@ -307,9 +302,9 @@ class Chooser:
|
||||
return profilenames.index('_random')
|
||||
|
||||
@property
|
||||
def player(self) -> ba.SessionPlayer:
|
||||
"""The ba.Player associated with this chooser."""
|
||||
return self._player
|
||||
def sessionplayer(self) -> ba.SessionPlayer:
|
||||
"""The ba.SessionPlayer associated with this chooser."""
|
||||
return self._sessionplayer
|
||||
|
||||
@property
|
||||
def ready(self) -> bool:
|
||||
@ -324,9 +319,10 @@ class Chooser:
|
||||
"""(internal)"""
|
||||
self._dead = val
|
||||
|
||||
def get_team(self) -> ba.SessionTeam:
|
||||
"""Return this chooser's selected ba.Team."""
|
||||
return self.lobby.teams[self._selected_team_index]
|
||||
@property
|
||||
def sessionteam(self) -> ba.SessionTeam:
|
||||
"""Return this chooser's currently selected ba.SessionTeam."""
|
||||
return self.lobby.sessionteams[self._selected_team_index]
|
||||
|
||||
@property
|
||||
def lobby(self) -> ba.Lobby:
|
||||
@ -376,7 +372,7 @@ class Chooser:
|
||||
|
||||
# Re-construct our profile index and other stuff since the profile
|
||||
# list might have changed.
|
||||
input_device = self._player.inputdevice
|
||||
input_device = self._sessionplayer.inputdevice
|
||||
is_remote = input_device.is_remote_client
|
||||
is_test_input = input_device.name.startswith('TestInput')
|
||||
|
||||
@ -434,10 +430,10 @@ class Chooser:
|
||||
|
||||
assert self._text_node
|
||||
spacing = 350
|
||||
teams = self.lobby.teams
|
||||
offs = (spacing * -0.5 * len(teams) +
|
||||
sessionteams = self.lobby.sessionteams
|
||||
offs = (spacing * -0.5 * len(sessionteams) +
|
||||
spacing * self._selected_team_index + 250)
|
||||
if len(teams) > 1:
|
||||
if len(sessionteams) > 1:
|
||||
offs -= 35
|
||||
animate_array(self._text_node, 'position', 2, {
|
||||
0: self._text_node.position,
|
||||
@ -460,14 +456,15 @@ class Chooser:
|
||||
clamp = False
|
||||
if name == '_random':
|
||||
try:
|
||||
name = (self._player.inputdevice.get_default_player_name())
|
||||
name = (
|
||||
self._sessionplayer.inputdevice.get_default_player_name())
|
||||
except Exception:
|
||||
print_exception('Error getting _random chooser name.')
|
||||
name = 'Invalid'
|
||||
clamp = not full
|
||||
elif name == '__account__':
|
||||
try:
|
||||
name = self._player.inputdevice.get_account_name(full)
|
||||
name = self._sessionplayer.inputdevice.get_account_name(full)
|
||||
except Exception:
|
||||
print_exception('Error getting account name for chooser.')
|
||||
name = 'Invalid'
|
||||
@ -513,41 +510,41 @@ class Chooser:
|
||||
|
||||
# Give their input-device UI ownership too
|
||||
# (prevent someone else from snatching it in crowded games)
|
||||
_ba.set_ui_input_device(self._player.inputdevice)
|
||||
_ba.set_ui_input_device(self._sessionplayer.inputdevice)
|
||||
return
|
||||
|
||||
if not ready:
|
||||
self._player.assign_input_call(
|
||||
self._sessionplayer.assigninput(
|
||||
'leftPress', Call(self.handlemessage,
|
||||
ChangeMessage('team', -1)))
|
||||
self._player.assign_input_call(
|
||||
self._sessionplayer.assigninput(
|
||||
'rightPress', Call(self.handlemessage,
|
||||
ChangeMessage('team', 1)))
|
||||
self._player.assign_input_call(
|
||||
self._sessionplayer.assigninput(
|
||||
'bombPress',
|
||||
Call(self.handlemessage, ChangeMessage('character', 1)))
|
||||
self._player.assign_input_call(
|
||||
self._sessionplayer.assigninput(
|
||||
'upPress',
|
||||
Call(self.handlemessage, ChangeMessage('profileindex', -1)))
|
||||
self._player.assign_input_call(
|
||||
self._sessionplayer.assigninput(
|
||||
'downPress',
|
||||
Call(self.handlemessage, ChangeMessage('profileindex', 1)))
|
||||
self._player.assign_input_call(
|
||||
self._sessionplayer.assigninput(
|
||||
('jumpPress', 'pickUpPress', 'punchPress'),
|
||||
Call(self.handlemessage, ChangeMessage('ready', 1)))
|
||||
self._ready = False
|
||||
self._update_text()
|
||||
self._player.set_name('untitled', real=False)
|
||||
self._sessionplayer.setname('untitled', real=False)
|
||||
else:
|
||||
self._player.assign_input_call(
|
||||
self._sessionplayer.assigninput(
|
||||
('leftPress', 'rightPress', 'upPress', 'downPress',
|
||||
'jumpPress', 'bombPress', 'pickUpPress'), self._do_nothing)
|
||||
self._player.assign_input_call(
|
||||
self._sessionplayer.assigninput(
|
||||
('jumpPress', 'bombPress', 'pickUpPress', 'punchPress'),
|
||||
Call(self.handlemessage, ChangeMessage('ready', 0)))
|
||||
|
||||
# Store the last profile picked by this input for reuse.
|
||||
input_device = self._player.inputdevice
|
||||
input_device = self._sessionplayer.inputdevice
|
||||
name = input_device.name
|
||||
unique_id = input_device.unique_identifier
|
||||
device_profiles = _ba.app.config.setdefault(
|
||||
@ -569,9 +566,9 @@ class Chooser:
|
||||
_ba.app.config.commit()
|
||||
|
||||
# Set this player's short and full name.
|
||||
self._player.set_name(self._getname(),
|
||||
self._getname(full=True),
|
||||
real=True)
|
||||
self._sessionplayer.setname(self._getname(),
|
||||
self._getname(full=True),
|
||||
real=True)
|
||||
self._ready = True
|
||||
self._update_text()
|
||||
|
||||
@ -586,25 +583,26 @@ class Chooser:
|
||||
if not self._ready:
|
||||
if _ba.app.config.get('Auto Balance Teams', False):
|
||||
lobby = self.lobby
|
||||
teams = lobby.teams
|
||||
if len(teams) > 1:
|
||||
sessionteams = lobby.sessionteams
|
||||
if len(sessionteams) > 1:
|
||||
|
||||
# First, calc how many players are on each team
|
||||
# ..we need to count both active players and
|
||||
# choosers that have been marked as ready.
|
||||
team_player_counts = {}
|
||||
for team in teams:
|
||||
team_player_counts[team.id] = len(team.players)
|
||||
for sessionteam in sessionteams:
|
||||
team_player_counts[sessionteam.id] = len(
|
||||
sessionteam.players)
|
||||
for chooser in lobby.choosers:
|
||||
if chooser.ready:
|
||||
team_player_counts[chooser.get_team().id] += 1
|
||||
team_player_counts[chooser.sessionteam.id] += 1
|
||||
largest_team_size = max(team_player_counts.values())
|
||||
smallest_team_size = (min(team_player_counts.values()))
|
||||
|
||||
# Force switch if we're on the biggest team
|
||||
# Force switch if we're on the biggest sessionteam
|
||||
# and there's a smaller one available.
|
||||
if (largest_team_size != smallest_team_size
|
||||
and team_player_counts[self.get_team().id] >=
|
||||
and team_player_counts[self.sessionteam.id] >=
|
||||
largest_team_size):
|
||||
force_team_switch = True
|
||||
|
||||
@ -623,7 +621,8 @@ class Chooser:
|
||||
if now - self._last_change[0] < QUICK_CHANGE_INTERVAL:
|
||||
count += 1
|
||||
if count > MAX_QUICK_CHANGE_COUNT:
|
||||
_ba.disconnect_client(self._player.inputdevice.client_id)
|
||||
_ba.disconnect_client(
|
||||
self._sessionplayer.inputdevice.client_id)
|
||||
elif now - self._last_change[0] > QUICK_CHANGE_RESET_INTERVAL:
|
||||
count = 0
|
||||
self._last_change = (now, count)
|
||||
@ -644,11 +643,12 @@ class Chooser:
|
||||
return
|
||||
|
||||
if msg.what == 'team':
|
||||
teams = self.lobby.teams
|
||||
if len(teams) > 1:
|
||||
sessionteams = self.lobby.sessionteams
|
||||
if len(sessionteams) > 1:
|
||||
_ba.playsound(self._swish_sound)
|
||||
self._selected_team_index = (
|
||||
(self._selected_team_index + msg.value) % len(teams))
|
||||
(self._selected_team_index + msg.value) %
|
||||
len(sessionteams))
|
||||
self._update_text()
|
||||
self.update_position()
|
||||
self._update_icon()
|
||||
@ -685,14 +685,14 @@ class Chooser:
|
||||
|
||||
# Once we're ready, we've saved the name, so lets ask the system
|
||||
# for it so we get appended numbers and stuff.
|
||||
text = Lstr(value=self._player.getname(full=True))
|
||||
text = Lstr(value=self._sessionplayer.getname(full=True))
|
||||
text = Lstr(value='${A} (${B})',
|
||||
subs=[('${A}', text),
|
||||
('${B}', Lstr(resource='readyText'))])
|
||||
else:
|
||||
text = Lstr(value=self._getname(full=True))
|
||||
|
||||
can_switch_teams = len(self.lobby.teams) > 1
|
||||
can_switch_teams = len(self.lobby.sessionteams) > 1
|
||||
|
||||
# Flash as we're coming in.
|
||||
fin_color = _ba.safecolor(self.get_color()) + (1, )
|
||||
@ -719,7 +719,7 @@ class Chooser:
|
||||
"""Return the currently selected color."""
|
||||
val: Sequence[float]
|
||||
if self.lobby.use_team_colors:
|
||||
val = self.lobby.teams[self._selected_team_index].color
|
||||
val = self.lobby.sessionteams[self._selected_team_index].color
|
||||
else:
|
||||
val = self._color
|
||||
if len(val) != 3:
|
||||
@ -736,17 +736,17 @@ class Chooser:
|
||||
# isn't too close to any other team's color.
|
||||
highlight = list(self._highlight)
|
||||
if self.lobby.use_team_colors:
|
||||
for i, team in enumerate(self.lobby.teams):
|
||||
for i, sessionteam in enumerate(self.lobby.sessionteams):
|
||||
if i != self._selected_team_index:
|
||||
|
||||
# Find the dominant component of this team's color
|
||||
# Find the dominant component of this sessionteam's color
|
||||
# and adjust ours so that the component is
|
||||
# not super-dominant.
|
||||
max_val = 0.0
|
||||
max_index = 0
|
||||
for j in range(3):
|
||||
if team.color[j] > max_val:
|
||||
max_val = team.color[j]
|
||||
if sessionteam.color[j] > max_val:
|
||||
max_val = sessionteam.color[j]
|
||||
max_index = j
|
||||
that_color_for_us = highlight[max_index]
|
||||
our_second_biggest = max(highlight[(max_index + 1) % 3],
|
||||
@ -760,7 +760,7 @@ class Chooser:
|
||||
|
||||
def getplayer(self) -> ba.SessionPlayer:
|
||||
"""Return the player associated with this chooser."""
|
||||
return self._player
|
||||
return self._sessionplayer
|
||||
|
||||
def _update_icon(self) -> None:
|
||||
if self._profilenames[self._profileindex] == '_edit':
|
||||
@ -791,7 +791,7 @@ class Chooser:
|
||||
clr = self.get_color()
|
||||
clr2 = self.get_highlight()
|
||||
|
||||
can_switch_teams = len(self.lobby.teams) > 1
|
||||
can_switch_teams = len(self.lobby.sessionteams) > 1
|
||||
|
||||
# If we're initing, flash.
|
||||
if not self._inited:
|
||||
@ -812,7 +812,7 @@ class Chooser:
|
||||
self.icon.tint2_color = clr2
|
||||
|
||||
# Store the icon info the the player.
|
||||
self._player.set_icon_info(tex_name, tint_tex_name, clr, clr2)
|
||||
self._sessionplayer.set_icon_info(tex_name, tint_tex_name, clr, clr2)
|
||||
|
||||
|
||||
class Lobby:
|
||||
@ -823,13 +823,13 @@ class Lobby:
|
||||
|
||||
def __del__(self) -> None:
|
||||
|
||||
# Reset any players that still have a chooser in us
|
||||
# Reset any players that still have a chooser in us.
|
||||
# (should allow the choosers to die).
|
||||
players = [
|
||||
chooser.player for chooser in self.choosers if chooser.player
|
||||
sessionplayers = [
|
||||
c.sessionplayer for c in self.choosers if c.sessionplayer
|
||||
]
|
||||
for player in players:
|
||||
player.reset()
|
||||
for sessionplayer in sessionplayers:
|
||||
sessionplayer.resetinput()
|
||||
|
||||
def __init__(self) -> None:
|
||||
from ba._team import SessionTeam
|
||||
@ -837,10 +837,10 @@ class Lobby:
|
||||
session = _ba.getsession()
|
||||
self._use_team_colors = session.use_team_colors
|
||||
if session.use_teams:
|
||||
self._teams = [weakref.ref(team) for team in session.teams]
|
||||
self._sessionteams = [weakref.ref(team) for team in session.teams]
|
||||
else:
|
||||
self._dummy_teams = SessionTeam()
|
||||
self._teams = [weakref.ref(self._dummy_teams)]
|
||||
self._sessionteams = [weakref.ref(self._dummy_teams)]
|
||||
v_offset = (-150 if isinstance(session, CoopSession) else -50)
|
||||
self.choosers: List[Chooser] = []
|
||||
self.base_v_offset = v_offset
|
||||
@ -868,10 +868,10 @@ class Lobby:
|
||||
return self._use_team_colors
|
||||
|
||||
@property
|
||||
def teams(self) -> List[ba.SessionTeam]:
|
||||
"""Teams available in this lobby."""
|
||||
def sessionteams(self) -> List[ba.SessionTeam]:
|
||||
"""ba.SessionTeams available in this lobby."""
|
||||
allteams = []
|
||||
for tref in self._teams:
|
||||
for tref in self._sessionteams:
|
||||
team = tref()
|
||||
assert team is not None
|
||||
allteams.append(team)
|
||||
@ -921,11 +921,12 @@ class Lobby:
|
||||
"""Return whether all choosers are marked ready."""
|
||||
return all(chooser.ready for chooser in self.choosers)
|
||||
|
||||
def add_chooser(self, player: ba.SessionPlayer) -> None:
|
||||
def add_chooser(self, sessionplayer: ba.SessionPlayer) -> None:
|
||||
"""Add a chooser to the lobby for the provided player."""
|
||||
self.choosers.append(
|
||||
Chooser(vpos=self._vpos, player=player, lobby=self))
|
||||
self._next_add_team = (self._next_add_team + 1) % len(self._teams)
|
||||
Chooser(vpos=self._vpos, sessionplayer=sessionplayer, lobby=self))
|
||||
self._next_add_team = (self._next_add_team + 1) % len(
|
||||
self._sessionteams)
|
||||
self._vpos -= 48
|
||||
|
||||
def remove_chooser(self, player: ba.SessionPlayer) -> None:
|
||||
@ -964,6 +965,6 @@ class Lobby:
|
||||
|
||||
# Copy the list; it can change under us otherwise.
|
||||
for chooser in list(self.choosers):
|
||||
if chooser.player:
|
||||
chooser.player.remove_from_game()
|
||||
if chooser.sessionplayer:
|
||||
chooser.sessionplayer.remove_from_game()
|
||||
self.remove_all_choosers()
|
||||
|
||||
@ -133,7 +133,7 @@ class MultiTeamSession(Session):
|
||||
self._instantiate_next_game()
|
||||
|
||||
# Start in our custom join screen.
|
||||
self.set_activity(_ba.new_activity(MultiTeamJoinActivity))
|
||||
self.setactivity(_ba.new_activity(MultiTeamJoinActivity))
|
||||
|
||||
def get_ffa_series_length(self) -> int:
|
||||
"""Return free-for-all series length."""
|
||||
@ -179,14 +179,14 @@ class MultiTeamSession(Session):
|
||||
# If we have a tutorial to show, that's the first thing we do no
|
||||
# matter what.
|
||||
if self._tutorial_activity_instance is not None:
|
||||
self.set_activity(self._tutorial_activity_instance)
|
||||
self.setactivity(self._tutorial_activity_instance)
|
||||
self._tutorial_activity_instance = None
|
||||
|
||||
# If we're leaving the tutorial activity, pop a transition activity
|
||||
# to transition us into a round gracefully (otherwise we'd snap from
|
||||
# one terrain to another instantly).
|
||||
elif isinstance(activity, TutorialActivity):
|
||||
self.set_activity(
|
||||
self.setactivity(
|
||||
_ba.new_activity(_activitytypes.TransitionActivity))
|
||||
|
||||
# If we're in a between-round activity or a restart-activity, hop
|
||||
@ -226,10 +226,10 @@ class MultiTeamSession(Session):
|
||||
has_team = False
|
||||
if has_team:
|
||||
self.stats.register_player(player)
|
||||
self.stats.set_activity(next_game)
|
||||
self.stats.setactivity(next_game)
|
||||
|
||||
# Now flip the current activity.
|
||||
self.set_activity(next_game)
|
||||
self.setactivity(next_game)
|
||||
|
||||
# If we're leaving a round, go to the score screen.
|
||||
else:
|
||||
|
||||
@ -26,6 +26,8 @@ from dataclasses import dataclass
|
||||
from typing import TYPE_CHECKING, TypeVar, Generic
|
||||
|
||||
import _ba
|
||||
from ba._error import SessionPlayerNotFoundError, print_exception
|
||||
from ba._messages import DeathType, DieMessage
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import (Type, Optional, Sequence, Dict, Any, Union, Tuple,
|
||||
@ -52,7 +54,7 @@ class StandLocation:
|
||||
|
||||
Category: Gameplay Classes
|
||||
"""
|
||||
position: _ba.Vec3
|
||||
position: ba.Vec3
|
||||
angle: Optional[float] = None
|
||||
|
||||
|
||||
@ -61,27 +63,35 @@ class Player(Generic[TeamType]):
|
||||
|
||||
Category: Gameplay Classes
|
||||
|
||||
These correspond to ba.SessionPlayer objects, but are created per activity
|
||||
so that the activity can use its own custom player subclass.
|
||||
These correspond to ba.SessionPlayer objects, but are associated with a
|
||||
single ba.Activity instance. This allows activities to specify their
|
||||
own custom ba.Player types.
|
||||
|
||||
Attributes:
|
||||
|
||||
actor
|
||||
The ba.Actor associated with the player.
|
||||
|
||||
"""
|
||||
|
||||
# Defining these types at the class level instead of in __init__ so
|
||||
# that types are introspectable (these are still instance attrs).
|
||||
team: TeamType
|
||||
# These are instance attrs but we define them at the type level so
|
||||
# their type annotations are introspectable (for docs generation).
|
||||
character: str
|
||||
actor: Optional[ba.Actor]
|
||||
color: Sequence[float]
|
||||
highlight: Sequence[float]
|
||||
_team: TeamType
|
||||
_sessionplayer: ba.SessionPlayer
|
||||
_nodeactor: Optional[ba.NodeActor]
|
||||
|
||||
# Should aim to kill this eventually (at least gamedata).
|
||||
# Game-specific data can be tacked on to the per-game player class.
|
||||
sessiondata: Dict
|
||||
gamedata: Dict
|
||||
_expired: bool
|
||||
_postinited: bool
|
||||
sessiondata: dict
|
||||
_gamedata: dict
|
||||
|
||||
# NOTE: avoiding having any __init__() here since it seems to not
|
||||
# get called by default if a dataclass inherits from us.
|
||||
# This also lets us keep trivial player classes cleaner by skipping
|
||||
# the super().__init__() line.
|
||||
|
||||
def postinit(self, sessionplayer: ba.SessionPlayer) -> None:
|
||||
"""Wire up a newly created player.
|
||||
@ -108,23 +118,82 @@ class Player(Generic[TeamType]):
|
||||
self.character = sessionplayer.character
|
||||
self.color = sessionplayer.color
|
||||
self.highlight = sessionplayer.highlight
|
||||
self.team = sessionplayer.team.gameteam # type: ignore
|
||||
assert self.team is not None
|
||||
self._team = sessionplayer.team.gameteam # type: ignore
|
||||
assert self._team is not None
|
||||
self.sessiondata = sessionplayer.sessiondata
|
||||
self.gamedata = sessionplayer.gamedata
|
||||
|
||||
# Create our player node in the current activity.
|
||||
# Note: do we want to save a few cycles here by managing our player
|
||||
# node manually instead of wrapping it in a NodeActor?
|
||||
self._gamedata = {}
|
||||
self._expired = False
|
||||
self._postinited = True
|
||||
node = _ba.newnode('player', attrs={'playerID': sessionplayer.id})
|
||||
self._nodeactor = NodeActor(node)
|
||||
sessionplayer.set_node(node)
|
||||
sessionplayer.setnode(node)
|
||||
|
||||
def leave(self) -> None:
|
||||
"""Called when the Player leaves a running game.
|
||||
|
||||
(internal)
|
||||
"""
|
||||
assert self._postinited
|
||||
assert not self._expired
|
||||
try:
|
||||
# If they still have an actor, kill it.
|
||||
if self.actor:
|
||||
self.actor.handlemessage(DieMessage(how=DeathType.LEFT_GAME))
|
||||
self.actor = None
|
||||
except Exception:
|
||||
print_exception(f'Error killing actor on leave for {self}')
|
||||
self._nodeactor = None
|
||||
del self._team
|
||||
del self._gamedata
|
||||
|
||||
def expire(self) -> None:
|
||||
"""Called when the Player is expiring (when its Activity does so).
|
||||
|
||||
(internal)
|
||||
"""
|
||||
assert self._postinited
|
||||
assert not self._expired
|
||||
self._expired = True
|
||||
|
||||
try:
|
||||
self.on_expire()
|
||||
except Exception:
|
||||
print_exception(f'Error in on_expire for {self}.')
|
||||
|
||||
def reset(self) -> None:
|
||||
"""(internal)"""
|
||||
self._nodeactor = None
|
||||
self.actor = None
|
||||
self.team = None # type: ignore
|
||||
del self._team
|
||||
del self._gamedata
|
||||
|
||||
def on_expire(self) -> None:
|
||||
"""Can be overridden to handle player expiration.
|
||||
|
||||
The player expires when the Activity it is a part of expires.
|
||||
Expired players should no longer run any game logic (which will
|
||||
likely error). They should, however, remove any references to
|
||||
players/teams/games/etc. which could prevent them from being freed.
|
||||
"""
|
||||
|
||||
@property
|
||||
def team(self) -> TeamType:
|
||||
"""The ba.Team for this player."""
|
||||
assert self._postinited
|
||||
assert not self._expired
|
||||
return self._team
|
||||
|
||||
@property
|
||||
def gamedata(self) -> dict:
|
||||
"""Arbitrary values associated with the player.
|
||||
Though it is encouraged that most player values be properly defined
|
||||
on the ba.Player subclass, it may be useful for player-agnostic
|
||||
objects to store values here. This dict is cleared when the player
|
||||
leaves or expires so objects stored here will be disposed of at
|
||||
the expected time, unlike the Player instance itself which may
|
||||
continue to be referenced after it is no longer part of the game.
|
||||
"""
|
||||
assert self._postinited
|
||||
assert not self._expired
|
||||
return self._gamedata
|
||||
|
||||
@property
|
||||
def sessionplayer(self) -> ba.SessionPlayer:
|
||||
@ -132,10 +201,10 @@ class Player(Generic[TeamType]):
|
||||
|
||||
Throws a ba.SessionPlayerNotFoundError if it does not exist.
|
||||
"""
|
||||
assert self._postinited
|
||||
if bool(self._sessionplayer):
|
||||
return self._sessionplayer
|
||||
from ba import _error
|
||||
raise _error.SessionPlayerNotFoundError()
|
||||
raise SessionPlayerNotFoundError()
|
||||
|
||||
@property
|
||||
def node(self) -> ba.Node:
|
||||
@ -143,29 +212,35 @@ class Player(Generic[TeamType]):
|
||||
|
||||
This node can be used to get a generic player position/etc.
|
||||
"""
|
||||
if not self._nodeactor:
|
||||
from ba import _error
|
||||
raise _error.NodeNotFoundError
|
||||
assert self._postinited
|
||||
assert not self._expired
|
||||
assert self._nodeactor
|
||||
return self._nodeactor.node
|
||||
|
||||
@property
|
||||
def position(self) -> ba.Vec3:
|
||||
"""The position of the player, as defined by its current Actor.
|
||||
"""The position of the player, as defined by its current ba.Actor.
|
||||
|
||||
This value should not be used when the player has no Actor, as
|
||||
it is undefined in that case.
|
||||
This value is undefined when the player has no Actor.
|
||||
"""
|
||||
assert self._postinited
|
||||
assert not self._expired
|
||||
assert self.actor is not None
|
||||
return _ba.Vec3(self.node.position)
|
||||
|
||||
def exists(self) -> bool:
|
||||
"""Whether the underlying player still exists.
|
||||
|
||||
This will return False if the underlying ba.SessionPlayer has
|
||||
left the game or if the ba.Activity this player was associated
|
||||
with has ended.
|
||||
Most functionality will fail on a nonexistent player.
|
||||
Note that you can also use the boolean operator for this same
|
||||
functionality, so a statement such as "if player" will do
|
||||
the right thing both for Player objects and values of None.
|
||||
"""
|
||||
return self._sessionplayer.exists()
|
||||
assert self._postinited
|
||||
return self._sessionplayer.exists() and not self._expired
|
||||
|
||||
def getname(self, full: bool = False, icon: bool = True) -> str:
|
||||
"""getname(full: bool = False, icon: bool = True) -> str
|
||||
@ -173,6 +248,8 @@ class Player(Generic[TeamType]):
|
||||
Returns the player's name. If icon is True, the long version of the
|
||||
name may include an icon.
|
||||
"""
|
||||
assert self._postinited
|
||||
assert not self._expired
|
||||
return self._sessionplayer.getname(full=full, icon=icon)
|
||||
|
||||
def is_alive(self) -> bool:
|
||||
@ -181,6 +258,8 @@ class Player(Generic[TeamType]):
|
||||
Returns True if the player has a ba.Actor assigned and its
|
||||
is_alive() method return True. False is returned otherwise.
|
||||
"""
|
||||
assert self._postinited
|
||||
assert not self._expired
|
||||
return self.actor is not None and self.actor.is_alive()
|
||||
|
||||
def get_icon(self) -> Dict[str, Any]:
|
||||
@ -188,11 +267,13 @@ class Player(Generic[TeamType]):
|
||||
|
||||
Returns the character's icon (images, colors, etc contained in a dict)
|
||||
"""
|
||||
assert self._postinited
|
||||
assert not self._expired
|
||||
return self._sessionplayer.get_icon()
|
||||
|
||||
def assign_input_call(self, inputtype: Union[str, Tuple[str, ...]],
|
||||
call: Callable) -> None:
|
||||
"""assign_input_call(type: Union[str, Tuple[str, ...]],
|
||||
def assigninput(self, inputtype: Union[str, Tuple[str, ...]],
|
||||
call: Callable) -> None:
|
||||
"""assigninput(type: Union[str, Tuple[str, ...]],
|
||||
call: Callable) -> None
|
||||
|
||||
Set the python callable to be run for one or more types of input.
|
||||
@ -203,14 +284,18 @@ class Player(Generic[TeamType]):
|
||||
'rightRelease', 'run', 'flyPress', 'flyRelease', 'startPress',
|
||||
'startRelease'
|
||||
"""
|
||||
return self._sessionplayer.assign_input_call(type=inputtype, call=call)
|
||||
assert self._postinited
|
||||
assert not self._expired
|
||||
return self._sessionplayer.assigninput(type=inputtype, call=call)
|
||||
|
||||
def reset_input(self) -> None:
|
||||
"""reset_input() -> None
|
||||
def resetinput(self) -> None:
|
||||
"""resetinput() -> None
|
||||
|
||||
Clears out the player's assigned input actions.
|
||||
"""
|
||||
self._sessionplayer.reset_input()
|
||||
assert self._postinited
|
||||
assert not self._expired
|
||||
self._sessionplayer.resetinput()
|
||||
|
||||
def __bool__(self) -> bool:
|
||||
return self.exists()
|
||||
|
||||
@ -348,7 +348,7 @@ class Session:
|
||||
'_launch_end_session_activity called twice (since_last=' +
|
||||
str(since_last) + ')')
|
||||
self._launch_end_session_activity_time = curtime
|
||||
self.set_activity(_ba.new_activity(EndSessionActivity))
|
||||
self.setactivity(_ba.new_activity(EndSessionActivity))
|
||||
self._wants_to_end = False
|
||||
self._ending = True # Prevent further actions.
|
||||
|
||||
@ -398,42 +398,44 @@ class Session:
|
||||
"""General message handling; can be passed any message object."""
|
||||
from ba._lobby import PlayerReadyMessage
|
||||
from ba._messages import PlayerProfilesChangedMessage, UNHANDLED
|
||||
|
||||
if isinstance(msg, PlayerReadyMessage):
|
||||
self._on_player_ready(msg.chooser)
|
||||
return None
|
||||
|
||||
if isinstance(msg, PlayerProfilesChangedMessage):
|
||||
elif isinstance(msg, PlayerProfilesChangedMessage):
|
||||
# If we have a current activity with a lobby, ask it to reload
|
||||
# profiles.
|
||||
with _ba.Context(self):
|
||||
self.lobby.reload_profiles()
|
||||
return None
|
||||
|
||||
return UNHANDLED
|
||||
else:
|
||||
return UNHANDLED
|
||||
return None
|
||||
|
||||
class _SetActivityLock:
|
||||
class _SetActivityScopedLock:
|
||||
|
||||
def __init__(self, session: ba.Session) -> None:
|
||||
self._session = session
|
||||
if session._in_set_activity:
|
||||
raise RuntimeError('Session.setactivity() called recursively.')
|
||||
self._session._in_set_activity = True
|
||||
|
||||
def __del__(self) -> None:
|
||||
self._session._in_set_activity = False
|
||||
|
||||
def set_activity(self, activity: ba.Activity) -> None:
|
||||
def setactivity(self, activity: ba.Activity) -> None:
|
||||
"""Assign a new current ba.Activity for the session.
|
||||
|
||||
Note that this will not change the current context to the new
|
||||
Activity's. Code must be run in the new activity's methods
|
||||
(on_transition_in, etc) to get it. (so you can't do
|
||||
session.set_activity(foo) and then ba.newnode() to add a node to foo)
|
||||
session.setactivity(foo) and then ba.newnode() to add a node to foo)
|
||||
"""
|
||||
from ba._enums import TimeType
|
||||
|
||||
# Sanity test: make sure this doesn't get called recursively.
|
||||
if self._in_set_activity:
|
||||
raise RuntimeError('Session.set_activity() called recursively.')
|
||||
self._in_set_activity = True
|
||||
# Make sure we don't get called recursively.
|
||||
_rlock = self._SetActivityScopedLock(self)
|
||||
|
||||
if activity.session is not _ba.getsession():
|
||||
raise RuntimeError("Provided Activity's Session is not current.")
|
||||
@ -482,7 +484,7 @@ class Session:
|
||||
if prev_activity is not None:
|
||||
with _ba.Context('ui'):
|
||||
_ba.timer(max(0.0, activity.transition_time),
|
||||
prev_activity.destroy,
|
||||
prev_activity.expire,
|
||||
timetype=TimeType.REAL)
|
||||
self._in_set_activity = False
|
||||
|
||||
@ -507,17 +509,17 @@ class Session:
|
||||
with _ba.Context(self):
|
||||
self.on_activity_end(activity, results)
|
||||
except Exception:
|
||||
print_exception('exception in on_activity_end() for session', self,
|
||||
'activity', activity, 'with results', results)
|
||||
print_exception(f'Error in on_activity_end() for session {self}'
|
||||
f' activity {activity} with results {results}')
|
||||
|
||||
def _request_player(self, sessionplayer: ba.SessionPlayer) -> bool:
|
||||
"""Called by the C++ layer when players want to join."""
|
||||
"""Called by the native layer when a player wants to join."""
|
||||
|
||||
# If we're ending, allow no new players.
|
||||
if self._ending:
|
||||
return False
|
||||
|
||||
# Ask the session subclass to approve/deny this request.
|
||||
# Ask the ba.Session subclass to approve/deny this request.
|
||||
try:
|
||||
with _ba.Context(self):
|
||||
result = self.on_player_request(sessionplayer)
|
||||
@ -525,14 +527,14 @@ class Session:
|
||||
print_exception(f'Error in on_player_request for {self}')
|
||||
result = False
|
||||
|
||||
# If the user said yes, add the player to the session list.
|
||||
# If they said yes, add the player to the lobby.
|
||||
if result:
|
||||
self.players.append(sessionplayer)
|
||||
with _ba.Context(self):
|
||||
try:
|
||||
self.lobby.add_chooser(sessionplayer)
|
||||
except Exception:
|
||||
print_exception('exception in lobby.add_chooser()')
|
||||
print_exception('Error in lobby.add_chooser().')
|
||||
|
||||
return result
|
||||
|
||||
@ -548,39 +550,42 @@ class Session:
|
||||
|
||||
This means we're ready to begin the next one
|
||||
"""
|
||||
if self._next_activity is not None:
|
||||
if self._next_activity is None:
|
||||
# Should this ever happen?
|
||||
print_error('begin_next_activity() called with no _next_activity')
|
||||
return
|
||||
|
||||
# We store both a weak and a strong ref to the new activity;
|
||||
# the strong is to keep it alive and the weak is so we can access
|
||||
# it even after we've released the strong-ref to allow it to die.
|
||||
self._activity_retained = self._next_activity
|
||||
self._activity_weak = weakref.ref(self._next_activity)
|
||||
self._next_activity = None
|
||||
self._activity_should_end_immediately = False
|
||||
# We store both a weak and a strong ref to the new activity;
|
||||
# the strong is to keep it alive and the weak is so we can access
|
||||
# it even after we've released the strong-ref to allow it to die.
|
||||
self._activity_retained = self._next_activity
|
||||
self._activity_weak = weakref.ref(self._next_activity)
|
||||
self._next_activity = None
|
||||
self._activity_should_end_immediately = False
|
||||
|
||||
# Kick out anyone loitering in the lobby.
|
||||
self.lobby.remove_all_choosers_and_kick_players()
|
||||
# Kick out anyone loitering in the lobby.
|
||||
self.lobby.remove_all_choosers_and_kick_players()
|
||||
|
||||
# Kick off the activity.
|
||||
self._activity_retained.begin(self)
|
||||
# Kick off the activity.
|
||||
self._activity_retained.begin(self)
|
||||
|
||||
# If we want to go down, we're now free to kick off that process.
|
||||
if self._wants_to_end:
|
||||
self._launch_end_session_activity()
|
||||
else:
|
||||
# Otherwise, if the activity has already been told to end,
|
||||
# do so now.
|
||||
if self._activity_should_end_immediately:
|
||||
self._activity_retained.end(
|
||||
self._activity_should_end_immediately_results,
|
||||
self._activity_should_end_immediately_delay)
|
||||
# If we want to completely end the session, we can now kick that off.
|
||||
if self._wants_to_end:
|
||||
self._launch_end_session_activity()
|
||||
else:
|
||||
# Otherwise, if the activity has already been told to end,
|
||||
# do so now.
|
||||
if self._activity_should_end_immediately:
|
||||
self._activity_retained.end(
|
||||
self._activity_should_end_immediately_results,
|
||||
self._activity_should_end_immediately_delay)
|
||||
|
||||
def _on_player_ready(self, chooser: ba.Chooser) -> None:
|
||||
"""Called when a ba.Player has checked themself ready."""
|
||||
lobby = chooser.lobby
|
||||
activity = self._activity_weak()
|
||||
|
||||
# In joining activities, we wait till all choosers are ready
|
||||
# In joining-activities, we wait till all choosers are ready
|
||||
# and then create all players at once.
|
||||
if activity is not None and activity.is_joining_activity:
|
||||
if lobby.check_all_ready():
|
||||
@ -613,8 +618,10 @@ class Session:
|
||||
"""(internal)"""
|
||||
from ba._apputils import garbage_collect, call_after_ad
|
||||
|
||||
# Since we're mostly between activities at this point, lets run a cycle
|
||||
# of garbage collection; hopefully it won't cause hitches here.
|
||||
# Since things should be generally still right now, it's a good time
|
||||
# to run garbage collection to clear out any circular dependency
|
||||
# loops. We keep this disabled normally to avoid non-deterministic
|
||||
# hitches.
|
||||
garbage_collect(session_end=False)
|
||||
|
||||
with _ba.Context(self):
|
||||
@ -635,7 +642,7 @@ class Session:
|
||||
|
||||
# Reset the player's input here, as it is probably
|
||||
# referencing the chooser which could inadvertently keep it alive.
|
||||
sessionplayer.reset_input()
|
||||
sessionplayer.resetinput()
|
||||
|
||||
# We can pass it to the current activity if it has already begun
|
||||
# (otherwise it'll get passed once begin is called).
|
||||
@ -658,7 +665,7 @@ class Session:
|
||||
# If we're a non-team session, each player gets their own team.
|
||||
# (keeps mini-game coding simpler if we can always deal with teams).
|
||||
if self.use_teams:
|
||||
sessionteam = chooser.get_team()
|
||||
sessionteam = chooser.sessionteam
|
||||
else:
|
||||
our_team_id = self._next_team_id
|
||||
self._next_team_id += 1
|
||||
@ -670,11 +677,12 @@ class Session:
|
||||
|
||||
# Add player's team to the Session.
|
||||
self.teams.append(sessionteam)
|
||||
try:
|
||||
with _ba.Context(self):
|
||||
|
||||
with _ba.Context(self):
|
||||
try:
|
||||
self.on_team_join(sessionteam)
|
||||
except Exception:
|
||||
print_exception(f'exception in on_team_join for {self}')
|
||||
except Exception:
|
||||
print_exception(f'Error in on_team_join for {self}.')
|
||||
|
||||
# Add player's team to the Activity.
|
||||
if pass_to_activity:
|
||||
@ -682,10 +690,10 @@ class Session:
|
||||
|
||||
assert sessionplayer not in sessionteam.players
|
||||
sessionteam.players.append(sessionplayer)
|
||||
sessionplayer.set_data(team=sessionteam,
|
||||
character=chooser.get_character_name(),
|
||||
color=chooser.get_color(),
|
||||
highlight=chooser.get_highlight())
|
||||
sessionplayer.setdata(team=sessionteam,
|
||||
character=chooser.get_character_name(),
|
||||
color=chooser.get_color(),
|
||||
highlight=chooser.get_highlight())
|
||||
|
||||
self.stats.register_player(sessionplayer)
|
||||
if pass_to_activity:
|
||||
|
||||
@ -259,7 +259,7 @@ class Stats:
|
||||
self.orchestrahitsound3: Optional[ba.Sound] = None
|
||||
self.orchestrahitsound4: Optional[ba.Sound] = None
|
||||
|
||||
def set_activity(self, activity: Optional[ba.Activity]) -> None:
|
||||
def setactivity(self, activity: Optional[ba.Activity]) -> None:
|
||||
"""Set the current activity for this instance."""
|
||||
|
||||
self._activity = None if activity is None else weakref.ref(activity)
|
||||
|
||||
@ -25,6 +25,8 @@ from __future__ import annotations
|
||||
import weakref
|
||||
from typing import TYPE_CHECKING, TypeVar, Generic
|
||||
|
||||
from ba._error import print_exception
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from weakref import ReferenceType
|
||||
from typing import Dict, List, Sequence, Tuple, Union, Optional
|
||||
@ -88,14 +90,9 @@ class SessionTeam:
|
||||
self.name = name
|
||||
self.color = tuple(color)
|
||||
self.players = []
|
||||
self.gamedata = {}
|
||||
self.sessiondata = {}
|
||||
self.gameteam: Optional[Team] = None
|
||||
|
||||
def reset_gamedata(self) -> None:
|
||||
"""(internal)"""
|
||||
self.gamedata = {}
|
||||
|
||||
def reset_sessiondata(self) -> None:
|
||||
"""(internal)"""
|
||||
self.sessiondata = {}
|
||||
@ -118,12 +115,14 @@ class Team(Generic[PlayerType]):
|
||||
players: List[PlayerType]
|
||||
id: int
|
||||
name: Union[ba.Lstr, str]
|
||||
color: Tuple[float, ...] # FIXME: can't we make this fixed len?
|
||||
color: Tuple[float, ...] # FIXME: can't we make this fixed length?
|
||||
_sessionteam: ReferenceType[SessionTeam]
|
||||
_expired: bool
|
||||
_postinited: bool
|
||||
_gamedata: dict
|
||||
|
||||
# TODO: kill these.
|
||||
gamedata: Dict
|
||||
sessiondata: Dict
|
||||
sessiondata: dict
|
||||
|
||||
# NOTE: avoiding having any __init__() here since it seems to not
|
||||
# get called by default if a dataclass inherits from us.
|
||||
@ -150,8 +149,10 @@ class Team(Generic[PlayerType]):
|
||||
self.id = sessionteam.id
|
||||
self.name = sessionteam.name
|
||||
self.color = sessionteam.color
|
||||
self.gamedata = sessionteam.gamedata
|
||||
self.sessiondata = sessionteam.sessiondata
|
||||
self._gamedata = {}
|
||||
self._expired = False
|
||||
self._postinited = True
|
||||
|
||||
def manual_init(self, team_id: int, name: Union[ba.Lstr, str],
|
||||
color: Tuple[float, ...]) -> None:
|
||||
@ -159,8 +160,54 @@ class Team(Generic[PlayerType]):
|
||||
self.id = team_id
|
||||
self.name = name
|
||||
self.color = color
|
||||
self.gamedata = {}
|
||||
self._gamedata = {}
|
||||
self.sessiondata = {}
|
||||
self._expired = False
|
||||
self._postinited = True
|
||||
|
||||
@property
|
||||
def gamedata(self) -> dict:
|
||||
"""Arbitrary values associated with the team.
|
||||
Though it is encouraged that most player values be properly defined
|
||||
on the ba.Team subclass, it may be useful for player-agnostic
|
||||
objects to store values here. This dict is cleared when the team
|
||||
leaves or expires so objects stored here will be disposed of at
|
||||
the expected time, unlike the Team instance itself which may
|
||||
continue to be referenced after it is no longer part of the game.
|
||||
"""
|
||||
assert self._postinited
|
||||
assert not self._expired
|
||||
return self._gamedata
|
||||
|
||||
def leave(self) -> None:
|
||||
"""Called when the Team leaves a running game.
|
||||
|
||||
(internal)
|
||||
"""
|
||||
assert self._postinited
|
||||
assert not self._expired
|
||||
del self._gamedata
|
||||
del self.players
|
||||
|
||||
def expire(self) -> None:
|
||||
"""Called when the Team is expiring (due to the Activity expiring).
|
||||
|
||||
(internal)
|
||||
"""
|
||||
assert self._postinited
|
||||
assert not self._expired
|
||||
self._expired = True
|
||||
|
||||
try:
|
||||
self.on_expire()
|
||||
except Exception:
|
||||
print_exception(f'Error in on_expire for {self}.')
|
||||
|
||||
del self._gamedata
|
||||
del self.players
|
||||
|
||||
def on_expire(self) -> None:
|
||||
"""Can be overridden to handle team expiration."""
|
||||
|
||||
@property
|
||||
def sessionteam(self) -> SessionTeam:
|
||||
@ -168,6 +215,7 @@ class Team(Generic[PlayerType]):
|
||||
|
||||
Throws a ba.SessionTeamNotFoundError if there is none.
|
||||
"""
|
||||
assert self._postinited
|
||||
if self._sessionteam is not None:
|
||||
sessionteam = self._sessionteam()
|
||||
if sessionteam is not None:
|
||||
|
||||
@ -138,34 +138,33 @@ class PlayerSpaz(Spaz):
|
||||
# wiring up.
|
||||
if self._connected_to_player:
|
||||
if player != self._connected_to_player:
|
||||
player.reset_input()
|
||||
player.resetinput()
|
||||
self.disconnect_controls_from_player()
|
||||
else:
|
||||
player.reset_input()
|
||||
player.resetinput()
|
||||
|
||||
player.assign_input_call('upDown', self.on_move_up_down)
|
||||
player.assign_input_call('leftRight', self.on_move_left_right)
|
||||
player.assign_input_call('holdPositionPress',
|
||||
self.on_hold_position_press)
|
||||
player.assign_input_call('holdPositionRelease',
|
||||
self.on_hold_position_release)
|
||||
player.assigninput('upDown', self.on_move_up_down)
|
||||
player.assigninput('leftRight', self.on_move_left_right)
|
||||
player.assigninput('holdPositionPress', self.on_hold_position_press)
|
||||
player.assigninput('holdPositionRelease',
|
||||
self.on_hold_position_release)
|
||||
if enable_jump:
|
||||
player.assign_input_call('jumpPress', self.on_jump_press)
|
||||
player.assign_input_call('jumpRelease', self.on_jump_release)
|
||||
player.assigninput('jumpPress', self.on_jump_press)
|
||||
player.assigninput('jumpRelease', self.on_jump_release)
|
||||
if enable_pickup:
|
||||
player.assign_input_call('pickUpPress', self.on_pickup_press)
|
||||
player.assign_input_call('pickUpRelease', self.on_pickup_release)
|
||||
player.assigninput('pickUpPress', self.on_pickup_press)
|
||||
player.assigninput('pickUpRelease', self.on_pickup_release)
|
||||
if enable_punch:
|
||||
player.assign_input_call('punchPress', self.on_punch_press)
|
||||
player.assign_input_call('punchRelease', self.on_punch_release)
|
||||
player.assigninput('punchPress', self.on_punch_press)
|
||||
player.assigninput('punchRelease', self.on_punch_release)
|
||||
if enable_bomb:
|
||||
player.assign_input_call('bombPress', self.on_bomb_press)
|
||||
player.assign_input_call('bombRelease', self.on_bomb_release)
|
||||
player.assigninput('bombPress', self.on_bomb_press)
|
||||
player.assigninput('bombRelease', self.on_bomb_release)
|
||||
if enable_run:
|
||||
player.assign_input_call('run', self.on_run)
|
||||
player.assigninput('run', self.on_run)
|
||||
if enable_fly:
|
||||
player.assign_input_call('flyPress', self.on_fly_press)
|
||||
player.assign_input_call('flyRelease', self.on_fly_release)
|
||||
player.assigninput('flyPress', self.on_fly_press)
|
||||
player.assigninput('flyRelease', self.on_fly_release)
|
||||
|
||||
self._connected_to_player = player
|
||||
|
||||
@ -175,7 +174,7 @@ class PlayerSpaz(Spaz):
|
||||
ba.Player from control of this spaz.
|
||||
"""
|
||||
if self._connected_to_player:
|
||||
self._connected_to_player.reset_input()
|
||||
self._connected_to_player.resetinput()
|
||||
self._connected_to_player = None
|
||||
|
||||
# Send releases for anything in case its held.
|
||||
@ -239,7 +238,7 @@ class PlayerSpaz(Spaz):
|
||||
|
||||
activity = self._activity()
|
||||
|
||||
player = self.getplayer(ba.Player, doraise=False)
|
||||
player = self.getplayer(ba.Player, False)
|
||||
if not killed:
|
||||
killerplayer = None
|
||||
else:
|
||||
|
||||
@ -46,10 +46,10 @@ class RespawnIcon:
|
||||
on_right, offs_extra, respawn_icons = self._get_context(player)
|
||||
|
||||
# Cache our mask tex on the team for easy access.
|
||||
mask_tex = getattr(player.team, '_spaz_respawn_icons_mask_tex', None)
|
||||
mask_tex = player.team.gamedata.get('_spaz_respawn_icons_mask_tex')
|
||||
if mask_tex is None:
|
||||
mask_tex = ba.gettexture('characterIconMask')
|
||||
setattr(player.team, '_spaz_respawn_icons_mask_tex', mask_tex)
|
||||
player.team.gamedata['_spaz_respawn_icons_mask_tex'] = mask_tex
|
||||
assert isinstance(mask_tex, ba.Texture)
|
||||
|
||||
# Now find the first unused slot and use that.
|
||||
@ -134,34 +134,31 @@ class RespawnIcon:
|
||||
def _get_context(self, player: ba.Player) -> Tuple[bool, float, Dict]:
|
||||
"""Return info on where we should be shown and stored."""
|
||||
activity = ba.getactivity()
|
||||
|
||||
if isinstance(ba.getsession(), ba.DualTeamSession):
|
||||
on_right = player.team.id % 2 == 1
|
||||
|
||||
# Store a list of icons in the team.
|
||||
respawn_icons = getattr(player.team, '_spaz_respawn_icons_right',
|
||||
None)
|
||||
if respawn_icons is None:
|
||||
respawn_icons = {}
|
||||
setattr(player.team, '_spaz_respawn_icons_right',
|
||||
respawn_icons)
|
||||
assert isinstance(respawn_icons, dict)
|
||||
icons = player.team.gamedata.get('_spaz_respawn_icons')
|
||||
if icons is None:
|
||||
player.team.gamedata['_spaz_respawn_icons'] = icons = {}
|
||||
assert isinstance(icons, dict)
|
||||
|
||||
offs_extra = -20
|
||||
else:
|
||||
on_right = False
|
||||
|
||||
# Store a list of icons in the activity.
|
||||
# FIXME: Need an elegant way to store our shared stuff with
|
||||
# the activity.
|
||||
try:
|
||||
respawn_icons = activity.spaz_respawn_icons_right
|
||||
except Exception:
|
||||
respawn_icons = activity.spaz_respawn_icons_right = {}
|
||||
icons = activity.gamedata.get('_spaz_respawn_icons')
|
||||
if icons is None:
|
||||
activity.gamedata['_spaz_respawn_icons'] = icons = {}
|
||||
assert isinstance(icons, dict)
|
||||
|
||||
if isinstance(activity.session, ba.FreeForAllSession):
|
||||
offs_extra = -150
|
||||
else:
|
||||
offs_extra = -20
|
||||
return on_right, offs_extra, respawn_icons
|
||||
return on_right, offs_extra, icons
|
||||
|
||||
def _update(self) -> None:
|
||||
remaining = int(round(self._respawn_time - ba.time()))
|
||||
|
||||
@ -30,14 +30,12 @@ import ba
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Optional, Sequence, Dict, Union
|
||||
|
||||
# This could use some tidying up when I get a chance..
|
||||
# pylint: disable=too-many-statements
|
||||
|
||||
|
||||
class _Entry:
|
||||
|
||||
def __init__(self, scoreboard: Scoreboard, team: ba.Team, do_cover: bool,
|
||||
scale: float, label: Optional[ba.Lstr], flash_length: float):
|
||||
# pylint: disable=too-many-statements
|
||||
self._scoreboard = weakref.ref(scoreboard)
|
||||
self._do_cover = do_cover
|
||||
self._scale = scale
|
||||
@ -58,7 +56,7 @@ class _Entry:
|
||||
safe_team_color = ba.safecolor(team.color, target_intensity=1.0)
|
||||
|
||||
# FIXME: Should not do things conditionally for vr-mode, as there may
|
||||
# be non-vr clients connected.
|
||||
# be non-vr clients connected which will also get these value.
|
||||
vrmode = ba.app.vr_mode
|
||||
|
||||
if self._do_cover:
|
||||
@ -152,11 +150,11 @@ class _Entry:
|
||||
else:
|
||||
team_name_label = team.name
|
||||
|
||||
# we do our own clipping here; should probably try to tap into some
|
||||
# existing functionality
|
||||
# We do our own clipping here; should probably try to tap into some
|
||||
# existing functionality.
|
||||
if isinstance(team_name_label, ba.Lstr):
|
||||
|
||||
# hmmm; if the team-name is a non-translatable value lets go
|
||||
# Hmmm; if the team-name is a non-translatable value lets go
|
||||
# ahead and clip it otherwise we leave it as-is so
|
||||
# translation can occur..
|
||||
if team_name_label.is_flat_value():
|
||||
@ -204,6 +202,7 @@ class _Entry:
|
||||
# Abort if we've been killed
|
||||
if not self._backing.node:
|
||||
return
|
||||
|
||||
self._pos = tuple(position)
|
||||
self._backing.node.position = (position[0] + self._width / 2,
|
||||
position[1] - self._height / 2)
|
||||
@ -226,29 +225,29 @@ class _Entry:
|
||||
def _set_flash_colors(self, flash: bool) -> None:
|
||||
self._flash_colors = flash
|
||||
|
||||
def _safesetattr(node: Optional[ba.Node], attr: str, val: Any) -> None:
|
||||
def _safesetcolor(node: Optional[ba.Node], val: Any) -> None:
|
||||
if node:
|
||||
setattr(node, attr, val)
|
||||
node.color = val
|
||||
|
||||
if flash:
|
||||
scale = 2.0
|
||||
_safesetattr(
|
||||
self._backing.node, 'color',
|
||||
_safesetcolor(
|
||||
self._backing.node,
|
||||
(self._backing_color[0] * scale, self._backing_color[1] *
|
||||
scale, self._backing_color[2] * scale))
|
||||
_safesetattr(self._bar.node, 'color',
|
||||
(self._barcolor[0] * scale, self._barcolor[1] * scale,
|
||||
self._barcolor[2] * scale))
|
||||
_safesetcolor(self._bar.node,
|
||||
(self._barcolor[0] * scale, self._barcolor[1] *
|
||||
scale, self._barcolor[2] * scale))
|
||||
if self._do_cover:
|
||||
_safesetattr(
|
||||
self._cover.node, 'color',
|
||||
_safesetcolor(
|
||||
self._cover.node,
|
||||
(self._cover_color[0] * scale, self._cover_color[1] *
|
||||
scale, self._cover_color[2] * scale))
|
||||
else:
|
||||
_safesetattr(self._backing.node, 'color', self._backing_color)
|
||||
_safesetattr(self._bar.node, 'color', self._barcolor)
|
||||
_safesetcolor(self._backing.node, self._backing_color)
|
||||
_safesetcolor(self._bar.node, self._barcolor)
|
||||
if self._do_cover:
|
||||
_safesetattr(self._cover.node, 'color', self._cover_color)
|
||||
_safesetcolor(self._cover.node, self._cover_color)
|
||||
|
||||
def _do_flash(self) -> None:
|
||||
assert self._flash_counter is not None
|
||||
@ -266,8 +265,8 @@ class _Entry:
|
||||
show_value: bool = True) -> None:
|
||||
"""Set the value for the scoreboard entry."""
|
||||
|
||||
# if we have no score yet, just set it.. otherwise compare
|
||||
# and see if we should flash
|
||||
# If we have no score yet, just set it.. otherwise compare
|
||||
# and see if we should flash.
|
||||
if self._score is None:
|
||||
self._score = score
|
||||
else:
|
||||
@ -327,8 +326,15 @@ class _EntryProxy:
|
||||
# Remove our team from the scoreboard if its still around.
|
||||
# (but deferred, in case we die in a sim step or something where
|
||||
# its illegal to modify nodes)
|
||||
if scoreboard is not None:
|
||||
if scoreboard is None:
|
||||
return
|
||||
|
||||
try:
|
||||
ba.pushcall(ba.Call(scoreboard.remove_team, self._team_id))
|
||||
except ba.ContextError:
|
||||
# This happens if we fire after the activity expires.
|
||||
# In that case we don't need to do anything.
|
||||
pass
|
||||
|
||||
|
||||
class Scoreboard:
|
||||
@ -338,7 +344,7 @@ class Scoreboard:
|
||||
"""
|
||||
|
||||
def __init__(self, label: ba.Lstr = None, score_split: float = 0.7):
|
||||
"""Instantiate a score-board.
|
||||
"""Instantiate a scoreboard.
|
||||
|
||||
Label can be something like 'points' and will
|
||||
show up on boards if provided.
|
||||
@ -376,8 +382,8 @@ class Scoreboard:
|
||||
|
||||
# Create a proxy in the team which will kill
|
||||
# our entry when it dies (for convenience)
|
||||
assert not hasattr(team, '_scoreboard_entry')
|
||||
setattr(team, '_scoreboard_entry', _EntryProxy(self, team))
|
||||
assert '_scoreboard_entry' not in team.gamedata
|
||||
team.gamedata['_scoreboard_entry'] = _EntryProxy(self, team)
|
||||
|
||||
# Now set the entry.
|
||||
self._entries[team.id].set_value(score=score,
|
||||
|
||||
@ -181,9 +181,13 @@ class AssaultGame(ba.TeamGameActivity[Player, Team]):
|
||||
ba.timer(length, light.delete)
|
||||
|
||||
def _handle_base_collide(self, team: Team) -> None:
|
||||
player = ba.getcollision().opposingnode.getdelegate(
|
||||
PlayerSpaz, True).getplayer(Player)
|
||||
if not player or not player.is_alive():
|
||||
try:
|
||||
player = ba.getcollision().opposingnode.getdelegate(
|
||||
PlayerSpaz, True).getplayer(Player, True)
|
||||
except ba.NotFoundError:
|
||||
return
|
||||
|
||||
if not player.is_alive():
|
||||
return
|
||||
|
||||
# If its another team's player, they scored.
|
||||
|
||||
@ -231,9 +231,9 @@ class CaptureTheFlagGame(ba.TeamGameActivity[Player, Team]):
|
||||
actions=(
|
||||
('modify_part_collision', 'physical', False),
|
||||
('call', 'at_connect',
|
||||
lambda: self._handle_hit_own_flag(team, 1)),
|
||||
lambda: self._handle_touching_own_flag(team, True)),
|
||||
('call', 'at_disconnect',
|
||||
lambda: self._handle_hit_own_flag(team, 0)),
|
||||
lambda: self._handle_touching_own_flag(team, False)),
|
||||
))
|
||||
|
||||
# Other parts of our spazzes don't collide with our flags at all.
|
||||
@ -448,32 +448,28 @@ class CaptureTheFlagGame(ba.TeamGameActivity[Player, Team]):
|
||||
delegate = node.getdelegate(PlayerSpaz)
|
||||
return None if delegate is None else delegate.getplayer(Player)
|
||||
|
||||
def _handle_hit_own_flag(self, team: Team, val: int) -> None:
|
||||
"""Called when a player touches their own team flag.
|
||||
def _handle_touching_own_flag(self, team: Team, connecting: bool) -> None:
|
||||
"""Called when a player touches or stops touching their own team flag.
|
||||
|
||||
We keep track of when each player is touching their
|
||||
own flag so we can award points when returned.
|
||||
We keep track of when each player is touching their own flag so we
|
||||
can award points when returned.
|
||||
"""
|
||||
player = self._player_from_node(ba.getcollision().sourcenode)
|
||||
if player:
|
||||
player.touching_own_flag += (1 if val else -1)
|
||||
player.touching_own_flag += (1 if connecting else -1)
|
||||
|
||||
# If return-time is zero, just kill it immediately.. otherwise keep
|
||||
# track of touches and count down.
|
||||
if float(self.flag_touch_return_time) <= 0.0:
|
||||
assert team.flag is not None
|
||||
if not team.home_flag_at_base and team.flag.held_count == 0:
|
||||
|
||||
# Use a node message to kill the flag instead of just killing
|
||||
# our team's. (avoids redundantly killing new flags if
|
||||
# multiple body parts generate callbacks in one step).
|
||||
node = ba.getcollision().opposingnode
|
||||
if (connecting and not team.home_flag_at_base
|
||||
and team.flag.held_count == 0):
|
||||
self._award_players_touching_own_flag(team)
|
||||
node.handlemessage(ba.DieMessage())
|
||||
ba.getcollision().opposingnode.handlemessage(ba.DieMessage())
|
||||
|
||||
# Takes a non-zero amount of time to return.
|
||||
else:
|
||||
if val:
|
||||
if connecting:
|
||||
team.flag_return_touches += 1
|
||||
if team.flag_return_touches == 1:
|
||||
team.touch_return_timer = ba.Timer(
|
||||
@ -506,7 +502,7 @@ class CaptureTheFlagGame(ba.TeamGameActivity[Player, Team]):
|
||||
angle: float = None) -> PlayerSpaz:
|
||||
"""Intercept new spazzes and add our team material for them."""
|
||||
spaz = super().spawn_player_spaz(player, position, angle)
|
||||
player = spaz.getplayer(Player, doraise=True)
|
||||
player = spaz.getplayer(Player, True)
|
||||
team: Team = player.team
|
||||
player.touching_own_flag = 0
|
||||
no_physical_mats: List[ba.Material] = [
|
||||
@ -548,10 +544,15 @@ class CaptureTheFlagGame(ba.TeamGameActivity[Player, Team]):
|
||||
ba.timer(0.1, ba.Call(self._spawn_flag_for_team, msg.flag.team))
|
||||
|
||||
elif isinstance(msg, FlagPickedUpMessage):
|
||||
|
||||
# Store the last player to hold the flag for scoring purposes.
|
||||
assert isinstance(msg.flag, CTFFlag)
|
||||
msg.flag.last_player_to_hold = msg.node.getdelegate(
|
||||
PlayerSpaz, True).getplayer(Player)
|
||||
try:
|
||||
msg.flag.last_player_to_hold = msg.node.getdelegate(
|
||||
PlayerSpaz, True).getplayer(Player, True)
|
||||
except ba.NotFoundError:
|
||||
pass
|
||||
|
||||
msg.flag.held_count += 1
|
||||
msg.flag.reset_return_times()
|
||||
|
||||
|
||||
@ -236,10 +236,12 @@ class ConquestGame(ba.TeamGameActivity[Player, Team]):
|
||||
|
||||
def _handle_flag_player_collide(self) -> None:
|
||||
collision = ba.getcollision()
|
||||
flag = collision.sourcenode.getdelegate(ConquestFlag)
|
||||
player = collision.opposingnode.getdelegate(PlayerSpaz,
|
||||
True).getplayer(Player)
|
||||
if not flag or not player:
|
||||
try:
|
||||
flag = collision.sourcenode.getdelegate(ConquestFlag, True)
|
||||
player = collision.opposingnode.getdelegate(PlayerSpaz,
|
||||
True).getplayer(
|
||||
Player, True)
|
||||
except ba.NotFoundError:
|
||||
return
|
||||
assert flag.light
|
||||
|
||||
|
||||
@ -139,41 +139,39 @@ class EasterEggHuntGame(ba.TeamGameActivity[Player, Team]):
|
||||
if self.has_ended():
|
||||
return
|
||||
collision = ba.getcollision()
|
||||
egg = collision.sourcenode.getdelegate(Egg)
|
||||
player = collision.opposingnode.getdelegate(PlayerSpaz,
|
||||
True).getplayer(Player)
|
||||
if player and egg:
|
||||
player.team.score += 1
|
||||
try:
|
||||
egg = collision.sourcenode.getdelegate(Egg, True)
|
||||
player = collision.opposingnode.getdelegate(PlayerSpaz,
|
||||
True).getplayer(
|
||||
Player, True)
|
||||
except Exception:
|
||||
return
|
||||
|
||||
# Displays a +1 (and adds to individual player score in
|
||||
# teams mode).
|
||||
self.stats.player_scored(player, 1, screenmessage=False)
|
||||
if self._max_eggs < 5:
|
||||
self._max_eggs += 1.0
|
||||
elif self._max_eggs < 10:
|
||||
self._max_eggs += 0.5
|
||||
elif self._max_eggs < 30:
|
||||
self._max_eggs += 0.3
|
||||
self._update_scoreboard()
|
||||
ba.playsound(self._collect_sound, 0.5, position=egg.node.position)
|
||||
player.team.score += 1
|
||||
|
||||
# Create a flash.
|
||||
light = ba.newnode('light',
|
||||
attrs={
|
||||
'position': egg.node.position,
|
||||
'height_attenuated': False,
|
||||
'radius': 0.1,
|
||||
'color': (1, 1, 0)
|
||||
})
|
||||
ba.animate(light,
|
||||
'intensity', {
|
||||
0: 0,
|
||||
0.1: 1.0,
|
||||
0.2: 0
|
||||
},
|
||||
loop=False)
|
||||
ba.timer(0.200, light.delete)
|
||||
egg.handlemessage(ba.DieMessage())
|
||||
# Displays a +1 (and adds to individual player score in
|
||||
# teams mode).
|
||||
self.stats.player_scored(player, 1, screenmessage=False)
|
||||
if self._max_eggs < 5:
|
||||
self._max_eggs += 1.0
|
||||
elif self._max_eggs < 10:
|
||||
self._max_eggs += 0.5
|
||||
elif self._max_eggs < 30:
|
||||
self._max_eggs += 0.3
|
||||
self._update_scoreboard()
|
||||
ba.playsound(self._collect_sound, 0.5, position=egg.node.position)
|
||||
|
||||
# Create a flash.
|
||||
light = ba.newnode('light',
|
||||
attrs={
|
||||
'position': egg.node.position,
|
||||
'height_attenuated': False,
|
||||
'radius': 0.1,
|
||||
'color': (1, 1, 0)
|
||||
})
|
||||
ba.animate(light, 'intensity', {0: 0, 0.1: 1.0, 0.2: 0}, loop=False)
|
||||
ba.timer(0.200, light.delete)
|
||||
egg.handlemessage(ba.DieMessage())
|
||||
|
||||
def _update(self) -> None:
|
||||
# Misc. periodic updating.
|
||||
|
||||
@ -267,9 +267,11 @@ class FootballTeamGame(ba.TeamGameActivity[Player, Team]):
|
||||
def handlemessage(self, msg: Any) -> Any:
|
||||
if isinstance(msg, FlagPickedUpMessage):
|
||||
assert isinstance(msg.flag, FootballFlag)
|
||||
player = msg.node.getdelegate(PlayerSpaz, True).getplayer(Player)
|
||||
if player:
|
||||
msg.flag.last_holding_player = player
|
||||
try:
|
||||
msg.flag.last_holding_player = msg.node.getdelegate(
|
||||
PlayerSpaz, True).getplayer(Player, True)
|
||||
except ba.NotFoundError:
|
||||
pass
|
||||
msg.flag.held_count += 1
|
||||
|
||||
elif isinstance(msg, FlagDroppedMessage):
|
||||
|
||||
@ -256,11 +256,15 @@ class HockeyGame(ba.TeamGameActivity[Player, Team]):
|
||||
|
||||
def _handle_puck_player_collide(self) -> None:
|
||||
collision = ba.getcollision()
|
||||
puck = collision.sourcenode.getdelegate(Puck)
|
||||
player = collision.opposingnode.getdelegate(PlayerSpaz,
|
||||
True).getplayer(Player)
|
||||
if player and puck:
|
||||
puck.last_players_to_touch[player.team.id] = player
|
||||
try:
|
||||
puck = collision.sourcenode.getdelegate(Puck, True)
|
||||
player = collision.opposingnode.getdelegate(PlayerSpaz,
|
||||
True).getplayer(
|
||||
Player, True)
|
||||
except ba.NotFoundError:
|
||||
return
|
||||
|
||||
puck.last_players_to_touch[player.team.id] = player
|
||||
|
||||
def _kill_puck(self) -> None:
|
||||
self._puck = None
|
||||
|
||||
@ -247,9 +247,10 @@ class KingOfTheHillGame(ba.TeamGameActivity[Player, Team]):
|
||||
ba.playsound(self._swipsound)
|
||||
|
||||
def _handle_player_flag_region_collide(self, colliding: bool) -> None:
|
||||
player = ba.getcollision().opposingnode.getdelegate(
|
||||
PlayerSpaz, True).getplayer(Player)
|
||||
if not player:
|
||||
try:
|
||||
player = ba.getcollision().opposingnode.getdelegate(
|
||||
PlayerSpaz, True).getplayer(Player, True)
|
||||
except ba.NotFoundError:
|
||||
return
|
||||
|
||||
# Different parts of us can collide so a single value isn't enough
|
||||
|
||||
@ -1196,8 +1196,7 @@ class OnslaughtGame(ba.CoopGameActivity[Player, Team]):
|
||||
def handlemessage(self, msg: Any) -> Any:
|
||||
|
||||
if isinstance(msg, PlayerSpazHurtMessage):
|
||||
player = msg.spaz.getplayer(Player, doraise=True)
|
||||
player.has_been_hurt = True
|
||||
msg.spaz.getplayer(Player, True).has_been_hurt = True
|
||||
self._a_player_has_been_hurt = True
|
||||
|
||||
elif isinstance(msg, ba.PlayerScoredMessage):
|
||||
|
||||
@ -231,11 +231,12 @@ class RaceGame(ba.TeamGameActivity[Player, Team]):
|
||||
# pylint: disable=too-many-branches
|
||||
# pylint: disable=too-many-nested-blocks
|
||||
collision = ba.getcollision()
|
||||
region = collision.sourcenode.getdelegate(RaceRegion)
|
||||
playerspaz = collision.opposingnode.getdelegate(PlayerSpaz,
|
||||
doraise=False)
|
||||
player = playerspaz.getplayer(Player) if playerspaz else None
|
||||
if not player or not region:
|
||||
try:
|
||||
region = collision.sourcenode.getdelegate(RaceRegion, True)
|
||||
player = collision.opposingnode.getdelegate(PlayerSpaz,
|
||||
True).getplayer(
|
||||
Player, True)
|
||||
except ba.NotFoundError:
|
||||
return
|
||||
|
||||
last_region = player.last_region
|
||||
|
||||
@ -920,14 +920,14 @@ class MainMenuSession(ba.Session):
|
||||
|
||||
super().__init__([self._activity_deps])
|
||||
self._locked = False
|
||||
self.set_activity(ba.new_activity(MainMenuActivity))
|
||||
self.setactivity(ba.new_activity(MainMenuActivity))
|
||||
|
||||
def on_activity_end(self, activity: ba.Activity, results: Any) -> None:
|
||||
if self._locked:
|
||||
_ba.unlock_all_input()
|
||||
|
||||
# Any ending activity leads us into the main menu one.
|
||||
self.set_activity(ba.new_activity(MainMenuActivity))
|
||||
self.setactivity(ba.new_activity(MainMenuActivity))
|
||||
|
||||
def on_player_request(self, player: ba.SessionPlayer) -> bool:
|
||||
# Reject all player requests.
|
||||
|
||||
@ -2412,7 +2412,7 @@ class TutorialActivity(ba.Activity[Player, Team]):
|
||||
super().on_player_join(player)
|
||||
|
||||
# We just wanna know if this player presses anything.
|
||||
player.assign_input_call(
|
||||
player.assigninput(
|
||||
('jumpPress', 'punchPress', 'bombPress', 'pickUpPress'),
|
||||
ba.Call(self._player_pressed_button, player))
|
||||
|
||||
|
||||
@ -254,13 +254,13 @@ class PlaylistEditWindow(ba.Window):
|
||||
|
||||
def _add(self) -> None:
|
||||
# Store list name then tell the session to perform an add.
|
||||
self._editcontroller.set_name(
|
||||
self._editcontroller.setname(
|
||||
cast(str, ba.textwidget(query=self._text_field)))
|
||||
self._editcontroller.add_game_pressed()
|
||||
|
||||
def _edit(self) -> None:
|
||||
# Store list name then tell the session to perform an add.
|
||||
self._editcontroller.set_name(
|
||||
self._editcontroller.setname(
|
||||
cast(str, ba.textwidget(query=self._text_field)))
|
||||
self._editcontroller.edit_game_pressed()
|
||||
|
||||
|
||||
@ -119,7 +119,7 @@ class PlaylistEditController:
|
||||
"""(internal)"""
|
||||
return self._name
|
||||
|
||||
def set_name(self, name: str) -> None:
|
||||
def setname(self, name: str) -> None:
|
||||
"""(internal)"""
|
||||
self._name = name
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<!-- THIS FILE IS AUTO GENERATED; DO NOT EDIT BY HAND -->
|
||||
<h4><em>last updated on 2020-05-30 for Ballistica version 1.5.0 build 20036</em></h4>
|
||||
<h4><em>last updated on 2020-05-31 for Ballistica version 1.5.0 build 20036</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>
|
||||
@ -343,7 +343,7 @@ actually award achievements.</p>
|
||||
can overlap during transitions.</p>
|
||||
|
||||
<h3>Attributes:</h3>
|
||||
<h5><a href="#attr_ba_Activity__expired">expired</a>, <a href="#attr_ba_Activity__globalsnode">globalsnode</a>, <a href="#attr_ba_Activity__players">players</a>, <a href="#attr_ba_Activity__playertype">playertype</a>, <a href="#attr_ba_Activity__session">session</a>, <a href="#attr_ba_Activity__settings_raw">settings_raw</a>, <a href="#attr_ba_Activity__stats">stats</a>, <a href="#attr_ba_Activity__teams">teams</a>, <a href="#attr_ba_Activity__teamtype">teamtype</a></h5>
|
||||
<h5><a href="#attr_ba_Activity__expired">expired</a>, <a href="#attr_ba_Activity__gamedata">gamedata</a>, <a href="#attr_ba_Activity__globalsnode">globalsnode</a>, <a href="#attr_ba_Activity__players">players</a>, <a href="#attr_ba_Activity__playertype">playertype</a>, <a href="#attr_ba_Activity__session">session</a>, <a href="#attr_ba_Activity__settings_raw">settings_raw</a>, <a href="#attr_ba_Activity__stats">stats</a>, <a href="#attr_ba_Activity__teams">teams</a>, <a href="#attr_ba_Activity__teamtype">teamtype</a></h5>
|
||||
<dl>
|
||||
<dt><h4><a name="attr_ba_Activity__expired">expired</a></h4></dt><dd>
|
||||
<p><span>bool</span></p>
|
||||
@ -353,6 +353,14 @@ actually award achievements.</p>
|
||||
At this point no new nodes, timers, etc should be made,
|
||||
run, etc, and the activity should be considered a 'zombie'.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="attr_ba_Activity__gamedata">gamedata</a></h4></dt><dd>
|
||||
<p><span>dict</span></p>
|
||||
<p>Entities needing to store simple data with an activity can put it
|
||||
here. This dict will be deleted when the activity expires, so contained
|
||||
objects generally do not need to worry about handling expired
|
||||
activities.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="attr_ba_Activity__globalsnode">globalsnode</a></h4></dt><dd>
|
||||
<p><span><a href="#class_ba_Node">ba.Node</a></span></p>
|
||||
@ -419,7 +427,7 @@ regardless of the player count).</p>
|
||||
|
||||
<p>Creates an Activity in the current <a href="#class_ba_Session">ba.Session</a>.</p>
|
||||
|
||||
<p>The activity will not be actually run until <a href="#method_ba_Session__set_activity">ba.Session.set_activity</a>()
|
||||
<p>The activity will not be actually run until <a href="#method_ba_Session__setactivity">ba.Session.setactivity</a>()
|
||||
is called. 'settings' should be a dict of key/value pairs specific
|
||||
to the activity.</p>
|
||||
|
||||
@ -1288,29 +1296,34 @@ mycall()</pre>
|
||||
</p>
|
||||
|
||||
<h3>Attributes:</h3>
|
||||
<h5><a href="#attr_ba_Chooser__lobby">lobby</a>, <a href="#attr_ba_Chooser__player">player</a>, <a href="#attr_ba_Chooser__ready">ready</a></h5>
|
||||
<h5><a href="#attr_ba_Chooser__lobby">lobby</a>, <a href="#attr_ba_Chooser__ready">ready</a>, <a href="#attr_ba_Chooser__sessionplayer">sessionplayer</a>, <a href="#attr_ba_Chooser__sessionteam">sessionteam</a></h5>
|
||||
<dl>
|
||||
<dt><h4><a name="attr_ba_Chooser__lobby">lobby</a></h4></dt><dd>
|
||||
<p><span><a href="#class_ba_Lobby">ba.Lobby</a></span></p>
|
||||
<p>The chooser's <a href="#class_ba_Lobby">ba.Lobby</a>.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="attr_ba_Chooser__player">player</a></h4></dt><dd>
|
||||
<p><span><a href="#class_ba_SessionPlayer">ba.SessionPlayer</a></span></p>
|
||||
<p>The <a href="#class_ba_Player">ba.Player</a> associated with this chooser.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="attr_ba_Chooser__ready">ready</a></h4></dt><dd>
|
||||
<p><span>bool</span></p>
|
||||
<p>Whether this chooser is checked in as ready.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="attr_ba_Chooser__sessionplayer">sessionplayer</a></h4></dt><dd>
|
||||
<p><span><a href="#class_ba_SessionPlayer">ba.SessionPlayer</a></span></p>
|
||||
<p>The <a href="#class_ba_SessionPlayer">ba.SessionPlayer</a> associated with this chooser.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="attr_ba_Chooser__sessionteam">sessionteam</a></h4></dt><dd>
|
||||
<p><span><a href="#class_ba_SessionTeam">ba.SessionTeam</a></span></p>
|
||||
<p>Return this chooser's currently selected <a href="#class_ba_SessionTeam">ba.SessionTeam</a>.</p>
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Methods:</h3>
|
||||
<h5><a href="#method_ba_Chooser____init__"><constructor></a>, <a href="#method_ba_Chooser__get_character_name">get_character_name()</a>, <a href="#method_ba_Chooser__get_color">get_color()</a>, <a href="#method_ba_Chooser__get_highlight">get_highlight()</a>, <a href="#method_ba_Chooser__get_lobby">get_lobby()</a>, <a href="#method_ba_Chooser__get_team">get_team()</a>, <a href="#method_ba_Chooser__getplayer">getplayer()</a>, <a href="#method_ba_Chooser__handlemessage">handlemessage()</a>, <a href="#method_ba_Chooser__reload_profiles">reload_profiles()</a>, <a href="#method_ba_Chooser__update_from_profile">update_from_profile()</a>, <a href="#method_ba_Chooser__update_position">update_position()</a></h5>
|
||||
<h5><a href="#method_ba_Chooser____init__"><constructor></a>, <a href="#method_ba_Chooser__get_character_name">get_character_name()</a>, <a href="#method_ba_Chooser__get_color">get_color()</a>, <a href="#method_ba_Chooser__get_highlight">get_highlight()</a>, <a href="#method_ba_Chooser__get_lobby">get_lobby()</a>, <a href="#method_ba_Chooser__getplayer">getplayer()</a>, <a href="#method_ba_Chooser__handlemessage">handlemessage()</a>, <a href="#method_ba_Chooser__reload_profiles">reload_profiles()</a>, <a href="#method_ba_Chooser__update_from_profile">update_from_profile()</a>, <a href="#method_ba_Chooser__update_position">update_position()</a></h5>
|
||||
<dl>
|
||||
<dt><h4><a name="method_ba_Chooser____init__"><constructor></a></dt></h4><dd>
|
||||
<p><span>ba.Chooser(vpos: float, player: _<a href="#class_ba_SessionPlayer">ba.SessionPlayer</a>, lobby: "Lobby")</span></p>
|
||||
<p><span>ba.Chooser(vpos: float, sessionplayer: _<a href="#class_ba_SessionPlayer">ba.SessionPlayer</a>, lobby: "Lobby")</span></p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="method_ba_Chooser__get_character_name">get_character_name()</a></dt></h4><dd>
|
||||
@ -1336,12 +1349,6 @@ mycall()</pre>
|
||||
|
||||
<p>Return this chooser's lobby if it still exists; otherwise None.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="method_ba_Chooser__get_team">get_team()</a></dt></h4><dd>
|
||||
<p><span>get_team(self) -> <a href="#class_ba_SessionTeam">ba.SessionTeam</a></span></p>
|
||||
|
||||
<p>Return this chooser's selected <a href="#class_ba_Team">ba.Team</a>.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="method_ba_Chooser__getplayer">getplayer()</a></dt></h4><dd>
|
||||
<p><span>getplayer(self) -> <a href="#class_ba_SessionPlayer">ba.SessionPlayer</a></span></p>
|
||||
@ -1545,7 +1552,7 @@ start_long_action(callback_when_done=<a href="#class_ba_ContextCall">ba.ContextC
|
||||
<h3>Attributes Inherited:</h3>
|
||||
<h5><a href="#attr_ba_Activity__players">players</a>, <a href="#attr_ba_Activity__settings_raw">settings_raw</a>, <a href="#attr_ba_Activity__teams">teams</a></h5>
|
||||
<h3>Attributes Defined Here:</h3>
|
||||
<h5><a href="#attr_ba_CoopGameActivity__expired">expired</a>, <a href="#attr_ba_CoopGameActivity__globalsnode">globalsnode</a>, <a href="#attr_ba_CoopGameActivity__map">map</a>, <a href="#attr_ba_CoopGameActivity__playertype">playertype</a>, <a href="#attr_ba_CoopGameActivity__session">session</a>, <a href="#attr_ba_CoopGameActivity__stats">stats</a>, <a href="#attr_ba_CoopGameActivity__teamtype">teamtype</a></h5>
|
||||
<h5><a href="#attr_ba_CoopGameActivity__expired">expired</a>, <a href="#attr_ba_CoopGameActivity__gamedata">gamedata</a>, <a href="#attr_ba_CoopGameActivity__globalsnode">globalsnode</a>, <a href="#attr_ba_CoopGameActivity__map">map</a>, <a href="#attr_ba_CoopGameActivity__playertype">playertype</a>, <a href="#attr_ba_CoopGameActivity__session">session</a>, <a href="#attr_ba_CoopGameActivity__stats">stats</a>, <a href="#attr_ba_CoopGameActivity__teamtype">teamtype</a></h5>
|
||||
<dl>
|
||||
<dt><h4><a name="attr_ba_CoopGameActivity__expired">expired</a></h4></dt><dd>
|
||||
<p><span>bool</span></p>
|
||||
@ -1555,6 +1562,14 @@ start_long_action(callback_when_done=<a href="#class_ba_ContextCall">ba.ContextC
|
||||
At this point no new nodes, timers, etc should be made,
|
||||
run, etc, and the activity should be considered a 'zombie'.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="attr_ba_CoopGameActivity__gamedata">gamedata</a></h4></dt><dd>
|
||||
<p><span>dict</span></p>
|
||||
<p>Entities needing to store simple data with an activity can put it
|
||||
here. This dict will be deleted when the activity expires, so contained
|
||||
objects generally do not need to worry about handling expired
|
||||
activities.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="attr_ba_CoopGameActivity__globalsnode">globalsnode</a></h4></dt><dd>
|
||||
<p><span><a href="#class_ba_Node">ba.Node</a></span></p>
|
||||
@ -1595,7 +1610,7 @@ start_long_action(callback_when_done=<a href="#class_ba_ContextCall">ba.ContextC
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Methods Inherited:</h3>
|
||||
<h5><a href="#method_ba_GameActivity__add_actor_weak_ref">add_actor_weak_ref()</a>, <a href="#method_ba_GameActivity__add_player">add_player()</a>, <a href="#method_ba_GameActivity__add_team">add_team()</a>, <a href="#method_ba_GameActivity__begin">begin()</a>, <a href="#method_ba_GameActivity__continue_or_end_game">continue_or_end_game()</a>, <a href="#method_ba_GameActivity__create_player">create_player()</a>, <a href="#method_ba_GameActivity__create_settings_ui">create_settings_ui()</a>, <a href="#method_ba_GameActivity__create_team">create_team()</a>, <a href="#method_ba_GameActivity__dep_is_present">dep_is_present()</a>, <a href="#method_ba_GameActivity__destroy">destroy()</a>, <a href="#method_ba_GameActivity__end">end()</a>, <a href="#method_ba_GameActivity__end_game">end_game()</a>, <a href="#method_ba_GameActivity__get_description">get_description()</a>, <a href="#method_ba_GameActivity__get_description_display_string">get_description_display_string()</a>, <a href="#method_ba_GameActivity__get_display_string">get_display_string()</a>, <a href="#method_ba_GameActivity__get_dynamic_deps">get_dynamic_deps()</a>, <a href="#method_ba_GameActivity__get_game_settings">get_game_settings()</a>, <a href="#method_ba_GameActivity__get_instance_description">get_instance_description()</a>, <a href="#method_ba_GameActivity__get_instance_description_short">get_instance_description_short()</a>, <a href="#method_ba_GameActivity__get_instance_display_string">get_instance_display_string()</a>, <a href="#method_ba_GameActivity__get_instance_scoreboard_display_string">get_instance_scoreboard_display_string()</a>, <a href="#method_ba_GameActivity__get_score_info">get_score_info()</a>, <a href="#method_ba_GameActivity__get_settings_display_string">get_settings_display_string()</a>, <a href="#method_ba_GameActivity__get_supported_maps">get_supported_maps()</a>, <a href="#method_ba_GameActivity__get_team_display_string">get_team_display_string()</a>, <a href="#method_ba_GameActivity__getname">getname()</a>, <a href="#method_ba_GameActivity__handlemessage">handlemessage()</a>, <a href="#method_ba_GameActivity__has_begun">has_begun()</a>, <a href="#method_ba_GameActivity__has_ended">has_ended()</a>, <a href="#method_ba_GameActivity__has_transitioned_in">has_transitioned_in()</a>, <a href="#method_ba_GameActivity__is_transitioning_out">is_transitioning_out()</a>, <a href="#method_ba_GameActivity__is_waiting_for_continue">is_waiting_for_continue()</a>, <a href="#method_ba_GameActivity__on_continue">on_continue()</a>, <a href="#method_ba_GameActivity__on_expire">on_expire()</a>, <a href="#method_ba_GameActivity__on_player_join">on_player_join()</a>, <a href="#method_ba_GameActivity__on_player_leave">on_player_leave()</a>, <a href="#method_ba_GameActivity__on_team_join">on_team_join()</a>, <a href="#method_ba_GameActivity__on_team_leave">on_team_leave()</a>, <a href="#method_ba_GameActivity__on_transition_in">on_transition_in()</a>, <a href="#method_ba_GameActivity__on_transition_out">on_transition_out()</a>, <a href="#method_ba_GameActivity__remove_player">remove_player()</a>, <a href="#method_ba_GameActivity__remove_team">remove_team()</a>, <a href="#method_ba_GameActivity__respawn_player">respawn_player()</a>, <a href="#method_ba_GameActivity__retain_actor">retain_actor()</a>, <a href="#method_ba_GameActivity__set_has_ended">set_has_ended()</a>, <a href="#method_ba_GameActivity__setup_standard_powerup_drops">setup_standard_powerup_drops()</a>, <a href="#method_ba_GameActivity__setup_standard_time_limit">setup_standard_time_limit()</a>, <a href="#method_ba_GameActivity__show_zoom_message">show_zoom_message()</a>, <a href="#method_ba_GameActivity__spawn_player">spawn_player()</a>, <a href="#method_ba_GameActivity__spawn_player_if_exists">spawn_player_if_exists()</a>, <a href="#method_ba_GameActivity__transition_in">transition_in()</a>, <a href="#method_ba_GameActivity__transition_out">transition_out()</a></h5>
|
||||
<h5><a href="#method_ba_GameActivity__add_actor_weak_ref">add_actor_weak_ref()</a>, <a href="#method_ba_GameActivity__add_player">add_player()</a>, <a href="#method_ba_GameActivity__add_team">add_team()</a>, <a href="#method_ba_GameActivity__begin">begin()</a>, <a href="#method_ba_GameActivity__continue_or_end_game">continue_or_end_game()</a>, <a href="#method_ba_GameActivity__create_player">create_player()</a>, <a href="#method_ba_GameActivity__create_settings_ui">create_settings_ui()</a>, <a href="#method_ba_GameActivity__create_team">create_team()</a>, <a href="#method_ba_GameActivity__dep_is_present">dep_is_present()</a>, <a href="#method_ba_GameActivity__end">end()</a>, <a href="#method_ba_GameActivity__end_game">end_game()</a>, <a href="#method_ba_GameActivity__expire">expire()</a>, <a href="#method_ba_GameActivity__get_description">get_description()</a>, <a href="#method_ba_GameActivity__get_description_display_string">get_description_display_string()</a>, <a href="#method_ba_GameActivity__get_display_string">get_display_string()</a>, <a href="#method_ba_GameActivity__get_dynamic_deps">get_dynamic_deps()</a>, <a href="#method_ba_GameActivity__get_game_settings">get_game_settings()</a>, <a href="#method_ba_GameActivity__get_instance_description">get_instance_description()</a>, <a href="#method_ba_GameActivity__get_instance_description_short">get_instance_description_short()</a>, <a href="#method_ba_GameActivity__get_instance_display_string">get_instance_display_string()</a>, <a href="#method_ba_GameActivity__get_instance_scoreboard_display_string">get_instance_scoreboard_display_string()</a>, <a href="#method_ba_GameActivity__get_score_info">get_score_info()</a>, <a href="#method_ba_GameActivity__get_settings_display_string">get_settings_display_string()</a>, <a href="#method_ba_GameActivity__get_supported_maps">get_supported_maps()</a>, <a href="#method_ba_GameActivity__get_team_display_string">get_team_display_string()</a>, <a href="#method_ba_GameActivity__getname">getname()</a>, <a href="#method_ba_GameActivity__handlemessage">handlemessage()</a>, <a href="#method_ba_GameActivity__has_begun">has_begun()</a>, <a href="#method_ba_GameActivity__has_ended">has_ended()</a>, <a href="#method_ba_GameActivity__has_transitioned_in">has_transitioned_in()</a>, <a href="#method_ba_GameActivity__is_transitioning_out">is_transitioning_out()</a>, <a href="#method_ba_GameActivity__is_waiting_for_continue">is_waiting_for_continue()</a>, <a href="#method_ba_GameActivity__on_continue">on_continue()</a>, <a href="#method_ba_GameActivity__on_expire">on_expire()</a>, <a href="#method_ba_GameActivity__on_player_join">on_player_join()</a>, <a href="#method_ba_GameActivity__on_player_leave">on_player_leave()</a>, <a href="#method_ba_GameActivity__on_team_join">on_team_join()</a>, <a href="#method_ba_GameActivity__on_team_leave">on_team_leave()</a>, <a href="#method_ba_GameActivity__on_transition_in">on_transition_in()</a>, <a href="#method_ba_GameActivity__on_transition_out">on_transition_out()</a>, <a href="#method_ba_GameActivity__remove_player">remove_player()</a>, <a href="#method_ba_GameActivity__remove_team">remove_team()</a>, <a href="#method_ba_GameActivity__respawn_player">respawn_player()</a>, <a href="#method_ba_GameActivity__retain_actor">retain_actor()</a>, <a href="#method_ba_GameActivity__set_has_ended">set_has_ended()</a>, <a href="#method_ba_GameActivity__setup_standard_powerup_drops">setup_standard_powerup_drops()</a>, <a href="#method_ba_GameActivity__setup_standard_time_limit">setup_standard_time_limit()</a>, <a href="#method_ba_GameActivity__show_zoom_message">show_zoom_message()</a>, <a href="#method_ba_GameActivity__spawn_player">spawn_player()</a>, <a href="#method_ba_GameActivity__spawn_player_if_exists">spawn_player_if_exists()</a>, <a href="#method_ba_GameActivity__transition_in">transition_in()</a>, <a href="#method_ba_GameActivity__transition_out">transition_out()</a></h5>
|
||||
<h3>Methods Defined or Overridden:</h3>
|
||||
<h5><a href="#method_ba_CoopGameActivity____init__"><constructor></a>, <a href="#method_ba_CoopGameActivity__celebrate">celebrate()</a>, <a href="#method_ba_CoopGameActivity__fade_to_red">fade_to_red()</a>, <a href="#method_ba_CoopGameActivity__get_score_type">get_score_type()</a>, <a href="#method_ba_CoopGameActivity__on_begin">on_begin()</a>, <a href="#method_ba_CoopGameActivity__setup_low_life_warning_sound">setup_low_life_warning_sound()</a>, <a href="#method_ba_CoopGameActivity__spawn_player_spaz">spawn_player_spaz()</a>, <a href="#method_ba_CoopGameActivity__supports_session_type">supports_session_type()</a></h5>
|
||||
<dl>
|
||||
@ -1685,7 +1700,7 @@ 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__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>
|
||||
<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__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__setactivity">setactivity()</a>, <a href="#method_ba_Session__transitioning_out_activity_was_freed">transitioning_out_activity_was_freed()</a></h5>
|
||||
<h3>Methods Defined or Overridden:</h3>
|
||||
<h5><a href="#method_ba_CoopSession____init__"><constructor></a>, <a href="#method_ba_CoopSession__get_current_game_instance">get_current_game_instance()</a>, <a href="#method_ba_CoopSession__get_custom_menu_entries">get_custom_menu_entries()</a>, <a href="#method_ba_CoopSession__on_activity_end">on_activity_end()</a>, <a href="#method_ba_CoopSession__on_player_leave">on_player_leave()</a>, <a href="#method_ba_CoopSession__restart">restart()</a></h5>
|
||||
<dl>
|
||||
@ -2036,7 +2051,7 @@ its time with lingering corpses, sound effects, etc.</p>
|
||||
</dd>
|
||||
</dl>
|
||||
<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__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>
|
||||
<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__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__setactivity">setactivity()</a>, <a href="#method_ba_MultiTeamSession__transitioning_out_activity_was_freed">transitioning_out_activity_was_freed()</a></h5>
|
||||
<h3>Methods Defined or Overridden:</h3>
|
||||
<dl>
|
||||
<dt><h4><a name="method_ba_DualTeamSession____init__"><constructor></a></dt></h4><dd>
|
||||
@ -2082,7 +2097,7 @@ its time with lingering corpses, sound effects, etc.</p>
|
||||
</dd>
|
||||
</dl>
|
||||
<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__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>
|
||||
<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__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__setactivity">setactivity()</a>, <a href="#method_ba_MultiTeamSession__transitioning_out_activity_was_freed">transitioning_out_activity_was_freed()</a></h5>
|
||||
<h3>Methods Defined or Overridden:</h3>
|
||||
<h5><a href="#method_ba_FreeForAllSession____init__"><constructor></a>, <a href="#method_ba_FreeForAllSession__get_ffa_point_awards">get_ffa_point_awards()</a></h5>
|
||||
<dl>
|
||||
@ -2130,7 +2145,7 @@ its time with lingering corpses, sound effects, etc.</p>
|
||||
<h3>Attributes Inherited:</h3>
|
||||
<h5><a href="#attr_ba_Activity__players">players</a>, <a href="#attr_ba_Activity__settings_raw">settings_raw</a>, <a href="#attr_ba_Activity__teams">teams</a></h5>
|
||||
<h3>Attributes Defined Here:</h3>
|
||||
<h5><a href="#attr_ba_GameActivity__expired">expired</a>, <a href="#attr_ba_GameActivity__globalsnode">globalsnode</a>, <a href="#attr_ba_GameActivity__map">map</a>, <a href="#attr_ba_GameActivity__playertype">playertype</a>, <a href="#attr_ba_GameActivity__session">session</a>, <a href="#attr_ba_GameActivity__stats">stats</a>, <a href="#attr_ba_GameActivity__teamtype">teamtype</a></h5>
|
||||
<h5><a href="#attr_ba_GameActivity__expired">expired</a>, <a href="#attr_ba_GameActivity__gamedata">gamedata</a>, <a href="#attr_ba_GameActivity__globalsnode">globalsnode</a>, <a href="#attr_ba_GameActivity__map">map</a>, <a href="#attr_ba_GameActivity__playertype">playertype</a>, <a href="#attr_ba_GameActivity__session">session</a>, <a href="#attr_ba_GameActivity__stats">stats</a>, <a href="#attr_ba_GameActivity__teamtype">teamtype</a></h5>
|
||||
<dl>
|
||||
<dt><h4><a name="attr_ba_GameActivity__expired">expired</a></h4></dt><dd>
|
||||
<p><span>bool</span></p>
|
||||
@ -2140,6 +2155,14 @@ its time with lingering corpses, sound effects, etc.</p>
|
||||
At this point no new nodes, timers, etc should be made,
|
||||
run, etc, and the activity should be considered a 'zombie'.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="attr_ba_GameActivity__gamedata">gamedata</a></h4></dt><dd>
|
||||
<p><span>dict</span></p>
|
||||
<p>Entities needing to store simple data with an activity can put it
|
||||
here. This dict will be deleted when the activity expires, so contained
|
||||
objects generally do not need to worry about handling expired
|
||||
activities.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="attr_ba_GameActivity__globalsnode">globalsnode</a></h4></dt><dd>
|
||||
<p><span><a href="#class_ba_Node">ba.Node</a></span></p>
|
||||
@ -2180,7 +2203,7 @@ its time with lingering corpses, sound effects, etc.</p>
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Methods Inherited:</h3>
|
||||
<h5><a href="#method_ba_Activity__add_actor_weak_ref">add_actor_weak_ref()</a>, <a href="#method_ba_Activity__add_player">add_player()</a>, <a href="#method_ba_Activity__add_team">add_team()</a>, <a href="#method_ba_Activity__begin">begin()</a>, <a href="#method_ba_Activity__create_player">create_player()</a>, <a href="#method_ba_Activity__create_team">create_team()</a>, <a href="#method_ba_Activity__dep_is_present">dep_is_present()</a>, <a href="#method_ba_Activity__destroy">destroy()</a>, <a href="#method_ba_Activity__get_dynamic_deps">get_dynamic_deps()</a>, <a href="#method_ba_Activity__has_begun">has_begun()</a>, <a href="#method_ba_Activity__has_ended">has_ended()</a>, <a href="#method_ba_Activity__has_transitioned_in">has_transitioned_in()</a>, <a href="#method_ba_Activity__is_transitioning_out">is_transitioning_out()</a>, <a href="#method_ba_Activity__on_expire">on_expire()</a>, <a href="#method_ba_Activity__on_player_leave">on_player_leave()</a>, <a href="#method_ba_Activity__on_team_join">on_team_join()</a>, <a href="#method_ba_Activity__on_team_leave">on_team_leave()</a>, <a href="#method_ba_Activity__on_transition_out">on_transition_out()</a>, <a href="#method_ba_Activity__remove_player">remove_player()</a>, <a href="#method_ba_Activity__remove_team">remove_team()</a>, <a href="#method_ba_Activity__retain_actor">retain_actor()</a>, <a href="#method_ba_Activity__set_has_ended">set_has_ended()</a>, <a href="#method_ba_Activity__transition_in">transition_in()</a>, <a href="#method_ba_Activity__transition_out">transition_out()</a></h5>
|
||||
<h5><a href="#method_ba_Activity__add_actor_weak_ref">add_actor_weak_ref()</a>, <a href="#method_ba_Activity__add_player">add_player()</a>, <a href="#method_ba_Activity__add_team">add_team()</a>, <a href="#method_ba_Activity__begin">begin()</a>, <a href="#method_ba_Activity__create_player">create_player()</a>, <a href="#method_ba_Activity__create_team">create_team()</a>, <a href="#method_ba_Activity__dep_is_present">dep_is_present()</a>, <a href="#method_ba_Activity__expire">expire()</a>, <a href="#method_ba_Activity__get_dynamic_deps">get_dynamic_deps()</a>, <a href="#method_ba_Activity__has_begun">has_begun()</a>, <a href="#method_ba_Activity__has_ended">has_ended()</a>, <a href="#method_ba_Activity__has_transitioned_in">has_transitioned_in()</a>, <a href="#method_ba_Activity__is_transitioning_out">is_transitioning_out()</a>, <a href="#method_ba_Activity__on_expire">on_expire()</a>, <a href="#method_ba_Activity__on_player_leave">on_player_leave()</a>, <a href="#method_ba_Activity__on_team_join">on_team_join()</a>, <a href="#method_ba_Activity__on_team_leave">on_team_leave()</a>, <a href="#method_ba_Activity__on_transition_out">on_transition_out()</a>, <a href="#method_ba_Activity__remove_player">remove_player()</a>, <a href="#method_ba_Activity__remove_team">remove_team()</a>, <a href="#method_ba_Activity__retain_actor">retain_actor()</a>, <a href="#method_ba_Activity__set_has_ended">set_has_ended()</a>, <a href="#method_ba_Activity__transition_in">transition_in()</a>, <a href="#method_ba_Activity__transition_out">transition_out()</a></h5>
|
||||
<h3>Methods Defined or Overridden:</h3>
|
||||
<h5><a href="#method_ba_GameActivity____init__"><constructor></a>, <a href="#method_ba_GameActivity__continue_or_end_game">continue_or_end_game()</a>, <a href="#method_ba_GameActivity__create_settings_ui">create_settings_ui()</a>, <a href="#method_ba_GameActivity__end">end()</a>, <a href="#method_ba_GameActivity__end_game">end_game()</a>, <a href="#method_ba_GameActivity__get_description">get_description()</a>, <a href="#method_ba_GameActivity__get_description_display_string">get_description_display_string()</a>, <a href="#method_ba_GameActivity__get_display_string">get_display_string()</a>, <a href="#method_ba_GameActivity__get_game_settings">get_game_settings()</a>, <a href="#method_ba_GameActivity__get_instance_description">get_instance_description()</a>, <a href="#method_ba_GameActivity__get_instance_description_short">get_instance_description_short()</a>, <a href="#method_ba_GameActivity__get_instance_display_string">get_instance_display_string()</a>, <a href="#method_ba_GameActivity__get_instance_scoreboard_display_string">get_instance_scoreboard_display_string()</a>, <a href="#method_ba_GameActivity__get_score_info">get_score_info()</a>, <a href="#method_ba_GameActivity__get_settings_display_string">get_settings_display_string()</a>, <a href="#method_ba_GameActivity__get_supported_maps">get_supported_maps()</a>, <a href="#method_ba_GameActivity__get_team_display_string">get_team_display_string()</a>, <a href="#method_ba_GameActivity__getname">getname()</a>, <a href="#method_ba_GameActivity__handlemessage">handlemessage()</a>, <a href="#method_ba_GameActivity__is_waiting_for_continue">is_waiting_for_continue()</a>, <a href="#method_ba_GameActivity__on_begin">on_begin()</a>, <a href="#method_ba_GameActivity__on_continue">on_continue()</a>, <a href="#method_ba_GameActivity__on_player_join">on_player_join()</a>, <a href="#method_ba_GameActivity__on_transition_in">on_transition_in()</a>, <a href="#method_ba_GameActivity__respawn_player">respawn_player()</a>, <a href="#method_ba_GameActivity__setup_standard_powerup_drops">setup_standard_powerup_drops()</a>, <a href="#method_ba_GameActivity__setup_standard_time_limit">setup_standard_time_limit()</a>, <a href="#method_ba_GameActivity__show_zoom_message">show_zoom_message()</a>, <a href="#method_ba_GameActivity__spawn_player">spawn_player()</a>, <a href="#method_ba_GameActivity__spawn_player_if_exists">spawn_player_if_exists()</a>, <a href="#method_ba_GameActivity__spawn_player_spaz">spawn_player_spaz()</a>, <a href="#method_ba_GameActivity__supports_session_type">supports_session_type()</a></h5>
|
||||
<dl>
|
||||
@ -2828,11 +2851,11 @@ can be changed to separate its new high score lists/etc. from the old.</p>
|
||||
</p>
|
||||
|
||||
<h3>Attributes:</h3>
|
||||
<h5><a href="#attr_ba_Lobby__teams">teams</a>, <a href="#attr_ba_Lobby__use_team_colors">use_team_colors</a></h5>
|
||||
<h5><a href="#attr_ba_Lobby__sessionteams">sessionteams</a>, <a href="#attr_ba_Lobby__use_team_colors">use_team_colors</a></h5>
|
||||
<dl>
|
||||
<dt><h4><a name="attr_ba_Lobby__teams">teams</a></h4></dt><dd>
|
||||
<dt><h4><a name="attr_ba_Lobby__sessionteams">sessionteams</a></h4></dt><dd>
|
||||
<p><span>List[<a href="#class_ba_SessionTeam">ba.SessionTeam</a>]</span></p>
|
||||
<p>Teams available in this lobby.</p>
|
||||
<p><a href="#class_ba_SessionTeam">ba.SessionTeams</a> available in this lobby.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="attr_ba_Lobby__use_team_colors">use_team_colors</a></h4></dt><dd>
|
||||
@ -2851,7 +2874,7 @@ can be changed to separate its new high score lists/etc. from the old.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="method_ba_Lobby__add_chooser">add_chooser()</a></dt></h4><dd>
|
||||
<p><span>add_chooser(self, player: <a href="#class_ba_SessionPlayer">ba.SessionPlayer</a>) -> None</span></p>
|
||||
<p><span>add_chooser(self, sessionplayer: <a href="#class_ba_SessionPlayer">ba.SessionPlayer</a>) -> None</span></p>
|
||||
|
||||
<p>Add a chooser to the lobby for the provided player.</p>
|
||||
|
||||
@ -3367,7 +3390,7 @@ Use <a href="#function_ba_getmodel">ba.getmodel</a>() to instantiate one.</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__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__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>
|
||||
<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__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__setactivity">setactivity()</a>, <a href="#method_ba_Session__transitioning_out_activity_was_freed">transitioning_out_activity_was_freed()</a></h5>
|
||||
<h3>Methods Defined or Overridden:</h3>
|
||||
<h5><a href="#method_ba_MultiTeamSession____init__"><constructor></a>, <a href="#method_ba_MultiTeamSession__announce_game_results">announce_game_results()</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__on_activity_end">on_activity_end()</a>, <a href="#method_ba_MultiTeamSession__on_team_join">on_team_join()</a></h5>
|
||||
<dl>
|
||||
@ -3843,13 +3866,29 @@ even if myactor is set to None.</p>
|
||||
|
||||
<p>Category: <a href="#class_category_Gameplay_Classes">Gameplay Classes</a></p>
|
||||
|
||||
<p> These correspond to <a href="#class_ba_SessionPlayer">ba.SessionPlayer</a> objects, but are created per activity
|
||||
so that the activity can use its own custom player subclass.
|
||||
</p>
|
||||
<p> These correspond to <a href="#class_ba_SessionPlayer">ba.SessionPlayer</a> objects, but are associated with a
|
||||
single <a href="#class_ba_Activity">ba.Activity</a> instance. This allows activities to specify their
|
||||
own custom <a href="#class_ba_Player">ba.Player</a> types.</p>
|
||||
|
||||
<h3>Attributes:</h3>
|
||||
<h5><a href="#attr_ba_Player__node">node</a>, <a href="#attr_ba_Player__position">position</a>, <a href="#attr_ba_Player__sessionplayer">sessionplayer</a></h5>
|
||||
<h5><a href="#attr_ba_Player__actor">actor</a>, <a href="#attr_ba_Player__gamedata">gamedata</a>, <a href="#attr_ba_Player__node">node</a>, <a href="#attr_ba_Player__position">position</a>, <a href="#attr_ba_Player__sessionplayer">sessionplayer</a>, <a href="#attr_ba_Player__team">team</a></h5>
|
||||
<dl>
|
||||
<dt><h4><a name="attr_ba_Player__actor">actor</a></h4></dt><dd>
|
||||
<p><span>Optional[<a href="#class_ba_Actor">ba.Actor</a>]</span></p>
|
||||
<p>The <a href="#class_ba_Actor">ba.Actor</a> associated with the player.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="attr_ba_Player__gamedata">gamedata</a></h4></dt><dd>
|
||||
<p><span>dict</span></p>
|
||||
<p>Arbitrary values associated with the player.
|
||||
Though it is encouraged that most player values be properly defined
|
||||
on the <a href="#class_ba_Player">ba.Player</a> subclass, it may be useful for player-agnostic
|
||||
objects to store values here. This dict is cleared when the player
|
||||
leaves or expires so objects stored here will be disposed of at
|
||||
the expected time, unlike the Player instance itself which may
|
||||
continue to be referenced after it is no longer part of the game.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="attr_ba_Player__node">node</a></h4></dt><dd>
|
||||
<p><span><a href="#class_ba_Node">ba.Node</a></span></p>
|
||||
<p>A <a href="#class_ba_Node">ba.Node</a> of type 'player' associated with this Player.</p>
|
||||
@ -3859,10 +3898,9 @@ even if myactor is set to None.</p>
|
||||
</dd>
|
||||
<dt><h4><a name="attr_ba_Player__position">position</a></h4></dt><dd>
|
||||
<p><span><a href="#class_ba_Vec3">ba.Vec3</a></span></p>
|
||||
<p>The position of the player, as defined by its current Actor.</p>
|
||||
<p>The position of the player, as defined by its current <a href="#class_ba_Actor">ba.Actor</a>.</p>
|
||||
|
||||
<p> This value should not be used when the player has no Actor, as
|
||||
it is undefined in that case.</p>
|
||||
<p> This value is undefined when the player has no Actor.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="attr_ba_Player__sessionplayer">sessionplayer</a></h4></dt><dd>
|
||||
@ -3871,15 +3909,20 @@ even if myactor is set to None.</p>
|
||||
|
||||
<p> Throws a <a href="#class_ba_SessionPlayerNotFoundError">ba.SessionPlayerNotFoundError</a> if it does not exist.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="attr_ba_Player__team">team</a></h4></dt><dd>
|
||||
<p><span>TeamType</span></p>
|
||||
<p>The <a href="#class_ba_Team">ba.Team</a> for this player.</p>
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Methods:</h3>
|
||||
<h5><a href="#method_ba_Player__assign_input_call">assign_input_call()</a>, <a href="#method_ba_Player__exists">exists()</a>, <a href="#method_ba_Player__get_icon">get_icon()</a>, <a href="#method_ba_Player__getname">getname()</a>, <a href="#method_ba_Player__is_alive">is_alive()</a>, <a href="#method_ba_Player__reset_input">reset_input()</a></h5>
|
||||
<h5><a href="#method_ba_Player__assigninput">assigninput()</a>, <a href="#method_ba_Player__exists">exists()</a>, <a href="#method_ba_Player__get_icon">get_icon()</a>, <a href="#method_ba_Player__getname">getname()</a>, <a href="#method_ba_Player__is_alive">is_alive()</a>, <a href="#method_ba_Player__on_expire">on_expire()</a>, <a href="#method_ba_Player__resetinput">resetinput()</a></h5>
|
||||
<dl>
|
||||
<dt><h4><a name="method_ba_Player__assign_input_call">assign_input_call()</a></dt></h4><dd>
|
||||
<p><span>assign_input_call(self, inputtype: Union[str, Tuple[str, ...]], call: Callable) -> None</span></p>
|
||||
<dt><h4><a name="method_ba_Player__assigninput">assigninput()</a></dt></h4><dd>
|
||||
<p><span>assigninput(self, inputtype: Union[str, Tuple[str, ...]], call: Callable) -> None</span></p>
|
||||
|
||||
<p>assign_input_call(type: Union[str, Tuple[str, ...]],
|
||||
<p>assigninput(type: Union[str, Tuple[str, ...]],
|
||||
call: Callable) -> None</p>
|
||||
|
||||
<p>Set the python callable to be run for one or more types of input.
|
||||
@ -3896,7 +3939,10 @@ Valid type values are: 'jumpPress', 'jumpRelease', 'punchPress',
|
||||
|
||||
<p>Whether the underlying player still exists.</p>
|
||||
|
||||
<p>Most functionality will fail on a nonexistent player.
|
||||
<p>This will return False if the underlying <a href="#class_ba_SessionPlayer">ba.SessionPlayer</a> has
|
||||
left the game or if the <a href="#class_ba_Activity">ba.Activity</a> this player was associated
|
||||
with has ended.
|
||||
Most functionality will fail on a nonexistent player.
|
||||
Note that you can also use the boolean operator for this same
|
||||
functionality, so a statement such as "if player" will do
|
||||
the right thing both for Player objects and values of None.</p>
|
||||
@ -3928,10 +3974,21 @@ name may include an icon.</p>
|
||||
is_alive() method return True. False is returned otherwise.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="method_ba_Player__reset_input">reset_input()</a></dt></h4><dd>
|
||||
<p><span>reset_input(self) -> None</span></p>
|
||||
<dt><h4><a name="method_ba_Player__on_expire">on_expire()</a></dt></h4><dd>
|
||||
<p><span>on_expire(self) -> None</span></p>
|
||||
|
||||
<p>reset_input() -> None</p>
|
||||
<p>Can be overridden to handle player expiration.</p>
|
||||
|
||||
<p>The player expires when the Activity it is a part of expires.
|
||||
Expired players should no longer run any game logic (which will
|
||||
likely error). They should, however, remove any references to
|
||||
players/teams/games/etc. which could prevent them from being freed.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="method_ba_Player__resetinput">resetinput()</a></dt></h4><dd>
|
||||
<p><span>resetinput(self) -> None</span></p>
|
||||
|
||||
<p>resetinput() -> None</p>
|
||||
|
||||
<p>Clears out the player's assigned input actions.</p>
|
||||
|
||||
@ -4362,7 +4419,7 @@ player that joins.</p>
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Methods:</h3>
|
||||
<h5><a href="#method_ba_Session____init__"><constructor></a>, <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__on_activity_end">on_activity_end()</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_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></h5>
|
||||
<h5><a href="#method_ba_Session____init__"><constructor></a>, <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__on_activity_end">on_activity_end()</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_join">on_team_join()</a>, <a href="#method_ba_Session__on_team_leave">on_team_leave()</a>, <a href="#method_ba_Session__setactivity">setactivity()</a></h5>
|
||||
<dl>
|
||||
<dt><h4><a name="method_ba_Session____init__"><constructor></a></dt></h4><dd>
|
||||
<p><span>ba.Session(depsets: Sequence[<a href="#class_ba_DependencySet">ba.DependencySet</a>], team_names: Sequence[str] = None, team_colors: Sequence[Sequence[float]] = None, min_players: int = 1, max_players: int = 8)</span></p>
|
||||
@ -4459,15 +4516,15 @@ another <a href="#class_ba_Activity">ba.Activity</a>.</p>
|
||||
<p>Called when a <a href="#class_ba_Team">ba.Team</a> is leaving the session.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="method_ba_Session__set_activity">set_activity()</a></dt></h4><dd>
|
||||
<p><span>set_activity(self, activity: <a href="#class_ba_Activity">ba.Activity</a>) -> None</span></p>
|
||||
<dt><h4><a name="method_ba_Session__setactivity">setactivity()</a></dt></h4><dd>
|
||||
<p><span>setactivity(self, activity: <a href="#class_ba_Activity">ba.Activity</a>) -> None</span></p>
|
||||
|
||||
<p>Assign a new current <a href="#class_ba_Activity">ba.Activity</a> for the session.</p>
|
||||
|
||||
<p>Note that this will not change the current context to the new
|
||||
Activity's. Code must be run in the new activity's methods
|
||||
(on_transition_in, etc) to get it. (so you can't do
|
||||
session.set_activity(foo) and then <a href="#function_ba_newnode">ba.newnode</a>() to add a node to foo)</p>
|
||||
session.setactivity(foo) and then <a href="#function_ba_newnode">ba.newnode</a>() to add a node to foo)</p>
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
@ -4499,7 +4556,7 @@ that a SessionPlayer is still present if retaining references to one
|
||||
for any length of time.</p>
|
||||
|
||||
<h3>Attributes:</h3>
|
||||
<h5><a href="#attr_ba_SessionPlayer__character">character</a>, <a href="#attr_ba_SessionPlayer__color">color</a>, <a href="#attr_ba_SessionPlayer__gamedata">gamedata</a>, <a href="#attr_ba_SessionPlayer__gameplayer">gameplayer</a>, <a href="#attr_ba_SessionPlayer__highlight">highlight</a>, <a href="#attr_ba_SessionPlayer__id">id</a>, <a href="#attr_ba_SessionPlayer__in_game">in_game</a>, <a href="#attr_ba_SessionPlayer__inputdevice">inputdevice</a>, <a href="#attr_ba_SessionPlayer__sessiondata">sessiondata</a>, <a href="#attr_ba_SessionPlayer__team">team</a></h5>
|
||||
<h5><a href="#attr_ba_SessionPlayer__character">character</a>, <a href="#attr_ba_SessionPlayer__color">color</a>, <a href="#attr_ba_SessionPlayer__gameplayer">gameplayer</a>, <a href="#attr_ba_SessionPlayer__highlight">highlight</a>, <a href="#attr_ba_SessionPlayer__id">id</a>, <a href="#attr_ba_SessionPlayer__in_game">in_game</a>, <a href="#attr_ba_SessionPlayer__inputdevice">inputdevice</a>, <a href="#attr_ba_SessionPlayer__sessiondata">sessiondata</a>, <a href="#attr_ba_SessionPlayer__team">team</a></h5>
|
||||
<dl>
|
||||
<dt><h4><a name="attr_ba_SessionPlayer__character">character</a></h4></dt><dd>
|
||||
<p><span> str</span></p>
|
||||
@ -4511,13 +4568,6 @@ for any length of time.</p>
|
||||
<p>The base color for this Player.
|
||||
In team games this will match the <a href="#class_ba_SessionTeam">ba.SessionTeam</a>'s color.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="attr_ba_SessionPlayer__gamedata">gamedata</a></h4></dt><dd>
|
||||
<p><span> Dict</span></p>
|
||||
<p>A dict for use by the current <a href="#class_ba_Activity">ba.Activity</a> for
|
||||
storing data associated with this Player.
|
||||
This gets cleared for each new <a href="#class_ba_Activity">ba.Activity</a>.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="attr_ba_SessionPlayer__gameplayer">gameplayer</a></h4></dt><dd>
|
||||
<p><span> Optional[<a href="#class_ba_Player">ba.Player</a>]</span></p>
|
||||
@ -4568,10 +4618,10 @@ is still in its lobby selecting a team/etc. then a
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Methods:</h3>
|
||||
<h5><a href="#method_ba_SessionPlayer__assign_input_call">assign_input_call()</a>, <a href="#method_ba_SessionPlayer__exists">exists()</a>, <a href="#method_ba_SessionPlayer__get_account_id">get_account_id()</a>, <a href="#method_ba_SessionPlayer__get_icon">get_icon()</a>, <a href="#method_ba_SessionPlayer__getname">getname()</a>, <a href="#method_ba_SessionPlayer__remove_from_game">remove_from_game()</a>, <a href="#method_ba_SessionPlayer__reset_input">reset_input()</a>, <a href="#method_ba_SessionPlayer__set_name">set_name()</a></h5>
|
||||
<h5><a href="#method_ba_SessionPlayer__assigninput">assigninput()</a>, <a href="#method_ba_SessionPlayer__exists">exists()</a>, <a href="#method_ba_SessionPlayer__get_account_id">get_account_id()</a>, <a href="#method_ba_SessionPlayer__get_icon">get_icon()</a>, <a href="#method_ba_SessionPlayer__getname">getname()</a>, <a href="#method_ba_SessionPlayer__remove_from_game">remove_from_game()</a>, <a href="#method_ba_SessionPlayer__resetinput">resetinput()</a>, <a href="#method_ba_SessionPlayer__setname">setname()</a></h5>
|
||||
<dl>
|
||||
<dt><h4><a name="method_ba_SessionPlayer__assign_input_call">assign_input_call()</a></dt></h4><dd>
|
||||
<p><span>assign_input_call(type: Union[str, Tuple[str, ...]],
|
||||
<dt><h4><a name="method_ba_SessionPlayer__assigninput">assigninput()</a></dt></h4><dd>
|
||||
<p><span>assigninput(type: Union[str, Tuple[str, ...]],
|
||||
call: Callable) -> None</span></p>
|
||||
|
||||
<p>Set the python callable to be run for one or more types of input.
|
||||
@ -4619,14 +4669,14 @@ name may include an icon.</p>
|
||||
<p>Removes the player from the game.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="method_ba_SessionPlayer__reset_input">reset_input()</a></dt></h4><dd>
|
||||
<p><span>reset_input() -> None</span></p>
|
||||
<dt><h4><a name="method_ba_SessionPlayer__resetinput">resetinput()</a></dt></h4><dd>
|
||||
<p><span>resetinput() -> None</span></p>
|
||||
|
||||
<p>Clears out the player's assigned input actions.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="method_ba_SessionPlayer__set_name">set_name()</a></dt></h4><dd>
|
||||
<p><span>set_name(name: str, full_name: str = None, real: bool = True)
|
||||
<dt><h4><a name="method_ba_SessionPlayer__setname">setname()</a></dt></h4><dd>
|
||||
<p><span>setname(name: str, full_name: str = None, real: bool = True)
|
||||
-> None</span></p>
|
||||
|
||||
<p>Set the player's name to the provided string.
|
||||
@ -4857,7 +4907,7 @@ of the session.</p>
|
||||
<h3>Methods:</h3>
|
||||
<dl>
|
||||
<dt><h4><a name="method_ba_StandLocation____init__"><constructor></a></dt></h4><dd>
|
||||
<p><span>ba.StandLocation(position: _<a href="#class_ba_Vec3">ba.Vec3</a>, angle: Optional[float] = None)</span></p>
|
||||
<p><span>ba.StandLocation(position: <a href="#class_ba_Vec3">ba.Vec3</a>, angle: Optional[float] = None)</span></p>
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
@ -4902,7 +4952,7 @@ of the session.</p>
|
||||
</p>
|
||||
|
||||
<h3>Methods:</h3>
|
||||
<h5><a href="#method_ba_Stats____init__"><constructor></a>, <a href="#method_ba_Stats__get_records">get_records()</a>, <a href="#method_ba_Stats__getactivity">getactivity()</a>, <a href="#method_ba_Stats__player_got_hit">player_got_hit()</a>, <a href="#method_ba_Stats__player_scored">player_scored()</a>, <a href="#method_ba_Stats__player_was_killed">player_was_killed()</a>, <a href="#method_ba_Stats__register_player">register_player()</a>, <a href="#method_ba_Stats__reset">reset()</a>, <a href="#method_ba_Stats__reset_accum">reset_accum()</a>, <a href="#method_ba_Stats__set_activity">set_activity()</a></h5>
|
||||
<h5><a href="#method_ba_Stats____init__"><constructor></a>, <a href="#method_ba_Stats__get_records">get_records()</a>, <a href="#method_ba_Stats__getactivity">getactivity()</a>, <a href="#method_ba_Stats__player_got_hit">player_got_hit()</a>, <a href="#method_ba_Stats__player_scored">player_scored()</a>, <a href="#method_ba_Stats__player_was_killed">player_was_killed()</a>, <a href="#method_ba_Stats__register_player">register_player()</a>, <a href="#method_ba_Stats__reset">reset()</a>, <a href="#method_ba_Stats__reset_accum">reset_accum()</a>, <a href="#method_ba_Stats__setactivity">setactivity()</a></h5>
|
||||
<dl>
|
||||
<dt><h4><a name="method_ba_Stats____init__"><constructor></a></dt></h4><dd>
|
||||
<p><span>ba.Stats()</span></p>
|
||||
@ -4960,8 +5010,8 @@ of the session.</p>
|
||||
<p>Reset per-sound sub-scores.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="method_ba_Stats__set_activity">set_activity()</a></dt></h4><dd>
|
||||
<p><span>set_activity(self, activity: Optional[<a href="#class_ba_Activity">ba.Activity</a>]) -> None</span></p>
|
||||
<dt><h4><a name="method_ba_Stats__setactivity">setactivity()</a></dt></h4><dd>
|
||||
<p><span>setactivity(self, activity: Optional[<a href="#class_ba_Activity">ba.Activity</a>]) -> None</span></p>
|
||||
|
||||
<p>Set the current activity for this instance.</p>
|
||||
|
||||
@ -4979,7 +5029,19 @@ of the session.</p>
|
||||
</p>
|
||||
|
||||
<h3>Attributes:</h3>
|
||||
<h5><a href="#attr_ba_Team__gamedata">gamedata</a>, <a href="#attr_ba_Team__sessionteam">sessionteam</a></h5>
|
||||
<dl>
|
||||
<dt><h4><a name="attr_ba_Team__gamedata">gamedata</a></h4></dt><dd>
|
||||
<p><span>dict</span></p>
|
||||
<p>Arbitrary values associated with the team.
|
||||
Though it is encouraged that most player values be properly defined
|
||||
on the <a href="#class_ba_Team">ba.Team</a> subclass, it may be useful for player-agnostic
|
||||
objects to store values here. This dict is cleared when the team
|
||||
leaves or expires so objects stored here will be disposed of at
|
||||
the expected time, unlike the Team instance itself which may
|
||||
continue to be referenced after it is no longer part of the game.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="attr_ba_Team__sessionteam">sessionteam</a></h4></dt><dd>
|
||||
<p><span>SessionTeam</span></p>
|
||||
<p>Return the <a href="#class_ba_SessionTeam">ba.SessionTeam</a> corresponding to this Team.</p>
|
||||
@ -4989,12 +5051,19 @@ of the session.</p>
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Methods:</h3>
|
||||
<h5><a href="#method_ba_Team__manual_init">manual_init()</a>, <a href="#method_ba_Team__on_expire">on_expire()</a></h5>
|
||||
<dl>
|
||||
<dt><h4><a name="method_ba_Team__manual_init">manual_init()</a></dt></h4><dd>
|
||||
<p><span>manual_init(self, team_id: int, name: Union[<a href="#class_ba_Lstr">ba.Lstr</a>, str], color: Tuple[float, ...]) -> None</span></p>
|
||||
|
||||
<p>Manually init a team for uses such as bots.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="method_ba_Team__on_expire">on_expire()</a></dt></h4><dd>
|
||||
<p><span>on_expire(self) -> None</span></p>
|
||||
|
||||
<p>Can be overridden to handle team expiration.</p>
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
<hr>
|
||||
@ -5011,7 +5080,7 @@ of the session.</p>
|
||||
<h3>Attributes Inherited:</h3>
|
||||
<h5><a href="#attr_ba_Activity__players">players</a>, <a href="#attr_ba_Activity__settings_raw">settings_raw</a>, <a href="#attr_ba_Activity__teams">teams</a></h5>
|
||||
<h3>Attributes Defined Here:</h3>
|
||||
<h5><a href="#attr_ba_TeamGameActivity__expired">expired</a>, <a href="#attr_ba_TeamGameActivity__globalsnode">globalsnode</a>, <a href="#attr_ba_TeamGameActivity__map">map</a>, <a href="#attr_ba_TeamGameActivity__playertype">playertype</a>, <a href="#attr_ba_TeamGameActivity__session">session</a>, <a href="#attr_ba_TeamGameActivity__stats">stats</a>, <a href="#attr_ba_TeamGameActivity__teamtype">teamtype</a></h5>
|
||||
<h5><a href="#attr_ba_TeamGameActivity__expired">expired</a>, <a href="#attr_ba_TeamGameActivity__gamedata">gamedata</a>, <a href="#attr_ba_TeamGameActivity__globalsnode">globalsnode</a>, <a href="#attr_ba_TeamGameActivity__map">map</a>, <a href="#attr_ba_TeamGameActivity__playertype">playertype</a>, <a href="#attr_ba_TeamGameActivity__session">session</a>, <a href="#attr_ba_TeamGameActivity__stats">stats</a>, <a href="#attr_ba_TeamGameActivity__teamtype">teamtype</a></h5>
|
||||
<dl>
|
||||
<dt><h4><a name="attr_ba_TeamGameActivity__expired">expired</a></h4></dt><dd>
|
||||
<p><span>bool</span></p>
|
||||
@ -5021,6 +5090,14 @@ of the session.</p>
|
||||
At this point no new nodes, timers, etc should be made,
|
||||
run, etc, and the activity should be considered a 'zombie'.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="attr_ba_TeamGameActivity__gamedata">gamedata</a></h4></dt><dd>
|
||||
<p><span>dict</span></p>
|
||||
<p>Entities needing to store simple data with an activity can put it
|
||||
here. This dict will be deleted when the activity expires, so contained
|
||||
objects generally do not need to worry about handling expired
|
||||
activities.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="attr_ba_TeamGameActivity__globalsnode">globalsnode</a></h4></dt><dd>
|
||||
<p><span><a href="#class_ba_Node">ba.Node</a></span></p>
|
||||
@ -5061,7 +5138,7 @@ of the session.</p>
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Methods Inherited:</h3>
|
||||
<h5><a href="#method_ba_GameActivity__add_actor_weak_ref">add_actor_weak_ref()</a>, <a href="#method_ba_GameActivity__add_player">add_player()</a>, <a href="#method_ba_GameActivity__add_team">add_team()</a>, <a href="#method_ba_GameActivity__begin">begin()</a>, <a href="#method_ba_GameActivity__continue_or_end_game">continue_or_end_game()</a>, <a href="#method_ba_GameActivity__create_player">create_player()</a>, <a href="#method_ba_GameActivity__create_settings_ui">create_settings_ui()</a>, <a href="#method_ba_GameActivity__create_team">create_team()</a>, <a href="#method_ba_GameActivity__dep_is_present">dep_is_present()</a>, <a href="#method_ba_GameActivity__destroy">destroy()</a>, <a href="#method_ba_GameActivity__end_game">end_game()</a>, <a href="#method_ba_GameActivity__get_description">get_description()</a>, <a href="#method_ba_GameActivity__get_description_display_string">get_description_display_string()</a>, <a href="#method_ba_GameActivity__get_display_string">get_display_string()</a>, <a href="#method_ba_GameActivity__get_dynamic_deps">get_dynamic_deps()</a>, <a href="#method_ba_GameActivity__get_game_settings">get_game_settings()</a>, <a href="#method_ba_GameActivity__get_instance_description">get_instance_description()</a>, <a href="#method_ba_GameActivity__get_instance_description_short">get_instance_description_short()</a>, <a href="#method_ba_GameActivity__get_instance_display_string">get_instance_display_string()</a>, <a href="#method_ba_GameActivity__get_instance_scoreboard_display_string">get_instance_scoreboard_display_string()</a>, <a href="#method_ba_GameActivity__get_score_info">get_score_info()</a>, <a href="#method_ba_GameActivity__get_settings_display_string">get_settings_display_string()</a>, <a href="#method_ba_GameActivity__get_supported_maps">get_supported_maps()</a>, <a href="#method_ba_GameActivity__get_team_display_string">get_team_display_string()</a>, <a href="#method_ba_GameActivity__getname">getname()</a>, <a href="#method_ba_GameActivity__handlemessage">handlemessage()</a>, <a href="#method_ba_GameActivity__has_begun">has_begun()</a>, <a href="#method_ba_GameActivity__has_ended">has_ended()</a>, <a href="#method_ba_GameActivity__has_transitioned_in">has_transitioned_in()</a>, <a href="#method_ba_GameActivity__is_transitioning_out">is_transitioning_out()</a>, <a href="#method_ba_GameActivity__is_waiting_for_continue">is_waiting_for_continue()</a>, <a href="#method_ba_GameActivity__on_continue">on_continue()</a>, <a href="#method_ba_GameActivity__on_expire">on_expire()</a>, <a href="#method_ba_GameActivity__on_player_join">on_player_join()</a>, <a href="#method_ba_GameActivity__on_player_leave">on_player_leave()</a>, <a href="#method_ba_GameActivity__on_team_join">on_team_join()</a>, <a href="#method_ba_GameActivity__on_team_leave">on_team_leave()</a>, <a href="#method_ba_GameActivity__on_transition_out">on_transition_out()</a>, <a href="#method_ba_GameActivity__remove_player">remove_player()</a>, <a href="#method_ba_GameActivity__remove_team">remove_team()</a>, <a href="#method_ba_GameActivity__respawn_player">respawn_player()</a>, <a href="#method_ba_GameActivity__retain_actor">retain_actor()</a>, <a href="#method_ba_GameActivity__set_has_ended">set_has_ended()</a>, <a href="#method_ba_GameActivity__setup_standard_powerup_drops">setup_standard_powerup_drops()</a>, <a href="#method_ba_GameActivity__setup_standard_time_limit">setup_standard_time_limit()</a>, <a href="#method_ba_GameActivity__show_zoom_message">show_zoom_message()</a>, <a href="#method_ba_GameActivity__spawn_player">spawn_player()</a>, <a href="#method_ba_GameActivity__spawn_player_if_exists">spawn_player_if_exists()</a>, <a href="#method_ba_GameActivity__transition_in">transition_in()</a>, <a href="#method_ba_GameActivity__transition_out">transition_out()</a></h5>
|
||||
<h5><a href="#method_ba_GameActivity__add_actor_weak_ref">add_actor_weak_ref()</a>, <a href="#method_ba_GameActivity__add_player">add_player()</a>, <a href="#method_ba_GameActivity__add_team">add_team()</a>, <a href="#method_ba_GameActivity__begin">begin()</a>, <a href="#method_ba_GameActivity__continue_or_end_game">continue_or_end_game()</a>, <a href="#method_ba_GameActivity__create_player">create_player()</a>, <a href="#method_ba_GameActivity__create_settings_ui">create_settings_ui()</a>, <a href="#method_ba_GameActivity__create_team">create_team()</a>, <a href="#method_ba_GameActivity__dep_is_present">dep_is_present()</a>, <a href="#method_ba_GameActivity__end_game">end_game()</a>, <a href="#method_ba_GameActivity__expire">expire()</a>, <a href="#method_ba_GameActivity__get_description">get_description()</a>, <a href="#method_ba_GameActivity__get_description_display_string">get_description_display_string()</a>, <a href="#method_ba_GameActivity__get_display_string">get_display_string()</a>, <a href="#method_ba_GameActivity__get_dynamic_deps">get_dynamic_deps()</a>, <a href="#method_ba_GameActivity__get_game_settings">get_game_settings()</a>, <a href="#method_ba_GameActivity__get_instance_description">get_instance_description()</a>, <a href="#method_ba_GameActivity__get_instance_description_short">get_instance_description_short()</a>, <a href="#method_ba_GameActivity__get_instance_display_string">get_instance_display_string()</a>, <a href="#method_ba_GameActivity__get_instance_scoreboard_display_string">get_instance_scoreboard_display_string()</a>, <a href="#method_ba_GameActivity__get_score_info">get_score_info()</a>, <a href="#method_ba_GameActivity__get_settings_display_string">get_settings_display_string()</a>, <a href="#method_ba_GameActivity__get_supported_maps">get_supported_maps()</a>, <a href="#method_ba_GameActivity__get_team_display_string">get_team_display_string()</a>, <a href="#method_ba_GameActivity__getname">getname()</a>, <a href="#method_ba_GameActivity__handlemessage">handlemessage()</a>, <a href="#method_ba_GameActivity__has_begun">has_begun()</a>, <a href="#method_ba_GameActivity__has_ended">has_ended()</a>, <a href="#method_ba_GameActivity__has_transitioned_in">has_transitioned_in()</a>, <a href="#method_ba_GameActivity__is_transitioning_out">is_transitioning_out()</a>, <a href="#method_ba_GameActivity__is_waiting_for_continue">is_waiting_for_continue()</a>, <a href="#method_ba_GameActivity__on_continue">on_continue()</a>, <a href="#method_ba_GameActivity__on_expire">on_expire()</a>, <a href="#method_ba_GameActivity__on_player_join">on_player_join()</a>, <a href="#method_ba_GameActivity__on_player_leave">on_player_leave()</a>, <a href="#method_ba_GameActivity__on_team_join">on_team_join()</a>, <a href="#method_ba_GameActivity__on_team_leave">on_team_leave()</a>, <a href="#method_ba_GameActivity__on_transition_out">on_transition_out()</a>, <a href="#method_ba_GameActivity__remove_player">remove_player()</a>, <a href="#method_ba_GameActivity__remove_team">remove_team()</a>, <a href="#method_ba_GameActivity__respawn_player">respawn_player()</a>, <a href="#method_ba_GameActivity__retain_actor">retain_actor()</a>, <a href="#method_ba_GameActivity__set_has_ended">set_has_ended()</a>, <a href="#method_ba_GameActivity__setup_standard_powerup_drops">setup_standard_powerup_drops()</a>, <a href="#method_ba_GameActivity__setup_standard_time_limit">setup_standard_time_limit()</a>, <a href="#method_ba_GameActivity__show_zoom_message">show_zoom_message()</a>, <a href="#method_ba_GameActivity__spawn_player">spawn_player()</a>, <a href="#method_ba_GameActivity__spawn_player_if_exists">spawn_player_if_exists()</a>, <a href="#method_ba_GameActivity__transition_in">transition_in()</a>, <a href="#method_ba_GameActivity__transition_out">transition_out()</a></h5>
|
||||
<h3>Methods Defined or Overridden:</h3>
|
||||
<h5><a href="#method_ba_TeamGameActivity____init__"><constructor></a>, <a href="#method_ba_TeamGameActivity__end">end()</a>, <a href="#method_ba_TeamGameActivity__on_begin">on_begin()</a>, <a href="#method_ba_TeamGameActivity__on_transition_in">on_transition_in()</a>, <a href="#method_ba_TeamGameActivity__spawn_player_spaz">spawn_player_spaz()</a>, <a href="#method_ba_TeamGameActivity__supports_session_type">supports_session_type()</a></h5>
|
||||
<dl>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user