bascenev1 package

Gameplay-centric api for classic BombSquad.

class bascenev1.Activity(settings: dict)[source]

Bases: DependencyComponent, Generic[PlayerT, TeamT]

Units of execution wrangled by a bascenev1.Session.

Examples of activities include games, score-screens, cutscenes, etc. A bascenev1.Session has one ‘current’ activity at any time, though their existence can overlap during transitions.

add_actor_weak_ref(actor: bascenev1.Actor) None[source]

Add a weak-ref to a bascenev1.Actor to the activity.

(called by the bascenev1.Actor base class)

allow_kick_idle_players = True

Whether idle players can potentially be kicked (should not happen in menus/etc).

allow_mid_activity_joins: bool = True

Whether players should be allowed to join in the middle of this activity. Note that a bascenev1.Session may not allow mid-activity-joins even if the activity says it is ok.

allow_pausing = False

Whether scene-time should still progress when in menus/etc.

announce_player_deaths = False

Whether to print every time a player dies. This can be pertinent in games such as Death-Match but can be annoying in games where it doesn’t matter.

can_show_ad_on_death = False

Is it ok to show an ad after this activity ends before showing the next activity?

property context: bascenev1.ContextRef

A context-ref pointing at this activity.

create_player(sessionplayer: bascenev1.SessionPlayer) PlayerT[source]

Create a bascenev1.Player instance for this activity.

Note that the player object should not be used at this point as it is not yet fully wired up; wait for bascenev1.Activity.on_player_join() for that.

create_team(sessionteam: bascenev1.SessionTeam) TeamT[source]

Create a bascenev1.Team instance for this activity.

Subclasses can override this if the activity’s team class requires a custom constructor; otherwise it will be called with no args. Note that the team object should not be used at this point as it is not yet fully wired up; wait for bascenev1.Activity.on_team_join() for that.

property customdata: dict

Entities needing to store simple data with an activity can put it here. This dict will be deleted when the activity expires, so contained objects generally do not need to worry about handling expired activities.

end(results: Any = None, delay: float = 0.0, force: bool = False) None[source]

Commence activity shutdown and delivers results to the session.

‘delay’ is the time delay before the Activity actually ends (in seconds). Further end calls will be ignored up until this time, unless ‘force’ is True, in which case the new results will replace the old.

property expired: bool

Whether the activity is expired.

An activity is set as expired when shutting down. At this point no new nodes, timers, etc should be made, run, etc, and the activity should be considered a ‘zombie’.

property globalsnode: bascenev1.Node

The ‘globals’ Node for the activity.

This contains various global controls and values.

handlemessage(msg: Any) Any[source]

General message handling; can be passed any message object.

has_begun() bool[source]

Whether on_begin() has run.

has_ended() bool[source]

Return whether the activity has commenced ending.

has_transitioned_in() bool[source]

Whether on_transition_in() has run.

inherits_music = False

Set this to True to keep playing the music from the previous activity (without even restarting it).

inherits_slow_motion = False

Set this to True to inherit slow motion setting from previous activity (useful for transitions to avoid hitches).

inherits_tint = False

Set this to true to inherit screen tint/vignette colors from the previous activity (useful to prevent sudden color changes during transitions).

inherits_vr_camera_offset = False

Set this to true to inherit VR camera offsets from the previous activity (useful for preventing sporadic camera movement during transitions).

inherits_vr_overlay_center = False

Set this to true to inherit (non-fixed) VR overlay positioning from the previous activity (useful for prevent sporadic overlay jostling during transitions).

is_joining_activity = False

Joining activities are for waiting for initial player joins. They are treated slightly differently than regular activities, mainly in that all players are passed to the activity at once instead of as each joins.

is_transitioning_out() bool[source]

Whether on_transition_out() has run.

on_begin() None[source]

Called once the previous activity has finished transitioning out.

At this point the activity’s initial players and teams are filled in and it should begin its actual game logic.

on_expire() None[source]

Called when your activity is being expired.

If your activity has created anything explicitly that may be retaining a strong reference to the activity and preventing it from dying, you should clear that out here. From this point on your activity’s sole purpose in life is to hit zero references and die so the next activity can begin.

on_player_join(player: PlayerT) None[source]

Called when a player joins the activity.

(including the initial set of players)

on_player_leave(player: PlayerT) None[source]

Called when a player is leaving the Activity.

on_team_join(team: TeamT) None[source]

Called when a new team joins the activity.

(including the initial set of teams)

on_team_leave(team: TeamT) None[source]

Called when a team leaves the activity.

on_transition_in() None[source]

Called when the activity is first becoming visible.

Upon this call, the activity should fade in backgrounds, start playing music, etc. It does not yet have access to players or teams, however. They remain owned by the previous activity up until on_begin() is called.

on_transition_out() None[source]

Called when your activity begins transitioning out.

Note that this may happen at any time even if bascenev1.Activity.end() has not been called.

players: list[PlayerT]

The list of players in the activity. This gets populated just before on_begin() is called and is updated automatically as players join or leave the game.

property playertype: type[PlayerT]

The Player subclass this activity uses.

preloads: dict[type, Any]

Preloaded data for actors, maps, etc; indexed by type.

remove_player(sessionplayer: bascenev1.SessionPlayer) None[source]

Remove a player from the activity while it is running.

(internal)

retain_actor(actor: bascenev1.Actor) None[source]

Add a strong-ref to a bascenev1.Actor to this activity.

The reference will be lazily released once bascenev1.Actor.exists() returns False for the actor. The bascenev1.Actor.autoretain() method is a convenient way to access this same functionality.

property session: bascenev1.Session

The session this activity belongs to.

Raises a SessionNotFoundError if the session no longer exists.

settings_raw: dict[str, Any]

The settings dict passed in when the activity was made. This attribute is deprecated and should be avoided when possible; activities should pull all values they need from the settings arg passed to the activity’s __init__ call.

slow_motion = False

If True, runs in slow motion and turns down sound pitch.

property stats: bascenev1.Stats

The stats instance accessible while the activity is running.

If access is attempted before or after, raises a NotFoundError.

teams: list[TeamT]

The list of teams in the activity. This gets populated just before on_begin() is called and is updated automatically as players join or leave the game. (at least in free-for-all mode where every player gets their own team; in teams mode there are always 2 teams regardless of the player count).

property teamtype: type[TeamT]

The Team subclass this activity uses.

transition_time = 0.0

If the activity fades or transitions in, it should set the length of time here so that previous activities will be kept alive for that long (avoiding ‘holes’ in the screen) This value is given in real-time seconds.

use_fixed_vr_overlay = False

In vr mode, this determines whether overlay nodes (text, images, etc) are created at a fixed position in space or one that moves based on the current map. Generally this should be on for games and off for transitions/score-screens/etc. that persist between maps.

exception bascenev1.ActivityNotFoundError[source]

Bases: NotFoundError

Raised when an expected activity does not exist.

class bascenev1.Actor[source]

Bases: object

High level logical entities in an Activity.

Actors act as controllers, combining some number of Node, Texture, Sound, and other type objects into a high-level cohesive unit.

Some example actors include the Bomb, Flag, and Spaz, classes that live in the bascenev1lib.actor package.

One key feature of actors is that they generally ‘die’ (killing off or transitioning out their nodes) when the last Python reference to them disappears, so you can use logic such as:

# Create a flag actor in our game activity (self):
from bascenev1lib.actor.flag import Flag

self.flag = Flag(position=(0, 10, 0))

# Later, destroy the flag (provided nothing else is holding a
# reference to it). We could also just assign a new flag to this
# value. Either way, the old flag should disappear.
self.flag = None

This is in contrast to the behavior of the more low level Node class, which is always explicitly created and destroyed and doesn’t care how many Python references to it exist.

Note, however, that you can use the autoretain() method if you want an actor to stick around until explicitly killed regardless of references.

Another key feature of actors is their handlemessage() method, which takes a single arbitrary object as an argument. This provides a safe way to communicate between Actor, Activity, Session, and any other class providing a handlemessage() method. The most universally handled message type for actors is the DieMessage.

Another way to kill the flag from the example above: We can safely call this on any type with a handlemessage method (though its not guaranteed to always have a meaningful effect). In this case the actor instance will still be around, but its exists() and is_alive() methods will both return False:

self.flag.handlemessage(bascenev1.DieMessage())
property activity: bascenev1.Activity

The activity this actor was created in.

Raises a ActivityNotFoundError if the activity no longer exists.

autoretain() ActorT[source]

Keep this actor alive without needing to hold a reference to it.

This keeps the actor in existence by storing a reference to it with the Activity it was created in. The reference is lazily released once exists() returns False for the actor or when the Activity is set as expired. This can be a convenient alternative to storing references explicitly just to keep an actor from dying. For convenience, this method returns the actor it is called with, enabling chained statements such as: myflag = bascenev1.Flag().autoretain()

exists() bool[source]

Returns whether the actor is still present in a meaningful way.

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 is_alive() for that).

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 bascenev1.Actor.autoretain()

The default implementation of this method always return True.

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.

property expired: bool

Whether the actor is expired.

(see on_expire())

getactivity(doraise: bool = True) bascenev1.Activity | None[source]

Return the activity this actor is associated with.

If the activity no longer exists, raises a ActivityNotFoundError or returns None depending on whether doraise is True.

handlemessage(msg: Any) Any[source]

General message handling; can be passed any message object.

is_alive() bool[source]

Returns whether the actor is ‘alive’.

What this means is up to the actor. It is not a requirement for actors to be able to die; just that they report whether they consider themselves to be alive or not. In cases where dead/alive is irrelevant, True should be returned.

on_expire() None[source]

Called for remaining actors when their activity dies.

Actors can use this opportunity to clear callbacks or other references which have the potential of keeping the Activity alive inadvertently (activities can not exit cleanly while any Python references to them remain.)

Once an actor is expired (see expired) it should no longer perform any game-affecting operations (creating, modifying, or deleting nodes, media, timers, etc.) Attempts to do so will likely result in errors.

class bascenev1.App[source]

Bases: object

High level Ballistica app functionality and state.

Access the single shared instance of this class via the app attr available on various high level modules such as babase, bauiv1, and bascenev1.

SHUTDOWN_TASK_TIMEOUT_SECONDS = 12

How long we allow shutdown tasks to run before killing them. Currently the entire app hard-exits if shutdown takes 15 seconds, so we need to keep it under that. Staying above 10 should allow 10 second network timeouts to happen though.

property active: bool

Whether the app is currently front and center.

This will be False when the app is hidden, other activities are covering it, etc. (depending on the platform).

add_shutdown_task(coro: Coroutine[None, None, None]) None[source]

Add a task to be run on app shutdown.

Note that shutdown tasks will be canceled after SHUTDOWN_TASK_TIMEOUT_SECONDS if they are still running.

property asyncio_loop: AbstractEventLoop

The logic thread’s asyncio event-loop.

This allows asyncio tasks to be run in the logic thread.

Generally you should call create_async_task() to schedule async code to run instead of using this directly. That will handle retaining the task and logging errors automatically. Only schedule tasks onto asyncio_loop yourself when you intend to hold on to the returned task and await its results. Releasing the task reference can lead to subtle bugs such as unreported errors and garbage-collected tasks disappearing before their work is done.

Note that, at this time, the asyncio loop is encapsulated and explicitly stepped by the engine’s logic thread loop and thus things like asyncio.get_running_loop() will unintuitively not return this loop from most places in the logic thread; only from within a task explicitly created in this loop. Hopefully this situation will be improved in the future with a unified event loop.

property classic: ClassicAppSubsystem | None

Our classic subsystem (if available).

components: AppComponentSubsystem
config: AppConfig

Config values for the app.

create_async_task(coro: Coroutine[Any, Any, T], *, name: str | None = None) None[source]

Create a fully managed asyncio task.

This will automatically retain and release a reference to the task and log any exceptions that occur in it. If you need to await a task or otherwise need more control, schedule a task directly using asyncio_loop.

devconsole: DevConsoleSubsystem

Subsystem for wrangling the dev-console UI.

env: babase.Env

Static environment values for the app.

fg_state: int

Incremented each time the app leaves the SUSPENDED state. This can be a simple way to determine if network data should be refreshed/etc.

Handle a deep link URL.

health: AppHealthSubsystem

Subsystem for keeping tabs on app health.

lang: LanguageSubsystem

Language subsystem.

meta: MetadataSubsystem

Subsystem for wrangling metadata.

property mode: AppMode | None

The app’s current mode.

property mode_selector: babase.AppModeSelector

Controls which app-modes are used for handling given intents.

Plugins can override this to change high level app behavior and spinoff projects can change the default implementation for the same effect.

net: NetworkSubsystem

Subsystem for network functionality.

plugins: PluginSubsystem

Subsystem for wrangling plugins.

property plus: PlusAppSubsystem | None

Our plus subsystem (if available).

postinit() None[source]

Called after we’ve been inited and assigned to babase.app.

Anything that accesses babase.app as part of its init process must go here instead of __init__.

run() None[source]

Run the app to completion.

Note that this only works on builds/runs where Ballistica is managing its own event loop.

set_intent(intent: AppIntent) None[source]

Set the intent for the app.

Intent defines what the app is trying to do at a given time. This call is asynchronous; the intent switch will happen in the logic thread in the near future. If this is called repeatedly before the change takes place, the final intent to be set will be used.

state: AppState

Current app state.

stringedit: StringEditSubsystem

Subsystem for wrangling text input from various sources.

threadpool: ThreadPoolExecutorEx

Default executor which can be used for misc background processing. It should also be passed to any additional asyncio loops we create so that everything shares the same single set of worker threads.

property ui_v1: UIV1AppSubsystem

Our ui_v1 subsystem (always available).

workspaces: WorkspaceSubsystem

Subsystem for wrangling workspaces.

class bascenev1.AppIntent[source]

Bases: object

Base class for high level directives given to the app.

class bascenev1.AppIntentDefault[source]

Bases: AppIntent

Tells the app to simply run in its default mode.

class bascenev1.AppIntentExec(code: str)[source]

Bases: AppIntent

Tells the app to exec some Python code.

class bascenev1.AppMode[source]

Bases: object

A low level mode the app can be in.

App-modes fundamentally change app behavior related to input handling, networking, graphics, and more. In a way, different app-modes can almost be considered different apps.

classmethod can_handle_intent(intent: AppIntent) bool[source]

Return whether this mode can handle the provided intent.

For this to return True, the app-mode must claim to support the provided intent (via its can_handle_intent_impl() method) AND the AppExperience associated with the app-mode must be supported by the current app and runtime environment.

classmethod can_handle_intent_impl(intent: AppIntent) bool[source]

Override this to define indent handling for an app-mode.

Note that AppExperience does not have to be considered here; that is handled automatically by the can_handle_intent() call.

classmethod get_app_experience() AppExperience[source]

Return the overall experience provided by this mode.

handle_intent(intent: AppIntent) None[source]

Handle an intent.

on_activate() None[source]

Called when the mode is becoming the active one fro the app.

on_app_active_changed() None[source]

Called when the app’s active state changes while in this app-mode.

This corresponds to the app’s active attr. App-active state becomes false when the app is hidden, minimized, backgrounded, etc. The app-mode may want to take action such as pausing a running game or saving state when this occurs.

