This commit is contained in:
Rikko 2022-10-05 22:30:12 +05:30
parent 9041d5cbf7
commit 6bdc35eda4
2 changed files with 491 additions and 503 deletions

View file

@ -34,7 +34,8 @@ from __future__ import annotations
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
import ba,_ba import ba
import _ba
from bastd.actor.playerspaz import PlayerSpaz from bastd.actor.playerspaz import PlayerSpaz
@ -46,315 +47,314 @@ from ba._profile import get_player_profile_colors
if TYPE_CHECKING: if TYPE_CHECKING:
from typing import Any, Type, List, Dict, Tuple, Union, Sequence, Optional from typing import Any, Type, List, Dict, Tuple, Union, Sequence, Optional
import weakref import weakref
import os,json import os
import json
from ba import _lobby from ba import _lobby
from bastd.actor.spazappearance import * from bastd.actor.spazappearance import *
from ba._lobby import ChangeMessage from ba._lobby import ChangeMessage
from ba._lobby import PlayerReadyMessage from ba._lobby import PlayerReadyMessage
def __init__(self, vpos: float, sessionplayer: _ba.SessionPlayer, def __init__(self, vpos: float, sessionplayer: _ba.SessionPlayer,
lobby: 'Lobby') -> None: lobby: 'Lobby') -> None:
self._deek_sound = _ba.getsound('deek') self._deek_sound = _ba.getsound('deek')
self._click_sound = _ba.getsound('click01') self._click_sound = _ba.getsound('click01')
self._punchsound = _ba.getsound('punch01') self._punchsound = _ba.getsound('punch01')
self._swish_sound = _ba.getsound('punchSwish') self._swish_sound = _ba.getsound('punchSwish')
self._errorsound = _ba.getsound('error') self._errorsound = _ba.getsound('error')
self._mask_texture = _ba.gettexture('characterIconMask') self._mask_texture = _ba.gettexture('characterIconMask')
self._vpos = vpos self._vpos = vpos
self._lobby = weakref.ref(lobby) self._lobby = weakref.ref(lobby)
self._sessionplayer = sessionplayer self._sessionplayer = sessionplayer
self._inited = False self._inited = False
self._dead = False self._dead = False
self._text_node: Optional[ba.Node] = None self._text_node: Optional[ba.Node] = None
self._profilename = '' self._profilename = ''
self._profilenames: List[str] = [] self._profilenames: List[str] = []
self._ready: bool = False self._ready: bool = False
self._character_names: List[str] = [] self._character_names: List[str] = []
self._last_change: Sequence[Union[float, int]] = (0, 0) self._last_change: Sequence[Union[float, int]] = (0, 0)
self._profiles: Dict[str, Dict[str, Any]] = {} self._profiles: Dict[str, Dict[str, Any]] = {}
app = _ba.app app = _ba.app
self.bakwas_chars=["Lee","Todd McBurton","Zola","Butch","Witch","warrior","Middle-Man","Alien","OldLady","Gladiator","Wrestler","Gretel","Robot"] self.bakwas_chars = ["Lee", "Todd McBurton", "Zola", "Butch", "Witch", "warrior",
"Middle-Man", "Alien", "OldLady", "Gladiator", "Wrestler", "Gretel", "Robot"]
# Load available player profiles either from the local config or # Load available player profiles either from the local config or
# from the remote device. # from the remote device.
self.reload_profiles() self.reload_profiles()
for name in _ba.app.spaz_appearances: for name in _ba.app.spaz_appearances:
if name not in self._character_names and name not in self.bakwas_chars: if name not in self._character_names and name not in self.bakwas_chars:
self._character_names.append(name) self._character_names.append(name)
# Note: this is just our local index out of available teams; *not* # Note: this is just our local index out of available teams; *not*
# the team-id! # the team-id!
self._selected_team_index: int = self.lobby.next_add_team self._selected_team_index: int = self.lobby.next_add_team
# Store a persistent random character index and colors; we'll use this # Store a persistent random character index and colors; we'll use this
# for the '_random' profile. Let's use their input_device id to seed # for the '_random' profile. Let's use their input_device id to seed
# it. This will give a persistent character for them between games # it. This will give a persistent character for them between games
# and will distribute characters nicely if everyone is random. # and will distribute characters nicely if everyone is random.
self._random_color, self._random_highlight = ( self._random_color, self._random_highlight = (
get_player_profile_colors(None)) get_player_profile_colors(None))
# To calc our random character we pick a random one out of our # To calc our random character we pick a random one out of our
# unlocked list and then locate that character's index in the full # unlocked list and then locate that character's index in the full
# list. # list.
char_index_offset = app.lobby_random_char_index_offset char_index_offset = app.lobby_random_char_index_offset
self._random_character_index = ( self._random_character_index = (
(sessionplayer.inputdevice.id + char_index_offset) % (sessionplayer.inputdevice.id + char_index_offset) %
len(self._character_names)) len(self._character_names))
# Attempt to set an initial profile based on what was used previously # Attempt to set an initial profile based on what was used previously
# for this input-device, etc. # for this input-device, etc.
self._profileindex = self._select_initial_profile() self._profileindex = self._select_initial_profile()
self._profilename = self._profilenames[self._profileindex] self._profilename = self._profilenames[self._profileindex]
self._text_node = _ba.newnode('text', self._text_node = _ba.newnode('text',
delegate=self, delegate=self,
attrs={ attrs={
'position': (-100, self._vpos), 'position': (-100, self._vpos),
'maxwidth': 190, 'maxwidth': 190,
'shadow': 0.5, 'shadow': 0.5,
'vr_depth': -20, 'vr_depth': -20,
'h_align': 'left', 'h_align': 'left',
'v_align': 'center', 'v_align': 'center',
'v_attach': 'top' 'v_attach': 'top'
}) })
animate(self._text_node, 'scale', {0: 0, 0.1: 1.0}) animate(self._text_node, 'scale', {0: 0, 0.1: 1.0})
self.icon = _ba.newnode('image', self.icon = _ba.newnode('image',
owner=self._text_node, owner=self._text_node,
attrs={ attrs={
'position': (-130, self._vpos + 20), 'position': (-130, self._vpos + 20),
'mask_texture': self._mask_texture, 'mask_texture': self._mask_texture,
'vr_depth': -10, 'vr_depth': -10,
'attach': 'topCenter' 'attach': 'topCenter'
}) })
animate_array(self.icon, 'scale', 2, {0: (0, 0), 0.1: (45, 45)}) animate_array(self.icon, 'scale', 2, {0: (0, 0), 0.1: (45, 45)})
# Set our initial name to '<choosing player>' in case anyone asks. # Set our initial name to '<choosing player>' in case anyone asks.
self._sessionplayer.setname( self._sessionplayer.setname(
Lstr(resource='choosingPlayerText').evaluate(), real=False) Lstr(resource='choosingPlayerText').evaluate(), real=False)
# Init these to our rando but they should get switched to the
# selected profile (if any) right after.
self._character_index = self._random_character_index
self._color = self._random_color
self._highlight = self._random_highlight
self.characterchooser=False
self.update_from_profile()
self.update_position()
self._inited = True
self._set_ready(False)
# Init these to our rando but they should get switched to the
# selected profile (if any) right after.
self._character_index = self._random_character_index
self._color = self._random_color
self._highlight = self._random_highlight
self.characterchooser = False
self.update_from_profile()
self.update_position()
self._inited = True
self._set_ready(False)
def _set_ready(self, ready: bool) -> None: def _set_ready(self, ready: bool) -> None:
# pylint: disable=cyclic-import # pylint: disable=cyclic-import
from bastd.ui.profile import browser as pbrowser from bastd.ui.profile import browser as pbrowser
from ba._general import Call from ba._general import Call
profilename = self._profilenames[self._profileindex] profilename = self._profilenames[self._profileindex]
# Handle '_edit' as a special case. # Handle '_edit' as a special case.
if profilename == '_edit' and ready: if profilename == '_edit' and ready:
with _ba.Context('ui'): with _ba.Context('ui'):
pbrowser.ProfileBrowserWindow(in_main_menu=False) pbrowser.ProfileBrowserWindow(in_main_menu=False)
# Give their input-device UI ownership too # Give their input-device UI ownership too
# (prevent someone else from snatching it in crowded games) # (prevent someone else from snatching it in crowded games)
_ba.set_ui_input_device(self._sessionplayer.inputdevice) _ba.set_ui_input_device(self._sessionplayer.inputdevice)
return return
if ready==False: if ready == False:
self._sessionplayer.assigninput( self._sessionplayer.assigninput(
InputType.LEFT_PRESS, InputType.LEFT_PRESS,
Call(self.handlemessage, ChangeMessage('team', -1))) Call(self.handlemessage, ChangeMessage('team', -1)))
self._sessionplayer.assigninput( self._sessionplayer.assigninput(
InputType.RIGHT_PRESS, InputType.RIGHT_PRESS,
Call(self.handlemessage, ChangeMessage('team', 1))) Call(self.handlemessage, ChangeMessage('team', 1)))
self._sessionplayer.assigninput( self._sessionplayer.assigninput(
InputType.BOMB_PRESS, InputType.BOMB_PRESS,
Call(self.handlemessage, ChangeMessage('character', 1))) Call(self.handlemessage, ChangeMessage('character', 1)))
self._sessionplayer.assigninput( self._sessionplayer.assigninput(
InputType.UP_PRESS, InputType.UP_PRESS,
Call(self.handlemessage, ChangeMessage('profileindex', -1))) Call(self.handlemessage, ChangeMessage('profileindex', -1)))
self._sessionplayer.assigninput( self._sessionplayer.assigninput(
InputType.DOWN_PRESS, InputType.DOWN_PRESS,
Call(self.handlemessage, ChangeMessage('profileindex', 1))) Call(self.handlemessage, ChangeMessage('profileindex', 1)))
self._sessionplayer.assigninput( self._sessionplayer.assigninput(
(InputType.JUMP_PRESS, InputType.PICK_UP_PRESS, (InputType.JUMP_PRESS, InputType.PICK_UP_PRESS,
InputType.PUNCH_PRESS), InputType.PUNCH_PRESS),
Call(self.handlemessage, ChangeMessage('ready', 1))) Call(self.handlemessage, ChangeMessage('ready', 1)))
self._ready = False self._ready = False
self._update_text() self._update_text()
self._sessionplayer.setname('untitled', real=False) self._sessionplayer.setname('untitled', real=False)
elif ready == True: elif ready == True:
self.characterchooser=True self.characterchooser = True
self._sessionplayer.assigninput( self._sessionplayer.assigninput(
(InputType.LEFT_PRESS, InputType.RIGHT_PRESS, (InputType.LEFT_PRESS, InputType.RIGHT_PRESS,
InputType.UP_PRESS, InputType.DOWN_PRESS, InputType.UP_PRESS, InputType.DOWN_PRESS,
InputType.JUMP_PRESS, InputType.BOMB_PRESS, InputType.JUMP_PRESS, InputType.BOMB_PRESS,
InputType.PICK_UP_PRESS), self._do_nothing) InputType.PICK_UP_PRESS), self._do_nothing)
self._sessionplayer.assigninput( self._sessionplayer.assigninput(
(InputType.UP_PRESS),Call(self.handlemessage,ChangeMessage('characterchooser',-1))) (InputType.UP_PRESS), Call(self.handlemessage, ChangeMessage('characterchooser', -1)))
self._sessionplayer.assigninput( self._sessionplayer.assigninput(
(InputType.DOWN_PRESS),Call(self.handlemessage,ChangeMessage('characterchooser',1))) (InputType.DOWN_PRESS), Call(self.handlemessage, ChangeMessage('characterchooser', 1)))
self._sessionplayer.assigninput( self._sessionplayer.assigninput(
(InputType.BOMB_PRESS),Call(self.handlemessage,ChangeMessage('ready',0))) (InputType.BOMB_PRESS), Call(self.handlemessage, ChangeMessage('ready', 0)))
self._sessionplayer.assigninput(
(InputType.JUMP_PRESS,InputType.PICK_UP_PRESS, InputType.PUNCH_PRESS),
Call(self.handlemessage, ChangeMessage('ready', 2)))
# Store the last profile picked by this input for reuse. self._sessionplayer.assigninput(
input_device = self._sessionplayer.inputdevice (InputType.JUMP_PRESS, InputType.PICK_UP_PRESS, InputType.PUNCH_PRESS),
name = input_device.name Call(self.handlemessage, ChangeMessage('ready', 2)))
unique_id = input_device.unique_identifier
device_profiles = _ba.app.config.setdefault(
'Default Player Profiles', {})
# Make an exception if we have no custom profiles and are set # Store the last profile picked by this input for reuse.
# to random; in that case we'll want to start picking up custom input_device = self._sessionplayer.inputdevice
# profiles if/when one is made so keep our setting cleared. name = input_device.name
special = ('_random', '_edit', '__account__') unique_id = input_device.unique_identifier
have_custom_profiles = any(p not in special device_profiles = _ba.app.config.setdefault(
for p in self._profiles) 'Default Player Profiles', {})
profilekey = name + ' ' + unique_id # Make an exception if we have no custom profiles and are set
if profilename == '_random' and not have_custom_profiles: # to random; in that case we'll want to start picking up custom
if profilekey in device_profiles: # profiles if/when one is made so keep our setting cleared.
del device_profiles[profilekey] special = ('_random', '_edit', '__account__')
else: have_custom_profiles = any(p not in special
device_profiles[profilekey] = profilename for p in self._profiles)
_ba.app.config.commit()
# Set this player's short and full name. profilekey = name + ' ' + unique_id
self._sessionplayer.setname(self._getname(), if profilename == '_random' and not have_custom_profiles:
self._getname(full=True), if profilekey in device_profiles:
real=True) del device_profiles[profilekey]
self._ready = True
self._update_text()
else: else:
device_profiles[profilekey] = profilename
_ba.app.config.commit()
# Set this player's short and full name.
self._sessionplayer.setname(self._getname(),
self._getname(full=True),
real=True)
self._ready = True
self._update_text()
else:
# Inform the session that this player is ready. # Inform the session that this player is ready.
_ba.getsession().handlemessage(PlayerReadyMessage(self)) _ba.getsession().handlemessage(PlayerReadyMessage(self))
def handlemessage(self, msg: Any) -> Any: def handlemessage(self, msg: Any) -> Any:
"""Standard generic message handler.""" """Standard generic message handler."""
if isinstance(msg, ChangeMessage): if isinstance(msg, ChangeMessage):
self._handle_repeat_message_attack() self._handle_repeat_message_attack()
# If we've been removed from the lobby, ignore this stuff. # If we've been removed from the lobby, ignore this stuff.
if self._dead: if self._dead:
print_error('chooser got ChangeMessage after dying') print_error('chooser got ChangeMessage after dying')
return return
if not self._text_node: if not self._text_node:
print_error('got ChangeMessage after nodes died') print_error('got ChangeMessage after nodes died')
return return
if msg.what=='characterchooser': if msg.what == 'characterchooser':
_ba.playsound(self._click_sound) _ba.playsound(self._click_sound)
# update our index in our local list of characters # update our index in our local list of characters
self._character_index = ((self._character_index + msg.value) % self._character_index = ((self._character_index + msg.value) %
len(self._character_names)) len(self._character_names))
self._update_text() self._update_text()
self._update_icon() self._update_icon()
if msg.what == 'team': if msg.what == 'team':
sessionteams = self.lobby.sessionteams sessionteams = self.lobby.sessionteams
if len(sessionteams) > 1: if len(sessionteams) > 1:
_ba.playsound(self._swish_sound) _ba.playsound(self._swish_sound)
self._selected_team_index = ( self._selected_team_index = (
(self._selected_team_index + msg.value) % (self._selected_team_index + msg.value) %
len(sessionteams)) len(sessionteams))
self._update_text() self._update_text()
self.update_position() self.update_position()
self._update_icon() self._update_icon()
elif msg.what == 'profileindex': elif msg.what == 'profileindex':
if len(self._profilenames) == 1: if len(self._profilenames) == 1:
# This should be pretty hard to hit now with # This should be pretty hard to hit now with
# automatic local accounts. # automatic local accounts.
_ba.playsound(_ba.getsound('error')) _ba.playsound(_ba.getsound('error'))
else: else:
# Pick the next player profile and assign our name # Pick the next player profile and assign our name
# and character based on that. # and character based on that.
_ba.playsound(self._deek_sound) _ba.playsound(self._deek_sound)
self._profileindex = ((self._profileindex + msg.value) % self._profileindex = ((self._profileindex + msg.value) %
len(self._profilenames)) len(self._profilenames))
self.update_from_profile() self.update_from_profile()
elif msg.what == 'character': elif msg.what == 'character':
_ba.playsound(self._click_sound) _ba.playsound(self._click_sound)
self.characterchooser=True self.characterchooser = True
# update our index in our local list of characters # update our index in our local list of characters
self._character_index = ((self._character_index + msg.value) % self._character_index = ((self._character_index + msg.value) %
len(self._character_names)) len(self._character_names))
self._update_text() self._update_text()
self._update_icon() self._update_icon()
elif msg.what == 'ready':
self._handle_ready_msg(msg.value)
elif msg.what == 'ready':
self._handle_ready_msg(msg.value)
def _update_text(self) -> None: def _update_text(self) -> None:
assert self._text_node is not None assert self._text_node is not None
if self._ready: if self._ready:
# Once we're ready, we've saved the name, so lets ask the system # Once we're ready, we've saved the name, so lets ask the system
# for it so we get appended numbers and stuff. # for it so we get appended numbers and stuff.
text = Lstr(value=self._sessionplayer.getname(full=True)) text = Lstr(value=self._sessionplayer.getname(full=True))
if self.characterchooser: if self.characterchooser:
text = Lstr(value='${A}\n${B}', text = Lstr(value='${A}\n${B}',
subs=[('${A}', text), subs=[('${A}', text),
('${B}', Lstr(value=""+self._character_names[self._character_index]))]) ('${B}', Lstr(value=""+self._character_names[self._character_index]))])
self._text_node.scale=0.8 self._text_node.scale = 0.8
else:
text = Lstr(value='${A} (${B})',
subs=[('${A}', text),
('${B}', Lstr(resource='readyText'))])
else: else:
text = Lstr(value=self._getname(full=True)) text = Lstr(value='${A} (${B})',
self._text_node.scale=1.0 subs=[('${A}', text),
('${B}', Lstr(resource='readyText'))])
else:
text = Lstr(value=self._getname(full=True))
self._text_node.scale = 1.0
can_switch_teams = len(self.lobby.sessionteams) > 1 can_switch_teams = len(self.lobby.sessionteams) > 1
# Flash as we're coming in. # Flash as we're coming in.
fin_color = _ba.safecolor(self.get_color()) + (1, ) fin_color = _ba.safecolor(self.get_color()) + (1, )
if not self._inited: if not self._inited:
animate_array(self._text_node, 'color', 4, {
0.15: fin_color,
0.25: (2, 2, 2, 1),
0.35: fin_color
})
else:
# Blend if we're in teams mode; switch instantly otherwise.
if can_switch_teams:
animate_array(self._text_node, 'color', 4, { animate_array(self._text_node, 'color', 4, {
0.15: fin_color, 0: self._text_node.color,
0.25: (2, 2, 2, 1), 0.1: fin_color
0.35: fin_color
}) })
else: else:
self._text_node.color = fin_color
# Blend if we're in teams mode; switch instantly otherwise. self._text_node.text = text
if can_switch_teams:
animate_array(self._text_node, 'color', 4, {
0: self._text_node.color,
0.1: fin_color
})
else:
self._text_node.color = fin_color
self._text_node.text = text
# ba_meta export plugin # ba_meta export plugin
class HeySmoothy(ba.Plugin): class HeySmoothy(ba.Plugin):
def __init__(self): def __init__(self):
_lobby.Chooser.__init__=__init__ _lobby.Chooser.__init__ = __init__
_lobby.Chooser._set_ready=_set_ready _lobby.Chooser._set_ready = _set_ready
_lobby.Chooser._update_text=_update_text _lobby.Chooser._update_text = _update_text
_lobby.Chooser.handlemessage=handlemessage _lobby.Chooser.handlemessage = handlemessage

