bombsquad-plugin-manager/plugins/utilities/auto_stunt.py

564 lines
20 KiB
Python
Raw Normal View History

2025-01-22 19:24:00 +05:30
# ba_meta require api 9
2022-11-26 12:33:00 +00:00
# AutoStunt mod by - Mr.Smoothy x Rikko
2022-11-26 18:01:28 +05:30
# https://discord.gg/ucyaesh
# https://bombsquad-community.web.app/home
2022-11-26 18:01:28 +05:30
# Dont modify redistribute this plugin , if want to use features of this plugin in your mod write logic in seprate file
# and import this as module.
# If want to contribute in this original module, raise PR on github https://github.com/bombsquad-community/plugin-manager
import babase
import bauiv1 as bui
import bascenev1 as bs
import _babase
import bascenev1lib
from bascenev1lib.actor.image import Image
from bascenev1lib.actor import spaz
from bascenev1lib.gameutils import SharedObjects
from bascenev1lib.actor.powerupbox import PowerupBoxFactory
from bascenev1lib.actor.spazfactory import SpazFactory
from bascenev1lib.game.elimination import EliminationGame
2022-11-26 18:01:28 +05:30
import math
import json
import os
from typing import Optional
CONTROLS_CENTER = (0, 0)
CONTROLS_SCALE = 1
BASE_STUNTS_DIRECTORY = os.path.join(_babase.env()["python_directory_user"], "CustomStunts")
2022-11-26 18:01:28 +05:30
PLAYERS_STUNT_INFO = {}
STUNT_CACHE = {}
original_on_begin = bs._activity.Activity.on_begin
original_chatmessage = bs.chatmessage
2022-11-26 18:01:28 +05:30
class ControlsUI:
2022-11-26 12:36:30 +00:00
2022-11-26 18:01:28 +05:30
def on_jump_press(activity):
2022-11-26 12:36:30 +00:00
activity._jump_image.node.color = list(
channel * 2 for channel in activity._jump_image.node.color[:3]) + [1]
2022-11-26 18:01:28 +05:30
def on_jump_release(activity):
2022-11-26 12:33:00 +00:00
activity._jump_image.node.color = list(
channel * 0.5 for channel in activity._jump_image.node.color[:3]) + [1]
2022-11-26 18:01:28 +05:30
def on_pickup_press(activity):
2022-11-26 12:33:00 +00:00
activity._pickup_image.node.color = list(
channel * 2 for channel in activity._pickup_image.node.color[:3]) + [1]
2022-11-26 18:01:28 +05:30
def on_pickup_release(activity):
2022-11-26 12:33:00 +00:00
activity._pickup_image.node.color = list(
channel * 0.5 for channel in activity._pickup_image.node.color[:3]) + [1]
2022-11-26 18:01:28 +05:30
def on_punch_press(activity):
2022-11-26 12:33:00 +00:00
activity._punch_image.node.color = list(
channel * 2 for channel in activity._punch_image.node.color[:3]) + [1]
2022-11-26 18:01:28 +05:30
def on_punch_release(activity):
2022-11-26 12:33:00 +00:00
activity._punch_image.node.color = list(
channel * 0.5 for channel in activity._punch_image.node.color[:3]) + [1]
2022-11-26 18:01:28 +05:30
def on_bomb_press(activity):
2022-11-26 12:33:00 +00:00
activity._bomb_image.node.color = list(
channel * 2 for channel in activity._bomb_image.node.color[:3]) + [1]
2022-11-26 18:01:28 +05:30
def on_bomb_release(activity):
2022-11-26 12:33:00 +00:00
activity._bomb_image.node.color = list(
channel * 0.5 for channel in activity._bomb_image.node.color[:3]) + [1]
def on_move_ud(activity, value):
2025-01-22 19:24:00 +05:30
activity.set_stick_image_position(activity.stick_image_position_x, value)
2022-11-26 12:33:00 +00:00
def on_move_lr(activity, value):
2025-01-22 19:24:00 +05:30
activity.set_stick_image_position(value, activity.stick_image_position_y)
2022-11-26 18:01:28 +05:30
def display(activity):
activity._jump_image.node.color = list(activity._jump_image.node.color[:3]) + [1]
activity._pickup_image.node.color = list(activity._pickup_image.node.color[:3]) + [1]
activity._punch_image.node.color = list(activity._punch_image.node.color[:3]) + [1]
activity._bomb_image.node.color = list(activity._bomb_image.node.color[:3]) + [1]
activity._stick_base_image.opacity = 1.0
activity._stick_nub_image.opacity = 1.0
def hide(activity):
activity._jump_image.node.color = list(activity._jump_image.node.color[:3]) + [0]
activity._pickup_image.node.color = list(activity._pickup_image.node.color[:3]) + [0]
activity._punch_image.node.color = list(activity._punch_image.node.color[:3]) + [0]
activity._bomb_image.node.color = list(activity._bomb_image.node.color[:3]) + [0]
activity._stick_base_image.opacity = 0.0
activity._stick_nub_image.opacity = 0.0
CONTROLS_UI_MAP = {
"JUMP_PRESS": ControlsUI.on_jump_press,
"JUMP_RELEASE": ControlsUI.on_jump_release,
"PICKUP_PRESS": ControlsUI.on_pickup_press,
"PICKUP_RELEASE": ControlsUI.on_pickup_release,
"PUNCH_PRESS": ControlsUI.on_punch_press,
"PUNCH_RELEASE": ControlsUI.on_punch_release,
"BOMB_PRESS": ControlsUI.on_bomb_press,
"BOMB_RELEASE": ControlsUI.on_bomb_release,
"UP_DOWN": ControlsUI.on_move_ud,
"LEFT_RIGHT": ControlsUI.on_move_lr
}
2022-11-26 12:33:00 +00:00
class NewSpaz(bascenev1lib.actor.spaz.Spaz):
2022-11-26 18:01:28 +05:30
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.move_map = {
"UP_DOWN": self.on_move_up_down,
"LEFT_RIGHT": self.on_move_left_right,
"HOLD_POSITION": self.on_hold_position_press,
"HOLD_RELEASE": self.on_hold_position_release,
"JUMP_PRESS": self.on_jump_press,
"JUMP_RELEASE": self.on_jump_release,
"PICKUP_PRESS": self.on_pickup_press,
"PICKUP_RELEASE": self.on_pickup_release,
"PUNCH_PRESS": self.on_punch_press,
"PUNCH_RELEASE": self.on_punch_release,
"BOMB_PRESS": self.on_bomb_press,
"BOMB_RELEASE": self.on_bomb_release,
"RUN": self.on_run,
}
2022-11-26 12:33:00 +00:00
class NewPlayerSpaz(bascenev1lib.actor.playerspaz.PlayerSpaz):
2022-11-26 18:01:28 +05:30
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.move_map = {
"UP_DOWN": self.on_move_up_down,
"LEFT_RIGHT": self.on_move_left_right,
"HOLD_POSITION": self.on_hold_position_press,
"HOLD_RELEASE": self.on_hold_position_release,
"JUMP_PRESS": self.on_jump_press,
"JUMP_RELEASE": self.on_jump_release,
"PICKUP_PRESS": self.on_pickup_press,
"PICKUP_RELEASE": self.on_pickup_release,
"PUNCH_PRESS": self.on_punch_press,
"PUNCH_RELEASE": self.on_punch_release,
"BOMB_PRESS": self.on_bomb_press,
"BOMB_RELEASE": self.on_bomb_release,
"RUN": self.on_run,
}
self.mirror_spaz = []
self.source_player.in_replay = False
self.source_player.mirror_mode = False
def _handle_action(self, action, value: Optional[float] = None) -> None:
if self.source_player.sessionplayer in PLAYERS_STUNT_INFO:
PLAYERS_STUNT_INFO[self.source_player.sessionplayer].append({
"time": bs.time() - self.source_player.recording_start_time,
2022-11-26 18:01:28 +05:30
"move": {
"action": action,
"value": value,
}
})
elif self.source_player.in_replay:
ui_activation = CONTROLS_UI_MAP.get(action)
if ui_activation:
2022-11-26 12:33:00 +00:00
if action in ["UP_DOWN", "LEFT_RIGHT"]:
ui_activation(self.source_player.actor._activity(), value)
2022-11-26 18:01:28 +05:30
else:
ui_activation(self.source_player.actor._activity())
elif self.source_player.mirror_mode:
for mspaz in self.mirror_spaz:
if mspaz and mspaz.node.exists():
2022-11-26 12:33:00 +00:00
if action in ["UP_DOWN", "LEFT_RIGHT", "RUN"]:
2022-11-26 18:01:28 +05:30
mspaz.move_map[action](value)
else:
mspaz.move_map[action]()
def on_move_up_down(self, value: float, *args, **kwargs) -> None:
self._handle_action("UP_DOWN", value)
super().on_move_up_down(value, *args, **kwargs)
def on_move_left_right(self, value: float, *args, **kwargs) -> None:
self._handle_action("LEFT_RIGHT", value)
super().on_move_left_right(value, *args, **kwargs)
def on_hold_position_press(self, *args, **kwargs) -> None:
self._handle_action("HOLD_POSITION")
super().on_hold_position_press(*args, **kwargs)
def on_hold_position_release(self, *args, **kwargs) -> None:
self._handle_action("HOLD_RELEASE")
super().on_hold_position_release(*args, **kwargs)
def on_jump_press(self, *args, **kwargs) -> None:
self._handle_action("JUMP_PRESS")
super().on_jump_press(*args, **kwargs)
def on_jump_release(self, *args, **kwargs) -> None:
self._handle_action("JUMP_RELEASE")
super().on_jump_release(*args, **kwargs)
def on_pickup_press(self, *args, **kwargs) -> None:
self._handle_action("PICKUP_PRESS")
super().on_pickup_press(*args, **kwargs)
def on_pickup_release(self, *args, **kwargs) -> None:
self._handle_action("PICKUP_RELEASE")
super().on_pickup_release(*args, **kwargs)
def on_punch_press(self, *args, **kwargs) -> None:
self._handle_action("PUNCH_PRESS")
super().on_punch_press(*args, **kwargs)
def on_punch_release(self, *args, **kwargs) -> None:
self._handle_action("PUNCH_RELEASE")
super().on_punch_release(*args, **kwargs)
def on_bomb_press(self, *args, **kwargs) -> None:
self._handle_action("BOMB_PRESS")
super().on_bomb_press(*args, **kwargs)
def on_bomb_release(self, *args, **kwargs) -> None:
self._handle_action("BOMB_RELEASE")
super().on_bomb_release(*args, **kwargs)
def on_run(self, value: float, *args, **kwargs) -> None:
self._handle_action("RUN", value)
super().on_run(value, *args, **kwargs)
def handle_player_replay_end(player):
player.in_replay = False
ControlsUI.hide(player.actor._activity())
def get_player_from_client_id(client_id, activity=None):
activity = activity or bs.get_foreground_host_activity()
2022-11-26 18:01:28 +05:30
for player in activity.players:
if player.sessionplayer.inputdevice.client_id == client_id:
return player
raise bs.SessionPlayerNotFound()
2022-11-26 18:01:28 +05:30
2022-11-26 12:33:00 +00:00
2022-11-26 18:01:28 +05:30
def mirror(clieid):
player = get_player_from_client_id(clieid)
spawn_mirror_spaz(player)
2022-11-26 12:33:00 +00:00
2022-11-26 18:01:28 +05:30
def capture(player):
2024-01-22 12:06:37 +03:00
with player.actor._activity().context:
player.recording_start_time = bs.time()
2022-11-26 18:01:28 +05:30
PLAYERS_STUNT_INFO[player.sessionplayer] = []
def save(player, stunt_name):
stunt_path = f"{os.path.join(BASE_STUNTS_DIRECTORY, stunt_name)}.json"
os.makedirs(BASE_STUNTS_DIRECTORY, exist_ok=True)
with open(stunt_path, "w") as fout:
json.dump(PLAYERS_STUNT_INFO[player.sessionplayer], fout, indent=2)
del PLAYERS_STUNT_INFO[player.sessionplayer]
def replay(player, stunt_name):
stunt_path = f"{os.path.join(BASE_STUNTS_DIRECTORY, stunt_name)}.json"
if stunt_name in STUNT_CACHE:
stunt = STUNT_CACHE[stunt_name]
else:
try:
with open(stunt_path, "r") as fin:
stunt = json.load(fin)
STUNT_CACHE[stunt_name] = stunt
except:
bui.screenmessage(f"{stunt_name} doesn't exists")
2022-11-26 18:01:28 +05:30
return
player.in_replay = True
2024-01-22 12:06:37 +03:00
with player.actor._activity().context:
2022-11-26 18:01:28 +05:30
ControlsUI.display(player.actor._activity())
for move in stunt:
value = move["move"]["value"]
if value is None:
bs.timer(
2022-11-26 18:01:28 +05:30
move["time"],
babase.Call(player.actor.move_map[move["move"]["action"]])
2022-11-26 18:01:28 +05:30
)
else:
bs.timer(
2022-11-26 18:01:28 +05:30
move["time"],
2024-01-18 13:41:11 +00:00
babase.Call(player.actor.move_map[move["move"]
["action"]], move["move"]["value"])
2022-11-26 18:01:28 +05:30
)
last_move_time = move["time"]
time_to_hide_controls = last_move_time + 1
bs.timer(time_to_hide_controls, babase.Call(handle_player_replay_end, player))
2022-11-26 18:01:28 +05:30
2022-11-26 12:33:00 +00:00
2022-11-26 18:01:28 +05:30
def spawn_mirror_spaz(player):
player.mirror_mode = True
2024-01-22 12:06:37 +03:00
with player.actor._activity().context:
2025-01-22 19:24:00 +05:30
bot = spaz.Spaz(
color=player.color,
highlight=player.highlight,
character=player.character
).autoretain()
bot.handlemessage(bs.StandMessage(
2022-11-26 12:33:00 +00:00
(player.actor.node.position[0], player.actor.node.position[1], player.actor.node.position[2]+1), 93))
2022-11-26 18:01:28 +05:30
bot.node.name = player.actor.node.name
bot.node.name_color = player.actor.node.name_color
player.actor.mirror_spaz.append(bot)
2022-11-26 12:33:00 +00:00
2022-11-26 18:01:28 +05:30
def ghost(player, stunt_name):
stunt_path = f"{os.path.join(BASE_STUNTS_DIRECTORY, stunt_name)}.json"
if stunt_name in STUNT_CACHE:
stunt = STUNT_CACHE[stunt_name]
else:
try:
with open(stunt_path, "r") as fin:
stunt = json.load(fin)
STUNT_CACHE[stunt_name] = stunt
except:
bui.screenmessage(f"{stunt_name} doesn't exists")
2022-11-26 18:01:28 +05:30
return
player.in_replay = True
2024-01-22 12:06:37 +03:00
with player.actor._activity().context:
2025-01-22 19:24:00 +05:30
bot = spaz.Spaz(color=(1, 0, 0), character="Spaz").autoretain()
bot.handlemessage(bs.StandMessage(player.actor.node.position, 93))
2022-11-26 18:01:28 +05:30
give_ghost_power(bot)
2025-01-22 19:24:00 +05:30
ControlsUI.display(bot._activity())
2022-11-26 18:01:28 +05:30
for move in stunt:
value = move["move"]["value"]
if value is None:
bs.timer(
2022-11-26 18:01:28 +05:30
move["time"],
babase.Call(bot.move_map[move["move"]["action"]])
2022-11-26 18:01:28 +05:30
)
ui_activation = CONTROLS_UI_MAP.get(move["move"]["action"])
if ui_activation:
bs.timer(
2022-11-26 18:01:28 +05:30
move["time"],
babase.Call(ui_activation, player.actor._activity())
2022-11-26 18:01:28 +05:30
)
else:
bs.timer(
2022-11-26 18:01:28 +05:30
move["time"],
babase.Call(bot.move_map[move["move"]["action"]], move["move"]["value"])
2022-11-26 18:01:28 +05:30
)
ui_activation = CONTROLS_UI_MAP.get(move["move"]["action"])
if ui_activation:
bs.timer(
2022-11-26 18:01:28 +05:30
move["time"],
babase.Call(ui_activation, player.actor._activity(), move["move"]["value"])
2022-11-26 18:01:28 +05:30
)
last_move_time = move["time"]
time_to_hide_controls = last_move_time + 1
bs.timer(time_to_hide_controls, babase.Call(handle_player_replay_end, player))
bs.timer(time_to_hide_controls, babase.Call(bot.node.delete))
2022-11-26 18:01:28 +05:30
2022-11-26 12:33:00 +00:00
2022-11-26 18:01:28 +05:30
def give_ghost_power(spaz):
spaz.node.invincible = True
shared = SharedObjects.get()
factory = SpazFactory.get()
ghost = bs.Material()
2022-11-26 18:01:28 +05:30
# smoothy hecks
ghost.add_actions(
2022-11-26 12:33:00 +00:00
conditions=(('they_have_material', factory.spaz_material), 'or',
('they_have_material', shared.player_material), 'or',
('they_have_material', shared.attack_material), 'or',
('they_have_material', shared.pickup_material), 'or',
('they_have_material', PowerupBoxFactory.get().powerup_accept_material)),
actions=(
2022-11-26 18:01:28 +05:30
('modify_part_collision', 'collide', False),
('modify_part_collision', 'physical', False)
2022-11-26 12:33:00 +00:00
))
mats = list(spaz.node.materials)
roller = list(spaz.node.roller_materials)
ext = list(spaz.node.extras_material)
pick = list(spaz.node.pickup_materials)
punch = list(spaz.node.punch_materials)
2022-11-26 18:01:28 +05:30
mats.append(ghost)
roller.append(ghost)
ext.append(ghost)
pick.append(ghost)
punch.append(ghost)
2022-11-26 12:33:00 +00:00
spaz.node.materials = tuple(mats)
spaz.node.roller_materials = tuple(roller)
spaz.node.extras_material = tuple(ext)
spaz.node.pickup_materials = tuple(pick)
spaz.node.punch_materials = tuple(pick)
2022-11-26 18:01:28 +05:30
def new_chatmessage(msg):
2024-01-22 12:06:37 +03:00
#! Fix here to make it work with other mods modifying chat message
2022-11-26 18:01:28 +05:30
if not msg.startswith("*"):
return original_chatmessage(msg)
stripped_msg = msg[1:]
msg_splits = stripped_msg.split(maxsplit=3)
command = msg_splits[0]
client_id = -1
2024-01-22 12:06:37 +03:00
try:
player = get_player_from_client_id(client_id)
except AttributeError:
bui.screenmessage("Start a game to use", color=(0, 1, 0))
return
2022-11-26 18:01:28 +05:30
if command == "start":
capture(player)
bs.chatmessage("Recording started for {}.".format(
2022-11-26 18:01:28 +05:30
player.getname(),
))
return original_chatmessage(msg)
stunt_name = " ".join(msg_splits[1:])
if command == "save":
if len(msg_splits) < 2:
bui.screenmessage("Enter name of stunt eg : *save bombjump")
2022-11-26 18:01:28 +05:30
return original_chatmessage(msg)
save(player, stunt_name)
bs.chatmessage('Recording "{}" by {} saved.'.format(
2022-11-26 18:01:28 +05:30
stunt_name,
player.getname(),
))
elif command == "stunt":
if len(msg_splits) < 2:
bui.screenmessage("Enter name of stunt eg : *stunt bombjump")
2022-11-26 18:01:28 +05:30
return original_chatmessage(msg)
2025-01-22 19:24:00 +05:30
if player is not None and player.actor is not None:
replay(player, stunt_name)
bs.chatmessage('Replaying "{}" on {}.'.format(
stunt_name,
player.getname(),
))
else:
bui.screenmessage("Player not found")
2022-11-26 18:01:28 +05:30
elif command == "learn":
if len(msg_splits) < 2:
bui.screenmessage("Enter name of stunt eg : *learn bombjump")
2022-11-26 18:01:28 +05:30
return original_chatmessage(msg)
2025-01-22 19:24:00 +05:30
if player is not None and player.actor is not None:
ghost(player, stunt_name)
bs.chatmessage('Replaying "{}" on {}.'.format(
stunt_name,
player.getname(),
))
else:
bui.screenmessage("Player not found")
2022-11-26 18:01:28 +05:30
elif command == "mirror":
spawn_mirror_spaz(player)
return original_chatmessage(msg)
2022-11-26 12:33:00 +00:00
2022-11-26 18:01:28 +05:30
def set_stick_image_position(self, x: float, y: float) -> None:
2022-11-26 12:33:00 +00:00
# Clamp this to a circle.
len_squared = x * x + y * y
if len_squared > 1.0:
length = math.sqrt(len_squared)
mult = 1.0 / length
x *= mult
y *= mult
self.stick_image_position_x = x
self.stick_image_position_y = y
offs = 50.0
assert self._scale is not None
p = [
self._stick_nub_position[0] + x * offs * 0.6,
self._stick_nub_position[1] + y * offs * 0.6
]
c = list(self._stick_nub_image_color)
if abs(x) > 0.1 or abs(y) > 0.1:
c[0] *= 2.0
c[1] *= 4.0
c[2] *= 2.0
assert self._stick_nub_image is not None
self._stick_nub_image.position = p
self._stick_nub_image.color = c
c = list(self._stick_base_image_color)
if abs(x) > 0.1 or abs(y) > 0.1:
c[0] *= 1.5
c[1] *= 1.5
c[2] *= 1.5
assert self._stick_base_image is not None
self._stick_base_image.color = c
2022-11-26 18:01:28 +05:30
def on_begin(self, *args, **kwargs) -> None:
self._jump_image = Image(
2024-01-22 12:06:37 +03:00
bs.gettexture('buttonJump'),
2022-11-26 12:33:00 +00:00
position=(385, 160),
scale=(50, 50),
color=[0.1, 0.45, 0.1, 0]
2022-11-26 18:01:28 +05:30
)
self._pickup_image = Image(
2024-01-22 12:06:37 +03:00
bs.gettexture('buttonPickUp'),
2022-11-26 12:33:00 +00:00
position=(385, 240),
scale=(50, 50),
color=[0, 0.35, 0, 0]
2022-11-26 18:01:28 +05:30
)
self._punch_image = Image(
2024-01-22 12:06:37 +03:00
bs.gettexture('buttonPunch'),
2022-11-26 12:33:00 +00:00
position=(345, 200),
scale=(50, 50),
color=[0.45, 0.45, 0, 0]
2022-11-26 18:01:28 +05:30
)
self._bomb_image = Image(
2024-01-22 12:06:37 +03:00
bs.gettexture('buttonBomb'),
2022-11-26 12:33:00 +00:00
position=(425, 200),
scale=(50, 50),
color=[0.45, 0.1, 0.1, 0]
2022-11-26 18:01:28 +05:30
)
self.stick_image_position_x = self.stick_image_position_y = 0.0
2022-11-26 12:33:00 +00:00
self._stick_base_position = p = (-328, 200)
2022-11-26 18:01:28 +05:30
self._stick_base_image_color = c2 = (0.25, 0.25, 0.25, 1.0)
self._stick_base_image = bs.newnode(
2022-11-26 12:33:00 +00:00
'image',
attrs={
2024-01-22 12:06:37 +03:00
'texture': bs.gettexture('nub'),
2022-11-26 12:33:00 +00:00
'absolute_scale': True,
'vr_depth': -40,
'position': p,
'scale': (220.0*0.6, 220.0*0.6),
'color': c2
})
2022-11-26 18:01:28 +05:30
self._stick_nub_position = p = (-328, 200)
self._stick_nub_image_color = c3 = (0.4, 0.4, 0.4, 1.0)
self._stick_nub_image = bs.newnode('image',
2022-11-26 12:33:00 +00:00
attrs={
2024-01-22 12:06:37 +03:00
'texture': bs.gettexture('nub'),
2022-11-26 12:33:00 +00:00
'absolute_scale': True,
'position': p,
'scale': (110*0.6, 110*0.66),
'color': c3
})
2022-11-26 18:01:28 +05:30
self._stick_base_image.opacity = 0.0
self._stick_nub_image.opacity = 0.0
return original_on_begin(self, *args, **kwargs)
2025-06-24 00:55:09 +05:30
# ba_meta export babase.Plugin
2025-06-23 19:27:10 +00:00
class byHeySmoothy(babase.Plugin):
2022-11-26 18:01:28 +05:30
def on_app_running(self):
bs._activity.Activity.on_begin = on_begin
2025-01-22 19:24:00 +05:30
bs._activity.Activity.set_stick_image_position = set_stick_image_position
bs.chatmessage = new_chatmessage
bascenev1lib.actor.playerspaz.PlayerSpaz = NewPlayerSpaz
bascenev1lib.actor.spaz.Spaz = NewSpaz
2022-11-26 18:01:28 +05:30
# lets define a sample elimination game that can use super power of this plugin
# ba_meta export bascenev1.GameActivity
2022-11-26 18:01:28 +05:30
class BroEliminaition(EliminationGame):
name = 'BroElimination'
description = 'Elimination Game with dual character control'
def spawn_player(self, player) -> bs.Actor:
2022-11-26 18:01:28 +05:30
super().spawn_player(player)
2022-11-26 12:33:00 +00:00
spawn_mirror_spaz(player)