mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-01-26 17:03:14 +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,
|
||||
PickedUpMessage, DroppedMessage,
|
||||
ShouldShatterMessage, ImpactDamageMessage,
|
||||
FreezeMessage, ThawMessage, HitMessage)
|
||||
FreezeMessage, ThawMessage, HitMessage,
|
||||
CelebrateMessage)
|
||||
from ba._music import setmusic, MusicPlayer, MusicType, MusicPlayMode
|
||||
from ba._powerup import PowerupMessage, PowerupAcceptMessage
|
||||
from ba._teambasesession import TeamBaseSession
|
||||
|
||||
@ -25,6 +25,9 @@ from __future__ import annotations
|
||||
import weakref
|
||||
from typing import TYPE_CHECKING, TypeVar
|
||||
|
||||
from ba._messages import DieMessage, DeathType, OutOfBoundsMessage
|
||||
from ba import _error
|
||||
|
||||
import _ba
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@ -83,9 +86,11 @@ class Actor:
|
||||
def __init__(self) -> None:
|
||||
"""Instantiates an Actor in the current ba.Activity."""
|
||||
|
||||
# FIXME: Actor should not be require to have a 'node' attr.
|
||||
self.node: Optional[ba.Node] = None
|
||||
# FIXME: Actor should not be assumed to have a 'node' attr.
|
||||
# self.node: Optional[ba.Node] = None
|
||||
|
||||
if __debug__:
|
||||
self._root_actor_init_called = True
|
||||
activity = _ba.getactivity()
|
||||
self._activity = weakref.ref(activity)
|
||||
activity.add_actor_weak_ref(self)
|
||||
@ -96,27 +101,20 @@ class Actor:
|
||||
# That way we can treat DieMessage handling as the single
|
||||
# point-of-action for death.
|
||||
if not self.is_expired():
|
||||
from ba import _messages
|
||||
self.handlemessage(_messages.DieMessage())
|
||||
self.handlemessage(DieMessage())
|
||||
except Exception:
|
||||
from ba import _error
|
||||
_error.print_exception('exception in ba.Actor.__del__() for', self)
|
||||
|
||||
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
|
||||
calling self.node.delete() if self contains a 'node' attribute.
|
||||
"""
|
||||
from ba._error import UNHANDLED
|
||||
del msg # Unused.
|
||||
return UNHANDLED
|
||||
# By default, actors going out-of-bounds simply kill themselves.
|
||||
if isinstance(msg, OutOfBoundsMessage):
|
||||
return self.handlemessage(DieMessage(how=DeathType.OUT_OF_BOUNDS))
|
||||
|
||||
def _handlemessage_sanity_check(self) -> None:
|
||||
if self.is_expired():
|
||||
from ba import _error
|
||||
_error.print_error(
|
||||
f'handlemessage called on expired actor: {self}')
|
||||
return _error.UNHANDLED
|
||||
|
||||
def autoretain(self: T) -> T:
|
||||
"""Keep this Actor alive without needing to hold a reference to it.
|
||||
@ -131,8 +129,7 @@ class Actor:
|
||||
"""
|
||||
activity = self._activity()
|
||||
if activity is None:
|
||||
from ba._error import ActivityNotFoundError
|
||||
raise ActivityNotFoundError()
|
||||
raise _error.ActivityNotFoundError()
|
||||
activity.retain_actor(self)
|
||||
return self
|
||||
|
||||
@ -192,6 +189,21 @@ class Actor:
|
||||
"""
|
||||
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
|
||||
def activity(self) -> ba.Activity:
|
||||
"""The Activity this Actor was created in.
|
||||
@ -200,8 +212,7 @@ class Actor:
|
||||
"""
|
||||
activity = self._activity()
|
||||
if activity is None:
|
||||
from ba._error import ActivityNotFoundError
|
||||
raise ActivityNotFoundError()
|
||||
raise _error.ActivityNotFoundError()
|
||||
return activity
|
||||
|
||||
def getactivity(self, doraise: bool = True) -> Optional[ba.Activity]:
|
||||
@ -212,6 +223,5 @@ class Actor:
|
||||
"""
|
||||
activity = self._activity()
|
||||
if activity is None and doraise:
|
||||
from ba._error import ActivityNotFoundError
|
||||
raise ActivityNotFoundError()
|
||||
raise _error.ActivityNotFoundError()
|
||||
return activity
|
||||
|
||||
@ -188,7 +188,6 @@ def print_live_object_warnings(when: Any,
|
||||
ignore_session: ba.Session = None,
|
||||
ignore_activity: ba.Activity = None) -> None:
|
||||
"""Print warnings for remaining objects in the current context."""
|
||||
# pylint: disable=too-many-branches
|
||||
# pylint: disable=cyclic-import
|
||||
import gc
|
||||
from ba import _session as bs_session
|
||||
@ -252,13 +251,14 @@ def print_live_object_warnings(when: Any,
|
||||
for actor in actors:
|
||||
_ba.app.printed_live_object_warning = True
|
||||
print('ERROR: Actor found', when, ':', actor)
|
||||
if isinstance(actor, bs_actor.Actor):
|
||||
try:
|
||||
if actor.node:
|
||||
print(' - contains node:', actor.node.getnodetype(), ';',
|
||||
actor.node.get_name())
|
||||
except Exception as exc:
|
||||
print(' - exception checking actor node:', exc)
|
||||
# if isinstance(actor, bs_actor.Actor):
|
||||
# try:
|
||||
# if actor.node:
|
||||
# print(' - contains node:',
|
||||
# actor.node.getnodetype(), ';',
|
||||
# actor.node.get_name())
|
||||
# except Exception as exc:
|
||||
# print(' - exception checking actor node:', exc)
|
||||
# refs = list(gc.get_referrers(actor))
|
||||
# i = 1
|
||||
# for ref in refs:
|
||||
|
||||
@ -135,10 +135,10 @@ class CoopGameActivity(GameActivity):
|
||||
a wave.
|
||||
duration is given in seconds.
|
||||
"""
|
||||
from ba._messages import CelebrateMessage
|
||||
for player in self.players:
|
||||
if player.actor is not None and player.actor.node:
|
||||
player.actor.node.handlemessage('celebrate',
|
||||
int(duration * 1000))
|
||||
if player.actor:
|
||||
player.actor.handlemessage(CelebrateMessage(duration))
|
||||
|
||||
def _preload_achievements(self) -> None:
|
||||
from ba import _achievement
|
||||
|
||||
@ -315,7 +315,6 @@ class AssetPackage(DependencyComponent):
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
# pylint: disable=no-member
|
||||
|
||||
# This is used internally by the get_package_xxx calls.
|
||||
self.context = _ba.Context('current')
|
||||
|
||||
@ -337,13 +337,13 @@ class GameActivity(Activity):
|
||||
self._game_scoreboard_description_text: Optional[ba.Actor] = None
|
||||
self._standard_time_limit_time: Optional[int] = None
|
||||
self._standard_time_limit_timer: Optional[ba.Timer] = None
|
||||
self._standard_time_limit_text: Optional[ba.Actor] = None
|
||||
self._standard_time_limit_text_input: Optional[ba.Actor] = None
|
||||
self._standard_time_limit_text: Optional[ba.NodeActor] = None
|
||||
self._standard_time_limit_text_input: Optional[ba.NodeActor] = None
|
||||
self._tournament_time_limit: Optional[int] = None
|
||||
self._tournament_time_limit_timer: Optional[ba.Timer] = None
|
||||
self._tournament_time_limit_title_text: Optional[ba.Actor] = None
|
||||
self._tournament_time_limit_text: Optional[ba.Actor] = None
|
||||
self._tournament_time_limit_text_input: Optional[ba.Actor] = None
|
||||
self._tournament_time_limit_title_text: Optional[ba.NodeActor] = None
|
||||
self._tournament_time_limit_text: Optional[ba.NodeActor] = None
|
||||
self._tournament_time_limit_text_input: Optional[ba.NodeActor] = None
|
||||
self._zoom_message_times: Dict[int, float] = {}
|
||||
self._is_waiting_for_continue = False
|
||||
|
||||
@ -1042,17 +1042,18 @@ class GameActivity(Activity):
|
||||
from ba import _messages
|
||||
from ba._gameutils import animate
|
||||
from ba._coopsession import CoopSession
|
||||
from bastd.actor import playerspaz
|
||||
from bastd.actor.playerspaz import PlayerSpaz
|
||||
name = player.get_name()
|
||||
color = player.color
|
||||
highlight = player.highlight
|
||||
|
||||
light_color = _math.normalized_color(color)
|
||||
display_color = _ba.safecolor(color, target_intensity=0.75)
|
||||
spaz = playerspaz.PlayerSpaz(color=color,
|
||||
highlight=highlight,
|
||||
character=player.character,
|
||||
player=player)
|
||||
spaz = PlayerSpaz(color=color,
|
||||
highlight=highlight,
|
||||
character=player.character,
|
||||
player=player)
|
||||
|
||||
player.set_actor(spaz)
|
||||
assert spaz.node
|
||||
|
||||
|
||||
@ -211,7 +211,7 @@ class Map(Actor):
|
||||
|
||||
# This is expected to always be a ba.Node object (whether valid or not)
|
||||
# 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
|
||||
# (and instruct the user if we weren't preloaded properly).
|
||||
@ -365,9 +365,8 @@ class Map(Actor):
|
||||
player_pts = []
|
||||
for player in players:
|
||||
try:
|
||||
if player.actor is not None and player.actor.is_alive():
|
||||
assert player.actor.node
|
||||
pnt = _ba.Vec3(player.actor.node.position)
|
||||
if player.node:
|
||||
pnt = _ba.Vec3(player.node.position)
|
||||
player_pts.append(pnt)
|
||||
except Exception as 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[team_index % len(self.flag_points)][:3]
|
||||
|
||||
def exists(self) -> bool:
|
||||
return bool(self.node)
|
||||
|
||||
def handlemessage(self, msg: Any) -> Any:
|
||||
from ba import _messages
|
||||
if isinstance(msg, _messages.DieMessage):
|
||||
if self.node:
|
||||
self.node.delete()
|
||||
super().handlemessage(msg)
|
||||
else:
|
||||
return super().handlemessage(msg)
|
||||
return None
|
||||
|
||||
|
||||
def register_map(maptype: Type[Map]) -> None:
|
||||
|
||||
@ -47,6 +47,7 @@ class DeathType(Enum):
|
||||
Category: Enums
|
||||
"""
|
||||
GENERIC = 'generic'
|
||||
OUT_OF_BOUNDS = 'out_of_bounds'
|
||||
IMPACT = 'impact'
|
||||
FALL = 'fall'
|
||||
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)
|
||||
class HitMessage:
|
||||
"""Tells an object it has been hit in some way.
|
||||
|
||||
@ -51,3 +51,6 @@ class NodeActor(Actor):
|
||||
self.node.delete()
|
||||
return None
|
||||
return super().handlemessage(msg)
|
||||
|
||||
def exists(self) -> bool:
|
||||
return bool(self.node)
|
||||
|
||||
@ -98,21 +98,6 @@ class Team:
|
||||
"""Returns the numeric 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:
|
||||
"""(internal)"""
|
||||
self.reset_gamedata()
|
||||
|
||||
@ -254,22 +254,23 @@ class TeamBaseSession(Session):
|
||||
announcement of the same.
|
||||
"""
|
||||
# pylint: disable=cyclic-import
|
||||
# pylint: disable=too-many-locals
|
||||
from ba import _math
|
||||
from ba import _general
|
||||
from ba._gameutils import cameraflash
|
||||
from ba import _lang
|
||||
from ba._freeforallsession import FreeForAllSession
|
||||
from ba._messages import CelebrateMessage
|
||||
_ba.timer(delay,
|
||||
_general.Call(_ba.playsound, _ba.getsound("boxingBell")))
|
||||
if announce_winning_team:
|
||||
winning_team = results.get_winning_team()
|
||||
if winning_team is not None:
|
||||
# Have all players celebrate.
|
||||
celebrate_msg = CelebrateMessage(duration=10.0)
|
||||
for player in winning_team.players:
|
||||
if player.actor is not None and player.actor.node:
|
||||
# Note: celebrate message takes milliseconds
|
||||
# for historical reasons.
|
||||
player.actor.node.handlemessage('celebrate', 10000)
|
||||
if player.actor:
|
||||
player.actor.handlemessage(celebrate_msg)
|
||||
cameraflash()
|
||||
|
||||
# Some languages say "FOO WINS" different for teams vs players.
|
||||
|
||||
@ -25,7 +25,7 @@ from __future__ import annotations
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import ba
|
||||
from bastd.actor import spaz as basespaz
|
||||
from bastd.actor.spaz import Spaz
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Optional, Sequence, Tuple
|
||||
@ -77,7 +77,7 @@ class PlayerSpazHurtMessage:
|
||||
self.spaz = spaz
|
||||
|
||||
|
||||
class PlayerSpaz(basespaz.Spaz):
|
||||
class PlayerSpaz(Spaz):
|
||||
"""A ba.Spaz subclass meant to be controlled by a ba.Player.
|
||||
|
||||
category: Gameplay Classes
|
||||
@ -102,13 +102,12 @@ class PlayerSpaz(basespaz.Spaz):
|
||||
you must call connect_controls_to_player() to do so.
|
||||
"""
|
||||
|
||||
basespaz.Spaz.__init__(self,
|
||||
color=color,
|
||||
highlight=highlight,
|
||||
character=character,
|
||||
source_player=player,
|
||||
start_invincible=True,
|
||||
powerups_expire=powerups_expire)
|
||||
super().__init__(color=color,
|
||||
highlight=highlight,
|
||||
character=character,
|
||||
source_player=player,
|
||||
start_invincible=True,
|
||||
powerups_expire=powerups_expire)
|
||||
self.last_player_attacked_by: Optional[ba.Player] = None
|
||||
self.last_attacked_time = 0.0
|
||||
self.last_attacked_type: Optional[Tuple[str, str]] = None
|
||||
|
||||
@ -155,7 +155,7 @@ class Spaz(ba.Actor):
|
||||
media = factory.get_media(character)
|
||||
punchmats = (factory.punch_material, ba.sharedobj('attack_material'))
|
||||
pickupmats = (factory.pickup_material, ba.sharedobj('pickup_material'))
|
||||
self.node = ba.newnode(
|
||||
self.node: ba.Node = ba.newnode(
|
||||
type="spaz",
|
||||
delegate=self,
|
||||
attrs={
|
||||
@ -256,10 +256,13 @@ class Spaz(ba.Actor):
|
||||
self.punch_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:
|
||||
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.punch_callback = None
|
||||
self.pick_up_powerup_callback = None
|
||||
@ -296,8 +299,8 @@ class Spaz(ba.Actor):
|
||||
assert isinstance(t_ms, int)
|
||||
t_bucket = int(t_ms / 1000)
|
||||
if t_bucket == self._turbo_filter_time_bucket:
|
||||
# add only once per timestep (filter out buttons triggering
|
||||
# multiple actions)
|
||||
# Add only once per timestep (filter out buttons triggering
|
||||
# multiple actions).
|
||||
if t_ms != self._turbo_filter_times.get(source, 0):
|
||||
self._turbo_filter_counts[source] = (
|
||||
self._turbo_filter_counts.get(source, 0) + 1)
|
||||
@ -306,11 +309,11 @@ class Spaz(ba.Actor):
|
||||
# ba.screenmessage( str(source) + " "
|
||||
# + str(self._turbo_filter_counts[source]))
|
||||
if self._turbo_filter_counts[source] == 15:
|
||||
# knock 'em out. That'll learn 'em.
|
||||
# Knock 'em out. That'll learn 'em.
|
||||
assert self.node
|
||||
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)
|
||||
if now > ba.app.last_spaz_turbo_warn_time + 30.0:
|
||||
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.
|
||||
self.node.hold_body = opposing_body
|
||||
self.node.hold_node = opposing_node
|
||||
elif isinstance(msg, ba.CelebrateMessage):
|
||||
if self.node:
|
||||
self.node.handlemessage('celebrate', int(msg.duration * 1000))
|
||||
|
||||
else:
|
||||
return super().handlemessage(msg)
|
||||
return None
|
||||
|
||||
@ -190,7 +190,7 @@ class SpazBot(basespaz.Spaz):
|
||||
closest_dist = None
|
||||
closest_vel = None
|
||||
closest = None
|
||||
assert self._player_pts
|
||||
assert self._player_pts is not None
|
||||
for plpt, plvel in self._player_pts:
|
||||
dist = (plpt - botpt).length()
|
||||
|
||||
@ -983,6 +983,7 @@ class BotSet:
|
||||
for player in ba.getactivity().players:
|
||||
try:
|
||||
if player.is_alive():
|
||||
assert isinstance(player.actor, basespaz.Spaz)
|
||||
assert player.actor is not None and player.actor.node
|
||||
player_pts.append((ba.Vec3(player.actor.node.position),
|
||||
ba.Vec3(player.actor.node.velocity)))
|
||||
@ -1006,16 +1007,6 @@ class BotSet:
|
||||
bot.handlemessage(ba.DieMessage(immediate=True))
|
||||
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:
|
||||
"""Start processing bot AI updates so they start doing their thing."""
|
||||
self._bot_update_timer = ba.Timer(0.05,
|
||||
@ -1035,6 +1026,17 @@ class BotSet:
|
||||
bot.node.move_left_right = 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:
|
||||
"""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.
|
||||
for botlist in self._bot_lists:
|
||||
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_up_down = 0
|
||||
ba.timer(
|
||||
0.5 * random.random(),
|
||||
ba.Call(bot.node.handlemessage, 'celebrate', 10.0))
|
||||
ba.timer(0.5 * random.random(),
|
||||
ba.Call(bot.handlemessage, ba.CelebrateMessage()))
|
||||
jump_duration = random.randrange(400, 500)
|
||||
j = random.randrange(0, 200)
|
||||
for _i in range(10):
|
||||
|
||||
@ -225,12 +225,8 @@ class AssaultGame(ba.TeamGameActivity):
|
||||
|
||||
# Have teammates celebrate.
|
||||
for player in player_team.players:
|
||||
try:
|
||||
# Note: celebrate message is milliseconds
|
||||
# for historical reasons.
|
||||
player.actor.node.handlemessage('celebrate', 2000)
|
||||
except Exception:
|
||||
pass
|
||||
if player.actor:
|
||||
player.actor.handlemessage(ba.CelebrateMessage(2.0))
|
||||
|
||||
player_team.gamedata['score'] += 1
|
||||
self._update_scoreboard()
|
||||
|
||||
@ -306,10 +306,8 @@ class CaptureTheFlagGame(ba.TeamGameActivity):
|
||||
|
||||
# Have teammates celebrate
|
||||
for player in team.players:
|
||||
if player.actor is not None and player.actor.node:
|
||||
# Note: celebrate message is milliseconds
|
||||
# for historical reasons.
|
||||
player.actor.node.handlemessage('celebrate', 2000)
|
||||
if player.actor:
|
||||
player.actor.handlemessage(ba.CelebrateMessage(2.0))
|
||||
|
||||
# Reset all flags/state.
|
||||
for reset_team in self.teams:
|
||||
|
||||
@ -279,7 +279,7 @@ class ChosenOneGame(ba.TeamGameActivity):
|
||||
self._flag = None
|
||||
self._chosen_one_player = player
|
||||
|
||||
if player.actor.node:
|
||||
if player.actor:
|
||||
if self.settings['Chosen One Gets Shield']:
|
||||
player.actor.handlemessage(
|
||||
ba.PowerupMessage('shield'))
|
||||
@ -311,8 +311,10 @@ class ChosenOneGame(ba.TeamGameActivity):
|
||||
0.4: 1.0
|
||||
},
|
||||
loop=True)
|
||||
assert isinstance(player.actor, playerspaz.PlayerSpaz)
|
||||
player.actor.node.connectattr('position', light.node,
|
||||
'position')
|
||||
|
||||
except Exception:
|
||||
ba.print_exception('EXC in _set_chosen_one_player')
|
||||
|
||||
|
||||
@ -143,7 +143,9 @@ class EasterEggHuntGame(ba.TeamGameActivity):
|
||||
'source_node', 'opposing_node')
|
||||
if egg_node is not None and playernode is not None:
|
||||
egg = egg_node.getdelegate()
|
||||
assert isinstance(egg, Egg)
|
||||
spaz = playernode.getdelegate()
|
||||
assert isinstance(spaz, playerspaz.PlayerSpaz)
|
||||
player = (spaz.getplayer()
|
||||
if hasattr(spaz, 'getplayer') else None)
|
||||
if player and egg:
|
||||
@ -187,13 +189,8 @@ class EasterEggHuntGame(ba.TeamGameActivity):
|
||||
ypos = random.uniform(3.5, 3.5)
|
||||
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.
|
||||
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.
|
||||
if len(self._eggs) < int(self._max_eggs):
|
||||
@ -283,12 +280,13 @@ class Egg(ba.Actor):
|
||||
'materials': mats
|
||||
})
|
||||
|
||||
def exists(self) -> bool:
|
||||
return bool(self.node)
|
||||
|
||||
def handlemessage(self, msg: Any) -> Any:
|
||||
if isinstance(msg, ba.DieMessage):
|
||||
if self.node:
|
||||
self.node.delete()
|
||||
elif isinstance(msg, ba.OutOfBoundsMessage):
|
||||
self.handlemessage(ba.DieMessage())
|
||||
elif isinstance(msg, ba.HitMessage):
|
||||
if self.node:
|
||||
assert msg.force_direction is not None
|
||||
|
||||
@ -386,8 +386,8 @@ class EliminationGame(ba.TeamGameActivity):
|
||||
for team in self.teams:
|
||||
for tplayer in team.players:
|
||||
if tplayer.is_alive():
|
||||
assert tplayer.actor is not None and tplayer.actor.node
|
||||
ppos = tplayer.actor.node.position
|
||||
assert tplayer.node
|
||||
ppos = tplayer.node.position
|
||||
living_player = tplayer
|
||||
living_player_pos = ppos
|
||||
break
|
||||
@ -416,20 +416,16 @@ class EliminationGame(ba.TeamGameActivity):
|
||||
|
||||
def _print_lives(self, player: ba.Player) -> None:
|
||||
from bastd.actor import popuptext
|
||||
if not player or not player.is_alive():
|
||||
return
|
||||
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)
|
||||
assert player # Shouldn't be passing invalid refs around.
|
||||
if not player or not player.is_alive() or not player.node:
|
||||
return
|
||||
|
||||
popuptext.PopupText('x' + str(player.gamedata['lives'] - 1),
|
||||
color=(1, 1, 0, 1),
|
||||
offset=(0, -0.8, 0),
|
||||
random_offset=0.0,
|
||||
scale=1.8,
|
||||
position=pos).autoretain()
|
||||
position=player.node.position).autoretain()
|
||||
|
||||
def on_player_leave(self, player: ba.Player) -> None:
|
||||
ba.TeamGameActivity.on_player_leave(self, player)
|
||||
|
||||
@ -128,10 +128,10 @@ class FootballTeamGame(ba.TeamGameActivity):
|
||||
True), ("modify_part_collision", "physical", False),
|
||||
("call", "at_connect", self._handle_score)))
|
||||
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_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]:
|
||||
touchdowns = self.settings['Score to Win'] / 7
|
||||
@ -203,13 +203,8 @@ class FootballTeamGame(ba.TeamGameActivity):
|
||||
|
||||
# Tell all players to celebrate.
|
||||
for player in team.players:
|
||||
if player.actor is not None and player.actor.node:
|
||||
try:
|
||||
# Note: celebrate message is milliseconds
|
||||
# (for historical reasons).
|
||||
player.actor.node.handlemessage('celebrate', 2000)
|
||||
except Exception:
|
||||
ba.print_exception('Error on celebrate')
|
||||
if player.actor:
|
||||
player.actor.handlemessage(ba.CelebrateMessage(2.0))
|
||||
|
||||
# If someone on this team was last to touch it,
|
||||
# give them points.
|
||||
@ -376,7 +371,7 @@ class FootballCoopGame(ba.CoopGameActivity):
|
||||
self._player_has_punched = False
|
||||
self._scoreboard: Optional[Scoreboard] = 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._have_tnt = False
|
||||
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_team: Optional[ba.Team] = None
|
||||
self._starttime_ms: Optional[int] = None
|
||||
self._time_text: Optional[ba.Actor] = None
|
||||
self._time_text_input: Optional[ba.Actor] = None
|
||||
self._time_text: Optional[ba.NodeActor] = None
|
||||
self._time_text_input: Optional[ba.NodeActor] = None
|
||||
self._tntspawner: Optional[stdbomb.TNTSpawner] = None
|
||||
self._bots = spazbot.BotSet()
|
||||
self._bot_spawn_timer: Optional[ba.Timer] = None
|
||||
@ -580,13 +575,11 @@ class FootballCoopGame(ba.CoopGameActivity):
|
||||
assert self._flag is not None
|
||||
if self._flag.node:
|
||||
for player in self.players:
|
||||
try:
|
||||
assert player.actor is not None and player.actor.node
|
||||
if player.actor:
|
||||
assert isinstance(player.actor, playerspaz.PlayerSpaz)
|
||||
if (player.actor.is_alive() and
|
||||
player.actor.node.hold_node == self._flag.node):
|
||||
return
|
||||
except Exception:
|
||||
ba.print_exception("exception checking hold node")
|
||||
|
||||
flagpos = ba.Vec3(self._flag.node.position)
|
||||
closest_bot = None
|
||||
@ -651,7 +644,6 @@ class FootballCoopGame(ba.CoopGameActivity):
|
||||
""" a point has been scored """
|
||||
# FIXME tidy this up
|
||||
# pylint: disable=too-many-branches
|
||||
# pylint: disable=too-many-nested-blocks
|
||||
|
||||
# Our flag might stick around for a second or two;
|
||||
# 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.
|
||||
if i == 0:
|
||||
for player in team.players:
|
||||
try:
|
||||
# Note: celebrate message is milliseconds
|
||||
# (for historical reasons).
|
||||
if player.actor is not None and player.actor.node:
|
||||
player.actor.node.handlemessage(
|
||||
'celebrate', 2000)
|
||||
except Exception:
|
||||
ba.print_exception()
|
||||
if player.actor:
|
||||
player.actor.handlemessage(
|
||||
ba.CelebrateMessage(2.0))
|
||||
else:
|
||||
self._bots.celebrate(2000)
|
||||
self._bots.celebrate(2.0)
|
||||
|
||||
# If the good guys scored, add more enemies.
|
||||
if i == 0:
|
||||
|
||||
@ -193,7 +193,7 @@ class HockeyGame(ba.TeamGameActivity):
|
||||
True), ("modify_part_collision", "physical", False),
|
||||
("call", "at_connect", self._handle_score)))
|
||||
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
|
||||
|
||||
def get_instance_description(self) -> Union[str, Sequence]:
|
||||
@ -284,10 +284,8 @@ class HockeyGame(ba.TeamGameActivity):
|
||||
|
||||
# Tell all players to celebrate.
|
||||
for player in team.players:
|
||||
if player.actor is not None and player.actor.node:
|
||||
# Note: celebrate message takes milliseconds
|
||||
# (for historical reasons).
|
||||
player.actor.node.handlemessage('celebrate', 2000)
|
||||
if player.actor:
|
||||
player.actor.handlemessage(ba.CelebrateMessage(2.0))
|
||||
|
||||
# If we've got the player from the scoring team that last
|
||||
# touched us, give them points.
|
||||
|
||||
@ -194,7 +194,7 @@ class KeepAwayGame(ba.TeamGameActivity):
|
||||
for player in self.players:
|
||||
holding_flag = False
|
||||
try:
|
||||
assert player.actor is not None
|
||||
assert isinstance(player.actor, playerspaz.PlayerSpaz)
|
||||
if (player.actor.is_alive() and player.actor.node
|
||||
and player.actor.node.hold_node):
|
||||
holding_flag = (
|
||||
|
||||
@ -188,7 +188,9 @@ class NinjaFightGame(ba.TeamGameActivity):
|
||||
ba.cameraflash()
|
||||
ba.playsound(self._winsound)
|
||||
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)
|
||||
|
||||
# Ends the activity.
|
||||
|
||||
@ -105,7 +105,7 @@ class OnslaughtGame(ba.CoopGameActivity):
|
||||
self._can_end_wave = True
|
||||
self._score = 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._dingsoundhigh = ba.getsound('dingSmallHigh')
|
||||
self._have_tnt = False
|
||||
@ -115,9 +115,9 @@ class OnslaughtGame(ba.CoopGameActivity):
|
||||
self._bots: Optional[spazbot.BotSet] = None
|
||||
self._powerup_drop_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._wave_text: Optional[ba.Actor] = None
|
||||
self._wave_text: Optional[ba.NodeActor] = None
|
||||
self._wave_update_timer: Optional[ba.Timer] = None
|
||||
self._throw_off_kills = 0
|
||||
self._land_mine_kills = 0
|
||||
@ -873,7 +873,7 @@ class OnslaughtGame(ba.CoopGameActivity):
|
||||
if self._game_over:
|
||||
return
|
||||
|
||||
# respawn applicable players
|
||||
# Respawn applicable players.
|
||||
if self._wave > 1 and not self.is_waiting_for_continue():
|
||||
for player in self.players:
|
||||
if (not player.is_alive()
|
||||
|
||||
@ -189,6 +189,7 @@ class RaceGame(ba.TeamGameActivity):
|
||||
self._regions.append(RaceRegion(rpt, len(self._regions)))
|
||||
|
||||
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
|
||||
pos = player.actor.node.position
|
||||
light = ba.newnode('light',
|
||||
@ -523,6 +524,7 @@ class RaceGame(ba.TeamGameActivity):
|
||||
for player in self.players:
|
||||
pos: Optional[ba.Vec3]
|
||||
try:
|
||||
assert isinstance(player.actor, PlayerSpaz)
|
||||
assert player.actor is not None and player.actor.node
|
||||
pos = ba.Vec3(player.actor.node.position)
|
||||
except Exception:
|
||||
|
||||
@ -117,15 +117,15 @@ class RunaroundGame(ba.CoopGameActivity):
|
||||
self._waves: Optional[List[Dict[str, Any]]] = None
|
||||
self._bots = spazbot.BotSet()
|
||||
self._tntspawner: Optional[TNTSpawner] = None
|
||||
self._lives_bg: Optional[ba.Actor] = None
|
||||
self._lives_bg: Optional[ba.NodeActor] = None
|
||||
self._start_lives = 10
|
||||
self._lives = self._start_lives
|
||||
self._lives_text: Optional[ba.Actor] = None
|
||||
self._lives_text: Optional[ba.NodeActor] = None
|
||||
self._flawless = True
|
||||
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._wave_text: Optional[ba.Actor] = None
|
||||
self._wave_text: Optional[ba.NodeActor] = None
|
||||
self._flawless_bonus: Optional[int] = 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:
|
||||
# Yup; that's a lot of return statements right there.
|
||||
# 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
|
||||
|
||||
assert bot.node
|
||||
|
||||
# FIXME: Do this in a type safe way.
|
||||
r_walk_speed: float = bot.r_walk_speed # 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:
|
||||
try:
|
||||
if player.is_alive():
|
||||
assert isinstance(player.actor, playerspaz.PlayerSpaz)
|
||||
assert player.actor is not None and player.actor.node
|
||||
playerpts.append(player.actor.node.position)
|
||||
except Exception as exc:
|
||||
|
||||
@ -262,7 +262,7 @@ class MainMenuActivity(ba.Activity):
|
||||
self._valid = True
|
||||
self._message_duration = 10.0
|
||||
self._message_spacing = 2.0
|
||||
self._text: Optional[ba.Actor] = None
|
||||
self._text: Optional[ba.NodeActor] = None
|
||||
self._activity = weakref.ref(activity)
|
||||
|
||||
# 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;
|
||||
# otherwise, rotate our phrase.
|
||||
assert app.main_menu_last_news_fetch_time is not None
|
||||
if time.time() - app.main_menu_last_news_fetch_time > 600.0:
|
||||
assert ba.app.main_menu_last_news_fetch_time is not None
|
||||
if time.time() - ba.app.main_menu_last_news_fetch_time > 600.0:
|
||||
self._fetch_news()
|
||||
self._text = None
|
||||
else:
|
||||
|
||||
@ -1169,8 +1169,8 @@ class TowerD(ba.Map):
|
||||
running: bool = False) -> bool:
|
||||
# see if we're within edge_box
|
||||
boxes = self.defs.boxes
|
||||
box_position = boxes['edge_box1'][0:3]
|
||||
box_scale = boxes['edge_box1'][6:9]
|
||||
box_position = boxes['edge_box'][0:3]
|
||||
box_scale = boxes['edge_box'][6:9]
|
||||
box_position2 = boxes['edge_box2'][0:3]
|
||||
box_scale2 = boxes['edge_box2'][6:9]
|
||||
xpos = (point.x - box_position[0]) / box_scale[0]
|
||||
|
||||
@ -1,4 +1,2 @@
|
||||
+/tools
|
||||
+/src/ballistica
|
||||
+/src/generated_src
|
||||
+/assets/src/ba_data/python
|
||||
|
||||
@ -80,6 +80,12 @@ good-names=i,
|
||||
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]
|
||||
# We've got various TODO and FIXME notes in scripts, but don't want
|
||||
# lint to trigger over that fact.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<!-- 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,
|
||||
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>
|
||||
@ -112,6 +112,7 @@
|
||||
</ul>
|
||||
<h4><a name="class_category_Message_Classes">Message Classes</a></h4>
|
||||
<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_DropMessage">ba.DropMessage</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>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>
|
||||
<dt><h4><a name="method_ba_Actor__is_alive">is_alive()</a></dt></h4><dd>
|
||||
<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>
|
||||
|
||||
</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>
|
||||
</dl>
|
||||
<hr>
|
||||
@ -1586,6 +1607,7 @@ the data object is requested and when it's value is accessed.</p>
|
||||
<h3>Values:</h3>
|
||||
<ul>
|
||||
<li>GENERIC</li>
|
||||
<li>OUT_OF_BOUNDS</li>
|
||||
<li>IMPACT</li>
|
||||
<li>FALL</li>
|
||||
<li>REACHED_GOAL</li>
|
||||
@ -2782,15 +2804,35 @@ etc.</p>
|
||||
</dd>
|
||||
</dl>
|
||||
<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>
|
||||
<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>
|
||||
<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>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>
|
||||
<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>
|
||||
@ -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>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>
|
||||
<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>
|
||||
@ -3347,24 +3386,41 @@ acting as an alternative to setting node attributes.</p>
|
||||
</dd>
|
||||
</dl>
|
||||
<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>
|
||||
<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>
|
||||
<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>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>
|
||||
<dt><h4><a name="method_ba_NodeActor__handlemessage">handlemessage()</a></dt></h4><dd>
|
||||
<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>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>
|
||||
</dl>
|
||||
<hr>
|
||||
@ -4267,7 +4323,7 @@ of the session.</p>
|
||||
</dd>
|
||||
</dl>
|
||||
<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>
|
||||
<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>
|
||||
@ -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>,
|
||||
<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>
|
||||
<dt><h4><a name="method_ba_Team__get_id">get_id()</a></dt></h4><dd>
|
||||
<p><span>get_id(self) -> int</span></p>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user