On platforms such as mobile where apps get suspended and later silently terminated by the OS, this is likely to be the last reliable place to save state/etc.

To best cover both mobile and desktop style platforms, actions such as saving state should generally happen in response to both on_deactivate() and on_app_active_changed() (when active is False).

on_deactivate() None[source]

Called when the mode stops being the active one for the app.

On platforms where the app is explicitly exited (such as desktop PC) this will also be called at app shutdown.

To best cover both mobile and desktop style platforms, actions such as saving state should generally happen in response to both on_deactivate() and on_app_active_changed() (when active is False).

class bascenev1.AppState(*values)[source]

Bases: Enum

High level state the app can be in.

INITING = 2

Python app subsystems are being inited but should not yet interact or do any work.

LOADING = 3

Python app subsystems are inited and interacting, but the app has not yet embarked on a high level course of action. It is doing initial account logins, workspace & asset downloads, etc.

NATIVE_BOOTSTRAPPING = 1

The native layer is spinning up its machinery (screens, renderers, etc.). Nothing should happen in the Python layer until this completes.

NOT_STARTED = 0

The app has not yet begun starting and should not be used in any way.

RUNNING = 4

All pieces are in place and the app is now doing its thing.

SHUTDOWN_COMPLETE = 7

The app has completed shutdown. Any code running here should be basically immediate.

SHUTTING_DOWN = 6

The app is shutting down. This process may involve sending network messages or other things that can take up to a few seconds, so ideally graphics and audio should remain functional (with fades or spinners or whatever to show something is happening).

SUSPENDED = 5

Used on platforms such as mobile where the app basically needs to shut down while backgrounded. In this state, all event loops are suspended and all graphics and audio must cease completely. Be aware that the suspended state can be entered from any other state including NATIVE_BOOTSTRAPPING and SHUTTING_DOWN.

class bascenev1.AppTimer(time: float, call: Callable[[], Any], repeat: bool = False)[source]

Bases: object

Timers are used to run code at later points in time.

This class encapsulates a timer based on app-time. The underlying timer will be destroyed when this object is no longer referenced. If you do not want to worry about keeping a reference to your timer around, use the apptimer() function instead to get a one-off timer.

Parameters:
  • time – Length of time in seconds that the timer will wait before firing.

  • call – A callable Python object. Remember that the timer will retain a strong reference to the callable for as long as it exists, so you may want to look into concepts such as WeakCall if that is not desired.

  • repeat – If True, the timer will fire repeatedly, with each successive firing having the same delay as the first.

Example: Use a timer object to print repeatedly for a few seconds:

def say_it():
    babase.screenmessage('BADGER!')

def stop_saying_it():
    global g_timer
    g_timer = None
    babase.screenmessage('MUSHROOM MUSHROOM!')

# Create our timer; it will run as long as we keep its ref alive.
g_timer = babase.AppTimer(0.3, say_it, repeat=True)

# Now fire off a one-shot timer to kill the ref.
babase.apptimer(3.89, stop_saying_it)
class bascenev1.AssetPackage[source]

Bases: DependencyComponent

bascenev1.DependencyComponent representing a package of assets.

classmethod dep_is_present(config: Any = None) bool[source]

Return whether this component/config is present on this device.

getcollisionmesh(name: str) bascenev1.CollisionMesh[source]

Load a named bascenev1.CollisionMesh from the AssetPackage.

Behavior is similar to bascenev1.getcollisionmesh()

getdata(name: str) bascenev1.Data[source]

Load a named bascenev1.Data from the AssetPackage.

Behavior is similar to bascenev1.getdata()

getmesh(name: str) bascenev1.Mesh[source]

Load a named bascenev1.Mesh from the AssetPackage.

Behavior is similar to bascenev1.getmesh()

getsound(name: str) bascenev1.Sound[source]

Load a named bascenev1.Sound from the AssetPackage.

Behavior is similar to bascenev1.getsound()

gettexture(name: str) bascenev1.Texture[source]

Load a named bascenev1.Texture from the AssetPackage.

Behavior is similar to bascenev1.gettexture()

class bascenev1.BaseTimer(time: float, call: Callable[[], Any], repeat: bool = False)[source]

Bases: object

Timers are used to run code at later points in time.

This class encapsulates a base-time timer in the current scene context. The underlying timer will be destroyed when either this object is no longer referenced or when its context (activity, etc.) dies. If you do not want to worry about keeping a reference to your timer around, you should use the bascenev1.basetimer() function instead.

Parameters:
  • time – Length of time in seconds that the timer will wait before firing.

  • call – A callable Python object. Remember that the timer will retain a strong reference to the callable for as long as it exists, so you may want to look into concepts such as WeakCall if that is not desired.

  • repeat – If True, the timer will fire repeatedly, with each successive firing having the same delay as the first.

Example

Use a base-timer object to print repeatedly for a few seconds:

import bascenev1 as bs

def say_it():
    bs.screenmessage('BADGER!')

def stop_saying_it():
    global g_timer
    g_timer = None
    bs.screenmessage('MUSHROOM MUSHROOM!')

# Create our timer; it will run as long as we keep its ref alive.
g_timer = bs.BaseTimer(0.3, say_it, repeat=True)

# Now fire off a one-shot timer to kill the ref.
bs.basetimer(3.89, stop_saying_it)
class bascenev1.BoolSetting(name: str, default: bool)[source]

Bases: Setting

A boolean game setting.

default: bool
class bascenev1.Call(*args: Any, **keywds: Any)

Bases: object

Wraps a callable and arguments into a single callable object.

The callable is strong-referenced so it won’t die until this object does.

Note that a bound method (ex: myobj.dosomething) contains a reference to self (myobj in that case), so you will be keeping that object alive too. Use babase.WeakCall if you want to pass a method to a callback without keeping its object alive.

Example: Wrap a method call with 1 positional and 1 keyword arg:

mycall = babase.Call(myobj.dostuff, argval, namedarg=argval2)

# Now we have a single callable to run that whole mess.
# ..the same as calling myobj.dostuff(argval, namedarg=argval2)
mycall()
class bascenev1.Campaign(name: str, sequential: bool = True, levels: list[bascenev1.Level] | None = None)[source]

Bases: object

Represents a unique set of Level instances.

addlevel(level: bascenev1.Level, index: int | None = None) None[source]

Add a level to the campaign.

property configdict: dict[str, Any]

Return the live config dict for this campaign.

get_selected_level() str[source]

Return the name of the Level currently selected in the UI.

getlevel(name: str) bascenev1.Level[source]

Return a contained level by name.

property levels: list[bascenev1.Level]

The list of levels in the campaign.

property name: str

The name of the campaign.

reset() None[source]

Reset state for the campaign.

property sequential: bool

Whether this campaign’s levels must be played in sequence.

set_selected_level(levelname: str) None[source]

Set the Level currently selected in the UI (by name).

class bascenev1.CelebrateMessage(duration: float = 10.0)[source]

Bases: object

Tells an object to celebrate.

duration: float = 10.0

Amount of time to celebrate in seconds.

class bascenev1.ChoiceSetting(name: str, default: Any, choices: list[tuple[str, Any]])[source]

Bases: Setting

A setting with multiple choices.

choices: list[tuple[str, Any]]
class bascenev1.Chooser(vpos: float, sessionplayer: bascenev1.SessionPlayer, lobby: Lobby)[source]

Bases: object

A character/team selector for a player.

get_character_name() str[source]

Return the selected character name.

get_color() Sequence[float][source]

Return the currently selected color.

get_highlight() Sequence[float][source]

Return the currently selected highlight.

get_lobby() bascenev1.Lobby | None[source]

Return this chooser’s lobby if it still exists; otherwise None.

getplayer() bascenev1.SessionPlayer[source]

Return the player associated with this chooser.

handlemessage(msg: Any) Any[source]

Standard generic message handler.

property lobby: bascenev1.Lobby

The chooser’s lobby.

property ready: bool

Whether this chooser is checked in as ready.

reload_profiles() None[source]

Reload all player profiles.

property sessionplayer: bascenev1.SessionPlayer

The session-player associated with this chooser.

property sessionteam: bascenev1.SessionTeam

Return this chooser’s currently selected bascenev1.SessionTeam.

update_from_profile() None[source]

Set character/colors based on the current profile.

update_position() None[source]

Update this chooser’s position.

class bascenev1.Collision[source]

Bases: object

A class providing info about occurring collisions.

property opposingbody: int

The body index on the opposing node in the current collision.

property opposingnode: bascenev1.Node

The node the current callback material node is hitting.

Throws a NodeNotFoundError if the node does not exist. This can be expected in some cases such as in ‘disconnect’ callbacks triggered by deleting a currently-colliding node.

property position: bascenev1.Vec3

The position of the current collision.

property sourcenode: bascenev1.Node

The node containing the material triggering the current callback.

Throws a NodeNotFoundError if the node does not exist, though the node should always exist (at least at the start of the collision callback).

class bascenev1.CollisionMesh[source]

Bases: object

A reference to a collision-mesh.

Use bascenev1.getcollisionmesh() to instantiate one.

exception bascenev1.ContextError[source]

Bases: Exception

Raised when a call is made in an invalid context.

Examples of this include calling UI functions within an activity context or calling scene manipulation functions outside of a scene context.

class bascenev1.ContextRef[source]

Bases: object

Store or use a Ballistica context.

Many operations such as bascenev1.newnode() or bascenev1.gettexture() operate implicitly on a current ‘context’. A context is some sort of state that functionality can implicitly use. Context determines, for example, which scene new nodes or textures get added to without having to specify that explicitly in the newnode()/gettexture() call. Contexts can also affect object lifecycles; for example a ContextCall will instantly become a no-op and release any references it is holding when the context it belongs to is destroyed.

In general, if you are a modder, you should not need to worry about contexts; mod code should mostly be getting run in the correct context and timers and other callbacks will take care of saving and restoring contexts automatically. There may be rare cases, however, where you need to deal directly with contexts, and that is where this class comes in.

Creating a context-ref will capture a reference to the current context. Other modules may provide ways to access their contexts; for example a bascenev1.Activity instance has a context attribute. You can also use the empty() classmethod to create a reference to no context. Some code such as UI calls may expect to be run with no context set and may complain if you try to use them within a context.

Usage

Context-refs are generally used with the Python with statement, which sets the context they point to as current on entry and resets it to the previous value on exit.

Example: Explicitly clear context while working with UI code from gameplay (UI stuff may complain if called within a context):

import bauiv1 as bui

def _callback_called_from_gameplay():

    # We are probably called with a game context as current, but
    # this makes UI stuff unhappy. So we clear the context while
    # doing our thing.
    with bui.ContextRef.empty():
        my_container = bui.containerwidget()
classmethod empty() ContextRef[source]

Return a context-ref pointing to no context.

This is useful when code should be run free of a context. For example, UI code generally insists on being run this way. Otherwise, callbacks set on the UI could inadvertently stop working due to a game activity ending, which would be unintuitive behavior.

is_empty() bool[source]

Whether the context was created as empty.

is_expired() bool[source]

Whether the context has expired.

Returns False for refs created as empty.

class bascenev1.CoopGameActivity(settings: dict)[source]

Bases: GameActivity[PlayerT, TeamT]

Base class for cooperative-mode games.

celebrate(duration: float) None[source]

Tells all existing player-controlled characters to celebrate.

Can be useful in co-op games when the good guys score or complete a wave. duration is given in seconds.

fade_to_red() None[source]

Fade the screen to red; (such as when the good guys have lost).

get_score_type() str[source]

Return the score unit this co-op game uses (‘point’, ‘seconds’, etc.)

on_begin() None[source]

Called once the previous activity has finished transitioning out.

At this point the activity’s initial players and teams are filled in and it should begin its actual game logic.

setup_low_life_warning_sound() None[source]

Set up a beeping noise to play when any players are near death.

spawn_player_spaz(player: PlayerT, position: Sequence[float] = (0.0, 0.0, 0.0), angle: float | None = None) PlayerSpaz[source]

Spawn and wire up a standard player spaz.

classmethod supports_session_type(sessiontype: type[bascenev1.Session]) bool[source]

Return whether this game supports the provided session type.

class bascenev1.CoopSession[source]

Bases: Session

A session which runs cooperative-mode games.

These generally consist of 1-4 players against the computer and include functionality such as high score lists.

allow_mid_activity_joins = False
campaign: bascenev1.Campaign | None

The baclassic.Campaign instance this Session represents, or None if there is no associated Campaign.

get_current_game_instance() bascenev1.GameActivity[source]

Get the game instance currently being played.

get_custom_menu_entries() list[dict[str, Any]][source]

Subclasses can override this to provide custom menu entries.

The returned value should be a list of dicts, each containing a ‘label’ and ‘call’ entry, with ‘label’ being the text for the entry and ‘call’ being the callable to trigger if the entry is pressed.

on_activity_end(activity: bascenev1.Activity, results: Any) None[source]

Method override for co-op sessions.

Jumps between co-op games and score screens.

on_player_leave(sessionplayer: bascenev1.SessionPlayer) None[source]

Called when a previously-accepted bascenev1.SessionPlayer leaves.

restart() None[source]

Restart the current game activity.

should_allow_mid_activity_joins(activity: bascenev1.Activity) bool[source]

Ask ourself if we should allow joins during an Activity.

