added character chooser and builder

This commit is contained in:
Ayush Saini 2022-10-05 21:36:29 +05:30
parent e6e984397a
commit 46645a6aad
3 changed files with 929 additions and 3 deletions

View file

@ -133,7 +133,7 @@
"authors": [ "authors": [
{ {
"name": "Mr.Smoothy", "name": "Mr.Smoothy",
"email": "", "email": "smoothy@bombsquad.ga",
"discord": "mr.smoothy#5824" "discord": "mr.smoothy#5824"
} }
], ],
@ -158,7 +158,7 @@
"authors": [ "authors": [
{ {
"name": "Mr.Smoothy", "name": "Mr.Smoothy",
"email": "smoothyt@bombsquad.ga", "email": "smoothy@bombsquad.ga",
"discord": "mr.smoothy#5824" "discord": "mr.smoothy#5824"
} }
], ],
@ -177,7 +177,7 @@
"authors": [ "authors": [
{ {
"name": "Mr.Smoothy", "name": "Mr.Smoothy",
"email": "smoothyt@bombsquad.ga", "email": "smoothy@bombsquad.ga",
"discord": "mr.smoothy#5824" "discord": "mr.smoothy#5824"
} }
], ],
@ -190,6 +190,34 @@
} }
} }
}, },
"character_chooser": {
"description": "Let you choose your character before joining game.",
"external_url": "https://www.youtube.com/watch?v=hNmv2l-NahE",
"authors": [
{
"name": "Mr.Smoothy",
"email": "smoothy@bombsquad.ga",
"discord": "mr.smoothy#5824"
}
],
"versions": {
"1.0.0": null
}
},
"character_builder": {
"description": "Make new characters by manipulating models and textures.",
"external_url": "https://www.youtube.com/watch?v=q0KxY1hfMPQ",
"authors": [
{
"name": "Mr.Smoothy",
"email": "smoothy@bombsquad.ga",
"discord": "mr.smoothy#5824"
}
],
"versions": {
"1.0.0": null
}
},
"icons_keyboard": { "icons_keyboard": {
"description": "Enable 'Always Use Internal Keyboard' in Settings>Advanced. Double tap space-bar to change keyboards", "description": "Enable 'Always Use Internal Keyboard' in Settings>Advanced. Double tap space-bar to change keyboards",
"external_url": "", "external_url": "",

View file

@ -0,0 +1,360 @@
# ba_meta require api 7
'''
Character Chooser by Mr.Smoothy
This plugin will let you choose your character from lobby.
Install this plugin on your Phone/PC or on Server
If installed on server :- this will also let players choose server specific custom characters . so no more sharing of character file with all players,
just install this plugin on server ...and players can pick character from lobby .
Use:-
> select your profile (focus on color and name)
> press ready (punch)
> now use UP/DOWN buttons to scroll character list
> Press ready again (punch) to join the game
> or press Bomb button to go back to profile choosing menu
> END
Watch : https://www.youtube.com/watch?v=hNmv2l-NahE
Join : https://discord.gg/ucyaesh
Contact : discord mr.smoothy#5824
Share this plugin with your server owner /admins to use it online
:)
'''
from __future__ import annotations
from typing import TYPE_CHECKING
import ba,_ba
from bastd.actor.playerspaz import PlayerSpaz
from ba._error import print_exception, print_error, NotFoundError
from ba._gameutils import animate, animate_array
from ba._language import Lstr
from ba._generated.enums import SpecialChar, InputType
from ba._profile import get_player_profile_colors
if TYPE_CHECKING:
from typing import Any, Type, List, Dict, Tuple, Union, Sequence, Optional
import weakref
import os,json
from ba import _lobby
from bastd.actor.spazappearance import *
from ba._lobby import ChangeMessage
from ba._lobby import PlayerReadyMessage
def __init__(self, vpos: float, sessionplayer: _ba.SessionPlayer,
lobby: 'Lobby') -> None:
self._deek_sound = _ba.getsound('deek')
self._click_sound = _ba.getsound('click01')
self._punchsound = _ba.getsound('punch01')
self._swish_sound = _ba.getsound('punchSwish')
self._errorsound = _ba.getsound('error')
self._mask_texture = _ba.gettexture('characterIconMask')
self._vpos = vpos
self._lobby = weakref.ref(lobby)
self._sessionplayer = sessionplayer
self._inited = False
self._dead = False
self._text_node: Optional[ba.Node] = None
self._profilename = ''
self._profilenames: List[str] = []
self._ready: bool = False
self._character_names: List[str] = []
self._last_change: Sequence[Union[float, int]] = (0, 0)
self._profiles: Dict[str, Dict[str, Any]] = {}
app = _ba.app
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
# from the remote device.
self.reload_profiles()
for name in _ba.app.spaz_appearances:
if name not in self._character_names and name not in self.bakwas_chars:
self._character_names.append(name)
# Note: this is just our local index out of available teams; *not*
# the team-id!
self._selected_team_index: int = self.lobby.next_add_team
# 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
# it. This will give a persistent character for them between games
# and will distribute characters nicely if everyone is random.
self._random_color, self._random_highlight = (
get_player_profile_colors(None))
# 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
# list.
char_index_offset = app.lobby_random_char_index_offset
self._random_character_index = (
(sessionplayer.inputdevice.id + char_index_offset) %
len(self._character_names))
# Attempt to set an initial profile based on what was used previously
# for this input-device, etc.
self._profileindex = self._select_initial_profile()
self._profilename = self._profilenames[self._profileindex]
self._text_node = _ba.newnode('text',
delegate=self,
attrs={
'position': (-100, self._vpos),
'maxwidth': 190,
'shadow': 0.5,
'vr_depth': -20,
'h_align': 'left',
'v_align': 'center',
'v_attach': 'top'
})
animate(self._text_node, 'scale', {0: 0, 0.1: 1.0})
self.icon = _ba.newnode('image',
owner=self._text_node,
attrs={
'position': (-130, self._vpos + 20),
'mask_texture': self._mask_texture,
'vr_depth': -10,
'attach': 'topCenter'
})
animate_array(self.icon, 'scale', 2, {0: (0, 0), 0.1: (45, 45)})
# Set our initial name to '<choosing player>' in case anyone asks.
self._sessionplayer.setname(
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)
def _set_ready(self, ready: bool) -> None:
# pylint: disable=cyclic-import
from bastd.ui.profile import browser as pbrowser
from ba._general import Call
profilename = self._profilenames[self._profileindex]
# Handle '_edit' as a special case.
if profilename == '_edit' and ready:
with _ba.Context('ui'):
pbrowser.ProfileBrowserWindow(in_main_menu=False)
# Give their input-device UI ownership too
# (prevent someone else from snatching it in crowded games)
_ba.set_ui_input_device(self._sessionplayer.inputdevice)
return
if ready==False:
self._sessionplayer.assigninput(
InputType.LEFT_PRESS,
Call(self.handlemessage, ChangeMessage('team', -1)))
self._sessionplayer.assigninput(
InputType.RIGHT_PRESS,
Call(self.handlemessage, ChangeMessage('team', 1)))
self._sessionplayer.assigninput(
InputType.BOMB_PRESS,
Call(self.handlemessage, ChangeMessage('character', 1)))
self._sessionplayer.assigninput(
InputType.UP_PRESS,
Call(self.handlemessage, ChangeMessage('profileindex', -1)))
self._sessionplayer.assigninput(
InputType.DOWN_PRESS,
Call(self.handlemessage, ChangeMessage('profileindex', 1)))
self._sessionplayer.assigninput(
(InputType.JUMP_PRESS, InputType.PICK_UP_PRESS,
InputType.PUNCH_PRESS),
Call(self.handlemessage, ChangeMessage('ready', 1)))
self._ready = False
self._update_text()
self._sessionplayer.setname('untitled', real=False)
elif ready == True:
self.characterchooser=True
self._sessionplayer.assigninput(
(InputType.LEFT_PRESS, InputType.RIGHT_PRESS,
InputType.UP_PRESS, InputType.DOWN_PRESS,
InputType.JUMP_PRESS, InputType.BOMB_PRESS,
InputType.PICK_UP_PRESS), self._do_nothing)
self._sessionplayer.assigninput(
(InputType.UP_PRESS),Call(self.handlemessage,ChangeMessage('characterchooser',-1)))
self._sessionplayer.assigninput(
(InputType.DOWN_PRESS),Call(self.handlemessage,ChangeMessage('characterchooser',1)))
self._sessionplayer.assigninput(
(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.
input_device = self._sessionplayer.inputdevice
name = input_device.name
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
# to random; in that case we'll want to start picking up custom
# profiles if/when one is made so keep our setting cleared.
special = ('_random', '_edit', '__account__')
have_custom_profiles = any(p not in special
for p in self._profiles)
profilekey = name + ' ' + unique_id
if profilename == '_random' and not have_custom_profiles:
if profilekey in device_profiles:
del device_profiles[profilekey]
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.
_ba.getsession().handlemessage(PlayerReadyMessage(self))
def handlemessage(self, msg: Any) -> Any:
"""Standard generic message handler."""
if isinstance(msg, ChangeMessage):
self._handle_repeat_message_attack()
# If we've been removed from the lobby, ignore this stuff.
if self._dead:
print_error('chooser got ChangeMessage after dying')
return
if not self._text_node:
print_error('got ChangeMessage after nodes died')
return
if msg.what=='characterchooser':
_ba.playsound(self._click_sound)
# update our index in our local list of characters
self._character_index = ((self._character_index + msg.value) %
len(self._character_names))
self._update_text()
self._update_icon()
if msg.what == 'team':
sessionteams = self.lobby.sessionteams
if len(sessionteams) > 1:
_ba.playsound(self._swish_sound)
self._selected_team_index = (
(self._selected_team_index + msg.value) %
len(sessionteams))
self._update_text()
self.update_position()
self._update_icon()
elif msg.what == 'profileindex':
if len(self._profilenames) == 1:
# This should be pretty hard to hit now with
# automatic local accounts.
_ba.playsound(_ba.getsound('error'))
else:
# Pick the next player profile and assign our name
# and character based on that.
_ba.playsound(self._deek_sound)
self._profileindex = ((self._profileindex + msg.value) %
len(self._profilenames))
self.update_from_profile()
elif msg.what == 'character':
_ba.playsound(self._click_sound)
self.characterchooser=True
# update our index in our local list of characters
self._character_index = ((self._character_index + msg.value) %
len(self._character_names))
self._update_text()
self._update_icon()
elif msg.what == 'ready':
self._handle_ready_msg(msg.value)
def _update_text(self) -> None:
assert self._text_node is not None
if self._ready:
# Once we're ready, we've saved the name, so lets ask the system
# for it so we get appended numbers and stuff.
text = Lstr(value=self._sessionplayer.getname(full=True))
if self.characterchooser:
text = Lstr(value='${A}\n${B}',
subs=[('${A}', text),
('${B}', Lstr(value=""+self._character_names[self._character_index]))])
self._text_node.scale=0.8
else:
text = Lstr(value='${A} (${B})',
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
# Flash as we're coming in.
fin_color = _ba.safecolor(self.get_color()) + (1, )
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, {
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
class HeySmoothy(ba.Plugin):
def __init__(self):
_lobby.Chooser.__init__=__init__
_lobby.Chooser._set_ready=_set_ready
_lobby.Chooser._update_text=_update_text
_lobby.Chooser.handlemessage=handlemessage

View file

@ -0,0 +1,538 @@
# Released under the MIT License. See LICENSE for details.
'''
Character Builder/Maker by Mr.Smoothy
Plugin helps to mix character models and textures in interactive way.
Watch tutorial : https://www.youtube.com/c/HeySmoothy
Join discord: https://discord.gg/ucyaesh for help
https://github.com/imayushsaini/Bombsquad-Ballistica-Modded-Server/
> create team playlist and add character maker mini game
> Use export command to save character
> Character will be saved in CustomCharacter folder inside Bombsquad Mods folder
*Only one player in that mini game supported ...
Characters can be used offline or online
for online you need to share character file with server owners.
*For server owners:_
You might know what to do with that file,
Still ,
refer code after line 455 in this file , add it as a plugin to import characters from json file.
*For modders:-
You can add more models and texture , check line near 400 and add asset names , you can also modify sounds and icon in json file (optional) .
To share your character with friends ,
send them character .json file and tell them to put file in same location i.e Bombsquad/CustomCharacter or for PC appdata/Local/Bombsquad/Mods/CustomCharacter
this plugin should be installed on their device too
Dont forget to share your creativity with me ,
send your character screenshot discord: mr.smoothy#5824 https://discord.gg/ucyaesh
Register your character in above discord server , so other server owners can add your characters.
Released on 28 May 2021
Update 2 june : use import <character-name>
'''
# ba_meta require api 7
from __future__ import annotations
from typing import TYPE_CHECKING
import ba,_ba
from bastd.actor.playerspaz import PlayerSpaz
from bastd.actor.scoreboard import Scoreboard
if TYPE_CHECKING:
from typing import Any, Type, List, Dict, Tuple, Union, Sequence, Optional
import os,json
from bastd.actor.spazappearance import *
spazoutfit={
"color_mask":"neoSpazColorMask",
"color_texture":"neoSpazColor",
"head":"neoSpazHead",
"hand":"neoSpazHand",
"torso":"neoSpazTorso",
"pelvis":"neoSpazTorso",
"upper_arm":"neoSpazUpperArm",
"forearm":"neoSpazForeArm",
"upper_leg":"neoSpazUpperLeg",
"lower_leg":"neoSpazLowerLeg",
"toes_model":"neoSpazToes",
"jump_sounds":['spazJump01', 'spazJump02', 'spazJump03', 'spazJump04'],
"attack_sounds":['spazAttack01', 'spazAttack02', 'spazAttack03', 'spazAttack04'],
"impact_sounds":['spazImpact01', 'spazImpact02', 'spazImpact03', 'spazImpact04'],
"death_sounds":['spazDeath01'],
"pickup_sounds":['spazPickup01'],
"fall_sounds":['spazFall01'],
"icon_texture":"neoSpazIcon",
"icon_mask_texture":"neoSpazIconColorMask",
"style":"spaz"
}
character=None
class Player(ba.Player['Team']):
"""Our player type for this game."""
class Team(ba.Team[Player]):
"""Our team type for this game."""
def __init__(self) -> None:
self.score = 0
# ba_meta export game
class CharacterBuilder(ba.TeamGameActivity[Player, Team]):
"""A game type based on acquiring kills."""
name = 'Character Maker'
description = 'Create your own custom Characters'
# Print messages when players die since it matters here.
announce_player_deaths = True
@classmethod
def get_available_settings(
cls, sessiontype: Type[ba.Session]) -> List[ba.Setting]:
settings = [
ba.IntSetting(
'Kills to Win Per Player',
min_value=1,
default=5,
increment=1,
),
ba.IntChoiceSetting(
'Time Limit',
choices=[
('None', 0),
('1 Minute', 60),
('2 Minutes', 120),
('5 Minutes', 300),
('10 Minutes', 600),
('20 Minutes', 1200),
],
default=0,
),
ba.FloatChoiceSetting(
'Respawn Times',
choices=[
('Shorter', 0.25),
('Short', 0.5),
('Normal', 1.0),
('Long', 2.0),
('Longer', 4.0),
],
default=1.0,
),
ba.BoolSetting('Epic Mode', default=False),
]
if issubclass(sessiontype, ba.FreeForAllSession):
settings.append(
ba.BoolSetting('Allow Negative Scores', default=False))
return settings
@classmethod
def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool:
return (issubclass(sessiontype, ba.DualTeamSession)
or issubclass(sessiontype, ba.FreeForAllSession))
@classmethod
def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]:
return ['Rampage']
def __init__(self, settings: dict):
super().__init__(settings)
self.initdic()
_ba.set_party_icon_always_visible(True)
self._score_to_win: Optional[int] = None
self._dingsound = ba.getsound('dingSmall')
self._epic_mode = bool(settings['Epic Mode'])
self._kills_to_win_per_player = int(
settings['Kills to Win Per Player'])
self._time_limit = float(settings['Time Limit'])
self._allow_negative_scores = bool(
settings.get('Allow Negative Scores', False))
self.bodyindex=0
self.modelindex=0
self.youtube= ba.newnode(
'text',
attrs={
'text': "youtube.com/c/HeySmoothy",
'in_world': True,
'scale': 0.02,
'color': (1, 0, 0, 0.4),
'h_align': 'center',
'position': (0,4,-1.9)
})
self.discordservere= ba.newnode(
'text',
attrs={
'text': "discord.gg/ucyaesh",
'in_world': True,
'scale': 0.02,
'color': (0.12, 0.3, 0.6, 0.4),
'h_align': 'center',
'position': (-3,2.7,-1.9)
})
# self.discord= ba.newnode(
# 'text',
# attrs={
# 'text': "mr.smoothy#5824",
# 'in_world': True,
# 'scale': 0.02,
# 'color': (01.2, 0.3, 0.7, 0.4),
# 'h_align': 'center',
# 'position': (4,2.7,-1.9)
# })
# Base class overrides.
self.bodypart= ba.newnode(
'text',
attrs={
'text': "<Choose Body Part>",
'in_world': True,
'scale': 0.02,
'color': (1, 1, 0, 1),
'h_align': 'center',
'position': (-4,6,-4)
})
self.newmodel = ba.newnode(
'text',
attrs={
'text': "<Choose model/tex>",
'in_world': True,
'scale': 0.02,
'color': (1, 1, 0, 1),
'h_align': 'center',
'position': (6,6,-4)
})
self.slow_motion = self._epic_mode
self.default_music = (ba.MusicType.EPIC if self._epic_mode else
ba.MusicType.TO_THE_DEATH)
def get_instance_description(self) -> Union[str, Sequence]:
return ''
def get_instance_description_short(self) -> Union[str, Sequence]:
return ''
def on_team_join(self, team: Team) -> None:
if self.has_begun():
pass
def on_begin(self) -> None:
super().on_begin()
def nextBodyPart(self):
self.bodyindex =(self.bodyindex+1)%len(self.dic.keys())
self.bodypart.delete()
PART=list(self.dic.keys())[self.bodyindex]
self.bodypart=ba.newnode(
'text',
attrs={
'text': PART,
'in_world': True,
'scale': 0.02,
'color': (1, 1, 1, 1),
'h_align': 'center',
'position': (-4,6,-4)
})
def prevBodyPart(self):
self.bodyindex =(self.bodyindex-1)%len(self.dic.keys())
self.bodypart.delete()
PART=list(self.dic.keys())[self.bodyindex]
self.bodypart=ba.newnode(
'text',
attrs={
'text': PART,
'in_world': True,
'scale': 0.02,
'color': (1, 1, 1, 1),
'h_align': 'center',
'position': (-4,6,-4)
})
def nextModel(self):
self.newmodel.delete()
PART=list(self.dic.keys())[self.bodyindex]
self.modelindex =(self.modelindex+1)%len(self.dic[PART])
model=self.dic[PART][self.modelindex]
self.newmodel=ba.newnode(
'text',
attrs={
'text': model,
'in_world': True,
'scale': 0.02,
'color': (1, 1, 1, 1),
'h_align': 'center',
'position': (6,6,-4)
})
self.setModel(PART,model)
def prevModel(self):
self.newmodel.delete()
PART=list(self.dic.keys())[self.bodyindex]
self.modelindex =(self.modelindex-1)%len(self.dic[PART])
model=self.dic[PART][self.modelindex]
self.newmodel=ba.newnode(
'text',
attrs={
'text': model,
'in_world': True,
'scale': 0.02,
'color': (1, 1, 1, 1),
'h_align': 'center',
'position': (6,6,-4)
})
self.setModel(PART,model)
def setModel(self,bodypart,modelname):
global spazoutfit
body=_ba.get_foreground_host_activity().players[0].actor.node
if bodypart=='head':
body.head_model=ba.getmodel(modelname)
elif bodypart=='torso':
body.torso_model=ba.getmodel(modelname)
elif bodypart=='pelvis':
body.pelvis_model=ba.getmodel(modelname)
elif bodypart=='upper_arm':
body.upper_arm_model=ba.getmodel(modelname)
elif bodypart=='forearm':
body.forearm_model=ba.getmodel(modelname)
elif bodypart=='hand':
body.hand_model=ba.getmodel(modelname)
elif bodypart=='upper_leg':
body.upper_leg_model=ba.getmodel(modelname)
elif bodypart=='lower_leg':
body.lower_leg_model=ba.getmodel(modelname)
elif bodypart=='toes_model':
body.toes_model=ba.getmodel(modelname)
elif bodypart=='style':
body.style=modelname
elif bodypart=='color_texture':
body.color_texture=ba.gettexture(modelname)
elif bodypart=='color_mask':
body.color_mask_texture=ba.gettexture(modelname)
spazoutfit[bodypart]=modelname
def spawn_player(self, player: Player) -> ba.Actor:
global character
if character!=None:
player.character=character
self.setcurrentcharacter(player.character)
spaz = self.spawn_player_spaz(player)
# Let's reconnect this player's controls to this
# spaz but *without* the ability to attack or pick stuff up.
spaz.connect_controls_to_player(enable_punch=False,
enable_jump=False,
enable_bomb=False,
enable_pickup=False)
intp = ba.InputType
player.assigninput(intp.JUMP_PRESS, self.nextBodyPart)
player.assigninput(intp.PICK_UP_PRESS, self.prevBodyPart)
player.assigninput(intp.PUNCH_PRESS, self.nextModel)
player.assigninput(intp.BOMB_PRESS, self.prevModel)
# Also lets have them make some noise when they die.
spaz.play_big_death_sound = True
return spaz
def handlemessage(self, msg: Any) -> Any:
if isinstance(msg, ba.PlayerDiedMessage):
# Augment standard behavior.
super().handlemessage(msg)
player = msg.getplayer(Player)
self.respawn_player(player)
else:
return super().handlemessage(msg)
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 _update_scoreboard(self) -> None:
for team in self.teams:
self._scoreboard.set_team_value(team, team.score,
self._score_to_win)
def end_game(self) -> None:
results = ba.GameResults()
for team in self.teams:
results.set_team_score(team, team.score)
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"]
}
chars=["neoSpaz","zoe","ninja","kronk","mel","jack","santa","frosty","bones","bear","penguin","ali","cyborg","agent","wizard","pixie","bunny"]
for char in chars:
self.dic["head"].append(char+"Head")
self.dic["hand"].append(char+"Hand")
self.dic["torso"].append(char+"Torso")
if char not in ['mel',"jack","santa"]:
self.dic["pelvis"].append(char+"Pelvis")
self.dic["upper_arm"].append(char+"UpperArm")
self.dic["forearm"].append(char+"ForeArm")
self.dic["upper_leg"].append(char+"UpperLeg")
self.dic["lower_leg"].append(char+"LowerLeg")
self.dic["toes_model"].append(char+"Toes")
self.dic["color_mask"].append(char+"ColorMask")
if char !="kronk":
self.dic["color_texture"].append(char+"Color")
cm=_ba.chatmessage
def _new_chatmessage(msg):
if msg.split(" ")[0]=="export":
if len(msg.split(" "))>1:
savecharacter(msg.split(" ")[1])
else:
_ba.screenmessage("Enter name of character")
elif msg.split(" ")[0]=="import":
importcharacter(msg[7:])
else:
cm(msg)
_ba.chatmessage=_new_chatmessage
def savecharacter(name):
path=os.path.join(_ba.env()["python_directory_user"],"CustomCharacters" + os.sep)
if not os.path.isdir(path):
os.makedirs(path)
if _ba.get_foreground_host_activity()!=None:
with open(path+name+".json",'w') as f:
json.dump(spazoutfit,f,indent=4)
registercharacter(name,spazoutfit)
ba.playsound(ba.getsound("gunCocking"))
_ba.screenmessage("Character Saved")
else:
_ba.screenmessage("Works offline with Character Maker")
def importcharacter(name):
if name in ba.app.spaz_appearances:
global character
character=name
try:
_ba.get_foreground_host_activity().players[0].actor.node.handlemessage(ba.DieMessage())
_ba.screenmessage("Imported")
except:
_ba.screenmessage("works offline with character maker")
else:
_ba.screenmessage("invalid name check typo \n name is case sensitive")
def registercharacter(name,char):
t = Appearance(name.split(".")[0])
t.color_texture = char['color_texture']
t.color_mask_texture = char['color_mask']
t.default_color = (0.6, 0.6, 0.6)
t.default_highlight = (0, 1, 0)
t.icon_texture = char['icon_texture']
t.icon_mask_texture = char['icon_mask_texture']
t.head_model = char['head']
t.torso_model = char['torso']
t.pelvis_model = char['pelvis']
t.upper_arm_model = char['upper_arm']
t.forearm_model = char['forearm']
t.hand_model = char['hand']
t.upper_leg_model = char['upper_leg']
t.lower_leg_model = char['lower_leg']
t.toes_model = char['toes_model']
t.jump_sounds = char['jump_sounds']
t.attack_sounds = char['attack_sounds']
t.impact_sounds = char['impact_sounds']
t.death_sounds = char['death_sounds']
t.pickup_sounds = char['pickup_sounds']
t.fall_sounds = char['fall_sounds']
t.style = char['style']
# ba_meta export plugin
class HeySmoothy(ba.Plugin):
def __init__(self):
_ba.set_party_icon_always_visible(True)
path=os.path.join(_ba.env()["python_directory_user"],"CustomCharacters" + os.sep)
if not os.path.isdir(path):
os.makedirs(path)
files=os.listdir(path)
for file in files:
with open(path+file, 'r') as f:
character = json.load(f)
registercharacter(file,character)