mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-02-06 15:47:06 +08:00
Cleaned up Actor class to behave better in type-checking world
This commit is contained in:
parent
f71404e7f7
commit
ff043c0262
@ -78,7 +78,8 @@ from ba._messages import (OutOfBoundsMessage, DeathType, DieMessage,
|
|||||||
StandMessage, PickUpMessage, DropMessage,
|
StandMessage, PickUpMessage, DropMessage,
|
||||||
PickedUpMessage, DroppedMessage,
|
PickedUpMessage, DroppedMessage,
|
||||||
ShouldShatterMessage, ImpactDamageMessage,
|
ShouldShatterMessage, ImpactDamageMessage,
|
||||||
FreezeMessage, ThawMessage, HitMessage)
|
FreezeMessage, ThawMessage, HitMessage,
|
||||||
|
CelebrateMessage)
|
||||||
from ba._music import setmusic, MusicPlayer, MusicType, MusicPlayMode
|
from ba._music import setmusic, MusicPlayer, MusicType, MusicPlayMode
|
||||||
from ba._powerup import PowerupMessage, PowerupAcceptMessage
|
from ba._powerup import PowerupMessage, PowerupAcceptMessage
|
||||||
from ba._teambasesession import TeamBaseSession
|
from ba._teambasesession import TeamBaseSession
|
||||||
|
|||||||
@ -25,6 +25,9 @@ from __future__ import annotations
|
|||||||
import weakref
|
import weakref
|
||||||
from typing import TYPE_CHECKING, TypeVar
|
from typing import TYPE_CHECKING, TypeVar
|
||||||
|
|
||||||
|
from ba._messages import DieMessage, DeathType, OutOfBoundsMessage
|
||||||
|
from ba import _error
|
||||||
|
|
||||||
import _ba
|
import _ba
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
@ -83,9 +86,11 @@ class Actor:
|
|||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
"""Instantiates an Actor in the current ba.Activity."""
|
"""Instantiates an Actor in the current ba.Activity."""
|
||||||
|
|
||||||
# FIXME: Actor should not be require to have a 'node' attr.
|
# FIXME: Actor should not be assumed to have a 'node' attr.
|
||||||
self.node: Optional[ba.Node] = None
|
# self.node: Optional[ba.Node] = None
|
||||||
|
|
||||||
|
if __debug__:
|
||||||
|
self._root_actor_init_called = True
|
||||||
activity = _ba.getactivity()
|
activity = _ba.getactivity()
|
||||||
self._activity = weakref.ref(activity)
|
self._activity = weakref.ref(activity)
|
||||||
activity.add_actor_weak_ref(self)
|
activity.add_actor_weak_ref(self)
|
||||||
@ -96,27 +101,20 @@ class Actor:
|
|||||||
# That way we can treat DieMessage handling as the single
|
# That way we can treat DieMessage handling as the single
|
||||||
# point-of-action for death.
|
# point-of-action for death.
|
||||||
if not self.is_expired():
|
if not self.is_expired():
|
||||||
from ba import _messages
|
self.handlemessage(DieMessage())
|
||||||
self.handlemessage(_messages.DieMessage())
|
|
||||||
except Exception:
|
except Exception:
|
||||||
from ba import _error
|
|
||||||
_error.print_exception('exception in ba.Actor.__del__() for', self)
|
_error.print_exception('exception in ba.Actor.__del__() for', self)
|
||||||
|
|
||||||
def handlemessage(self, msg: Any) -> Any:
|
def handlemessage(self, msg: Any) -> Any:
|
||||||
"""General message handling; can be passed any message object.
|
"""General message handling; can be passed any message object."""
|
||||||
|
if __debug__:
|
||||||
|
self._handlemessage_sanity_check()
|
||||||
|
|
||||||
The default implementation will handle ba.DieMessages by
|
# By default, actors going out-of-bounds simply kill themselves.
|
||||||
calling self.node.delete() if self contains a 'node' attribute.
|
if isinstance(msg, OutOfBoundsMessage):
|
||||||
"""
|
return self.handlemessage(DieMessage(how=DeathType.OUT_OF_BOUNDS))
|
||||||
from ba._error import UNHANDLED
|
|
||||||
del msg # Unused.
|
|
||||||
return UNHANDLED
|
|
||||||
|
|
||||||
def _handlemessage_sanity_check(self) -> None:
|
return _error.UNHANDLED
|
||||||
if self.is_expired():
|
|
||||||
from ba import _error
|
|
||||||
_error.print_error(
|
|
||||||
f'handlemessage called on expired actor: {self}')
|
|
||||||
|
|
||||||
def autoretain(self: T) -> T:
|
def autoretain(self: T) -> T:
|
||||||
"""Keep this Actor alive without needing to hold a reference to it.
|
"""Keep this Actor alive without needing to hold a reference to it.
|
||||||
@ -131,8 +129,7 @@ class Actor:
|
|||||||
"""
|
"""
|
||||||
activity = self._activity()
|
activity = self._activity()
|
||||||
if activity is None:
|
if activity is None:
|
||||||
from ba._error import ActivityNotFoundError
|
raise _error.ActivityNotFoundError()
|
||||||
raise ActivityNotFoundError()
|
|
||||||
activity.retain_actor(self)
|
activity.retain_actor(self)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
@ -192,6 +189,21 @@ class Actor:
|
|||||||
"""
|
"""
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def _handlemessage_sanity_check(self) -> None:
|
||||||
|
"""Make sure things are kosher in handlemessage().
|
||||||
|
|
||||||
|
Place this in an 'if __debug__:' clause at the top of handlemessage()
|
||||||
|
overrides. This will will complain if anything is sending the Actor
|
||||||
|
messages after the activity has ended, which should be explicitly
|
||||||
|
avoided.
|
||||||
|
"""
|
||||||
|
assert __debug__, "This should only be called in __debug__ mode."
|
||||||
|
if not getattr(self, '_root_actor_init_called', False):
|
||||||
|
_error.print_error('Root Actor __init__() not called.')
|
||||||
|
if self.is_expired():
|
||||||
|
_error.print_error(
|
||||||
|
f'handlemessage() called on expired actor: {self}')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def activity(self) -> ba.Activity:
|
def activity(self) -> ba.Activity:
|
||||||
"""The Activity this Actor was created in.
|
"""The Activity this Actor was created in.
|
||||||
@ -200,8 +212,7 @@ class Actor:
|
|||||||
"""
|
"""
|
||||||
activity = self._activity()
|
activity = self._activity()
|
||||||
if activity is None:
|
if activity is None:
|
||||||
from ba._error import ActivityNotFoundError
|
raise _error.ActivityNotFoundError()
|
||||||
raise ActivityNotFoundError()
|
|
||||||
return activity
|
return activity
|
||||||
|
|
||||||
def getactivity(self, doraise: bool = True) -> Optional[ba.Activity]:
|
def getactivity(self, doraise: bool = True) -> Optional[ba.Activity]:
|
||||||
@ -212,6 +223,5 @@ class Actor:
|
|||||||
"""
|
"""
|
||||||
activity = self._activity()
|
activity = self._activity()
|
||||||
if activity is None and doraise:
|
if activity is None and doraise:
|
||||||
from ba._error import ActivityNotFoundError
|
raise _error.ActivityNotFoundError()
|
||||||
raise ActivityNotFoundError()
|
|
||||||
return activity
|
return activity
|
||||||
|
|||||||
@ -188,7 +188,6 @@ def print_live_object_warnings(when: Any,
|
|||||||
ignore_session: ba.Session = None,
|
ignore_session: ba.Session = None,
|
||||||
ignore_activity: ba.Activity = None) -> None:
|
ignore_activity: ba.Activity = None) -> None:
|
||||||
"""Print warnings for remaining objects in the current context."""
|
"""Print warnings for remaining objects in the current context."""
|
||||||
# pylint: disable=too-many-branches
|
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
import gc
|
import gc
|
||||||
from ba import _session as bs_session
|
from ba import _session as bs_session
|
||||||
@ -252,13 +251,14 @@ def print_live_object_warnings(when: Any,
|
|||||||
for actor in actors:
|
for actor in actors:
|
||||||
_ba.app.printed_live_object_warning = True
|
_ba.app.printed_live_object_warning = True
|
||||||
print('ERROR: Actor found', when, ':', actor)
|
print('ERROR: Actor found', when, ':', actor)
|
||||||
if isinstance(actor, bs_actor.Actor):
|
# if isinstance(actor, bs_actor.Actor):
|
||||||
try:
|
# try:
|
||||||
if actor.node:
|
# if actor.node:
|
||||||
print(' - contains node:', actor.node.getnodetype(), ';',
|
# print(' - contains node:',
|
||||||
actor.node.get_name())
|
# actor.node.getnodetype(), ';',
|
||||||
except Exception as exc:
|
# actor.node.get_name())
|
||||||
print(' - exception checking actor node:', exc)
|
# except Exception as exc:
|
||||||
|
# print(' - exception checking actor node:', exc)
|
||||||
# refs = list(gc.get_referrers(actor))
|
# refs = list(gc.get_referrers(actor))
|
||||||
# i = 1
|
# i = 1
|
||||||
# for ref in refs:
|
# for ref in refs:
|
||||||
|
|||||||
@ -135,10 +135,10 @@ class CoopGameActivity(GameActivity):
|
|||||||
a wave.
|
a wave.
|
||||||
duration is given in seconds.
|
duration is given in seconds.
|
||||||
"""
|
"""
|
||||||
|
from ba._messages import CelebrateMessage
|
||||||
for player in self.players:
|
for player in self.players:
|
||||||
if player.actor is not None and player.actor.node:
|
if player.actor:
|
||||||
player.actor.node.handlemessage('celebrate',
|
player.actor.handlemessage(CelebrateMessage(duration))
|
||||||
int(duration * 1000))
|
|
||||||
|
|
||||||
def _preload_achievements(self) -> None:
|
def _preload_achievements(self) -> None:
|
||||||
from ba import _achievement
|
from ba import _achievement
|
||||||
|
|||||||
@ -315,7 +315,6 @@ class AssetPackage(DependencyComponent):
|
|||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
# pylint: disable=no-member
|
|
||||||
|
|
||||||
# This is used internally by the get_package_xxx calls.
|
# This is used internally by the get_package_xxx calls.
|
||||||
self.context = _ba.Context('current')
|
self.context = _ba.Context('current')
|
||||||
|
|||||||
@ -337,13 +337,13 @@ class GameActivity(Activity):
|
|||||||
self._game_scoreboard_description_text: Optional[ba.Actor] = None
|
self._game_scoreboard_description_text: Optional[ba.Actor] = None
|
||||||
self._standard_time_limit_time: Optional[int] = None
|
self._standard_time_limit_time: Optional[int] = None
|
||||||
self._standard_time_limit_timer: Optional[ba.Timer] = None
|
self._standard_time_limit_timer: Optional[ba.Timer] = None
|
||||||
self._standard_time_limit_text: Optional[ba.Actor] = None
|
self._standard_time_limit_text: Optional[ba.NodeActor] = None
|
||||||
self._standard_time_limit_text_input: Optional[ba.Actor] = None
|
self._standard_time_limit_text_input: Optional[ba.NodeActor] = None
|
||||||
self._tournament_time_limit: Optional[int] = None
|
self._tournament_time_limit: Optional[int] = None
|
||||||
self._tournament_time_limit_timer: Optional[ba.Timer] = None
|
self._tournament_time_limit_timer: Optional[ba.Timer] = None
|
||||||
self._tournament_time_limit_title_text: Optional[ba.Actor] = None
|
self._tournament_time_limit_title_text: Optional[ba.NodeActor] = None
|
||||||
self._tournament_time_limit_text: Optional[ba.Actor] = None
|
self._tournament_time_limit_text: Optional[ba.NodeActor] = None
|
||||||
self._tournament_time_limit_text_input: Optional[ba.Actor] = None
|
self._tournament_time_limit_text_input: Optional[ba.NodeActor] = None
|
||||||
self._zoom_message_times: Dict[int, float] = {}
|
self._zoom_message_times: Dict[int, float] = {}
|
||||||
self._is_waiting_for_continue = False
|
self._is_waiting_for_continue = False
|
||||||
|
|
||||||
@ -1042,17 +1042,18 @@ class GameActivity(Activity):
|
|||||||
from ba import _messages
|
from ba import _messages
|
||||||
from ba._gameutils import animate
|
from ba._gameutils import animate
|
||||||
from ba._coopsession import CoopSession
|
from ba._coopsession import CoopSession
|
||||||
from bastd.actor import playerspaz
|
from bastd.actor.playerspaz import PlayerSpaz
|
||||||
name = player.get_name()
|
name = player.get_name()
|
||||||
color = player.color
|
color = player.color
|
||||||
highlight = player.highlight
|
highlight = player.highlight
|
||||||
|
|
||||||
light_color = _math.normalized_color(color)
|
light_color = _math.normalized_color(color)
|
||||||
display_color = _ba.safecolor(color, target_intensity=0.75)
|
display_color = _ba.safecolor(color, target_intensity=0.75)
|
||||||
spaz = playerspaz.PlayerSpaz(color=color,
|
spaz = PlayerSpaz(color=color,
|
||||||
highlight=highlight,
|
highlight=highlight,
|
||||||
character=player.character,
|
character=player.character,
|
||||||
player=player)
|
player=player)
|
||||||
|
|
||||||
player.set_actor(spaz)
|
player.set_actor(spaz)
|
||||||
assert spaz.node
|
assert spaz.node
|
||||||
|
|
||||||
|
|||||||
@ -211,7 +211,7 @@ class Map(Actor):
|
|||||||
|
|
||||||
# This is expected to always be a ba.Node object (whether valid or not)
|
# This is expected to always be a ba.Node object (whether valid or not)
|
||||||
# should be set to something meaningful by child classes.
|
# should be set to something meaningful by child classes.
|
||||||
self.node = None
|
self.node: Optional[_ba.Node] = None
|
||||||
|
|
||||||
# Make our class' preload-data available to us
|
# Make our class' preload-data available to us
|
||||||
# (and instruct the user if we weren't preloaded properly).
|
# (and instruct the user if we weren't preloaded properly).
|
||||||
@ -365,9 +365,8 @@ class Map(Actor):
|
|||||||
player_pts = []
|
player_pts = []
|
||||||
for player in players:
|
for player in players:
|
||||||
try:
|
try:
|
||||||
if player.actor is not None and player.actor.is_alive():
|
if player.node:
|
||||||
assert player.actor.node
|
pnt = _ba.Vec3(player.node.position)
|
||||||
pnt = _ba.Vec3(player.actor.node.position)
|
|
||||||
player_pts.append(pnt)
|
player_pts.append(pnt)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
print('EXC in get_ffa_start_position:', exc)
|
print('EXC in get_ffa_start_position:', exc)
|
||||||
@ -412,12 +411,17 @@ class Map(Actor):
|
|||||||
return self.flag_points_default[:3]
|
return self.flag_points_default[:3]
|
||||||
return self.flag_points[team_index % len(self.flag_points)][:3]
|
return self.flag_points[team_index % len(self.flag_points)][:3]
|
||||||
|
|
||||||
|
def exists(self) -> bool:
|
||||||
|
return bool(self.node)
|
||||||
|
|
||||||
def handlemessage(self, msg: Any) -> Any:
|
def handlemessage(self, msg: Any) -> Any:
|
||||||
from ba import _messages
|
from ba import _messages
|
||||||
if isinstance(msg, _messages.DieMessage):
|
if isinstance(msg, _messages.DieMessage):
|
||||||
if self.node:
|
if self.node:
|
||||||
self.node.delete()
|
self.node.delete()
|
||||||
super().handlemessage(msg)
|
else:
|
||||||
|
return super().handlemessage(msg)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def register_map(maptype: Type[Map]) -> None:
|
def register_map(maptype: Type[Map]) -> None:
|
||||||
|
|||||||
@ -47,6 +47,7 @@ class DeathType(Enum):
|
|||||||
Category: Enums
|
Category: Enums
|
||||||
"""
|
"""
|
||||||
GENERIC = 'generic'
|
GENERIC = 'generic'
|
||||||
|
OUT_OF_BOUNDS = 'out_of_bounds'
|
||||||
IMPACT = 'impact'
|
IMPACT = 'impact'
|
||||||
FALL = 'fall'
|
FALL = 'fall'
|
||||||
REACHED_GOAL = 'reached_goal'
|
REACHED_GOAL = 'reached_goal'
|
||||||
@ -187,6 +188,20 @@ class ThawMessage:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class CelebrateMessage:
|
||||||
|
"""Tells an object to celebrate.
|
||||||
|
|
||||||
|
Category: Message Classes
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
|
||||||
|
duration
|
||||||
|
Amount of time to celebrate in seconds.
|
||||||
|
"""
|
||||||
|
duration: float = 10.0
|
||||||
|
|
||||||
|
|
||||||
@dataclass(init=False)
|
@dataclass(init=False)
|
||||||
class HitMessage:
|
class HitMessage:
|
||||||
"""Tells an object it has been hit in some way.
|
"""Tells an object it has been hit in some way.
|
||||||
|
|||||||
@ -51,3 +51,6 @@ class NodeActor(Actor):
|
|||||||
self.node.delete()
|
self.node.delete()
|
||||||
return None
|
return None
|
||||||
return super().handlemessage(msg)
|
return super().handlemessage(msg)
|
||||||
|
|
||||||
|
def exists(self) -> bool:
|
||||||
|
return bool(self.node)
|
||||||
|
|||||||
@ -98,21 +98,6 @@ class Team:
|
|||||||
"""Returns the numeric team ID."""
|
"""Returns the numeric team ID."""
|
||||||
return self._team_id
|
return self._team_id
|
||||||
|
|
||||||
def celebrate(self, duration: float = 10.0) -> None:
|
|
||||||
"""Tells all players on the team to celebrate.
|
|
||||||
|
|
||||||
duration is given in seconds.
|
|
||||||
"""
|
|
||||||
for player in self.players:
|
|
||||||
try:
|
|
||||||
if player.actor is not None and player.actor.node:
|
|
||||||
# Internal node-message is in milliseconds.
|
|
||||||
player.actor.node.handlemessage('celebrate',
|
|
||||||
int(duration * 1000))
|
|
||||||
except Exception:
|
|
||||||
from ba import _error
|
|
||||||
_error.print_exception('Error on celebrate')
|
|
||||||
|
|
||||||
def reset(self) -> None:
|
def reset(self) -> None:
|
||||||
"""(internal)"""
|
"""(internal)"""
|
||||||
self.reset_gamedata()
|
self.reset_gamedata()
|
||||||
|
|||||||
@ -254,22 +254,23 @@ class TeamBaseSession(Session):
|
|||||||
announcement of the same.
|
announcement of the same.
|
||||||
"""
|
"""
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
|
# pylint: disable=too-many-locals
|
||||||
from ba import _math
|
from ba import _math
|
||||||
from ba import _general
|
from ba import _general
|
||||||
from ba._gameutils import cameraflash
|
from ba._gameutils import cameraflash
|
||||||
from ba import _lang
|
from ba import _lang
|
||||||
from ba._freeforallsession import FreeForAllSession
|
from ba._freeforallsession import FreeForAllSession
|
||||||
|
from ba._messages import CelebrateMessage
|
||||||
_ba.timer(delay,
|
_ba.timer(delay,
|
||||||
_general.Call(_ba.playsound, _ba.getsound("boxingBell")))
|
_general.Call(_ba.playsound, _ba.getsound("boxingBell")))
|
||||||
if announce_winning_team:
|
if announce_winning_team:
|
||||||
winning_team = results.get_winning_team()
|
winning_team = results.get_winning_team()
|
||||||
if winning_team is not None:
|
if winning_team is not None:
|
||||||
# Have all players celebrate.
|
# Have all players celebrate.
|
||||||
|
celebrate_msg = CelebrateMessage(duration=10.0)
|
||||||
for player in winning_team.players:
|
for player in winning_team.players:
|
||||||
if player.actor is not None and player.actor.node:
|
if player.actor:
|
||||||
# Note: celebrate message takes milliseconds
|
player.actor.handlemessage(celebrate_msg)
|
||||||
# for historical reasons.
|
|
||||||
player.actor.node.handlemessage('celebrate', 10000)
|
|
||||||
cameraflash()
|
cameraflash()
|
||||||
|
|
||||||
# Some languages say "FOO WINS" different for teams vs players.
|
# Some languages say "FOO WINS" different for teams vs players.
|
||||||
|
|||||||
@ -25,7 +25,7 @@ from __future__ import annotations
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
import ba
|
import ba
|
||||||
from bastd.actor import spaz as basespaz
|
from bastd.actor.spaz import Spaz
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Any, Optional, Sequence, Tuple
|
from typing import Any, Optional, Sequence, Tuple
|
||||||
@ -77,7 +77,7 @@ class PlayerSpazHurtMessage:
|
|||||||
self.spaz = spaz
|
self.spaz = spaz
|
||||||
|
|
||||||
|
|
||||||
class PlayerSpaz(basespaz.Spaz):
|
class PlayerSpaz(Spaz):
|
||||||
"""A ba.Spaz subclass meant to be controlled by a ba.Player.
|
"""A ba.Spaz subclass meant to be controlled by a ba.Player.
|
||||||
|
|
||||||
category: Gameplay Classes
|
category: Gameplay Classes
|
||||||
@ -102,13 +102,12 @@ class PlayerSpaz(basespaz.Spaz):
|
|||||||
you must call connect_controls_to_player() to do so.
|
you must call connect_controls_to_player() to do so.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
basespaz.Spaz.__init__(self,
|
super().__init__(color=color,
|
||||||
color=color,
|
highlight=highlight,
|
||||||
highlight=highlight,
|
character=character,
|
||||||
character=character,
|
source_player=player,
|
||||||
source_player=player,
|
start_invincible=True,
|
||||||
start_invincible=True,
|
powerups_expire=powerups_expire)
|
||||||
powerups_expire=powerups_expire)
|
|
||||||
self.last_player_attacked_by: Optional[ba.Player] = None
|
self.last_player_attacked_by: Optional[ba.Player] = None
|
||||||
self.last_attacked_time = 0.0
|
self.last_attacked_time = 0.0
|
||||||
self.last_attacked_type: Optional[Tuple[str, str]] = None
|
self.last_attacked_type: Optional[Tuple[str, str]] = None
|
||||||
|
|||||||
@ -155,7 +155,7 @@ class Spaz(ba.Actor):
|
|||||||
media = factory.get_media(character)
|
media = factory.get_media(character)
|
||||||
punchmats = (factory.punch_material, ba.sharedobj('attack_material'))
|
punchmats = (factory.punch_material, ba.sharedobj('attack_material'))
|
||||||
pickupmats = (factory.pickup_material, ba.sharedobj('pickup_material'))
|
pickupmats = (factory.pickup_material, ba.sharedobj('pickup_material'))
|
||||||
self.node = ba.newnode(
|
self.node: ba.Node = ba.newnode(
|
||||||
type="spaz",
|
type="spaz",
|
||||||
delegate=self,
|
delegate=self,
|
||||||
attrs={
|
attrs={
|
||||||
@ -256,10 +256,13 @@ class Spaz(ba.Actor):
|
|||||||
self.punch_callback: Optional[Callable[[Spaz], Any]] = None
|
self.punch_callback: Optional[Callable[[Spaz], Any]] = None
|
||||||
self.pick_up_powerup_callback: Optional[Callable[[Spaz], Any]] = None
|
self.pick_up_powerup_callback: Optional[Callable[[Spaz], Any]] = None
|
||||||
|
|
||||||
|
def exists(self) -> bool:
|
||||||
|
return bool(self.node)
|
||||||
|
|
||||||
def on_expire(self) -> None:
|
def on_expire(self) -> None:
|
||||||
super().on_expire()
|
super().on_expire()
|
||||||
|
|
||||||
# release callbacks/refs so we don't wind up with dependency loops..
|
# Release callbacks/refs so we don't wind up with dependency loops.
|
||||||
self._dropped_bomb_callbacks = []
|
self._dropped_bomb_callbacks = []
|
||||||
self.punch_callback = None
|
self.punch_callback = None
|
||||||
self.pick_up_powerup_callback = None
|
self.pick_up_powerup_callback = None
|
||||||
@ -296,8 +299,8 @@ class Spaz(ba.Actor):
|
|||||||
assert isinstance(t_ms, int)
|
assert isinstance(t_ms, int)
|
||||||
t_bucket = int(t_ms / 1000)
|
t_bucket = int(t_ms / 1000)
|
||||||
if t_bucket == self._turbo_filter_time_bucket:
|
if t_bucket == self._turbo_filter_time_bucket:
|
||||||
# add only once per timestep (filter out buttons triggering
|
# Add only once per timestep (filter out buttons triggering
|
||||||
# multiple actions)
|
# multiple actions).
|
||||||
if t_ms != self._turbo_filter_times.get(source, 0):
|
if t_ms != self._turbo_filter_times.get(source, 0):
|
||||||
self._turbo_filter_counts[source] = (
|
self._turbo_filter_counts[source] = (
|
||||||
self._turbo_filter_counts.get(source, 0) + 1)
|
self._turbo_filter_counts.get(source, 0) + 1)
|
||||||
@ -306,11 +309,11 @@ class Spaz(ba.Actor):
|
|||||||
# ba.screenmessage( str(source) + " "
|
# ba.screenmessage( str(source) + " "
|
||||||
# + str(self._turbo_filter_counts[source]))
|
# + str(self._turbo_filter_counts[source]))
|
||||||
if self._turbo_filter_counts[source] == 15:
|
if self._turbo_filter_counts[source] == 15:
|
||||||
# knock 'em out. That'll learn 'em.
|
# Knock 'em out. That'll learn 'em.
|
||||||
assert self.node
|
assert self.node
|
||||||
self.node.handlemessage("knockout", 500.0)
|
self.node.handlemessage("knockout", 500.0)
|
||||||
|
|
||||||
# also issue periodic notices about who is turbo-ing
|
# Also issue periodic notices about who is turbo-ing.
|
||||||
now = ba.time(ba.TimeType.REAL)
|
now = ba.time(ba.TimeType.REAL)
|
||||||
if now > ba.app.last_spaz_turbo_warn_time + 30.0:
|
if now > ba.app.last_spaz_turbo_warn_time + 30.0:
|
||||||
ba.app.last_spaz_turbo_warn_time = now
|
ba.app.last_spaz_turbo_warn_time = now
|
||||||
@ -1226,6 +1229,10 @@ class Spaz(ba.Actor):
|
|||||||
# hold_body needs to be set before hold_node.
|
# hold_body needs to be set before hold_node.
|
||||||
self.node.hold_body = opposing_body
|
self.node.hold_body = opposing_body
|
||||||
self.node.hold_node = opposing_node
|
self.node.hold_node = opposing_node
|
||||||
|
elif isinstance(msg, ba.CelebrateMessage):
|
||||||
|
if self.node:
|
||||||
|
self.node.handlemessage('celebrate', int(msg.duration * 1000))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
return super().handlemessage(msg)
|
return super().handlemessage(msg)
|
||||||
return None
|
return None
|
||||||
|
|||||||
@ -190,7 +190,7 @@ class SpazBot(basespaz.Spaz):
|
|||||||
closest_dist = None
|
closest_dist = None
|
||||||
closest_vel = None
|
closest_vel = None
|
||||||
closest = None
|
closest = None
|
||||||
assert self._player_pts
|
assert self._player_pts is not None
|
||||||
for plpt, plvel in self._player_pts:
|
for plpt, plvel in self._player_pts:
|
||||||
dist = (plpt - botpt).length()
|
dist = (plpt - botpt).length()
|
||||||
|
|
||||||
@ -983,6 +983,7 @@ class BotSet:
|
|||||||
for player in ba.getactivity().players:
|
for player in ba.getactivity().players:
|
||||||
try:
|
try:
|
||||||
if player.is_alive():
|
if player.is_alive():
|
||||||
|
assert isinstance(player.actor, basespaz.Spaz)
|
||||||
assert player.actor is not None and player.actor.node
|
assert player.actor is not None and player.actor.node
|
||||||
player_pts.append((ba.Vec3(player.actor.node.position),
|
player_pts.append((ba.Vec3(player.actor.node.position),
|
||||||
ba.Vec3(player.actor.node.velocity)))
|
ba.Vec3(player.actor.node.velocity)))
|
||||||
@ -1006,16 +1007,6 @@ class BotSet:
|
|||||||
bot.handlemessage(ba.DieMessage(immediate=True))
|
bot.handlemessage(ba.DieMessage(immediate=True))
|
||||||
self._bot_lists[i] = []
|
self._bot_lists[i] = []
|
||||||
|
|
||||||
def celebrate(self, duration: float) -> None:
|
|
||||||
"""Tell all living bots in the set to celebrate momentarily.
|
|
||||||
|
|
||||||
Duration is given in seconds.
|
|
||||||
"""
|
|
||||||
for botlist in self._bot_lists:
|
|
||||||
for bot in botlist:
|
|
||||||
if bot.node:
|
|
||||||
bot.node.handlemessage('celebrate', int(duration * 1000))
|
|
||||||
|
|
||||||
def start_moving(self) -> None:
|
def start_moving(self) -> None:
|
||||||
"""Start processing bot AI updates so they start doing their thing."""
|
"""Start processing bot AI updates so they start doing their thing."""
|
||||||
self._bot_update_timer = ba.Timer(0.05,
|
self._bot_update_timer = ba.Timer(0.05,
|
||||||
@ -1035,6 +1026,17 @@ class BotSet:
|
|||||||
bot.node.move_left_right = 0
|
bot.node.move_left_right = 0
|
||||||
bot.node.move_up_down = 0
|
bot.node.move_up_down = 0
|
||||||
|
|
||||||
|
def celebrate(self, duration: float) -> None:
|
||||||
|
"""Tell all living bots in the set to celebrate momentarily.
|
||||||
|
|
||||||
|
Duration is given in seconds.
|
||||||
|
"""
|
||||||
|
msg = ba.CelebrateMessage(duration=duration)
|
||||||
|
for botlist in self._bot_lists:
|
||||||
|
for bot in botlist:
|
||||||
|
if bot:
|
||||||
|
bot.handlemessage(msg)
|
||||||
|
|
||||||
def final_celebrate(self) -> None:
|
def final_celebrate(self) -> None:
|
||||||
"""Tell all bots in the set to stop what they were doing and celebrate.
|
"""Tell all bots in the set to stop what they were doing and celebrate.
|
||||||
|
|
||||||
@ -1045,12 +1047,12 @@ class BotSet:
|
|||||||
# At this point stop doing anything but jumping and celebrating.
|
# At this point stop doing anything but jumping and celebrating.
|
||||||
for botlist in self._bot_lists:
|
for botlist in self._bot_lists:
|
||||||
for bot in botlist:
|
for bot in botlist:
|
||||||
if bot.node:
|
if bot:
|
||||||
|
assert bot.node # (should exist if 'if bot' was True)
|
||||||
bot.node.move_left_right = 0
|
bot.node.move_left_right = 0
|
||||||
bot.node.move_up_down = 0
|
bot.node.move_up_down = 0
|
||||||
ba.timer(
|
ba.timer(0.5 * random.random(),
|
||||||
0.5 * random.random(),
|
ba.Call(bot.handlemessage, ba.CelebrateMessage()))
|
||||||
ba.Call(bot.node.handlemessage, 'celebrate', 10.0))
|
|
||||||
jump_duration = random.randrange(400, 500)
|
jump_duration = random.randrange(400, 500)
|
||||||
j = random.randrange(0, 200)
|
j = random.randrange(0, 200)
|
||||||
for _i in range(10):
|
for _i in range(10):
|
||||||
|
|||||||
@ -225,12 +225,8 @@ class AssaultGame(ba.TeamGameActivity):
|
|||||||
|
|
||||||
# Have teammates celebrate.
|
# Have teammates celebrate.
|
||||||
for player in player_team.players:
|
for player in player_team.players:
|
||||||
try:
|
if player.actor:
|
||||||
# Note: celebrate message is milliseconds
|
player.actor.handlemessage(ba.CelebrateMessage(2.0))
|
||||||
# for historical reasons.
|
|
||||||
player.actor.node.handlemessage('celebrate', 2000)
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
|
|
||||||
player_team.gamedata['score'] += 1
|
player_team.gamedata['score'] += 1
|
||||||
self._update_scoreboard()
|
self._update_scoreboard()
|
||||||
|
|||||||
@ -306,10 +306,8 @@ class CaptureTheFlagGame(ba.TeamGameActivity):
|
|||||||
|
|
||||||
# Have teammates celebrate
|
# Have teammates celebrate
|
||||||
for player in team.players:
|
for player in team.players:
|
||||||
if player.actor is not None and player.actor.node:
|
if player.actor:
|
||||||
# Note: celebrate message is milliseconds
|
player.actor.handlemessage(ba.CelebrateMessage(2.0))
|
||||||
# for historical reasons.
|
|
||||||
player.actor.node.handlemessage('celebrate', 2000)
|
|
||||||
|
|
||||||
# Reset all flags/state.
|
# Reset all flags/state.
|
||||||
for reset_team in self.teams:
|
for reset_team in self.teams:
|
||||||
|
|||||||
@ -279,7 +279,7 @@ class ChosenOneGame(ba.TeamGameActivity):
|
|||||||
self._flag = None
|
self._flag = None
|
||||||
self._chosen_one_player = player
|
self._chosen_one_player = player
|
||||||
|
|
||||||
if player.actor.node:
|
if player.actor:
|
||||||
if self.settings['Chosen One Gets Shield']:
|
if self.settings['Chosen One Gets Shield']:
|
||||||
player.actor.handlemessage(
|
player.actor.handlemessage(
|
||||||
ba.PowerupMessage('shield'))
|
ba.PowerupMessage('shield'))
|
||||||
@ -311,8 +311,10 @@ class ChosenOneGame(ba.TeamGameActivity):
|
|||||||
0.4: 1.0
|
0.4: 1.0
|
||||||
},
|
},
|
||||||
loop=True)
|
loop=True)
|
||||||
|
assert isinstance(player.actor, playerspaz.PlayerSpaz)
|
||||||
player.actor.node.connectattr('position', light.node,
|
player.actor.node.connectattr('position', light.node,
|
||||||
'position')
|
'position')
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
ba.print_exception('EXC in _set_chosen_one_player')
|
ba.print_exception('EXC in _set_chosen_one_player')
|
||||||
|
|
||||||
|
|||||||
@ -143,7 +143,9 @@ class EasterEggHuntGame(ba.TeamGameActivity):
|
|||||||
'source_node', 'opposing_node')
|
'source_node', 'opposing_node')
|
||||||
if egg_node is not None and playernode is not None:
|
if egg_node is not None and playernode is not None:
|
||||||
egg = egg_node.getdelegate()
|
egg = egg_node.getdelegate()
|
||||||
|
assert isinstance(egg, Egg)
|
||||||
spaz = playernode.getdelegate()
|
spaz = playernode.getdelegate()
|
||||||
|
assert isinstance(spaz, playerspaz.PlayerSpaz)
|
||||||
player = (spaz.getplayer()
|
player = (spaz.getplayer()
|
||||||
if hasattr(spaz, 'getplayer') else None)
|
if hasattr(spaz, 'getplayer') else None)
|
||||||
if player and egg:
|
if player and egg:
|
||||||
@ -187,13 +189,8 @@ class EasterEggHuntGame(ba.TeamGameActivity):
|
|||||||
ypos = random.uniform(3.5, 3.5)
|
ypos = random.uniform(3.5, 3.5)
|
||||||
zpos = random.uniform(-8.2, 3.7)
|
zpos = random.uniform(-8.2, 3.7)
|
||||||
|
|
||||||
def _is_exists(egg: Egg) -> bool:
|
|
||||||
if egg.node is None:
|
|
||||||
return False
|
|
||||||
return egg.node.exists()
|
|
||||||
|
|
||||||
# Prune dead eggs from our list.
|
# Prune dead eggs from our list.
|
||||||
self._eggs = [e for e in self._eggs if _is_exists(e)]
|
self._eggs = [e for e in self._eggs if e]
|
||||||
|
|
||||||
# Spawn more eggs if we've got space.
|
# Spawn more eggs if we've got space.
|
||||||
if len(self._eggs) < int(self._max_eggs):
|
if len(self._eggs) < int(self._max_eggs):
|
||||||
@ -283,12 +280,13 @@ class Egg(ba.Actor):
|
|||||||
'materials': mats
|
'materials': mats
|
||||||
})
|
})
|
||||||
|
|
||||||
|
def exists(self) -> bool:
|
||||||
|
return bool(self.node)
|
||||||
|
|
||||||
def handlemessage(self, msg: Any) -> Any:
|
def handlemessage(self, msg: Any) -> Any:
|
||||||
if isinstance(msg, ba.DieMessage):
|
if isinstance(msg, ba.DieMessage):
|
||||||
if self.node:
|
if self.node:
|
||||||
self.node.delete()
|
self.node.delete()
|
||||||
elif isinstance(msg, ba.OutOfBoundsMessage):
|
|
||||||
self.handlemessage(ba.DieMessage())
|
|
||||||
elif isinstance(msg, ba.HitMessage):
|
elif isinstance(msg, ba.HitMessage):
|
||||||
if self.node:
|
if self.node:
|
||||||
assert msg.force_direction is not None
|
assert msg.force_direction is not None
|
||||||
|
|||||||
@ -386,8 +386,8 @@ class EliminationGame(ba.TeamGameActivity):
|
|||||||
for team in self.teams:
|
for team in self.teams:
|
||||||
for tplayer in team.players:
|
for tplayer in team.players:
|
||||||
if tplayer.is_alive():
|
if tplayer.is_alive():
|
||||||
assert tplayer.actor is not None and tplayer.actor.node
|
assert tplayer.node
|
||||||
ppos = tplayer.actor.node.position
|
ppos = tplayer.node.position
|
||||||
living_player = tplayer
|
living_player = tplayer
|
||||||
living_player_pos = ppos
|
living_player_pos = ppos
|
||||||
break
|
break
|
||||||
@ -416,20 +416,16 @@ class EliminationGame(ba.TeamGameActivity):
|
|||||||
|
|
||||||
def _print_lives(self, player: ba.Player) -> None:
|
def _print_lives(self, player: ba.Player) -> None:
|
||||||
from bastd.actor import popuptext
|
from bastd.actor import popuptext
|
||||||
if not player or not player.is_alive():
|
assert player # Shouldn't be passing invalid refs around.
|
||||||
return
|
if not player or not player.is_alive() or not player.node:
|
||||||
try:
|
|
||||||
assert player.actor is not None and player.actor.node
|
|
||||||
pos = player.actor.node.position
|
|
||||||
except Exception as exc:
|
|
||||||
print('EXC getting player pos in bs_elim', exc)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
popuptext.PopupText('x' + str(player.gamedata['lives'] - 1),
|
popuptext.PopupText('x' + str(player.gamedata['lives'] - 1),
|
||||||
color=(1, 1, 0, 1),
|
color=(1, 1, 0, 1),
|
||||||
offset=(0, -0.8, 0),
|
offset=(0, -0.8, 0),
|
||||||
random_offset=0.0,
|
random_offset=0.0,
|
||||||
scale=1.8,
|
scale=1.8,
|
||||||
position=pos).autoretain()
|
position=player.node.position).autoretain()
|
||||||
|
|
||||||
def on_player_leave(self, player: ba.Player) -> None:
|
def on_player_leave(self, player: ba.Player) -> None:
|
||||||
ba.TeamGameActivity.on_player_leave(self, player)
|
ba.TeamGameActivity.on_player_leave(self, player)
|
||||||
|
|||||||
@ -128,10 +128,10 @@ class FootballTeamGame(ba.TeamGameActivity):
|
|||||||
True), ("modify_part_collision", "physical", False),
|
True), ("modify_part_collision", "physical", False),
|
||||||
("call", "at_connect", self._handle_score)))
|
("call", "at_connect", self._handle_score)))
|
||||||
self._flag_spawn_pos: Optional[Sequence[float]] = None
|
self._flag_spawn_pos: Optional[Sequence[float]] = None
|
||||||
self._score_regions: List[ba.Actor] = []
|
self._score_regions: List[ba.NodeActor] = []
|
||||||
self._flag: Optional[FootballFlag] = None
|
self._flag: Optional[FootballFlag] = None
|
||||||
self._flag_respawn_timer: Optional[ba.Timer] = None
|
self._flag_respawn_timer: Optional[ba.Timer] = None
|
||||||
self._flag_respawn_light: Optional[ba.Actor] = None
|
self._flag_respawn_light: Optional[ba.NodeActor] = None
|
||||||
|
|
||||||
def get_instance_description(self) -> Union[str, Sequence]:
|
def get_instance_description(self) -> Union[str, Sequence]:
|
||||||
touchdowns = self.settings['Score to Win'] / 7
|
touchdowns = self.settings['Score to Win'] / 7
|
||||||
@ -203,13 +203,8 @@ class FootballTeamGame(ba.TeamGameActivity):
|
|||||||
|
|
||||||
# Tell all players to celebrate.
|
# Tell all players to celebrate.
|
||||||
for player in team.players:
|
for player in team.players:
|
||||||
if player.actor is not None and player.actor.node:
|
if player.actor:
|
||||||
try:
|
player.actor.handlemessage(ba.CelebrateMessage(2.0))
|
||||||
# Note: celebrate message is milliseconds
|
|
||||||
# (for historical reasons).
|
|
||||||
player.actor.node.handlemessage('celebrate', 2000)
|
|
||||||
except Exception:
|
|
||||||
ba.print_exception('Error on celebrate')
|
|
||||||
|
|
||||||
# If someone on this team was last to touch it,
|
# If someone on this team was last to touch it,
|
||||||
# give them points.
|
# give them points.
|
||||||
@ -376,7 +371,7 @@ class FootballCoopGame(ba.CoopGameActivity):
|
|||||||
self._player_has_punched = False
|
self._player_has_punched = False
|
||||||
self._scoreboard: Optional[Scoreboard] = None
|
self._scoreboard: Optional[Scoreboard] = None
|
||||||
self._flag_spawn_pos: Optional[Sequence[float]] = None
|
self._flag_spawn_pos: Optional[Sequence[float]] = None
|
||||||
self.score_regions: List[ba.Actor] = []
|
self.score_regions: List[ba.NodeActor] = []
|
||||||
self._exclude_powerups: List[str] = []
|
self._exclude_powerups: List[str] = []
|
||||||
self._have_tnt = False
|
self._have_tnt = False
|
||||||
self._bot_types_initial: Optional[List[Type[spazbot.SpazBot]]] = None
|
self._bot_types_initial: Optional[List[Type[spazbot.SpazBot]]] = None
|
||||||
@ -384,8 +379,8 @@ class FootballCoopGame(ba.CoopGameActivity):
|
|||||||
self._bot_types_14: Optional[List[Type[spazbot.SpazBot]]] = None
|
self._bot_types_14: Optional[List[Type[spazbot.SpazBot]]] = None
|
||||||
self._bot_team: Optional[ba.Team] = None
|
self._bot_team: Optional[ba.Team] = None
|
||||||
self._starttime_ms: Optional[int] = None
|
self._starttime_ms: Optional[int] = None
|
||||||
self._time_text: Optional[ba.Actor] = None
|
self._time_text: Optional[ba.NodeActor] = None
|
||||||
self._time_text_input: Optional[ba.Actor] = None
|
self._time_text_input: Optional[ba.NodeActor] = None
|
||||||
self._tntspawner: Optional[stdbomb.TNTSpawner] = None
|
self._tntspawner: Optional[stdbomb.TNTSpawner] = None
|
||||||
self._bots = spazbot.BotSet()
|
self._bots = spazbot.BotSet()
|
||||||
self._bot_spawn_timer: Optional[ba.Timer] = None
|
self._bot_spawn_timer: Optional[ba.Timer] = None
|
||||||
@ -580,13 +575,11 @@ class FootballCoopGame(ba.CoopGameActivity):
|
|||||||
assert self._flag is not None
|
assert self._flag is not None
|
||||||
if self._flag.node:
|
if self._flag.node:
|
||||||
for player in self.players:
|
for player in self.players:
|
||||||
try:
|
if player.actor:
|
||||||
assert player.actor is not None and player.actor.node
|
assert isinstance(player.actor, playerspaz.PlayerSpaz)
|
||||||
if (player.actor.is_alive() and
|
if (player.actor.is_alive() and
|
||||||
player.actor.node.hold_node == self._flag.node):
|
player.actor.node.hold_node == self._flag.node):
|
||||||
return
|
return
|
||||||
except Exception:
|
|
||||||
ba.print_exception("exception checking hold node")
|
|
||||||
|
|
||||||
flagpos = ba.Vec3(self._flag.node.position)
|
flagpos = ba.Vec3(self._flag.node.position)
|
||||||
closest_bot = None
|
closest_bot = None
|
||||||
@ -651,7 +644,6 @@ class FootballCoopGame(ba.CoopGameActivity):
|
|||||||
""" a point has been scored """
|
""" a point has been scored """
|
||||||
# FIXME tidy this up
|
# FIXME tidy this up
|
||||||
# pylint: disable=too-many-branches
|
# pylint: disable=too-many-branches
|
||||||
# pylint: disable=too-many-nested-blocks
|
|
||||||
|
|
||||||
# Our flag might stick around for a second or two;
|
# Our flag might stick around for a second or two;
|
||||||
# we don't want it to be able to score again.
|
# we don't want it to be able to score again.
|
||||||
@ -674,16 +666,11 @@ class FootballCoopGame(ba.CoopGameActivity):
|
|||||||
# Tell all players (or bots) to celebrate.
|
# Tell all players (or bots) to celebrate.
|
||||||
if i == 0:
|
if i == 0:
|
||||||
for player in team.players:
|
for player in team.players:
|
||||||
try:
|
if player.actor:
|
||||||
# Note: celebrate message is milliseconds
|
player.actor.handlemessage(
|
||||||
# (for historical reasons).
|
ba.CelebrateMessage(2.0))
|
||||||
if player.actor is not None and player.actor.node:
|
|
||||||
player.actor.node.handlemessage(
|
|
||||||
'celebrate', 2000)
|
|
||||||
except Exception:
|
|
||||||
ba.print_exception()
|
|
||||||
else:
|
else:
|
||||||
self._bots.celebrate(2000)
|
self._bots.celebrate(2.0)
|
||||||
|
|
||||||
# If the good guys scored, add more enemies.
|
# If the good guys scored, add more enemies.
|
||||||
if i == 0:
|
if i == 0:
|
||||||
|
|||||||
@ -193,7 +193,7 @@ class HockeyGame(ba.TeamGameActivity):
|
|||||||
True), ("modify_part_collision", "physical", False),
|
True), ("modify_part_collision", "physical", False),
|
||||||
("call", "at_connect", self._handle_score)))
|
("call", "at_connect", self._handle_score)))
|
||||||
self._puck_spawn_pos: Optional[Sequence[float]] = None
|
self._puck_spawn_pos: Optional[Sequence[float]] = None
|
||||||
self._score_regions: Optional[List[ba.Actor]] = None
|
self._score_regions: Optional[List[ba.NodeActor]] = None
|
||||||
self._puck: Optional[Puck] = None
|
self._puck: Optional[Puck] = None
|
||||||
|
|
||||||
def get_instance_description(self) -> Union[str, Sequence]:
|
def get_instance_description(self) -> Union[str, Sequence]:
|
||||||
@ -284,10 +284,8 @@ class HockeyGame(ba.TeamGameActivity):
|
|||||||
|
|
||||||
# Tell all players to celebrate.
|
# Tell all players to celebrate.
|
||||||
for player in team.players:
|
for player in team.players:
|
||||||
if player.actor is not None and player.actor.node:
|
if player.actor:
|
||||||
# Note: celebrate message takes milliseconds
|
player.actor.handlemessage(ba.CelebrateMessage(2.0))
|
||||||
# (for historical reasons).
|
|
||||||
player.actor.node.handlemessage('celebrate', 2000)
|
|
||||||
|
|
||||||
# If we've got the player from the scoring team that last
|
# If we've got the player from the scoring team that last
|
||||||
# touched us, give them points.
|
# touched us, give them points.
|
||||||
|
|||||||
@ -194,7 +194,7 @@ class KeepAwayGame(ba.TeamGameActivity):
|
|||||||
for player in self.players:
|
for player in self.players:
|
||||||
holding_flag = False
|
holding_flag = False
|
||||||
try:
|
try:
|
||||||
assert player.actor is not None
|
assert isinstance(player.actor, playerspaz.PlayerSpaz)
|
||||||
if (player.actor.is_alive() and player.actor.node
|
if (player.actor.is_alive() and player.actor.node
|
||||||
and player.actor.node.hold_node):
|
and player.actor.node.hold_node):
|
||||||
holding_flag = (
|
holding_flag = (
|
||||||
|
|||||||
@ -188,7 +188,9 @@ class NinjaFightGame(ba.TeamGameActivity):
|
|||||||
ba.cameraflash()
|
ba.cameraflash()
|
||||||
ba.playsound(self._winsound)
|
ba.playsound(self._winsound)
|
||||||
for team in self.teams:
|
for team in self.teams:
|
||||||
team.celebrate() # Woooo! par-tay!
|
for player in team.players:
|
||||||
|
if player.actor:
|
||||||
|
player.actor.handlemessage(ba.CelebrateMessage())
|
||||||
results.set_team_score(team, elapsed_time_ms)
|
results.set_team_score(team, elapsed_time_ms)
|
||||||
|
|
||||||
# Ends the activity.
|
# Ends the activity.
|
||||||
|
|||||||
@ -105,7 +105,7 @@ class OnslaughtGame(ba.CoopGameActivity):
|
|||||||
self._can_end_wave = True
|
self._can_end_wave = True
|
||||||
self._score = 0
|
self._score = 0
|
||||||
self._time_bonus = 0
|
self._time_bonus = 0
|
||||||
self._spawn_info_text: Optional[ba.Actor] = None
|
self._spawn_info_text: Optional[ba.NodeActor] = None
|
||||||
self._dingsound = ba.getsound('dingSmall')
|
self._dingsound = ba.getsound('dingSmall')
|
||||||
self._dingsoundhigh = ba.getsound('dingSmallHigh')
|
self._dingsoundhigh = ba.getsound('dingSmallHigh')
|
||||||
self._have_tnt = False
|
self._have_tnt = False
|
||||||
@ -115,9 +115,9 @@ class OnslaughtGame(ba.CoopGameActivity):
|
|||||||
self._bots: Optional[spazbot.BotSet] = None
|
self._bots: Optional[spazbot.BotSet] = None
|
||||||
self._powerup_drop_timer: Optional[ba.Timer] = None
|
self._powerup_drop_timer: Optional[ba.Timer] = None
|
||||||
self._time_bonus_timer: Optional[ba.Timer] = None
|
self._time_bonus_timer: Optional[ba.Timer] = None
|
||||||
self._time_bonus_text: Optional[ba.Actor] = None
|
self._time_bonus_text: Optional[ba.NodeActor] = None
|
||||||
self._flawless_bonus: Optional[int] = None
|
self._flawless_bonus: Optional[int] = None
|
||||||
self._wave_text: Optional[ba.Actor] = None
|
self._wave_text: Optional[ba.NodeActor] = None
|
||||||
self._wave_update_timer: Optional[ba.Timer] = None
|
self._wave_update_timer: Optional[ba.Timer] = None
|
||||||
self._throw_off_kills = 0
|
self._throw_off_kills = 0
|
||||||
self._land_mine_kills = 0
|
self._land_mine_kills = 0
|
||||||
@ -873,7 +873,7 @@ class OnslaughtGame(ba.CoopGameActivity):
|
|||||||
if self._game_over:
|
if self._game_over:
|
||||||
return
|
return
|
||||||
|
|
||||||
# respawn applicable players
|
# Respawn applicable players.
|
||||||
if self._wave > 1 and not self.is_waiting_for_continue():
|
if self._wave > 1 and not self.is_waiting_for_continue():
|
||||||
for player in self.players:
|
for player in self.players:
|
||||||
if (not player.is_alive()
|
if (not player.is_alive()
|
||||||
|
|||||||
@ -189,6 +189,7 @@ class RaceGame(ba.TeamGameActivity):
|
|||||||
self._regions.append(RaceRegion(rpt, len(self._regions)))
|
self._regions.append(RaceRegion(rpt, len(self._regions)))
|
||||||
|
|
||||||
def _flash_player(self, player: ba.Player, scale: float) -> None:
|
def _flash_player(self, player: ba.Player, scale: float) -> None:
|
||||||
|
assert isinstance(player.actor, PlayerSpaz)
|
||||||
assert player.actor is not None and player.actor.node
|
assert player.actor is not None and player.actor.node
|
||||||
pos = player.actor.node.position
|
pos = player.actor.node.position
|
||||||
light = ba.newnode('light',
|
light = ba.newnode('light',
|
||||||
@ -523,6 +524,7 @@ class RaceGame(ba.TeamGameActivity):
|
|||||||
for player in self.players:
|
for player in self.players:
|
||||||
pos: Optional[ba.Vec3]
|
pos: Optional[ba.Vec3]
|
||||||
try:
|
try:
|
||||||
|
assert isinstance(player.actor, PlayerSpaz)
|
||||||
assert player.actor is not None and player.actor.node
|
assert player.actor is not None and player.actor.node
|
||||||
pos = ba.Vec3(player.actor.node.position)
|
pos = ba.Vec3(player.actor.node.position)
|
||||||
except Exception:
|
except Exception:
|
||||||
|
|||||||
@ -117,15 +117,15 @@ class RunaroundGame(ba.CoopGameActivity):
|
|||||||
self._waves: Optional[List[Dict[str, Any]]] = None
|
self._waves: Optional[List[Dict[str, Any]]] = None
|
||||||
self._bots = spazbot.BotSet()
|
self._bots = spazbot.BotSet()
|
||||||
self._tntspawner: Optional[TNTSpawner] = None
|
self._tntspawner: Optional[TNTSpawner] = None
|
||||||
self._lives_bg: Optional[ba.Actor] = None
|
self._lives_bg: Optional[ba.NodeActor] = None
|
||||||
self._start_lives = 10
|
self._start_lives = 10
|
||||||
self._lives = self._start_lives
|
self._lives = self._start_lives
|
||||||
self._lives_text: Optional[ba.Actor] = None
|
self._lives_text: Optional[ba.NodeActor] = None
|
||||||
self._flawless = True
|
self._flawless = True
|
||||||
self._time_bonus_timer: Optional[ba.Timer] = None
|
self._time_bonus_timer: Optional[ba.Timer] = None
|
||||||
self._time_bonus_text: Optional[ba.Actor] = None
|
self._time_bonus_text: Optional[ba.NodeActor] = None
|
||||||
self._time_bonus_mult: Optional[float] = None
|
self._time_bonus_mult: Optional[float] = None
|
||||||
self._wave_text: Optional[ba.Actor] = None
|
self._wave_text: Optional[ba.NodeActor] = None
|
||||||
self._flawless_bonus: Optional[int] = None
|
self._flawless_bonus: Optional[int] = None
|
||||||
self._wave_update_timer: Optional[ba.Timer] = None
|
self._wave_update_timer: Optional[ba.Timer] = None
|
||||||
|
|
||||||
@ -1050,10 +1050,12 @@ class RunaroundGame(ba.CoopGameActivity):
|
|||||||
def _update_bot(self, bot: spazbot.SpazBot) -> bool:
|
def _update_bot(self, bot: spazbot.SpazBot) -> bool:
|
||||||
# Yup; that's a lot of return statements right there.
|
# Yup; that's a lot of return statements right there.
|
||||||
# pylint: disable=too-many-return-statements
|
# pylint: disable=too-many-return-statements
|
||||||
assert bot.node
|
|
||||||
if not bot.is_alive() or not bot.node.exists():
|
if not bool(bot):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
assert bot.node
|
||||||
|
|
||||||
# FIXME: Do this in a type safe way.
|
# FIXME: Do this in a type safe way.
|
||||||
r_walk_speed: float = bot.r_walk_speed # type: ignore
|
r_walk_speed: float = bot.r_walk_speed # type: ignore
|
||||||
r_walk_row: int = bot.r_walk_row # type: ignore
|
r_walk_row: int = bot.r_walk_row # type: ignore
|
||||||
|
|||||||
@ -197,6 +197,7 @@ class TheLastStandGame(ba.CoopGameActivity):
|
|||||||
for player in self.players:
|
for player in self.players:
|
||||||
try:
|
try:
|
||||||
if player.is_alive():
|
if player.is_alive():
|
||||||
|
assert isinstance(player.actor, playerspaz.PlayerSpaz)
|
||||||
assert player.actor is not None and player.actor.node
|
assert player.actor is not None and player.actor.node
|
||||||
playerpts.append(player.actor.node.position)
|
playerpts.append(player.actor.node.position)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
|
|||||||
@ -262,7 +262,7 @@ class MainMenuActivity(ba.Activity):
|
|||||||
self._valid = True
|
self._valid = True
|
||||||
self._message_duration = 10.0
|
self._message_duration = 10.0
|
||||||
self._message_spacing = 2.0
|
self._message_spacing = 2.0
|
||||||
self._text: Optional[ba.Actor] = None
|
self._text: Optional[ba.NodeActor] = None
|
||||||
self._activity = weakref.ref(activity)
|
self._activity = weakref.ref(activity)
|
||||||
|
|
||||||
# If we're signed in, fetch news immediately.
|
# If we're signed in, fetch news immediately.
|
||||||
@ -290,8 +290,8 @@ class MainMenuActivity(ba.Activity):
|
|||||||
|
|
||||||
# If our news is way out of date, lets re-request it;
|
# If our news is way out of date, lets re-request it;
|
||||||
# otherwise, rotate our phrase.
|
# otherwise, rotate our phrase.
|
||||||
assert app.main_menu_last_news_fetch_time is not None
|
assert ba.app.main_menu_last_news_fetch_time is not None
|
||||||
if time.time() - app.main_menu_last_news_fetch_time > 600.0:
|
if time.time() - ba.app.main_menu_last_news_fetch_time > 600.0:
|
||||||
self._fetch_news()
|
self._fetch_news()
|
||||||
self._text = None
|
self._text = None
|
||||||
else:
|
else:
|
||||||
|
|||||||
@ -1169,8 +1169,8 @@ class TowerD(ba.Map):
|
|||||||
running: bool = False) -> bool:
|
running: bool = False) -> bool:
|
||||||
# see if we're within edge_box
|
# see if we're within edge_box
|
||||||
boxes = self.defs.boxes
|
boxes = self.defs.boxes
|
||||||
box_position = boxes['edge_box1'][0:3]
|
box_position = boxes['edge_box'][0:3]
|
||||||
box_scale = boxes['edge_box1'][6:9]
|
box_scale = boxes['edge_box'][6:9]
|
||||||
box_position2 = boxes['edge_box2'][0:3]
|
box_position2 = boxes['edge_box2'][0:3]
|
||||||
box_scale2 = boxes['edge_box2'][6:9]
|
box_scale2 = boxes['edge_box2'][6:9]
|
||||||
xpos = (point.x - box_position[0]) / box_scale[0]
|
xpos = (point.x - box_position[0]) / box_scale[0]
|
||||||
|
|||||||
@ -1,4 +1,2 @@
|
|||||||
+/tools
|
+/tools
|
||||||
+/src/ballistica
|
|
||||||
+/src/generated_src
|
|
||||||
+/assets/src/ba_data/python
|
+/assets/src/ba_data/python
|
||||||
|
|||||||
@ -80,6 +80,12 @@ good-names=i,
|
|||||||
U,
|
U,
|
||||||
_
|
_
|
||||||
|
|
||||||
|
[TYPECHECK]
|
||||||
|
# Mypy does most all the type checking we need, and in some cases
|
||||||
|
# Pylint has conflicting views about what types it thinks things are,
|
||||||
|
# so let's just flip stuff off here.
|
||||||
|
disable=no-member
|
||||||
|
|
||||||
[MISCELLANEOUS]
|
[MISCELLANEOUS]
|
||||||
# We've got various TODO and FIXME notes in scripts, but don't want
|
# We've got various TODO and FIXME notes in scripts, but don't want
|
||||||
# lint to trigger over that fact.
|
# lint to trigger over that fact.
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<!-- THIS FILE IS AUTO GENERATED; DO NOT EDIT BY HAND -->
|
<!-- THIS FILE IS AUTO GENERATED; DO NOT EDIT BY HAND -->
|
||||||
<h4><em>last updated on 2020-04-06 for Ballistica version 1.5.0 build 20001</em></h4>
|
<h4><em>last updated on 2020-04-07 for Ballistica version 1.5.0 build 20001</em></h4>
|
||||||
<p>This page documents the Python classes and functions in the 'ba' module,
|
<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>
|
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>
|
<hr>
|
||||||
@ -112,6 +112,7 @@
|
|||||||
</ul>
|
</ul>
|
||||||
<h4><a name="class_category_Message_Classes">Message Classes</a></h4>
|
<h4><a name="class_category_Message_Classes">Message Classes</a></h4>
|
||||||
<ul>
|
<ul>
|
||||||
|
<li><a href="#class_ba_CelebrateMessage">ba.CelebrateMessage</a></li>
|
||||||
<li><a href="#class_ba_DieMessage">ba.DieMessage</a></li>
|
<li><a href="#class_ba_DieMessage">ba.DieMessage</a></li>
|
||||||
<li><a href="#class_ba_DropMessage">ba.DropMessage</a></li>
|
<li><a href="#class_ba_DropMessage">ba.DropMessage</a></li>
|
||||||
<li><a href="#class_ba_DroppedMessage">ba.DroppedMessage</a></li>
|
<li><a href="#class_ba_DroppedMessage">ba.DroppedMessage</a></li>
|
||||||
@ -646,9 +647,6 @@ or returns None depending on whether 'doraise' is set.</p>
|
|||||||
|
|
||||||
<p>General message handling; can be passed any <a href="#class_category_Message_Classes">message object</a>.</p>
|
<p>General message handling; can be passed any <a href="#class_category_Message_Classes">message object</a>.</p>
|
||||||
|
|
||||||
<p>The default implementation will handle <a href="#class_ba_DieMessage">ba.DieMessages</a> by
|
|
||||||
calling self.node.delete() if self contains a 'node' attribute.</p>
|
|
||||||
|
|
||||||
</dd>
|
</dd>
|
||||||
<dt><h4><a name="method_ba_Actor__is_alive">is_alive()</a></dt></h4><dd>
|
<dt><h4><a name="method_ba_Actor__is_alive">is_alive()</a></dt></h4><dd>
|
||||||
<p><span>is_alive(self) -> bool</span></p>
|
<p><span>is_alive(self) -> bool</span></p>
|
||||||
@ -1183,6 +1181,29 @@ mycall()</pre>
|
|||||||
|
|
||||||
<p>Set the Level currently selected in the UI (by name).</p>
|
<p>Set the Level currently selected in the UI (by name).</p>
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
<hr>
|
||||||
|
<h2><strong><a name="class_ba_CelebrateMessage">ba.CelebrateMessage</a></strong></h3>
|
||||||
|
<p><em><top level class></em>
|
||||||
|
</p>
|
||||||
|
<p>Tells an object to celebrate.</p>
|
||||||
|
|
||||||
|
<p>Category: <a href="#class_category_Message_Classes">Message Classes</a></p>
|
||||||
|
|
||||||
|
<h3>Attributes:</h3>
|
||||||
|
<dl>
|
||||||
|
<dt><h4><a name="attr_ba_CelebrateMessage__duration">duration</a></h4></dt><dd>
|
||||||
|
<p><span>float</span></p>
|
||||||
|
<p>Amount of time to celebrate in seconds.</p>
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
<h3>Methods:</h3>
|
||||||
|
<dl>
|
||||||
|
<dt><h4><a name="method_ba_CelebrateMessage____init__"><constructor></a></dt></h4><dd>
|
||||||
|
<p><span>ba.CelebrateMessage(duration: float = 10.0)</span></p>
|
||||||
|
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
<hr>
|
<hr>
|
||||||
@ -1586,6 +1607,7 @@ the data object is requested and when it's value is accessed.</p>
|
|||||||
<h3>Values:</h3>
|
<h3>Values:</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li>GENERIC</li>
|
<li>GENERIC</li>
|
||||||
|
<li>OUT_OF_BOUNDS</li>
|
||||||
<li>IMPACT</li>
|
<li>IMPACT</li>
|
||||||
<li>FALL</li>
|
<li>FALL</li>
|
||||||
<li>REACHED_GOAL</li>
|
<li>REACHED_GOAL</li>
|
||||||
@ -2782,15 +2804,35 @@ etc.</p>
|
|||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
<h3>Methods Inherited:</h3>
|
<h3>Methods Inherited:</h3>
|
||||||
<h5><a href="#method_ba_Actor__autoretain">autoretain()</a>, <a href="#method_ba_Actor__exists">exists()</a>, <a href="#method_ba_Actor__getactivity">getactivity()</a>, <a href="#method_ba_Actor__is_alive">is_alive()</a>, <a href="#method_ba_Actor__is_expired">is_expired()</a>, <a href="#method_ba_Actor__on_expire">on_expire()</a></h5>
|
<h5><a href="#method_ba_Actor__autoretain">autoretain()</a>, <a href="#method_ba_Actor__getactivity">getactivity()</a>, <a href="#method_ba_Actor__is_alive">is_alive()</a>, <a href="#method_ba_Actor__is_expired">is_expired()</a>, <a href="#method_ba_Actor__on_expire">on_expire()</a></h5>
|
||||||
<h3>Methods Defined or Overridden:</h3>
|
<h3>Methods Defined or Overridden:</h3>
|
||||||
<h5><a href="#method_ba_Map____init__"><constructor></a>, <a href="#method_ba_Map__get_def_bound_box">get_def_bound_box()</a>, <a href="#method_ba_Map__get_def_point">get_def_point()</a>, <a href="#method_ba_Map__get_def_points">get_def_points()</a>, <a href="#method_ba_Map__get_ffa_start_position">get_ffa_start_position()</a>, <a href="#method_ba_Map__get_flag_position">get_flag_position()</a>, <a href="#method_ba_Map__get_music_type">get_music_type()</a>, <a href="#method_ba_Map__get_name">get_name()</a>, <a href="#method_ba_Map__get_play_types">get_play_types()</a>, <a href="#method_ba_Map__get_preview_texture_name">get_preview_texture_name()</a>, <a href="#method_ba_Map__get_start_position">get_start_position()</a>, <a href="#method_ba_Map__handlemessage">handlemessage()</a>, <a href="#method_ba_Map__is_point_near_edge">is_point_near_edge()</a>, <a href="#method_ba_Map__on_preload">on_preload()</a>, <a href="#method_ba_Map__preload">preload()</a></h5>
|
<h5><a href="#method_ba_Map____init__"><constructor></a>, <a href="#method_ba_Map__exists">exists()</a>, <a href="#method_ba_Map__get_def_bound_box">get_def_bound_box()</a>, <a href="#method_ba_Map__get_def_point">get_def_point()</a>, <a href="#method_ba_Map__get_def_points">get_def_points()</a>, <a href="#method_ba_Map__get_ffa_start_position">get_ffa_start_position()</a>, <a href="#method_ba_Map__get_flag_position">get_flag_position()</a>, <a href="#method_ba_Map__get_music_type">get_music_type()</a>, <a href="#method_ba_Map__get_name">get_name()</a>, <a href="#method_ba_Map__get_play_types">get_play_types()</a>, <a href="#method_ba_Map__get_preview_texture_name">get_preview_texture_name()</a>, <a href="#method_ba_Map__get_start_position">get_start_position()</a>, <a href="#method_ba_Map__handlemessage">handlemessage()</a>, <a href="#method_ba_Map__is_point_near_edge">is_point_near_edge()</a>, <a href="#method_ba_Map__on_preload">on_preload()</a>, <a href="#method_ba_Map__preload">preload()</a></h5>
|
||||||
<dl>
|
<dl>
|
||||||
<dt><h4><a name="method_ba_Map____init__"><constructor></a></dt></h4><dd>
|
<dt><h4><a name="method_ba_Map____init__"><constructor></a></dt></h4><dd>
|
||||||
<p><span>ba.Map(vr_overlay_offset: Optional[Sequence[float]] = None)</span></p>
|
<p><span>ba.Map(vr_overlay_offset: Optional[Sequence[float]] = None)</span></p>
|
||||||
|
|
||||||
<p>Instantiate a map.</p>
|
<p>Instantiate a map.</p>
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
<dt><h4><a name="method_ba_Map__exists">exists()</a></dt></h4><dd>
|
||||||
|
<p><span>exists(self) -> bool</span></p>
|
||||||
|
|
||||||
|
<p>Returns whether the Actor is still present in a meaningful way.</p>
|
||||||
|
|
||||||
|
<p>Note that a dying character should still return True here as long as
|
||||||
|
their corpse is visible; this is about presence, not being 'alive'
|
||||||
|
(see <a href="#method_ba_Actor__is_alive">ba.Actor.is_alive</a>() for that).</p>
|
||||||
|
|
||||||
|
<p>If this returns False, it is assumed the Actor can be completely
|
||||||
|
deleted without affecting the game; this call is often used
|
||||||
|
when pruning lists of Actors, such as with <a href="#method_ba_Actor__autoretain">ba.Actor.autoretain</a>()</p>
|
||||||
|
|
||||||
|
<p>The default implementation of this method always return True.</p>
|
||||||
|
|
||||||
|
<p>Note that the boolean operator for the Actor class calls this method,
|
||||||
|
so a simple "if myactor" test will conveniently do the right thing
|
||||||
|
even if myactor is set to None.</p>
|
||||||
|
|
||||||
</dd>
|
</dd>
|
||||||
<dt><h4><a name="method_ba_Map__get_def_bound_box">get_def_bound_box()</a></dt></h4><dd>
|
<dt><h4><a name="method_ba_Map__get_def_bound_box">get_def_bound_box()</a></dt></h4><dd>
|
||||||
<p><span>get_def_bound_box(self, name: str) -> Optional[Tuple[float, float, float, float, float, float]]</span></p>
|
<p><span>get_def_bound_box(self, name: str) -> Optional[Tuple[float, float, float, float, float, float]]</span></p>
|
||||||
@ -2872,9 +2914,6 @@ as far from these players as possible.</p>
|
|||||||
|
|
||||||
<p>General message handling; can be passed any <a href="#class_category_Message_Classes">message object</a>.</p>
|
<p>General message handling; can be passed any <a href="#class_category_Message_Classes">message object</a>.</p>
|
||||||
|
|
||||||
<p>The default implementation will handle <a href="#class_ba_DieMessage">ba.DieMessages</a> by
|
|
||||||
calling self.node.delete() if self contains a 'node' attribute.</p>
|
|
||||||
|
|
||||||
</dd>
|
</dd>
|
||||||
<dt><h4><a name="method_ba_Map__is_point_near_edge">is_point_near_edge()</a></dt></h4><dd>
|
<dt><h4><a name="method_ba_Map__is_point_near_edge">is_point_near_edge()</a></dt></h4><dd>
|
||||||
<p><span>is_point_near_edge(self, point: <a href="#class_ba_Vec3">ba.Vec3</a>, running: bool = False) -> bool</span></p>
|
<p><span>is_point_near_edge(self, point: <a href="#class_ba_Vec3">ba.Vec3</a>, running: bool = False) -> bool</span></p>
|
||||||
@ -3347,24 +3386,41 @@ acting as an alternative to setting node attributes.</p>
|
|||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
<h3>Methods Inherited:</h3>
|
<h3>Methods Inherited:</h3>
|
||||||
<h5><a href="#method_ba_Actor__autoretain">autoretain()</a>, <a href="#method_ba_Actor__exists">exists()</a>, <a href="#method_ba_Actor__getactivity">getactivity()</a>, <a href="#method_ba_Actor__is_alive">is_alive()</a>, <a href="#method_ba_Actor__is_expired">is_expired()</a>, <a href="#method_ba_Actor__on_expire">on_expire()</a></h5>
|
<h5><a href="#method_ba_Actor__autoretain">autoretain()</a>, <a href="#method_ba_Actor__getactivity">getactivity()</a>, <a href="#method_ba_Actor__is_alive">is_alive()</a>, <a href="#method_ba_Actor__is_expired">is_expired()</a>, <a href="#method_ba_Actor__on_expire">on_expire()</a></h5>
|
||||||
<h3>Methods Defined or Overridden:</h3>
|
<h3>Methods Defined or Overridden:</h3>
|
||||||
<h5><a href="#method_ba_NodeActor____init__"><constructor></a>, <a href="#method_ba_NodeActor__handlemessage">handlemessage()</a></h5>
|
<h5><a href="#method_ba_NodeActor____init__"><constructor></a>, <a href="#method_ba_NodeActor__exists">exists()</a>, <a href="#method_ba_NodeActor__handlemessage">handlemessage()</a></h5>
|
||||||
<dl>
|
<dl>
|
||||||
<dt><h4><a name="method_ba_NodeActor____init__"><constructor></a></dt></h4><dd>
|
<dt><h4><a name="method_ba_NodeActor____init__"><constructor></a></dt></h4><dd>
|
||||||
<p><span>ba.NodeActor(node: <a href="#class_ba_Node">ba.Node</a>)</span></p>
|
<p><span>ba.NodeActor(node: <a href="#class_ba_Node">ba.Node</a>)</span></p>
|
||||||
|
|
||||||
<p>Instantiates an Actor in the current <a href="#class_ba_Activity">ba.Activity</a>.</p>
|
<p>Instantiates an Actor in the current <a href="#class_ba_Activity">ba.Activity</a>.</p>
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
<dt><h4><a name="method_ba_NodeActor__exists">exists()</a></dt></h4><dd>
|
||||||
|
<p><span>exists(self) -> bool</span></p>
|
||||||
|
|
||||||
|
<p>Returns whether the Actor is still present in a meaningful way.</p>
|
||||||
|
|
||||||
|
<p>Note that a dying character should still return True here as long as
|
||||||
|
their corpse is visible; this is about presence, not being 'alive'
|
||||||
|
(see <a href="#method_ba_Actor__is_alive">ba.Actor.is_alive</a>() for that).</p>
|
||||||
|
|
||||||
|
<p>If this returns False, it is assumed the Actor can be completely
|
||||||
|
deleted without affecting the game; this call is often used
|
||||||
|
when pruning lists of Actors, such as with <a href="#method_ba_Actor__autoretain">ba.Actor.autoretain</a>()</p>
|
||||||
|
|
||||||
|
<p>The default implementation of this method always return True.</p>
|
||||||
|
|
||||||
|
<p>Note that the boolean operator for the Actor class calls this method,
|
||||||
|
so a simple "if myactor" test will conveniently do the right thing
|
||||||
|
even if myactor is set to None.</p>
|
||||||
|
|
||||||
</dd>
|
</dd>
|
||||||
<dt><h4><a name="method_ba_NodeActor__handlemessage">handlemessage()</a></dt></h4><dd>
|
<dt><h4><a name="method_ba_NodeActor__handlemessage">handlemessage()</a></dt></h4><dd>
|
||||||
<p><span>handlemessage(self, msg: Any) -> Any</span></p>
|
<p><span>handlemessage(self, msg: Any) -> Any</span></p>
|
||||||
|
|
||||||
<p>General message handling; can be passed any <a href="#class_category_Message_Classes">message object</a>.</p>
|
<p>General message handling; can be passed any <a href="#class_category_Message_Classes">message object</a>.</p>
|
||||||
|
|
||||||
<p>The default implementation will handle <a href="#class_ba_DieMessage">ba.DieMessages</a> by
|
|
||||||
calling self.node.delete() if self contains a 'node' attribute.</p>
|
|
||||||
|
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
<hr>
|
<hr>
|
||||||
@ -4267,7 +4323,7 @@ of the session.</p>
|
|||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
<h3>Methods:</h3>
|
<h3>Methods:</h3>
|
||||||
<h5><a href="#method_ba_Team____init__"><constructor></a>, <a href="#method_ba_Team__celebrate">celebrate()</a>, <a href="#method_ba_Team__get_id">get_id()</a></h5>
|
<h5><a href="#method_ba_Team____init__"><constructor></a>, <a href="#method_ba_Team__get_id">get_id()</a></h5>
|
||||||
<dl>
|
<dl>
|
||||||
<dt><h4><a name="method_ba_Team____init__"><constructor></a></dt></h4><dd>
|
<dt><h4><a name="method_ba_Team____init__"><constructor></a></dt></h4><dd>
|
||||||
<p><span>ba.Team(team_id: 'int' = 0, name: 'Union[<a href="#class_ba_Lstr">ba.Lstr</a>, str]' = '', color: 'Sequence[float]' = (1.0, 1.0, 1.0))</span></p>
|
<p><span>ba.Team(team_id: 'int' = 0, name: 'Union[<a href="#class_ba_Lstr">ba.Lstr</a>, str]' = '', color: 'Sequence[float]' = (1.0, 1.0, 1.0))</span></p>
|
||||||
@ -4277,14 +4333,6 @@ of the session.</p>
|
|||||||
<p>In most cases, all teams are provided to you by the <a href="#class_ba_Session">ba.Session</a>,
|
<p>In most cases, all teams are provided to you by the <a href="#class_ba_Session">ba.Session</a>,
|
||||||
<a href="#class_ba_Session">ba.Session</a>, so calling this shouldn't be necessary.</p>
|
<a href="#class_ba_Session">ba.Session</a>, so calling this shouldn't be necessary.</p>
|
||||||
|
|
||||||
</dd>
|
|
||||||
<dt><h4><a name="method_ba_Team__celebrate">celebrate()</a></dt></h4><dd>
|
|
||||||
<p><span>celebrate(self, duration: float = 10.0) -> None</span></p>
|
|
||||||
|
|
||||||
<p>Tells all players on the team to celebrate.</p>
|
|
||||||
|
|
||||||
<p>duration is given in seconds.</p>
|
|
||||||
|
|
||||||
</dd>
|
</dd>
|
||||||
<dt><h4><a name="method_ba_Team__get_id">get_id()</a></dt></h4><dd>
|
<dt><h4><a name="method_ba_Team__get_id">get_id()</a></dt></h4><dd>
|
||||||
<p><span>get_id(self) -> int</span></p>
|
<p><span>get_id(self) -> int</span></p>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user