Note that for a join to be allowed, both the session and activity have to be ok with it (via this function and the bascenev1.Activity.allow_mid_activity_joins property.

use_team_colors: bool = False

Whether players on a team should all adopt the colors of that team instead of their own profile colors. This only applies if use_teams is enabled.

use_teams: bool = True

Whether this session groups players into an explicit set of teams. If this is off, a unique team is generated for each player that joins.

class bascenev1.Data[source]

Bases: object

A reference to a data object.

Use bascenev1.getdata() to instantiate one.

getvalue() Any[source]

Return the data object’s value.

This can consist of anything representable by json (dicts, lists, numbers, bools, None, etc). Note that this call will block if the data has not yet been loaded, so it can be beneficial to plan a short bit of time between when the data object is requested and when it’s value is accessed.

class bascenev1.DeathType(*values)[source]

Bases: Enum

A reason for a death.

FALL = 'fall'
GENERIC = 'generic'
IMPACT = 'impact'
LEFT_GAME = 'left_game'
OUT_OF_BOUNDS = 'out_of_bounds'
REACHED_GOAL = 'reached_goal'
class bascenev1.Dependency(cls: type[T], config: Any = None)[source]

Bases: Generic[T]

A dependency on a DependencyComponent (with an optional config).

This class is used to request and access functionality provided by other DependencyComponent classes from a DependencyComponent class. The class functions as a descriptor, allowing dependencies to be added at a class level much the same as properties or methods and then used with class instances to access those dependencies. For instance, if you do ‘floofcls = bascenev1.Dependency(FloofClass)’ you would then be able to instantiate a FloofClass in your class’s methods via self.floofcls().

get_hash() int[source]

Return the dependency’s hash, calculating it if necessary.

class bascenev1.DependencyComponent[source]

Bases: object

Base class for all classes that can act as or use dependencies.

classmethod dep_is_present(config: Any = None) bool[source]

Return whether this component/config is present on this device.

classmethod get_dynamic_deps(config: Any = None) list[Dependency][source]

Return any dynamically-calculated deps for this component/config.

Deps declared statically as part of the class do not need to be included here; this is only for additional deps that may vary based on the dep config value. (for instance a map required by a game type)

class bascenev1.DependencySet(root_dependency: Dependency[T])[source]

Bases: Generic[T]

Set of resolved dependencies and their associated data.

To use DependencyComponents, a set must be created, resolved, and then loaded. The DependencyComponents are only valid while the set remains in existence.

get_asset_package_ids() set[str][source]

Return the set of asset-package-ids required by this dep-set.

Must be called on a resolved dep-set.

load() None[source]

Instantiate all DependencyComponents in the set.

Returns a wrapper which can be used to instantiate the root dep.

resolve() None[source]

Resolve the complete set of required dependencies for this set.

Raises a bascenev1.DependencyError if dependencies are missing (or other Exception types on other errors).

property resolved: bool

Whether this set has been successfully resolved.

property root: T

The instantiated root DependencyComponent instance for the set.

class bascenev1.DieMessage(immediate: bool = False, how: DeathType = DeathType.GENERIC)[source]

Bases: object

A message telling an object to die.

Most bascenev1.Actor-s respond to this.

how: DeathType = 'generic'

The particular reason for death.

immediate: bool = False

If this is set to True, the actor should disappear immediately. This is for ‘removing’ stuff from the game more so than ‘killing’ it. If False, the actor should die a ‘normal’ death and can take its time with lingering corpses, sound effects, etc.

class bascenev1.DisplayTimer(time: float, call: Callable[[], Any], repeat: bool = False)[source]

Bases: object

Timers are used to run code at later points in time.

This class encapsulates a timer based on display-time. The underlying timer will be destroyed when this object is no longer referenced. If you do not want to worry about keeping a reference to your timer around, use the displaytimer() function instead to get a one-off timer.

Display-time is a time value intended to be used for animation and other visual purposes. It will generally increment by a consistent amount each frame. It will pass at an overall similar rate to AppTime, but trades accuracy for smoothness.

Parameters:
  • time – Length of time in seconds that the timer will wait before firing.

  • call – A callable Python object. Remember that the timer will retain a strong reference to the callable for as long as it exists, so you may want to look into concepts such as WeakCall if that is not desired.

  • repeat – If True, the timer will fire repeatedly, with each successive firing having the same delay as the first.

Example: Use a Timer object to print repeatedly for a few seconds:

def say_it():
    babase.screenmessage('BADGER!')

def stop_saying_it():
    global g_timer
    g_timer = None
    babase.screenmessage('MUSHROOM MUSHROOM!')

# Create our timer; it will run as long as we keep its ref alive.
g_timer = babase.DisplayTimer(0.3, say_it, repeat=True)

# Now fire off a one-shot timer to kill the ref.
babase.displaytimer(3.89, stop_saying_it)
class bascenev1.DropMessage[source]

Bases: object

Tells an object that it has dropped what it was holding.

class bascenev1.DroppedMessage(node: bascenev1.Node)[source]

Bases: object

Tells an object that it has been dropped.

node: bascenev1.Node

The bascenev1.Node doing the dropping.

class bascenev1.DualTeamSession[source]

Bases: MultiTeamSession

bascenev1.Session type for teams mode games.

use_team_colors: bool = True

Whether players on a team should all adopt the colors of that team instead of their own profile colors. This only applies if use_teams is enabled.

use_teams: bool = True

Whether this session groups players into an explicit set of teams. If this is off, a unique team is generated for each player that joins.

class bascenev1.EmptyPlayer[source]

Bases: Player[bascenev1.EmptyTeam]

An empty player for use by Activities that don’t need to define one.

bascenev1.Player and bascenev1.Team are ‘Generic’ types, and so passing those top level classes as type arguments when defining a bascenev1.Activity reduces type safety. For example, activity.teams[0].player will have type ‘Any’ in that case. For that reason, it is better to pass EmptyPlayer and EmptyTeam when defining a bascenev1.Activity that does not need custom types of its own.

Note that EmptyPlayer defines its team type as EmptyTeam and vice versa, so if you want to define your own class for one of them you should do so for both.

class bascenev1.EmptyTeam[source]

Bases: Team[bascenev1.EmptyPlayer]

An empty player for use by Activities that don’t define one.

bascenev1.Player and bascenev1.Team are ‘Generic’ types, and so passing those top level classes as type arguments when defining a bascenev1.Activity reduces type safety. For example, activity.teams[0].player will have type ‘Any’ in that case. For that reason, it is better to pass EmptyPlayer and EmptyTeam when defining a bascenev1.Activity that does not need custom types of its own.

Note that EmptyPlayer defines its team type as EmptyTeam and vice versa, so if you want to define your own class for one of them you should do so for both.

class bascenev1.FloatChoiceSetting(name: str, default: float, choices: list[tuple[str, float]])[source]

Bases: ChoiceSetting

A float setting with multiple choices.

choices: list[tuple[str, float]]
default: float
class bascenev1.FloatSetting(name: str, default: float, min_value: float = 0.0, max_value: float = 9999.0, increment: float = 1.0)[source]

Bases: Setting

A floating point game setting.

default: float
increment: float = 1.0
max_value: float = 9999.0
min_value: float = 0.0
class bascenev1.FreeForAllSession[source]

Bases: MultiTeamSession

bascenev1.Session type for free-for-all mode games.

get_ffa_point_awards() dict[int, int][source]

Return the number of points awarded for different rankings.

This is based on the current number of players.

use_team_colors: bool = False

Whether players on a team should all adopt the colors of that team instead of their own profile colors. This only applies if use_teams is enabled.

use_teams: bool = False

Whether this session groups players into an explicit set of teams. If this is off, a unique team is generated for each player that joins.

class bascenev1.FreezeMessage(time: float = 5.0)[source]

Bases: object

Tells an object to become frozen.

As seen in the effects of an ice bascenev1.Bomb.

time: float = 5.0

The amount of time the object will be frozen.

class bascenev1.GameActivity(settings: dict)[source]

Bases: Activity[PlayerT, TeamT]

Common base class for all game bascenev1.Activities.

allow_kick_idle_players = True

Whether idle players can potentially be kicked (should not happen in menus/etc).

allow_pausing = True

Whether scene-time should still progress when in menus/etc.

available_settings: list[bascenev1.Setting] | None = None
default_music: bascenev1.MusicType | None = None
description: str | None = None
end(results: Any = None, delay: float = 0.0, force: bool = False) None[source]

Commence activity shutdown and delivers results to the session.

‘delay’ is the time delay before the Activity actually ends (in seconds). Further end calls will be ignored up until this time, unless ‘force’ is True, in which case the new results will replace the old.

end_game() None[source]

Tell the game to wrap up and call bascenev1.Activity.end().

This method should be overridden by subclasses. A game should always be prepared to end and deliver results, even if there is no ‘winner’ yet; this way things like the standard time-limit (bascenev1.GameActivity.setup_standard_time_limit()) will work with the game.

classmethod get_available_settings(sessiontype: type[bascenev1.Session]) list[bascenev1.Setting][source]

Return a list of settings relevant to this game type when running under the provided session type.

classmethod get_description(sessiontype: type[bascenev1.Session]) str[source]

Get a str description of this game type.

The default implementation simply returns the ‘description’ class var. Classes which want to change their description depending on the session can override this method.

classmethod get_description_display_string(sessiontype: type[bascenev1.Session]) babase.Lstr[source]

Return a translated version of get_description().

Sub-classes should override get_description(); not this.

classmethod get_display_string(settings: dict | None = None) Lstr[source]

Return a descriptive name for this game/settings combo.

Subclasses should override getname(); not this.

get_instance_description() str | Sequence[source]

Return a description for this game instance, in English.

This is shown in the center of the screen below the game name at the start of a game. It should start with a capital letter and end with a period, and can be a bit more verbose than the version returned by get_instance_description_short().

Note that translation is applied by looking up the specific returned value as a key, so the number of returned variations should be limited; ideally just one or two. To include arbitrary values in the description, you can return a sequence of values in the following form instead of just a string:

# This will give us something like ‘Score 3 goals.’ in English # and can properly translate to ‘Anota 3 goles.’ in Spanish. # If we just returned the string ‘Score 3 Goals’ here, there would # have to be a translation entry for each specific number. ew. return [‘Score ${ARG1} goals.’, self.settings_raw[‘Score to Win’]]

This way the first string can be consistently translated, with any arg values then substituted into the result. ${ARG1} will be replaced with the first value, ${ARG2} with the second, etc.

get_instance_description_short() str | Sequence[source]

Return a short description for this game instance in English.

This description is used above the game scoreboard in the corner of the screen, so it should be as concise as possible. It should be lowercase and should not contain periods or other punctuation.

Note that translation is applied by looking up the specific returned value as a key, so the number of returned variations should be limited; ideally just one or two. To include arbitrary values in the description, you can return a sequence of values in the following form instead of just a string:

# This will give us something like ‘score 3 goals’ in English # and can properly translate to ‘anota 3 goles’ in Spanish. # If we just returned the string ‘score 3 goals’ here, there would # have to be a translation entry for each specific number. ew. return [‘score ${ARG1} goals’, self.settings_raw[‘Score to Win’]]

This way the first string can be consistently translated, with any arg values then substituted into the result. ${ARG1} will be replaced with the first value, ${ARG2} with the second, etc.

get_instance_display_string() Lstr[source]

Return a name for this particular game instance.

get_instance_scoreboard_display_string() Lstr[source]

Return a name for this particular game instance.

This name is used above the game scoreboard in the corner of the screen, so it should be as concise as possible.

classmethod get_settings_display_string(config: dict[str, Any]) Lstr[source]

Given a game config dict, return a short description for it.

This is used when viewing game-lists or showing what game is up next in a series.

classmethod get_supported_maps(sessiontype: type[bascenev1.Session]) list[str][source]

Called by the default bascenev1.GameActivity.create_settings_ui() implementation; should return a list of map names valid for this game-type for the given bascenev1.Session type.

classmethod get_team_display_string(name: str) Lstr[source]

Given a team name, returns a localized version of it.

classmethod getname() str[source]

Return a str name for this game type.

This default implementation simply returns the ‘name’ class attr.

classmethod getscoreconfig() bascenev1.ScoreConfig[source]

Return info about game scoring setup; can be overridden by games.

handlemessage(msg: Any) Any[source]

General message handling; can be passed any message object.

initialplayerinfos: list[bascenev1.PlayerInfo] | None

Holds some flattened info about the player set at the point when on_begin() is called.

property map: Map

The map being used for this game.

Raises a bascenev1.MapNotFoundError if the map does not currently exist.

name: str | None = None
on_begin() None[source]

Called once the previous activity has finished transitioning out.

At this point the activity’s initial players and teams are filled in and it should begin its actual game logic.

on_player_join(player: PlayerT) None[source]

Called when a player joins the activity.

(including the initial set of players)

on_transition_in() None[source]

Called when the activity is first becoming visible.

Upon this call, the activity should fade in backgrounds, start playing music, etc. It does not yet have access to players or teams, however. They remain owned by the previous activity up until on_begin() is called.

respawn_player(player: PlayerT, respawn_time: float | None = None) None[source]

Given a bascenev1.Player, sets up a standard respawn timer, along with the standard counter display, etc. At the end of the respawn period spawn_player() will be called if the Player still exists. An explicit ‘respawn_time’ can optionally be provided (in seconds).

scoreconfig: bascenev1.ScoreConfig | None = None
setup_standard_powerup_drops(enable_tnt: bool = True) None[source]

Create standard powerup drops for the current map.

setup_standard_time_limit(duration: float) None[source]

Create a standard game time-limit given the provided duration in seconds. This will be displayed at the top of the screen. If the time-limit expires, end_game() will be called.

show_kill_points = True
show_zoom_message(message: Lstr, *, color: Sequence[float] = (0.9, 0.4, 0.0), scale: float = 0.8, duration: float = 2.0, trail: bool = False) None[source]

Zooming text used to announce game names and winners.

spawn_player(player: PlayerT) bascenev1.Actor[source]

Spawn something for the provided player.

The default implementation simply calls spawn_player_spaz().

spawn_player_if_exists(player: PlayerT) None[source]

A utility method which calls self.spawn_player() only if the bascenev1.Player provided still exists; handy for use in timers and whatnot.

There is no need to override this; just override spawn_player().

spawn_player_spaz(player: PlayerT, position: Sequence[float] = (0, 0, 0), angle: float | None = None) PlayerSpaz[source]

Create and wire up a player-spaz for the provided player.

classmethod supports_session_type(sessiontype: type[bascenev1.Session]) bool[source]

Return whether this game supports the provided session type.

tips: list[str | bascenev1.GameTip] = []
class bascenev1.GameResults[source]

Bases: object

Results for a completed game.

Upon completion, a game should fill one of these out and pass it to its end() call.

get_sessionteam_score(sessionteam: bascenev1.SessionTeam) int | None[source]

Return the score for a given team.

get_sessionteam_score_str(sessionteam: bascenev1.SessionTeam) babase.Lstr[source]

Return the score for the given team as an Lstr.

(properly formatted for the score type.)

has_score_for_sessionteam(sessionteam: bascenev1.SessionTeam) bool[source]

Return whether there is a score for a given team.

property lower_is_better: bool

Whether lower scores are better.

property playerinfos: list[bascenev1.PlayerInfo]

Get info about the players represented by the results.

property score_label: str

The label associated with scores (‘points’, etc).

property scoretype: bascenev1.ScoreType

The type of score.

property sessionteams: list[bascenev1.SessionTeam]

Return all teams in the results.

set_game(game: bascenev1.GameActivity) None[source]

Set the game instance these results are applying to.

set_team_score(team: bascenev1.Team, score: int | None) None[source]

Set the score for a given team.

This can be a number or None (see the none_is_winner arg in the constructor).

property winnergroups: list[WinnerGroup]

The ordered list of winner-groups.

property winning_sessionteam: bascenev1.SessionTeam | None

The winning team if there is exactly one, or else None.

class bascenev1.GameTip(text: str, icon: bascenev1.Texture | None = None, sound: bascenev1.Sound | None = None)[source]

Bases: object

Defines a tip presentable to the user at the start of a game.

icon: bascenev1.Texture | None = None
sound: bascenev1.Sound | None = None
text: str
class bascenev1.HitMessage(*, srcnode: bascenev1.Node | None = None, pos: Sequence[float] | None = None, velocity: Sequence[float] | None = None, magnitude: float = 1.0, velocity_magnitude: float = 0.0, radius: float = 1.0, source_player: bascenev1.Player | None = None, kick_back: float = 1.0, flat_damage: float | None = None, hit_type: str = 'generic', force_direction: Sequence[float] | None = None, hit_subtype: str = 'default')[source]

Bases: object

Tells an object it has been hit in some way.

This is used by punches, explosions, etc to convey their effect to a target.

get_source_player(playertype: type[PlayerT]) PlayerT | None[source]

Return the source-player if one exists and is the provided type.

class bascenev1.HostInfo(name: str, build_number: int, address: str | None, port: int | None)[source]

Bases: object

Info about a host.

address: str | None
build_number: int
name: str
port: int | None
class bascenev1.ImpactDamageMessage(intensity: float)[source]

Bases: object

Tells an object that it has been jarred violently.

intensity: float

The intensity of the impact.

class bascenev1.InputDevice[source]

Bases: object

An input-device such as a gamepad, touchscreen, or keyboard.

allows_configuring: bool

Whether the input-device can be configured in the app.

allows_configuring_in_system_settings: bool

Whether the input-device can be configured in the system. setings app. This can be used to redirect the user to go there if they attempt to configure the device.

client_id: int

The numeric client-id this device is associated with. This is only meaningful for remote client inputs; for all local devices this will be -1.

detach_from_player() None[source]

Detach the device from any player it is controlling.

This applies both to local players and remote players.

exists() bool[source]

Return whether the underlying device for this object is still present.

get_axis_name(axis_id: int) str[source]

Given an axis ID, return the name of the axis on this device.

Can return an empty string if the value is not meaningful to humans.

get_button_name(button_id: int) babase.Lstr[source]

Given a button ID, return a human-readable name for that key/button.

Can return an empty string if the value is not meaningful to humans.

get_default_player_name() str[source]

(internal)

Returns the default player name for this device. (used for the ‘random’ profile)

get_player_profiles() dict[source]

(internal)

get_v1_account_name(full: bool) str[source]

Returns the account name associated with this device.

(can be used to get account names for remote players)

has_meaningful_button_names: bool

Whether button names returned by this instance match labels on the actual device. (Can be used to determine whether to show them in controls-overlays, etc.).

id: int

The unique numeric id of this device.

instance_number: int

The number of this device among devices of the same type.

is_attached_to_player() bool[source]

Return whether this device is controlling a player of some sort.

This can mean either a local player or a remote player.

is_controller_app: bool

Whether this input-device represents a locally-connected controller-app.

is_remote_client: bool

Whether this input-device represents a remotely-connected client.

is_test_input: bool

Whether this input-device is a dummy device for testing.

name: str

The name of the device.

player: bascenev1.SessionPlayer | None

The player associated with this input device.

unique_identifier: str

A string that can be used to persistently identify the device, even among other devices of the same type. Used for saving prefs, etc.

class bascenev1.InputType(*values)[source]

Bases: Enum

Types of input a controller can send to the game.

BOMB_PRESS = 8
BOMB_RELEASE = 9
DOWN_PRESS = 25
DOWN_RELEASE = 26
FLY_PRESS = 13
FLY_RELEASE = 14
HOLD_POSITION_PRESS = 17
HOLD_POSITION_RELEASE = 18
JUMP_PRESS = 4
JUMP_RELEASE = 5
LEFT_PRESS = 19
LEFT_RELEASE = 20
LEFT_RIGHT = 3
PICK_UP_PRESS = 10
PICK_UP_RELEASE = 11
PUNCH_PRESS = 6
PUNCH_RELEASE = 7
RIGHT_PRESS = 21
RIGHT_RELEASE = 22
RUN = 12
START_PRESS = 15
START_RELEASE = 16
UP_DOWN = 2
UP_PRESS = 23
UP_RELEASE = 24
class bascenev1.IntChoiceSetting(name: str, default: int, choices: list[tuple[str, int]])[source]

Bases: ChoiceSetting

An int setting with multiple choices.

choices: list[tuple[str, int]]
default: int
class bascenev1.IntSetting(name: str, default: int, min_value: int = 0, max_value: int = 9999, increment: int = 1)[source]

Bases: Setting

An integer game setting.

default: int
increment: int = 1
max_value: int = 9999
min_value: int = 0
class bascenev1.JoinActivity(settings: dict)[source]

Bases: Activity[EmptyPlayer, EmptyTeam]

Standard activity for waiting for players to join.

It shows tips and other info and waits for all players to check ready.

on_transition_in() None[source]

Called when the activity is first becoming visible.

Upon this call, the activity should fade in backgrounds, start playing music, etc. It does not yet have access to players or teams, however. They remain owned by the previous activity up until on_begin() is called.

class bascenev1.Level(name: str, gametype: type[bascenev1.GameActivity], settings: dict, preview_texture_name: str, *, displayname: str | None = None)[source]

Bases: object

An entry in a Campaign.

property campaign: bascenev1.Campaign | None

The campaign this level is associated with, or None.

property complete: bool

Whether this level has been completed.

property displayname: bascenev1.Lstr

The localized name for this level.

property gametype: type[bascenev1.GameActivity]

The type of game used for this level.

get_high_scores() dict[source]

Return the current high scores for this level.

get_score_version_string() str[source]

Return the score version string for this level.

If a level’s gameplay changes significantly, its version string can be changed to separate its new high score lists/etc. from the old.

get_settings() dict[str, Any][source]

Returns the settings for this Level.

property index: int

The zero-based index of this level in its campaign.

Access results in a RuntimeError if the level is not assigned to a campaign.

property name: str

The unique name for this level.

property preview_texture_name: str

The preview texture name for this level.

property rating: float

The current rating for this level.

set_complete(val: bool) None[source]

Set whether or not this level is complete.

set_high_scores(high_scores: dict) None[source]

Set high scores for this level.

set_rating(rating: float) None[source]

Set a rating for this level, replacing the old ONLY IF higher.

class bascenev1.Lobby[source]

Bases: object

Environment where players can selecting characters, etc.

add_chooser(sessionplayer: bascenev1.SessionPlayer) None[source]

Add a chooser to the lobby for the provided player.

check_all_ready() bool[source]

Return whether all choosers are marked ready.

create_join_info() JoinInfo[source]

Create a display of on-screen information for joiners.

(how to switch teams, players, etc.) Intended for use in initial joining-screens.

get_choosers() list[Chooser][source]

The current choosers present.

property next_add_team: int

(internal)

reload_profiles() None[source]

Reload available player profiles.

remove_all_choosers() None[source]

Remove all choosers without kicking players.

This is called after all players check in and enter a game.

remove_all_choosers_and_kick_players() None[source]

Remove all player choosers and kick attached players.

remove_chooser(player: bascenev1.SessionPlayer) None[source]

Remove a single player’s chooser; does not kick them.

This is used when a player enters the game and no longer needs a chooser.

property sessionteams: list[bascenev1.SessionTeam]

The teams available in this lobby.

update_positions() None[source]

Update positions for all choosers.

property use_team_colors: bool

Whether this lobby is using team colors.

If False, inidividual player colors are used instead.

class bascenev1.Lstr(*, resource: str, fallback_resource: str = '', fallback_value: str = '', subs: Sequence[tuple[str, str | Lstr]] | None = None)[source]
class bascenev1.Lstr(*, translate: tuple[str, str], subs: Sequence[tuple[str, str | Lstr]] | None = None)
class bascenev1.Lstr(*, value: str, subs: Sequence[tuple[str, str | Lstr]] | None = None)

Bases: object

Used to define strings in a language-independent way.

These should be used whenever possible in place of hard-coded strings so that in-game or UI elements show up correctly on all clients in their currently active language.

To see available resource keys, look at any of the ba_data/data/languages/*.json files in the game or the translations pages at legacy.ballistica.net/translate.

Parameters:
  • resource – Pass a string to look up a translation by resource key.

  • translate – Pass a tuple consisting of a translation category and untranslated value. Any matching translation found in that category will be used. Otherwise the untranslated value will be.

  • value – Pass a regular string value to be used as-is.

  • subs – A sequence of 2-member tuples consisting of values and replacements. Replacements can be regular strings or other Lstr values.

  • fallback_resource – A resource key that will be used if the main one is not present for the current language instead of falling back to the english value (‘resource’ mode only).

  • fallback_value – A regular string that will be used if neither the resource nor the fallback resource is found (‘resource’ mode only).

Example 1: Resource path

mynode.text = babase.Lstr(resource='audioSettingsWindow.titleText')

Example 2: Translation

If a translated value is available, it will be used; otherwise the English value will be. To see available translation categories, look under the translations resource section.

mynode.text = babase.Lstr(translate=('gameDescriptions',
                                     'Defeat all enemies'))

Example 3: Substitutions

Substitutions can be used with resource and translate modes as well as the value shown here.

mynode.text = babase.Lstr(value='${A} / ${B}',
                          subs=[('${A}', str(score)),
                                ('${B}', str(total))])

Example 4: Nesting

Lstr instances can be nested. This example would display the translated resource at 'res_a' but replace any instances of '${NAME}' it contains with the translated resource at 'res_b'.

mytextnode.text = babase.Lstr(
    resource='res_a',
    subs=[('${NAME}', babase.Lstr(resource='res_b'))])
args

Basically just stores the exact args passed. However if Lstr values were passed for subs, they are replaced with that Lstr’s dict.

evaluate() str[source]

Evaluate to a flat string in the current language.

You should avoid doing this as much as possible and instead pass and store Lstr values.

static from_json(json_string: str) babase.Lstr[source]

Given a json string, returns a Lstr.

Does no validation.

is_flat_value() bool[source]

Return whether this instance represents a ‘flat’ value.

This is defined as a simple string value incorporating no translations, resources, or substitutions. In this case it may be reasonable to replace it with a raw string value, perform string manipulation on it, etc.

class bascenev1.Map(vr_overlay_offset: Sequence[float] | None = None)[source]

Bases: Actor

A game map.

Consists of a collection of terrain nodes, metadata, and other functionality comprising a game map.

defs: Any = None
exists() bool[source]

Returns whether the actor is still present in a meaningful way.

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 is_alive() for that).

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 bascenev1.Actor.autoretain()

The default implementation of this method always return True.

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.

get_def_bound_box(name: str) tuple[float, float, float, float, float, float] | None[source]

Return a 6 member bounds tuple or None if it is not defined.

get_def_point(name: str) Sequence[float] | None[source]

Return a single defined point or a default value in its absence.

get_def_points(name: str) list[Sequence[float]][source]

Return a list of named points.

Return as many sequential ones are defined (flag1, flag2, flag3), etc. If none are defined, returns an empty list.

get_ffa_start_position(players: Sequence[bascenev1.Player]) Sequence[float][source]

Return a random starting position in one of the FFA spawn areas.

If a list of bascenev1.Player-s is provided; the returned points will be as far from these players as possible.

get_flag_position(team_index: int | None = None) Sequence[float][source]

Return a flag position on the map for the given team index.

Pass None to get the default flag point. (used for things such as king-of-the-hill)

classmethod get_music_type() bascenev1.MusicType | None[source]

Return a music-type string that should be played on this map.

If None is returned, default music will be used.

classmethod get_play_types() list[str][source]

Return valid play types for this map.

classmethod get_preview_texture_name() str | None[source]

Return the name of the preview texture for this map.

get_start_position(team_index: int) Sequence[float][source]

Return a random starting position for the given team index.

classmethod getname() str[source]

Return the unique name of this map, in English.

handlemessage(msg: Any) Any[source]

General message handling; can be passed any message object.

is_point_near_edge(point: Vec3, running: bool = False) bool[source]

Return whether the provided point is near an edge of the map.

Simple bot logic uses this call to determine if they are approaching a cliff or wall. If this returns True they will generally not walk/run any farther away from the origin. If ‘running’ is True, the buffer should be a bit larger.

name = 'Map'
classmethod on_preload() Any[source]

Called when the map is being preloaded.

It should return any media/data it requires to operate

classmethod preload() None[source]

Preload map media.

This runs the class’s on_preload() method as needed to prep it to run. Preloading should generally be done in a bascenev1.Activity’s __init__ method. Note that this is a classmethod since it is not operate on map instances but rather on the class itself before instances are made

class bascenev1.Material(label: str | None = None)[source]

Bases: object

An entity applied to game objects to modify collision behavior.

A material can affect physical characteristics, generate sounds, or trigger callback functions when collisions occur.

Materials are applied to ‘parts’, which are groups of one or more rigid bodies created as part of a bascenev1.Node. Nodes can have any number of parts, each with its own set of materials. Generally materials are specified as array attributes on the Node. The spaz node, for example, has various attributes such as materials, roller_materials, and punch_materials, which correspond to the various parts it creates.

Use bascenev1.Material to instantiate a blank material, and then use its bascenev1.Material.add_actions() method to define what the material does.

add_actions(actions: tuple, conditions: tuple | None = None) None[source]

Add one or more actions to the material, optionally with conditions.

Conditions

Conditions are provided as tuples which can be combined to form boolean logic. A single condition might look like:

('condition_name', cond_arg)

Or a more complex nested one might look like:

(('condition1', cond_arg), 'or', ('condition2', cond2_arg))

The strings 'and', 'or', and 'xor' can chain together two conditions, as seen above.

Available Conditions

('they_have_material', material)

Does the part we’re hitting have a given bascenev1.Material?

('they_dont_have_material', material)

Does the part we’re hitting not have a given bascenev1.Material?

('eval_colliding')

Is 'collide' true at this point in material evaluation? (see the modify_part_collision action)

('eval_not_colliding')

Is collide false at this point in material evaluation? (see the modify_part_collision action)

('we_are_younger_than', age)

Is our part younger than age (in milliseconds)?

('we_are_older_than', age)

Is our part older than age (in milliseconds)?

('they_are_younger_than', age)

Is the part we’re hitting younger than age (in milliseconds)?

('they_are_older_than', age)

Is the part we’re hitting older than age (in milliseconds)?

('they_are_same_node_as_us')

Does the part we’re hitting belong to the same bascenev1.Node as us?

('they_are_different_node_than_us')

Does the part we’re hitting belong to a different bascenev1.Node?

Actions

In a similar manner, actions are specified as tuples. Multiple actions can be specified by providing a tuple of tuples.

Available Actions

('call', when, callable)

Calls the provided callable; when can be either 'at_connect' or 'at_disconnect'. 'at_connect' means to fire when the two parts first come in contact; 'at_disconnect' means to fire once they cease being in contact.

('message', who, when, message_obj)

Sends a message object; who can be either 'our_node' or 'their_node', when can be 'at_connect' or 'at_disconnect', and message_obj is the message object to send. This has the same effect as calling the node’s bascenev1.Node.handlemessage() method.

('modify_part_collision', attr, value)

Changes some characteristic of the physical collision that will occur between our part and their part. This change will remain in effect as long as the two parts remain overlapping. This means if you have a part with a material that turns 'collide' off against parts younger than 100ms, and it touches another part that is 50ms old, it will continue to not collide with that part until they separate, even if the 100ms threshold is passed. Options for attr/value are: 'physical' (boolean value; whether a physical response will occur at all), 'friction' (float value; how friction-y the physical response will be), 'collide' (boolean value; whether any collision will occur at all, including non-physical stuff like callbacks), 'use_node_collide' (boolean value; whether to honor modify_node_collision overrides for this collision), 'stiffness' (float value, how springy the physical response is), 'damping' (float value, how damped the physical response is), 'bounce' (float value; how bouncy the physical response is).

('modify_node_collision', attr, value)

Similar to modify_part_collision, but operates at a node-level. Collision attributes set here will remain in effect as long as anything from our part’s node and their part’s node overlap. A key use of this functionality is to prevent new nodes from colliding with each other if they appear overlapped; if modify_part_collision is used, only the individual parts that were overlapping would avoid contact, but other parts could still contact leaving the two nodes ‘tangled up’. Using modify_node_collision ensures that the nodes must completely separate before they can start colliding. Currently the only attr available here is 'collide' (a boolean value).

('sound', sound, volume)

Plays a bascenev1.Sound when a collision occurs, at a given volume, regardless of the collision speed/etc.

('impact_sound', sound, target_impulse, volume)

Plays a sound when a collision occurs, based on the speed of impact. Provide a bascenev1.Sound, a target-impulse, and a volume.

('skid_sound', sound, target_impulse, volume)

Plays a sound during a collision when parts are ‘scraping’ against each other. Provide a bascenev1.Sound, a target-impulse, and a volume.

('roll_sound', sound, targetImpulse, volume)

Plays a sound during a collision when parts are ‘rolling’ against each other. Provide a bascenev1.Sound, a target-impulse, and a volume.

Examples

Example 1: Create a material that lets us ignore collisions against any nodes we touch in the first 100 ms of our existence; handy for preventing us from exploding outward if we spawn on top of another object:

m = bascenev1.Material()
m.add_actions(
     conditions=(('we_are_younger_than', 100),
                 'or', ('they_are_younger_than', 100)),
     actions=('modify_node_collision', 'collide', False))

Example 2: Send a bascenev1.DieMessage to anything we touch, but cause no physical response. This should cause any bascenev1.Actor to drop dead:

m = bascenev1.Material()
m.add_actions(
 actions=(
   ('modify_part_collision', 'physical', False),
   ('message', 'their_node', 'at_connect', bascenev1.DieMessage())
 )
)

Example 3: Play some sounds when we’re contacting the ground:

m = bascenev1.Material()
m.add_actions(
  conditions=('they_have_material' shared.footing_material),
  actions=(
    ('impact_sound', bascenev1.getsound('metalHit'), 2, 5),
    ('skid_sound', bascenev1.getsound('metalSkid'), 2, 5)
  )
)
label: str

A label for the material; only used for debugging.

class bascenev1.Mesh[source]

Bases: object

A reference to a mesh.

Meshes are used for drawing. Use bascenev1.getmesh() to instantiate one.

class bascenev1.MultiTeamSession[source]

Bases: Session

Common base for DualTeamSession and FreeForAllSession.

Free-for-all-mode is essentially just teams-mode with each bascenev1.Player having their own bascenev1.Team, so there is much overlap in functionality.

announce_game_results(activity: bascenev1.GameActivity, results: bascenev1.GameResults, delay: float, announce_winning_team: bool = True) None[source]

Show basic game result at the end of a game.

(before transitioning to a score screen). This will include a zoom-text of ‘BLUE WINS’ or whatnot, along with a possible audio announcement of the same.

get_ffa_series_length() int[source]

Return free-for-all series length.

get_game_number() int[source]

Returns which game in the series is currently being played.

get_max_players() int[source]

Return max number of Players allowed to join the game at once.

get_next_game_description() Lstr[source]

Returns a description of the next game on deck.

get_series_length() int[source]

Return teams series length.

on_activity_end(activity: bascenev1.Activity, results: Any) None[source]

Called when the current activity has ended.

The session should look at the results and start another activity.

on_team_join(team: bascenev1.SessionTeam) None[source]

Called when a new team joins the session.

class bascenev1.MusicType(*values)[source]

Bases: Enum

Types of music available to play in-game.

These do not correspond to specific pieces of music, but rather to ‘situations’. The actual music played for each type can be overridden by the game or by the user.

CHAR_SELECT = 'CharSelect'
CHOSEN_ONE = 'Chosen One'
EPIC = 'Epic'
EPIC_RACE = 'Epic Race'
FLAG_CATCHER = 'FlagCatcher'
FLYING = 'Flying'
FOOTBALL = 'Football'
FORWARD_MARCH = 'ForwardMarch'
GRAND_ROMP = 'GrandRomp'
HOCKEY = 'Hockey'
KEEP_AWAY = 'Keep Away'
MARCHING = 'Marching'
MENU = 'Menu'
ONSLAUGHT = 'Onslaught'
RACE = 'Race'
RUN_AWAY = 'RunAway'
SCARY = 'Scary'
SCORES = 'Scores'
SPORTS = 'Sports'
SURVIVAL = 'Survival'
TO_THE_DEATH = 'ToTheDeath'
VICTORY = 'Victory'
class bascenev1.Node[source]

Bases: object

Reference to a Node; the low level building block of a game.

At its core, a game is nothing more than a scene of Nodes with attributes getting interconnected or set over time.

A bascenev1.Node instance should be thought of as a weak-reference to a game node; not the node itself. This means a Node’s lifecycle is completely independent of how many Python references to it exist. To explicitly add a new node to the game, use bascenev1.newnode(), and to explicitly delete one, use bascenev1.Node.delete(). bascenev1.Node.exists() can be used to determine if a Node still points to a live node in the game.

You can use bascenev1.Node(None) to instantiate an invalid Node reference (sometimes used as attr values/etc).

add_death_action(action: Callable[[], None]) None[source]

Add a callable object to be called upon this node’s death. Note that these actions are run just after the node dies, not before.

allow_kick_idle_players: bool = False

Available on globals node.

always_show_health_bar: bool = False

On shield node.

ambient_color: Sequence[float] = (1.0, 1.0, 1.0)
area_of_interest_bounds: Sequence[float] = (-1, -1, -1, 1, 1, 1)
billboard_cross_out: bool = False

Available on spaz node.

billboard_opacity: float = 0.0

Available on spaz node.

billboard_texture: bascenev1.Texture | None = None

Available on spaz node.

bomb_pressed: bool = False
boxing_gloves: bool = False
boxing_gloves_flashing: bool = False

Available on spaz node.

camera_mode: str = 'rotate'
client_only: bool = False
color: Sequence[float] = (0.0, 0.0, 0.0)
connectattr(srcattr: str, dstnode: Node, dstattr: str) None[source]

Connect one of this node’s attributes to an attribute on another node. This will immediately set the target attribute’s value to that of the source attribute, and will continue to do so once per step as long as the two nodes exist. The connection can be severed by setting the target attribute to any value or connecting another node attribute to it.

Example: Create a locator and attach a light to it:

light = bascenev1.newnode('light')
loc = bascenev1.newnode('locator', attrs={'position': (0, 10, 0)})
loc.connectattr('position', light, 'position')
counter_text: str = ''
counter_texture: bascenev1.Texture | None = None
curse_death_time: int = 0
damage: int = 0
damage_smoothed: float = 0.0
dead: bool = False

Available on spaz node.

debris_friction: float = 0.0
debris_kill_height: float = 0.0
delete(ignore_missing: bool = True) None[source]

Delete the node. Ignores already-deleted nodes if ignore_missing is True; otherwise a babase.NodeNotFoundError is thrown.

exists() bool[source]

Returns whether the Node still exists. Most functionality will fail on a nonexistent Node, so it’s never a bad idea to check this.

Note that you can also use the boolean operator for this same functionality, so a statement such as “if mynode” will do the right thing both for Node objects and values of None.

extras_material: Sequence[bascenev1.Material] = ()
flashing: bool = False
floor_reflection: bool = False
fly_pressed: bool = False
frozen: bool = False
getdelegate(type: Any, doraise: bool = False) Any[source]

Return the node’s current delegate object if it matches a certain type.

If the node has no delegate or it is not an instance of the passed type, then None will be returned. If ‘doraise’ is True, then an bascenev1.DelegateNotFoundError will be raised instead.

getname() str[source]

Return the name assigned to a Node; used mainly for debugging

getnodetype() str[source]

Return the internal type of node referenced by this object as a string. (Note this is different from the Python type which is always bascenev1.Node)

gravity_scale: float = 1.0
handlemessage(*args: Any) None[source]

General message handling; can be passed any message object.

All standard message objects are forwarded along to the node’s delegate for handling (generally the bascenev1.Actor that made the node).

Nodes also support a second form of message; ‘node-messages’. These consist of a string type-name as a first argument along with the args specific to that type name as additional arguments. Node-messages communicate directly with the low-level node layer and are delivered simultaneously on all game clients, acting as an alternative to setting node attributes.

happy_thoughts_mode: bool = False
hockey: bool = False
hold_body: int = 0
hold_node: bascenev1.Node | None = None
hold_position_pressed: bool = False
host_only: bool = False
hurt: float = 0.0

Available on spaz node.

input0: float = 0.0
input1: float = 0.0
input2: float = 0.0
input3: float = 0.0
invincible: bool = False
is_area_of_interest: bool = False
jump_pressed: bool = False
knockout: float = 0.0

Available on spaz node.

loop: bool = False
materials: Sequence[bascenev1.Material] = ()
mesh_opaque: bascenev1.Mesh | None = None
mesh_transparent: bascenev1.Mesh | None = None
mini_billboard_1_end_time: int = 0

Available on spaz node.

mini_billboard_1_start_time: int = 0

Available on spaz node.

mini_billboard_1_texture: bascenev1.Texture | None = None

Available on spaz node.

mini_billboard_2_end_time: int = 0

Available on spaz node.

mini_billboard_2_start_time: int = 0

Available on spaz node.

mini_billboard_2_texture: bascenev1.Texture | None = None

Available on spaz node.

mini_billboard_3_end_time: int = 0

Available on spaz node.

mini_billboard_3_start_time: int = 0

Available on spaz node.

mini_billboard_3_texture: bascenev1.Texture | None = None

Available on spaz node.

move_left_right: float = 0.0

Available on spaz node.

move_up_down: float = 0.0

Available on spaz node.

music: str = ''
music_continuous: bool = False
music_count: int = 0
name: str = ''
name_color: Sequence[float] = (0.0, 0.0, 0.0)
offset: float = 0.0
opacity: float = 0.0
paused: bool = False
pickup_materials: Sequence[bascenev1.Material] = ()
pickup_pressed: bool = False
position: Sequence[float] = (0.0, 0.0, 0.0)
position_center: Sequence[float] = (0.0, 0.0, 0.0)
position_forward: Sequence[float] = (0.0, 0.0, 0.0)
premultiplied: bool = False
punch_materials: Sequence[bascenev1.Material] = ()
punch_momentum_angular: float = 0.0
punch_momentum_linear: Sequence[float] = (0.0, 0.0, 0.0)
punch_position: Sequence[float] = (0.0, 0.0, 0.0)
punch_power: float = 0.0
punch_pressed: bool = False
punch_velocity: Sequence[float] = (0.0, 0.0, 0.0)
rate: int = 0
roller_materials: Sequence[bascenev1.Material] = ()
rotate: float = 0.0
run: float = 0.0

Available on spaz node.

scale: float | Sequence[float] = 0.0
shadow_offset: Sequence[float] = (0.0, 0.0)
shadow_ortho: bool = False
shadow_range: Sequence[float] = (0, 0, 0, 0)
shattered: int = 0

Available on spaz node.

size: Sequence[float] = (0.0, 0.0, 0.0)
slow_motion: bool = False
source_player: bascenev1.Player | None = None
stick_to_owner: bool = False
text: babase.Lstr | str = ''
texture: bascenev1.Texture | None = None
time: int = 0
time1: int = 0
time2: int = 0
timemax: int = 0
times: Sequence[int] = (1, 2, 3, 4, 5)
tint: Sequence[float] = (1.0, 1.0, 1.0)
tint2_color: Sequence[float] = (0.0, 0.0, 0.0)
tint_color: Sequence[float] = (0.0, 0.0, 0.0)
tint_texture: bascenev1.Texture | None = None
use_fixed_vr_overlay: bool = False
values: Sequence[float] = (1.0, 2.0, 3.0, 4.0)
velocity: Sequence[float] = (0.0, 0.0, 0.0)
vignette_inner: Sequence[float] = (0.0, 0.0)
vignette_outer: Sequence[float] = (0.0, 0.0)
vr_camera_offset: Sequence[float] = (0.0, 0.0, 0.0)
vr_depth: float = 0.0
vr_near_clip: float = 0.0
vr_overlay_center: Sequence[float] = (0.0, 0.0, 0.0)
vr_overlay_center_enabled: bool = False
class bascenev1.NodeActor(node: bascenev1.Node)[source]

Bases: Actor

A simple bascenev1.Actor type that wraps a single bascenev1.Node.

This Actor will delete its Node when told to die, and it’s exists() call will return whether the Node still exists or not.

exists() bool[source]

Returns whether the actor is still present in a meaningful way.

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 is_alive() for that).

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 bascenev1.Actor.autoretain()

The default implementation of this method always return True.

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.

handlemessage(msg: Any) Any[source]

General message handling; can be passed any message object.

exception bascenev1.NodeNotFoundError[source]

Bases: NotFoundError

Raised when an expected node does not exist.

exception bascenev1.NotFoundError[source]

Bases: Exception

Raised when a referenced object does not exist.

class bascenev1.OutOfBoundsMessage[source]

Bases: object

A message telling an object that it is out of bounds.

class bascenev1.PickUpMessage(node: bascenev1.Node)[source]

Bases: object

Tells an object that it has picked something up.

node: bascenev1.Node

The bascenev1.Node that is getting picked up.

class bascenev1.PickedUpMessage(node: bascenev1.Node)[source]

Bases: object

Tells an object that it has been picked up by something.

node: bascenev1.Node

The bascenev1.Node doing the picking up.

class bascenev1.Player[source]

Bases: Generic[TeamT]

A player in a specific bascenev1.Activity.

These correspond to bascenev1.SessionPlayer objects, but are associated with a single bascenev1.Activity instance. This allows activities to specify their own custom bascenev1.Player types.

actor: bascenev1.Actor | None

The bascenev1.Actor associated with the player.

assigninput(inputtype: InputType | tuple[InputType, ...], call: Callable) None[source]

Set the python callable to be run for one or more types of input.

character: str
color: Sequence[float]
property customdata: dict

Arbitrary values associated with the player. Though it is encouraged that most player values be properly defined on the bascenev1.Player subclass, it may be useful for player-agnostic objects to store values here. This dict is cleared when the player leaves or expires so objects stored here will be disposed of at the expected time, unlike the Player instance itself which may continue to be referenced after it is no longer part of the game.

exists() bool[source]

Whether the underlying player still exists.

This will return False if the underlying bascenev1.SessionPlayer has left the game or if the bascenev1.Activity this player was associated with has ended. Most functionality will fail on a nonexistent player. Note that you can also use the boolean operator for this same functionality, so a statement such as “if player” will do the right thing both for Player objects and values of None.

expire() None[source]

Called when the Player is expiring (when its Activity does so).

(internal)

get_icon() dict[str, Any][source]

Returns the character’s icon (images, colors, etc contained in a dict)

getname(full: bool = False, icon: bool = True) str[source]

Returns the player’s name. If icon is True, the long version of the name may include an icon.

highlight: Sequence[float]
is_alive() bool[source]

Returns True if the player has a bascenev1.Actor assigned and its is_alive() method return True. False is returned otherwise.

leave() None[source]

Called when the Player leaves a running game.

(internal)

property node: bascenev1.Node

A bascenev1.Node of type ‘player’ associated with this Player.

This node can be used to get a generic player position/etc.

on_expire() None[source]

Can be overridden to handle player expiration.

The player expires when the Activity it is a part of expires. Expired players should no longer run any game logic (which will likely error). They should, however, remove any references to players/teams/games/etc. which could prevent them from being freed.

property position: Vec3

The position of the player, as defined by its bascenev1.Actor.

If the player currently has no actor, raises a babase.ActorNotFoundError.

postinit(sessionplayer: bascenev1.SessionPlayer) None[source]

Wire up a newly created player.

(internal)

resetinput() None[source]

Clears out the player’s assigned input actions.

property sessionplayer: bascenev1.SessionPlayer

Return the bascenev1.SessionPlayer corresponding to this Player.

Throws a bascenev1.SessionPlayerNotFoundError if it does not exist.

property team: TeamT

The bascenev1.Team for this player.

class bascenev1.PlayerDiedMessage(player: bascenev1.Player, was_killed: bool, killerplayer: bascenev1.Player | None, how: DeathType)[source]

Bases: object

A message saying a bascenev1.Player has died.

getkillerplayer(playertype: type[PlayerT]) PlayerT | None[source]

Return the bascenev1.Player responsible for the killing, if any.

Pass the Player type being used by the current game.

getplayer(playertype: type[PlayerT]) PlayerT[source]

Return the bascenev1.Player that died.

The type of player for the current activity should be passed so that the type-checker properly identifies the returned value as one.

how: DeathType

The particular type of death.

killed: bool

If True, the player was killed; If False, they left the game or the round ended.

class bascenev1.PlayerInfo(name: str, character: str)[source]

Bases: object

Holds basic info about a player.

character: str
name: str
exception bascenev1.PlayerNotFoundError[source]

Bases: NotFoundError

Raised when an expected player does not exist.

class bascenev1.PlayerProfilesChangedMessage[source]

Bases: object

Signals player profiles may have changed and should be reloaded.

class bascenev1.PlayerRecord(name: str, name_full: str, sessionplayer: bascenev1.SessionPlayer, stats: bascenev1.Stats)[source]

Bases: object

Stats for an individual player in a bascenev1.Stats object.

This does not necessarily correspond to a bascenev1.Player that is still present (stats may be retained for players that leave mid-game)

associate_with_sessionplayer(sessionplayer: bascenev1.SessionPlayer) None[source]

Associate this entry with a bascenev1.SessionPlayer.

cancel_multi_kill_timer() None[source]

Cancel any multi-kill timer for this player entry.

character: str
get_icon() dict[str, Any][source]

Get the icon for this instance’s player.

get_last_sessionplayer() bascenev1.SessionPlayer[source]

Return the last bascenev1.Player we were associated with.

getactivity() bascenev1.Activity | None[source]

Return the bascenev1.Activity this instance is associated with.

Returns None if the activity no longer exists.

getname(full: bool = False) str[source]

Return the player entry’s name.

property player: bascenev1.SessionPlayer

Return the instance’s associated bascenev1.SessionPlayer.

Raises a bascenev1.SessionPlayerNotFoundError if the player no longer exists.

submit_kill(showpoints: bool = True) None[source]

Submit a kill for this player entry.

property team: bascenev1.SessionTeam

The bascenev1.SessionTeam the last associated player was last on.

This can still return a valid result even if the player is gone. Raises a bascenev1.SessionTeamNotFoundError if the team no longer exists.

class bascenev1.PlayerScoredMessage(score: int)[source]

Bases: object

Informs something that a bascenev1.Player scored.

score: int

The score value.

class bascenev1.Plugin[source]

Bases: object

A plugin to alter app behavior in some way.

Plugins are discoverable by the MetadataSubsystem system and the user can select which ones they want to enable. Enabled plugins are then called at specific times as the app is running in order to modify its behavior in some way.

has_settings_ui() bool[source]

Called to ask if we have settings UI we can show.

on_app_running() None[source]

Called when the app reaches the running state.

on_app_shutdown() None[source]

Called when the app is beginning the shutdown process.

on_app_shutdown_complete() None[source]

Called when the app has completed the shutdown process.

on_app_suspend() None[source]

Called when the app enters the suspended state.

on_app_unsuspend() None[source]

Called when the app exits the suspended state.

show_settings_ui(source_widget: Any | None) None[source]

Called to show our settings UI.

class bascenev1.PowerupAcceptMessage[source]

Bases: object

A message informing a bascenev1.Powerup that it was accepted.

This is generally sent in response to a bascenev1.PowerupMessage to inform the box (or whoever granted it) that it can go away.

class bascenev1.PowerupMessage(poweruptype: str, sourcenode: bascenev1.Node | None = None)[source]

Bases: object

A message telling an object to accept a powerup.

This message is normally received by touching a bascenev1.PowerupBox.

poweruptype: str

The type of powerup to be granted (a string). See bascenev1.Powerup.poweruptype for available type values.

sourcenode: bascenev1.Node | None = None

The node the powerup game from, or None otherwise. If a powerup is accepted, a bascenev1.PowerupAcceptMessage should be sent back to the sourcenode to inform it of the fact. This will generally cause the powerup box to make a sound and disappear or whatnot.

class bascenev1.ScoreConfig(label: str = 'Score', scoretype: bascenev1.ScoreType = ScoreType.POINTS, lower_is_better: bool = False, none_is_winner: bool = False, version: str = '')[source]

Bases: object

Settings for how a game handles scores.

label: str = 'Score'

A label show to the user for scores; ‘Score’, ‘Time Survived’, etc.

lower_is_better: bool = False

Whether lower scores are preferable. Higher scores are by default.

none_is_winner: bool = False

Whether a value of None is considered better than other scores. By default it is not.

scoretype: bascenev1.ScoreType = 'p'

How the score value should be displayed.

version: str = ''

To change high-score lists used by a game without renaming the game, change this. Defaults to an empty string.

class bascenev1.ScoreScreenActivity(settings: dict)[source]

Bases: Activity[EmptyPlayer, EmptyTeam]

A standard score screen that fades in and shows stuff for a while.

After a specified delay, player input is assigned to end the activity.

default_music: MusicType | None = 'Scores'
inherits_tint = True

Set this to true to inherit screen tint/vignette colors from the previous activity (useful to prevent sudden color changes during transitions).

inherits_vr_camera_offset = True

Set this to true to inherit VR camera offsets from the previous activity (useful for preventing sporadic camera movement during transitions).

on_begin() None[source]

Called once the previous activity has finished transitioning out.

At this point the activity’s initial players and teams are filled in and it should begin its actual game logic.

on_player_join(player: EmptyPlayer) None[source]

Called when a player joins the activity.

(including the initial set of players)

on_transition_in() None[source]

Called when the activity is first becoming visible.

Upon this call, the activity should fade in backgrounds, start playing music, etc. It does not yet have access to players or teams, however. They remain owned by the previous activity up until on_begin() is called.

transition_time = 0.5

If the activity fades or transitions in, it should set the length of time here so that previous activities will be kept alive for that long (avoiding ‘holes’ in the screen) This value is given in real-time seconds.

use_fixed_vr_overlay = True

In vr mode, this determines whether overlay nodes (text, images, etc) are created at a fixed position in space or one that moves based on the current map. Generally this should be on for games and off for transitions/score-screens/etc. that persist between maps.

class bascenev1.ScoreType(*values)[source]

Bases: Enum

Type of scores.

MILLISECONDS = 'ms'
POINTS = 'p'
SECONDS = 's'
class bascenev1.Session(depsets: Sequence[bascenev1.DependencySet], *, team_names: Sequence[str] | None = None, team_colors: Sequence[Sequence[float]] | None = None, min_players: int = 1, max_players: int = 8, submit_score: bool = True)[source]

Bases: object

Wrangles a series of Activity instances.

Examples of sessions are bascenev1.FreeForAllSession, bascenev1.DualTeamSession, and bascenev1.CoopSession.

A session is responsible for wrangling and transitioning between various activity instances such as mini-games and score-screens, and for maintaining state between them (players, teams, score tallies, etc).

begin_next_activity() None[source]

Called once the previous activity has been totally torn down.

This means we’re ready to begin the next one.

property context: bascenev1.ContextRef

A context-ref pointing at this activity.

customdata: dict

A shared dictionary for objects to use as storage on this session. Ensure that keys here are unique to avoid collisions.

end() None[source]

Initiate an end to the session and a return to the main menu.

Note that this happens asynchronously, allowing the session and its activities to shut down gracefully.

end_activity(activity: bascenev1.Activity, results: Any, delay: float, force: bool) None[source]

Commence shutdown of an activity (if not already occurring).

‘delay’ is the time delay before the activity actually ends (in seconds). Further calls to end the activity will be ignored up until this time, unless ‘force’ is True, in which case the new results will replace the old.

get_custom_menu_entries() list[dict[str, Any]][source]

Subclasses can override this to provide custom menu entries.

The returned value should be a list of dicts, each containing a ‘label’ and ‘call’ entry, with ‘label’ being the text for the entry and ‘call’ being the callable to trigger if the entry is pressed.

getactivity() bascenev1.Activity | None[source]

Return the current foreground activity for this session.

handlemessage(msg: Any) Any[source]

General message handling; can be passed any message object.

lobby: bascenev1.Lobby

The lobby instance where new players go to select a profile/team/etc. before being added to games. Be aware this value may be None if a session does not allow any such selection.

max_players: int

The maximum number of players allowed in the Session.

min_players: int

The minimum number of players who must be present for the Session to proceed past the initial joining screen

on_activity_end(activity: bascenev1.Activity, results: Any) None[source]

Called when the current activity has ended.

The session should look at the results and start another activity.

on_player_leave(sessionplayer: bascenev1.SessionPlayer) None[source]

Called when a previously-accepted bascenev1.SessionPlayer leaves.

on_player_request(player: bascenev1.SessionPlayer) bool[source]

Called when a new player wants to join the session.

This should return True or False to accept/reject.

on_team_join(team: bascenev1.SessionTeam) None[source]

Called when a new team joins the session.

on_team_leave(team: bascenev1.SessionTeam) None[source]

Called when a team is leaving the session.

property sessionglobalsnode: bascenev1.Node

The sessionglobals node for the session.

sessionplayers: list[bascenev1.SessionPlayer]

All players in the session. Note that most things should use the list of Player instances found in the Activity; not this. Some players, such as those who have not yet selected a character, will only be found on this list.

sessionteams: list[bascenev1.SessionTeam]

All the teams in the session. Most things will operate on the list of Team instances found in an Activity; not this.

setactivity(activity: bascenev1.Activity) None[source]

Assign a new current activity for the session.

Note that this will not change the current context to the new activity’s. Code must be run in the new activity’s methods (on_transition_in(), etc) to get it. (so you can’t do session.setactivity(foo) and then bascenev1.newnode() to add a node to foo).

should_allow_mid_activity_joins(activity: bascenev1.Activity) bool[source]

Ask ourself if we should allow joins during an Activity.

Note that for a join to be allowed, both the session and activity have to be ok with it (via this function and the bascenev1.Activity.allow_mid_activity_joins property.

use_team_colors: bool = True

Whether players on a team should all adopt the colors of that team instead of their own profile colors. This only applies if use_teams is enabled.

use_teams: bool = False

Whether this session groups players into an explicit set of teams. If this is off, a unique team is generated for each player that joins.

exception bascenev1.SessionNotFoundError[source]

Bases: NotFoundError

Raised when an expected session does not exist.

class bascenev1.SessionPlayer[source]

Bases: object

A reference to a player in a Session.

These are created and managed internally and provided to your Session/Activity instances. Be aware that, like Node objects, SessionPlayer objects are effectively ‘weak’ references under-the-hood; a player can leave the game at any point. For this reason, you should make judicious use of the bascenev1.SessionPlayer.exists() method (or boolean operator) to ensure that a SessionPlayer is still present if retaining references to one for any length of time.

activityplayer: bascenev1.Player | None

The current game-specific instance for this player.

assigninput(type: bascenev1.InputType | tuple[bascenev1.InputType, ...], call: Callable) None[source]

Set the python callable to be run for one or more types of input.

character: str

The character this player has selected in their profile.

color: Sequence[float]

The base color for this player. In team games this will match the team’s color.

exists() bool[source]

Return whether the underlying player is still in the game.

get_icon() dict[str, Any][source]

Return the character’s icon (images, colors, etc contained in a dict.

get_v1_account_id() str[source]

Return the V1 account id this player is signed in under, if there is one and it can be determined with relative certainty. Returns None otherwise. Note that this may require an active internet connection (especially for network-connected players) and may return None for a short while after a player initially joins (while verification occurs).

getname(full: bool = False, icon: bool = True) str[source]

Returns the player’s name. If icon is True, the long version of the name may include an icon.

highlight: Sequence[float]

A secondary color for this player. This is used for minor highlights and accents to allow a player to stand apart from his teammates who may all share the same team (primary) color.

id: int

The unique numeric id of the player.

Note that you can also use the boolean operator for this same functionality, so a statement such as if player: will do the right thing both for SessionPlayer objects as well as values of None.

in_game: bool

This bool value will be True once the player has completed any lobby character/team selection.

inputdevice: bascenev1.InputDevice

The input device associated with the player.

remove_from_game() None[source]

Removes the player from the game.

resetinput() None[source]

Clears out the player’s assigned input actions.

sessionteam: bascenev1.SessionTeam

The session-team this session-player is on. If the player is still in its lobby selecting a team/etc. then a SessionTeamNotFoundError will be raised.

setdata(team: bascenev1.SessionTeam, character: str, color: Sequence[float], highlight: Sequence[float]) None[source]

(internal)

setname(name: str, full_name: str | None = None, real: bool = True) None[source]

Set the player’s name to the provided string. A number will automatically be appended if the name is not unique from other players.

class bascenev1.SessionTeam(team_id: int = 0, name: Lstr | str = '', color: Sequence[float] = (1.0, 1.0, 1.0))[source]

Bases: object

A team of one or more SessionPlayer.

Note that a player will always have a team. in some cases, such as free-for-all Sessions, each team consists of just one player.

color: tuple[float, ...]

The team’s color.

customdata: dict

A dict for use by the current Session for storing data associated with this team. Unlike customdata, this persists for the duration of the session.

id: int

The unique numeric id of the team.

name: babase.Lstr | str

The team’s name.

players: list[bascenev1.SessionPlayer]

The list of players on the team.

class bascenev1.Setting(name: str, default: Any)[source]

Bases: object

Defines a user-controllable setting for a game or other entity.

default: Any
name: str
class bascenev1.ShouldShatterMessage[source]

Bases: object

Tells an object that it should shatter.

class bascenev1.Sound[source]

Bases: object

A reference to a sound.

Use bascenev1.getsound() to instantiate one.

play(volume: float = 1.0, position: Sequence[float] | None = None, host_only: bool = False) None[source]

Play the sound a single time.

If position is not provided, the sound will be at a constant volume everywhere. Position should be a float tuple of size 3.

class bascenev1.StandLocation(position: Vec3, angle: float | None = None)[source]

Bases: object

Describes a point in space and an angle to face.

angle: float | None = None
position: Vec3
class bascenev1.StandMessage(position: Sequence[float] = (0.0, 0.0, 0.0), angle: float = 0.0)[source]

Bases: object

A message telling an object to move to a position in space.

Used when teleporting players to home base, etc.

angle: float = 0.0

The angle to face (in degrees)

position: Sequence[float] = (0.0, 0.0, 0.0)

Where to move to.

class bascenev1.Stats[source]

Bases: object

Manages scores and statistics for a bascenev1.Session.

get_records() dict[str, bascenev1.PlayerRecord][source]

Get PlayerRecord corresponding to still-existing players.

getactivity() bascenev1.Activity | None[source]

Get the activity associated with this instance.

May return None.

player_scored(player: bascenev1.Player, base_points: int = 1, *, target: Sequence[float] | None = None, kill: bool = False, victim_player: bascenev1.Player | None = None, scale: float = 1.0, color: Sequence[float] | None = None, title: str | babase.Lstr | None = None, screenmessage: bool = True, display: bool = True, importance: int = 1, showpoints: bool = True, big_message: bool = False) int[source]

Register a score for the player.

Return value is actual score with multipliers and such factored in.

player_was_killed(player: bascenev1.Player, killed: bool = False, killer: bascenev1.Player | None = None) None[source]

Should be called when a player is killed.

register_sessionplayer(player: bascenev1.SessionPlayer) None[source]

Register a bascenev1.SessionPlayer with this score-set.

reset() None[source]

Reset the stats instance completely.

reset_accum() None[source]

Reset per-sound sub-scores.

setactivity(activity: bascenev1.Activity | None) None[source]

Set the current activity for this instance.

class bascenev1.Team[source]

Bases: Generic[PlayerT]

A team in a specific Activity.

These correspond to SessionTeam objects, but are created per activity so that the activity can use its own custom team subclass.

color: tuple[float, ...]
property customdata: dict

Arbitrary values associated with the team. Though it is encouraged that most player values be properly defined on the Team subclass, it may be useful for player-agnostic objects to store values here. This dict is cleared when the team leaves or expires so objects stored here will be disposed of at the expected time, unlike the Team instance itself which may continue to be referenced after it is no longer part of the game.

id: int
manual_init(team_id: int, name: Lstr | str, color: tuple[float, ...]) None[source]

Manually init a team for uses such as bots.

name: Lstr | str
on_expire() None[source]

Can be overridden to handle team expiration.

players: list[PlayerT]
property sessionteam: SessionTeam

The SessionTeam corresponding to this team.

Throws a SessionTeamNotFoundError if there is none.

class bascenev1.TeamGameActivity(settings: dict)[source]

Bases: GameActivity[PlayerT, TeamT]

Base class for teams and free-for-all mode games.

(Free-for-all is essentially just a special case where every player has their own team)

end(results: Any = None, announce_winning_team: bool = True, announce_delay: float = 0.1, force: bool = False) None[source]

End the game and announce the single winning team unless ‘announce_winning_team’ is False. (for results without a single most-important winner).

on_begin() None[source]

Called once the previous activity has finished transitioning out.

At this point the activity’s initial players and teams are filled in and it should begin its actual game logic.

on_transition_in() None[source]

Called when the activity is first becoming visible.

Upon this call, the activity should fade in backgrounds, start playing music, etc. It does not yet have access to players or teams, however. They remain owned by the previous activity up until on_begin() is called.

spawn_player_spaz(player: PlayerT, position: Sequence[float] | None = None, angle: float | None = None) PlayerSpaz[source]

Override to spawn and wire up a standard PlayerSpaz for a Player.

If position or angle is not supplied, a default will be chosen based on the Player and their Team.

classmethod supports_session_type(sessiontype: type[bascenev1.Session]) bool[source]

Return whether this game supports the provided session type.

class bascenev1.Texture[source]

Bases: object

A reference to a texture.

Use bascenev1.gettexture() to instantiate one.

class bascenev1.ThawMessage[source]

Bases: object

Tells an object to stop being frozen.

class bascenev1.Timer(time: float, call: Callable[[], Any], repeat: bool = False)[source]

Bases: object

Timers are used to run code at later points in time.

This class encapsulates a scene-time timer in the current bascenev1.Context. The underlying timer will be destroyed when either this object is no longer referenced or when its Context (Activity, etc.) dies. If you do not want to worry about keeping a reference to your timer around, you should use the bs.timer() function instead.

Scene time maps to local simulation time in bascenev1.Activity or bascenev1.Session Contexts. This means that it may progress slower in slow-motion play modes, stop when the game is paused, etc.

Parameters:
  • time – Length of time (in seconds by default) that the timer will wait before firing. Note that the actual delay experienced may vary depending on the timetype. (see below)

  • call – A callable Python object. Note that the timer will retain a strong reference to the callable for as long as it exists, so you may want to look into concepts such as WeakCall if that is not desired.

  • repeat – If True, the timer will fire repeatedly, with each successive firing having the same delay as the first.

Example: Use a Timer object to print repeatedly for a few seconds:

import bascenev1 as bs

def say_it():
    bs.screenmessage('BADGER!')

def stop_saying_it():
    global g_timer
    g_timer = None
    bs.screenmessage('MUSHROOM MUSHROOM!')

# Create our timer; it will run as long as we hold its ref.
g_timer = bs.Timer(0.3, say_it, repeat=True)

# Now fire off a one-shot timer to kill the ref.
bs.timer(3.89, stop_saying_it)
class bascenev1.UIScale(*values)[source]

Bases: Enum

The overall scale the UI is being rendered for. Note that this is independent of pixel resolution. For example, a phone and a desktop PC might render the game at similar pixel resolutions but the size they display content at will vary significantly.

‘large’ is used for devices such as desktop PCs where fine details can

be clearly seen. UI elements are generally smaller on the screen and more content can be seen at once.

‘medium’ is used for devices such as tablets, TVs, or VR headsets.

This mode strikes a balance between clean readability and amount of content visible.

‘small’ is used primarily for phones or other small devices where

content needs to be presented as large and clear in order to remain readable from an average distance.

LARGE = 2
MEDIUM = 1
SMALL = 0
class bascenev1.Vec3[source]
class bascenev1.Vec3(value: float)
class bascenev1.Vec3(values: Sequence[float])
class bascenev1.Vec3(x: float, y: float, z: float)

Bases: Sequence[float]

A vector of 3 floats.

These can be created the following ways (checked in this order):
  • With no args, all values are set to 0.

  • With a single numeric arg, all values are set to that value.

  • With a three-member sequence arg, sequence values are copied.

  • Otherwise assumes individual x/y/z args (positional or keywords).

cross(other: Vec3) Vec3[source]

Returns the cross product of this vector and another.

dot(other: Vec3) float[source]

Returns the dot product of this vector and another.

length() float[source]

Returns the length of the vector.

normalized() Vec3[source]

Returns a normalized version of the vector.

x: float

The vector’s X component.

y: float

The vector’s Y component.

z: float

The vector’s Z component.

class bascenev1.WeakCall(*args: Any, **keywds: Any)

Bases: object

Wrap a callable and arguments into a single callable object.

When passed a bound method as the callable, the instance portion of it is weak-referenced, meaning the underlying instance is free to die if all other references to it go away. Should this occur, calling the weak-call is simply a no-op.

Think of this as a handy way to tell an object to do something at some point in the future if it happens to still exist.

EXAMPLE A: This code will create a FooClass instance and call its bar() method 5 seconds later; it will be kept alive even though we overwrite its variable with None because the bound method we pass as a timer callback (foo.bar) strong-references it:

foo = FooClass()
babase.apptimer(5.0, foo.bar)
foo = None

EXAMPLE B: This code will not keep our object alive; it will die when we overwrite it with None and the timer will be a no-op when it fires:

foo = FooClass()
babase.apptimer(5.0, ba.WeakCall(foo.bar))
foo = None

EXAMPLE C: Wrap a method call with some positional and keyword args:

myweakcall = babase.WeakCall(self.dostuff, argval1,
                             namedarg=argval2)

# Now we have a single callable to run that whole mess.
# The same as calling myobj.dostuff(argval1, namedarg=argval2)
# (provided my_obj still exists; this will do nothing otherwise).
myweakcall()

Note: additional args and keywords you provide to the weak-call constructor are stored as regular strong-references; you’ll need to wrap them in weakrefs manually if desired.

class bascenev1.WinnerGroup(score: int | None, teams: list[bascenev1.SessionTeam])[source]

Bases: object

Winning team or teams as calculated by a GameResults.

score: int | None
teams: list[bascenev1.SessionTeam]
bascenev1.animate(node: bascenev1.Node, attr: str, keys: dict[float, float], loop: bool = False, offset: float = 0) bascenev1.Node[source]

Animate values on a target bascenev1.Node.

Creates an ‘animcurve’ node with the provided values and time as an input, connect it to the provided attribute, and set it to die with the target. Key values are provided as time:value dictionary pairs. Time values are relative to the current time. By default, times are specified in seconds, but timeformat can also be set to MILLISECONDS to recreate the old behavior (prior to ba 1.5) of taking milliseconds. Returns the animcurve node.

bascenev1.animate_array(node: bascenev1.Node, attr: str, size: int, keys: dict[float, Sequence[float]], *, loop: bool = False, offset: float = 0) None[source]

Animate an array of values on a target bascenev1.Node.

Like bs.animate, but operates on array attributes.

bascenev1.apptime() babase.AppTime[source]

Return the current app-time in seconds.

App-time is a monotonic time value; it starts at 0.0 when the app launches and will never jump by large amounts or go backwards, even if the system time changes. Its progression will pause when the app is in a suspended state.

Note that the AppTime returned here is simply float; it just has a unique type in the type-checker’s eyes to help prevent it from being accidentally used with time functionality expecting other time types.

bascenev1.apptimer(time: float, call: Callable[[], Any]) None[source]

Schedule a callable object to run based on app-time.

This function creates a one-off timer which cannot be canceled or modified once created. If you require the ability to do so, or need a repeating timer, use the babase.AppTimer class instead.

Parameters:
  • time – Length of time in seconds that the timer will wait before firing.

  • call – A callable Python object. Note that the timer will retain a strong reference to the callable for as long as the timer exists, so you may want to look into concepts such as WeakCall if that is not desired.

Example: Print some stuff through time:

import babase

babase.screenmessage('hello from now!')
babase.apptimer(1.0, babase.Call(babase.screenmessage,
                'hello from the future!'))
babase.apptimer(2.0, babase.Call(babase.screenmessage,
                'hello from the future 2!'))
bascenev1.basetime() bascenev1.BaseTime[source]

Return the base-time in seconds for the current scene-v1 context.

Base-time is a time value that progresses at a constant rate for a scene, even when the scene is sped up, slowed down, or paused. It may, however, speed up or slow down due to replay speed adjustments or may slow down if the cpu is overloaded. Note that the value returned here is simply a float; it just has a unique type in the type-checker’s eyes to help prevent it from being accidentally used with time functionality expecting other time types.

bascenev1.basetimer(time: float, call: Callable[[], Any], repeat: bool = False) None[source]

Schedule a call to run at a later point in scene base-time. Base-time is a value that progresses at a constant rate for a scene, even when the scene is sped up, slowed down, or paused. It may, however, speed up or slow down due to replay speed adjustments or may slow down if the cpu is overloaded.

This function adds a timer to the current scene context. This timer cannot be canceled or modified once created. If you require the ability to do so, use the bascenev1.BaseTimer class instead.

Parameters:
  • time – Length of time in seconds that the timer will wait before firing.

  • call – A callable Python object. Remember that the timer will retain a strong reference to the callable for the duration of the timer, so you may want to look into concepts such as WeakCall if that is not desired.

  • repeat – If True, the timer will fire repeatedly, with each successive firing having the same delay as the first.

Example: Print some stuff through time:

import bascenev1 as bs

bs.screenmessage('hello from now!')
bs.basetimer(1.0, bs.Call(bs.screenmessage,
             'hello from the future!'))
bs.basetimer(2.0, bs.Call(bs.screenmessage,
             'hello from the future 2!'))
bascenev1.broadcastmessage(message: str | babase.Lstr, color: Sequence[float] | None = None, top: bool = False, image: dict[str, Any] | None = None, log: bool = False, clients: Sequence[int] | None = None, transient: bool = False) None[source]

Broadcast a screen-message to clients in the current session.

If ‘top’ is True, the message will go to the top message area. For ‘top’ messages, ‘image’ must be a dict containing ‘texture’ and ‘tint_texture’ textures and ‘tint_color’ and ‘tint2_color’ colors. This defines an icon to display alongside the message. If ‘log’ is True, the message will also be submitted to the log. ‘clients’ can be a list of client-ids the message should be sent to, or None to specify that everyone should receive it. If ‘transient’ is True, the message will not be included in the game-stream and thus will not show up when viewing replays. Currently the ‘clients’ option only works for transient messages.

bascenev1.cameraflash(duration: float = 999.0) None[source]

Create a strobing camera flash effect.

(as seen when a team wins a game) Duration is in seconds.

bascenev1.camerashake(intensity: float = 1.0) None[source]

Shake the camera.

Note that some cameras and/or platforms (such as VR) may not display camera-shake, so do not rely on this always being visible to the player as a gameplay cue.

bascenev1.capture_gamepad_input(call: Callable[[dict], None]) None[source]

(internal)

Add a callable to be called for subsequent gamepad events. The method is passed a dict containing info about the event.

bascenev1.capture_keyboard_input(call: Callable[[dict], None]) None[source]

(internal)

Add a callable to be called for subsequent keyboard-game-pad events. The method is passed a dict containing info about the event.

bascenev1.chatmessage(message: str | babase.Lstr, clients: Sequence[int] | None = None, sender_override: str | None = None) None[source]

(internal)

bascenev1.client_info_query_response(token: str, response: Any) None[source]

(internal)

bascenev1.connect_to_party(address: str, port: int | None = None, print_progress: bool = True) None[source]

(internal)

bascenev1.disconnect_client(client_id: int, ban_time: int = 300) bool[source]

(internal)

bascenev1.disconnect_from_host() None[source]

(internal)

bascenev1.displaytime() babase.DisplayTime[source]

Return the current display-time in seconds.

Display-time is a time value intended to be used for animation and other visual purposes. It will generally increment by a consistent amount each frame. It will pass at an overall similar rate to app-time, but trades accuracy for smoothness.

Note that the value returned here is simply a float; it just has a unique type in the type-checker’s eyes to help prevent it from being accidentally used with time functionality expecting other time types.

bascenev1.displaytimer(time: float, call: Callable[[], Any]) None[source]

Schedule a callable object to run based on display-time.

This function creates a one-off timer which cannot be canceled or modified once created. If you require the ability to do so, or need a repeating timer, use the DisplayTimer class instead.

Display-time is a time value intended to be used for animation and other visual purposes. It will generally increment by a consistent amount each frame. It will pass at an overall similar rate to app-time, but trades accuracy for smoothness.

Parameters:
  • time – Length of time in seconds that the timer will wait before firing.

  • call – A callable Python object. Note that the timer will retain a strong reference to the callable for as long as the timer exists, so you may want to look into concepts such as WeakCall if that is not desired.

Example: Print some stuff through time:

babase.screenmessage('hello from now!')
babase.displaytimer(1.0, babase.Call(babase.screenmessage,
                    'hello from the future!'))
babase.displaytimer(2.0, babase.Call(babase.screenmessage,
                    'hello from the future 2!'))
bascenev1.emitfx(position: Sequence[float], velocity: Sequence[float] | None = None, count: int = 10, scale: float = 1.0, spread: float = 1.0, chunk_type: str = 'rock', emit_type: str = 'chunks', tendril_type: str = 'smoke') None[source]

Emit particles, smoke, etc. into the fx sim layer.

The fx sim layer is a secondary dynamics simulation that runs in the background and just looks pretty; it does not affect gameplay. Note that the actual amount emitted may vary depending on graphics settings, exiting element counts, or other factors.

bascenev1.end_host_scanning() None[source]

(internal)

bascenev1.existing(obj: ExistableT | None) ExistableT | None[source]

Convert invalid references to None for any babase.Existable object.

To best support type checking, it is important that invalid references not be passed around and instead get converted to values of None. That way the type checker can properly flag attempts to pass possibly-dead objects (FooType | None) into functions expecting only live ones (FooType), etc. This call can be used on any ‘existable’ object (one with an exists() method) and will convert it to a None value if it does not exist.

For more info, see notes on ‘existables’ here: https://ballistica.net/wiki/Coding-Style-Guide

bascenev1.filter_playlist(playlist: PlaylistType, sessiontype: type[Session], *, add_resolved_type: bool = False, remove_unowned: bool = True, mark_unowned: bool = False, name: str = '?') PlaylistType[source]

Return a filtered version of a playlist.

Strips out or replaces invalid or unowned game types, makes sure all settings are present, and adds in a ‘resolved_type’ which is the actual type.

bascenev1.get_chat_messages() list[str][source]

(internal)

bascenev1.get_connection_to_host_info() dict[source]

(internal)

bascenev1.get_connection_to_host_info_2() bascenev1.HostInfo | None[source]

Return info about the host we are currently connected to.

bascenev1.get_default_free_for_all_playlist() list[dict[str, Any]][source]

Return a default playlist for free-for-all mode.

bascenev1.get_default_powerup_distribution() Sequence[tuple[str, int]][source]

Standard set of powerups.

bascenev1.get_default_teams_playlist() list[dict[str, Any]][source]

Return a default playlist for teams mode.

bascenev1.get_filtered_map_name(name: str) str[source]

Filter a map name to account for name changes, etc.

This can be used to support old playlists, etc.

bascenev1.get_foreground_host_activity() bascenev1.Activity | None[source]

(internal)

Returns the bascenev1.Activity currently in the foreground, or None if there is none.

bascenev1.get_foreground_host_session() bascenev1.Session | None[source]

(internal)

Return the bascenev1.Session currently being displayed, or None if there is none.

bascenev1.get_game_port() int[source]

(internal)

Return the port ballistica is hosting on.

bascenev1.get_game_roster() list[dict[str, Any]][source]

(internal)

bascenev1.get_local_active_input_devices_count() int[source]

(internal)

bascenev1.get_map_class(name: str) type[Map][source]

Return a map type given a name.

bascenev1.get_map_display_string(name: str) Lstr[source]

Return a babase.Lstr for displaying a given map’s name.

bascenev1.get_player_colors() list[tuple[float, float, float]][source]

Return user-selectable player colors.

bascenev1.get_player_profile_colors(profilename: str | None, profiles: dict[str, dict[str, Any]] | None = None) tuple[tuple[float, float, float], tuple[float, float, float]][source]

Given a profile, return colors for them.

bascenev1.get_player_profile_icon(profilename: str) str[source]

Given a profile name, returns an icon string for it.

(non-account profiles only)

bascenev1.get_public_party_enabled() bool[source]

(internal)

bascenev1.get_public_party_max_size() int[source]

(internal)

bascenev1.get_random_names() list[source]

(internal)

Returns the random names used by the game.

bascenev1.get_replay_speed_exponent() int[source]

(internal)

Returns current replay speed value. Actual displayed speed is pow(2,speed).

bascenev1.get_trophy_string(trophy_id: str) str[source]

Given a trophy id, returns a string to visualize it.

bascenev1.get_ui_input_device() bascenev1.InputDevice | None[source]

(internal)

Returns the input-device that currently owns the user interface, or None if there is none.

bascenev1.getactivity(doraise: bool = True) bascenev1.Activity | None[source]

Return the current bascenev1.Activity instance.

Note that this is based on context_ref; thus code run in a timer generated in Activity ‘foo’ will properly return ‘foo’ here, even if another Activity has since been created or is transitioning in. If there is no current Activity, raises a babase.ActivityNotFoundError. If doraise is False, None will be returned instead in that case.

bascenev1.getcollision() Collision[source]

Return the in-progress collision.

bascenev1.getcollisionmesh(name: str) bascenev1.CollisionMesh[source]

Return a collision-mesh, loading it if necessary.

Collision-meshes are used in physics calculations for such things as terrain.

Note that this function returns immediately even if the asset has yet to be loaded. Loading will happen in the background or on-demand. To avoid hitches, try to instantiate asset objects a bit earlier than they are actually needed, giving them time to load gracefully in the background.

bascenev1.getdata(name: str) bascenev1.Data[source]

Return a data, loading it if necessary.

Note that this function returns immediately even if the asset has yet to be loaded. Loading will happen in the background or on-demand. To avoid hitches, try to instantiate asset objects a bit earlier than they are actually needed, giving them time to load gracefully in the background.

bascenev1.getinputdevice(name: str, unique_id: str, doraise: bool = True) Any[source]

(internal)

Given a type name and a unique identifier, returns an InputDevice. Throws an Exception if the input-device is not found, or returns None if ‘doraise’ is False.

bascenev1.getmesh(name: str) bascenev1.Mesh[source]

Return a mesh, loading it if necessary.

Note that this function returns immediately even if the asset has yet to be loaded. Loading will happen in the background or on-demand. To avoid hitches, try to instantiate asset objects a bit earlier than they are actually needed, giving them time to load gracefully in the background.

bascenev1.getnodes() list[source]

Return all nodes in the current scene context.

bascenev1.getsession(doraise: bool = True) bascenev1.Session | None[source]

Return the session associated with the current context. If there is none, a SessionNotFoundError is raised (unless doraise is False, in which case None is returned instead).

bascenev1.getsound(name: str) bascenev1.Sound[source]

Return a sound, loading it if necessary.

Note that this function returns immediately even if the asset has yet to be loaded. Loading will happen in the background or on-demand. To avoid hitches, try to instantiate asset objects a bit earlier than they are actually needed, giving them time to load gracefully in the background.

bascenev1.gettexture(name: str) bascenev1.Texture[source]

Return a texture, loading it if necessary.

Note that this function returns immediately even if the asset has yet to be loaded. Loading will happen in the background or on-demand. To avoid hitches, try to instantiate asset objects a bit earlier than they are actually needed, giving them time to load gracefully in the background.

bascenev1.init_campaigns() None[source]

Fill out initial default Campaigns.

bascenev1.is_in_replay() bool[source]

(internal)

bascenev1.is_replay_paused() bool[source]

(internal)

Returns if Replay is paused or not.

bascenev1.ls_input_devices() None[source]

Print debugging info about game objects.

This call only functions in debug builds of the game. It prints various info about the current object count, etc.

bascenev1.ls_objects() None[source]

Log debugging info about C++ level objects.

This call only functions in debug builds of the game. It prints various info about the current object count, etc.

bascenev1.new_host_session(sessiontype: type[bascenev1.Session], benchmark_type: str | None = None) None[source]

(internal)

bascenev1.new_replay_session(file_name: str) None[source]

(internal)

bascenev1.newactivity(activity_type: type[bascenev1.Activity], settings: dict | None = None) bascenev1.Activity[source]

Instantiates a bascenev1.Activity given a type object.

Activities require special setup and thus cannot be directly instantiated; you must go through this function.

bascenev1.newnode(type: str, owner: bascenev1.Node | None = None, attrs: dict | None = None, name: str | None = None, delegate: Any = None) bascenev1.Node[source]

Add a node of the given type to the game.

If a dict is provided for ‘attributes’, the node’s initial attributes will be set based on them.

‘name’, if provided, will be stored with the node purely for debugging purposes. If no name is provided, an automatic one will be generated such as ‘terrain@foo.py:30’.

If ‘delegate’ is provided, Python messages sent to the node will go to that object’s handlemessage() method. Note that the delegate is stored as a weak-ref, so the node itself will not keep the object alive.

if ‘owner’ is provided, the node will be automatically killed when that object dies. ‘owner’ can be another node or a bascenev1.Actor

bascenev1.normalized_color(color: Sequence[float]) tuple[float, ...][source]

Scale a color so its largest value is 1.0; useful for coloring lights.

bascenev1.pause_replay() None[source]

(internal)

Pauses replay.

bascenev1.print_live_object_warnings(when: Any, ignore_session: bascenev1.Session | None = None, ignore_activity: bascenev1.Activity | None = None) None[source]

Print warnings for remaining objects in the current context.

IMPORTANT - don’t call this in production; usage of gc.get_objects() can bork Python. See notes at top of efro.debug module.

bascenev1.printnodes() None[source]

Print various info about existing nodes; useful for debugging.

bascenev1.protocol_version() int[source]

(internal)

bascenev1.pushcall(call: Callable, from_other_thread: bool = False, suppress_other_thread_warning: bool = False, other_thread_use_fg_context: bool = False, raw: bool = False) None[source]

Push a call to the logic-thread’s event loop.

This function expects to be called from the logic thread, and will automatically save and restore the context to behave seamlessly.

To push a call from outside of the logic thread, pass from_other_thread=True. In that case the call will run with no context set. To instead run in whichever context is currently active on the logic thread, pass other_thread_use_fg_context=True. Passing raw=True will skip thread checks and context saves/restores altogether.

bascenev1.register_map(maptype: type[Map]) None[source]

Register a map class with the game.

bascenev1.release_gamepad_input() None[source]

(internal)

Resumes normal gamepad event processing.

bascenev1.release_keyboard_input() None[source]

(internal)

Resumes normal keyboard event processing.

bascenev1.reset_random_player_names() None[source]

(internal)

bascenev1.resume_replay() None[source]

(internal)

Resumes replay.

bascenev1.safecolor(color: Sequence[float], target_intensity: float = 0.6) tuple[float, ...][source]

Given a color tuple, return a color safe to display as text.

Accepts tuples of length 3 or 4. This will slightly brighten very dark colors, etc.

bascenev1.screenmessage(message: str | babase.Lstr, color: Sequence[float] | None = None, log: bool = False) None[source]

Print a message to the local client’s screen in a given color.

Note that this function is purely for local display. To broadcast screen-messages during gameplay, look for methods such as bascenev1.broadcastmessage().

bascenev1.seek_replay(delta: float) None[source]

(internal)

Rewind or fast-forward replay.

bascenev1.set_admins(admins: list[str]) None[source]

(internal)

bascenev1.set_authenticate_clients(enable: bool) None[source]

(internal)

bascenev1.set_debug_speed_exponent(speed: int) None[source]

(internal)

Sets the debug speed scale for the game. Actual speed is pow(2,speed).

bascenev1.set_enable_default_kick_voting(enable: bool) None[source]

(internal)

bascenev1.set_internal_music(music: babase.SimpleSound | None, volume: float = 1.0, loop: bool = True) None[source]

(internal).

bascenev1.set_map_bounds(bounds: tuple[float, float, float, float, float, float]) None[source]

(internal)

Set map bounds. Generally nodes that go outside of this box are killed.

bascenev1.set_master_server_source(source: int) None[source]

(internal)

bascenev1.set_max_players_override(max_players: int | None) None[source]

Set the override for how many players can join a session

bascenev1.set_player_rejoin_cooldown(cooldown: float) None[source]

Set the cooldown for individual players rejoining after leaving.

bascenev1.set_public_party_enabled(enabled: bool) None[source]

(internal)

bascenev1.set_public_party_max_size(max_size: int) None[source]

(internal)

bascenev1.set_public_party_name(name: str) None[source]

(internal)

bascenev1.set_public_party_public_address_ipv4(address: str | None) None[source]

(internal)

bascenev1.set_public_party_public_address_ipv6(address: str | None) None[source]

(internal)

bascenev1.set_public_party_queue_enabled(max_size: bool) None[source]

(internal)

bascenev1.set_public_party_stats_url(url: str | None) None[source]

(internal)

bascenev1.set_replay_speed_exponent(speed: int) None[source]

(internal)

Set replay speed. Actual displayed speed is pow(2, speed).

bascenev1.set_touchscreen_editing(editing: bool) None[source]

(internal)

bascenev1.setmusic(musictype: MusicType | None, continuous: bool = False) None[source]

Set the app to play (or stop playing) a certain type of music.

This function will handle loading and playing sound assets as necessary, and also supports custom user soundtracks on specific platforms so the user can override particular game music with their own.

Pass None to stop music.

if continuous is True and musictype is the same as what is already playing, the playing track will not be restarted.

bascenev1.show_damage_count(damage: str, position: Sequence[float], direction: Sequence[float]) None[source]

Pop up a damage count at a position in space.

bascenev1.storagename(suffix: str | None = None) str[source]

Generate a unique name for storing class data in shared places.

This consists of a leading underscore, the module path at the call site with dots replaced by underscores, the containing class’s qualified name, and the provided suffix. When storing data in public places such as ‘customdata’ dicts, this minimizes the chance of collisions with other similarly named classes.

Note that this will function even if called in the class definition.

Example: Generate a unique name for storage purposes:

class MyThingie:

    # This will give something like
    # '_mymodule_submodule_mythingie_data'.
    _STORENAME = babase.storagename('data')

    # Use that name to store some data in the Activity we were
    # passed.
    def __init__(self, activity):
        activity.customdata[self._STORENAME] = {}
bascenev1.time() bascenev1.Time[source]

Return the current scene time in seconds.

Scene time maps to local simulation time in bascenev1.Activity or bascenev1.Session Contexts. This means that it may progress slower in slow-motion play modes, stop when the game is paused, etc.

Note that the value returned here is simply a float; it just has a unique type in the type-checker’s eyes to help prevent it from being accidentally used with time functionality expecting other time types.

bascenev1.timer(time: float, call: Callable[[], Any], repeat: bool = False) None[source]

Schedule a call to run at a later point in time.

This function adds a scene-time timer to the current bascenev1.ContextRef. This timer cannot be canceled or modified once created. If you require the ability to do so, use the bascenev1.Timer class instead.

Scene time maps to local simulation time in bascenev1.Activity or bascenev1.Session Contexts. This means that it may progress slower in slow-motion play modes, stop when the game is paused, etc.

Parameters:
  • time – Length of scene time in seconds that the timer will wait before firing.

  • call – A callable Python object. Note that the timer will retain a strong reference to the callable for as long as it exists, so you may want to look into concepts such as bascenev1.WeakCall if that is not desired.

  • repeat – If True, the timer will fire repeatedly, with each successive firing having the same delay as the first.

Examples

Print some stuff through time:

import bascenev1 as bs
bs.screenmessage('hello from now!')
bs.timer(1.0, bs.Call(bs.screenmessage, 'hello from the future!'))
bs.timer(2.0, bs.Call(bs.screenmessage, 'hello from the future 2!'))
bascenev1.timestring(timeval: float | int, centi: bool = True) babase.Lstr[source]

Generate a localized string for displaying a time value.

Given a time value, returns a localized string with: (hours if > 0 ) : minutes : seconds : (centiseconds if centi=True).

Warning

the underlying localized-string value is somewhat large, so don’t use this to rapidly update text values for an in-game timer or you may consume significant network bandwidth. For that sort of thing you should use things like ‘timedisplay’ nodes and attribute connections.