View file

@ -50,38 +50,41 @@ from __future__ import annotations
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
import ba,_ba import ba
import _ba
from bastd.actor.playerspaz import PlayerSpaz from bastd.actor.playerspaz import PlayerSpaz
from bastd.actor.scoreboard import Scoreboard from bastd.actor.scoreboard import Scoreboard
if TYPE_CHECKING: if TYPE_CHECKING:
from typing import Any, Type, List, Dict, Tuple, Union, Sequence, Optional from typing import Any, Type, List, Dict, Tuple, Union, Sequence, Optional
import os,json import os
import json
from bastd.actor.spazappearance import * from bastd.actor.spazappearance import *
spazoutfit={ spazoutfit = {
"color_mask":"neoSpazColorMask", "color_mask": "neoSpazColorMask",
"color_texture":"neoSpazColor", "color_texture": "neoSpazColor",
"head":"neoSpazHead", "head": "neoSpazHead",
"hand":"neoSpazHand", "hand": "neoSpazHand",
"torso":"neoSpazTorso", "torso": "neoSpazTorso",
"pelvis":"neoSpazTorso", "pelvis": "neoSpazTorso",
"upper_arm":"neoSpazUpperArm", "upper_arm": "neoSpazUpperArm",
"forearm":"neoSpazForeArm", "forearm": "neoSpazForeArm",
"upper_leg":"neoSpazUpperLeg", "upper_leg": "neoSpazUpperLeg",
"lower_leg":"neoSpazLowerLeg", "lower_leg": "neoSpazLowerLeg",
"toes_model":"neoSpazToes", "toes_model": "neoSpazToes",
"jump_sounds":['spazJump01', 'spazJump02', 'spazJump03', 'spazJump04'], "jump_sounds": ['spazJump01', 'spazJump02', 'spazJump03', 'spazJump04'],
"attack_sounds":['spazAttack01', 'spazAttack02', 'spazAttack03', 'spazAttack04'], "attack_sounds": ['spazAttack01', 'spazAttack02', 'spazAttack03', 'spazAttack04'],
"impact_sounds":['spazImpact01', 'spazImpact02', 'spazImpact03', 'spazImpact04'], "impact_sounds": ['spazImpact01', 'spazImpact02', 'spazImpact03', 'spazImpact04'],
"death_sounds":['spazDeath01'], "death_sounds": ['spazDeath01'],
"pickup_sounds":['spazPickup01'], "pickup_sounds": ['spazPickup01'],
"fall_sounds":['spazFall01'], "fall_sounds": ['spazFall01'],
"icon_texture":"neoSpazIcon", "icon_texture": "neoSpazIcon",
"icon_mask_texture":"neoSpazIconColorMask", "icon_mask_texture": "neoSpazIconColorMask",
"style":"spaz" "style": "spaz"
} }
character=None character = None
class Player(ba.Player['Team']): class Player(ba.Player['Team']):
"""Our player type for this game.""" """Our player type for this game."""
@ -140,7 +143,6 @@ class CharacterBuilder(ba.TeamGameActivity[Player, Team]):
ba.BoolSetting('Epic Mode', default=False), ba.BoolSetting('Epic Mode', default=False),
] ]
if issubclass(sessiontype, ba.FreeForAllSession): if issubclass(sessiontype, ba.FreeForAllSession):
settings.append( settings.append(
ba.BoolSetting('Allow Negative Scores', default=False)) ba.BoolSetting('Allow Negative Scores', default=False))
@ -157,10 +159,9 @@ class CharacterBuilder(ba.TeamGameActivity[Player, Team]):
return ['Rampage'] return ['Rampage']
def __init__(self, settings: dict): def __init__(self, settings: dict):
super().__init__(settings) super().__init__(settings)
self.initdic() self.initdic()
_ba.set_party_icon_always_visible(True) _ba.set_party_icon_always_visible(True)
self._score_to_win: Optional[int] = None self._score_to_win: Optional[int] = None
@ -171,28 +172,28 @@ class CharacterBuilder(ba.TeamGameActivity[Player, Team]):
self._time_limit = float(settings['Time Limit']) self._time_limit = float(settings['Time Limit'])
self._allow_negative_scores = bool( self._allow_negative_scores = bool(
settings.get('Allow Negative Scores', False)) settings.get('Allow Negative Scores', False))
self.bodyindex=0 self.bodyindex = 0
self.modelindex=0 self.modelindex = 0
self.youtube= ba.newnode( self.youtube = ba.newnode(
'text', 'text',
attrs={ attrs={
'text': "youtube.com/c/HeySmoothy", 'text': "youtube.com/c/HeySmoothy",
'in_world': True, 'in_world': True,
'scale': 0.02, 'scale': 0.02,
'color': (1, 0, 0, 0.4), 'color': (1, 0, 0, 0.4),
'h_align': 'center', 'h_align': 'center',
'position': (0,4,-1.9) 'position': (0, 4, -1.9)
}) })
self.discordservere= ba.newnode( self.discordservere = ba.newnode(
'text', 'text',
attrs={ attrs={
'text': "discord.gg/ucyaesh", 'text': "discord.gg/ucyaesh",
'in_world': True, 'in_world': True,
'scale': 0.02, 'scale': 0.02,
'color': (0.12, 0.3, 0.6, 0.4), 'color': (0.12, 0.3, 0.6, 0.4),
'h_align': 'center', 'h_align': 'center',
'position': (-3,2.7,-1.9) 'position': (-3, 2.7, -1.9)
}) })
# self.discord= ba.newnode( # self.discord= ba.newnode(
# 'text', # 'text',
# attrs={ # attrs={
@ -204,26 +205,26 @@ class CharacterBuilder(ba.TeamGameActivity[Player, Team]):
# 'position': (4,2.7,-1.9) # 'position': (4,2.7,-1.9)
# }) # })
# Base class overrides. # Base class overrides.
self.bodypart= ba.newnode( self.bodypart = ba.newnode(
'text', 'text',
attrs={ attrs={
'text': "<Choose Body Part>", 'text': "<Choose Body Part>",
'in_world': True, 'in_world': True,
'scale': 0.02, 'scale': 0.02,
'color': (1, 1, 0, 1), 'color': (1, 1, 0, 1),
'h_align': 'center', 'h_align': 'center',
'position': (-4,6,-4) 'position': (-4, 6, -4)
}) })
self.newmodel = ba.newnode( self.newmodel = ba.newnode(
'text', 'text',
attrs={ attrs={
'text': "<Choose model/tex>", 'text': "<Choose model/tex>",
'in_world': True, 'in_world': True,
'scale': 0.02, 'scale': 0.02,
'color': (1, 1, 0, 1), 'color': (1, 1, 0, 1),
'h_align': 'center', 'h_align': 'center',
'position': (6,6,-4) 'position': (6, 6, -4)
}) })
self.slow_motion = self._epic_mode self.slow_motion = self._epic_mode
self.default_music = (ba.MusicType.EPIC if self._epic_mode else self.default_music = (ba.MusicType.EPIC if self._epic_mode else
ba.MusicType.TO_THE_DEATH) ba.MusicType.TO_THE_DEATH)
@ -240,113 +241,110 @@ class CharacterBuilder(ba.TeamGameActivity[Player, Team]):
def on_begin(self) -> None: def on_begin(self) -> None:
super().on_begin() super().on_begin()
def nextBodyPart(self): def nextBodyPart(self):
self.bodyindex =(self.bodyindex+1)%len(self.dic.keys()) self.bodyindex = (self.bodyindex+1) % len(self.dic.keys())
self.bodypart.delete() self.bodypart.delete()
PART=list(self.dic.keys())[self.bodyindex] PART = list(self.dic.keys())[self.bodyindex]
self.bodypart=ba.newnode( self.bodypart = ba.newnode(
'text', 'text',
attrs={ attrs={
'text': PART, 'text': PART,
'in_world': True, 'in_world': True,
'scale': 0.02, 'scale': 0.02,
'color': (1, 1, 1, 1), 'color': (1, 1, 1, 1),
'h_align': 'center', 'h_align': 'center',
'position': (-4,6,-4) 'position': (-4, 6, -4)
}) })
def prevBodyPart(self): def prevBodyPart(self):
self.bodyindex =(self.bodyindex-1)%len(self.dic.keys()) self.bodyindex = (self.bodyindex-1) % len(self.dic.keys())
self.bodypart.delete() self.bodypart.delete()
PART=list(self.dic.keys())[self.bodyindex] PART = list(self.dic.keys())[self.bodyindex]
self.bodypart=ba.newnode( self.bodypart = ba.newnode(
'text', 'text',
attrs={ attrs={
'text': PART, 'text': PART,
'in_world': True, 'in_world': True,
'scale': 0.02, 'scale': 0.02,
'color': (1, 1, 1, 1), 'color': (1, 1, 1, 1),
'h_align': 'center', 'h_align': 'center',
'position': (-4,6,-4) 'position': (-4, 6, -4)
}) })
def nextModel(self): def nextModel(self):
self.newmodel.delete() self.newmodel.delete()
PART=list(self.dic.keys())[self.bodyindex] PART = list(self.dic.keys())[self.bodyindex]
self.modelindex =(self.modelindex+1)%len(self.dic[PART]) self.modelindex = (self.modelindex+1) % len(self.dic[PART])
model=self.dic[PART][self.modelindex] model = self.dic[PART][self.modelindex]
self.newmodel=ba.newnode( self.newmodel = ba.newnode(
'text', 'text',
attrs={ attrs={
'text': model, 'text': model,
'in_world': True, 'in_world': True,
'scale': 0.02, 'scale': 0.02,
'color': (1, 1, 1, 1), 'color': (1, 1, 1, 1),
'h_align': 'center', 'h_align': 'center',
'position': (6,6,-4) 'position': (6, 6, -4)
}) })
self.setModel(PART,model) self.setModel(PART, model)
def prevModel(self): def prevModel(self):
self.newmodel.delete() self.newmodel.delete()
PART=list(self.dic.keys())[self.bodyindex] PART = list(self.dic.keys())[self.bodyindex]
self.modelindex =(self.modelindex-1)%len(self.dic[PART]) self.modelindex = (self.modelindex-1) % len(self.dic[PART])
model=self.dic[PART][self.modelindex] model = self.dic[PART][self.modelindex]
self.newmodel=ba.newnode( self.newmodel = ba.newnode(
'text', 'text',
attrs={ attrs={
'text': model, 'text': model,
'in_world': True, 'in_world': True,
'scale': 0.02, 'scale': 0.02,
'color': (1, 1, 1, 1), 'color': (1, 1, 1, 1),
'h_align': 'center', 'h_align': 'center',
'position': (6,6,-4) 'position': (6, 6, -4)
}) })
self.setModel(PART,model) self.setModel(PART, model)
def setModel(self,bodypart,modelname): def setModel(self, bodypart, modelname):
global spazoutfit global spazoutfit
body=_ba.get_foreground_host_activity().players[0].actor.node body = _ba.get_foreground_host_activity().players[0].actor.node
if bodypart=='head': if bodypart == 'head':
body.head_model=ba.getmodel(modelname) body.head_model = ba.getmodel(modelname)
elif bodypart=='torso': elif bodypart == 'torso':
body.torso_model=ba.getmodel(modelname) body.torso_model = ba.getmodel(modelname)
elif bodypart=='pelvis': elif bodypart == 'pelvis':
body.pelvis_model=ba.getmodel(modelname) body.pelvis_model = ba.getmodel(modelname)
elif bodypart=='upper_arm': elif bodypart == 'upper_arm':
body.upper_arm_model=ba.getmodel(modelname) body.upper_arm_model = ba.getmodel(modelname)
elif bodypart=='forearm': elif bodypart == 'forearm':
body.forearm_model=ba.getmodel(modelname) body.forearm_model = ba.getmodel(modelname)
elif bodypart=='hand': elif bodypart == 'hand':
body.hand_model=ba.getmodel(modelname) body.hand_model = ba.getmodel(modelname)
elif bodypart=='upper_leg': elif bodypart == 'upper_leg':
body.upper_leg_model=ba.getmodel(modelname) body.upper_leg_model = ba.getmodel(modelname)
elif bodypart=='lower_leg': elif bodypart == 'lower_leg':
body.lower_leg_model=ba.getmodel(modelname) body.lower_leg_model = ba.getmodel(modelname)
elif bodypart=='toes_model': elif bodypart == 'toes_model':
body.toes_model=ba.getmodel(modelname) body.toes_model = ba.getmodel(modelname)
elif bodypart=='style': elif bodypart == 'style':
body.style=modelname body.style = modelname
elif bodypart=='color_texture': elif bodypart == 'color_texture':
body.color_texture=ba.gettexture(modelname) body.color_texture = ba.gettexture(modelname)
elif bodypart=='color_mask': elif bodypart == 'color_mask':
body.color_mask_texture=ba.gettexture(modelname) body.color_mask_texture = ba.gettexture(modelname)
spazoutfit[bodypart]=modelname spazoutfit[bodypart] = modelname
def spawn_player(self, player: Player) -> ba.Actor: def spawn_player(self, player: Player) -> ba.Actor:
global character global character
if character!=None: if character != None:
player.character=character player.character = character
self.setcurrentcharacter(player.character) self.setcurrentcharacter(player.character)
spaz = self.spawn_player_spaz(player) spaz = self.spawn_player_spaz(player)
# Let's reconnect this player's controls to this # Let's reconnect this player's controls to this
@ -374,31 +372,25 @@ class CharacterBuilder(ba.TeamGameActivity[Player, Team]):
player = msg.getplayer(Player) player = msg.getplayer(Player)
self.respawn_player(player) self.respawn_player(player)
else: else:
return super().handlemessage(msg) return super().handlemessage(msg)
return None return None
def setcurrentcharacter(self,charname):
global spazoutfit
char=ba.app.spaz_appearances[charname]
spazoutfit['head']=char.head_model
spazoutfit['hand']=char.hand_model
spazoutfit['torso']=char.torso_model
spazoutfit['pelvis']=char.pelvis_model
spazoutfit['upper_arm']=char.upper_arm_model
spazoutfit['forearm']=char.forearm_model
spazoutfit['upper_leg']=char.upper_leg_model
spazoutfit['lower_leg']=char.lower_leg_model
spazoutfit['toes_model']=char.toes_model
spazoutfit['style']=char.style
spazoutfit['color_mask']=char.color_mask_texture
spazoutfit['color_texture']=char.color_texture
def setcurrentcharacter(self, charname):
global spazoutfit
char = ba.app.spaz_appearances[charname]
spazoutfit['head'] = char.head_model
spazoutfit['hand'] = char.hand_model
spazoutfit['torso'] = char.torso_model
spazoutfit['pelvis'] = char.pelvis_model
spazoutfit['upper_arm'] = char.upper_arm_model
spazoutfit['forearm'] = char.forearm_model
spazoutfit['upper_leg'] = char.upper_leg_model
spazoutfit['lower_leg'] = char.lower_leg_model
spazoutfit['toes_model'] = char.toes_model
spazoutfit['style'] = char.style
spazoutfit['color_mask'] = char.color_mask_texture
spazoutfit['color_texture'] = char.color_texture
def _update_scoreboard(self) -> None: def _update_scoreboard(self) -> None:
for team in self.teams: for team in self.teams:
@ -410,27 +402,29 @@ class CharacterBuilder(ba.TeamGameActivity[Player, Team]):
for team in self.teams: for team in self.teams:
results.set_team_score(team, team.score) results.set_team_score(team, team.score)
self.end(results=results) self.end(results=results)
def initdic(self):
self.dic={"head":["bomb","landMine","trees","wing","eyeLid","impactBomb"],
"hand":["hairTuft3","bomb","powerup"],
"torso":["bomb","landMine","bomb"],
"pelvis":["hairTuft4","bomb"],
"upper_arm":["wing","locator","bomb"],
"forearm":["flagPole","bomb"],
"upper_leg":["bomb"],
"lower_leg":["bomb"],
"toes_model":["bomb"],
"style":["spaz","female","ninja","kronk","mel","pirate","santa","frosty","bones","bear","penguin","ali","cyborg","agent","pixie","bunny"],
"color_texture":["kronk","egg1","egg2","egg3","achievementGotTheMoves","bombColor","crossOut","explosion","rgbStripes","powerupCurse","powerupHealth","impactBombColorLit"],
"color_mask":["egg1","egg2","egg3","bombColor","crossOutMask","fontExtras3"]
} def initdic(self):
chars=["neoSpaz","zoe","ninja","kronk","mel","jack","santa","frosty","bones","bear","penguin","ali","cyborg","agent","wizard","pixie","bunny"] self.dic = {"head": ["bomb", "landMine", "trees", "wing", "eyeLid", "impactBomb"],
"hand": ["hairTuft3", "bomb", "powerup"],
"torso": ["bomb", "landMine", "bomb"],
"pelvis": ["hairTuft4", "bomb"],
"upper_arm": ["wing", "locator", "bomb"],
"forearm": ["flagPole", "bomb"],
"upper_leg": ["bomb"],
"lower_leg": ["bomb"],
"toes_model": ["bomb"],
"style": ["spaz", "female", "ninja", "kronk", "mel", "pirate", "santa", "frosty", "bones", "bear", "penguin", "ali", "cyborg", "agent", "pixie", "bunny"],
"color_texture": ["kronk", "egg1", "egg2", "egg3", "achievementGotTheMoves", "bombColor", "crossOut", "explosion", "rgbStripes", "powerupCurse", "powerupHealth", "impactBombColorLit"],
"color_mask": ["egg1", "egg2", "egg3", "bombColor", "crossOutMask", "fontExtras3"]
}
chars = ["neoSpaz", "zoe", "ninja", "kronk", "mel", "jack", "santa", "frosty",
"bones", "bear", "penguin", "ali", "cyborg", "agent", "wizard", "pixie", "bunny"]
for char in chars: for char in chars:
self.dic["head"].append(char+"Head") self.dic["head"].append(char+"Head")
self.dic["hand"].append(char+"Hand") self.dic["hand"].append(char+"Hand")
self.dic["torso"].append(char+"Torso") self.dic["torso"].append(char+"Torso")
if char not in ['mel',"jack","santa"]: if char not in ['mel', "jack", "santa"]:
self.dic["pelvis"].append(char+"Pelvis") self.dic["pelvis"].append(char+"Pelvis")
self.dic["upper_arm"].append(char+"UpperArm") self.dic["upper_arm"].append(char+"UpperArm")
self.dic["forearm"].append(char+"ForeArm") self.dic["forearm"].append(char+"ForeArm")
@ -438,101 +432,95 @@ class CharacterBuilder(ba.TeamGameActivity[Player, Team]):
self.dic["lower_leg"].append(char+"LowerLeg") self.dic["lower_leg"].append(char+"LowerLeg")
self.dic["toes_model"].append(char+"Toes") self.dic["toes_model"].append(char+"Toes")
self.dic["color_mask"].append(char+"ColorMask") self.dic["color_mask"].append(char+"ColorMask")
if char !="kronk": if char != "kronk":
self.dic["color_texture"].append(char+"Color") self.dic["color_texture"].append(char+"Color")
cm=_ba.chatmessage cm = _ba.chatmessage
def _new_chatmessage(msg): def _new_chatmessage(msg):
if msg.split(" ")[0]=="export": if msg.split(" ")[0] == "export":
if len(msg.split(" "))>1: if len(msg.split(" ")) > 1:
savecharacter(msg.split(" ")[1]) savecharacter(msg.split(" ")[1])
else: else:
_ba.screenmessage("Enter name of character") _ba.screenmessage("Enter name of character")
elif msg.split(" ")[0]=="import": elif msg.split(" ")[0] == "import":
importcharacter(msg[7:]) importcharacter(msg[7:])
else: else:
cm(msg) cm(msg)
_ba.chatmessage=_new_chatmessage
_ba.chatmessage = _new_chatmessage
def savecharacter(name): def savecharacter(name):
path=os.path.join(_ba.env()["python_directory_user"],"CustomCharacters" + os.sep) path = os.path.join(_ba.env()["python_directory_user"], "CustomCharacters" + os.sep)
if not os.path.isdir(path): if not os.path.isdir(path):
os.makedirs(path) os.makedirs(path)
if _ba.get_foreground_host_activity()!=None: if _ba.get_foreground_host_activity() != None:
with open(path+name+".json",'w') as f: with open(path+name+".json", 'w') as f:
json.dump(spazoutfit,f,indent=4) json.dump(spazoutfit, f, indent=4)
registercharacter(name,spazoutfit) registercharacter(name, spazoutfit)
ba.playsound(ba.getsound("gunCocking")) ba.playsound(ba.getsound("gunCocking"))
_ba.screenmessage("Character Saved") _ba.screenmessage("Character Saved")
else: else:
_ba.screenmessage("Works offline with Character Maker") _ba.screenmessage("Works offline with Character Maker")
def importcharacter(name): def importcharacter(name):
if name in ba.app.spaz_appearances: if name in ba.app.spaz_appearances:
global character global character
character=name character = name
try: try:
_ba.get_foreground_host_activity().players[0].actor.node.handlemessage(ba.DieMessage()) _ba.get_foreground_host_activity().players[0].actor.node.handlemessage(ba.DieMessage())
_ba.screenmessage("Imported") _ba.screenmessage("Imported")
except: except:
_ba.screenmessage("works offline with character maker") _ba.screenmessage("works offline with character maker")
else: else:
_ba.screenmessage("invalid name check typo \n name is case sensitive") _ba.screenmessage("invalid name check typo \n name is case sensitive")
def registercharacter(name,char): def registercharacter(name, char):
t = Appearance(name.split(".")[0]) t = Appearance(name.split(".")[0])
t.color_texture = char['color_texture'] t.color_texture = char['color_texture']
t.color_mask_texture = char['color_mask'] t.color_mask_texture = char['color_mask']
t.default_color = (0.6, 0.6, 0.6) t.default_color = (0.6, 0.6, 0.6)
t.default_highlight = (0, 1, 0) t.default_highlight = (0, 1, 0)
t.icon_texture = char['icon_texture'] t.icon_texture = char['icon_texture']
t.icon_mask_texture = char['icon_mask_texture'] t.icon_mask_texture = char['icon_mask_texture']
t.head_model = char['head'] t.head_model = char['head']
t.torso_model = char['torso'] t.torso_model = char['torso']
t.pelvis_model = char['pelvis'] t.pelvis_model = char['pelvis']
t.upper_arm_model = char['upper_arm'] t.upper_arm_model = char['upper_arm']
t.forearm_model = char['forearm'] t.forearm_model = char['forearm']
t.hand_model = char['hand'] t.hand_model = char['hand']
t.upper_leg_model = char['upper_leg'] t.upper_leg_model = char['upper_leg']
t.lower_leg_model = char['lower_leg'] t.lower_leg_model = char['lower_leg']
t.toes_model = char['toes_model'] t.toes_model = char['toes_model']
t.jump_sounds = char['jump_sounds'] t.jump_sounds = char['jump_sounds']
t.attack_sounds = char['attack_sounds'] t.attack_sounds = char['attack_sounds']
t.impact_sounds = char['impact_sounds'] t.impact_sounds = char['impact_sounds']
t.death_sounds = char['death_sounds'] t.death_sounds = char['death_sounds']
t.pickup_sounds = char['pickup_sounds'] t.pickup_sounds = char['pickup_sounds']
t.fall_sounds = char['fall_sounds'] t.fall_sounds = char['fall_sounds']
t.style = char['style'] t.style = char['style']
# ba_meta export plugin # ba_meta export plugin
class HeySmoothy(ba.Plugin): class HeySmoothy(ba.Plugin):
def __init__(self): def __init__(self):
_ba.set_party_icon_always_visible(True) _ba.set_party_icon_always_visible(True)
path=os.path.join(_ba.env()["python_directory_user"],"CustomCharacters" + os.sep) path = os.path.join(_ba.env()["python_directory_user"], "CustomCharacters" + os.sep)
if not os.path.isdir(path): if not os.path.isdir(path):
os.makedirs(path) os.makedirs(path)
files=os.listdir(path) files = os.listdir(path)
for file in files: for file in files:
with open(path+file, 'r') as f: with open(path+file, 'r') as f:
character = json.load(f) character = json.load(f)
registercharacter(file,character) registercharacter(file, character)