From 6e5964a01bab0c81ac196206a741164469c630bf Mon Sep 17 00:00:00 2001 From: Loup <90267658+Loup-Garou911XD@users.noreply.github.com> Date: Mon, 10 Oct 2022 13:53:11 +0530 Subject: [PATCH 01/55] Made variables global Made Ldefault,Udefault variables global in new_chat function --- plugins/utilities/mood_light.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/utilities/mood_light.py b/plugins/utilities/mood_light.py index 0a0b827..8ed9801 100644 --- a/plugins/utilities/mood_light.py +++ b/plugins/utilities/mood_light.py @@ -257,6 +257,7 @@ def new_chat_message(msg: Union[str, ba.Lstr], clients: Sequence[int] = None, se old_fcm(msg, clients, sender_override) if msg == 'ml': try: + global Ldefault,Udefault Ldefault, Udefault = ba.app.config.get("moodlightingSettings") SettingWindow() cprint("Mood light settings opened") From 7f7e2fd0a4cc81739293014f611115fde415951f Mon Sep 17 00:00:00 2001 From: Loup-Garou911XD Date: Mon, 10 Oct 2022 08:23:32 +0000 Subject: [PATCH 02/55] [ci] auto-format --- plugins/utilities/mood_light.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/utilities/mood_light.py b/plugins/utilities/mood_light.py index 8ed9801..df1024f 100644 --- a/plugins/utilities/mood_light.py +++ b/plugins/utilities/mood_light.py @@ -257,7 +257,7 @@ def new_chat_message(msg: Union[str, ba.Lstr], clients: Sequence[int] = None, se old_fcm(msg, clients, sender_override) if msg == 'ml': try: - global Ldefault,Udefault + global Ldefault, Udefault Ldefault, Udefault = ba.app.config.get("moodlightingSettings") SettingWindow() cprint("Mood light settings opened") From e1e5097ebbde9899f5296e84397b23daa31f0347 Mon Sep 17 00:00:00 2001 From: Loup <90267658+Loup-Garou911XD@users.noreply.github.com> Date: Fri, 28 Oct 2022 18:21:24 +0530 Subject: [PATCH 03/55] Added has_settings_ui() and show_settings_ui() --- plugins/utilities/mood_light.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/plugins/utilities/mood_light.py b/plugins/utilities/mood_light.py index df1024f..3ba0b30 100644 --- a/plugins/utilities/mood_light.py +++ b/plugins/utilities/mood_light.py @@ -4,14 +4,13 @@ from typing import TYPE_CHECKING, cast if TYPE_CHECKING: from typing import Any, Sequence, Callable, List, Dict, Tuple, Optional, Union +import random import ba import _ba -import random from ba._map import Map from bastd import mainmenu from bastd.ui.party import PartyWindow from bastd.gameutils import SharedObjects -from time import sleep """mood light plugin by ʟօʊքɢǟʀօʊ type ml in chat or use plugin manager to open settings""" @@ -257,12 +256,12 @@ def new_chat_message(msg: Union[str, ba.Lstr], clients: Sequence[int] = None, se old_fcm(msg, clients, sender_override) if msg == 'ml': try: - global Ldefault, Udefault + global Ldefault,Udefault Ldefault, Udefault = ba.app.config.get("moodlightingSettings") SettingWindow() cprint("Mood light settings opened") except Exception as err: - Print(err) + Print(err,"-from new_chat_message") old_fcm = _ba.chatmessage @@ -279,9 +278,12 @@ class moodlight(ba.Plugin): def on_app_running(self): _ba.show_progress_bar() - - def on_plugin_manager_prompt(self): # called by plugin manager + + def has_settings_ui(self): + return True + def show_settings_ui(self,button): SettingWindow() + def _new_init(self, vr_overlay_offset: Optional[Sequence[float]] = None) -> None: self._old_init(vr_overlay_offset) From b8186247786b05a0eda7efdcbbe832e7c7a3bdb9 Mon Sep 17 00:00:00 2001 From: Loup-Garou911XD Date: Fri, 28 Oct 2022 12:51:45 +0000 Subject: [PATCH 04/55] [ci] auto-format --- plugins/utilities/mood_light.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/utilities/mood_light.py b/plugins/utilities/mood_light.py index 3ba0b30..733adef 100644 --- a/plugins/utilities/mood_light.py +++ b/plugins/utilities/mood_light.py @@ -256,12 +256,12 @@ def new_chat_message(msg: Union[str, ba.Lstr], clients: Sequence[int] = None, se old_fcm(msg, clients, sender_override) if msg == 'ml': try: - global Ldefault,Udefault + global Ldefault, Udefault Ldefault, Udefault = ba.app.config.get("moodlightingSettings") SettingWindow() cprint("Mood light settings opened") except Exception as err: - Print(err,"-from new_chat_message") + Print(err, "-from new_chat_message") old_fcm = _ba.chatmessage @@ -278,12 +278,12 @@ class moodlight(ba.Plugin): def on_app_running(self): _ba.show_progress_bar() - + def has_settings_ui(self): return True - def show_settings_ui(self,button): + + def show_settings_ui(self, button): SettingWindow() - def _new_init(self, vr_overlay_offset: Optional[Sequence[float]] = None) -> None: self._old_init(vr_overlay_offset) From 1a56b577ff98221df56df25f7b79c72fa1a908f8 Mon Sep 17 00:00:00 2001 From: Loup <90267658+Loup-Garou911XD@users.noreply.github.com> Date: Fri, 28 Oct 2022 18:33:06 +0530 Subject: [PATCH 05/55] Changed version to 1.2.1 --- plugins/utilities.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/utilities.json b/plugins/utilities.json index 63413f6..d62682b 100644 --- a/plugins/utilities.json +++ b/plugins/utilities.json @@ -14,6 +14,7 @@ } ], "versions": { + "1.2.1": null, "1.2.0": { "api_version": 7, "commit_sha": "d838115", @@ -298,4 +299,4 @@ } } } -} \ No newline at end of file +} From cb4d34bec48882272cd8532725060eca867d4f4e Mon Sep 17 00:00:00 2001 From: Loup-Garou911XD Date: Fri, 28 Oct 2022 13:03:30 +0000 Subject: [PATCH 06/55] [ci] apply-version-metadata --- plugins/utilities.json | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/plugins/utilities.json b/plugins/utilities.json index d62682b..d3c9ac1 100644 --- a/plugins/utilities.json +++ b/plugins/utilities.json @@ -14,7 +14,12 @@ } ], "versions": { - "1.2.1": null, + "1.2.1": { + "api_version": 7, + "commit_sha": "1a56b57", + "released_on": "28-10-2022", + "md5sum": "81414a2b497da3d2340a4d7eb004336c" + }, "1.2.0": { "api_version": 7, "commit_sha": "d838115", @@ -299,4 +304,4 @@ } } } -} +} \ No newline at end of file From 85304770d332d58e48f500dd6d71a9edb75f4176 Mon Sep 17 00:00:00 2001 From: Loup <90267658+Loup-Garou911XD@users.noreply.github.com> Date: Thu, 3 Nov 2022 22:37:45 +0530 Subject: [PATCH 07/55] Add files via upload --- plugins/utilities/CustomDeath.py | 38 ++ plugins/utilities/MaxPlayers.py | 356 ++++++++++++++++++ plugins/utilities/QuickCustonGame.py | 373 +++++++++++++++++++ plugins/utilities/RandomColors.py | 48 +++ plugins/utilities/chat_cmd.py | 531 +++++++++++++++++++++++++++ 5 files changed, 1346 insertions(+) create mode 100644 plugins/utilities/CustomDeath.py create mode 100644 plugins/utilities/MaxPlayers.py create mode 100644 plugins/utilities/QuickCustonGame.py create mode 100644 plugins/utilities/RandomColors.py create mode 100644 plugins/utilities/chat_cmd.py diff --git a/plugins/utilities/CustomDeath.py b/plugins/utilities/CustomDeath.py new file mode 100644 index 0000000..809db73 --- /dev/null +++ b/plugins/utilities/CustomDeath.py @@ -0,0 +1,38 @@ +# ba_meta require api 7 +# (see https://ballistica.net/wiki/meta-tag-system) + +from __future__ import annotations + +from typing import TYPE_CHECKING + +import ba +from bastd.actor.spaz import Spaz + +if TYPE_CHECKING: + from typing import Any + + +Spaz.oldhandlemessage = Spaz.handlemessage +def handlemessage(self, msg: Any) -> Any: + if isinstance(msg, ba.DieMessage): + if self.node: + self.node.color_texture = ba.gettexture('bonesColor') + self.node.color_mask_texture = ba.gettexture('bonesColorMask') + self.node.head_model = ba.getmodel('bonesHead') + self.node.torso_model = ba.getmodel('bonesTorso') + self.node.pelvis_model = ba.getmodel('bonesPelvis') + self.node.upper_arm_model = ba.getmodel('bonesUpperArm') + self.node.forearm_model = ba.getmodel('bonesForeArm') + self.node.hand_model = ba.getmodel('bonesHand') + self.node.upper_leg_model = ba.getmodel('bonesUpperLeg') + self.node.lower_leg_model = ba.getmodel('bonesLowerLeg') + self.node.toes_model = ba.getmodel('bonesToes') + self.node.style = 'bones' + self.oldhandlemessage(msg) + else: + return self.oldhandlemessage(msg) + + +# ba_meta export plugin +class CustomDeath(ba.Plugin): + Spaz.handlemessage = handlemessage diff --git a/plugins/utilities/MaxPlayers.py b/plugins/utilities/MaxPlayers.py new file mode 100644 index 0000000..dce5ec0 --- /dev/null +++ b/plugins/utilities/MaxPlayers.py @@ -0,0 +1,356 @@ +"""===========MAX_PLAYERS===========""" + +# ba_meta require api 7 +# (see https://ballistica.net/wiki/meta-tag-system) + +from __future__ import annotations +from typing import TYPE_CHECKING + +import ba +import _ba +from ba._session import Session +from ba._coopsession import CoopSession, TEAM_COLORS, TEAM_NAMES +from ba._multiteamsession import MultiTeamSession +from bastd.ui.gather import GatherWindow +from bastd.ui.popup import PopupWindow + +if TYPE_CHECKING: + from typing import List, Any, Optional, Sequence + + +cfg = ba.app.config +cmp = {'coop_max_players': 4, + 'teams_max_players': 8, + 'ffa_max_players': 8} + +lang = ba.app.lang.language +if lang == 'Spanish': + title_text = 'Máximo de Jugadores' + title_short_text = 'Jugadores' + coop_text = 'Cooperativo' + teams_text = 'Equipos' + ffa_text = 'Todos Contra Todos' +else: + title_text = 'Max Players' + title_short_text = 'Players' + coop_text = 'Co-op' + teams_text = 'Teams' + ffa_text = 'FFA' + +class ConfigNumberEdit: + + def __init__(self, + parent: ba.Widget, + position: Tuple[float, float], + value: int, + config: str, + text: str): + self._increment = 1 + self._minval = 1 + self._maxval = 100 + self._value = value + self._config = config + + textscale = 1.0 + self.nametext = ba.textwidget( + parent=parent, + position=(position[0], position[1]), + size=(100, 30), + text=text, + maxwidth=150, + color=(0.8, 0.8, 0.8, 1.0), + h_align='left', + v_align='center', + scale=textscale) + self.valuetext = ba.textwidget( + parent=parent, + position=(position[0]+150, position[1]), + size=(60, 28), + editable=False, + color=(0.3, 1.0, 0.3, 1.0), + h_align='right', + v_align='center', + text=str(value), + padding=2) + self.minusbutton = ba.buttonwidget( + parent=parent, + position=(position[0]+240, position[1]), + size=(28, 28), + label='-', + autoselect=True, + on_activate_call=ba.Call(self._down), + repeat=True) + self.plusbutton = ba.buttonwidget( + parent=parent, + position=(position[0]+290, position[1]), + size=(28, 28), + label='+', + autoselect=True, + on_activate_call=ba.Call(self._up), + repeat=True) + + def _up(self) -> None: + self._value = min(self._maxval, self._value + self._increment) + self._update_display() + + def _down(self) -> None: + self._value = max(self._minval, self._value - self._increment) + self._update_display() + + def _update_display(self) -> None: + ba.textwidget(edit=self.valuetext, text=str(self._value)) + cfg['Config Max Players'][self._config] = self._value + cfg.apply_and_commit() + +class SettingsMaxPlayers(PopupWindow): + + def __init__(self): + # pylint: disable=too-many-locals + uiscale = ba.app.ui.uiscale + self._transitioning_out = False + self._width = 400 + self._height = 220 + bg_color = (0.5, 0.4, 0.6) + + # creates our _root_widget + PopupWindow.__init__(self, + position=(0.0, 0.0), + size=(self._width, self._height), + scale=1.2, + bg_color=bg_color) + + self._cancel_button = ba.buttonwidget( + parent=self.root_widget, + position=(25, self._height - 40), + size=(50, 50), + scale=0.58, + label='', + color=bg_color, + on_activate_call=self._on_cancel_press, + autoselect=True, + icon=ba.gettexture('crossOut'), + iconscale=1.2) + ba.containerwidget(edit=self.root_widget, + cancel_button=self._cancel_button) + + ba.textwidget( + parent=self.root_widget, + position=(self._width * 0.5, self._height - 30), + size=(0, 0), + h_align='center', + v_align='center', + scale=0.8, + text=title_text, + maxwidth=200, + color=ba.app.ui.title_color) + + posx = 33 + posy = self._height + + # co-op + ConfigNumberEdit(parent=self.root_widget, + position=(posx, posy*0.6), + value=cfg['Config Max Players']['coop_max_players'], + config='coop_max_players', + text=coop_text) + + # teams + ConfigNumberEdit(parent=self.root_widget, + position=(posx, posy*0.38), + value=cfg['Config Max Players']['teams_max_players'], + config='teams_max_players', + text=teams_text) + + # ffa + ConfigNumberEdit(parent=self.root_widget, + position=(posx, posy*0.16), + value=cfg['Config Max Players']['ffa_max_players'], + config='ffa_max_players', + text=ffa_text) + + def _on_cancel_press(self) -> None: + self._transition_out() + + def _transition_out(self) -> None: + if not self._transitioning_out: + self._transitioning_out = True + ba.containerwidget(edit=self.root_widget, transition='out_scale') + + def on_popup_cancel(self) -> None: + ba.playsound(ba.getsound('swish')) + self._transition_out() + +def __init__(self) -> None: + """Instantiate a co-op mode session.""" + # pylint: disable=cyclic-import + from ba._campaign import getcampaign + from bastd.activity.coopjoin import CoopJoinActivity + + _ba.increment_analytics_count('Co-op session start') + app = _ba.app + + # If they passed in explicit min/max, honor that. + # Otherwise defer to user overrides or defaults. + if 'min_players' in app.coop_session_args: + min_players = app.coop_session_args['min_players'] + else: + min_players = 1 + if 'max_players' in app.coop_session_args: + max_players = app.coop_session_args['max_players'] + else: + max_players = app.config.get( + 'Coop Game Max Players', + cfg['Config Max Players']['coop_max_players']) + + # print('FIXME: COOP SESSION WOULD CALC DEPS.') + depsets: Sequence[ba.DependencySet] = [] + + Session.__init__(self, + depsets, + team_names=TEAM_NAMES, + team_colors=TEAM_COLORS, + min_players=min_players, + max_players=max_players) + + # Tournament-ID if we correspond to a co-op tournament (otherwise None) + self.tournament_id: Optional[str] = ( + app.coop_session_args.get('tournament_id')) + + self.campaign = getcampaign(app.coop_session_args['campaign']) + self.campaign_level_name: str = app.coop_session_args['level'] + + self._ran_tutorial_activity = False + self._tutorial_activity: Optional[ba.Activity] = None + self._custom_menu_ui: List[Dict[str, Any]] = [] + + # Start our joining screen. + self.setactivity(_ba.newactivity(CoopJoinActivity)) + + self._next_game_instance: Optional[ba.GameActivity] = None + self._next_game_level_name: Optional[str] = None + self._update_on_deck_game_instances() + +def get_max_players(self) -> int: + """Return max number of ba.Players allowed to join the game at once.""" + if self.use_teams: + return _ba.app.config.get( + 'Team Game Max Players', + cfg['Config Max Players']['teams_max_players']) + return _ba.app.config.get( + 'Free-for-All Max Players', + cfg['Config Max Players']['ffa_max_players']) + +GatherWindow.__old_init__ = GatherWindow.__init__ +def __gather_init__(self, + transition: Optional[str] = 'in_right', + origin_widget: ba.Widget = None): + self.__old_init__(transition, origin_widget) + def _do_max_players(): + SettingsMaxPlayers() + self._max_players_button = ba.buttonwidget( + parent=self._root_widget, + position=(self._width*0.72, self._height*0.91), + size=(220, 60), + scale=1.0, + color=(0.6, 0.0, 0.9), + icon=ba.gettexture('usersButton'), + iconscale=1.5, + autoselect=True, + label=title_short_text, + button_type='regular', + on_activate_call=_do_max_players) + +def _save_state(self) -> None: + try: + for tab in self._tabs.values(): + tab.save_state() + + sel = self._root_widget.get_selected_child() + selected_tab_ids = [ + tab_id for tab_id, tab in self._tab_row.tabs.items() + if sel == tab.button + ] + if sel == self._back_button: + sel_name = 'Back' + elif sel == self._max_players_button: + sel_name = 'Max Players' + elif selected_tab_ids: + assert len(selected_tab_ids) == 1 + sel_name = f'Tab:{selected_tab_ids[0].value}' + elif sel == self._tab_container: + sel_name = 'TabContainer' + else: + raise ValueError(f'unrecognized selection: \'{sel}\'') + ba.app.ui.window_states[type(self)] = { + 'sel_name': sel_name, + } + except Exception: + ba.print_exception(f'Error saving state for {self}.') + +def _restore_state(self) -> None: + from efro.util import enum_by_value + try: + for tab in self._tabs.values(): + tab.restore_state() + + sel: Optional[ba.Widget] + winstate = ba.app.ui.window_states.get(type(self), {}) + sel_name = winstate.get('sel_name', None) + assert isinstance(sel_name, (str, type(None))) + current_tab = self.TabID.ABOUT + gather_tab_val = ba.app.config.get('Gather Tab') + try: + stored_tab = enum_by_value(self.TabID, gather_tab_val) + if stored_tab in self._tab_row.tabs: + current_tab = stored_tab + except ValueError: + pass + self._set_tab(current_tab) + if sel_name == 'Back': + sel = self._back_button + elif sel_name == 'Max Players': + sel = self._back_button + elif sel_name == 'TabContainer': + sel = self._tab_container + elif isinstance(sel_name, str) and sel_name.startswith('Tab:'): + try: + sel_tab_id = enum_by_value(self.TabID, + sel_name.split(':')[-1]) + except ValueError: + sel_tab_id = self.TabID.ABOUT + sel = self._tab_row.tabs[sel_tab_id].button + else: + sel = self._tab_row.tabs[current_tab].button + ba.containerwidget(edit=self._root_widget, selected_child=sel) + except Exception: + ba.print_exception('Error restoring gather-win state.') + +# ba_meta export plugin +class MaxPlayersPlugin(ba.Plugin): + + def has_settings_ui(self) -> bool: + return True + + def show_settings_ui(self, source_widget: ba.Widget | None) -> None: + SettingsMaxPlayers() + + if 'Config Max Players' in ba.app.config: + old_config = ba.app.config['Config Max Players'] + for setting in cmp: + if setting not in old_config: + ba.app.config['Config Max Players'].update({setting:cmp[setting]}) + remove_list = [] + for setting in old_config: + if setting not in cmp: + remove_list.append(setting) + for element in remove_list: + ba.app.config['Config Max Players'].pop(element) + else: + ba.app.config['Config Max Players'] = cmp + ba.app.config.apply_and_commit() + + CoopSession.__init__ = __init__ + MultiTeamSession.get_max_players = get_max_players + GatherWindow.__init__ = __gather_init__ + GatherWindow._save_state = _save_state + GatherWindow._restore_state = _restore_state diff --git a/plugins/utilities/QuickCustonGame.py b/plugins/utilities/QuickCustonGame.py new file mode 100644 index 0000000..dcc93c4 --- /dev/null +++ b/plugins/utilities/QuickCustonGame.py @@ -0,0 +1,373 @@ +# ba_meta require api 7 +# (see https://ballistica.net/wiki/meta-tag-system) + +from __future__ import annotations + +from typing import TYPE_CHECKING + +import ba +import _ba +from bastd.ui.play import PlayWindow +from bastd.ui.playlist.addgame import PlaylistAddGameWindow +from ba._freeforallsession import FreeForAllSession +from bastd.activity.multiteamjoin import MultiTeamJoinActivity + +if TYPE_CHECKING: + pass + + +lang = ba.app.lang.language + +if lang == 'Spanish': + custom_txt = 'personalizar...' +else: + custom_txt = 'custom...' + + +if 'quick_game_button' in ba.app.config: + config = ba.app.config['quick_game_button'] +else: + config = {'selected': None, 'config': None} + ba.app.config['quick_game_button'] = config + ba.app.config.commit() + +def start_game(session: ba.Session, fadeout: bool = True): + def callback(): + if fadeout: + _ba.unlock_all_input() + try: + _ba.new_host_session(session) + except Exception: + from bastd import mainmenu + ba.print_exception('exception running session', session) + + # Drop back into a main menu session. + _ba.new_host_session(mainmenu.MainMenuSession) + + if fadeout: + _ba.fade_screen(False, time=0.25, endcall=callback) + _ba.lock_all_input() + else: + callback() + +class SimplePlaylist: + + def __init__(self, + settings: dict, + gametype: type[ba.GameActivity]): + self.settings = settings + self.gametype = gametype + + def pull_next(self) -> None: + if 'map' not in self.settings['settings']: + settings = dict( + map=self.settings['map'], **self.settings['settings']) + else: + settings = self.settings['settings'] + return dict(resolved_type=self.gametype, settings=settings) + +class CustomSession(FreeForAllSession): + + def __init__(self, *args, **kwargs): + # pylint: disable=cyclic-import + self.use_teams = False + self._tutorial_activity_instance = None + ba.Session.__init__(self, depsets=[], + team_names=None, + team_colors=None, + min_players=1, + max_players=self.get_max_players()) + + self._series_length = 1 + self._ffa_series_length = 1 + + # Which game activity we're on. + self._game_number = 0 + self._playlist = SimplePlaylist(self._config, self._gametype) + config['selected'] = self._gametype.__name__ + config['config'] = self._config + ba.app.config.commit() + + # Get a game on deck ready to go. + self._current_game_spec: Optional[Dict[str, Any]] = None + self._next_game_spec: Dict[str, Any] = self._playlist.pull_next() + self._next_game: Type[ba.GameActivity] = ( + self._next_game_spec['resolved_type']) + + # Go ahead and instantiate the next game we'll + # use so it has lots of time to load. + self._instantiate_next_game() + + # Start in our custom join screen. + self.setactivity(_ba.newactivity(MultiTeamJoinActivity)) + + +class SelectGameWindow(PlaylistAddGameWindow): + + def __init__(self, transition: str = 'in_right'): + class EditController: + _sessiontype = ba.FreeForAllSession + + def get_session_type(self) -> Type[ba.Session]: + return self._sessiontype + + self._editcontroller = EditController() + self._r = 'addGameWindow' + uiscale = ba.app.ui.uiscale + self._width = 750 if uiscale is ba.UIScale.SMALL else 650 + x_inset = 50 if uiscale is ba.UIScale.SMALL else 0 + self._height = (346 if uiscale is ba.UIScale.SMALL else + 380 if uiscale is ba.UIScale.MEDIUM else 440) + top_extra = 30 if uiscale is ba.UIScale.SMALL else 20 + self._scroll_width = 210 + + self._root_widget = ba.containerwidget( + size=(self._width, self._height + top_extra), + transition=transition, + scale=(2.17 if uiscale is ba.UIScale.SMALL else + 1.5 if uiscale is ba.UIScale.MEDIUM else 1.0), + stack_offset=(0, 1) if uiscale is ba.UIScale.SMALL else (0, 0)) + + self._back_button = ba.buttonwidget(parent=self._root_widget, + position=(58 + x_inset, + self._height - 53), + size=(165, 70), + scale=0.75, + text_scale=1.2, + label=ba.Lstr(resource='backText'), + autoselect=True, + button_type='back', + on_activate_call=self._back) + self._select_button = select_button = ba.buttonwidget( + parent=self._root_widget, + position=(self._width - (172 + x_inset), self._height - 50), + autoselect=True, + size=(160, 60), + scale=0.75, + text_scale=1.2, + label=ba.Lstr(resource='selectText'), + on_activate_call=self._add) + + if ba.app.ui.use_toolbars: + ba.widget(edit=select_button, + right_widget=_ba.get_special_widget('party_button')) + + ba.textwidget(parent=self._root_widget, + position=(self._width * 0.5, self._height - 28), + size=(0, 0), + scale=1.0, + text=ba.Lstr(resource=self._r + '.titleText'), + h_align='center', + color=ba.app.ui.title_color, + maxwidth=250, + v_align='center') + v = self._height - 64 + + self._selected_title_text = ba.textwidget( + parent=self._root_widget, + position=(x_inset + self._scroll_width + 50 + 30, v - 15), + size=(0, 0), + scale=1.0, + color=(0.7, 1.0, 0.7, 1.0), + maxwidth=self._width - self._scroll_width - 150 - x_inset * 2, + h_align='left', + v_align='center') + v -= 30 + + self._selected_description_text = ba.textwidget( + parent=self._root_widget, + position=(x_inset + self._scroll_width + 50 + 30, v), + size=(0, 0), + scale=0.7, + color=(0.5, 0.8, 0.5, 1.0), + maxwidth=self._width - self._scroll_width - 150 - x_inset * 2, + h_align='left') + + scroll_height = self._height - 100 + + v = self._height - 60 + + self._scrollwidget = ba.scrollwidget(parent=self._root_widget, + position=(x_inset + 61, + v - scroll_height), + size=(self._scroll_width, + scroll_height), + highlight=False) + ba.widget(edit=self._scrollwidget, + up_widget=self._back_button, + left_widget=self._back_button, + right_widget=select_button) + self._column: Optional[ba.Widget] = None + + v -= 35 + ba.containerwidget(edit=self._root_widget, + cancel_button=self._back_button, + start_button=select_button) + self._selected_game_type: Optional[Type[ba.GameActivity]] = None + + ba.containerwidget(edit=self._root_widget, + selected_child=self._scrollwidget) + + self._game_types: list[type[ba.GameActivity]] = [] + + # Get actual games loading in the bg. + ba.app.meta.load_exported_classes(ba.GameActivity, + self._on_game_types_loaded, + completion_cb_in_bg_thread=True) + + # Refresh with our initial empty list. We'll refresh again once + # game loading is complete. + self._refresh() + + if config['selected']: + for gt in self._game_types: + if gt.__name__ == config['selected']: + self._refresh(selected=gt) + self._set_selected_game_type(gt) + + def _refresh(self, + select_get_more_games_button: bool = False, + selected: bool = None) -> None: + # from ba.internal import get_game_types + + if self._column is not None: + self._column.delete() + + self._column = ba.columnwidget(parent=self._scrollwidget, + border=2, + margin=0) + + for i, gametype in enumerate(self._game_types): + + def _doit() -> None: + if self._select_button: + ba.timer(0.1, + self._select_button.activate, + timetype=ba.TimeType.REAL) + + txt = ba.textwidget(parent=self._column, + position=(0, 0), + size=(self._width - 88, 24), + text=gametype.get_display_string(), + h_align='left', + v_align='center', + color=(0.8, 0.8, 0.8, 1.0), + maxwidth=self._scroll_width * 0.8, + on_select_call=ba.Call( + self._set_selected_game_type, gametype), + always_highlight=True, + selectable=True, + on_activate_call=_doit) + if i == 0: + ba.widget(edit=txt, up_widget=self._back_button) + + self._get_more_games_button = ba.buttonwidget( + parent=self._column, + autoselect=True, + label=ba.Lstr(resource=self._r + '.getMoreGamesText'), + color=(0.54, 0.52, 0.67), + textcolor=(0.7, 0.65, 0.7), + on_activate_call=self._on_get_more_games_press, + size=(178, 50)) + if select_get_more_games_button: + ba.containerwidget(edit=self._column, + selected_child=self._get_more_games_button, + visible_child=self._get_more_games_button) + + def _add(self) -> None: + _ba.lock_all_input() # Make sure no more commands happen. + ba.timer(0.1, _ba.unlock_all_input, timetype=ba.TimeType.REAL) + gameconfig = {} + if config['selected'] == self._selected_game_type.__name__: + if config['config']: + gameconfig = config['config'] + if 'map' in gameconfig: + gameconfig['settings']['map'] = gameconfig.pop('map') + self._selected_game_type.create_settings_ui( + self._editcontroller.get_session_type(), + gameconfig, + self._edit_game_done) + + def _edit_game_done(self, config: Optional[Dict[str, Any]]) -> None: + if config: + CustomSession._config = config + CustomSession._gametype = self._selected_game_type + start_game(CustomSession) + else: + ba.app.ui.clear_main_menu_window(transition='out_right') + ba.app.ui.set_main_menu_window( + SelectGameWindow(transition='in_left').get_root_widget()) + + def _back(self) -> None: + ba.containerwidget(edit=self._root_widget, transition='out_right') + ba.app.ui.set_main_menu_window( + PlayWindow(transition='in_left').get_root_widget()) + + +PlayWindow._old_init = PlayWindow.__init__ +def __init__(self, *args, **kwargs): + self._old_init() + + width = 800 + height = 550 + + def do_quick_game() -> None: + self._save_state() + ba.containerwidget(edit=self._root_widget, transition='out_left') + ba.app.ui.set_main_menu_window( + SelectGameWindow().get_root_widget()) + + self._quick_game_button = ba.buttonwidget( + parent=self._root_widget, + position=(width - 55 - 120, height - 132), + autoselect=True, + size=(120, 60), + scale=1.1, + text_scale=1.2, + label=custom_txt, + on_activate_call=do_quick_game, + color=(0.54, 0.52, 0.67), + textcolor=(0.7, 0.65, 0.7)) + + self._restore_state() + +def states(self) -> None: + return { + 'Team Games': self._teams_button, + 'Co-op Games': self._coop_button, + 'Free-for-All Games': self._free_for_all_button, + 'Back': self._back_button, + 'Quick Game': self._quick_game_button + } + +def _save_state(self) -> None: + swapped = {v: k for k, v in states(self).items()} + if self._root_widget.get_selected_child() in swapped: + ba.app.ui.window_states[ + self.__class__.__name__] = swapped[ + self._root_widget.get_selected_child()] + else: + ba.print_exception(f'Error saving state for {self}.') + +def _restore_state(self) -> None: + if not hasattr(self, '_quick_game_button'): + return # ensure that our monkey patched init ran + if self.__class__.__name__ not in ba.app.ui.window_states: + ba.containerwidget(edit=self._root_widget, + selected_child=self._coop_button) + return + sel = states(self).get( + ba.app.ui.window_states[self.__class__.__name__], None) + if sel: + ba.containerwidget(edit=self._root_widget, selected_child=sel) + else: + ba.containerwidget(edit=self._root_widget, + selected_child=self._coop_button) + ba.print_exception(f'Error restoring state for {self}.') + + +# ba_meta export plugin +class QuickGamePlugin(ba.Plugin): + PlayWindow.__init__ = __init__ + PlayWindow._save_state = _save_state + PlayWindow._restore_state = _restore_state diff --git a/plugins/utilities/RandomColors.py b/plugins/utilities/RandomColors.py new file mode 100644 index 0000000..eacf0be --- /dev/null +++ b/plugins/utilities/RandomColors.py @@ -0,0 +1,48 @@ +# ba_meta require api 7 +# (see https://ballistica.net/wiki/meta-tag-system) + +from __future__ import annotations + +from typing import TYPE_CHECKING + +import ba +import random +from bastd.actor import bomb + +if TYPE_CHECKING: + from typing import Sequence + + +class NewBlast(bomb.Blast): + def __init__( + self, + position: Sequence[float] = (0.0, 1.0, 0.0), + velocity: Sequence[float] = (0.0, 0.0, 0.0), + blast_radius: float = 2.0, + blast_type: str = 'normal', + source_player: ba.Player | None = None, + hit_type: str = 'explosion', + hit_subtype: str = 'normal', + ): + super().__init__(position, velocity, blast_radius, blast_type, + source_player, hit_type, hit_subtype) + scorch_radius = light_radius = self.radius + if self.blast_type == 'tnt': + scorch_radius *= 1.15 + scorch = ba.newnode( + 'scorch', + attrs={ + 'position': position, + 'size': scorch_radius * 0.5, + 'big': (self.blast_type == 'tnt'), + }, + ) + random_color = (random.random(), random.random(), random.random()) + scorch.color = ba.safecolor(random_color) + ba.animate(scorch, 'presence', {3.000: 1, 13.000: 0}) + ba.timer(13.0, scorch.delete) + + +# ba_meta export plugin +class RandomColorsPlugin(ba.Plugin): + bomb.Blast = NewBlast diff --git a/plugins/utilities/chat_cmd.py b/plugins/utilities/chat_cmd.py new file mode 100644 index 0000000..cc9150d --- /dev/null +++ b/plugins/utilities/chat_cmd.py @@ -0,0 +1,531 @@ +"""python 3.9 | chatcmd for a beutiful game - BombSquad OwO""" +# modded by IM_NOT_PRANAV#7874 + +# biggggggg thankssssssssssssss to FireFighter1037 for helping everything + +# -*- coding: utf-8 -*- +# ba_meta require api 7 +from _ba import env,get_foreground_host_activity,get_foreground_host_session,get_game_roster, get_chat_messages,set_party_icon_always_visible, chatmessage as cmsg, screenmessage as smsg +import ba + +#our prefix that what we starts cmds with +px='/' + +#main class +class _cmds: + + def _process_cmd(): + set_party_icon_always_visible(True) + messages=get_chat_messages() + if len(messages)>1: + lastmsg = messages[len(messages)-1] + + m=lastmsg.split(' ')[1] + if m.startswith(px): + return _cmds._handle() + else: + pass + + def _handle(): + messages=get_chat_messages() + if len(messages)>1: + lastmsg = messages[len(messages)-1] + + m=lastmsg.split(' ')[1] #cmd + n=lastmsg.split(' ')[2:] #aguments + + roster=get_game_roster() + session=get_foreground_host_session() + session_players=session.sessionplayers + + activity=get_foreground_host_activity() + activity_players=activity.players + + if m == px: + cmsg(px+'help for help') + + elif m == px+'help' : + if n==[]: + cmsg('===========================================') + cmsg(f' {px}help 1 - for page 1 | simple commands') + cmsg(f' {px}help 2 - for page 2 | all or number of list cmds') + cmsg(f' {px}help 3 - for page 3 | Other useful cmds') + cmsg('===========================================') + elif n[0]=='1': + cmsg('============================') + cmsg(f' {px}help 1 page 1 |') + cmsg(f' {px}help 1 page 2 |') + cmsg('============================') + if n[1] in [ 'page' , 'Page' , ]: + if n[2]=='1': + cmsg('============== Help 1, Page 1 ==============') + cmsg(f' your command prefix is or all commands starts with - {px}') + cmsg(f' {px}list or {px}l -- to see ids of players and execute commands') + cmsg(f' {px}uniqeid or {px}id -- to see accountid/uniqeid of player') + cmsg(f' {px}quit or {px}restart -- to restart the game') + cmsg(f' {px}mute/unmute -- to mute chat for everyone in your game') + elif n[2]=='2': + cmsg('============== Help 1, Page 2 ==============') + cmsg(f' {px}pause -- to pause everyone in your game') + cmsg(f' {px}nv or {px}night -- to make night in your game') + cmsg(f' {px}dv or {px}day -- to make night in your game') + cmsg(f' {px}camera_mode -- to rotate camera ,repat to off') + cmsg('===========================================') + elif n[0]=='2': + cmsg('============================') + cmsg(f' {px}help 2 page 1 |') + cmsg(f' {px}help 2 page 2 |') + cmsg(f' {px}help 2 page 3 |') + cmsg('============================') + if n[1] in [ 'page' , 'Page' ]: + if n[2] == '1': + cmsg('============== Help 2 Page 1 ==============') + cmsg(f' {px}kill all or {px}kill number of list | kills the player') + cmsg(f' {px}heal all or {px}heal number of list | heals the players') + cmsg(f' {px}freeze all or {px}freeze number of list | freeze the player') + cmsg(f' {px}unfreeze/thaw all or {px}unfreeze/thaw number of list | unfreeze the player') + cmsg(f' {px}gloves all or {px}gloves number of list | give gloves to player') + cmsg('============================') + elif n[2] == '2': + cmsg('============== Help 2 Page 2 ==============') + cmsg(f' {px}shield all or {px}shield number of list | give shield the player') + cmsg(f' {px}fall all or {px}fall number of list | teleport in down and fall up the player') + cmsg(f' {px}curse all or {px}curse number of list | curse the player') + cmsg(f' {px}creepy all or {px}creepy number of list | make creepy actor of player') + cmsg(f' {px}inv all or {px}inv number of list | makes invisible player') + cmsg(f' {px}celebrate all or {px}celebrate number of list | celebrate action to the player') + cmsg('============================') + elif n[2] == '3': + cmsg('============== Help 2 Page 3 ==============') + cmsg(f' {px}gm all or {px}gm number of list | give bs gods like powers to player') + cmsg(f' {px}sp all or {px}sp number of list | give superrrrrrr damages when punch to player') + cmsg(f' {px}sleep all or {px}sleep number of list | sleep up the player') + cmsg(f' {px}fly all or {px}fly number of list | fly up the player ') + cmsg(f' {px}hug number of list | hugup the player') + cmsg('============================') + + elif n[0]=='3': + cmsg('============================') + cmsg(f" {px}d_bomb bombType | changes default bomb | do {px}d_bomb help for bomb names ") + cmsg(f' {px}dbc (number of bombs) | changes default count of player') + cmsg('============================') + + + elif m in [ px+'list' , px+'l' , px+'clientids' , px+'ids' , px+'playerids' ]: + cmsg('======= Indexs ======') + for i in session_players: + cmsg(i.getname()+' --> '+str(session_players.index(i))+'\n') + if not roster ==[]: + for i in roster: + cmsg(f'======For {px}kick only======') + cmsg(str(i['players'][0]['nam_full'])+' - '+str(i['client_id'])) + + elif m in [ px+'uniqeid' , px+'id' , px+'pb-id' , px+'pb' , px+'accountid' ]: + if n==[]: + cmsg(f'use : {px}uniqeid number of list') + else: + try: + id=session_players[int(n[0])] + cmsg(id.getname()+"'s accountid is "+id.get_v1_account_id()) + except: + cmsg('could not found player') + + elif m in [ px+'quit' , px+'restart' ]: + ba.quit() + + elif m in [ px+'mute' , px+'mutechat' ]: + cfg=ba.app.config + cfg['Chat Muted']=True + cfg.apply_and_commit() + cmsg('muted') + smsg(f'chat muted use {px}unmute and click on send to unmute') + + elif m in [ px+'unmute' , px+'unmutechat' ]: + cfg=ba.app.config + cfg['Chat Muted']=False + cfg.apply_and_commit() + cmsg('un_muted') + smsg('chat un_muted') + + elif m in [ px+'end' , px+'next' ]: + if n==[]: + try: + activity.end_game() + cmsg('Game ended Hope you scored great') + except: + cmsg('Game already ended') + + elif m in [ px+'dv' , px+'day' ]: + if activity.globalsnode.tint==(1.0,1.0,1.0): + cmsg(f'alwardy {px}dv is on ,do {px}nv for night') + else: + activity.globalsnode.tint=(1.0,1.0,1.0) + cmsg('day mode on!') + + elif m in [ px+'nv' , px+'night' ]: + if activity.globalsnode.tint==(0.5, 0.7, 1.0): + cmsg(f'alwardy {px}nv is on ,do {px}dv for day') + else: + activity.globalsnode.tint=(0.5, 0.7, 1.0) + cmsg('night mode on!') + + elif m in [ px+'sm' , px+'slow' , px+'slowmo' ]: + if n==[]: + if not activity.globalsnode.slow_motion: + activity.globalsnode.slow_motion=True + cmsg('Game in Epic Mode Now') + else: + activity.globalsnode.slow_motion=False + cmsg('Game in normal mode now ') + + elif m in [ px+'pause' , px+'pausegame' ]: + if n == []: + if not activity.globalsnode.paused: + activity.globalsnode.paused=True + cmsg('Game Paused') + else: + activity.globalsnode.paused=False + cmsg('Game un paused') + + elif m in [ px+'cameraMode', px+'camera_mode' , px+'rotate_camera' ]: + if n == []: + if not activity.globalsnode.camera_mode == 'rotate': + activity.globalsnode.camera_mode = 'rotate' + cmsg('camera mode is rotate now') + else: + activity.globalsnode.camera_mode = 'follow' + cmsg('camera mode is normal now') + + elif m in [ px+'remove' , px+'rm' ]: + if n == []: + cmsg(f'{px}remove all or {px}remove number in list') + elif n[0] == 'all': + for i in session_players: + i.remove_from_game() + cmsg('Removed All') + else: + try: + r=session_players[int(n[0])] + r.remove_from_game() + cmsg('Removed') #cant use getname() activity alwrady finish + except: + cmsg('could not found player') + elif m in [ px+'inv' , px+'invisible' ]: + if n==[]: + cmsg(f'help : {px}inv all or {px}inv number of list') + elif n[0]=='all': + for i in activity_players: + body=i.actor.node + if not body.torso_model==None: + body.head_model=None + body.torso_model=None + body.upper_arm_model=None + body.forearm_model=None + body.pelvis_model=None + body.hand_model=None + body.toes_model=None + body.upper_leg_model=None + body.lower_leg_model=None + body.style='cyborg' + cmsg('All invisible now Dont get cought') + else: + cmsg('alwardy invisible') + else: + body=activity_players[int(n[0])].actor.node + is_name=session_players[int(n[0])].getname() + if not body.torso_model==None: + body.head_model=None + body.torso_model=None + body.upper_arm_model=None + body.forearm_model=None + body.pelvis_model=None + body.hand_model=None + body.toes_model=None + body.upper_leg_model=None + body.lower_leg_model=None + body.style='cyborg' + cmsg(is_name+' using invisiblelity ') + else: + cmsg('alwardy invisible') + + elif m in [ px+'hl' , px+'headless' ]: + if n==[]: + cmsg(f'help : {px}spaz all or {px}spaz number of list') + elif n[0]=='all': + for i in activity_players: + body=i.actor.node + if not body.head_model==None: + body.head_model=None + body.style='cyborg' + cmsg('headless ? xD') + else: + cmsg('alwardy headless are you really headless?') + else: + body=activity_players[int(n[0])].actor.node + is_name=session_players[int(n[0])].getname() + if not body.head_model==None: + body.head_model=None + body.style='cyborg' + cmsg(is_name+'is headless now xD') + else: + cmsg('alwardy headless are you really headless?') + + elif m in [ px+'creepy' , px+'creep' ]: + if n==[]: + cmsg(f'use: {px}creepy all or {px}creepy number of list') + elif n[0]=='all': + for i in activity_players: + body=i.actor.node + body.head_model=None + body.handlemessage(ba.PowerupMessage(poweruptype='punch')) + body.handlemessage(ba.PowerupMessage(poweruptype='shield')) + cmsg('dont creep out childs all will be scared') + else: + try: + body=activity_players[int(n[0])].actor.node + body.head_model=None + body.handlemessage(ba.PowerupMessage(poweruptype='punch')) + body.handlemessage(ba.PowerupMessage(poweruptype='shield')) + cmsg('dont creep out childs all will be scared') + except: + cmsg('could not found player to make') + + elif m in [ px+'kill' , px+'die' ]: + if n == []: + cmsg(f'Use : {px}kill all or {px}kill number of list') + elif n[0]=='all': + for i in activity_players: + i.actor.node.handlemessage(ba.DieMessage()) + cmsg('Killed all') + else: + is_name=session_players[int(n[0])].getname() + activity_players[int(n[0])].actor.node.handlemessage(ba.DieMessage()) + cmsg('Killed '+is_name) + + elif m in [ px+'heal' , px+'heath' ]: + if n == []: + cmsg(f'Use: {px}heal all or {px}heal number of list') + elif n[0]=='all': + for i in activity_players: + i.actor.node.handlemessage(ba.PowerupMessage(poweruptype='health')) + cmsg('Heald all') + else: + is_name=session_players[int(n[0])].getname() + activity_players[int(n[0])].actor.node.handlemessage(ba.PowerupMessage(poweruptype='health')) + cmsg('Heald '+is_name) + + elif m in [ px+'curse' , px+'cur' ]: + if n == []: + cmsg(f'Use: {px}curse all or {px}curse number of list') + elif n[0]=='all': + for i in activity_players: + i.actor.node.handlemessage(ba.PowerupMessage(poweruptype='curse')) + cmsg('Cursed all') + else: + is_name=session_players[int(n[0])].getname() + activity_players[int(n[0])].actor.node.handlemessage(ba.PowerupMessage(poweruptype='curse')) + cmsg('Cursed '+is_name) + + elif m in [ px+'sleep' ]: + if n == []: + cmsg(f'Use: {px}sleep all or {px}sleep number of list') + elif n[0]=='all': + for i in activity_players: + i.actor.node.handlemessage('knockout', 8000) + cmsg('Sleep all its Night :)') + else: + is_name=session_players[int(n[0])].getname() + activity_players[int(n[0])].actor.node.handlemessage('knockout', 8000) + cmsg(is_name+' sleeped now') + + elif m in [ px+'sp' , px+'superpunch' ]: + if n == []: + cmsg(f'Use : {px}sp/superpunch all or {px}sp/superpunch number of list') + elif n[0]=='all': + for i in activity_players: + if not i.actor._punch_power_scale==15: + i.actor._punch_power_scale=15 + i.actor._punch_cooldown=0 + cmsg('Everyone enjoy your Super punches') + else: + i.actor._punch_power_scale=1.2 + i.actor._punch_cooldown=400 + cmsg('Super punches off now') + else: + try: + if not activity_players[int(n[0])].actor._punch_power_scale==15: + is_name=session_players[int(n[0])].getname() + activity_players[int(n[0])].actor._punch_power_scale=15 + activity_players[int(n[0])].actor._punch_cooldown=0 + cmsg(is_name+' using super punches get away from him') + else: + activity_players[int(n[0])].actor._punch_power_scale=1.2 + activity_players[int(n[0])].actor._punch_cooldown=400 + cmsg(':( ') + except: + pass + + elif m in [ px+'gloves' , px+'punch' ]: + if n == []: + cmsg(f'Use: {px}gloves all or {px}gloves number of list') + elif n[0]=='all': + for i in activity_players: + i.actor.node.handlemessage(ba.PowerupMessage(poweruptype='punch')) + cmsg('Free Gloves enjoy all') + else: + is_name=session_players[int(n[0])].getname() + activity_players[int(n[0])].actor.node.handlemessage(ba.PowerupMessage(poweruptype='punch')) + cmsg(is_name+' using gloves') + + + elif m in [ px+'shield' , px+'protect' ]: + if n == []: + cmsg(f'Use: {px}shield all or {px}shield number of list') + elif n[0]=='all': + for i in activity_players: + i.actor.node.handlemessage(ba.PowerupMessage(poweruptype='shield')) + cmsg('Everyone enjoy free shield :)') + else: + is_name=session_players[int(n[0])].getname() + activity_players[int(n[0])].actor.node.handlemessage(ba.PowerupMessage(poweruptype='shield')) + cmsg(is_name+' using shield') + + elif m in [ px+'freeze' , px+'ice' ]: + if n == []: + cmsg(f'Use: {px}freeze all or {px}freeze number of list') + elif n[0]=='all': + for i in activity_players: + i.actor.node.handlemessage(ba.FreezeMessage()) + cmsg('Freezed all') + else: + is_name=session_players[int(n[0])].getname() + activity_players[int(n[0])].actor.node.handlemessage(ba.FreezeMessage()) + cmsg('Un freezed '+is_name) + + elif m in [ px+'unfreeze' , px+'thaw' ]: + if n == []: + cmsg(f'Use: {px}unfreeze/thaw all or {px}unfreeze/thaw number of list') + elif n[0]=='all': + for i in activity_players: + i.actor.node.handlemessage(ba.ThawMessage()) + cmsg('Un freezed all ') + else: + is_name=session_players[int(n[0])].getname() + activity_players[int(n[0])].actor.node.handlemessage(ba.ThawMessage()) + cmsg('Un freezed '+is_name) + + elif m in [ px+'fall' ]: + if n == []: + cmsg(f'Use: {px}fall all or {px}fall number of list') + elif n[0]=='all': + for i in activity_players: + i.actor.node.handlemessage(ba.StandMessage()) + cmsg('Felt everyone') + else: + is_name=session_players[int(n[0])].getname() + activity_players[int(n[0])].actor.node.handlemessage(ba.StandMessage()) + cmsg(is_name+' got felt') + + elif m in [ px+'celebrate' , px+'celeb' ]: + if n == []: + cmsg(f'Use: {px}celebrate all or {px}celebrate number of list') + elif n[0]=='all': + for i in activity_players: + i.actor.node.handlemessage(ba.CelebrateMessage()) + cmsg('Celebrate all :)') + else: + is_name=session_players[int(n[0])].getname() + activity_players[int(n[0])].actor.node.handlemessage(ba.CelebrateMessage()) + cmsg(is_name+' is celebrating bt why?') + + elif m in [ px+'fly' ]: + if n==[]: + cmsg(f'Use: {px}fly all or {px}fly number of list') + elif n[0]=='all': + for i in activity_players: + if not i.actor.node.fly==True: + i.actor.node.fly=True + cmsg('fly all dont go out ok') + else: + i.actor.node.fly=False + cmsg('flying mode off') + else: + try: + is_name=session_players[int(n[0])].getname() + if not activity_players[int(n[0])].actor.node.fly==True: + activity_players[int(n[0])].actor.node.fly=True + cmsg(is_name+' is flying') + else: + activity_players[int(n[0])].actor.node.fly=False + cmsg('fly off :(') + except: + cmsg('player not found') + pass + + elif m in [ px+'gm' , px+'godmode' ]: + if n==[]: + cmsg(f'Use: {px}gm all or {px}gm number of list') + elif n[0]=='all': + for i in activity_players: + if not i.actor.node.hockey==True: + i.actor.node.hockey=True + i.actor.node.invincible=True + i.actor._punch_power_scale=7 + cmsg('Gmed all ') + else: + i.actor.node.hockey=False + i.actor.node.invincible=False + i.actor._punch_power_scale=1.2 + cmsg('Un gmed all') + else: + try: + is_name=session_players[int(n[0])].getname() + if not activity_players[int(n[0])].actor.node.hockey==True: + activity_players[int(n[0])].actor.node.hockey=True + activity_players[int(n[0])].actor.node.invincible=True + activity_players[int(n[0])].actor._punch_power_scale=7 + cmsg('Gmed '+is_name) + else: + activity_players[int(n[0])].actor.node.hockey=False + activity_players[int(n[0])].actor.node.invincible=False + activity_players[int(n[0])].actor._punch_power_scale=1.2 + cmsg('un gmed '+is_name) + except: + cmsg('could not found player') + elif m in [ px+'d_bomb', px+'default_bomb' ]: + if n == []: + cmsg(f'Use: {px}d_bomb/default_bomb all or {px}d_bomb number of list ,type {px}d_bomb help for help') + elif n[0]=='help': + cmsg("bombtypes - ['ice', 'impact', 'land_mine', 'normal', 'sticky','tnt']") + elif n[0] in [ 'ice' , 'impact', 'land_mine' , 'normal' , 'sticky' , 'tnt']: + for i in activity_players: + i.actor.bomb_type=n[0] + cmsg('default bomb type - '+str(n[0])+' now') + else: + cmsg('unkwon bombtype , type {px}d_bomb help for help') + + elif m in [ px+'d_bomb_count', px+'default_bomb_count' , px+'dbc' ]: + if n == []: + cmsg(f'Use: {px}d_bomb_count/default_bomb/dbc all or {px}d_bomb_count/default_bomb_count/dbc number of list') + else: + try: + for i in activity_players: + i.actor.set_bomb_count(int(n[0])) + cmsg('default bomb count is '+(str(n[0]))+' now') + except: + cmsg('Must use number to use') + elif m in [ px+'credits' ]: + if n==[]: + cmsg(u'\U0001F95A created by Nazz \U0001F95A') + cmsg(u'\U0001F95A Nazz are past/present/future \U0001F95A') + cmsg(u'\U0001F95A everything is Nazz \U0001F95A') + + + +# ba.timer(0.05, _update, repeat=True) +def same(): + ba.timer(0.5, _cmds._process_cmd, True) + +# ba_meta export plugin +class _enableee(ba.Plugin): + same() \ No newline at end of file From d58e326d4ca1198e4286540fe059a6f7eec522a9 Mon Sep 17 00:00:00 2001 From: Loup-Garou911XD Date: Thu, 3 Nov 2022 17:08:09 +0000 Subject: [PATCH 08/55] [ci] auto-format --- plugins/utilities/CustomDeath.py | 2 + plugins/utilities/MaxPlayers.py | 18 +- plugins/utilities/QuickCustonGame.py | 12 +- plugins/utilities/RandomColors.py | 40 +- plugins/utilities/chat_cmd.py | 1022 +++++++++++++------------- 5 files changed, 564 insertions(+), 530 deletions(-) diff --git a/plugins/utilities/CustomDeath.py b/plugins/utilities/CustomDeath.py index 809db73..b3730e1 100644 --- a/plugins/utilities/CustomDeath.py +++ b/plugins/utilities/CustomDeath.py @@ -13,6 +13,8 @@ if TYPE_CHECKING: Spaz.oldhandlemessage = Spaz.handlemessage + + def handlemessage(self, msg: Any) -> Any: if isinstance(msg, ba.DieMessage): if self.node: diff --git a/plugins/utilities/MaxPlayers.py b/plugins/utilities/MaxPlayers.py index dce5ec0..6d6257a 100644 --- a/plugins/utilities/MaxPlayers.py +++ b/plugins/utilities/MaxPlayers.py @@ -37,6 +37,7 @@ else: teams_text = 'Teams' ffa_text = 'FFA' + class ConfigNumberEdit: def __init__(self, @@ -102,6 +103,7 @@ class ConfigNumberEdit: cfg['Config Max Players'][self._config] = self._value cfg.apply_and_commit() + class SettingsMaxPlayers(PopupWindow): def __init__(self): @@ -180,6 +182,7 @@ class SettingsMaxPlayers(PopupWindow): ba.playsound(ba.getsound('swish')) self._transition_out() + def __init__(self) -> None: """Instantiate a co-op mode session.""" # pylint: disable=cyclic-import @@ -230,6 +233,7 @@ def __init__(self) -> None: self._next_game_level_name: Optional[str] = None self._update_on_deck_game_instances() + def get_max_players(self) -> int: """Return max number of ba.Players allowed to join the game at once.""" if self.use_teams: @@ -240,11 +244,15 @@ def get_max_players(self) -> int: 'Free-for-All Max Players', cfg['Config Max Players']['ffa_max_players']) + GatherWindow.__old_init__ = GatherWindow.__init__ + + def __gather_init__(self, - transition: Optional[str] = 'in_right', - origin_widget: ba.Widget = None): + transition: Optional[str] = 'in_right', + origin_widget: ba.Widget = None): self.__old_init__(transition, origin_widget) + def _do_max_players(): SettingsMaxPlayers() self._max_players_button = ba.buttonwidget( @@ -260,6 +268,7 @@ def __gather_init__(self, button_type='regular', on_activate_call=_do_max_players) + def _save_state(self) -> None: try: for tab in self._tabs.values(): @@ -287,6 +296,7 @@ def _save_state(self) -> None: except Exception: ba.print_exception(f'Error saving state for {self}.') + def _restore_state(self) -> None: from efro.util import enum_by_value try: @@ -326,6 +336,8 @@ def _restore_state(self) -> None: ba.print_exception('Error restoring gather-win state.') # ba_meta export plugin + + class MaxPlayersPlugin(ba.Plugin): def has_settings_ui(self) -> bool: @@ -338,7 +350,7 @@ class MaxPlayersPlugin(ba.Plugin): old_config = ba.app.config['Config Max Players'] for setting in cmp: if setting not in old_config: - ba.app.config['Config Max Players'].update({setting:cmp[setting]}) + ba.app.config['Config Max Players'].update({setting: cmp[setting]}) remove_list = [] for setting in old_config: if setting not in cmp: diff --git a/plugins/utilities/QuickCustonGame.py b/plugins/utilities/QuickCustonGame.py index dcc93c4..259dff2 100644 --- a/plugins/utilities/QuickCustonGame.py +++ b/plugins/utilities/QuickCustonGame.py @@ -19,9 +19,9 @@ if TYPE_CHECKING: lang = ba.app.lang.language if lang == 'Spanish': - custom_txt = 'personalizar...' + custom_txt = 'personalizar...' else: - custom_txt = 'custom...' + custom_txt = 'custom...' if 'quick_game_button' in ba.app.config: @@ -31,6 +31,7 @@ else: ba.app.config['quick_game_button'] = config ba.app.config.commit() + def start_game(session: ba.Session, fadeout: bool = True): def callback(): if fadeout: @@ -50,6 +51,7 @@ def start_game(session: ba.Session, fadeout: bool = True): else: callback() + class SimplePlaylist: def __init__(self, @@ -66,6 +68,7 @@ class SimplePlaylist: settings = self.settings['settings'] return dict(resolved_type=self.gametype, settings=settings) + class CustomSession(FreeForAllSession): def __init__(self, *args, **kwargs): @@ -305,6 +308,8 @@ class SelectGameWindow(PlaylistAddGameWindow): PlayWindow._old_init = PlayWindow.__init__ + + def __init__(self, *args, **kwargs): self._old_init() @@ -331,6 +336,7 @@ def __init__(self, *args, **kwargs): self._restore_state() + def states(self) -> None: return { 'Team Games': self._teams_button, @@ -340,6 +346,7 @@ def states(self) -> None: 'Quick Game': self._quick_game_button } + def _save_state(self) -> None: swapped = {v: k for k, v in states(self).items()} if self._root_widget.get_selected_child() in swapped: @@ -349,6 +356,7 @@ def _save_state(self) -> None: else: ba.print_exception(f'Error saving state for {self}.') + def _restore_state(self) -> None: if not hasattr(self, '_quick_game_button'): return # ensure that our monkey patched init ran diff --git a/plugins/utilities/RandomColors.py b/plugins/utilities/RandomColors.py index eacf0be..3ea0ba6 100644 --- a/plugins/utilities/RandomColors.py +++ b/plugins/utilities/RandomColors.py @@ -10,11 +10,11 @@ import random from bastd.actor import bomb if TYPE_CHECKING: - from typing import Sequence + from typing import Sequence class NewBlast(bomb.Blast): - def __init__( + def __init__( self, position: Sequence[float] = (0.0, 1.0, 0.0), velocity: Sequence[float] = (0.0, 0.0, 0.0), @@ -24,25 +24,25 @@ class NewBlast(bomb.Blast): hit_type: str = 'explosion', hit_subtype: str = 'normal', ): - super().__init__(position, velocity, blast_radius, blast_type, - source_player, hit_type, hit_subtype) - scorch_radius = light_radius = self.radius - if self.blast_type == 'tnt': - scorch_radius *= 1.15 - scorch = ba.newnode( - 'scorch', - attrs={ - 'position': position, - 'size': scorch_radius * 0.5, - 'big': (self.blast_type == 'tnt'), - }, - ) - random_color = (random.random(), random.random(), random.random()) - scorch.color = ba.safecolor(random_color) - ba.animate(scorch, 'presence', {3.000: 1, 13.000: 0}) - ba.timer(13.0, scorch.delete) + super().__init__(position, velocity, blast_radius, blast_type, + source_player, hit_type, hit_subtype) + scorch_radius = light_radius = self.radius + if self.blast_type == 'tnt': + scorch_radius *= 1.15 + scorch = ba.newnode( + 'scorch', + attrs={ + 'position': position, + 'size': scorch_radius * 0.5, + 'big': (self.blast_type == 'tnt'), + }, + ) + random_color = (random.random(), random.random(), random.random()) + scorch.color = ba.safecolor(random_color) + ba.animate(scorch, 'presence', {3.000: 1, 13.000: 0}) + ba.timer(13.0, scorch.delete) # ba_meta export plugin class RandomColorsPlugin(ba.Plugin): - bomb.Blast = NewBlast + bomb.Blast = NewBlast diff --git a/plugins/utilities/chat_cmd.py b/plugins/utilities/chat_cmd.py index cc9150d..5bb3da4 100644 --- a/plugins/utilities/chat_cmd.py +++ b/plugins/utilities/chat_cmd.py @@ -4,528 +4,540 @@ # biggggggg thankssssssssssssss to FireFighter1037 for helping everything # -*- coding: utf-8 -*- -# ba_meta require api 7 -from _ba import env,get_foreground_host_activity,get_foreground_host_session,get_game_roster, get_chat_messages,set_party_icon_always_visible, chatmessage as cmsg, screenmessage as smsg +# ba_meta require api 7 +from _ba import env, get_foreground_host_activity, get_foreground_host_session, get_game_roster, get_chat_messages, set_party_icon_always_visible, chatmessage as cmsg, screenmessage as smsg import ba -#our prefix that what we starts cmds with -px='/' +# our prefix that what we starts cmds with +px = '/' + +# main class + -#main class class _cmds: - - def _process_cmd(): - set_party_icon_always_visible(True) - messages=get_chat_messages() - if len(messages)>1: - lastmsg = messages[len(messages)-1] - - m=lastmsg.split(' ')[1] - if m.startswith(px): - return _cmds._handle() - else: - pass - - def _handle(): - messages=get_chat_messages() - if len(messages)>1: - lastmsg = messages[len(messages)-1] - - m=lastmsg.split(' ')[1] #cmd - n=lastmsg.split(' ')[2:] #aguments - - roster=get_game_roster() - session=get_foreground_host_session() - session_players=session.sessionplayers - - activity=get_foreground_host_activity() - activity_players=activity.players - - if m == px: - cmsg(px+'help for help') - - elif m == px+'help' : - if n==[]: - cmsg('===========================================') - cmsg(f' {px}help 1 - for page 1 | simple commands') - cmsg(f' {px}help 2 - for page 2 | all or number of list cmds') - cmsg(f' {px}help 3 - for page 3 | Other useful cmds') - cmsg('===========================================') - elif n[0]=='1': - cmsg('============================') - cmsg(f' {px}help 1 page 1 |') - cmsg(f' {px}help 1 page 2 |') - cmsg('============================') - if n[1] in [ 'page' , 'Page' , ]: - if n[2]=='1': - cmsg('============== Help 1, Page 1 ==============') - cmsg(f' your command prefix is or all commands starts with - {px}') - cmsg(f' {px}list or {px}l -- to see ids of players and execute commands') - cmsg(f' {px}uniqeid or {px}id -- to see accountid/uniqeid of player') - cmsg(f' {px}quit or {px}restart -- to restart the game') - cmsg(f' {px}mute/unmute -- to mute chat for everyone in your game') - elif n[2]=='2': - cmsg('============== Help 1, Page 2 ==============') - cmsg(f' {px}pause -- to pause everyone in your game') - cmsg(f' {px}nv or {px}night -- to make night in your game') - cmsg(f' {px}dv or {px}day -- to make night in your game') - cmsg(f' {px}camera_mode -- to rotate camera ,repat to off') - cmsg('===========================================') - elif n[0]=='2': - cmsg('============================') - cmsg(f' {px}help 2 page 1 |') - cmsg(f' {px}help 2 page 2 |') - cmsg(f' {px}help 2 page 3 |') - cmsg('============================') - if n[1] in [ 'page' , 'Page' ]: - if n[2] == '1': - cmsg('============== Help 2 Page 1 ==============') - cmsg(f' {px}kill all or {px}kill number of list | kills the player') - cmsg(f' {px}heal all or {px}heal number of list | heals the players') - cmsg(f' {px}freeze all or {px}freeze number of list | freeze the player') - cmsg(f' {px}unfreeze/thaw all or {px}unfreeze/thaw number of list | unfreeze the player') - cmsg(f' {px}gloves all or {px}gloves number of list | give gloves to player') - cmsg('============================') - elif n[2] == '2': - cmsg('============== Help 2 Page 2 ==============') - cmsg(f' {px}shield all or {px}shield number of list | give shield the player') - cmsg(f' {px}fall all or {px}fall number of list | teleport in down and fall up the player') - cmsg(f' {px}curse all or {px}curse number of list | curse the player') - cmsg(f' {px}creepy all or {px}creepy number of list | make creepy actor of player') - cmsg(f' {px}inv all or {px}inv number of list | makes invisible player') - cmsg(f' {px}celebrate all or {px}celebrate number of list | celebrate action to the player') - cmsg('============================') - elif n[2] == '3': - cmsg('============== Help 2 Page 3 ==============') - cmsg(f' {px}gm all or {px}gm number of list | give bs gods like powers to player') - cmsg(f' {px}sp all or {px}sp number of list | give superrrrrrr damages when punch to player') - cmsg(f' {px}sleep all or {px}sleep number of list | sleep up the player') - cmsg(f' {px}fly all or {px}fly number of list | fly up the player ') - cmsg(f' {px}hug number of list | hugup the player') - cmsg('============================') - elif n[0]=='3': - cmsg('============================') - cmsg(f" {px}d_bomb bombType | changes default bomb | do {px}d_bomb help for bomb names ") - cmsg(f' {px}dbc (number of bombs) | changes default count of player') - cmsg('============================') + def _process_cmd(): + set_party_icon_always_visible(True) + messages = get_chat_messages() + if len(messages) > 1: + lastmsg = messages[len(messages)-1] + m = lastmsg.split(' ')[1] + if m.startswith(px): + return _cmds._handle() + else: + pass - elif m in [ px+'list' , px+'l' , px+'clientids' , px+'ids' , px+'playerids' ]: - cmsg('======= Indexs ======') - for i in session_players: - cmsg(i.getname()+' --> '+str(session_players.index(i))+'\n') - if not roster ==[]: - for i in roster: - cmsg(f'======For {px}kick only======') - cmsg(str(i['players'][0]['nam_full'])+' - '+str(i['client_id'])) - - elif m in [ px+'uniqeid' , px+'id' , px+'pb-id' , px+'pb' , px+'accountid' ]: - if n==[]: - cmsg(f'use : {px}uniqeid number of list') - else: - try: - id=session_players[int(n[0])] - cmsg(id.getname()+"'s accountid is "+id.get_v1_account_id()) - except: - cmsg('could not found player') - - elif m in [ px+'quit' , px+'restart' ]: - ba.quit() - - elif m in [ px+'mute' , px+'mutechat' ]: - cfg=ba.app.config - cfg['Chat Muted']=True - cfg.apply_and_commit() - cmsg('muted') - smsg(f'chat muted use {px}unmute and click on send to unmute') - - elif m in [ px+'unmute' , px+'unmutechat' ]: - cfg=ba.app.config - cfg['Chat Muted']=False - cfg.apply_and_commit() - cmsg('un_muted') - smsg('chat un_muted') - - elif m in [ px+'end' , px+'next' ]: - if n==[]: - try: - activity.end_game() - cmsg('Game ended Hope you scored great') - except: - cmsg('Game already ended') + def _handle(): + messages = get_chat_messages() + if len(messages) > 1: + lastmsg = messages[len(messages)-1] - elif m in [ px+'dv' , px+'day' ]: - if activity.globalsnode.tint==(1.0,1.0,1.0): - cmsg(f'alwardy {px}dv is on ,do {px}nv for night') - else: - activity.globalsnode.tint=(1.0,1.0,1.0) - cmsg('day mode on!') + m = lastmsg.split(' ')[1] # cmd + n = lastmsg.split(' ')[2:] # aguments - elif m in [ px+'nv' , px+'night' ]: - if activity.globalsnode.tint==(0.5, 0.7, 1.0): - cmsg(f'alwardy {px}nv is on ,do {px}dv for day') - else: - activity.globalsnode.tint=(0.5, 0.7, 1.0) - cmsg('night mode on!') - - elif m in [ px+'sm' , px+'slow' , px+'slowmo' ]: - if n==[]: - if not activity.globalsnode.slow_motion: - activity.globalsnode.slow_motion=True - cmsg('Game in Epic Mode Now') - else: - activity.globalsnode.slow_motion=False - cmsg('Game in normal mode now ') - - elif m in [ px+'pause' , px+'pausegame' ]: - if n == []: - if not activity.globalsnode.paused: - activity.globalsnode.paused=True - cmsg('Game Paused') - else: - activity.globalsnode.paused=False - cmsg('Game un paused') - - elif m in [ px+'cameraMode', px+'camera_mode' , px+'rotate_camera' ]: - if n == []: - if not activity.globalsnode.camera_mode == 'rotate': - activity.globalsnode.camera_mode = 'rotate' - cmsg('camera mode is rotate now') - else: - activity.globalsnode.camera_mode = 'follow' - cmsg('camera mode is normal now') + roster = get_game_roster() + session = get_foreground_host_session() + session_players = session.sessionplayers - elif m in [ px+'remove' , px+'rm' ]: - if n == []: - cmsg(f'{px}remove all or {px}remove number in list') - elif n[0] == 'all': - for i in session_players: - i.remove_from_game() - cmsg('Removed All') - else: - try: - r=session_players[int(n[0])] - r.remove_from_game() - cmsg('Removed') #cant use getname() activity alwrady finish - except: - cmsg('could not found player') - elif m in [ px+'inv' , px+'invisible' ]: - if n==[]: - cmsg(f'help : {px}inv all or {px}inv number of list') - elif n[0]=='all': - for i in activity_players: - body=i.actor.node - if not body.torso_model==None: - body.head_model=None - body.torso_model=None - body.upper_arm_model=None - body.forearm_model=None - body.pelvis_model=None - body.hand_model=None - body.toes_model=None - body.upper_leg_model=None - body.lower_leg_model=None - body.style='cyborg' - cmsg('All invisible now Dont get cought') - else: - cmsg('alwardy invisible') - else: - body=activity_players[int(n[0])].actor.node - is_name=session_players[int(n[0])].getname() - if not body.torso_model==None: - body.head_model=None - body.torso_model=None - body.upper_arm_model=None - body.forearm_model=None - body.pelvis_model=None - body.hand_model=None - body.toes_model=None - body.upper_leg_model=None - body.lower_leg_model=None - body.style='cyborg' - cmsg(is_name+' using invisiblelity ') - else: - cmsg('alwardy invisible') - - elif m in [ px+'hl' , px+'headless' ]: - if n==[]: - cmsg(f'help : {px}spaz all or {px}spaz number of list') - elif n[0]=='all': - for i in activity_players: - body=i.actor.node - if not body.head_model==None: - body.head_model=None - body.style='cyborg' - cmsg('headless ? xD') - else: - cmsg('alwardy headless are you really headless?') - else: - body=activity_players[int(n[0])].actor.node - is_name=session_players[int(n[0])].getname() - if not body.head_model==None: - body.head_model=None - body.style='cyborg' - cmsg(is_name+'is headless now xD') - else: - cmsg('alwardy headless are you really headless?') - - elif m in [ px+'creepy' , px+'creep' ]: - if n==[]: - cmsg(f'use: {px}creepy all or {px}creepy number of list') - elif n[0]=='all': - for i in activity_players: - body=i.actor.node - body.head_model=None - body.handlemessage(ba.PowerupMessage(poweruptype='punch')) - body.handlemessage(ba.PowerupMessage(poweruptype='shield')) - cmsg('dont creep out childs all will be scared') - else: - try: - body=activity_players[int(n[0])].actor.node - body.head_model=None - body.handlemessage(ba.PowerupMessage(poweruptype='punch')) - body.handlemessage(ba.PowerupMessage(poweruptype='shield')) - cmsg('dont creep out childs all will be scared') - except: - cmsg('could not found player to make') - - elif m in [ px+'kill' , px+'die' ]: - if n == []: - cmsg(f'Use : {px}kill all or {px}kill number of list') - elif n[0]=='all': - for i in activity_players: - i.actor.node.handlemessage(ba.DieMessage()) - cmsg('Killed all') - else: - is_name=session_players[int(n[0])].getname() - activity_players[int(n[0])].actor.node.handlemessage(ba.DieMessage()) - cmsg('Killed '+is_name) + activity = get_foreground_host_activity() + activity_players = activity.players - elif m in [ px+'heal' , px+'heath' ]: - if n == []: - cmsg(f'Use: {px}heal all or {px}heal number of list') - elif n[0]=='all': - for i in activity_players: - i.actor.node.handlemessage(ba.PowerupMessage(poweruptype='health')) - cmsg('Heald all') - else: - is_name=session_players[int(n[0])].getname() - activity_players[int(n[0])].actor.node.handlemessage(ba.PowerupMessage(poweruptype='health')) - cmsg('Heald '+is_name) - - elif m in [ px+'curse' , px+'cur' ]: - if n == []: - cmsg(f'Use: {px}curse all or {px}curse number of list') - elif n[0]=='all': - for i in activity_players: - i.actor.node.handlemessage(ba.PowerupMessage(poweruptype='curse')) - cmsg('Cursed all') - else: - is_name=session_players[int(n[0])].getname() - activity_players[int(n[0])].actor.node.handlemessage(ba.PowerupMessage(poweruptype='curse')) - cmsg('Cursed '+is_name) - - elif m in [ px+'sleep' ]: - if n == []: - cmsg(f'Use: {px}sleep all or {px}sleep number of list') - elif n[0]=='all': - for i in activity_players: - i.actor.node.handlemessage('knockout', 8000) - cmsg('Sleep all its Night :)') - else: - is_name=session_players[int(n[0])].getname() - activity_players[int(n[0])].actor.node.handlemessage('knockout', 8000) - cmsg(is_name+' sleeped now') - - elif m in [ px+'sp' , px+'superpunch' ]: - if n == []: - cmsg(f'Use : {px}sp/superpunch all or {px}sp/superpunch number of list') - elif n[0]=='all': - for i in activity_players: - if not i.actor._punch_power_scale==15: - i.actor._punch_power_scale=15 - i.actor._punch_cooldown=0 - cmsg('Everyone enjoy your Super punches') - else: - i.actor._punch_power_scale=1.2 - i.actor._punch_cooldown=400 - cmsg('Super punches off now') - else: - try: - if not activity_players[int(n[0])].actor._punch_power_scale==15: - is_name=session_players[int(n[0])].getname() - activity_players[int(n[0])].actor._punch_power_scale=15 - activity_players[int(n[0])].actor._punch_cooldown=0 - cmsg(is_name+' using super punches get away from him') - else: - activity_players[int(n[0])].actor._punch_power_scale=1.2 - activity_players[int(n[0])].actor._punch_cooldown=400 - cmsg(':( ') - except: - pass + if m == px: + cmsg(px+'help for help') - elif m in [ px+'gloves' , px+'punch' ]: - if n == []: - cmsg(f'Use: {px}gloves all or {px}gloves number of list') - elif n[0]=='all': - for i in activity_players: - i.actor.node.handlemessage(ba.PowerupMessage(poweruptype='punch')) - cmsg('Free Gloves enjoy all') - else: - is_name=session_players[int(n[0])].getname() - activity_players[int(n[0])].actor.node.handlemessage(ba.PowerupMessage(poweruptype='punch')) - cmsg(is_name+' using gloves') - - - elif m in [ px+'shield' , px+'protect' ]: - if n == []: - cmsg(f'Use: {px}shield all or {px}shield number of list') - elif n[0]=='all': - for i in activity_players: - i.actor.node.handlemessage(ba.PowerupMessage(poweruptype='shield')) - cmsg('Everyone enjoy free shield :)') - else: - is_name=session_players[int(n[0])].getname() - activity_players[int(n[0])].actor.node.handlemessage(ba.PowerupMessage(poweruptype='shield')) - cmsg(is_name+' using shield') - - elif m in [ px+'freeze' , px+'ice' ]: - if n == []: - cmsg(f'Use: {px}freeze all or {px}freeze number of list') - elif n[0]=='all': - for i in activity_players: - i.actor.node.handlemessage(ba.FreezeMessage()) - cmsg('Freezed all') - else: - is_name=session_players[int(n[0])].getname() - activity_players[int(n[0])].actor.node.handlemessage(ba.FreezeMessage()) - cmsg('Un freezed '+is_name) - - elif m in [ px+'unfreeze' , px+'thaw' ]: - if n == []: - cmsg(f'Use: {px}unfreeze/thaw all or {px}unfreeze/thaw number of list') - elif n[0]=='all': - for i in activity_players: - i.actor.node.handlemessage(ba.ThawMessage()) - cmsg('Un freezed all ') - else: - is_name=session_players[int(n[0])].getname() - activity_players[int(n[0])].actor.node.handlemessage(ba.ThawMessage()) - cmsg('Un freezed '+is_name) - - elif m in [ px+'fall' ]: - if n == []: - cmsg(f'Use: {px}fall all or {px}fall number of list') - elif n[0]=='all': - for i in activity_players: - i.actor.node.handlemessage(ba.StandMessage()) - cmsg('Felt everyone') - else: - is_name=session_players[int(n[0])].getname() - activity_players[int(n[0])].actor.node.handlemessage(ba.StandMessage()) - cmsg(is_name+' got felt') - - elif m in [ px+'celebrate' , px+'celeb' ]: - if n == []: - cmsg(f'Use: {px}celebrate all or {px}celebrate number of list') - elif n[0]=='all': - for i in activity_players: - i.actor.node.handlemessage(ba.CelebrateMessage()) - cmsg('Celebrate all :)') - else: - is_name=session_players[int(n[0])].getname() - activity_players[int(n[0])].actor.node.handlemessage(ba.CelebrateMessage()) - cmsg(is_name+' is celebrating bt why?') - - elif m in [ px+'fly' ]: - if n==[]: - cmsg(f'Use: {px}fly all or {px}fly number of list') - elif n[0]=='all': - for i in activity_players: - if not i.actor.node.fly==True: - i.actor.node.fly=True - cmsg('fly all dont go out ok') - else: - i.actor.node.fly=False - cmsg('flying mode off') - else: - try: - is_name=session_players[int(n[0])].getname() - if not activity_players[int(n[0])].actor.node.fly==True: - activity_players[int(n[0])].actor.node.fly=True - cmsg(is_name+' is flying') - else: - activity_players[int(n[0])].actor.node.fly=False - cmsg('fly off :(') - except: - cmsg('player not found') - pass - - elif m in [ px+'gm' , px+'godmode' ]: - if n==[]: - cmsg(f'Use: {px}gm all or {px}gm number of list') - elif n[0]=='all': - for i in activity_players: - if not i.actor.node.hockey==True: - i.actor.node.hockey=True - i.actor.node.invincible=True - i.actor._punch_power_scale=7 - cmsg('Gmed all ') - else: - i.actor.node.hockey=False - i.actor.node.invincible=False - i.actor._punch_power_scale=1.2 - cmsg('Un gmed all') - else: - try: - is_name=session_players[int(n[0])].getname() - if not activity_players[int(n[0])].actor.node.hockey==True: - activity_players[int(n[0])].actor.node.hockey=True - activity_players[int(n[0])].actor.node.invincible=True - activity_players[int(n[0])].actor._punch_power_scale=7 - cmsg('Gmed '+is_name) - else: - activity_players[int(n[0])].actor.node.hockey=False - activity_players[int(n[0])].actor.node.invincible=False - activity_players[int(n[0])].actor._punch_power_scale=1.2 - cmsg('un gmed '+is_name) - except: - cmsg('could not found player') - elif m in [ px+'d_bomb', px+'default_bomb' ]: - if n == []: - cmsg(f'Use: {px}d_bomb/default_bomb all or {px}d_bomb number of list ,type {px}d_bomb help for help') - elif n[0]=='help': - cmsg("bombtypes - ['ice', 'impact', 'land_mine', 'normal', 'sticky','tnt']") - elif n[0] in [ 'ice' , 'impact', 'land_mine' , 'normal' , 'sticky' , 'tnt']: - for i in activity_players: - i.actor.bomb_type=n[0] - cmsg('default bomb type - '+str(n[0])+' now') - else: - cmsg('unkwon bombtype , type {px}d_bomb help for help') - - elif m in [ px+'d_bomb_count', px+'default_bomb_count' , px+'dbc' ]: - if n == []: - cmsg(f'Use: {px}d_bomb_count/default_bomb/dbc all or {px}d_bomb_count/default_bomb_count/dbc number of list') - else: - try: - for i in activity_players: - i.actor.set_bomb_count(int(n[0])) - cmsg('default bomb count is '+(str(n[0]))+' now') - except: - cmsg('Must use number to use') - elif m in [ px+'credits' ]: - if n==[]: - cmsg(u'\U0001F95A created by Nazz \U0001F95A') - cmsg(u'\U0001F95A Nazz are past/present/future \U0001F95A') - cmsg(u'\U0001F95A everything is Nazz \U0001F95A') + elif m == px+'help': + if n == []: + cmsg('===========================================') + cmsg(f' {px}help 1 - for page 1 | simple commands') + cmsg(f' {px}help 2 - for page 2 | all or number of list cmds') + cmsg(f' {px}help 3 - for page 3 | Other useful cmds') + cmsg('===========================================') + elif n[0] == '1': + cmsg('============================') + cmsg(f' {px}help 1 page 1 |') + cmsg(f' {px}help 1 page 2 |') + cmsg('============================') + if n[1] in ['page', 'Page', ]: + if n[2] == '1': + cmsg('============== Help 1, Page 1 ==============') + cmsg(f' your command prefix is or all commands starts with - {px}') + cmsg(f' {px}list or {px}l -- to see ids of players and execute commands') + cmsg(f' {px}uniqeid or {px}id -- to see accountid/uniqeid of player') + cmsg(f' {px}quit or {px}restart -- to restart the game') + cmsg(f' {px}mute/unmute -- to mute chat for everyone in your game') + elif n[2] == '2': + cmsg('============== Help 1, Page 2 ==============') + cmsg(f' {px}pause -- to pause everyone in your game') + cmsg(f' {px}nv or {px}night -- to make night in your game') + cmsg(f' {px}dv or {px}day -- to make night in your game') + cmsg(f' {px}camera_mode -- to rotate camera ,repat to off') + cmsg('===========================================') + elif n[0] == '2': + cmsg('============================') + cmsg(f' {px}help 2 page 1 |') + cmsg(f' {px}help 2 page 2 |') + cmsg(f' {px}help 2 page 3 |') + cmsg('============================') + if n[1] in ['page', 'Page']: + if n[2] == '1': + cmsg('============== Help 2 Page 1 ==============') + cmsg(f' {px}kill all or {px}kill number of list | kills the player') + cmsg(f' {px}heal all or {px}heal number of list | heals the players') + cmsg(f' {px}freeze all or {px}freeze number of list | freeze the player') + cmsg( + f' {px}unfreeze/thaw all or {px}unfreeze/thaw number of list | unfreeze the player') + cmsg(f' {px}gloves all or {px}gloves number of list | give gloves to player') + cmsg('============================') + elif n[2] == '2': + cmsg('============== Help 2 Page 2 ==============') + cmsg(f' {px}shield all or {px}shield number of list | give shield the player') + cmsg( + f' {px}fall all or {px}fall number of list | teleport in down and fall up the player') + cmsg(f' {px}curse all or {px}curse number of list | curse the player') + cmsg( + f' {px}creepy all or {px}creepy number of list | make creepy actor of player') + cmsg(f' {px}inv all or {px}inv number of list | makes invisible player') + cmsg( + f' {px}celebrate all or {px}celebrate number of list | celebrate action to the player') + cmsg('============================') + elif n[2] == '3': + cmsg('============== Help 2 Page 3 ==============') + cmsg(f' {px}gm all or {px}gm number of list | give bs gods like powers to player') + cmsg( + f' {px}sp all or {px}sp number of list | give superrrrrrr damages when punch to player') + cmsg(f' {px}sleep all or {px}sleep number of list | sleep up the player') + cmsg(f' {px}fly all or {px}fly number of list | fly up the player ') + cmsg(f' {px}hug number of list | hugup the player') + cmsg('============================') + elif n[0] == '3': + cmsg('============================') + cmsg(f" {px}d_bomb bombType | changes default bomb | do {px}d_bomb help for bomb names ") + cmsg(f' {px}dbc (number of bombs) | changes default count of player') + cmsg('============================') + + elif m in [px+'list', px+'l', px+'clientids', px+'ids', px+'playerids']: + cmsg('======= Indexs ======') + for i in session_players: + cmsg(i.getname()+' --> '+str(session_players.index(i))+'\n') + if not roster == []: + for i in roster: + cmsg(f'======For {px}kick only======') + cmsg(str(i['players'][0]['nam_full'])+' - '+str(i['client_id'])) + + elif m in [px+'uniqeid', px+'id', px+'pb-id', px+'pb', px+'accountid']: + if n == []: + cmsg(f'use : {px}uniqeid number of list') + else: + try: + id = session_players[int(n[0])] + cmsg(id.getname()+"'s accountid is "+id.get_v1_account_id()) + except: + cmsg('could not found player') + + elif m in [px+'quit', px+'restart']: + ba.quit() + + elif m in [px+'mute', px+'mutechat']: + cfg = ba.app.config + cfg['Chat Muted'] = True + cfg.apply_and_commit() + cmsg('muted') + smsg(f'chat muted use {px}unmute and click on send to unmute') + + elif m in [px+'unmute', px+'unmutechat']: + cfg = ba.app.config + cfg['Chat Muted'] = False + cfg.apply_and_commit() + cmsg('un_muted') + smsg('chat un_muted') + + elif m in [px+'end', px+'next']: + if n == []: + try: + activity.end_game() + cmsg('Game ended Hope you scored great') + except: + cmsg('Game already ended') + + elif m in [px+'dv', px+'day']: + if activity.globalsnode.tint == (1.0, 1.0, 1.0): + cmsg(f'alwardy {px}dv is on ,do {px}nv for night') + else: + activity.globalsnode.tint = (1.0, 1.0, 1.0) + cmsg('day mode on!') + + elif m in [px+'nv', px+'night']: + if activity.globalsnode.tint == (0.5, 0.7, 1.0): + cmsg(f'alwardy {px}nv is on ,do {px}dv for day') + else: + activity.globalsnode.tint = (0.5, 0.7, 1.0) + cmsg('night mode on!') + + elif m in [px+'sm', px+'slow', px+'slowmo']: + if n == []: + if not activity.globalsnode.slow_motion: + activity.globalsnode.slow_motion = True + cmsg('Game in Epic Mode Now') + else: + activity.globalsnode.slow_motion = False + cmsg('Game in normal mode now ') + + elif m in [px+'pause', px+'pausegame']: + if n == []: + if not activity.globalsnode.paused: + activity.globalsnode.paused = True + cmsg('Game Paused') + else: + activity.globalsnode.paused = False + cmsg('Game un paused') + + elif m in [px+'cameraMode', px+'camera_mode', px+'rotate_camera']: + if n == []: + if not activity.globalsnode.camera_mode == 'rotate': + activity.globalsnode.camera_mode = 'rotate' + cmsg('camera mode is rotate now') + else: + activity.globalsnode.camera_mode = 'follow' + cmsg('camera mode is normal now') + + elif m in [px+'remove', px+'rm']: + if n == []: + cmsg(f'{px}remove all or {px}remove number in list') + elif n[0] == 'all': + for i in session_players: + i.remove_from_game() + cmsg('Removed All') + else: + try: + r = session_players[int(n[0])] + r.remove_from_game() + cmsg('Removed') # cant use getname() activity alwrady finish + except: + cmsg('could not found player') + elif m in [px+'inv', px+'invisible']: + if n == []: + cmsg(f'help : {px}inv all or {px}inv number of list') + elif n[0] == 'all': + for i in activity_players: + body = i.actor.node + if not body.torso_model == None: + body.head_model = None + body.torso_model = None + body.upper_arm_model = None + body.forearm_model = None + body.pelvis_model = None + body.hand_model = None + body.toes_model = None + body.upper_leg_model = None + body.lower_leg_model = None + body.style = 'cyborg' + cmsg('All invisible now Dont get cought') + else: + cmsg('alwardy invisible') + else: + body = activity_players[int(n[0])].actor.node + is_name = session_players[int(n[0])].getname() + if not body.torso_model == None: + body.head_model = None + body.torso_model = None + body.upper_arm_model = None + body.forearm_model = None + body.pelvis_model = None + body.hand_model = None + body.toes_model = None + body.upper_leg_model = None + body.lower_leg_model = None + body.style = 'cyborg' + cmsg(is_name+' using invisiblelity ') + else: + cmsg('alwardy invisible') + + elif m in [px+'hl', px+'headless']: + if n == []: + cmsg(f'help : {px}spaz all or {px}spaz number of list') + elif n[0] == 'all': + for i in activity_players: + body = i.actor.node + if not body.head_model == None: + body.head_model = None + body.style = 'cyborg' + cmsg('headless ? xD') + else: + cmsg('alwardy headless are you really headless?') + else: + body = activity_players[int(n[0])].actor.node + is_name = session_players[int(n[0])].getname() + if not body.head_model == None: + body.head_model = None + body.style = 'cyborg' + cmsg(is_name+'is headless now xD') + else: + cmsg('alwardy headless are you really headless?') + + elif m in [px+'creepy', px+'creep']: + if n == []: + cmsg(f'use: {px}creepy all or {px}creepy number of list') + elif n[0] == 'all': + for i in activity_players: + body = i.actor.node + body.head_model = None + body.handlemessage(ba.PowerupMessage(poweruptype='punch')) + body.handlemessage(ba.PowerupMessage(poweruptype='shield')) + cmsg('dont creep out childs all will be scared') + else: + try: + body = activity_players[int(n[0])].actor.node + body.head_model = None + body.handlemessage(ba.PowerupMessage(poweruptype='punch')) + body.handlemessage(ba.PowerupMessage(poweruptype='shield')) + cmsg('dont creep out childs all will be scared') + except: + cmsg('could not found player to make') + + elif m in [px+'kill', px+'die']: + if n == []: + cmsg(f'Use : {px}kill all or {px}kill number of list') + elif n[0] == 'all': + for i in activity_players: + i.actor.node.handlemessage(ba.DieMessage()) + cmsg('Killed all') + else: + is_name = session_players[int(n[0])].getname() + activity_players[int(n[0])].actor.node.handlemessage(ba.DieMessage()) + cmsg('Killed '+is_name) + + elif m in [px+'heal', px+'heath']: + if n == []: + cmsg(f'Use: {px}heal all or {px}heal number of list') + elif n[0] == 'all': + for i in activity_players: + i.actor.node.handlemessage(ba.PowerupMessage(poweruptype='health')) + cmsg('Heald all') + else: + is_name = session_players[int(n[0])].getname() + activity_players[int(n[0])].actor.node.handlemessage( + ba.PowerupMessage(poweruptype='health')) + cmsg('Heald '+is_name) + + elif m in [px+'curse', px+'cur']: + if n == []: + cmsg(f'Use: {px}curse all or {px}curse number of list') + elif n[0] == 'all': + for i in activity_players: + i.actor.node.handlemessage(ba.PowerupMessage(poweruptype='curse')) + cmsg('Cursed all') + else: + is_name = session_players[int(n[0])].getname() + activity_players[int(n[0])].actor.node.handlemessage( + ba.PowerupMessage(poweruptype='curse')) + cmsg('Cursed '+is_name) + + elif m in [px+'sleep']: + if n == []: + cmsg(f'Use: {px}sleep all or {px}sleep number of list') + elif n[0] == 'all': + for i in activity_players: + i.actor.node.handlemessage('knockout', 8000) + cmsg('Sleep all its Night :)') + else: + is_name = session_players[int(n[0])].getname() + activity_players[int(n[0])].actor.node.handlemessage('knockout', 8000) + cmsg(is_name+' sleeped now') + + elif m in [px+'sp', px+'superpunch']: + if n == []: + cmsg(f'Use : {px}sp/superpunch all or {px}sp/superpunch number of list') + elif n[0] == 'all': + for i in activity_players: + if not i.actor._punch_power_scale == 15: + i.actor._punch_power_scale = 15 + i.actor._punch_cooldown = 0 + cmsg('Everyone enjoy your Super punches') + else: + i.actor._punch_power_scale = 1.2 + i.actor._punch_cooldown = 400 + cmsg('Super punches off now') + else: + try: + if not activity_players[int(n[0])].actor._punch_power_scale == 15: + is_name = session_players[int(n[0])].getname() + activity_players[int(n[0])].actor._punch_power_scale = 15 + activity_players[int(n[0])].actor._punch_cooldown = 0 + cmsg(is_name+' using super punches get away from him') + else: + activity_players[int(n[0])].actor._punch_power_scale = 1.2 + activity_players[int(n[0])].actor._punch_cooldown = 400 + cmsg(':( ') + except: + pass + + elif m in [px+'gloves', px+'punch']: + if n == []: + cmsg(f'Use: {px}gloves all or {px}gloves number of list') + elif n[0] == 'all': + for i in activity_players: + i.actor.node.handlemessage(ba.PowerupMessage(poweruptype='punch')) + cmsg('Free Gloves enjoy all') + else: + is_name = session_players[int(n[0])].getname() + activity_players[int(n[0])].actor.node.handlemessage( + ba.PowerupMessage(poweruptype='punch')) + cmsg(is_name+' using gloves') + + elif m in [px+'shield', px+'protect']: + if n == []: + cmsg(f'Use: {px}shield all or {px}shield number of list') + elif n[0] == 'all': + for i in activity_players: + i.actor.node.handlemessage(ba.PowerupMessage(poweruptype='shield')) + cmsg('Everyone enjoy free shield :)') + else: + is_name = session_players[int(n[0])].getname() + activity_players[int(n[0])].actor.node.handlemessage( + ba.PowerupMessage(poweruptype='shield')) + cmsg(is_name+' using shield') + + elif m in [px+'freeze', px+'ice']: + if n == []: + cmsg(f'Use: {px}freeze all or {px}freeze number of list') + elif n[0] == 'all': + for i in activity_players: + i.actor.node.handlemessage(ba.FreezeMessage()) + cmsg('Freezed all') + else: + is_name = session_players[int(n[0])].getname() + activity_players[int(n[0])].actor.node.handlemessage(ba.FreezeMessage()) + cmsg('Un freezed '+is_name) + + elif m in [px+'unfreeze', px+'thaw']: + if n == []: + cmsg(f'Use: {px}unfreeze/thaw all or {px}unfreeze/thaw number of list') + elif n[0] == 'all': + for i in activity_players: + i.actor.node.handlemessage(ba.ThawMessage()) + cmsg('Un freezed all ') + else: + is_name = session_players[int(n[0])].getname() + activity_players[int(n[0])].actor.node.handlemessage(ba.ThawMessage()) + cmsg('Un freezed '+is_name) + + elif m in [px+'fall']: + if n == []: + cmsg(f'Use: {px}fall all or {px}fall number of list') + elif n[0] == 'all': + for i in activity_players: + i.actor.node.handlemessage(ba.StandMessage()) + cmsg('Felt everyone') + else: + is_name = session_players[int(n[0])].getname() + activity_players[int(n[0])].actor.node.handlemessage(ba.StandMessage()) + cmsg(is_name+' got felt') + + elif m in [px+'celebrate', px+'celeb']: + if n == []: + cmsg(f'Use: {px}celebrate all or {px}celebrate number of list') + elif n[0] == 'all': + for i in activity_players: + i.actor.node.handlemessage(ba.CelebrateMessage()) + cmsg('Celebrate all :)') + else: + is_name = session_players[int(n[0])].getname() + activity_players[int(n[0])].actor.node.handlemessage(ba.CelebrateMessage()) + cmsg(is_name+' is celebrating bt why?') + + elif m in [px+'fly']: + if n == []: + cmsg(f'Use: {px}fly all or {px}fly number of list') + elif n[0] == 'all': + for i in activity_players: + if not i.actor.node.fly == True: + i.actor.node.fly = True + cmsg('fly all dont go out ok') + else: + i.actor.node.fly = False + cmsg('flying mode off') + else: + try: + is_name = session_players[int(n[0])].getname() + if not activity_players[int(n[0])].actor.node.fly == True: + activity_players[int(n[0])].actor.node.fly = True + cmsg(is_name+' is flying') + else: + activity_players[int(n[0])].actor.node.fly = False + cmsg('fly off :(') + except: + cmsg('player not found') + pass + + elif m in [px+'gm', px+'godmode']: + if n == []: + cmsg(f'Use: {px}gm all or {px}gm number of list') + elif n[0] == 'all': + for i in activity_players: + if not i.actor.node.hockey == True: + i.actor.node.hockey = True + i.actor.node.invincible = True + i.actor._punch_power_scale = 7 + cmsg('Gmed all ') + else: + i.actor.node.hockey = False + i.actor.node.invincible = False + i.actor._punch_power_scale = 1.2 + cmsg('Un gmed all') + else: + try: + is_name = session_players[int(n[0])].getname() + if not activity_players[int(n[0])].actor.node.hockey == True: + activity_players[int(n[0])].actor.node.hockey = True + activity_players[int(n[0])].actor.node.invincible = True + activity_players[int(n[0])].actor._punch_power_scale = 7 + cmsg('Gmed '+is_name) + else: + activity_players[int(n[0])].actor.node.hockey = False + activity_players[int(n[0])].actor.node.invincible = False + activity_players[int(n[0])].actor._punch_power_scale = 1.2 + cmsg('un gmed '+is_name) + except: + cmsg('could not found player') + elif m in [px+'d_bomb', px+'default_bomb']: + if n == []: + cmsg( + f'Use: {px}d_bomb/default_bomb all or {px}d_bomb number of list ,type {px}d_bomb help for help') + elif n[0] == 'help': + cmsg("bombtypes - ['ice', 'impact', 'land_mine', 'normal', 'sticky','tnt']") + elif n[0] in ['ice', 'impact', 'land_mine', 'normal', 'sticky', 'tnt']: + for i in activity_players: + i.actor.bomb_type = n[0] + cmsg('default bomb type - '+str(n[0])+' now') + else: + cmsg('unkwon bombtype , type {px}d_bomb help for help') + + elif m in [px+'d_bomb_count', px+'default_bomb_count', px+'dbc']: + if n == []: + cmsg( + f'Use: {px}d_bomb_count/default_bomb/dbc all or {px}d_bomb_count/default_bomb_count/dbc number of list') + else: + try: + for i in activity_players: + i.actor.set_bomb_count(int(n[0])) + cmsg('default bomb count is '+(str(n[0]))+' now') + except: + cmsg('Must use number to use') + elif m in [px+'credits']: + if n == []: + cmsg(u'\U0001F95A created by Nazz \U0001F95A') + cmsg(u'\U0001F95A Nazz are past/present/future \U0001F95A') + cmsg(u'\U0001F95A everything is Nazz \U0001F95A') # ba.timer(0.05, _update, repeat=True) def same(): - ba.timer(0.5, _cmds._process_cmd, True) + ba.timer(0.5, _cmds._process_cmd, True) # ba_meta export plugin + + class _enableee(ba.Plugin): - same() \ No newline at end of file + same() From 2d294591775e793d537c099651e0dc2ce4013890 Mon Sep 17 00:00:00 2001 From: Loup <90267658+Loup-Garou911XD@users.noreply.github.com> Date: Thu, 3 Nov 2022 22:41:35 +0530 Subject: [PATCH 09/55] Added CustomDeath, MaxPlayers, QuickCustomgame, randomColors, and chat_cmd --- plugins/utilities.json | 77 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 76 insertions(+), 1 deletion(-) diff --git a/plugins/utilities.json b/plugins/utilities.json index d3c9ac1..f62619e 100644 --- a/plugins/utilities.json +++ b/plugins/utilities.json @@ -3,6 +3,81 @@ "description": "Utilities", "plugins_base_url": "http://github.com/bombsquad-community/plugin-manager/{content_type}/{tag}/plugins/utilities", "plugins": { + "CustomDeath": { + "description": "Characters turn to Bones after death", + "external_url": "https://youtube.com/c/JoseANG3LYT", + "authors": [ + { + "name": "JoseAng3l", + "email": null, + "discord": "! JoseANG3L#0268" + } + ], + "versions": { + "1.0.0": null + } + }, + "MaxPlayers": { + "description": "Increase the max player limit of 8 players", + "external_url": "https://youtube.com/c/JoseANG3LYT", + "authors": [ + { + "name": "JoseAng3l", + "email": null, + "discord": "! JoseANG3L#0268" + } + ], + "versions": { + "1.0.0": null + } + }, + "QuickCustomGame": { + "description": "Quckly create a custom game with any gamemode", + "external_url": "https://youtube.com/c/JoseANG3LYT", + "authors": [ + { + "name": "JoseAng3l", + "email": null, + "discord": "! JoseANG3L#0268" + } + ], + "versions": { + "1.0.0": null + } + }, + "RandomColors": { + "description": "Creates patches of random color after bomb explosions", + "external_url": "https://youtube.com/c/JoseANG3LYT", + "authors": [ + { + "name": "JoseAng3l", + "email": null, + "discord": "! JoseANG3L#0268" + } + ], + "versions": { + "1.0.0": null + } + }, + "chat_cmd": { + "description": "chatcmd for a beutiful game - BombSquad OwO,type /help in chat for more info", + "external_url": "", + "authors": [ + { + "name": "IM_NOT_PRANAV#7874", + "email": null, + "discord": "IM_NOT_PRANAV#7874" + }, + { + "name": "FireFighter1037 ", + "email": null, + "discord": null + } + ], + "versions": { + "1.0.0": null + } + }, "mood_light": { "description": "Dynamic lighting in co-op games (adjustable using \"ml\" chat command)", "external_url": "", @@ -304,4 +379,4 @@ } } } -} \ No newline at end of file +} From d513809ad3742a33e7c0a720571f2f50cacf5bf6 Mon Sep 17 00:00:00 2001 From: Loup <90267658+Loup-Garou911XD@users.noreply.github.com> Date: Thu, 3 Nov 2022 22:59:16 +0530 Subject: [PATCH 10/55] Add files via upload --- plugins/minigames/BasketBomb.py | 754 ++++++++++++++++++++++++ plugins/minigames/Boxing.py | 240 ++++++++ plugins/minigames/MeteorShower.py | 406 +++++++++++++ plugins/minigames/SimonSays.py | 333 +++++++++++ plugins/minigames/SquidRace.py | 949 ++++++++++++++++++++++++++++++ plugins/minigames/ZombieHorde.py | 878 +++++++++++++++++++++++++++ 6 files changed, 3560 insertions(+) create mode 100644 plugins/minigames/BasketBomb.py create mode 100644 plugins/minigames/Boxing.py create mode 100644 plugins/minigames/MeteorShower.py create mode 100644 plugins/minigames/SimonSays.py create mode 100644 plugins/minigames/SquidRace.py create mode 100644 plugins/minigames/ZombieHorde.py diff --git a/plugins/minigames/BasketBomb.py b/plugins/minigames/BasketBomb.py new file mode 100644 index 0000000..c9030e5 --- /dev/null +++ b/plugins/minigames/BasketBomb.py @@ -0,0 +1,754 @@ +# Released under the MIT License. See LICENSE for details. +# ba_meta require api 7 +# (see https://ballistica.net/wiki/meta-tag-system) + +from __future__ import annotations + +from typing import TYPE_CHECKING + +import ba, _ba +from bastd.actor.playerspaz import PlayerSpaz +from bastd.actor.scoreboard import Scoreboard +from bastd.actor.powerupbox import PowerupBoxFactory +from bastd.gameutils import SharedObjects +from bastd.actor import playerspaz as ps +from bastd import maps + +if TYPE_CHECKING: + from typing import Any, Sequence, Dict, Type, List, Optional, Union + +bsuSpaz = None + +def getlanguage(text, sub: str = ''): + lang = _ba.app.lang.language + translate = { + "Name": + {"Spanish": "Baloncesto", + "English": "Basketbomb", + "Portuguese": "Basketbomb"}, + "Info": + {"Spanish": "Anota todas las canastas y sé el MVP.", + "English": "Score all the baskets and be the MVP.", + "Portuguese": "Marque cada cesta e seja o MVP."}, + "Info-Short": + {"Spanish": f"Anota {sub} canasta(s) para ganar", + "English": f"Score {sub} baskets to win", + "Portuguese": f"Cestas de {sub} pontos para ganhar"}, + "S: Powerups": + {"Spanish": "Aparecer Potenciadores", + "English": "Powerups Spawn", + "Portuguese": "Habilitar Potenciadores"}, + "S: Velocity": + {"Spanish": "Activar velocidad", + "English": "Enable speed", + "Portuguese": "Ativar velocidade"}, + } + + languages = ['Spanish','Portuguese','English'] + if lang not in languages: lang = 'English' + + if text not in translate: + return text + return translate[text][lang] + +class BallDiedMessage: + def __init__(self, ball: Ball): + self.ball = ball + +class Ball(ba.Actor): + def __init__(self, position: Sequence[float] = (0.0, 1.0, 0.0)): + super().__init__() + shared = SharedObjects.get() + activity = self.getactivity() + velocty = (0.0, 8.0, 0.0) + _scale = 1.2 + + self._spawn_pos = (position[0], position[1] + 0.5, position[2]) + self.last_players_to_touch: Dict[int, Player] = {} + self.scored = False + + assert activity is not None + assert isinstance(activity, BasketGame) + + pmats = [shared.object_material, activity.ball_material] + self.node = ba.newnode('prop', + delegate=self, + attrs={ + 'model': activity.ball_model, + 'color_texture': activity.ball_tex, + 'body': 'sphere', + 'reflection': 'soft', + 'body_scale': 1.0 * _scale, + 'reflection_scale': [1.3], + 'shadow_size': 1.0, + 'gravity_scale': 0.92, + 'density': max(0.4 * _scale, 0.3), + 'position': self._spawn_pos, + 'velocity': velocty, + 'materials': pmats}) + self.scale = scale = 0.25 * _scale + ba.animate(self.node, 'model_scale', {0: 0, 0.2: scale*1.3, 0.26: scale}) + + def handlemessage(self, msg: Any) -> Any: + if isinstance(msg, ba.DieMessage): + assert self.node + self.node.delete() + activity = self._activity() + if activity and not msg.immediate: + activity.handlemessage(BallDiedMessage(self)) + + elif isinstance(msg, ba.OutOfBoundsMessage): + assert self.node + self.node.position = self._spawn_pos + self.node.velocity = (0.0, 0.0, 0.0) + + elif isinstance(msg, ba.HitMessage): + assert self.node + assert msg.force_direction is not None + self.node.handlemessage( + 'impulse', msg.pos[0], msg.pos[1], msg.pos[2], msg.velocity[0], + msg.velocity[1], msg.velocity[2], 1.0 * msg.magnitude, + 1.0 * msg.velocity_magnitude, msg.radius, 0, + msg.force_direction[0], msg.force_direction[1], + msg.force_direction[2]) + + s_player = msg.get_source_player(Player) + if s_player is not None: + activity = self._activity() + if activity: + if s_player in activity.players: + self.last_players_to_touch[s_player.team.id] = s_player + else: + super().handlemessage(msg) + + +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 + +class Points: + postes = dict() + postes['pal_0'] = (10.64702320098877, 0.0000000000000000, 0.0000000000000000) #10.736066818237305, 0.3002409040927887, 0.5281256437301636 + postes['pal_1'] = (-10.64702320098877, 0.0000000000000000, 0.0000000000000000) + +# ba_meta export game +class BasketGame(ba.TeamGameActivity[Player, Team]): + + name = getlanguage('Name') + description = getlanguage('Info') + available_settings = [ + ba.IntSetting( + 'Score to Win', + min_value=1, + default=1, + 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(getlanguage('S: Powerups'), default=True), + ba.BoolSetting(getlanguage('S: Velocity'), default=False), + ba.BoolSetting('Epic Mode', default=False), + ] + default_music = ba.MusicType.HOCKEY + + @classmethod + def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool: + return issubclass(sessiontype, ba.DualTeamSession) + + @classmethod + def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]: + return ['BasketBall Stadium', 'BasketBall Stadium V2'] + + def __init__(self, settings: dict): + super().__init__(settings) + shared = SharedObjects.get() + self._scoreboard = Scoreboard() + self._cheer_sound = ba.getsound('cheer') + self._chant_sound = ba.getsound('crowdChant') + self._foghorn_sound = ba.getsound('foghorn') + self._swipsound = ba.getsound('swip') + self._whistle_sound = ba.getsound('refWhistle') + self.ball_model = ba.getmodel('shield') + self.ball_tex = ba.gettexture('fontExtras3') + self._ball_sound = ba.getsound('bunnyJump') + self._powerups = bool(settings[getlanguage('S: Powerups')]) + self._speed = bool(settings[getlanguage('S: Velocity')]) + self._epic_mode = bool(settings['Epic Mode']) + self.slow_motion = self._epic_mode + + self.ball_material = ba.Material() + self.ball_material.add_actions(actions=(('modify_part_collision', + 'friction', 0.5))) + self.ball_material.add_actions(conditions=('they_have_material', + shared.pickup_material), + actions=('modify_part_collision', + 'collide', True)) + self.ball_material.add_actions( + conditions=( + ('we_are_younger_than', 100), + 'and', + ('they_have_material', shared.object_material), + ), + actions=('modify_node_collision', 'collide', False), + ) + self.ball_material.add_actions(conditions=('they_have_material', + shared.footing_material), + actions=('impact_sound', + self._ball_sound, 0.2, 5)) + + # Keep track of which player last touched the ball + self.ball_material.add_actions( + conditions=('they_have_material', shared.player_material), + actions=(('call', 'at_connect', + self._handle_ball_player_collide), )) + + self._score_region_material = ba.Material() + self._score_region_material.add_actions( + conditions=('they_have_material', self.ball_material), + actions=(('modify_part_collision', 'collide', + True), ('modify_part_collision', 'physical', False), + ('call', 'at_connect', self._handle_score))) + self._ball_spawn_pos: Optional[Sequence[float]] = None + self._score_regions: Optional[List[ba.NodeActor]] = None + self._ball: Optional[Ball] = None + self._score_to_win = int(settings['Score to Win']) + self._time_limit = float(settings['Time Limit']) + + def get_instance_description(self) -> Union[str, Sequence]: + return getlanguage('Info-Short', sub=self._score_to_win) + + def get_instance_description_short(self) -> Union[str, Sequence]: + return getlanguage('Info-Short', sub=self._score_to_win) + + def on_begin(self) -> None: + super().on_begin() + + self.setup_standard_time_limit(self._time_limit) + + if self._powerups: + self.setup_standard_powerup_drops() + + self._ball_spawn_pos = self.map.get_flag_position(None) + self._spawn_ball() + + defs = self.map.defs + self._score_regions = [] + self._score_regions.append( + ba.NodeActor( + ba.newnode('region', + attrs={ + 'position': defs.boxes['goal1'][0:3], + 'scale': defs.boxes['goal1'][6:9], + 'type': 'box', + 'materials': [] + }))) + self._score_regions.append( + ba.NodeActor( + ba.newnode('region', + attrs={ + 'position': defs.boxes['goal2'][0:3], + 'scale': defs.boxes['goal2'][6:9], + 'type': 'box', + 'materials': [] + }))) + self._update_scoreboard() + ba.playsound(self._chant_sound) + + for id, team in enumerate(self.teams): + self.postes(id) + + def on_team_join(self, team: Team) -> None: + self._update_scoreboard() + + def _handle_ball_player_collide(self) -> None: + collision = ba.getcollision() + try: + ball = collision.sourcenode.getdelegate(Ball, True) + player = collision.opposingnode.getdelegate(PlayerSpaz, + True).getplayer( + Player, True) + except ba.NotFoundError: + return + + ball.last_players_to_touch[player.team.id] = player + + def _kill_ball(self) -> None: + self._ball = None + + def _handle_score(self, team_index: int = None) -> None: + assert self._ball is not None + assert self._score_regions is not None + + if self._ball.scored: + return + + region = ba.getcollision().sourcenode + index = 0 + for index in range(len(self._score_regions)): + if region == self._score_regions[index].node: + break + + if team_index is not None: + index = team_index + + for team in self.teams: + if team.id == index: + scoring_team = team + team.score += 1 + + for player in team.players: + if player.actor: + player.actor.handlemessage(ba.CelebrateMessage(2.0)) + + if (scoring_team.id in self._ball.last_players_to_touch + and self._ball.last_players_to_touch[scoring_team.id]): + self.stats.player_scored( + self._ball.last_players_to_touch[scoring_team.id], + 100, big_message=True) + + if team.score >= self._score_to_win: + self.end_game() + + #ba.playsound(self._foghorn_sound) + ba.playsound(self._cheer_sound) + + self._ball.scored = True + + # Kill the ball (it'll respawn itself shortly). + ba.timer(1.0, self._kill_ball) + + light = ba.newnode('light', + attrs={ + 'position': ba.getcollision().position, + 'height_attenuated': False, + 'color': (1, 0, 0) + }) + ba.animate(light, 'intensity', {0: 0, 0.5: 1, 1.0: 0}, loop=True) + ba.timer(1.0, light.delete) + + ba.cameraflash(duration=10.0) + self._update_scoreboard() + + 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 _update_scoreboard(self) -> None: + winscore = self._score_to_win + for id, team in enumerate(self.teams): + self._scoreboard.set_team_value(team, team.score, winscore) + #self.postes(id) + + def spawn_player(self, player: Player) -> ba.Actor: + if bsuSpaz is None: + spaz = self.spawn_player_spaz(player) + else: + ps.PlayerSpaz = bsuSpaz.BskSpaz + spaz = self.spawn_player_spaz(player) + ps.PlayerSpaz = bsuSpaz.OldPlayerSpaz + + if self._speed: + spaz.node.hockey = True + return spaz + + def handlemessage(self, msg: Any) -> Any: + if isinstance(msg, ba.PlayerDiedMessage): + super().handlemessage(msg) + self.respawn_player(msg.getplayer(Player)) + elif isinstance(msg, BallDiedMessage): + if not self.has_ended(): + ba.timer(3.0, self._spawn_ball) + else: + super().handlemessage(msg) + + def postes(self, team_id: int): + if not hasattr(self._map, 'poste_'+str(team_id)): + setattr(self._map, 'poste_'+str(team_id), + Palos(team=team_id, + position=Points.postes['pal_' + + str(team_id)]).autoretain()) + + def _flash_ball_spawn(self) -> None: + light = ba.newnode('light', + attrs={ + 'position': self._ball_spawn_pos, + 'height_attenuated': False, + 'color': (1, 0, 0) + }) + ba.animate(light, 'intensity', {0.0: 0, 0.25: 1, 0.5: 0}, loop=True) + ba.timer(1.0, light.delete) + + def _spawn_ball(self) -> None: + ba.playsound(self._swipsound) + ba.playsound(self._whistle_sound) + self._flash_ball_spawn() + assert self._ball_spawn_pos is not None + self._ball = Ball(position=self._ball_spawn_pos) + +class Aro(ba.Actor): + def __init__(self, team: int = 0, + position: Sequence[float] = (0.0, 1.0, 0.0)): + super().__init__() + act = self.getactivity() + shared = SharedObjects.get() + setattr(self, 'team', team) + setattr(self, 'locs', []) + + # Material Para; Traspasar Objetos + self.no_collision = ba.Material() + self.no_collision.add_actions( + actions=(('modify_part_collision', 'collide', False))) + + self.collision = ba.Material() + self.collision.add_actions( + actions=(('modify_part_collision', 'collide', True))) + + # Score + self._score_region_material = ba.Material() + self._score_region_material.add_actions( + conditions=('they_have_material', act.ball_material), + actions=(('modify_part_collision', 'collide', + True), ('modify_part_collision', 'physical', False), + ('call', 'at_connect', self._annotation))) + + self._spawn_pos = (position[0], position[1], position[2]) + self._materials_region0 = [self.collision, + shared.footing_material] + + model = None + tex = ba.gettexture('null') + + pmats = [self.no_collision] + self.node = ba.newnode('prop', + delegate=self, + attrs={ + 'model': model, + 'color_texture': tex, + 'body': 'box', + 'reflection': 'soft', + 'reflection_scale': [1.5], + 'shadow_size': 0.1, + 'position': self._spawn_pos, + 'materials': pmats}) + + self.scale = scale = 1.4 + ba.animate(self.node, 'model_scale', {0: 0}) + + pos = (position[0], position[1]+0.6, position[2]) + self.regions: List[ba.Node] = [ + ba.newnode('region', + attrs={'position': position, + 'scale': (0.6, 0.05, 0.6), + 'type': 'box', + 'materials': self._materials_region0}), + + ba.newnode('region', + attrs={'position': pos, + 'scale': (0.5, 0.3, 0.9), + 'type': 'box', + 'materials': [self._score_region_material]}) + ] + self.regions[0].connectattr('position', self.node, 'position') + #self.regions[0].connectattr('position', self.regions[1], 'position') + + locs_count = 9 + pos = list(position) + + try: + id = 0 if team == 1 else 1 + color = act.teams[id].color + except: color = (1,1,1) + + while locs_count > 1: + scale = (1.5 * 0.1 * locs_count) + 0.8 + + self.locs.append(ba.newnode('locator', + owner=self.node, + attrs={'shape': 'circleOutline', + 'position': pos, + 'color': color, + 'opacity': 1.0, + 'size': [scale], + 'draw_beauty': True, + 'additive': False})) + + pos[1] -= 0.1 + locs_count -= 1 + + def _annotation(self): + assert len(self.regions) >= 2 + ball = self.getactivity()._ball + + if ball: + p = self.regions[0].position + ball.node.position = p + ball.node.velocity = (0.0, 0.0, 0.0) + + act = self.getactivity() + act._handle_score(self.team) + + def handlemessage(self, msg: Any) -> Any: + if isinstance(msg, ba.DieMessage): + if self.node.exists(): + self.node.delete() + else: + super().handlemessage(msg) + +class Cuadro(ba.Actor): + def __init__(self, team: int = 0, + position: Sequence[float] = (0.0, 1.0, 0.0)): + super().__init__() + act = self.getactivity() + shared = SharedObjects.get() + setattr(self, 'locs', []) + + self.collision = ba.Material() + self.collision.add_actions( + actions=(('modify_part_collision', 'collide', True))) + + pos = (position[0], position[1]+0.9, position[2]+1.5) + self.region: ba.Node = ba.newnode('region', + attrs={'position': pos, + 'scale': (0.5, 2.7, 2.5), + 'type': 'box', + 'materials': [self.collision, + shared.footing_material]}) + + #self.shield = ba.newnode('shield', attrs={'radius': 1.0, 'color': (0,10,0)}) + #self.region.connectattr('position', self.shield, 'position') + + position = (position[0], position[1], position[2]+0.09) + pos = list(position) + oldpos = list(position) + old_count = 14 + + count = old_count + count_y = 9 + + try: + id = 0 if team == 1 else 1 + color = act.teams[id].color + except: color = (1,1,1) + + while(count_y != 1): + + while(count != 1): + pos[2] += 0.19 + + self.locs.append( + ba.newnode('locator', + owner=self.region, + attrs={'shape': 'circle', + 'position': pos, + 'size': [0.5], + 'color': color, + 'opacity': 1.0, + 'draw_beauty': True, + 'additive': False})) + count -= 1 + + + count = old_count + pos[1] += 0.2 + pos[2] = oldpos[2] + count_y -= 1 + + def handlemessage(self, msg: Any) -> Any: + if isinstance(msg, ba.DieMessage): + if self.node.exists(): + self.node.delete() + else: + super().handlemessage(msg) + +class Palos(ba.Actor): + def __init__(self, team: int = 0, + position: Sequence[float] = (0.0, 1.0, 0.0)): + super().__init__() + shared = SharedObjects.get() + activity = self.getactivity() + self._pos = position + self.aro = None + self.cua = None + + # Material Para; Traspasar Objetos + self.no_collision = ba.Material() + self.no_collision.add_actions( + actions=(('modify_part_collision', 'collide', False))) + + # + self.collision = ba.Material() + self.collision.add_actions( + actions=(('modify_part_collision', 'collide', True))) + + # Spawn just above the provided point. + self._spawn_pos = (position[0], position[2]+2.5, position[2]) + + model = ba.getmodel('flagPole') + tex = ba.gettexture('flagPoleColor') + + pmats = [self.no_collision] + self.node = ba.newnode('prop', + delegate=self, + attrs={ + 'model': model, + 'color_texture': tex, + 'body': 'puck', + 'reflection': 'soft', + 'reflection_scale': [2.6], + 'shadow_size': 0, + 'is_area_of_interest': True, + 'position': self._spawn_pos, + 'materials': pmats + }) + self.scale = scale = 4.0 + ba.animate(self.node, 'model_scale', {0: scale}) + + self.loc = ba.newnode('locator', + owner=self.node, + attrs={'shape': 'circle', + 'position': position, + 'color': (1,1,0), + 'opacity': 1.0, + 'draw_beauty': False, + 'additive': True}) + + self._y = _y = 0.30 + _x = -0.25 if team == 1 else 0.25 + _pos = (position[0]+_x, position[1]-1.5 + _y, position[2]) + self.region = ba.newnode('region', + attrs={ + 'position': _pos, + 'scale': (0.4, 8, 0.4), + 'type': 'box', + 'materials': [self.collision]}) + self.region.connectattr('position', self.node, 'position') + + _y = self._y + position = self._pos + if team == 0: + pos = (position[0]-0.8, position[1] + 2.0 + _y, position[2]) + else: pos = (position[0]+0.8, position[1] + 2.0 + _y, position[2]) + + if self.aro is None: + self.aro = Aro(team, pos).autoretain() + + if self.cua is None: + pos = (position[0], position[1] + 1.8 + _y, position[2]-1.4) + self.cua = Cuadro(team, pos).autoretain() + + def handlemessage(self, msg: Any) -> Any: + if isinstance(msg, ba.DieMessage): + if self.node.exists(): + self.node.delete() + else: + super().handlemessage(msg) + +class BasketMap(maps.FootballStadium): + name = 'BasketBall Stadium' + + @classmethod + def get_play_types(cls) -> List[str]: + """Return valid play types for this map.""" + return [] + + def __init__(self) -> None: + super().__init__() + + gnode = ba.getactivity().globalsnode + gnode.tint = [(0.806, 0.8, 1.0476), (1.3, 1.2, 1.0)][0] + gnode.ambient_color = (1.3, 1.2, 1.0) + gnode.vignette_outer = (0.57, 0.57, 0.57) + gnode.vignette_inner = (0.9, 0.9, 0.9) + gnode.vr_camera_offset = (0, -0.8, -1.1) + gnode.vr_near_clip = 0.5 + +class BasketMapV2(maps.HockeyStadium): + name = 'BasketBall Stadium V2' + + def __init__(self) -> None: + super().__init__() + + shared = SharedObjects.get() + self.node.materials = [shared.footing_material] + self.node.collide_model = ba.getcollidemodel('footballStadiumCollide') + self.node.model = None + self.stands.model = None + self.floor.reflection = 'soft' + self.floor.reflection_scale = [1.6] + self.floor.color = (1.1, 0.05, 0.8) + + self.background = ba.newnode('terrain', + attrs={'model': ba.getmodel('thePadBG'), + 'lighting': False, + 'background': True, + 'color': (1.0, 0.2, 1.0), + 'color_texture': ba.gettexture('menuBG')}) + + gnode = ba.getactivity().globalsnode + gnode.floor_reflection = True + gnode.debris_friction = 0.3 + gnode.debris_kill_height = -0.3 + gnode.tint = [(1.2, 1.3, 1.33), (0.7, 0.9, 1.0)][1] + gnode.ambient_color = (1.15, 1.25, 1.6) + gnode.vignette_outer = (0.66, 0.67, 0.73) + gnode.vignette_inner = (0.93, 0.93, 0.95) + gnode.vr_camera_offset = (0, -0.8, -1.1) + gnode.vr_near_clip = 0.5 + self.is_hockey = False + + ################## + self.collision = ba.Material() + self.collision.add_actions( + actions=(('modify_part_collision', 'collide', True))) + + self.regions: List[ba.Node] = [ + ba.newnode('region', + attrs={'position': (12.676897048950195, 0.2997918128967285, 5.583303928375244), + 'scale': (1.01, 12, 28), + 'type': 'box', + 'materials': [self.collision]}), + + ba.newnode('region', + attrs={'position': (11.871315956115723, 0.29975247383117676, 5.711406707763672), + 'scale': (50, 12, 0.9), + 'type': 'box', + 'materials': [self.collision]}), + + ba.newnode('region', + attrs={'position': (-12.776557922363281, 0.30036890506744385, 4.96237850189209), + 'scale': (1.01, 12, 28), + 'type': 'box', + 'materials': [self.collision]}), + ] + +ba._map.register_map(BasketMap) +ba._map.register_map(BasketMapV2) \ No newline at end of file diff --git a/plugins/minigames/Boxing.py b/plugins/minigames/Boxing.py new file mode 100644 index 0000000..0a6a4b2 --- /dev/null +++ b/plugins/minigames/Boxing.py @@ -0,0 +1,240 @@ +# ba_meta require api 7 +# (see https://ballistica.net/wiki/meta-tag-system) + +from __future__ import annotations + +from typing import TYPE_CHECKING + +import ba +from bastd.actor.playerspaz import PlayerSpaz +from bastd.actor.scoreboard import Scoreboard +from bastd.game.deathmatch import DeathMatchGame + +if TYPE_CHECKING: + from typing import Any, Sequence + + +lang = ba.app.lang.language + +if lang == 'Spanish': + name = 'Super Boxeo' + description = ('¡Sin bombas!\n' + '¡Noquea a los enemigos con tus propias manos!\n') + super_jump_text = 'Super Salto' + enable_powerups = 'Habilitar Potenciadores' +else: + name = 'Super Boxing' + description = ('No bombs!\n' + 'Knock out your enemies using your bare hands!\n') + super_jump_text = 'Super Jump' + enable_powerups = 'Enable Powerups' + + +class NewPlayerSpaz(PlayerSpaz): + + def __init__(self, + player: ba.Player, + color: Sequence[float] = (1.0, 1.0, 1.0), + highlight: Sequence[float] = (0.5, 0.5, 0.5), + character: str = 'Spaz', + powerups_expire: bool = True, + super_jump: bool = False): + super().__init__(player=player, + color=color, + highlight=highlight, + character=character, + powerups_expire=powerups_expire) + from bastd.gameutils import SharedObjects + shared = SharedObjects.get() + self._super_jump = super_jump + self.jump_mode = False + self.super_jump_material = ba.Material() + self.super_jump_material.add_actions( + conditions=('they_have_material', shared.footing_material), + actions=( + ('call', 'at_connect', ba.Call(self.jump_state, True)), + ('call', 'at_disconnect', ba.Call(self.jump_state, False)) + ), + ) + self.node.roller_materials += (self.super_jump_material, ) + + def jump_state(self, mode: bool) -> None: + self.jump_mode = mode + + def on_jump_press(self) -> None: + """ + Called to 'press jump' on this spaz; + used by player or AI connections. + """ + if not self.node: + return + t_ms = ba.time(timeformat=ba.TimeFormat.MILLISECONDS) + assert isinstance(t_ms, int) + if t_ms - self.last_jump_time_ms >= self._jump_cooldown: + self.node.jump_pressed = True + self.last_jump_time_ms = t_ms + if self._player.is_alive() and self.jump_mode and ( + self._super_jump): + def do_jump(): + self.node.handlemessage( + 'impulse', + self.node.position[0], + self.node.position[1], + self.node.position[2], + 0, 0, 0, 150, 150, 0, 0, 0, 1, 0 + ) + ba.timer(0.0, do_jump) + ba.timer(0.1, do_jump) + ba.timer(0.2, do_jump) + self._turbo_filter_add_press('jump') + + +# ba_meta export game +class BoxingGame(DeathMatchGame): + + name = name + description = description + + @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(super_jump_text, default=False), + ba.BoolSetting(enable_powerups, default=False), + ba.BoolSetting('Epic Mode', default=False), + ] + + # In teams mode, a suicide gives a point to the other team, but in + # free-for-all it subtracts from your own score. By default we clamp + # this at zero to benefit new players, but pro players might like to + # be able to go negative. (to avoid a strategy of just + # suiciding until you get a good drop) + if issubclass(sessiontype, ba.FreeForAllSession): + settings.append( + ba.BoolSetting('Allow Negative Scores', default=False) + ) + + return settings + + def __init__(self, settings: dict): + super().__init__(settings) + self._scoreboard = Scoreboard() + self._score_to_win: int | None = 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._super_jump = bool(settings[super_jump_text]) + self._enable_powerups = bool(settings[enable_powerups]) + + # Base class overrides. + self.slow_motion = self._epic_mode + self.default_music = ( + ba.MusicType.EPIC if self._epic_mode else ba.MusicType.TO_THE_DEATH + ) + + def on_begin(self) -> None: + ba.TeamGameActivity.on_begin(self) + self.setup_standard_time_limit(self._time_limit) + if self._enable_powerups: + self.setup_standard_powerup_drops() + + # Base kills needed to win on the size of the largest team. + self._score_to_win = self._kills_to_win_per_player * max( + 1, max(len(t.players) for t in self.teams) + ) + self._update_scoreboard() + + def _standard_drop_powerup(self, index: int, expire: bool = True) -> None: + # pylint: disable=cyclic-import + from bastd.actor.powerupbox import PowerupBox, PowerupBoxFactory + + PowerupBox( + position=self.map.powerup_spawn_points[index], + poweruptype=PowerupBoxFactory.get().get_random_powerup_type( + excludetypes=['triple_bombs','ice_bombs','impact_bombs', + 'land_mines','sticky_bombs','punch'] + ), + expire=expire, + ).autoretain() + + def spawn_player(self, player: Player) -> ba.Actor: + import random + from ba import _math + from ba._gameutils import animate + from ba._coopsession import CoopSession + + if isinstance(self.session, ba.DualTeamSession): + position = self.map.get_start_position(player.team.id) + else: + # otherwise do free-for-all spawn locations + position = self.map.get_ffa_start_position(self.players) + angle = None + name = player.getname() + color = player.color + highlight = player.highlight + + light_color = _math.normalized_color(color) + display_color = ba.safecolor(color, target_intensity=0.75) + + spaz = NewPlayerSpaz(color=color, + highlight=highlight, + character=player.character, + player=player, + super_jump=self._super_jump) + + player.actor = spaz + assert spaz.node + + spaz.node.name = name + spaz.node.name_color = display_color + + # Move to the stand position and add a flash of light. + spaz.handlemessage( + ba.StandMessage( + position, + angle if angle is not None else random.uniform(0, 360))) + ba.playsound(self._spawn_sound, 1, position=spaz.node.position) + light = ba.newnode('light', attrs={'color': light_color}) + spaz.node.connectattr('position', light, 'position') + animate(light, 'intensity', {0: 0, 0.25: 1, 0.5: 0}) + ba.timer(0.5, light.delete) + + # custom + spaz.connect_controls_to_player(enable_bomb=False) + spaz.equip_boxing_gloves() + + return spaz diff --git a/plugins/minigames/MeteorShower.py b/plugins/minigames/MeteorShower.py new file mode 100644 index 0000000..149f2a9 --- /dev/null +++ b/plugins/minigames/MeteorShower.py @@ -0,0 +1,406 @@ +# ba_meta require api 7 +# (see https://ballistica.net/wiki/meta-tag-system) + +from __future__ import annotations + +import random +from typing import TYPE_CHECKING + +import ba +from bastd.actor.bomb import Bomb +from bastd.actor.onscreentimer import OnScreenTimer + +if TYPE_CHECKING: + from typing import Any, Sequence + + +lang = ba.app.lang.language + +if lang == 'Spanish': + name = 'Lluvia de Meteoritos v2' + bomb_type = 'Tipo de Bomba' + ice = 'hielo' + sticky = 'pegajosa' + impact = 'insta-bomba' + land_mine = 'mina terrestre' + random_bomb = 'aleatoria' + normal_rain = 'Lluvia Normal' + frozen_rain = 'Lluvia Congelada' + sticky_rain = 'Lluvia Pegajosa' + impact_rain = 'Lluvia de Impacto' + mine_rain = 'Lluvia de Minas' + tnt_rain = 'Lluvia de TNT' + random_rain = 'Lluvia Aleatoria' +else: + name = 'Meteor Shower v2' + bomb_type = 'Bomb Type' + ice = 'ice' + sticky = 'sticky' + impact = 'impact' + land_mine = 'land mine' + random_bomb = 'random' + normal_rain = 'Normal Rain' + frozen_rain = 'Frozen Rain' + sticky_rain = 'Sticky Rain' + impact_rain = 'Impact Rain' + mine_rain = 'Mine Rain' + tnt_rain = 'TNT Rain' + random_rain = 'Random Rain' + + +class Player(ba.Player['Team']): + """Our player type for this game.""" + + def __init__(self) -> None: + super().__init__() + self.death_time: float | None = None + + +class Team(ba.Team[Player]): + """Our team type for this game.""" + + +# ba_meta export game +class MeteorShowerv2Game(ba.TeamGameActivity[Player, Team]): + """Minigame involving dodging falling bombs.""" + + name = name + description = 'Dodge the falling bombs.' + scoreconfig = ba.ScoreConfig( + label='Survived', scoretype=ba.ScoreType.MILLISECONDS, version='B' + ) + + # Print messages when players die (since its meaningful in this game). + announce_player_deaths = True + + # Don't allow joining after we start + # (would enable leave/rejoin tomfoolery). + allow_mid_activity_joins = False + + @classmethod + def get_available_settings( + cls, sessiontype: type[ba.Session] + ) -> list[ba.Setting]: + settings = [ + ba.IntChoiceSetting( + bomb_type, + choices=[ + ('normal', 0), + (ice, 1), + (sticky, 2), + (impact, 3), + (land_mine, 4), + ('tnt', 5), + (random_bomb, 6) + ], + default=0, + ), + ba.BoolSetting('Epic Mode', default=False), + ] + return settings + + # We're currently hard-coded for one map. + @classmethod + def get_supported_maps(cls, sessiontype: type[ba.Session]) -> list[str]: + return ['Rampage'] + + # We support teams, free-for-all, and co-op sessions. + @classmethod + def supports_session_type(cls, sessiontype: type[ba.Session]) -> bool: + return ( + issubclass(sessiontype, ba.DualTeamSession) + or issubclass(sessiontype, ba.FreeForAllSession) + or issubclass(sessiontype, ba.CoopSession) + ) + + def __init__(self, settings: dict): + super().__init__(settings) + btype = int(settings[bomb_type]) + if btype == 0: + newbtype = 'normal' + elif btype == 1: + newbtype = 'ice' + elif btype == 2: + newbtype = 'sticky' + elif btype == 3: + newbtype = 'impact' + elif btype == 4: + newbtype = 'land_mine' + elif btype == 5: + newbtype = 'tnt' + else: + newbtype = 'random' + self._bomb_type = newbtype + self._epic_mode = settings.get('Epic Mode', False) + self._last_player_death_time: float | None = None + self._meteor_time = 2.0 + self._timer: OnScreenTimer | None = None + + # Some base class overrides: + self.default_music = ( + ba.MusicType.EPIC if self._epic_mode else ba.MusicType.SURVIVAL + ) + if self._epic_mode: + self.slow_motion = True + + def on_begin(self) -> None: + super().on_begin() + + # Drop a wave every few seconds.. and every so often drop the time + # between waves ..lets have things increase faster if we have fewer + # players. + delay = 5.0 if len(self.players) > 2 else 2.5 + if self._epic_mode: + delay *= 0.25 + ba.timer(delay, self._decrement_meteor_time, repeat=True) + + # Kick off the first wave in a few seconds. + delay = 3.0 + if self._epic_mode: + delay *= 0.25 + ba.timer(delay, self._set_meteor_timer) + + self._timer = OnScreenTimer() + self._timer.start() + + # Check for immediate end (if we've only got 1 player, etc). + ba.timer(5.0, self._check_end_game) + + def on_player_leave(self, player: Player) -> None: + # Augment default behavior. + super().on_player_leave(player) + + # A departing player may trigger game-over. + self._check_end_game() + + # overriding the default character spawning.. + def spawn_player(self, player: Player) -> ba.Actor: + 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_bomb=False, enable_pickup=False + ) + + # Also lets have them make some noise when they die. + spaz.play_big_death_sound = True + return spaz + + # Various high-level game events come through this method. + def handlemessage(self, msg: Any) -> Any: + if isinstance(msg, ba.PlayerDiedMessage): + + # Augment standard behavior. + super().handlemessage(msg) + + curtime = ba.time() + + # Record the player's moment of death. + # assert isinstance(msg.spaz.player + msg.getplayer(Player).death_time = curtime + + # In co-op mode, end the game the instant everyone dies + # (more accurate looking). + # In teams/ffa, allow a one-second fudge-factor so we can + # get more draws if players die basically at the same time. + if isinstance(self.session, ba.CoopSession): + # Teams will still show up if we check now.. check in + # the next cycle. + ba.pushcall(self._check_end_game) + + # Also record this for a final setting of the clock. + self._last_player_death_time = curtime + else: + ba.timer(1.0, self._check_end_game) + + else: + # Default handler: + return super().handlemessage(msg) + return None + + def _check_end_game(self) -> None: + living_team_count = 0 + for team in self.teams: + for player in team.players: + if player.is_alive(): + living_team_count += 1 + break + + # In co-op, we go till everyone is dead.. otherwise we go + # until one team remains. + if isinstance(self.session, ba.CoopSession): + if living_team_count <= 0: + self.end_game() + else: + if living_team_count <= 1: + self.end_game() + + def _set_meteor_timer(self) -> None: + ba.timer( + (1.0 + 0.2 * random.random()) * self._meteor_time, + self._drop_bomb_cluster, + ) + + def _drop_bomb_cluster(self) -> None: + + # Random note: code like this is a handy way to plot out extents + # and debug things. + loc_test = False + if loc_test: + ba.newnode('locator', attrs={'position': (8, 6, -5.5)}) + ba.newnode('locator', attrs={'position': (8, 6, -2.3)}) + ba.newnode('locator', attrs={'position': (-7.3, 6, -5.5)}) + ba.newnode('locator', attrs={'position': (-7.3, 6, -2.3)}) + + # Drop several bombs in series. + delay = 0.0 + for _i in range(random.randrange(1, 3)): + # Drop them somewhere within our bounds with velocity pointing + # toward the opposite side. + pos = ( + -7.3 + 15.3 * random.random(), + 11, + -5.57 + 2.1 * random.random(), + ) + dropdir = -1.0 if pos[0] > 0 else 1.0 + vel = ( + (-5.0 + random.random() * 30.0) * dropdir, + random.uniform(-3.066, -4.12), + 0, + ) + ba.timer(delay, ba.Call(self._drop_bomb, pos, vel)) + delay += 0.1 + self._set_meteor_timer() + + def _drop_bomb( + self, position: Sequence[float], velocity: Sequence[float] + ) -> None: + if self._bomb_type == 'tnt': + bomb_type = random.choice(['tnt','tnt','tnt','tnt','impact']) + elif self._bomb_type == 'land_mine': + bomb_type = random.choice([ + 'land_mine','land_mine','land_mine','land_mine','impact']) + elif self._bomb_type == 'random': + bomb_type = random.choice([ + 'normal','ice','sticky','impact','land_mine','tnt']) + else: + bomb_type = self._bomb_type + Bomb(position=position, + velocity=velocity, + bomb_type=bomb_type).autoretain() + + def _decrement_meteor_time(self) -> None: + self._meteor_time = max(0.01, self._meteor_time * 0.9) + + def end_game(self) -> None: + cur_time = ba.time() + assert self._timer is not None + start_time = self._timer.getstarttime() + + # Mark death-time as now for any still-living players + # and award players points for how long they lasted. + # (these per-player scores are only meaningful in team-games) + for team in self.teams: + for player in team.players: + survived = False + + # Throw an extra fudge factor in so teams that + # didn't die come out ahead of teams that did. + if player.death_time is None: + survived = True + player.death_time = cur_time + 1 + + # Award a per-player score depending on how many seconds + # they lasted (per-player scores only affect teams mode; + # everywhere else just looks at the per-team score). + score = int(player.death_time - self._timer.getstarttime()) + if survived: + score += 50 # A bit extra for survivors. + self.stats.player_scored(player, score, screenmessage=False) + + # Stop updating our time text, and set the final time to match + # exactly when our last guy died. + self._timer.stop(endtime=self._last_player_death_time) + + # Ok now calc game results: set a score for each team and then tell + # the game to end. + results = ba.GameResults() + + # Remember that 'free-for-all' mode is simply a special form + # of 'teams' mode where each player gets their own team, so we can + # just always deal in teams and have all cases covered. + for team in self.teams: + + # Set the team score to the max time survived by any player on + # that team. + longest_life = 0.0 + for player in team.players: + assert player.death_time is not None + longest_life = max(longest_life, player.death_time - start_time) + + # Submit the score value in milliseconds. + results.set_team_score(team, int(1000.0 * longest_life)) + + self.end(results=results) + + +# ba_meta export plugin +class MeteorShowerv2Coop(ba.Plugin): + def on_app_running(self) -> None: + ba.app.add_coop_practice_level( + ba.Level( + normal_rain, + gametype=MeteorShowerv2Game, + settings={bomb_type: 0}, + preview_texture_name='rampagePreview', + ) + ) + ba.app.add_coop_practice_level( + ba.Level( + frozen_rain, + gametype=MeteorShowerv2Game, + settings={bomb_type: 1}, + preview_texture_name='rampagePreview', + ) + ) + ba.app.add_coop_practice_level( + ba.Level( + sticky_rain, + gametype=MeteorShowerv2Game, + settings={bomb_type: 2}, + preview_texture_name='rampagePreview', + ) + ) + ba.app.add_coop_practice_level( + ba.Level( + impact_rain, + gametype=MeteorShowerv2Game, + settings={bomb_type: 3}, + preview_texture_name='rampagePreview', + ) + ) + ba.app.add_coop_practice_level( + ba.Level( + mine_rain, + gametype=MeteorShowerv2Game, + settings={bomb_type: 4}, + preview_texture_name='rampagePreview', + ) + ) + ba.app.add_coop_practice_level( + ba.Level( + tnt_rain, + gametype=MeteorShowerv2Game, + settings={bomb_type: 5}, + preview_texture_name='rampagePreview', + ) + ) + ba.app.add_coop_practice_level( + ba.Level( + random_rain, + gametype=MeteorShowerv2Game, + settings={bomb_type: 6}, + preview_texture_name='rampagePreview', + ) + ) diff --git a/plugins/minigames/SimonSays.py b/plugins/minigames/SimonSays.py new file mode 100644 index 0000000..151963d --- /dev/null +++ b/plugins/minigames/SimonSays.py @@ -0,0 +1,333 @@ +#SimonSays +# you had really better do what Simon says... +# ba_meta require api 7 +from __future__ import annotations + +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from typing import Any, Union, Sequence + +from ba import _gameutils +import ba +import random + +class CustomText(ba.Actor): + """Text that pops up above a position to denote something special. + + category: Gameplay Classes + """ + + def __init__(self, + text: Union[str, ba.Lstr], + position: Sequence[float] = (0.0, 0.0, 0.0), + color: Sequence[float] = (1.0, 1.0, 1.0, 1.0), + random_offset: float = 0.5, + duration: float = 1.5, + offset: Sequence[float] = (0.0, 0.0, 0.0), + scale: float = 1.0): + super().__init__() + if len(color) == 3: + color = (color[0], color[1], color[2], 1.0) + pos = (position[0] + offset[0] + random_offset * + (0.5 - random.random()), position[1] + offset[0] + + random_offset * (0.5 - random.random()), position[2] + + offset[0] + random_offset * (0.5 - random.random())) + self.node = ba.newnode('text', + attrs={ + 'text': text, + 'in_world': True, + 'shadow': 1.0, + 'flatness': 1.0, + 'h_align': 'center'},delegate=self) + lifespan = duration + ba.animate( + self.node, 'scale', { + 0: 0.0, + lifespan * 0.11: 0.020 * 0.7 * scale, + lifespan * 0.16: 0.013 * 0.7 * scale, + lifespan * 0.25: 0.014 * 0.7 * scale + }) + self._tcombine = ba.newnode('combine', + owner=self.node, + attrs={ + 'input0': pos[0], + 'input2': pos[2], + 'size': 3 + }) + ba.animate(self._tcombine, 'input1', { + 0: pos[1] + 1.5, + lifespan: pos[1] + 2.0 + }) + self._tcombine.connectattr('output', self.node, 'position') + # fade our opacity in/out + self._combine = ba.newnode('combine', + owner=self.node, + attrs={ + 'input0': color[0], + 'input1': color[1], + 'input2': color[2], + 'size': 4 + }) + for i in range(4): + ba.animate( + self._combine, 'input' + str(i), { + 0.13 * lifespan: color[i], + 0.18 * lifespan: 4.0 * color[i], + 0.22 * lifespan: color[i]}) + ba.animate(self._combine, 'input3', { + 0: 0, + 0.1 * lifespan: color[3], + 0.7 * lifespan: color[3], + lifespan: 0}) + self._combine.connectattr('output', self.node, 'color') + self._die_timer = ba.Timer( + lifespan, ba.WeakCall(self.handlemessage, ba.DieMessage())) + def handlemessage(self, msg: Any) -> Any: + assert not self.expired + if isinstance(msg, ba.DieMessage): + if self.node: + self.node.delete() + else: + super().handlemessage(msg) + +class Player(ba.Player['Team']): + """Our player type for this game.""" + def __init__(self) -> None: + self.score = 0 + +class Team(ba.Team[Player]): + """Our team type for this game.""" + + def __init__(self) -> None: + self.score = 0 + +# ba_meta export game +class SimonSays(ba.TeamGameActivity[Player, Team]): + name = "Simon Says" + description = "You have to better do what Simon says!" + @classmethod + def get_available_settings(cls, sessiontype: Type[ba.Session]) -> List[ba.Setting]: + settings = [ + ba.BoolSetting("Epic Mode", default=False), + ba.BoolSetting("Enable Jumping", default=False), + ba.BoolSetting("Enable Punching", default=False), + ba.BoolSetting("Enable Picking Up", default=False), + ba.IntChoiceSetting("Timer Speed", + choices=[("Snaily", 1200), + ("Slow", 900), + ("Normal", 655), + ("Fast", 544), + ("Turbo", 460)], default=655), + + ba.FloatChoiceSetting("Text Duration", + choices=[("Slow", 2.5), + ("Normal", 1.5), + ("Mediocre", 1.0), + ("Quick", 0.75)], default=1.5)] + return settings + + @classmethod + def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]: + return ["Courtyard"] + + @classmethod + def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool: + return issubclass(sessiontype, ba.FreeForAllSession) + + def __init__(self, settings: dict): + super().__init__(settings) + self.settings = settings + self._is_slow_motion = bool(settings['Epic Mode']) + self.speed = float(settings['Timer Speed']) + self.lifespan = float(settings['Text Duration']) + self.round_num = 0 + self.string = "" + self.now = 0 + self.simon = False + self.ended = False + self.counter_loop = None + self.time = 5000 + self._r1 = 2 + self.ct_text = ba.newnode('text',attrs={ + 'in_world': True, + 'text':'......', + 'shadow': 1.0, + 'color': (1.0,1.0,1.0), + 'flatness': 0.5, + 'position': (-5.627144702, 3.3275475, -9.572879116), + 'scale': 0.05}) + self.n1 = ba.newnode('locator',attrs={'shape':'circle','position':(-4,0,-6), + 'color':(1,0,0),'opacity':0.5, + 'draw_beauty':True,'additive':True}) + self.n2 = ba.newnode('locator',attrs={'shape':'circle','position':(0,0,-6), + 'color':(0,1,0),'opacity':0.5, + 'draw_beauty':True,'additive':True}) + self.n3 = ba.newnode('locator',attrs={'shape':'circle','position':(4,0,-6), + 'color':(0,0,1),'opacity':0.5, + 'draw_beauty':True,'additive':True}) + self.n4 = ba.newnode('locator',attrs={'shape':'circle','position':(-4,0,-2), + 'color':(1,1,0),'opacity':0.5, + 'draw_beauty':True,'additive':True}) + self.n5 = ba.newnode('locator',attrs={'shape':'circle','position':(0,0,-2), + 'color':(0,1,1),'opacity':0.5, + 'draw_beauty':True,'additive':True}) + self.n6 = ba.newnode('locator',attrs={'shape':'circle','position':(4,0,-2), + 'color':(1,0,1),'opacity':0.5, + 'draw_beauty':True,'additive':True}) + self.n7 = ba.newnode('locator',attrs={'shape':'circle','position':(-4,0,2), + 'color':(.5,.5,.5),'opacity':0.5, + 'draw_beauty':True,'additive':True}) + self.n8 = ba.newnode('locator',attrs={'shape':'circle','position':(0,0,2), + 'color':(.5,.325,0),'opacity':0.5, + 'draw_beauty':True,'additive':True}) + self.n9 = ba.newnode('locator',attrs={'shape':'circle','position':(4,0,2), + 'color':(1,1,1),'opacity':0.5, + 'draw_beauty':True,'additive':True}) + self.options = ["red", "green", "blue", "yellow", "teal", "purple", "gray", "orange", "white", "top", "bottom", "middle row", "left", "right", "center column", "outside"] + self.default_music = ba.MusicType.FLAG_CATCHER + + def get_instance_description(self) -> str: + return 'Follow the commands... but only when \"Simon says!"' + + def on_player_join(self, player: Player) -> None: + if self.has_begun(): + ba.screenmessage( + ba.Lstr(resource = 'playerDelayedJoinText', + subs = [('${PLAYER}', player.getname(full=True))]), + color=(0, 1, 0),) + return + else: + self.spawn_player(player) + + def on_begin(self) -> None: + super().on_begin() + s = self.settings + _gameutils.animate_array(self.n1,'size',1,{0:[0.0],0.2:[self._r1*2.0]}) + _gameutils.animate_array(self.n2,'size',1,{0:[0.0],0.2:[self._r1*2.0]}) + _gameutils.animate_array(self.n3,'size',1,{0:[0.0],0.2:[self._r1*2.0]}) + _gameutils.animate_array(self.n4,'size',1,{0:[0.0],0.2:[self._r1*2.0]}) + _gameutils.animate_array(self.n5,'size',1,{0:[0.0],0.2:[self._r1*2.0]}) + _gameutils.animate_array(self.n6,'size',1,{0:[0.0],0.2:[self._r1*2.0]}) + _gameutils.animate_array(self.n7,'size',1,{0:[0.0],0.2:[self._r1*2.0]}) + _gameutils.animate_array(self.n8,'size',1,{0:[0.0],0.2:[self._r1*2.0]}) + _gameutils.animate_array(self.n9,'size',1,{0:[0.0],0.2:[self._r1*2.0]}) + for team in self.teams: + team.score = 0 + for player in self.players: + player.score = 0 + # check for immediate end if theres only 1 player + if len(self.players) == 1: + ba.timer(4000, lambda: self.check_end(),timeformat=ba.TimeFormat.MILLISECONDS) + else: + ba.timer(6000, self.call_round, timeformat=ba.TimeFormat.MILLISECONDS) + + def spawn_player(self, player: PlayerType) -> ba.Actor: + assert player + spaz = self.spawn_player_spaz(player, position=(0 + random.uniform(-3.6, 3.6), 2.9, -2 + random.uniform(-3.6, 3.6))) + assert spaz.node + spaz.connect_controls_to_player( + enable_bomb=False, + enable_run = True, + enable_punch = self.settings["Enable Punching"], + enable_pickup = self.settings["Enable Picking Up"], + enable_jump = self.settings["Enable Jumping"]) + + def call_round(self) -> None: + if self.ended: return + self.round_num += 1 + self.num = random.randint(0, 15) + self.numa = self.num + self.simon = random.choice([True, False]) + false_prefix = random.choices(['Simon say r', 'Simon said r', 'Simon r', 'Simons says r', 'Simons r', 'R'], weights=[35,45,45,39,49,100])[0] + if self.numa < 9: + if not self.simon: line = false_prefix + "un to the " + self.options[self.numa] + " circle!" + else: line = "Run to the " + self.options[self.numa] + " circle!" + + elif self.numa < 15: + if not self.simon: line = false_prefix + "un to the " + self.options[self.numa] + "!" + else: line = "Run to the " + self.options[self.numa] + "!" + + else: + if not self.simon: line = false_prefix + "un outside of the circles!" + else: line = "Run outside of the circles!" + + + if self.simon: + line = "Simon says " + line[0].lower() + line[1:] + self.text = CustomText(line, + position=(0, 5, -4), + color=(0.68, 0.95, 1.12), + random_offset=0.5, + offset=(0, 0, 0), + duration=self.lifespan, + scale=2.0).autoretain() + self.now = 6 + def dummy_check(): + self.string = "...." + self.check_round() + def set_counter(): + self.now = self.now - 1 + if self.now == 0: + self.string = "0" + self.ct_text.text = self.string + self.counter_loop = None + ba.timer(1, dummy_check, timeformat=ba.TimeFormat.MILLISECONDS) + else: + self.ct_text.text = str(self.now) + ba.playsound(ba.getsound('tick')) + self.counter_loop = ba.Timer(self.speed, set_counter ,timeformat=ba.TimeFormat.MILLISECONDS,repeat=True) + + def check_round(self) -> None: + if self.ended: return + for player in self.players: + if player.is_alive(): + safe = True if self.options[self.numa] in self.in_circle(player.actor.node.position_center) else False + if ((self.simon and safe == False) or ((not self.simon) and safe == True)): + player.team.score = self.round_num + player.actor.handlemessage(ba.DieMessage()) + ba.timer(1633, self.call_round, timeformat=ba.TimeFormat.MILLISECONDS) + + + def in_circle(self, pos) -> None: + circles = [] + x = pos[0] + z = pos[2] + if (x + 4) ** 2 + (z + 6) ** 2 < 4: circles.append("red") + elif (x) ** 2 + (z + 6) ** 2 < 4: circles.append("green") + elif (x - 4) ** 2 + (z + 6) ** 2 < 4: circles.append("blue") + elif (x + 4) ** 2 + (z + 2) ** 2 < 4: circles.append("yellow") + elif (x) ** 2 + (z + 2) ** 2 < 4: circles.append("teal") + elif (x - 4) ** 2 + (z + 2) ** 2 < 4: circles.append("purple") + elif (x + 4) ** 2 + (z - 2) ** 2 < 4: circles.append("gray") + elif (x) ** 2 + (z - 2) ** 2 < 4: circles.append("orange") + elif (x - 4) ** 2 + (z - 2) ** 2 < 4: circles.append("white") + else: circles.append("outside") + if x < -2: circles.append("left") + if x > 2: circles.append("right") + if x > -2 and x < 2: circles.append("center column") + if z > 0: circles.append("bottom") + if z < -4: circles.append("top") + if z < 0 and z > -4: circles.append("middle row") + return circles + + def handlemessage(self, msg) -> None: + if isinstance(msg, ba.PlayerDiedMessage): + self.check_end() + else: + super().handlemessage(msg) + + def end_game(self) -> None: + self.ended = True + results = ba.GameResults() + for team in self.teams: + results.set_team_score(team, team.score) + self.end(results=results) + + def check_end(self) -> None: + i = 0 + for player in self.players: + if player.is_alive(): + i += 1 + if i <= 2 : + ba.timer(0.6, lambda: self.end_game()) diff --git a/plugins/minigames/SquidRace.py b/plugins/minigames/SquidRace.py new file mode 100644 index 0000000..c13276a --- /dev/null +++ b/plugins/minigames/SquidRace.py @@ -0,0 +1,949 @@ +# Released under the MIT License. See LICENSE for details. +# +"""Defines Race mini-game.""" + +# ba_meta require api 7 +# (see https://ballistica.net/wiki/meta-tag-system) + +from __future__ import annotations + +import random +from typing import TYPE_CHECKING +from dataclasses import dataclass + +import ba +from bastd.actor.bomb import Bomb, Blast, ExplodeHitMessage +from bastd.actor.playerspaz import PlayerSpaz +from bastd.actor.scoreboard import Scoreboard +from bastd.gameutils import SharedObjects + +if TYPE_CHECKING: + from typing import (Any, Type, Tuple, List, Sequence, Optional, Dict, + Union) + from bastd.actor.onscreentimer import OnScreenTimer + + +class NewBlast(Blast): + def handlemessage(self, msg: Any) -> Any: + if isinstance(msg, ExplodeHitMessage): + pass + else: + return super().handlemessage(msg) + +@dataclass +class RaceMine: + """Holds info about a mine on the track.""" + point: Sequence[float] + mine: Optional[Bomb] + + +class RaceRegion(ba.Actor): + """Region used to track progress during a race.""" + + def __init__(self, pt: Sequence[float], index: int): + super().__init__() + activity = self.activity + assert isinstance(activity, RaceGame) + self.pos = pt + self.index = index + self.node = ba.newnode( + 'region', + delegate=self, + attrs={ + 'position': pt[:3], + 'scale': (pt[3] * 2.0, pt[4] * 2.0, pt[5] * 2.0), + 'type': 'box', + 'materials': [activity.race_region_material] + }) + + +class Player(ba.Player['Team']): + """Our player type for this game.""" + + def __init__(self) -> None: + self.distance_txt: Optional[ba.Node] = None + self.last_region = 0 + self.lap = 0 + self.distance = 0.0 + self.finished = False + self.rank: Optional[int] = None + + +class Team(ba.Team[Player]): + """Our team type for this game.""" + + def __init__(self) -> None: + self.time: Optional[float] = None + self.lap = 0 + self.finished = False + + +# ba_meta export game +class SquidRaceGame(ba.TeamGameActivity[Player, Team]): + """Game of racing around a track.""" + + name = 'Squid Race' + description = 'Run real fast!' + scoreconfig = ba.ScoreConfig(label='Time', + lower_is_better=True, + scoretype=ba.ScoreType.MILLISECONDS) + + @classmethod + def get_available_settings( + cls, sessiontype: Type[ba.Session]) -> List[ba.Setting]: + settings = [ + ba.IntSetting('Laps', min_value=1, default=3, increment=1), + ba.IntChoiceSetting( + 'Time Limit', + default=0, + choices=[ + ('None', 0), + ('1 Minute', 60), + ('2 Minutes', 120), + ('5 Minutes', 300), + ('10 Minutes', 600), + ('20 Minutes', 1200), + ], + ), + ba.IntChoiceSetting( + 'Mine Spawning', + default=4000, + choices=[ + ('No Mines', 0), + ('8 Seconds', 8000), + ('4 Seconds', 4000), + ('2 Seconds', 2000), + ], + ), + ba.IntChoiceSetting( + 'Bomb Spawning', + choices=[ + ('None', 0), + ('8 Seconds', 8000), + ('4 Seconds', 4000), + ('2 Seconds', 2000), + ('1 Second', 1000), + ], + default=2000, + ), + ba.BoolSetting('Epic Mode', default=False), + ] + + # We have some specific settings in teams mode. + if issubclass(sessiontype, ba.DualTeamSession): + settings.append( + ba.BoolSetting('Entire Team Must Finish', default=False)) + return settings + + @classmethod + def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool: + return issubclass(sessiontype, ba.MultiTeamSession) + + @classmethod + def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]: + return ba.getmaps('race') + + def __init__(self, settings: dict): + self._race_started = False + super().__init__(settings) + self._scoreboard = Scoreboard() + self._score_sound = ba.getsound('score') + self._swipsound = ba.getsound('swip') + self._last_team_time: Optional[float] = None + self._front_race_region: Optional[int] = None + self._nub_tex = ba.gettexture('nub') + self._beep_1_sound = ba.getsound('raceBeep1') + self._beep_2_sound = ba.getsound('raceBeep2') + self.race_region_material: Optional[ba.Material] = None + self._regions: List[RaceRegion] = [] + self._team_finish_pts: Optional[int] = None + self._time_text: Optional[ba.Actor] = None + self._timer: Optional[OnScreenTimer] = None + self._race_mines: Optional[List[RaceMine]] = None + self._race_mine_timer: Optional[ba.Timer] = None + self._scoreboard_timer: Optional[ba.Timer] = None + self._player_order_update_timer: Optional[ba.Timer] = None + self._start_lights: Optional[List[ba.Node]] = None + self._squid_lights: Optional[List[ba.Node]] = None + self._countdown_timer: int = 0 + self._sq_mode: str = 'Easy' + self._tick_timer: Optional[ba.Timer] = None + self._bomb_spawn_timer: Optional[ba.Timer] = None + self._laps = int(settings['Laps']) + self._entire_team_must_finish = bool( + settings.get('Entire Team Must Finish', False)) + self._time_limit = float(settings['Time Limit']) + self._mine_spawning = int(settings['Mine Spawning']) + self._bomb_spawning = int(settings['Bomb Spawning']) + self._epic_mode = bool(settings['Epic Mode']) + + self._countdownsounds = { + 10: ba.getsound('announceTen'), + 9: ba.getsound('announceNine'), + 8: ba.getsound('announceEight'), + 7: ba.getsound('announceSeven'), + 6: ba.getsound('announceSix'), + 5: ba.getsound('announceFive'), + 4: ba.getsound('announceFour'), + 3: ba.getsound('announceThree'), + 2: ba.getsound('announceTwo'), + 1: ba.getsound('announceOne') + } + + # Base class overrides. + self.slow_motion = self._epic_mode + self.default_music = (ba.MusicType.EPIC_RACE + if self._epic_mode else ba.MusicType.RACE) + + def get_instance_description(self) -> Union[str, Sequence]: + if (isinstance(self.session, ba.DualTeamSession) + and self._entire_team_must_finish): + t_str = ' Your entire team has to finish.' + else: + t_str = '' + + if self._laps > 1: + return 'Run ${ARG1} laps.' + t_str, self._laps + return 'Run 1 lap.' + t_str + + def get_instance_description_short(self) -> Union[str, Sequence]: + if self._laps > 1: + return 'run ${ARG1} laps', self._laps + return 'run 1 lap' + + def on_transition_in(self) -> None: + super().on_transition_in() + shared = SharedObjects.get() + pts = self.map.get_def_points('race_point') + mat = self.race_region_material = ba.Material() + mat.add_actions(conditions=('they_have_material', + shared.player_material), + actions=( + ('modify_part_collision', 'collide', True), + ('modify_part_collision', 'physical', False), + ('call', 'at_connect', + self._handle_race_point_collide), + )) + for rpt in pts: + self._regions.append(RaceRegion(rpt, len(self._regions))) + + def _flash_player(self, player: Player, scale: float) -> None: + assert isinstance(player.actor, PlayerSpaz) + assert player.actor.node + pos = player.actor.node.position + light = ba.newnode('light', + attrs={ + 'position': pos, + 'color': (1, 1, 0), + 'height_attenuated': False, + 'radius': 0.4 + }) + ba.timer(0.5, light.delete) + ba.animate(light, 'intensity', {0: 0, 0.1: 1.0 * scale, 0.5: 0}) + + def _handle_race_point_collide(self) -> None: + # FIXME: Tidy this up. + # pylint: disable=too-many-statements + # pylint: disable=too-many-branches + # pylint: disable=too-many-nested-blocks + collision = ba.getcollision() + try: + region = collision.sourcenode.getdelegate(RaceRegion, True) + player = collision.opposingnode.getdelegate(PlayerSpaz, + True).getplayer( + Player, True) + except ba.NotFoundError: + return + + last_region = player.last_region + this_region = region.index + + if last_region != this_region: + + # If a player tries to skip regions, smite them. + # Allow a one region leeway though (its plausible players can get + # blown over a region, etc). + if this_region > last_region + 2: + if player.is_alive(): + assert player.actor + player.actor.handlemessage(ba.DieMessage()) + ba.screenmessage(ba.Lstr( + translate=('statements', 'Killing ${NAME} for' + ' skipping part of the track!'), + subs=[('${NAME}', player.getname(full=True))]), + color=(1, 0, 0)) + else: + # If this player is in first, note that this is the + # front-most race-point. + if player.rank == 0: + self._front_race_region = this_region + + player.last_region = this_region + if last_region >= len(self._regions) - 2 and this_region == 0: + team = player.team + player.lap = min(self._laps, player.lap + 1) + + # In teams mode with all-must-finish on, the team lap + # value is the min of all team players. + # Otherwise its the max. + if isinstance(self.session, ba.DualTeamSession + ) and self._entire_team_must_finish: + team.lap = min([p.lap for p in team.players]) + else: + team.lap = max([p.lap for p in team.players]) + + # A player is finishing. + if player.lap == self._laps: + + # In teams mode, hand out points based on the order + # players come in. + if isinstance(self.session, ba.DualTeamSession): + assert self._team_finish_pts is not None + if self._team_finish_pts > 0: + self.stats.player_scored(player, + self._team_finish_pts, + screenmessage=False) + self._team_finish_pts -= 25 + + # Flash where the player is. + self._flash_player(player, 1.0) + player.finished = True + assert player.actor + player.actor.handlemessage( + ba.DieMessage(immediate=True)) + + # Makes sure noone behind them passes them in rank + # while finishing. + player.distance = 9999.0 + + # If the whole team has finished the race. + if team.lap == self._laps: + ba.playsound(self._score_sound) + player.team.finished = True + assert self._timer is not None + elapsed = ba.time() - self._timer.getstarttime() + self._last_team_time = player.team.time = elapsed + + # Team has yet to finish. + else: + ba.playsound(self._swipsound) + + # They've just finished a lap but not the race. + else: + ba.playsound(self._swipsound) + self._flash_player(player, 0.3) + + # Print their lap number over their head. + try: + assert isinstance(player.actor, PlayerSpaz) + mathnode = ba.newnode('math', + owner=player.actor.node, + attrs={ + 'input1': (0, 1.9, 0), + 'operation': 'add' + }) + player.actor.node.connectattr( + 'torso_position', mathnode, 'input2') + tstr = ba.Lstr(resource='lapNumberText', + subs=[('${CURRENT}', + str(player.lap + 1)), + ('${TOTAL}', str(self._laps)) + ]) + txtnode = ba.newnode('text', + owner=mathnode, + attrs={ + 'text': tstr, + 'in_world': True, + 'color': (1, 1, 0, 1), + 'scale': 0.015, + 'h_align': 'center' + }) + mathnode.connectattr('output', txtnode, 'position') + ba.animate(txtnode, 'scale', { + 0.0: 0, + 0.2: 0.019, + 2.0: 0.019, + 2.2: 0 + }) + ba.timer(2.3, mathnode.delete) + except Exception: + ba.print_exception('Error printing lap.') + + def on_team_join(self, team: Team) -> None: + self._update_scoreboard() + + def on_player_join(self, player: Player) -> None: + # Don't allow joining after we start + # (would enable leave/rejoin tomfoolery). + if self.has_begun(): + ba.screenmessage( + ba.Lstr(resource='playerDelayedJoinText', + subs=[('${PLAYER}', player.getname(full=True))]), + color=(0, 1, 0), + ) + return + self.spawn_player(player) + + def on_player_leave(self, player: Player) -> None: + super().on_player_leave(player) + + # A player leaving disqualifies the team if 'Entire Team Must Finish' + # is on (otherwise in teams mode everyone could just leave except the + # leading player to win). + if (isinstance(self.session, ba.DualTeamSession) + and self._entire_team_must_finish): + ba.screenmessage(ba.Lstr( + translate=('statements', + '${TEAM} is disqualified because ${PLAYER} left'), + subs=[('${TEAM}', player.team.name), + ('${PLAYER}', player.getname(full=True))]), + color=(1, 1, 0)) + player.team.finished = True + player.team.time = None + player.team.lap = 0 + ba.playsound(ba.getsound('boo')) + for otherplayer in player.team.players: + otherplayer.lap = 0 + otherplayer.finished = True + try: + if otherplayer.actor is not None: + otherplayer.actor.handlemessage(ba.DieMessage()) + except Exception: + ba.print_exception('Error sending DieMessage.') + + # Defer so team/player lists will be updated. + ba.pushcall(self._check_end_game) + + def _update_scoreboard(self) -> None: + for team in self.teams: + distances = [player.distance for player in team.players] + if not distances: + teams_dist = 0.0 + else: + if (isinstance(self.session, ba.DualTeamSession) + and self._entire_team_must_finish): + teams_dist = min(distances) + else: + teams_dist = max(distances) + self._scoreboard.set_team_value( + team, + teams_dist, + self._laps, + flash=(teams_dist >= float(self._laps)), + show_value=False) + + def on_begin(self) -> None: + from bastd.actor.onscreentimer import OnScreenTimer + super().on_begin() + self.setup_standard_time_limit(self._time_limit) + self.setup_standard_powerup_drops() + self._team_finish_pts = 100 + + # Throw a timer up on-screen. + self._time_text = ba.NodeActor( + ba.newnode('text', + attrs={ + 'v_attach': 'top', + 'h_attach': 'center', + 'h_align': 'center', + 'color': (1, 1, 0.5, 1), + 'flatness': 0.5, + 'shadow': 0.5, + 'position': (0, -50), + 'scale': 1.4, + 'text': '' + })) + self._timer = OnScreenTimer() + + if self._mine_spawning != 0: + self._race_mines = [ + RaceMine(point=p, mine=None) + for p in self.map.get_def_points('race_mine') + ] + if self._race_mines: + self._race_mine_timer = ba.Timer(0.001 * self._mine_spawning, + self._update_race_mine, + repeat=True) + + self._scoreboard_timer = ba.Timer(0.25, + self._update_scoreboard, + repeat=True) + self._player_order_update_timer = ba.Timer(0.25, + self._update_player_order, + repeat=True) + + if self.slow_motion: + t_scale = 0.4 + light_y = 50 + else: + t_scale = 1.0 + light_y = 150 + lstart = 7.1 * t_scale + inc = 1.25 * t_scale + + ba.timer(lstart, self._do_light_1) + ba.timer(lstart + inc, self._do_light_2) + ba.timer(lstart + 2 * inc, self._do_light_3) + ba.timer(lstart + 3 * inc, self._start_race) + + self._start_lights = [] + for i in range(4): + lnub = ba.newnode('image', + attrs={ + 'texture': ba.gettexture('nub'), + 'opacity': 1.0, + 'absolute_scale': True, + 'position': (-75 + i * 50, light_y), + 'scale': (50, 50), + 'attach': 'center' + }) + ba.animate( + lnub, 'opacity', { + 4.0 * t_scale: 0, + 5.0 * t_scale: 1.0, + 12.0 * t_scale: 1.0, + 12.5 * t_scale: 0.0 + }) + ba.timer(13.0 * t_scale, lnub.delete) + self._start_lights.append(lnub) + + self._start_lights[0].color = (0.2, 0, 0) + self._start_lights[1].color = (0.2, 0, 0) + self._start_lights[2].color = (0.2, 0.05, 0) + self._start_lights[3].color = (0.0, 0.3, 0) + + self._squid_lights = [] + for i in range(2): + lnub = ba.newnode('image', + attrs={ + 'texture': ba.gettexture('nub'), + 'opacity': 1.0, + 'absolute_scale': True, + 'position': (-33 + i * 65, 220), + 'scale': (60, 60), + 'attach': 'center' + }) + ba.animate( + lnub, 'opacity', { + 4.0 * t_scale: 0, + 5.0 * t_scale: 1.0}) + self._squid_lights.append(lnub) + self._squid_lights[0].color = (0.2, 0, 0) + self._squid_lights[1].color = (0.0, 0.3, 0) + + ba.timer(1.0, self._check_squid_end, repeat=True) + self._squidgame_countdown() + + def _squidgame_countdown(self) -> None: + self._countdown_timer = 80 * self._laps # 80 + ba.newnode( + 'image', + attrs={ + 'opacity': 0.7, + 'color': (0.2, 0.2, 0.2), + 'attach': 'topCenter', + 'position': (-220, -40), + 'scale': (135, 45), + 'texture': ba.gettexture('bar')}) + ba.newnode( + 'image', + attrs={ + 'opacity': 1.0, + 'color': (1.0, 0.0, 0.0), + 'attach': 'topCenter', + 'position': (-220, -38), + 'scale':(155, 65), + 'texture': ba.gettexture('uiAtlas'), + 'model_transparent': ba.getmodel('meterTransparent')}) + self._sgcountdown_text = ba.newnode( + 'text', + attrs={ + 'v_attach': 'top', + 'h_attach': 'center', + 'h_align': 'center', + 'position': (-220, -57), + 'shadow': 0.5, + 'flatness': 0.5, + 'scale': 1.1, + 'text': str(self._countdown_timer)+"s"}) + + def _update_sgcountdown(self) -> None: + self._countdown_timer -= 1 + self._countdown_timer + if self._countdown_timer <= 0: + self._countdown_timer = 0 + self._squid_game_all_die() + if self._countdown_timer == 20: + self._sq_mode = 'Hard' + ba.playsound(ba.getsound('alarm')) + if self._countdown_timer == 40: + self._sq_mode = 'Normal' + if self._countdown_timer <= 20: + self._sgcountdown_text.color = (1.2, 0.0, 0.0) + self._sgcountdown_text.scale = 1.2 + if self._countdown_timer in self._countdownsounds: + ba.playsound(self._countdownsounds[self._countdown_timer]) + else: + self._sgcountdown_text.color = (1.0, 1.0, 1.0) + self._sgcountdown_text.text = str(self._countdown_timer)+"s" + + def _squid_game_all_die(self) -> None: + for player in self.players: + if player.is_alive(): + player.actor._cursed = True + player.actor.handlemessage(ba.DieMessage()) + NewBlast( + position=player.actor.node.position, + velocity=player.actor.node.velocity, + blast_radius=3.0, + blast_type='normal').autoretain() + player.actor.handlemessage( + ba.HitMessage( + pos=player.actor.node.position, + velocity=player.actor.node.velocity, + magnitude=2000, + hit_type='explosion', + hit_subtype='normal', + radius=2.0, + source_player=None)) + player.actor._cursed = False + + def _do_ticks(self) -> None: + def do_ticks(): + if self._ticks: + ba.playsound(ba.getsound('tick')) + self._tick_timer = ba.timer(1.0, do_ticks, repeat=True) + + def _start_squid_game(self) -> None: + easy = [4.5,5,5.5,6] + normal = [4,4.5,5] + hard = [3,3.5,4] + random_number = random.choice( + hard if self._sq_mode == 'Hard' else + normal if self._sq_mode == 'Normal' else easy) + # if random_number == 6: + # ba.playsound(ba.getsound('lrlg_06s')) + # elif random_number == 5.5: + # ba.playsound(ba.getsound('lrlg_055s')) + # elif random_number == 5: + # ba.playsound(ba.getsound('lrlg_05s')) + # elif random_number == 4.5: + # ba.playsound(ba.getsound('lrlg_045s')) + # elif random_number == 4: + # ba.playsound(ba.getsound('lrlg_04s')) + # elif random_number == 3.5: + # ba.playsound(ba.getsound('lrlg_035s')) + # elif random_number == 3: + # ba.playsound(ba.getsound('lrlg_03s')) + self._squid_lights[0].color = (0.2, 0, 0) + self._squid_lights[1].color = (0.0, 1.0, 0) + self._do_delete = False + self._ticks = True + ba.timer(random_number, self._stop_squid_game) + + def _stop_squid_game(self) -> None: + self._ticks = False + self._squid_lights[0].color = (1.0, 0, 0) + self._squid_lights[1].color = (0.0, 0.3, 0) + ba.timer(0.2, self._check_delete) + + def _check_delete(self) -> None: + for player in self.players: + if player.is_alive(): + player.customdata['position'] = None + player.customdata['position'] = player.actor.node.position + self._do_delete = True + ba.timer(3.0 if self._sq_mode == 'Hard' else 4.0, + self._start_squid_game) + + def _start_delete(self) -> None: + for player in self.players: + if player.is_alive() and self._do_delete: + + posx = float("%.1f" % player.customdata['position'][0]) + posz = float("%.1f" % player.customdata['position'][1]) + posy = float("%.1f" % player.customdata['position'][2]) + + posx_list = [ + round(posx,1),round(posx+0.1,1),round(posx+0.2,1), + round(posx-0.1,1),round(posx-0.2,1)] + current_posx = float("%.1f" % player.actor.node.position[0]) + + posz_list = [ + round(posz,1),round(posz+0.1,1),round(posz+0.2,1), + round(posz-0.1,1),round(posz-0.2,1)] + current_posz = float("%.1f" % player.actor.node.position[1]) + + posy_list = [ + round(posy,1),round(posy+0.1,1),round(posy+0.2,1), + round(posy-0.1,1),round(posy-0.2,1)] + current_posy = float("%.1f" % player.actor.node.position[2]) + + if not (current_posx in posx_list) or not ( + current_posz in posz_list) or not ( + current_posy in posy_list): + player.actor._cursed = True + player.actor.handlemessage(ba.DieMessage()) + NewBlast( + position=player.actor.node.position, + velocity=player.actor.node.velocity, + blast_radius=3.0, + blast_type='normal').autoretain() + player.actor.handlemessage( + ba.HitMessage( + pos=player.actor.node.position, + velocity=player.actor.node.velocity, + magnitude=2000, + hit_type='explosion', + hit_subtype='normal', + radius=2.0, + source_player=None)) + player.actor._cursed = False + + def _check_squid_end(self) -> None: + squid_player_alive = 0 + for player in self.players: + if player.is_alive(): + squid_player_alive += 1 + break + if squid_player_alive < 1: + self.end_game() + + def _do_light_1(self) -> None: + assert self._start_lights is not None + self._start_lights[0].color = (1.0, 0, 0) + ba.playsound(self._beep_1_sound) + + def _do_light_2(self) -> None: + assert self._start_lights is not None + self._start_lights[1].color = (1.0, 0, 0) + ba.playsound(self._beep_1_sound) + + def _do_light_3(self) -> None: + assert self._start_lights is not None + self._start_lights[2].color = (1.0, 0.3, 0) + ba.playsound(self._beep_1_sound) + + def _start_race(self) -> None: + assert self._start_lights is not None + self._start_lights[3].color = (0.0, 1.0, 0) + ba.playsound(self._beep_2_sound) + for player in self.players: + if player.actor is not None: + try: + assert isinstance(player.actor, PlayerSpaz) + player.actor.connect_controls_to_player() + except Exception: + ba.print_exception('Error in race player connects.') + assert self._timer is not None + self._timer.start() + + if self._bomb_spawning != 0: + self._bomb_spawn_timer = ba.Timer(0.001 * self._bomb_spawning, + self._spawn_bomb, + repeat=True) + + self._race_started = True + self._squid_lights[1].color = (0.0, 1.0, 0) + self._start_squid_game() + self._do_ticks() + ba.timer(0.2, self._start_delete, repeat=True) + ba.timer(1.0, self._update_sgcountdown, repeat=True) + + def _update_player_order(self) -> None: + + # Calc all player distances. + for player in self.players: + pos: Optional[ba.Vec3] + try: + pos = player.position + except ba.NotFoundError: + pos = None + if pos is not None: + r_index = player.last_region + rg1 = self._regions[r_index] + r1pt = ba.Vec3(rg1.pos[:3]) + rg2 = self._regions[0] if r_index == len( + self._regions) - 1 else self._regions[r_index + 1] + r2pt = ba.Vec3(rg2.pos[:3]) + r2dist = (pos - r2pt).length() + amt = 1.0 - (r2dist / (r2pt - r1pt).length()) + amt = player.lap + (r_index + amt) * (1.0 / len(self._regions)) + player.distance = amt + + # Sort players by distance and update their ranks. + p_list = [(player.distance, player) for player in self.players] + + p_list.sort(reverse=True, key=lambda x: x[0]) + for i, plr in enumerate(p_list): + plr[1].rank = i + if plr[1].actor: + node = plr[1].distance_txt + if node: + node.text = str(i + 1) if plr[1].is_alive() else '' + + def _spawn_bomb(self) -> None: + if self._front_race_region is None: + return + region = (self._front_race_region + 3) % len(self._regions) + pos = self._regions[region].pos + + # Don't use the full region so we're less likely to spawn off a cliff. + region_scale = 0.8 + x_range = ((-0.5, 0.5) if pos[3] == 0 else + (-region_scale * pos[3], region_scale * pos[3])) + z_range = ((-0.5, 0.5) if pos[5] == 0 else + (-region_scale * pos[5], region_scale * pos[5])) + pos = (pos[0] + random.uniform(*x_range), pos[1] + 1.0, + pos[2] + random.uniform(*z_range)) + ba.timer(random.uniform(0.0, 2.0), + ba.WeakCall(self._spawn_bomb_at_pos, pos)) + + def _spawn_bomb_at_pos(self, pos: Sequence[float]) -> None: + if self.has_ended(): + return + Bomb(position=pos, bomb_type='normal').autoretain() + + def _make_mine(self, i: int) -> None: + assert self._race_mines is not None + rmine = self._race_mines[i] + rmine.mine = Bomb(position=rmine.point[:3], bomb_type='land_mine') + rmine.mine.arm() + + def _flash_mine(self, i: int) -> None: + assert self._race_mines is not None + rmine = self._race_mines[i] + light = ba.newnode('light', + attrs={ + 'position': rmine.point[:3], + 'color': (1, 0.2, 0.2), + 'radius': 0.1, + 'height_attenuated': False + }) + ba.animate(light, 'intensity', {0.0: 0, 0.1: 1.0, 0.2: 0}, loop=True) + ba.timer(1.0, light.delete) + + def _update_race_mine(self) -> None: + assert self._race_mines is not None + m_index = -1 + rmine = None + for _i in range(3): + m_index = random.randrange(len(self._race_mines)) + rmine = self._race_mines[m_index] + if not rmine.mine: + break + assert rmine is not None + if not rmine.mine: + self._flash_mine(m_index) + ba.timer(0.95, ba.Call(self._make_mine, m_index)) + + def spawn_player(self, player: Player) -> ba.Actor: + if player.team.finished: + # FIXME: This is not type-safe! + # This call is expected to always return an Actor! + # Perhaps we need something like can_spawn_player()... + # noinspection PyTypeChecker + return None # type: ignore + pos = self._regions[player.last_region].pos + + # Don't use the full region so we're less likely to spawn off a cliff. + region_scale = 0.8 + x_range = ((-0.5, 0.5) if pos[3] == 0 else + (-region_scale * pos[3], region_scale * pos[3])) + z_range = ((-0.5, 0.5) if pos[5] == 0 else + (-region_scale * pos[5], region_scale * pos[5])) + pos = (pos[0] + random.uniform(*x_range), pos[1], + pos[2] + random.uniform(*z_range)) + spaz = self.spawn_player_spaz( + player, position=pos, angle=90 if not self._race_started else None) + assert spaz.node + + # Prevent controlling of characters before the start of the race. + if not self._race_started: + spaz.disconnect_controls_from_player() + + mathnode = ba.newnode('math', + owner=spaz.node, + attrs={ + 'input1': (0, 1.4, 0), + 'operation': 'add' + }) + spaz.node.connectattr('torso_position', mathnode, 'input2') + + distance_txt = ba.newnode('text', + owner=spaz.node, + attrs={ + 'text': '', + 'in_world': True, + 'color': (1, 1, 0.4), + 'scale': 0.02, + 'h_align': 'center' + }) + player.distance_txt = distance_txt + mathnode.connectattr('output', distance_txt, 'position') + return spaz + + def _check_end_game(self) -> None: + + # If there's no teams left racing, finish. + teams_still_in = len([t for t in self.teams if not t.finished]) + if teams_still_in == 0: + self.end_game() + return + + # Count the number of teams that have completed the race. + teams_completed = len( + [t for t in self.teams if t.finished and t.time is not None]) + + if teams_completed > 0: + session = self.session + + # In teams mode its over as soon as any team finishes the race + + # FIXME: The get_ffa_point_awards code looks dangerous. + if isinstance(session, ba.DualTeamSession): + self.end_game() + else: + # In ffa we keep the race going while there's still any points + # to be handed out. Find out how many points we have to award + # and how many teams have finished, and once that matches + # we're done. + assert isinstance(session, ba.FreeForAllSession) + points_to_award = len(session.get_ffa_point_awards()) + if teams_completed >= points_to_award - teams_completed: + self.end_game() + return + + def end_game(self) -> None: + + # Stop updating our time text, and set it to show the exact last + # finish time if we have one. (so users don't get upset if their + # final time differs from what they see onscreen by a tiny amount) + assert self._timer is not None + if self._timer.has_started(): + self._timer.stop( + endtime=None if self._last_team_time is None else ( + self._timer.getstarttime() + self._last_team_time)) + + results = ba.GameResults() + + for team in self.teams: + if team.time is not None: + # We store time in seconds, but pass a score in milliseconds. + results.set_team_score(team, int(team.time * 1000.0)) + else: + results.set_team_score(team, None) + + # We don't announce a winner in ffa mode since its probably been a + # while since the first place guy crossed the finish line so it seems + # odd to be announcing that now. + self.end(results=results, + announce_winning_team=isinstance(self.session, + ba.DualTeamSession)) + + def handlemessage(self, msg: Any) -> Any: + if isinstance(msg, ba.PlayerDiedMessage): + # Augment default behavior. + super().handlemessage(msg) + else: + super().handlemessage(msg) diff --git a/plugins/minigames/ZombieHorde.py b/plugins/minigames/ZombieHorde.py new file mode 100644 index 0000000..673c9f5 --- /dev/null +++ b/plugins/minigames/ZombieHorde.py @@ -0,0 +1,878 @@ +# ba_meta require api 7 +# (see https://ballistica.net/wiki/meta-tag-system) + +from __future__ import annotations + +from typing import TYPE_CHECKING + +import ba +import _ba +import copy +import random +from ba import _math +from ba._coopsession import CoopSession +from ba._messages import PlayerDiedMessage, StandMessage +from bastd.actor.playerspaz import PlayerSpaz +from bastd.actor.scoreboard import Scoreboard +from bastd.game.elimination import Icon, Player +from bastd.actor.spaz import PickupMessage +from bastd.actor.spazbot import SpazBotSet, BrawlerBot, SpazBotDiedMessage +from bastd.actor.spazfactory import SpazFactory + + +if TYPE_CHECKING: + from typing import Any, Sequence + + +class PlayerSpaz_Zom(PlayerSpaz): + def handlemessage(self, m: Any) -> Any: + if isinstance(m, ba.HitMessage): + if not self.node: + return + if not m._source_player is None: + try: + playa = m._source_player.getname(True, False) + if not playa is None: + if m._source_player.lives < 1: + super().handlemessage(m) + except: + super().handlemessage(m) + else: + super().handlemessage(m) + + elif isinstance(m, ba.FreezeMessage): + pass + + elif isinstance(m, PickupMessage): + if not self.node: + return None + + try: + collision = ba.getcollision() + opposingnode = collision.opposingnode + opposingbody = collision.opposingbody + except ba.NotFoundError: + return True + + try: + if opposingnode.invincible: + return True + except Exception: + pass + + try: + playa = opposingnode._source_player.getname(True, False) + if not playa is None: + if opposingnode._source_player.lives > 0: + return True + except Exception: + pass + + if (opposingnode.getnodetype() == 'spaz' + and not opposingnode.shattered and opposingbody == 4): + opposingbody = 1 + + held = self.node.hold_node + if held and held.getnodetype() == 'flag': + return True + + self.node.hold_body = opposingbody + self.node.hold_node = opposingnode + else: + return super().handlemessage(m) + return None + +class PlayerZombie(PlayerSpaz): + def handlemessage(self, m: Any) -> Any: + if isinstance(m, ba.HitMessage): + if not self.node: + return None + if not m._source_player is None: + try: + playa = m._source_player.getname(True, False) + if playa is None: + pass + else: + super().handlemessage(m) + except: + super().handlemessage(m) + else: + super().handlemessage(m) + else: + super().handlemessage(m) + +class zBotSet(SpazBotSet): + def start_moving(self) -> None: + """Start processing bot AI updates so they start doing their thing.""" + self._bot_update_timer = ba.Timer(0.05, + ba.WeakCall(self.zUpdate), + repeat=True) + + def zUpdate(self) -> None: + + try: + bot_list = self._bot_lists[self._bot_update_list] = ([ + b for b in self._bot_lists[self._bot_update_list] if b + ]) + except Exception: + bot_list = [] + ba.print_exception('Error updating bot list: ' + + str(self._bot_lists[self._bot_update_list])) + self._bot_update_list = (self._bot_update_list + + 1) % self._bot_list_count + + player_pts = [] + for player in ba.getactivity().players: + assert isinstance(player, ba.Player) + try: + if player.is_alive(): + assert isinstance(player.actor, Spaz) + assert player.actor.node + if player.lives > 0: + player_pts.append( + (ba.Vec3(player.actor.node.position), + ba.Vec3(player.actor.node.velocity))) + except Exception: + ba.print_exception('Error on bot-set _update.') + + for bot in bot_list: + bot.set_player_points(player_pts) + bot.update_ai() + +class Team(ba.Team[Player]): + """Our team type for this game.""" + + def __init__(self) -> None: + self.score = 0 + self.spawn_order: list[Player] = [] + + +# ba_meta export game +class ZombieHorde(ba.TeamGameActivity[Player, Team]): + + name = 'Zombie Horde' + description = 'Kill walkers for points!' + scoreconfig = ba.ScoreConfig(label='Score', + scoretype=ba.ScoreType.POINTS, + none_is_winner=False, + lower_is_better=False) + # Show messages when players die since it's meaningful here. + announce_player_deaths = True + + @classmethod + def get_available_settings( + cls, sessiontype: type[ba.Session]) -> list[ba.Setting]: + settings = [ + ba.IntSetting( + 'Lives Per Player', + default=1, + min_value=1, + max_value=10, + increment=1, + ), + ba.IntSetting( + 'Max Zombies', + default=10, + min_value=5, + max_value=50, + increment=5, + ), + 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.DualTeamSession): + settings.append(ba.BoolSetting('Solo Mode', default=False)) + settings.append( + ba.BoolSetting('Balance Total Lives', 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 ba.getmaps('melee') + + def __init__(self, settings: dict): + super().__init__(settings) + self._scoreboard = Scoreboard() + self._start_time: float | None = None + self._vs_text: ba.Actor | None = None + self._round_end_timer: ba.Timer | None = None + self._epic_mode = bool(settings['Epic Mode']) + self._lives_per_player = int(settings['Lives Per Player']) + self._max_zombies = int(settings['Max Zombies']) + self._time_limit = float(settings['Time Limit']) + self._balance_total_lives = bool( + settings.get('Balance Total Lives', False)) + self._solo_mode = bool(settings.get('Solo Mode', False)) + + # Base class overrides: + self.slow_motion = self._epic_mode + self.default_music = (ba.MusicType.EPIC + if self._epic_mode else ba.MusicType.SURVIVAL) + + self.spazList = [] + self.zombieQ = 0 + + activity = ba.getactivity() + my_factory = SpazFactory.get() + + appears = ['Kronk','Zoe','Pixel','Agent Johnson', + 'Bones','Frosty','Kronk2'] + myAppear = copy.copy(ba.app.spaz_appearances['Kronk']) + myAppear.name = 'Kronk2' + ba.app.spaz_appearances['Kronk2'] = myAppear + for appear in appears: + my_factory.get_media(appear) + med = my_factory.spaz_media + med['Kronk2']['head_model'] = med['Zoe']['head_model'] + med['Kronk2']['color_texture'] = med['Agent Johnson']['color_texture'] + med['Kronk2']['color_mask_texture']=med['Pixel']['color_mask_texture'] + med['Kronk2']['torso_model'] = med['Bones']['torso_model'] + med['Kronk2']['pelvis_model'] = med['Pixel']['pelvis_model'] + med['Kronk2']['upper_arm_model'] = med['Frosty']['upper_arm_model'] + med['Kronk2']['forearm_model'] = med['Frosty']['forearm_model'] + med['Kronk2']['hand_model'] = med['Bones']['hand_model'] + med['Kronk2']['upper_leg_model'] = med['Bones']['upper_leg_model'] + med['Kronk2']['lower_leg_model'] = med['Pixel']['lower_leg_model'] + med['Kronk2']['toes_model'] = med['Bones']['toes_model'] + + def get_instance_description(self) -> str | Sequence: + return ('Kill walkers for points! ', + 'Dead player walker: 2 points!') if isinstance( + self.session, ba.DualTeamSession) else ( + 'Kill walkers for points! Dead player walker: 2 points!') + + def get_instance_description_short(self) -> str | Sequence: + return ('Kill walkers for points! ', + 'Dead player walker: 2 points!') if isinstance( + self.session, ba.DualTeamSession) else ( + 'Kill walkers for points! Dead player walker: 2 points!') + + def on_player_join(self, player: Player) -> None: + if self.has_begun(): + player.lives = 0 + player.icons = [] + ba.screenmessage( + ba.Lstr(resource='playerDelayedJoinText', + subs=[('${PLAYER}', player.getname(full=True))]), + color=(0, 1, 0), + ) + return + + player.lives = self._lives_per_player + + if self._solo_mode: + player.icons = [] + player.team.spawn_order.append(player) + self._update_solo_mode() + else: + player.icons = [Icon(player, position=(0, 50), scale=0.8)] + if player.lives > 0: + self.spawn_player(player) + + if self.has_begun(): + self._update_icons() + + def _update_solo_mode(self) -> None: + for team in self.teams: + team.spawn_order = [p for p in team.spawn_order if p] + for player in team.spawn_order: + assert isinstance(player, Player) + if player.lives > 0: + if not player.is_alive(): + self.spawn_player(player) + break + + def on_begin(self) -> None: + super().on_begin() + self._start_time = ba.time() + self.setup_standard_time_limit(self._time_limit) + self.setup_standard_powerup_drops() + self.zombieQ = 1 + if self._solo_mode: + self._vs_text = ba.NodeActor( + ba.newnode('text', + attrs={ + 'position': (0, 105), + 'h_attach': 'center', + 'h_align': 'center', + 'maxwidth': 200, + 'shadow': 0.5, + 'vr_depth': 390, + 'scale': 0.6, + 'v_attach': 'bottom', + 'color': (0.8, 0.8, 0.3, 1.0), + 'text': ba.Lstr(resource='vsText') + })) + + # If balance-team-lives is on, add lives to the smaller team until + # total lives match. + if (isinstance(self.session, ba.DualTeamSession) + and self._balance_total_lives and self.teams[0].players + and self.teams[1].players): + if self._get_total_team_lives( + self.teams[0]) < self._get_total_team_lives(self.teams[1]): + lesser_team = self.teams[0] + greater_team = self.teams[1] + else: + lesser_team = self.teams[1] + greater_team = self.teams[0] + add_index = 0 + while (self._get_total_team_lives(lesser_team) < + self._get_total_team_lives(greater_team)): + lesser_team.players[add_index].lives += 1 + add_index = (add_index + 1) % len(lesser_team.players) + + self._bots = zBotSet() + + #Set colors and character for ToughGuyBot to be zombie + setattr(BrawlerBot, 'color', (0.4,0.1,0.05)) + setattr(BrawlerBot, 'highlight', (0.2,0.4,0.3)) + setattr(BrawlerBot, 'character', 'Kronk2') + # start some timers to spawn bots + thePt = self.map.get_ffa_start_position(self.players) + + self._update_icons() + + # We could check game-over conditions at explicit trigger points, + # but lets just do the simple thing and poll it. + ba.timer(1.0, self._update, repeat=True) + + def _update_icons(self) -> None: + # pylint: disable=too-many-branches + + # In free-for-all mode, everyone is just lined up along the bottom. + if isinstance(self.session, ba.FreeForAllSession): + count = len(self.teams) + x_offs = 85 + xval = x_offs * (count - 1) * -0.5 + for team in self.teams: + if len(team.players) == 1: + player = team.players[0] + for icon in player.icons: + icon.set_position_and_scale((xval, 30), 0.7) + icon.update_for_lives() + xval += x_offs + + # In teams mode we split up teams. + else: + if self._solo_mode: + # First off, clear out all icons. + for player in self.players: + player.icons = [] + + # Now for each team, cycle through our available players + # adding icons. + for team in self.teams: + if team.id == 0: + xval = -60 + x_offs = -78 + else: + xval = 60 + x_offs = 78 + is_first = True + test_lives = 1 + while True: + players_with_lives = [ + p for p in team.spawn_order + if p and p.lives >= test_lives + ] + if not players_with_lives: + break + for player in players_with_lives: + player.icons.append( + Icon(player, + position=(xval, (40 if is_first else 25)), + scale=1.0 if is_first else 0.5, + name_maxwidth=130 if is_first else 75, + name_scale=0.8 if is_first else 1.0, + flatness=0.0 if is_first else 1.0, + shadow=0.5 if is_first else 1.0, + show_death=is_first, + show_lives=False)) + xval += x_offs * (0.8 if is_first else 0.56) + is_first = False + test_lives += 1 + # Non-solo mode. + else: + for team in self.teams: + if team.id == 0: + xval = -50 + x_offs = -85 + else: + xval = 50 + x_offs = 85 + for player in team.players: + for icon in player.icons: + icon.set_position_and_scale((xval, 30), 0.7) + icon.update_for_lives() + xval += x_offs + + + def _get_spawn_point(self, player: Player) -> ba.Vec3 | None: + del player # Unused. + + # In solo-mode, if there's an existing live player on the map, spawn at + # whichever spot is farthest from them (keeps the action spread out). + if self._solo_mode: + living_player = None + living_player_pos = None + for team in self.teams: + for tplayer in team.players: + if tplayer.is_alive(): + assert tplayer.node + ppos = tplayer.node.position + living_player = tplayer + living_player_pos = ppos + break + if living_player: + assert living_player_pos is not None + player_pos = ba.Vec3(living_player_pos) + points: list[tuple[float, ba.Vec3]] = [] + for team in self.teams: + start_pos = ba.Vec3(self.map.get_start_position(team.id)) + points.append( + ((start_pos - player_pos).length(), start_pos)) + # Hmm.. we need to sorting vectors too? + points.sort(key=lambda x: x[0]) + return points[-1][1] + return None + + def spawn_player(self, player: Player) -> ba.Actor: + position = self.map.get_ffa_start_position(self.players) + angle = 20 + name = player.getname() + + light_color = _math.normalized_color(player.color) + display_color = _ba.safecolor(player.color, target_intensity=0.75) + spaz = PlayerSpaz_Zom(color=player.color, + highlight=player.highlight, + character=player.character, + player=player) + player.actor = spaz + assert spaz.node + self.spazList.append(spaz) + + if isinstance(self.session, CoopSession) and self.map.getname() in [ + 'Courtyard', 'Tower D' + ]: + mat = self.map.preloaddata['collide_with_wall_material'] + assert isinstance(spaz.node.materials, tuple) + assert isinstance(spaz.node.roller_materials, tuple) + spaz.node.materials += (mat, ) + spaz.node.roller_materials += (mat, ) + + spaz.node.name = name + spaz.node.name_color = display_color + spaz.connect_controls_to_player() + factory = SpazFactory() + + # Move to the stand position and add a flash of light. + spaz.handlemessage( + StandMessage( + position, + angle if angle is not None else random.uniform(0, 360))) + _ba.playsound(self._spawn_sound, 1, position=spaz.node.position) + light = _ba.newnode('light', attrs={'color': light_color}) + spaz.node.connectattr('position', light, 'position') + ba.animate(light, 'intensity', {0: 0, 0.25: 1, 0.5: 0}) + _ba.timer(0.5, light.delete) + + if not self._solo_mode: + ba.timer(0.3, ba.Call(self._print_lives, player)) + + for icon in player.icons: + icon.handle_player_spawned() + return spaz + + def respawn_player_zombie(self, + player: Player, + respawn_time: float | None = None) -> None: + # pylint: disable=cyclic-import + + assert player + if respawn_time is None: + teamsize = len(player.team.players) + if teamsize == 1: + respawn_time = 3.0 + elif teamsize == 2: + respawn_time = 5.0 + elif teamsize == 3: + respawn_time = 6.0 + else: + respawn_time = 7.0 + + # If this standard setting is present, factor it in. + if 'Respawn Times' in self.settings_raw: + respawn_time *= self.settings_raw['Respawn Times'] + + # We want whole seconds. + assert respawn_time is not None + respawn_time = round(max(1.0, respawn_time), 0) + + if player.actor and not self.has_ended(): + from bastd.actor.respawnicon import RespawnIcon + player.customdata['respawn_timer'] = _ba.Timer( + respawn_time, ba.WeakCall( + self.spawn_player_if_exists_as_zombie, player)) + player.customdata['respawn_icon'] = RespawnIcon( + player, respawn_time) + + def spawn_player_if_exists_as_zombie(self, player: PlayerType) -> None: + """ + A utility method which calls self.spawn_player() *only* if the + ba.Player provided still exists; handy for use in timers and whatnot. + + There is no need to override this; just override spawn_player(). + """ + if player: + self.spawn_player_zombie(player) + + def spawn_player_zombie(self, player: PlayerType) -> ba.Actor: + position = self.map.get_ffa_start_position(self.players) + angle = 20 + name = player.getname() + + light_color = _math.normalized_color(player.color) + display_color = _ba.safecolor(player.color, target_intensity=0.75) + spaz = PlayerSpaz_Zom(color=player.color, + highlight=player.highlight, + character='Kronk2', + player=player) + player.actor = spaz + assert spaz.node + self.spazList.append(spaz) + + if isinstance(self.session, CoopSession) and self.map.getname() in [ + 'Courtyard', 'Tower D' + ]: + mat = self.map.preloaddata['collide_with_wall_material'] + assert isinstance(spaz.node.materials, tuple) + assert isinstance(spaz.node.roller_materials, tuple) + spaz.node.materials += (mat, ) + spaz.node.roller_materials += (mat, ) + + spaz.node.name = name + spaz.node.name_color = display_color + spaz.connect_controls_to_player(enable_punch=True, + enable_bomb=False, + enable_pickup=False) + + # Move to the stand position and add a flash of light. + spaz.handlemessage( + StandMessage( + position, + angle if angle is not None else random.uniform(0, 360))) + _ba.playsound(self._spawn_sound, 1, position=spaz.node.position) + light = _ba.newnode('light', attrs={'color': light_color}) + spaz.node.connectattr('position', light, 'position') + ba.animate(light, 'intensity', {0: 0, 0.25: 1, 0.5: 0}) + _ba.timer(0.5, light.delete) + + if not self._solo_mode: + ba.timer(0.3, ba.Call(self._print_lives, player)) + + for icon in player.icons: + icon.handle_player_spawned() + return spaz + + def _print_lives(self, player: Player) -> None: + from bastd.actor import popuptext + + # We get called in a timer so it's possible our player has left/etc. + if not player or not player.is_alive() or not player.node: + return + + try: + pos = player.actor.node.position + except Exception as e: + print('EXC getting player pos in bsElim',e) + return + if player.lives > 0: + popuptext.PopupText('x' + str(player.lives - 1), + color=(1, 1, 0, 1), + offset=(0, -0.8, 0), + random_offset=0.0, + scale=1.8, + position=pos).autoretain() + else: + popuptext.PopupText('Dead!', + color=(1, 1, 0, 1), + offset=(0, -0.8, 0), + random_offset=0.0, + scale=1.8, + position=pos).autoretain() + + def on_player_leave(self, player: Player) -> None: + super().on_player_leave(player) + player.icons = [] + + # Remove us from spawn-order. + if self._solo_mode: + if player in player.team.spawn_order: + player.team.spawn_order.remove(player) + + # Update icons in a moment since our team will be gone from the + # list then. + ba.timer(0, self._update_icons) + + def _get_total_team_lives(self, team: Team) -> int: + return sum(player.lives for player in team.players) + + def handlemessage(self, msg: Any) -> Any: + if isinstance(msg, ba.PlayerDiedMessage): + + # Augment standard behavior. + super().handlemessage(msg) + player: Player = msg.getplayer(Player) + + if player.lives > 0: + player.lives -= 1 + else: + if msg._killerplayer: + if msg._killerplayer.lives > 0: + msg._killerplayer.team.score += 2 + self._update_scoreboard() + + if msg._player in self.spazList: + self.spazList.remove(msg._player) + if player.lives < 0: + ba.print_error( + "Got lives < 0 in Elim; this shouldn't happen. solo:" + + str(self._solo_mode)) + player.lives = 0 + + # If we have any icons, update their state. + for icon in player.icons: + icon.handle_player_died() + + # Play big death sound on our last death + # or for every one in solo mode. + if self._solo_mode or player.lives == 0: + ba.playsound(SpazFactory.get().single_player_death_sound) + + # If we hit zero lives, we're dead (and our team might be too). + if player.lives == 0: + self.respawn_player_zombie(player) + else: + # Otherwise, in regular mode, respawn. + if not self._solo_mode: + self.respawn_player(player) + + # In solo, put ourself at the back of the spawn order. + if self._solo_mode: + player.team.spawn_order.remove(player) + player.team.spawn_order.append(player) + + elif isinstance(msg, SpazBotDiedMessage): + self._onSpazBotDied(msg) + super().handlemessage(msg)#bs.PopupText("died",position=self._position,color=popupColor,scale=popupScale).autoRetain() + else: + super().handlemessage(msg) + + def _update(self) -> None: + if self.zombieQ > 0: + self.zombieQ -= 1 + self.spawn_zombie() + if self._solo_mode: + # For both teams, find the first player on the spawn order + # list with lives remaining and spawn them if they're not alive. + for team in self.teams: + # Prune dead players from the spawn order. + team.spawn_order = [p for p in team.spawn_order if p] + for player in team.spawn_order: + assert isinstance(player, Player) + if player.lives > 0: + if not player.is_alive(): + self.spawn_player(player) + self._update_icons() + break + + # If we're down to 1 or fewer living teams, start a timer to end + # the game (allows the dust to settle and draws to occur if deaths + # are close enough). + teamsRemain = self._get_living_teams() + if len(teamsRemain) < 2: + if len(teamsRemain) == 1: + theScores = [] + for team in self.teams: + theScores.append(team.score) + if teamsRemain[0].score < max(theScores): + pass + elif teamsRemain[0].score == max( + theScores) and theScores.count(max(theScores)) > 1: + pass + else: + self._round_end_timer = ba.Timer(0.5, self.end_game) + else: + self._round_end_timer = ba.Timer(0.5, self.end_game) + + def spawn_zombie(self) -> None: + #We need a Z height... + thePt = list(self.get_random_point_in_play()) + thePt2 = self.map.get_ffa_start_position(self.players) + thePt[1] = thePt2[1] + ba.timer(0.1, ba.Call( + self._bots.spawn_bot, BrawlerBot, pos=thePt, spawn_time=1.0)) + + def _onSpazBotDied(self,DeathMsg) -> None: + #Just in case we are over max... + if len(self._bots.get_living_bots()) < self._max_zombies: + self.zombieQ += 1 + + if DeathMsg.killerplayer is None: + pass + else: + player = DeathMsg.killerplayer + if not player: + return + if player.lives < 1: + return + player.team.score += 1 + self.zombieQ += 1 + self._update_scoreboard() + + def get_random_point_in_play(self) -> None: + myMap = self.map.getname() + if myMap == 'Doom Shroom': + while True: + x = random.uniform(-1.0,1.0) + y = random.uniform(-1.0,1.0) + if x*x+y*y < 1.0: break + return ((8.0*x,8.0,-3.5+5.0*y)) + elif myMap == 'Rampage': + x = random.uniform(-6.0,7.0) + y = random.uniform(-6.0,-2.5) + return ((x, 8.0, y)) + elif myMap == 'Hockey Stadium': + x = random.uniform(-11.5,11.5) + y = random.uniform(-4.5,4.5) + return ((x, 5.0, y)) + elif myMap == 'Courtyard': + x = random.uniform(-4.3,4.3) + y = random.uniform(-4.4,0.3) + return ((x, 8.0, y)) + elif myMap == 'Crag Castle': + x = random.uniform(-6.7,8.0) + y = random.uniform(-6.0,0.0) + return ((x, 12.0, y)) + elif myMap == 'Big G': + x = random.uniform(-8.7,8.0) + y = random.uniform(-7.5,6.5) + return ((x, 8.0, y)) + elif myMap == 'Football Stadium': + x = random.uniform(-12.5,12.5) + y = random.uniform(-5.0,5.5) + return ((x, 8.0, y)) + else: + x = random.uniform(-5.0,5.0) + y = random.uniform(-6.0,0.0) + return ((x, 8.0, y)) + + def _update_scoreboard(self) -> None: + for team in self.teams: + self._scoreboard.set_team_value(team, team.score) + + def _get_living_teams(self) -> list[Team]: + return [ + team for team in self.teams + if len(team.players) > 0 and any(player.lives > 0 + for player in team.players) + ] + + def end_game(self) -> None: + if self.has_ended(): + return + setattr(BrawlerBot, 'color', (0.6, 0.6, 0.6)) + setattr(BrawlerBot, 'highlight', (0.6, 0.6, 0.6)) + setattr(BrawlerBot, 'character', 'Kronk') + results = ba.GameResults() + self._vs_text = None # Kill our 'vs' if its there. + for team in self.teams: + results.set_team_score(team, team.score) + self.end(results=results) + + +# ba_meta export game +class ZombieHordeCoop(ZombieHorde): + + name = 'Zombie Horde' + + @classmethod + def get_supported_maps(cls, sessiontype: type[ba.Session]) -> list[str]: + return ['Football Stadium'] + + @classmethod + def supports_session_type(cls, sessiontype: type[ba.Session]) -> bool: + return (issubclass(sessiontype, ba.CoopSession)) + + def _update(self) -> None: + if self.zombieQ > 0: + self.zombieQ -= 1 + self.spawn_zombie() + if self._solo_mode: + # For both teams, find the first player on the spawn order + # list with lives remaining and spawn them if they're not alive. + for team in self.teams: + # Prune dead players from the spawn order. + team.spawn_order = [p for p in team.spawn_order if p] + for player in team.spawn_order: + assert isinstance(player, Player) + if player.lives > 0: + if not player.is_alive(): + self.spawn_player(player) + self._update_icons() + break + + if not any(player.is_alive() for player in self.teams[0].players): + self._round_end_timer = ba.Timer(0.5, self.end_game) + + def handlemessage(self, msg: Any) -> Any: + if isinstance(msg, ba.PlayerDiedMessage): + # Augment standard behavior. + ba.TeamGameActivity.handlemessage(self, msg) + player: Player = msg.getplayer(Player) + # If we have any icons, update their state. + for icon in player.icons: + icon.handle_player_died() + else: + super().handlemessage(msg) + + +# ba_meta export plugin +class ZombieHordeLevel(ba.Plugin): + def on_app_running(self) -> None: + ba.app.add_coop_practice_level( + ba.Level( + 'Zombie Horde', + gametype=ZombieHordeCoop, + settings={}, + preview_texture_name='footballStadiumPreview', + ) + ) From c052a1d7c14f43f68474edb180de10fbfcb6c9dc Mon Sep 17 00:00:00 2001 From: Loup-Garou911XD Date: Thu, 3 Nov 2022 17:29:43 +0000 Subject: [PATCH 11/55] [ci] auto-format --- plugins/minigames/BasketBomb.py | 279 +++++++------ plugins/minigames/Boxing.py | 384 ++++++++--------- plugins/minigames/MeteorShower.py | 658 +++++++++++++++--------------- plugins/minigames/SimonSays.py | 291 +++++++------ plugins/minigames/SquidRace.py | 29 +- plugins/minigames/ZombieHorde.py | 66 +-- 6 files changed, 883 insertions(+), 824 deletions(-) diff --git a/plugins/minigames/BasketBomb.py b/plugins/minigames/BasketBomb.py index c9030e5..78c35b8 100644 --- a/plugins/minigames/BasketBomb.py +++ b/plugins/minigames/BasketBomb.py @@ -6,7 +6,8 @@ from __future__ import annotations from typing import TYPE_CHECKING -import ba, _ba +import ba +import _ba from bastd.actor.playerspaz import PlayerSpaz from bastd.actor.scoreboard import Scoreboard from bastd.actor.powerupbox import PowerupBoxFactory @@ -19,42 +20,46 @@ if TYPE_CHECKING: bsuSpaz = None + def getlanguage(text, sub: str = ''): lang = _ba.app.lang.language translate = { - "Name": - {"Spanish": "Baloncesto", - "English": "Basketbomb", - "Portuguese": "Basketbomb"}, - "Info": - {"Spanish": "Anota todas las canastas y sé el MVP.", - "English": "Score all the baskets and be the MVP.", - "Portuguese": "Marque cada cesta e seja o MVP."}, - "Info-Short": - {"Spanish": f"Anota {sub} canasta(s) para ganar", - "English": f"Score {sub} baskets to win", - "Portuguese": f"Cestas de {sub} pontos para ganhar"}, - "S: Powerups": - {"Spanish": "Aparecer Potenciadores", - "English": "Powerups Spawn", - "Portuguese": "Habilitar Potenciadores"}, - "S: Velocity": + "Name": + {"Spanish": "Baloncesto", + "English": "Basketbomb", + "Portuguese": "Basketbomb"}, + "Info": + {"Spanish": "Anota todas las canastas y sé el MVP.", + "English": "Score all the baskets and be the MVP.", + "Portuguese": "Marque cada cesta e seja o MVP."}, + "Info-Short": + {"Spanish": f"Anota {sub} canasta(s) para ganar", + "English": f"Score {sub} baskets to win", + "Portuguese": f"Cestas de {sub} pontos para ganhar"}, + "S: Powerups": + {"Spanish": "Aparecer Potenciadores", + "English": "Powerups Spawn", + "Portuguese": "Habilitar Potenciadores"}, + "S: Velocity": {"Spanish": "Activar velocidad", "English": "Enable speed", "Portuguese": "Ativar velocidade"}, - } - - languages = ['Spanish','Portuguese','English'] - if lang not in languages: lang = 'English' + } + + languages = ['Spanish', 'Portuguese', 'English'] + if lang not in languages: + lang = 'English' if text not in translate: return text return translate[text][lang] + class BallDiedMessage: def __init__(self, ball: Ball): self.ball = ball + class Ball(ba.Actor): def __init__(self, position: Sequence[float] = (0.0, 1.0, 0.0)): super().__init__() @@ -62,14 +67,14 @@ class Ball(ba.Actor): activity = self.getactivity() velocty = (0.0, 8.0, 0.0) _scale = 1.2 - + self._spawn_pos = (position[0], position[1] + 0.5, position[2]) self.last_players_to_touch: Dict[int, Player] = {} self.scored = False assert activity is not None assert isinstance(activity, BasketGame) - + pmats = [shared.object_material, activity.ball_material] self.node = ba.newnode('prop', delegate=self, @@ -132,14 +137,18 @@ class Team(ba.Team[Player]): def __init__(self) -> None: self.score = 0 + class Points: postes = dict() - postes['pal_0'] = (10.64702320098877, 0.0000000000000000, 0.0000000000000000) #10.736066818237305, 0.3002409040927887, 0.5281256437301636 + # 10.736066818237305, 0.3002409040927887, 0.5281256437301636 + postes['pal_0'] = (10.64702320098877, 0.0000000000000000, 0.0000000000000000) postes['pal_1'] = (-10.64702320098877, 0.0000000000000000, 0.0000000000000000) # ba_meta export game + + class BasketGame(ba.TeamGameActivity[Player, Team]): - + name = getlanguage('Name') description = getlanguage('Info') available_settings = [ @@ -202,7 +211,7 @@ class BasketGame(ba.TeamGameActivity[Player, Team]): self._speed = bool(settings[getlanguage('S: Velocity')]) self._epic_mode = bool(settings['Epic Mode']) self.slow_motion = self._epic_mode - + self.ball_material = ba.Material() self.ball_material.add_actions(actions=(('modify_part_collision', 'friction', 0.5))) @@ -251,10 +260,10 @@ class BasketGame(ba.TeamGameActivity[Player, Team]): super().on_begin() self.setup_standard_time_limit(self._time_limit) - + if self._powerups: self.setup_standard_powerup_drops() - + self._ball_spawn_pos = self.map.get_flag_position(None) self._spawn_ball() @@ -336,7 +345,7 @@ class BasketGame(ba.TeamGameActivity[Player, Team]): if team.score >= self._score_to_win: self.end_game() - #ba.playsound(self._foghorn_sound) + # ba.playsound(self._foghorn_sound) ba.playsound(self._cheer_sound) self._ball.scored = True @@ -366,8 +375,8 @@ class BasketGame(ba.TeamGameActivity[Player, Team]): winscore = self._score_to_win for id, team in enumerate(self.teams): self._scoreboard.set_team_value(team, team.score, winscore) - #self.postes(id) - + # self.postes(id) + def spawn_player(self, player: Player) -> ba.Actor: if bsuSpaz is None: spaz = self.spawn_player_spaz(player) @@ -375,7 +384,7 @@ class BasketGame(ba.TeamGameActivity[Player, Team]): ps.PlayerSpaz = bsuSpaz.BskSpaz spaz = self.spawn_player_spaz(player) ps.PlayerSpaz = bsuSpaz.OldPlayerSpaz - + if self._speed: spaz.node.hockey = True return spaz @@ -393,9 +402,9 @@ class BasketGame(ba.TeamGameActivity[Player, Team]): def postes(self, team_id: int): if not hasattr(self._map, 'poste_'+str(team_id)): setattr(self._map, 'poste_'+str(team_id), - Palos(team=team_id, - position=Points.postes['pal_' + - str(team_id)]).autoretain()) + Palos(team=team_id, + position=Points.postes['pal_' + + str(team_id)]).autoretain()) def _flash_ball_spawn(self) -> None: light = ba.newnode('light', @@ -414,6 +423,7 @@ class BasketGame(ba.TeamGameActivity[Player, Team]): assert self._ball_spawn_pos is not None self._ball = Ball(position=self._ball_spawn_pos) + class Aro(ba.Actor): def __init__(self, team: int = 0, position: Sequence[float] = (0.0, 1.0, 0.0)): @@ -422,7 +432,7 @@ class Aro(ba.Actor): shared = SharedObjects.get() setattr(self, 'team', team) setattr(self, 'locs', []) - + # Material Para; Traspasar Objetos self.no_collision = ba.Material() self.no_collision.add_actions( @@ -443,10 +453,10 @@ class Aro(ba.Actor): self._spawn_pos = (position[0], position[1], position[2]) self._materials_region0 = [self.collision, shared.footing_material] - + model = None tex = ba.gettexture('null') - + pmats = [self.no_collision] self.node = ba.newnode('prop', delegate=self, @@ -459,55 +469,56 @@ class Aro(ba.Actor): 'shadow_size': 0.1, 'position': self._spawn_pos, 'materials': pmats}) - + self.scale = scale = 1.4 ba.animate(self.node, 'model_scale', {0: 0}) pos = (position[0], position[1]+0.6, position[2]) self.regions: List[ba.Node] = [ ba.newnode('region', - attrs={'position': position, - 'scale': (0.6, 0.05, 0.6), - 'type': 'box', - 'materials': self._materials_region0}), - + attrs={'position': position, + 'scale': (0.6, 0.05, 0.6), + 'type': 'box', + 'materials': self._materials_region0}), + ba.newnode('region', - attrs={'position': pos, - 'scale': (0.5, 0.3, 0.9), - 'type': 'box', - 'materials': [self._score_region_material]}) - ] + attrs={'position': pos, + 'scale': (0.5, 0.3, 0.9), + 'type': 'box', + 'materials': [self._score_region_material]}) + ] self.regions[0].connectattr('position', self.node, 'position') #self.regions[0].connectattr('position', self.regions[1], 'position') locs_count = 9 pos = list(position) - + try: id = 0 if team == 1 else 1 color = act.teams[id].color - except: color = (1,1,1) - + except: + color = (1, 1, 1) + while locs_count > 1: scale = (1.5 * 0.1 * locs_count) + 0.8 self.locs.append(ba.newnode('locator', - owner=self.node, - attrs={'shape': 'circleOutline', - 'position': pos, - 'color': color, - 'opacity': 1.0, - 'size': [scale], - 'draw_beauty': True, - 'additive': False})) - + owner=self.node, + attrs={'shape': 'circleOutline', + 'position': pos, + 'color': color, + 'opacity': 1.0, + 'size': [scale], + 'draw_beauty': True, + 'additive': False})) + pos[1] -= 0.1 locs_count -= 1 - + def _annotation(self): assert len(self.regions) >= 2 ball = self.getactivity()._ball - + if ball: p = self.regions[0].position ball.node.position = p @@ -523,6 +534,7 @@ class Aro(ba.Actor): else: super().handlemessage(msg) + class Cuadro(ba.Actor): def __init__(self, team: int = 0, position: Sequence[float] = (0.0, 1.0, 0.0)): @@ -536,13 +548,13 @@ class Cuadro(ba.Actor): actions=(('modify_part_collision', 'collide', True))) pos = (position[0], position[1]+0.9, position[2]+1.5) - self.region: ba.Node = ba.newnode('region', - attrs={'position': pos, - 'scale': (0.5, 2.7, 2.5), - 'type': 'box', - 'materials': [self.collision, - shared.footing_material]}) - + self.region: ba.Node = ba.newnode('region', + attrs={'position': pos, + 'scale': (0.5, 2.7, 2.5), + 'type': 'box', + 'materials': [self.collision, + shared.footing_material]}) + #self.shield = ba.newnode('shield', attrs={'radius': 1.0, 'color': (0,10,0)}) #self.region.connectattr('position', self.shield, 'position') @@ -550,38 +562,38 @@ class Cuadro(ba.Actor): pos = list(position) oldpos = list(position) old_count = 14 - + count = old_count count_y = 9 try: id = 0 if team == 1 else 1 color = act.teams[id].color - except: color = (1,1,1) + except: + color = (1, 1, 1) - while(count_y != 1): + while (count_y != 1): - while(count != 1): + while (count != 1): pos[2] += 0.19 - + self.locs.append( ba.newnode('locator', - owner=self.region, - attrs={'shape': 'circle', - 'position': pos, - 'size': [0.5], - 'color': color, - 'opacity': 1.0, - 'draw_beauty': True, - 'additive': False})) + owner=self.region, + attrs={'shape': 'circle', + 'position': pos, + 'size': [0.5], + 'color': color, + 'opacity': 1.0, + 'draw_beauty': True, + 'additive': False})) count -= 1 - count = old_count pos[1] += 0.2 pos[2] = oldpos[2] count_y -= 1 - + def handlemessage(self, msg: Any) -> Any: if isinstance(msg, ba.DieMessage): if self.node.exists(): @@ -589,6 +601,7 @@ class Cuadro(ba.Actor): else: super().handlemessage(msg) + class Palos(ba.Actor): def __init__(self, team: int = 0, position: Sequence[float] = (0.0, 1.0, 0.0)): @@ -604,17 +617,17 @@ class Palos(ba.Actor): self.no_collision.add_actions( actions=(('modify_part_collision', 'collide', False))) - # + # self.collision = ba.Material() self.collision.add_actions( actions=(('modify_part_collision', 'collide', True))) # Spawn just above the provided point. self._spawn_pos = (position[0], position[2]+2.5, position[2]) - + model = ba.getmodel('flagPole') tex = ba.gettexture('flagPoleColor') - + pmats = [self.no_collision] self.node = ba.newnode('prop', delegate=self, @@ -633,34 +646,35 @@ class Palos(ba.Actor): ba.animate(self.node, 'model_scale', {0: scale}) self.loc = ba.newnode('locator', - owner=self.node, - attrs={'shape': 'circle', - 'position': position, - 'color': (1,1,0), - 'opacity': 1.0, - 'draw_beauty': False, - 'additive': True}) + owner=self.node, + attrs={'shape': 'circle', + 'position': position, + 'color': (1, 1, 0), + 'opacity': 1.0, + 'draw_beauty': False, + 'additive': True}) self._y = _y = 0.30 _x = -0.25 if team == 1 else 0.25 _pos = (position[0]+_x, position[1]-1.5 + _y, position[2]) self.region = ba.newnode('region', - attrs={ - 'position': _pos, - 'scale': (0.4, 8, 0.4), - 'type': 'box', - 'materials': [self.collision]}) + attrs={ + 'position': _pos, + 'scale': (0.4, 8, 0.4), + 'type': 'box', + 'materials': [self.collision]}) self.region.connectattr('position', self.node, 'position') _y = self._y position = self._pos if team == 0: pos = (position[0]-0.8, position[1] + 2.0 + _y, position[2]) - else: pos = (position[0]+0.8, position[1] + 2.0 + _y, position[2]) - + else: + pos = (position[0]+0.8, position[1] + 2.0 + _y, position[2]) + if self.aro is None: self.aro = Aro(team, pos).autoretain() - + if self.cua is None: pos = (position[0], position[1] + 1.8 + _y, position[2]-1.4) self.cua = Cuadro(team, pos).autoretain() @@ -670,7 +684,8 @@ class Palos(ba.Actor): if self.node.exists(): self.node.delete() else: - super().handlemessage(msg) + super().handlemessage(msg) + class BasketMap(maps.FootballStadium): name = 'BasketBall Stadium' @@ -682,7 +697,7 @@ class BasketMap(maps.FootballStadium): def __init__(self) -> None: super().__init__() - + gnode = ba.getactivity().globalsnode gnode.tint = [(0.806, 0.8, 1.0476), (1.3, 1.2, 1.0)][0] gnode.ambient_color = (1.3, 1.2, 1.0) @@ -691,13 +706,14 @@ class BasketMap(maps.FootballStadium): gnode.vr_camera_offset = (0, -0.8, -1.1) gnode.vr_near_clip = 0.5 + class BasketMapV2(maps.HockeyStadium): name = 'BasketBall Stadium V2' def __init__(self) -> None: super().__init__() - - shared = SharedObjects.get() + + shared = SharedObjects.get() self.node.materials = [shared.footing_material] self.node.collide_model = ba.getcollidemodel('footballStadiumCollide') self.node.model = None @@ -705,13 +721,13 @@ class BasketMapV2(maps.HockeyStadium): self.floor.reflection = 'soft' self.floor.reflection_scale = [1.6] self.floor.color = (1.1, 0.05, 0.8) - + self.background = ba.newnode('terrain', - attrs={'model': ba.getmodel('thePadBG'), - 'lighting': False, - 'background': True, - 'color': (1.0, 0.2, 1.0), - 'color_texture': ba.gettexture('menuBG')}) + attrs={'model': ba.getmodel('thePadBG'), + 'lighting': False, + 'background': True, + 'color': (1.0, 0.2, 1.0), + 'color_texture': ba.gettexture('menuBG')}) gnode = ba.getactivity().globalsnode gnode.floor_reflection = True @@ -729,26 +745,27 @@ class BasketMapV2(maps.HockeyStadium): self.collision = ba.Material() self.collision.add_actions( actions=(('modify_part_collision', 'collide', True))) - + self.regions: List[ba.Node] = [ ba.newnode('region', - attrs={'position': (12.676897048950195, 0.2997918128967285, 5.583303928375244), - 'scale': (1.01, 12, 28), - 'type': 'box', - 'materials': [self.collision]}), - + attrs={'position': (12.676897048950195, 0.2997918128967285, 5.583303928375244), + 'scale': (1.01, 12, 28), + 'type': 'box', + 'materials': [self.collision]}), + ba.newnode('region', - attrs={'position': (11.871315956115723, 0.29975247383117676, 5.711406707763672), - 'scale': (50, 12, 0.9), - 'type': 'box', - 'materials': [self.collision]}), - + attrs={'position': (11.871315956115723, 0.29975247383117676, 5.711406707763672), + 'scale': (50, 12, 0.9), + 'type': 'box', + 'materials': [self.collision]}), + ba.newnode('region', - attrs={'position': (-12.776557922363281, 0.30036890506744385, 4.96237850189209), - 'scale': (1.01, 12, 28), - 'type': 'box', - 'materials': [self.collision]}), - ] + attrs={'position': (-12.776557922363281, 0.30036890506744385, 4.96237850189209), + 'scale': (1.01, 12, 28), + 'type': 'box', + 'materials': [self.collision]}), + ] + ba._map.register_map(BasketMap) -ba._map.register_map(BasketMapV2) \ No newline at end of file +ba._map.register_map(BasketMapV2) diff --git a/plugins/minigames/Boxing.py b/plugins/minigames/Boxing.py index 0a6a4b2..35a7c75 100644 --- a/plugins/minigames/Boxing.py +++ b/plugins/minigames/Boxing.py @@ -11,230 +11,230 @@ from bastd.actor.scoreboard import Scoreboard from bastd.game.deathmatch import DeathMatchGame if TYPE_CHECKING: - from typing import Any, Sequence + from typing import Any, Sequence lang = ba.app.lang.language if lang == 'Spanish': - name = 'Super Boxeo' - description = ('¡Sin bombas!\n' - '¡Noquea a los enemigos con tus propias manos!\n') - super_jump_text = 'Super Salto' - enable_powerups = 'Habilitar Potenciadores' + name = 'Super Boxeo' + description = ('¡Sin bombas!\n' + '¡Noquea a los enemigos con tus propias manos!\n') + super_jump_text = 'Super Salto' + enable_powerups = 'Habilitar Potenciadores' else: - name = 'Super Boxing' - description = ('No bombs!\n' - 'Knock out your enemies using your bare hands!\n') - super_jump_text = 'Super Jump' - enable_powerups = 'Enable Powerups' + name = 'Super Boxing' + description = ('No bombs!\n' + 'Knock out your enemies using your bare hands!\n') + super_jump_text = 'Super Jump' + enable_powerups = 'Enable Powerups' class NewPlayerSpaz(PlayerSpaz): - def __init__(self, - player: ba.Player, - color: Sequence[float] = (1.0, 1.0, 1.0), - highlight: Sequence[float] = (0.5, 0.5, 0.5), - character: str = 'Spaz', - powerups_expire: bool = True, - super_jump: bool = False): - super().__init__(player=player, - color=color, - highlight=highlight, - character=character, - powerups_expire=powerups_expire) - from bastd.gameutils import SharedObjects - shared = SharedObjects.get() - self._super_jump = super_jump - self.jump_mode = False - self.super_jump_material = ba.Material() - self.super_jump_material.add_actions( - conditions=('they_have_material', shared.footing_material), - actions=( - ('call', 'at_connect', ba.Call(self.jump_state, True)), - ('call', 'at_disconnect', ba.Call(self.jump_state, False)) - ), - ) - self.node.roller_materials += (self.super_jump_material, ) + def __init__(self, + player: ba.Player, + color: Sequence[float] = (1.0, 1.0, 1.0), + highlight: Sequence[float] = (0.5, 0.5, 0.5), + character: str = 'Spaz', + powerups_expire: bool = True, + super_jump: bool = False): + super().__init__(player=player, + color=color, + highlight=highlight, + character=character, + powerups_expire=powerups_expire) + from bastd.gameutils import SharedObjects + shared = SharedObjects.get() + self._super_jump = super_jump + self.jump_mode = False + self.super_jump_material = ba.Material() + self.super_jump_material.add_actions( + conditions=('they_have_material', shared.footing_material), + actions=( + ('call', 'at_connect', ba.Call(self.jump_state, True)), + ('call', 'at_disconnect', ba.Call(self.jump_state, False)) + ), + ) + self.node.roller_materials += (self.super_jump_material, ) - def jump_state(self, mode: bool) -> None: - self.jump_mode = mode + def jump_state(self, mode: bool) -> None: + self.jump_mode = mode - def on_jump_press(self) -> None: - """ - Called to 'press jump' on this spaz; - used by player or AI connections. - """ - if not self.node: - return - t_ms = ba.time(timeformat=ba.TimeFormat.MILLISECONDS) - assert isinstance(t_ms, int) - if t_ms - self.last_jump_time_ms >= self._jump_cooldown: - self.node.jump_pressed = True - self.last_jump_time_ms = t_ms - if self._player.is_alive() and self.jump_mode and ( - self._super_jump): - def do_jump(): - self.node.handlemessage( - 'impulse', - self.node.position[0], - self.node.position[1], - self.node.position[2], - 0, 0, 0, 150, 150, 0, 0, 0, 1, 0 - ) - ba.timer(0.0, do_jump) - ba.timer(0.1, do_jump) - ba.timer(0.2, do_jump) - self._turbo_filter_add_press('jump') + def on_jump_press(self) -> None: + """ + Called to 'press jump' on this spaz; + used by player or AI connections. + """ + if not self.node: + return + t_ms = ba.time(timeformat=ba.TimeFormat.MILLISECONDS) + assert isinstance(t_ms, int) + if t_ms - self.last_jump_time_ms >= self._jump_cooldown: + self.node.jump_pressed = True + self.last_jump_time_ms = t_ms + if self._player.is_alive() and self.jump_mode and ( + self._super_jump): + def do_jump(): + self.node.handlemessage( + 'impulse', + self.node.position[0], + self.node.position[1], + self.node.position[2], + 0, 0, 0, 150, 150, 0, 0, 0, 1, 0 + ) + ba.timer(0.0, do_jump) + ba.timer(0.1, do_jump) + ba.timer(0.2, do_jump) + self._turbo_filter_add_press('jump') # ba_meta export game class BoxingGame(DeathMatchGame): - name = name - description = description + name = name + description = description - @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(super_jump_text, default=False), - ba.BoolSetting(enable_powerups, default=False), - ba.BoolSetting('Epic Mode', default=False), - ] + @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(super_jump_text, default=False), + ba.BoolSetting(enable_powerups, default=False), + ba.BoolSetting('Epic Mode', default=False), + ] - # In teams mode, a suicide gives a point to the other team, but in - # free-for-all it subtracts from your own score. By default we clamp - # this at zero to benefit new players, but pro players might like to - # be able to go negative. (to avoid a strategy of just - # suiciding until you get a good drop) - if issubclass(sessiontype, ba.FreeForAllSession): - settings.append( - ba.BoolSetting('Allow Negative Scores', default=False) - ) + # In teams mode, a suicide gives a point to the other team, but in + # free-for-all it subtracts from your own score. By default we clamp + # this at zero to benefit new players, but pro players might like to + # be able to go negative. (to avoid a strategy of just + # suiciding until you get a good drop) + if issubclass(sessiontype, ba.FreeForAllSession): + settings.append( + ba.BoolSetting('Allow Negative Scores', default=False) + ) - return settings + return settings - def __init__(self, settings: dict): - super().__init__(settings) - self._scoreboard = Scoreboard() - self._score_to_win: int | None = 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._super_jump = bool(settings[super_jump_text]) - self._enable_powerups = bool(settings[enable_powerups]) + def __init__(self, settings: dict): + super().__init__(settings) + self._scoreboard = Scoreboard() + self._score_to_win: int | None = 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._super_jump = bool(settings[super_jump_text]) + self._enable_powerups = bool(settings[enable_powerups]) - # Base class overrides. - self.slow_motion = self._epic_mode - self.default_music = ( - ba.MusicType.EPIC if self._epic_mode else ba.MusicType.TO_THE_DEATH - ) + # Base class overrides. + self.slow_motion = self._epic_mode + self.default_music = ( + ba.MusicType.EPIC if self._epic_mode else ba.MusicType.TO_THE_DEATH + ) - def on_begin(self) -> None: - ba.TeamGameActivity.on_begin(self) - self.setup_standard_time_limit(self._time_limit) - if self._enable_powerups: - self.setup_standard_powerup_drops() + def on_begin(self) -> None: + ba.TeamGameActivity.on_begin(self) + self.setup_standard_time_limit(self._time_limit) + if self._enable_powerups: + self.setup_standard_powerup_drops() - # Base kills needed to win on the size of the largest team. - self._score_to_win = self._kills_to_win_per_player * max( - 1, max(len(t.players) for t in self.teams) - ) - self._update_scoreboard() + # Base kills needed to win on the size of the largest team. + self._score_to_win = self._kills_to_win_per_player * max( + 1, max(len(t.players) for t in self.teams) + ) + self._update_scoreboard() - def _standard_drop_powerup(self, index: int, expire: bool = True) -> None: - # pylint: disable=cyclic-import - from bastd.actor.powerupbox import PowerupBox, PowerupBoxFactory + def _standard_drop_powerup(self, index: int, expire: bool = True) -> None: + # pylint: disable=cyclic-import + from bastd.actor.powerupbox import PowerupBox, PowerupBoxFactory - PowerupBox( - position=self.map.powerup_spawn_points[index], - poweruptype=PowerupBoxFactory.get().get_random_powerup_type( - excludetypes=['triple_bombs','ice_bombs','impact_bombs', - 'land_mines','sticky_bombs','punch'] - ), - expire=expire, - ).autoretain() + PowerupBox( + position=self.map.powerup_spawn_points[index], + poweruptype=PowerupBoxFactory.get().get_random_powerup_type( + excludetypes=['triple_bombs', 'ice_bombs', 'impact_bombs', + 'land_mines', 'sticky_bombs', 'punch'] + ), + expire=expire, + ).autoretain() - def spawn_player(self, player: Player) -> ba.Actor: - import random - from ba import _math - from ba._gameutils import animate - from ba._coopsession import CoopSession + def spawn_player(self, player: Player) -> ba.Actor: + import random + from ba import _math + from ba._gameutils import animate + from ba._coopsession import CoopSession - if isinstance(self.session, ba.DualTeamSession): - position = self.map.get_start_position(player.team.id) - else: - # otherwise do free-for-all spawn locations - position = self.map.get_ffa_start_position(self.players) - angle = None - name = player.getname() - color = player.color - highlight = player.highlight + if isinstance(self.session, ba.DualTeamSession): + position = self.map.get_start_position(player.team.id) + else: + # otherwise do free-for-all spawn locations + position = self.map.get_ffa_start_position(self.players) + angle = None + name = player.getname() + color = player.color + highlight = player.highlight - light_color = _math.normalized_color(color) - display_color = ba.safecolor(color, target_intensity=0.75) + light_color = _math.normalized_color(color) + display_color = ba.safecolor(color, target_intensity=0.75) - spaz = NewPlayerSpaz(color=color, - highlight=highlight, - character=player.character, - player=player, - super_jump=self._super_jump) + spaz = NewPlayerSpaz(color=color, + highlight=highlight, + character=player.character, + player=player, + super_jump=self._super_jump) - player.actor = spaz - assert spaz.node + player.actor = spaz + assert spaz.node - spaz.node.name = name - spaz.node.name_color = display_color + spaz.node.name = name + spaz.node.name_color = display_color - # Move to the stand position and add a flash of light. - spaz.handlemessage( - ba.StandMessage( - position, - angle if angle is not None else random.uniform(0, 360))) - ba.playsound(self._spawn_sound, 1, position=spaz.node.position) - light = ba.newnode('light', attrs={'color': light_color}) - spaz.node.connectattr('position', light, 'position') - animate(light, 'intensity', {0: 0, 0.25: 1, 0.5: 0}) - ba.timer(0.5, light.delete) + # Move to the stand position and add a flash of light. + spaz.handlemessage( + ba.StandMessage( + position, + angle if angle is not None else random.uniform(0, 360))) + ba.playsound(self._spawn_sound, 1, position=spaz.node.position) + light = ba.newnode('light', attrs={'color': light_color}) + spaz.node.connectattr('position', light, 'position') + animate(light, 'intensity', {0: 0, 0.25: 1, 0.5: 0}) + ba.timer(0.5, light.delete) - # custom - spaz.connect_controls_to_player(enable_bomb=False) - spaz.equip_boxing_gloves() + # custom + spaz.connect_controls_to_player(enable_bomb=False) + spaz.equip_boxing_gloves() - return spaz + return spaz diff --git a/plugins/minigames/MeteorShower.py b/plugins/minigames/MeteorShower.py index 149f2a9..0f87f39 100644 --- a/plugins/minigames/MeteorShower.py +++ b/plugins/minigames/MeteorShower.py @@ -11,396 +11,396 @@ from bastd.actor.bomb import Bomb from bastd.actor.onscreentimer import OnScreenTimer if TYPE_CHECKING: - from typing import Any, Sequence + from typing import Any, Sequence lang = ba.app.lang.language if lang == 'Spanish': - name = 'Lluvia de Meteoritos v2' - bomb_type = 'Tipo de Bomba' - ice = 'hielo' - sticky = 'pegajosa' - impact = 'insta-bomba' - land_mine = 'mina terrestre' - random_bomb = 'aleatoria' - normal_rain = 'Lluvia Normal' - frozen_rain = 'Lluvia Congelada' - sticky_rain = 'Lluvia Pegajosa' - impact_rain = 'Lluvia de Impacto' - mine_rain = 'Lluvia de Minas' - tnt_rain = 'Lluvia de TNT' - random_rain = 'Lluvia Aleatoria' + name = 'Lluvia de Meteoritos v2' + bomb_type = 'Tipo de Bomba' + ice = 'hielo' + sticky = 'pegajosa' + impact = 'insta-bomba' + land_mine = 'mina terrestre' + random_bomb = 'aleatoria' + normal_rain = 'Lluvia Normal' + frozen_rain = 'Lluvia Congelada' + sticky_rain = 'Lluvia Pegajosa' + impact_rain = 'Lluvia de Impacto' + mine_rain = 'Lluvia de Minas' + tnt_rain = 'Lluvia de TNT' + random_rain = 'Lluvia Aleatoria' else: - name = 'Meteor Shower v2' - bomb_type = 'Bomb Type' - ice = 'ice' - sticky = 'sticky' - impact = 'impact' - land_mine = 'land mine' - random_bomb = 'random' - normal_rain = 'Normal Rain' - frozen_rain = 'Frozen Rain' - sticky_rain = 'Sticky Rain' - impact_rain = 'Impact Rain' - mine_rain = 'Mine Rain' - tnt_rain = 'TNT Rain' - random_rain = 'Random Rain' + name = 'Meteor Shower v2' + bomb_type = 'Bomb Type' + ice = 'ice' + sticky = 'sticky' + impact = 'impact' + land_mine = 'land mine' + random_bomb = 'random' + normal_rain = 'Normal Rain' + frozen_rain = 'Frozen Rain' + sticky_rain = 'Sticky Rain' + impact_rain = 'Impact Rain' + mine_rain = 'Mine Rain' + tnt_rain = 'TNT Rain' + random_rain = 'Random Rain' class Player(ba.Player['Team']): - """Our player type for this game.""" + """Our player type for this game.""" - def __init__(self) -> None: - super().__init__() - self.death_time: float | None = None + def __init__(self) -> None: + super().__init__() + self.death_time: float | None = None class Team(ba.Team[Player]): - """Our team type for this game.""" + """Our team type for this game.""" # ba_meta export game class MeteorShowerv2Game(ba.TeamGameActivity[Player, Team]): - """Minigame involving dodging falling bombs.""" + """Minigame involving dodging falling bombs.""" - name = name - description = 'Dodge the falling bombs.' - scoreconfig = ba.ScoreConfig( - label='Survived', scoretype=ba.ScoreType.MILLISECONDS, version='B' - ) + name = name + description = 'Dodge the falling bombs.' + scoreconfig = ba.ScoreConfig( + label='Survived', scoretype=ba.ScoreType.MILLISECONDS, version='B' + ) - # Print messages when players die (since its meaningful in this game). - announce_player_deaths = True + # Print messages when players die (since its meaningful in this game). + announce_player_deaths = True - # Don't allow joining after we start - # (would enable leave/rejoin tomfoolery). - allow_mid_activity_joins = False + # Don't allow joining after we start + # (would enable leave/rejoin tomfoolery). + allow_mid_activity_joins = False - @classmethod - def get_available_settings( - cls, sessiontype: type[ba.Session] - ) -> list[ba.Setting]: - settings = [ - ba.IntChoiceSetting( - bomb_type, - choices=[ - ('normal', 0), - (ice, 1), - (sticky, 2), - (impact, 3), - (land_mine, 4), - ('tnt', 5), - (random_bomb, 6) - ], - default=0, - ), - ba.BoolSetting('Epic Mode', default=False), - ] - return settings + @classmethod + def get_available_settings( + cls, sessiontype: type[ba.Session] + ) -> list[ba.Setting]: + settings = [ + ba.IntChoiceSetting( + bomb_type, + choices=[ + ('normal', 0), + (ice, 1), + (sticky, 2), + (impact, 3), + (land_mine, 4), + ('tnt', 5), + (random_bomb, 6) + ], + default=0, + ), + ba.BoolSetting('Epic Mode', default=False), + ] + return settings - # We're currently hard-coded for one map. - @classmethod - def get_supported_maps(cls, sessiontype: type[ba.Session]) -> list[str]: - return ['Rampage'] + # We're currently hard-coded for one map. + @classmethod + def get_supported_maps(cls, sessiontype: type[ba.Session]) -> list[str]: + return ['Rampage'] - # We support teams, free-for-all, and co-op sessions. - @classmethod - def supports_session_type(cls, sessiontype: type[ba.Session]) -> bool: - return ( - issubclass(sessiontype, ba.DualTeamSession) - or issubclass(sessiontype, ba.FreeForAllSession) - or issubclass(sessiontype, ba.CoopSession) - ) + # We support teams, free-for-all, and co-op sessions. + @classmethod + def supports_session_type(cls, sessiontype: type[ba.Session]) -> bool: + return ( + issubclass(sessiontype, ba.DualTeamSession) + or issubclass(sessiontype, ba.FreeForAllSession) + or issubclass(sessiontype, ba.CoopSession) + ) - def __init__(self, settings: dict): - super().__init__(settings) - btype = int(settings[bomb_type]) - if btype == 0: - newbtype = 'normal' - elif btype == 1: - newbtype = 'ice' - elif btype == 2: - newbtype = 'sticky' - elif btype == 3: - newbtype = 'impact' - elif btype == 4: - newbtype = 'land_mine' - elif btype == 5: - newbtype = 'tnt' - else: - newbtype = 'random' - self._bomb_type = newbtype - self._epic_mode = settings.get('Epic Mode', False) - self._last_player_death_time: float | None = None - self._meteor_time = 2.0 - self._timer: OnScreenTimer | None = None + def __init__(self, settings: dict): + super().__init__(settings) + btype = int(settings[bomb_type]) + if btype == 0: + newbtype = 'normal' + elif btype == 1: + newbtype = 'ice' + elif btype == 2: + newbtype = 'sticky' + elif btype == 3: + newbtype = 'impact' + elif btype == 4: + newbtype = 'land_mine' + elif btype == 5: + newbtype = 'tnt' + else: + newbtype = 'random' + self._bomb_type = newbtype + self._epic_mode = settings.get('Epic Mode', False) + self._last_player_death_time: float | None = None + self._meteor_time = 2.0 + self._timer: OnScreenTimer | None = None - # Some base class overrides: - self.default_music = ( - ba.MusicType.EPIC if self._epic_mode else ba.MusicType.SURVIVAL - ) - if self._epic_mode: - self.slow_motion = True + # Some base class overrides: + self.default_music = ( + ba.MusicType.EPIC if self._epic_mode else ba.MusicType.SURVIVAL + ) + if self._epic_mode: + self.slow_motion = True - def on_begin(self) -> None: - super().on_begin() + def on_begin(self) -> None: + super().on_begin() - # Drop a wave every few seconds.. and every so often drop the time - # between waves ..lets have things increase faster if we have fewer - # players. - delay = 5.0 if len(self.players) > 2 else 2.5 - if self._epic_mode: - delay *= 0.25 - ba.timer(delay, self._decrement_meteor_time, repeat=True) + # Drop a wave every few seconds.. and every so often drop the time + # between waves ..lets have things increase faster if we have fewer + # players. + delay = 5.0 if len(self.players) > 2 else 2.5 + if self._epic_mode: + delay *= 0.25 + ba.timer(delay, self._decrement_meteor_time, repeat=True) - # Kick off the first wave in a few seconds. - delay = 3.0 - if self._epic_mode: - delay *= 0.25 - ba.timer(delay, self._set_meteor_timer) + # Kick off the first wave in a few seconds. + delay = 3.0 + if self._epic_mode: + delay *= 0.25 + ba.timer(delay, self._set_meteor_timer) - self._timer = OnScreenTimer() - self._timer.start() + self._timer = OnScreenTimer() + self._timer.start() - # Check for immediate end (if we've only got 1 player, etc). - ba.timer(5.0, self._check_end_game) + # Check for immediate end (if we've only got 1 player, etc). + ba.timer(5.0, self._check_end_game) - def on_player_leave(self, player: Player) -> None: - # Augment default behavior. - super().on_player_leave(player) + def on_player_leave(self, player: Player) -> None: + # Augment default behavior. + super().on_player_leave(player) - # A departing player may trigger game-over. - self._check_end_game() + # A departing player may trigger game-over. + self._check_end_game() - # overriding the default character spawning.. - def spawn_player(self, player: Player) -> ba.Actor: - spaz = self.spawn_player_spaz(player) + # overriding the default character spawning.. + def spawn_player(self, player: Player) -> ba.Actor: + 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_bomb=False, enable_pickup=False - ) + # 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_bomb=False, enable_pickup=False + ) - # Also lets have them make some noise when they die. - spaz.play_big_death_sound = True - return spaz + # Also lets have them make some noise when they die. + spaz.play_big_death_sound = True + return spaz - # Various high-level game events come through this method. - def handlemessage(self, msg: Any) -> Any: - if isinstance(msg, ba.PlayerDiedMessage): + # Various high-level game events come through this method. + def handlemessage(self, msg: Any) -> Any: + if isinstance(msg, ba.PlayerDiedMessage): - # Augment standard behavior. - super().handlemessage(msg) + # Augment standard behavior. + super().handlemessage(msg) - curtime = ba.time() + curtime = ba.time() - # Record the player's moment of death. - # assert isinstance(msg.spaz.player - msg.getplayer(Player).death_time = curtime + # Record the player's moment of death. + # assert isinstance(msg.spaz.player + msg.getplayer(Player).death_time = curtime - # In co-op mode, end the game the instant everyone dies - # (more accurate looking). - # In teams/ffa, allow a one-second fudge-factor so we can - # get more draws if players die basically at the same time. - if isinstance(self.session, ba.CoopSession): - # Teams will still show up if we check now.. check in - # the next cycle. - ba.pushcall(self._check_end_game) + # In co-op mode, end the game the instant everyone dies + # (more accurate looking). + # In teams/ffa, allow a one-second fudge-factor so we can + # get more draws if players die basically at the same time. + if isinstance(self.session, ba.CoopSession): + # Teams will still show up if we check now.. check in + # the next cycle. + ba.pushcall(self._check_end_game) - # Also record this for a final setting of the clock. - self._last_player_death_time = curtime - else: - ba.timer(1.0, self._check_end_game) + # Also record this for a final setting of the clock. + self._last_player_death_time = curtime + else: + ba.timer(1.0, self._check_end_game) - else: - # Default handler: - return super().handlemessage(msg) - return None + else: + # Default handler: + return super().handlemessage(msg) + return None - def _check_end_game(self) -> None: - living_team_count = 0 - for team in self.teams: - for player in team.players: - if player.is_alive(): - living_team_count += 1 - break + def _check_end_game(self) -> None: + living_team_count = 0 + for team in self.teams: + for player in team.players: + if player.is_alive(): + living_team_count += 1 + break - # In co-op, we go till everyone is dead.. otherwise we go - # until one team remains. - if isinstance(self.session, ba.CoopSession): - if living_team_count <= 0: - self.end_game() - else: - if living_team_count <= 1: - self.end_game() + # In co-op, we go till everyone is dead.. otherwise we go + # until one team remains. + if isinstance(self.session, ba.CoopSession): + if living_team_count <= 0: + self.end_game() + else: + if living_team_count <= 1: + self.end_game() - def _set_meteor_timer(self) -> None: - ba.timer( - (1.0 + 0.2 * random.random()) * self._meteor_time, - self._drop_bomb_cluster, - ) + def _set_meteor_timer(self) -> None: + ba.timer( + (1.0 + 0.2 * random.random()) * self._meteor_time, + self._drop_bomb_cluster, + ) - def _drop_bomb_cluster(self) -> None: + def _drop_bomb_cluster(self) -> None: - # Random note: code like this is a handy way to plot out extents - # and debug things. - loc_test = False - if loc_test: - ba.newnode('locator', attrs={'position': (8, 6, -5.5)}) - ba.newnode('locator', attrs={'position': (8, 6, -2.3)}) - ba.newnode('locator', attrs={'position': (-7.3, 6, -5.5)}) - ba.newnode('locator', attrs={'position': (-7.3, 6, -2.3)}) + # Random note: code like this is a handy way to plot out extents + # and debug things. + loc_test = False + if loc_test: + ba.newnode('locator', attrs={'position': (8, 6, -5.5)}) + ba.newnode('locator', attrs={'position': (8, 6, -2.3)}) + ba.newnode('locator', attrs={'position': (-7.3, 6, -5.5)}) + ba.newnode('locator', attrs={'position': (-7.3, 6, -2.3)}) - # Drop several bombs in series. - delay = 0.0 - for _i in range(random.randrange(1, 3)): - # Drop them somewhere within our bounds with velocity pointing - # toward the opposite side. - pos = ( - -7.3 + 15.3 * random.random(), - 11, - -5.57 + 2.1 * random.random(), - ) - dropdir = -1.0 if pos[0] > 0 else 1.0 - vel = ( - (-5.0 + random.random() * 30.0) * dropdir, - random.uniform(-3.066, -4.12), - 0, - ) - ba.timer(delay, ba.Call(self._drop_bomb, pos, vel)) - delay += 0.1 - self._set_meteor_timer() + # Drop several bombs in series. + delay = 0.0 + for _i in range(random.randrange(1, 3)): + # Drop them somewhere within our bounds with velocity pointing + # toward the opposite side. + pos = ( + -7.3 + 15.3 * random.random(), + 11, + -5.57 + 2.1 * random.random(), + ) + dropdir = -1.0 if pos[0] > 0 else 1.0 + vel = ( + (-5.0 + random.random() * 30.0) * dropdir, + random.uniform(-3.066, -4.12), + 0, + ) + ba.timer(delay, ba.Call(self._drop_bomb, pos, vel)) + delay += 0.1 + self._set_meteor_timer() - def _drop_bomb( - self, position: Sequence[float], velocity: Sequence[float] - ) -> None: - if self._bomb_type == 'tnt': - bomb_type = random.choice(['tnt','tnt','tnt','tnt','impact']) - elif self._bomb_type == 'land_mine': - bomb_type = random.choice([ - 'land_mine','land_mine','land_mine','land_mine','impact']) - elif self._bomb_type == 'random': - bomb_type = random.choice([ - 'normal','ice','sticky','impact','land_mine','tnt']) - else: - bomb_type = self._bomb_type - Bomb(position=position, - velocity=velocity, - bomb_type=bomb_type).autoretain() + def _drop_bomb( + self, position: Sequence[float], velocity: Sequence[float] + ) -> None: + if self._bomb_type == 'tnt': + bomb_type = random.choice(['tnt', 'tnt', 'tnt', 'tnt', 'impact']) + elif self._bomb_type == 'land_mine': + bomb_type = random.choice([ + 'land_mine', 'land_mine', 'land_mine', 'land_mine', 'impact']) + elif self._bomb_type == 'random': + bomb_type = random.choice([ + 'normal', 'ice', 'sticky', 'impact', 'land_mine', 'tnt']) + else: + bomb_type = self._bomb_type + Bomb(position=position, + velocity=velocity, + bomb_type=bomb_type).autoretain() - def _decrement_meteor_time(self) -> None: - self._meteor_time = max(0.01, self._meteor_time * 0.9) + def _decrement_meteor_time(self) -> None: + self._meteor_time = max(0.01, self._meteor_time * 0.9) - def end_game(self) -> None: - cur_time = ba.time() - assert self._timer is not None - start_time = self._timer.getstarttime() + def end_game(self) -> None: + cur_time = ba.time() + assert self._timer is not None + start_time = self._timer.getstarttime() - # Mark death-time as now for any still-living players - # and award players points for how long they lasted. - # (these per-player scores are only meaningful in team-games) - for team in self.teams: - for player in team.players: - survived = False + # Mark death-time as now for any still-living players + # and award players points for how long they lasted. + # (these per-player scores are only meaningful in team-games) + for team in self.teams: + for player in team.players: + survived = False - # Throw an extra fudge factor in so teams that - # didn't die come out ahead of teams that did. - if player.death_time is None: - survived = True - player.death_time = cur_time + 1 + # Throw an extra fudge factor in so teams that + # didn't die come out ahead of teams that did. + if player.death_time is None: + survived = True + player.death_time = cur_time + 1 - # Award a per-player score depending on how many seconds - # they lasted (per-player scores only affect teams mode; - # everywhere else just looks at the per-team score). - score = int(player.death_time - self._timer.getstarttime()) - if survived: - score += 50 # A bit extra for survivors. - self.stats.player_scored(player, score, screenmessage=False) + # Award a per-player score depending on how many seconds + # they lasted (per-player scores only affect teams mode; + # everywhere else just looks at the per-team score). + score = int(player.death_time - self._timer.getstarttime()) + if survived: + score += 50 # A bit extra for survivors. + self.stats.player_scored(player, score, screenmessage=False) - # Stop updating our time text, and set the final time to match - # exactly when our last guy died. - self._timer.stop(endtime=self._last_player_death_time) + # Stop updating our time text, and set the final time to match + # exactly when our last guy died. + self._timer.stop(endtime=self._last_player_death_time) - # Ok now calc game results: set a score for each team and then tell - # the game to end. - results = ba.GameResults() + # Ok now calc game results: set a score for each team and then tell + # the game to end. + results = ba.GameResults() - # Remember that 'free-for-all' mode is simply a special form - # of 'teams' mode where each player gets their own team, so we can - # just always deal in teams and have all cases covered. - for team in self.teams: + # Remember that 'free-for-all' mode is simply a special form + # of 'teams' mode where each player gets their own team, so we can + # just always deal in teams and have all cases covered. + for team in self.teams: - # Set the team score to the max time survived by any player on - # that team. - longest_life = 0.0 - for player in team.players: - assert player.death_time is not None - longest_life = max(longest_life, player.death_time - start_time) + # Set the team score to the max time survived by any player on + # that team. + longest_life = 0.0 + for player in team.players: + assert player.death_time is not None + longest_life = max(longest_life, player.death_time - start_time) - # Submit the score value in milliseconds. - results.set_team_score(team, int(1000.0 * longest_life)) + # Submit the score value in milliseconds. + results.set_team_score(team, int(1000.0 * longest_life)) - self.end(results=results) + self.end(results=results) # ba_meta export plugin class MeteorShowerv2Coop(ba.Plugin): - def on_app_running(self) -> None: - ba.app.add_coop_practice_level( - ba.Level( - normal_rain, - gametype=MeteorShowerv2Game, - settings={bomb_type: 0}, - preview_texture_name='rampagePreview', - ) - ) - ba.app.add_coop_practice_level( - ba.Level( - frozen_rain, - gametype=MeteorShowerv2Game, - settings={bomb_type: 1}, - preview_texture_name='rampagePreview', - ) - ) - ba.app.add_coop_practice_level( - ba.Level( - sticky_rain, - gametype=MeteorShowerv2Game, - settings={bomb_type: 2}, - preview_texture_name='rampagePreview', - ) - ) - ba.app.add_coop_practice_level( - ba.Level( - impact_rain, - gametype=MeteorShowerv2Game, - settings={bomb_type: 3}, - preview_texture_name='rampagePreview', - ) - ) - ba.app.add_coop_practice_level( - ba.Level( - mine_rain, - gametype=MeteorShowerv2Game, - settings={bomb_type: 4}, - preview_texture_name='rampagePreview', - ) - ) - ba.app.add_coop_practice_level( - ba.Level( - tnt_rain, - gametype=MeteorShowerv2Game, - settings={bomb_type: 5}, - preview_texture_name='rampagePreview', - ) - ) - ba.app.add_coop_practice_level( - ba.Level( - random_rain, - gametype=MeteorShowerv2Game, - settings={bomb_type: 6}, - preview_texture_name='rampagePreview', - ) - ) + def on_app_running(self) -> None: + ba.app.add_coop_practice_level( + ba.Level( + normal_rain, + gametype=MeteorShowerv2Game, + settings={bomb_type: 0}, + preview_texture_name='rampagePreview', + ) + ) + ba.app.add_coop_practice_level( + ba.Level( + frozen_rain, + gametype=MeteorShowerv2Game, + settings={bomb_type: 1}, + preview_texture_name='rampagePreview', + ) + ) + ba.app.add_coop_practice_level( + ba.Level( + sticky_rain, + gametype=MeteorShowerv2Game, + settings={bomb_type: 2}, + preview_texture_name='rampagePreview', + ) + ) + ba.app.add_coop_practice_level( + ba.Level( + impact_rain, + gametype=MeteorShowerv2Game, + settings={bomb_type: 3}, + preview_texture_name='rampagePreview', + ) + ) + ba.app.add_coop_practice_level( + ba.Level( + mine_rain, + gametype=MeteorShowerv2Game, + settings={bomb_type: 4}, + preview_texture_name='rampagePreview', + ) + ) + ba.app.add_coop_practice_level( + ba.Level( + tnt_rain, + gametype=MeteorShowerv2Game, + settings={bomb_type: 5}, + preview_texture_name='rampagePreview', + ) + ) + ba.app.add_coop_practice_level( + ba.Level( + random_rain, + gametype=MeteorShowerv2Game, + settings={bomb_type: 6}, + preview_texture_name='rampagePreview', + ) + ) diff --git a/plugins/minigames/SimonSays.py b/plugins/minigames/SimonSays.py index 151963d..ad3ac27 100644 --- a/plugins/minigames/SimonSays.py +++ b/plugins/minigames/SimonSays.py @@ -1,4 +1,4 @@ -#SimonSays +# SimonSays # you had really better do what Simon says... # ba_meta require api 7 from __future__ import annotations @@ -12,6 +12,7 @@ from ba import _gameutils import ba import random + class CustomText(ba.Actor): """Text that pops up above a position to denote something special. @@ -39,7 +40,7 @@ class CustomText(ba.Actor): 'in_world': True, 'shadow': 1.0, 'flatness': 1.0, - 'h_align': 'center'},delegate=self) + 'h_align': 'center'}, delegate=self) lifespan = duration ba.animate( self.node, 'scale', { @@ -83,6 +84,7 @@ class CustomText(ba.Actor): self._combine.connectattr('output', self.node, 'color') self._die_timer = ba.Timer( lifespan, ba.WeakCall(self.handlemessage, ba.DieMessage())) + def handlemessage(self, msg: Any) -> Any: assert not self.expired if isinstance(msg, ba.DieMessage): @@ -91,11 +93,14 @@ class CustomText(ba.Actor): else: super().handlemessage(msg) + class Player(ba.Player['Team']): """Our player type for this game.""" + def __init__(self) -> None: self.score = 0 + class Team(ba.Team[Player]): """Our team type for this game.""" @@ -103,30 +108,33 @@ class Team(ba.Team[Player]): self.score = 0 # ba_meta export game + + class SimonSays(ba.TeamGameActivity[Player, Team]): name = "Simon Says" description = "You have to better do what Simon says!" + @classmethod def get_available_settings(cls, sessiontype: Type[ba.Session]) -> List[ba.Setting]: settings = [ - ba.BoolSetting("Epic Mode", default=False), - ba.BoolSetting("Enable Jumping", default=False), - ba.BoolSetting("Enable Punching", default=False), - ba.BoolSetting("Enable Picking Up", default=False), - ba.IntChoiceSetting("Timer Speed", - choices=[("Snaily", 1200), - ("Slow", 900), - ("Normal", 655), - ("Fast", 544), - ("Turbo", 460)], default=655), + ba.BoolSetting("Epic Mode", default=False), + ba.BoolSetting("Enable Jumping", default=False), + ba.BoolSetting("Enable Punching", default=False), + ba.BoolSetting("Enable Picking Up", default=False), + ba.IntChoiceSetting("Timer Speed", + choices=[("Snaily", 1200), + ("Slow", 900), + ("Normal", 655), + ("Fast", 544), + ("Turbo", 460)], default=655), - ba.FloatChoiceSetting("Text Duration", - choices=[("Slow", 2.5), - ("Normal", 1.5), - ("Mediocre", 1.0), - ("Quick", 0.75)], default=1.5)] + ba.FloatChoiceSetting("Text Duration", + choices=[("Slow", 2.5), + ("Normal", 1.5), + ("Mediocre", 1.0), + ("Quick", 0.75)], default=1.5)] return settings - + @classmethod def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]: return ["Courtyard"] @@ -149,53 +157,54 @@ class SimonSays(ba.TeamGameActivity[Player, Team]): self.counter_loop = None self.time = 5000 self._r1 = 2 - self.ct_text = ba.newnode('text',attrs={ - 'in_world': True, - 'text':'......', - 'shadow': 1.0, - 'color': (1.0,1.0,1.0), - 'flatness': 0.5, - 'position': (-5.627144702, 3.3275475, -9.572879116), - 'scale': 0.05}) - self.n1 = ba.newnode('locator',attrs={'shape':'circle','position':(-4,0,-6), - 'color':(1,0,0),'opacity':0.5, - 'draw_beauty':True,'additive':True}) - self.n2 = ba.newnode('locator',attrs={'shape':'circle','position':(0,0,-6), - 'color':(0,1,0),'opacity':0.5, - 'draw_beauty':True,'additive':True}) - self.n3 = ba.newnode('locator',attrs={'shape':'circle','position':(4,0,-6), - 'color':(0,0,1),'opacity':0.5, - 'draw_beauty':True,'additive':True}) - self.n4 = ba.newnode('locator',attrs={'shape':'circle','position':(-4,0,-2), - 'color':(1,1,0),'opacity':0.5, - 'draw_beauty':True,'additive':True}) - self.n5 = ba.newnode('locator',attrs={'shape':'circle','position':(0,0,-2), - 'color':(0,1,1),'opacity':0.5, - 'draw_beauty':True,'additive':True}) - self.n6 = ba.newnode('locator',attrs={'shape':'circle','position':(4,0,-2), - 'color':(1,0,1),'opacity':0.5, - 'draw_beauty':True,'additive':True}) - self.n7 = ba.newnode('locator',attrs={'shape':'circle','position':(-4,0,2), - 'color':(.5,.5,.5),'opacity':0.5, - 'draw_beauty':True,'additive':True}) - self.n8 = ba.newnode('locator',attrs={'shape':'circle','position':(0,0,2), - 'color':(.5,.325,0),'opacity':0.5, - 'draw_beauty':True,'additive':True}) - self.n9 = ba.newnode('locator',attrs={'shape':'circle','position':(4,0,2), - 'color':(1,1,1),'opacity':0.5, - 'draw_beauty':True,'additive':True}) - self.options = ["red", "green", "blue", "yellow", "teal", "purple", "gray", "orange", "white", "top", "bottom", "middle row", "left", "right", "center column", "outside"] + self.ct_text = ba.newnode('text', attrs={ + 'in_world': True, + 'text': '......', + 'shadow': 1.0, + 'color': (1.0, 1.0, 1.0), + 'flatness': 0.5, + 'position': (-5.627144702, 3.3275475, -9.572879116), + 'scale': 0.05}) + self.n1 = ba.newnode('locator', attrs={'shape': 'circle', 'position': (-4, 0, -6), + 'color': (1, 0, 0), 'opacity': 0.5, + 'draw_beauty': True, 'additive': True}) + self.n2 = ba.newnode('locator', attrs={'shape': 'circle', 'position': (0, 0, -6), + 'color': (0, 1, 0), 'opacity': 0.5, + 'draw_beauty': True, 'additive': True}) + self.n3 = ba.newnode('locator', attrs={'shape': 'circle', 'position': (4, 0, -6), + 'color': (0, 0, 1), 'opacity': 0.5, + 'draw_beauty': True, 'additive': True}) + self.n4 = ba.newnode('locator', attrs={'shape': 'circle', 'position': (-4, 0, -2), + 'color': (1, 1, 0), 'opacity': 0.5, + 'draw_beauty': True, 'additive': True}) + self.n5 = ba.newnode('locator', attrs={'shape': 'circle', 'position': (0, 0, -2), + 'color': (0, 1, 1), 'opacity': 0.5, + 'draw_beauty': True, 'additive': True}) + self.n6 = ba.newnode('locator', attrs={'shape': 'circle', 'position': (4, 0, -2), + 'color': (1, 0, 1), 'opacity': 0.5, + 'draw_beauty': True, 'additive': True}) + self.n7 = ba.newnode('locator', attrs={'shape': 'circle', 'position': (-4, 0, 2), + 'color': (.5, .5, .5), 'opacity': 0.5, + 'draw_beauty': True, 'additive': True}) + self.n8 = ba.newnode('locator', attrs={'shape': 'circle', 'position': (0, 0, 2), + 'color': (.5, .325, 0), 'opacity': 0.5, + 'draw_beauty': True, 'additive': True}) + self.n9 = ba.newnode('locator', attrs={'shape': 'circle', 'position': (4, 0, 2), + 'color': (1, 1, 1), 'opacity': 0.5, + 'draw_beauty': True, 'additive': True}) + self.options = ["red", "green", "blue", "yellow", "teal", "purple", "gray", "orange", + "white", "top", "bottom", "middle row", "left", "right", "center column", "outside"] self.default_music = ba.MusicType.FLAG_CATCHER - + def get_instance_description(self) -> str: return 'Follow the commands... but only when \"Simon says!"' def on_player_join(self, player: Player) -> None: if self.has_begun(): ba.screenmessage( - ba.Lstr(resource = 'playerDelayedJoinText', - subs = [('${PLAYER}', player.getname(full=True))]), - color=(0, 1, 0),) + ba.Lstr(resource='playerDelayedJoinText', + subs=[('${PLAYER}', player.getname(full=True))]), + color=(0, 1, 0),) return else: self.spawn_player(player) @@ -203,119 +212,147 @@ class SimonSays(ba.TeamGameActivity[Player, Team]): def on_begin(self) -> None: super().on_begin() s = self.settings - _gameutils.animate_array(self.n1,'size',1,{0:[0.0],0.2:[self._r1*2.0]}) - _gameutils.animate_array(self.n2,'size',1,{0:[0.0],0.2:[self._r1*2.0]}) - _gameutils.animate_array(self.n3,'size',1,{0:[0.0],0.2:[self._r1*2.0]}) - _gameutils.animate_array(self.n4,'size',1,{0:[0.0],0.2:[self._r1*2.0]}) - _gameutils.animate_array(self.n5,'size',1,{0:[0.0],0.2:[self._r1*2.0]}) - _gameutils.animate_array(self.n6,'size',1,{0:[0.0],0.2:[self._r1*2.0]}) - _gameutils.animate_array(self.n7,'size',1,{0:[0.0],0.2:[self._r1*2.0]}) - _gameutils.animate_array(self.n8,'size',1,{0:[0.0],0.2:[self._r1*2.0]}) - _gameutils.animate_array(self.n9,'size',1,{0:[0.0],0.2:[self._r1*2.0]}) + _gameutils.animate_array(self.n1, 'size', 1, {0: [0.0], 0.2: [self._r1*2.0]}) + _gameutils.animate_array(self.n2, 'size', 1, {0: [0.0], 0.2: [self._r1*2.0]}) + _gameutils.animate_array(self.n3, 'size', 1, {0: [0.0], 0.2: [self._r1*2.0]}) + _gameutils.animate_array(self.n4, 'size', 1, {0: [0.0], 0.2: [self._r1*2.0]}) + _gameutils.animate_array(self.n5, 'size', 1, {0: [0.0], 0.2: [self._r1*2.0]}) + _gameutils.animate_array(self.n6, 'size', 1, {0: [0.0], 0.2: [self._r1*2.0]}) + _gameutils.animate_array(self.n7, 'size', 1, {0: [0.0], 0.2: [self._r1*2.0]}) + _gameutils.animate_array(self.n8, 'size', 1, {0: [0.0], 0.2: [self._r1*2.0]}) + _gameutils.animate_array(self.n9, 'size', 1, {0: [0.0], 0.2: [self._r1*2.0]}) for team in self.teams: team.score = 0 for player in self.players: player.score = 0 # check for immediate end if theres only 1 player if len(self.players) == 1: - ba.timer(4000, lambda: self.check_end(),timeformat=ba.TimeFormat.MILLISECONDS) + ba.timer(4000, lambda: self.check_end(), timeformat=ba.TimeFormat.MILLISECONDS) else: ba.timer(6000, self.call_round, timeformat=ba.TimeFormat.MILLISECONDS) def spawn_player(self, player: PlayerType) -> ba.Actor: assert player - spaz = self.spawn_player_spaz(player, position=(0 + random.uniform(-3.6, 3.6), 2.9, -2 + random.uniform(-3.6, 3.6))) + spaz = self.spawn_player_spaz(player, position=( + 0 + random.uniform(-3.6, 3.6), 2.9, -2 + random.uniform(-3.6, 3.6))) assert spaz.node spaz.connect_controls_to_player( - enable_bomb=False, - enable_run = True, - enable_punch = self.settings["Enable Punching"], - enable_pickup = self.settings["Enable Picking Up"], - enable_jump = self.settings["Enable Jumping"]) + enable_bomb=False, + enable_run=True, + enable_punch=self.settings["Enable Punching"], + enable_pickup=self.settings["Enable Picking Up"], + enable_jump=self.settings["Enable Jumping"]) def call_round(self) -> None: - if self.ended: return + if self.ended: + return self.round_num += 1 self.num = random.randint(0, 15) self.numa = self.num self.simon = random.choice([True, False]) - false_prefix = random.choices(['Simon say r', 'Simon said r', 'Simon r', 'Simons says r', 'Simons r', 'R'], weights=[35,45,45,39,49,100])[0] + false_prefix = random.choices(['Simon say r', 'Simon said r', 'Simon r', + 'Simons says r', 'Simons r', 'R'], weights=[35, 45, 45, 39, 49, 100])[0] if self.numa < 9: - if not self.simon: line = false_prefix + "un to the " + self.options[self.numa] + " circle!" - else: line = "Run to the " + self.options[self.numa] + " circle!" + if not self.simon: + line = false_prefix + "un to the " + self.options[self.numa] + " circle!" + else: + line = "Run to the " + self.options[self.numa] + " circle!" elif self.numa < 15: - if not self.simon: line = false_prefix + "un to the " + self.options[self.numa] + "!" - else: line = "Run to the " + self.options[self.numa] + "!" + if not self.simon: + line = false_prefix + "un to the " + self.options[self.numa] + "!" + else: + line = "Run to the " + self.options[self.numa] + "!" else: - if not self.simon: line = false_prefix + "un outside of the circles!" - else: line = "Run outside of the circles!" - + if not self.simon: + line = false_prefix + "un outside of the circles!" + else: + line = "Run outside of the circles!" if self.simon: - line = "Simon says " + line[0].lower() + line[1:] + line = "Simon says " + line[0].lower() + line[1:] self.text = CustomText(line, - position=(0, 5, -4), - color=(0.68, 0.95, 1.12), - random_offset=0.5, - offset=(0, 0, 0), - duration=self.lifespan, - scale=2.0).autoretain() + position=(0, 5, -4), + color=(0.68, 0.95, 1.12), + random_offset=0.5, + offset=(0, 0, 0), + duration=self.lifespan, + scale=2.0).autoretain() self.now = 6 + def dummy_check(): - self.string = "...." - self.check_round() + self.string = "...." + self.check_round() + def set_counter(): - self.now = self.now - 1 - if self.now == 0: - self.string = "0" - self.ct_text.text = self.string - self.counter_loop = None - ba.timer(1, dummy_check, timeformat=ba.TimeFormat.MILLISECONDS) - else: - self.ct_text.text = str(self.now) - ba.playsound(ba.getsound('tick')) - self.counter_loop = ba.Timer(self.speed, set_counter ,timeformat=ba.TimeFormat.MILLISECONDS,repeat=True) + self.now = self.now - 1 + if self.now == 0: + self.string = "0" + self.ct_text.text = self.string + self.counter_loop = None + ba.timer(1, dummy_check, timeformat=ba.TimeFormat.MILLISECONDS) + else: + self.ct_text.text = str(self.now) + ba.playsound(ba.getsound('tick')) + self.counter_loop = ba.Timer(self.speed, set_counter, + timeformat=ba.TimeFormat.MILLISECONDS, repeat=True) def check_round(self) -> None: - if self.ended: return + if self.ended: + return for player in self.players: if player.is_alive(): - safe = True if self.options[self.numa] in self.in_circle(player.actor.node.position_center) else False + safe = True if self.options[self.numa] in self.in_circle( + player.actor.node.position_center) else False if ((self.simon and safe == False) or ((not self.simon) and safe == True)): player.team.score = self.round_num player.actor.handlemessage(ba.DieMessage()) ba.timer(1633, self.call_round, timeformat=ba.TimeFormat.MILLISECONDS) - def in_circle(self, pos) -> None: circles = [] x = pos[0] z = pos[2] - if (x + 4) ** 2 + (z + 6) ** 2 < 4: circles.append("red") - elif (x) ** 2 + (z + 6) ** 2 < 4: circles.append("green") - elif (x - 4) ** 2 + (z + 6) ** 2 < 4: circles.append("blue") - elif (x + 4) ** 2 + (z + 2) ** 2 < 4: circles.append("yellow") - elif (x) ** 2 + (z + 2) ** 2 < 4: circles.append("teal") - elif (x - 4) ** 2 + (z + 2) ** 2 < 4: circles.append("purple") - elif (x + 4) ** 2 + (z - 2) ** 2 < 4: circles.append("gray") - elif (x) ** 2 + (z - 2) ** 2 < 4: circles.append("orange") - elif (x - 4) ** 2 + (z - 2) ** 2 < 4: circles.append("white") - else: circles.append("outside") - if x < -2: circles.append("left") - if x > 2: circles.append("right") - if x > -2 and x < 2: circles.append("center column") - if z > 0: circles.append("bottom") - if z < -4: circles.append("top") - if z < 0 and z > -4: circles.append("middle row") + if (x + 4) ** 2 + (z + 6) ** 2 < 4: + circles.append("red") + elif (x) ** 2 + (z + 6) ** 2 < 4: + circles.append("green") + elif (x - 4) ** 2 + (z + 6) ** 2 < 4: + circles.append("blue") + elif (x + 4) ** 2 + (z + 2) ** 2 < 4: + circles.append("yellow") + elif (x) ** 2 + (z + 2) ** 2 < 4: + circles.append("teal") + elif (x - 4) ** 2 + (z + 2) ** 2 < 4: + circles.append("purple") + elif (x + 4) ** 2 + (z - 2) ** 2 < 4: + circles.append("gray") + elif (x) ** 2 + (z - 2) ** 2 < 4: + circles.append("orange") + elif (x - 4) ** 2 + (z - 2) ** 2 < 4: + circles.append("white") + else: + circles.append("outside") + if x < -2: + circles.append("left") + if x > 2: + circles.append("right") + if x > -2 and x < 2: + circles.append("center column") + if z > 0: + circles.append("bottom") + if z < -4: + circles.append("top") + if z < 0 and z > -4: + circles.append("middle row") return circles def handlemessage(self, msg) -> None: if isinstance(msg, ba.PlayerDiedMessage): - self.check_end() + self.check_end() else: - super().handlemessage(msg) + super().handlemessage(msg) def end_game(self) -> None: self.ended = True @@ -327,7 +364,7 @@ class SimonSays(ba.TeamGameActivity[Player, Team]): def check_end(self) -> None: i = 0 for player in self.players: - if player.is_alive(): - i += 1 - if i <= 2 : - ba.timer(0.6, lambda: self.end_game()) + if player.is_alive(): + i += 1 + if i <= 2: + ba.timer(0.6, lambda: self.end_game()) diff --git a/plugins/minigames/SquidRace.py b/plugins/minigames/SquidRace.py index c13276a..d8cd54b 100644 --- a/plugins/minigames/SquidRace.py +++ b/plugins/minigames/SquidRace.py @@ -30,6 +30,7 @@ class NewBlast(Blast): else: return super().handlemessage(msg) + @dataclass class RaceMine: """Holds info about a mine on the track.""" @@ -223,7 +224,7 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]): ('modify_part_collision', 'physical', False), ('call', 'at_connect', self._handle_race_point_collide), - )) + )) for rpt in pts: self._regions.append(RaceRegion(rpt, len(self._regions))) @@ -271,7 +272,7 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]): translate=('statements', 'Killing ${NAME} for' ' skipping part of the track!'), subs=[('${NAME}', player.getname(full=True))]), - color=(1, 0, 0)) + color=(1, 0, 0)) else: # If this player is in first, note that this is the # front-most race-point. @@ -397,7 +398,7 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]): '${TEAM} is disqualified because ${PLAYER} left'), subs=[('${TEAM}', player.team.name), ('${PLAYER}', player.getname(full=True))]), - color=(1, 1, 0)) + color=(1, 1, 0)) player.team.finished = True player.team.time = None player.team.lap = 0 @@ -535,7 +536,7 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]): self._squidgame_countdown() def _squidgame_countdown(self) -> None: - self._countdown_timer = 80 * self._laps # 80 + self._countdown_timer = 80 * self._laps # 80 ba.newnode( 'image', attrs={ @@ -552,7 +553,7 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]): 'color': (1.0, 0.0, 0.0), 'attach': 'topCenter', 'position': (-220, -38), - 'scale':(155, 65), + 'scale': (155, 65), 'texture': ba.gettexture('uiAtlas'), 'model_transparent': ba.getmodel('meterTransparent')}) self._sgcountdown_text = ba.newnode( @@ -615,9 +616,9 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]): self._tick_timer = ba.timer(1.0, do_ticks, repeat=True) def _start_squid_game(self) -> None: - easy = [4.5,5,5.5,6] - normal = [4,4.5,5] - hard = [3,3.5,4] + easy = [4.5, 5, 5.5, 6] + normal = [4, 4.5, 5] + hard = [3, 3.5, 4] random_number = random.choice( hard if self._sq_mode == 'Hard' else normal if self._sq_mode == 'Normal' else easy) @@ -665,18 +666,18 @@ class SquidRaceGame(ba.TeamGameActivity[Player, Team]): posy = float("%.1f" % player.customdata['position'][2]) posx_list = [ - round(posx,1),round(posx+0.1,1),round(posx+0.2,1), - round(posx-0.1,1),round(posx-0.2,1)] + round(posx, 1), round(posx+0.1, 1), round(posx+0.2, 1), + round(posx-0.1, 1), round(posx-0.2, 1)] current_posx = float("%.1f" % player.actor.node.position[0]) posz_list = [ - round(posz,1),round(posz+0.1,1),round(posz+0.2,1), - round(posz-0.1,1),round(posz-0.2,1)] + round(posz, 1), round(posz+0.1, 1), round(posz+0.2, 1), + round(posz-0.1, 1), round(posz-0.2, 1)] current_posz = float("%.1f" % player.actor.node.position[1]) posy_list = [ - round(posy,1),round(posy+0.1,1),round(posy+0.2,1), - round(posy-0.1,1),round(posy-0.2,1)] + round(posy, 1), round(posy+0.1, 1), round(posy+0.2, 1), + round(posy-0.1, 1), round(posy-0.2, 1)] current_posy = float("%.1f" % player.actor.node.position[2]) if not (current_posx in posx_list) or not ( diff --git a/plugins/minigames/ZombieHorde.py b/plugins/minigames/ZombieHorde.py index 673c9f5..afb48f3 100644 --- a/plugins/minigames/ZombieHorde.py +++ b/plugins/minigames/ZombieHorde.py @@ -65,7 +65,7 @@ class PlayerSpaz_Zom(PlayerSpaz): if not playa is None: if opposingnode._source_player.lives > 0: return True - except Exception: + except Exception: pass if (opposingnode.getnodetype() == 'spaz' @@ -82,6 +82,7 @@ class PlayerSpaz_Zom(PlayerSpaz): return super().handlemessage(m) return None + class PlayerZombie(PlayerSpaz): def handlemessage(self, m: Any) -> Any: if isinstance(m, ba.HitMessage): @@ -101,6 +102,7 @@ class PlayerZombie(PlayerSpaz): else: super().handlemessage(m) + class zBotSet(SpazBotSet): def start_moving(self) -> None: """Start processing bot AI updates so they start doing their thing.""" @@ -139,6 +141,7 @@ class zBotSet(SpazBotSet): bot.set_player_points(player_pts) bot.update_ai() + class Team(ba.Team[Player]): """Our team type for this game.""" @@ -242,8 +245,8 @@ class ZombieHorde(ba.TeamGameActivity[Player, Team]): activity = ba.getactivity() my_factory = SpazFactory.get() - appears = ['Kronk','Zoe','Pixel','Agent Johnson', - 'Bones','Frosty','Kronk2'] + appears = ['Kronk', 'Zoe', 'Pixel', 'Agent Johnson', + 'Bones', 'Frosty', 'Kronk2'] myAppear = copy.copy(ba.app.spaz_appearances['Kronk']) myAppear.name = 'Kronk2' ba.app.spaz_appearances['Kronk2'] = myAppear @@ -252,7 +255,7 @@ class ZombieHorde(ba.TeamGameActivity[Player, Team]): med = my_factory.spaz_media med['Kronk2']['head_model'] = med['Zoe']['head_model'] med['Kronk2']['color_texture'] = med['Agent Johnson']['color_texture'] - med['Kronk2']['color_mask_texture']=med['Pixel']['color_mask_texture'] + med['Kronk2']['color_mask_texture'] = med['Pixel']['color_mask_texture'] med['Kronk2']['torso_model'] = med['Bones']['torso_model'] med['Kronk2']['pelvis_model'] = med['Pixel']['pelvis_model'] med['Kronk2']['upper_arm_model'] = med['Frosty']['upper_arm_model'] @@ -351,9 +354,9 @@ class ZombieHorde(ba.TeamGameActivity[Player, Team]): self._bots = zBotSet() - #Set colors and character for ToughGuyBot to be zombie - setattr(BrawlerBot, 'color', (0.4,0.1,0.05)) - setattr(BrawlerBot, 'highlight', (0.2,0.4,0.3)) + # Set colors and character for ToughGuyBot to be zombie + setattr(BrawlerBot, 'color', (0.4, 0.1, 0.05)) + setattr(BrawlerBot, 'highlight', (0.2, 0.4, 0.3)) setattr(BrawlerBot, 'character', 'Kronk2') # start some timers to spawn bots thePt = self.map.get_ffa_start_position(self.players) @@ -434,7 +437,6 @@ class ZombieHorde(ba.TeamGameActivity[Player, Team]): icon.update_for_lives() xval += x_offs - def _get_spawn_point(self, player: Player) -> ba.Vec3 | None: del player # Unused. @@ -612,7 +614,7 @@ class ZombieHorde(ba.TeamGameActivity[Player, Team]): try: pos = player.actor.node.position except Exception as e: - print('EXC getting player pos in bsElim',e) + print('EXC getting player pos in bsElim', e) return if player.lives > 0: popuptext.PopupText('x' + str(player.lives - 1), @@ -692,7 +694,8 @@ class ZombieHorde(ba.TeamGameActivity[Player, Team]): elif isinstance(msg, SpazBotDiedMessage): self._onSpazBotDied(msg) - super().handlemessage(msg)#bs.PopupText("died",position=self._position,color=popupColor,scale=popupScale).autoRetain() + # bs.PopupText("died",position=self._position,color=popupColor,scale=popupScale).autoRetain() + super().handlemessage(msg) else: super().handlemessage(msg) @@ -734,15 +737,15 @@ class ZombieHorde(ba.TeamGameActivity[Player, Team]): self._round_end_timer = ba.Timer(0.5, self.end_game) def spawn_zombie(self) -> None: - #We need a Z height... + # We need a Z height... thePt = list(self.get_random_point_in_play()) thePt2 = self.map.get_ffa_start_position(self.players) thePt[1] = thePt2[1] ba.timer(0.1, ba.Call( self._bots.spawn_bot, BrawlerBot, pos=thePt, spawn_time=1.0)) - def _onSpazBotDied(self,DeathMsg) -> None: - #Just in case we are over max... + def _onSpazBotDied(self, DeathMsg) -> None: + # Just in case we are over max... if len(self._bots.get_living_bots()) < self._max_zombies: self.zombieQ += 1 @@ -762,37 +765,38 @@ class ZombieHorde(ba.TeamGameActivity[Player, Team]): myMap = self.map.getname() if myMap == 'Doom Shroom': while True: - x = random.uniform(-1.0,1.0) - y = random.uniform(-1.0,1.0) - if x*x+y*y < 1.0: break - return ((8.0*x,8.0,-3.5+5.0*y)) + x = random.uniform(-1.0, 1.0) + y = random.uniform(-1.0, 1.0) + if x*x+y*y < 1.0: + break + return ((8.0*x, 8.0, -3.5+5.0*y)) elif myMap == 'Rampage': - x = random.uniform(-6.0,7.0) - y = random.uniform(-6.0,-2.5) + x = random.uniform(-6.0, 7.0) + y = random.uniform(-6.0, -2.5) return ((x, 8.0, y)) elif myMap == 'Hockey Stadium': - x = random.uniform(-11.5,11.5) - y = random.uniform(-4.5,4.5) + x = random.uniform(-11.5, 11.5) + y = random.uniform(-4.5, 4.5) return ((x, 5.0, y)) elif myMap == 'Courtyard': - x = random.uniform(-4.3,4.3) - y = random.uniform(-4.4,0.3) + x = random.uniform(-4.3, 4.3) + y = random.uniform(-4.4, 0.3) return ((x, 8.0, y)) elif myMap == 'Crag Castle': - x = random.uniform(-6.7,8.0) - y = random.uniform(-6.0,0.0) + x = random.uniform(-6.7, 8.0) + y = random.uniform(-6.0, 0.0) return ((x, 12.0, y)) elif myMap == 'Big G': - x = random.uniform(-8.7,8.0) - y = random.uniform(-7.5,6.5) + x = random.uniform(-8.7, 8.0) + y = random.uniform(-7.5, 6.5) return ((x, 8.0, y)) elif myMap == 'Football Stadium': - x = random.uniform(-12.5,12.5) - y = random.uniform(-5.0,5.5) + x = random.uniform(-12.5, 12.5) + y = random.uniform(-5.0, 5.5) return ((x, 8.0, y)) else: - x = random.uniform(-5.0,5.0) - y = random.uniform(-6.0,0.0) + x = random.uniform(-5.0, 5.0) + y = random.uniform(-6.0, 0.0) return ((x, 8.0, y)) def _update_scoreboard(self) -> None: From 9bf4def90bec16d9c1a3fa8724451e6662636186 Mon Sep 17 00:00:00 2001 From: Loup <90267658+Loup-Garou911XD@users.noreply.github.com> Date: Thu, 3 Nov 2022 23:02:32 +0530 Subject: [PATCH 12/55] Added SimonSays, SquidRace, BasketBomb, Boxing, MeteorShower, ZombieHorde --- plugins/minigames.json | 107 +++++++++++++++++++++++++++++++++-------- 1 file changed, 86 insertions(+), 21 deletions(-) diff --git a/plugins/minigames.json b/plugins/minigames.json index 989ca69..dda48e2 100644 --- a/plugins/minigames.json +++ b/plugins/minigames.json @@ -2,7 +2,91 @@ "name": "Minigames", "description": "Minigames", "plugins_base_url": "http://github.com/bombsquad-community/plugin-manager/{content_type}/{tag}/plugins/minigames", - "plugins": { + "plugins": { + "SimonSays": { + "description": "You better do what Simon says", + "external_url": "", + "authors": [ + { + "name": "Unknown", + "email": null, + "discord": null + } + ], + "versions": { + "1.0.0": null + } + }, + "SquidRace": { + "description": "Race inspired by the squid games", + "external_url": "https://youtube.com/c/JoseANG3LYT", + "authors": [ + { + "name": "JoseAng3l", + "email": null, + "discord": "! JoseANG3L#0268" + } + ], + "versions": { + "1.0.0": null + } + }, + "ZombieHorde": { + "description": "Fight or defend against horde of zombies", + "external_url": "https://youtube.com/c/JoseANG3LYT", + "authors": [ + { + "name": "JoseAng3l", + "email": null, + "discord": "! JoseANG3L#0268" + } + ], + "versions": { + "1.0.0": null + } + }, + "MeteorShower": { + "description": "MeteorShower with many different bombs", + "external_url": "https://youtube.com/c/JoseANG3LYT", + "authors": [ + { + "name": "JoseAng3l", + "email": null, + "discord": "! JoseANG3L#0268" + } + ], + "versions": { + "1.0.0": null + } + }, + "Boxing": { + "description": "Simple boxing minigame", + "external_url": "https://youtube.com/c/JoseANG3LYT", + "authors": [ + { + "name": "JoseAng3l", + "email": null, + "discord": "! JoseANG3L#0268" + } + ], + "versions": { + "1.0.0": null + } + }, + "BasketBomb": { + "description": "Score all the baskets and be the MVP.", + "external_url": "", + "authors": [ + { + "name": "Unknown", + "email": null, + "discord": null + } + ], + "versions": { + "1.0.0": null + } + }, "ultimate_last_stand": { "description": "Bring Last Stand minigame into team fight and FFA.", "external_url": "", @@ -97,25 +181,6 @@ "md5sum": "c84b7f415de5d3e9189ee73fc0e3ce93" } } - }, - "soccer": { - "description": "Shoot the ball in left or right edge of the map to score", - "external_url": "", - "authors": [ - { - "name": "Stary_Agent", - "email": "", - "discord": "" - } - ], - "versions": { - "1.0.0": { - "api_version": 7, - "commit_sha": "e59073b", - "released_on": "02-11-2022", - "md5sum": "ceb7ac417c85396722fa9f7fee3cfc01" - } - } } } -} \ No newline at end of file +} From 0359fe13a10dbd3e4b8495ed163e6b55b555ca1c Mon Sep 17 00:00:00 2001 From: Loup <90267658+Loup-Garou911XD@users.noreply.github.com> Date: Thu, 3 Nov 2022 23:06:11 +0530 Subject: [PATCH 13/55] Update mood_light.py --- plugins/utilities/mood_light.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/utilities/mood_light.py b/plugins/utilities/mood_light.py index 733adef..c29425d 100644 --- a/plugins/utilities/mood_light.py +++ b/plugins/utilities/mood_light.py @@ -278,6 +278,9 @@ class moodlight(ba.Plugin): def on_app_running(self): _ba.show_progress_bar() + + def on_plugin_manager_prompt(self): + SettingWindow() def has_settings_ui(self): return True From b1e668ad6168f9289af17d4e6e87a513790d6cdb Mon Sep 17 00:00:00 2001 From: Loup-Garou911XD Date: Thu, 3 Nov 2022 17:36:35 +0000 Subject: [PATCH 14/55] [ci] auto-format --- plugins/utilities/mood_light.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/utilities/mood_light.py b/plugins/utilities/mood_light.py index c29425d..dabd85e 100644 --- a/plugins/utilities/mood_light.py +++ b/plugins/utilities/mood_light.py @@ -278,7 +278,7 @@ class moodlight(ba.Plugin): def on_app_running(self): _ba.show_progress_bar() - + def on_plugin_manager_prompt(self): SettingWindow() From 7d3d1170fa4bdff77bf21c288ee621522ec94192 Mon Sep 17 00:00:00 2001 From: Loup <90267658+Loup-Garou911XD@users.noreply.github.com> Date: Thu, 3 Nov 2022 23:11:55 +0530 Subject: [PATCH 15/55] Rename QuickCustonGame.py to QuickCustomGame.py Did a oopsies --- plugins/utilities/{QuickCustonGame.py => QuickCustomGame.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename plugins/utilities/{QuickCustonGame.py => QuickCustomGame.py} (100%) diff --git a/plugins/utilities/QuickCustonGame.py b/plugins/utilities/QuickCustomGame.py similarity index 100% rename from plugins/utilities/QuickCustonGame.py rename to plugins/utilities/QuickCustomGame.py From cbca3a67edb7472412b675711a5fc1b39cb5c330 Mon Sep 17 00:00:00 2001 From: Loup-Garou911XD Date: Thu, 3 Nov 2022 17:42:19 +0000 Subject: [PATCH 16/55] [ci] apply-version-metadata --- plugins/minigames.json | 80 +++++++++++++++++++++++++++++------------- plugins/utilities.json | 55 +++++++++++++++++++++-------- 2 files changed, 95 insertions(+), 40 deletions(-) diff --git a/plugins/minigames.json b/plugins/minigames.json index dda48e2..d1897cc 100644 --- a/plugins/minigames.json +++ b/plugins/minigames.json @@ -2,75 +2,100 @@ "name": "Minigames", "description": "Minigames", "plugins_base_url": "http://github.com/bombsquad-community/plugin-manager/{content_type}/{tag}/plugins/minigames", - "plugins": { + "plugins": { "SimonSays": { - "description": "You better do what Simon says", + "description": "You better do what Simon says", "external_url": "", "authors": [ { "name": "Unknown", "email": null, - "discord": null + "discord": null } ], - "versions": { - "1.0.0": null + "versions": { + "1.0.0": { + "api_version": 7, + "commit_sha": "7d3d117", + "released_on": "03-11-2022", + "md5sum": "def39482b339095a7affb574af829ea0" + } } }, "SquidRace": { - "description": "Race inspired by the squid games", + "description": "Race inspired by the squid games", "external_url": "https://youtube.com/c/JoseANG3LYT", "authors": [ { "name": "JoseAng3l", "email": null, - "discord": "! JoseANG3L#0268" + "discord": "! JoseANG3L#0268" } ], - "versions": { - "1.0.0": null + "versions": { + "1.0.0": { + "api_version": 7, + "commit_sha": "7d3d117", + "released_on": "03-11-2022", + "md5sum": "7ec43481e6b35b4da4f6425977ee0004" + } } }, "ZombieHorde": { - "description": "Fight or defend against horde of zombies", + "description": "Fight or defend against horde of zombies", "external_url": "https://youtube.com/c/JoseANG3LYT", "authors": [ { "name": "JoseAng3l", "email": null, - "discord": "! JoseANG3L#0268" + "discord": "! JoseANG3L#0268" } ], - "versions": { - "1.0.0": null + "versions": { + "1.0.0": { + "api_version": 7, + "commit_sha": "7d3d117", + "released_on": "03-11-2022", + "md5sum": "671e7b98a9d3eb0aeb7e47448db25af9" + } } - }, + }, "MeteorShower": { - "description": "MeteorShower with many different bombs", + "description": "MeteorShower with many different bombs", "external_url": "https://youtube.com/c/JoseANG3LYT", "authors": [ { "name": "JoseAng3l", "email": null, - "discord": "! JoseANG3L#0268" + "discord": "! JoseANG3L#0268" } ], - "versions": { - "1.0.0": null + "versions": { + "1.0.0": { + "api_version": 7, + "commit_sha": "7d3d117", + "released_on": "03-11-2022", + "md5sum": "1ce8c1a3f3ec240af39b7a73375e7891" + } } }, "Boxing": { - "description": "Simple boxing minigame", + "description": "Simple boxing minigame", "external_url": "https://youtube.com/c/JoseANG3LYT", "authors": [ { "name": "JoseAng3l", "email": null, - "discord": "! JoseANG3L#0268" + "discord": "! JoseANG3L#0268" } ], - "versions": { - "1.0.0": null + "versions": { + "1.0.0": { + "api_version": 7, + "commit_sha": "7d3d117", + "released_on": "03-11-2022", + "md5sum": "c1b615df09886ba05622c4e8b4f6be40" + } } }, "BasketBomb": { @@ -83,8 +108,13 @@ "discord": null } ], - "versions": { - "1.0.0": null + "versions": { + "1.0.0": { + "api_version": 7, + "commit_sha": "7d3d117", + "released_on": "03-11-2022", + "md5sum": "7ec87edbdd5183ec4b2daffad0019820" + } } }, "ultimate_last_stand": { @@ -183,4 +213,4 @@ } } } -} +} \ No newline at end of file diff --git a/plugins/utilities.json b/plugins/utilities.json index f62619e..1bfdc3b 100644 --- a/plugins/utilities.json +++ b/plugins/utilities.json @@ -4,31 +4,41 @@ "plugins_base_url": "http://github.com/bombsquad-community/plugin-manager/{content_type}/{tag}/plugins/utilities", "plugins": { "CustomDeath": { - "description": "Characters turn to Bones after death", + "description": "Characters turn to Bones after death", "external_url": "https://youtube.com/c/JoseANG3LYT", "authors": [ { "name": "JoseAng3l", "email": null, - "discord": "! JoseANG3L#0268" + "discord": "! JoseANG3L#0268" } ], - "versions": { - "1.0.0": null + "versions": { + "1.0.0": { + "api_version": 7, + "commit_sha": "7d3d117", + "released_on": "03-11-2022", + "md5sum": "7b1941512532321eec18140087569215" + } } }, "MaxPlayers": { - "description": "Increase the max player limit of 8 players", + "description": "Increase the max player limit of 8 players", "external_url": "https://youtube.com/c/JoseANG3LYT", "authors": [ { "name": "JoseAng3l", "email": null, - "discord": "! JoseANG3L#0268" + "discord": "! JoseANG3L#0268" } ], - "versions": { - "1.0.0": null + "versions": { + "1.0.0": { + "api_version": 7, + "commit_sha": "7d3d117", + "released_on": "03-11-2022", + "md5sum": "f5e129f009e9732b3179c7edaf75478e" + } } }, "QuickCustomGame": { @@ -41,8 +51,13 @@ "discord": "! JoseANG3L#0268" } ], - "versions": { - "1.0.0": null + "versions": { + "1.0.0": { + "api_version": 7, + "commit_sha": "7d3d117", + "released_on": "03-11-2022", + "md5sum": "b691e35afb17cd3b5f6fe21c0194567d" + } } }, "RandomColors": { @@ -55,8 +70,13 @@ "discord": "! JoseANG3L#0268" } ], - "versions": { - "1.0.0": null + "versions": { + "1.0.0": { + "api_version": 7, + "commit_sha": "7d3d117", + "released_on": "03-11-2022", + "md5sum": "0c351a0aebed77c3771053cde0c18d7b" + } } }, "chat_cmd": { @@ -74,8 +94,13 @@ "discord": null } ], - "versions": { - "1.0.0": null + "versions": { + "1.0.0": { + "api_version": 7, + "commit_sha": "7d3d117", + "released_on": "03-11-2022", + "md5sum": "c84d9a1c9e63e77949134020e1f11834" + } } }, "mood_light": { @@ -379,4 +404,4 @@ } } } -} +} \ No newline at end of file From 8ea35e72ee445dc11b6aec0a9d1db3b3157cc57d Mon Sep 17 00:00:00 2001 From: Loup <90267658+Loup-Garou911XD@users.noreply.github.com> Date: Sat, 5 Nov 2022 03:44:32 +0530 Subject: [PATCH 17/55] Fixed "Restart level" sending when not playing --- plugins/utilities/mood_light.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/plugins/utilities/mood_light.py b/plugins/utilities/mood_light.py index dabd85e..91eb528 100644 --- a/plugins/utilities/mood_light.py +++ b/plugins/utilities/mood_light.py @@ -17,12 +17,12 @@ type ml in chat or use plugin manager to open settings""" def Print(*args): - out = " ".join(args) + out = " ".join(str(args)) ba.screenmessage(out) def cprint(*args): - out = "\n".join(args) + out = "\n".join(str(args)) _ba.chatmessage(out) @@ -237,7 +237,9 @@ class SettingWindow(ba.Window): loop = True label = "DISABLE" color = (1, 0, 0) - Print("Restart level to enable") + in_game = not isinstance(_ba.get_foreground_host_session(), mainmenu.MainMenuSession) + if in_game: + Print("Restart level to apply") ba.app.config["moodlightEnabled"] = loop ba.app.config.commit() ba.buttonwidget(edit=self.enable_button, label=label, color=color) From 490b857e80d5ca981f79356da1515919e440bce7 Mon Sep 17 00:00:00 2001 From: Loup <90267658+Loup-Garou911XD@users.noreply.github.com> Date: Sat, 5 Nov 2022 03:52:08 +0530 Subject: [PATCH 18/55] Bumped version --- plugins/utilities.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/utilities.json b/plugins/utilities.json index 1bfdc3b..123a780 100644 --- a/plugins/utilities.json +++ b/plugins/utilities.json @@ -114,6 +114,7 @@ } ], "versions": { + "1.2.2": null, "1.2.1": { "api_version": 7, "commit_sha": "1a56b57", @@ -404,4 +405,4 @@ } } } -} \ No newline at end of file +} From 87f0e52decaf6a5852ee545b8efad5151da36860 Mon Sep 17 00:00:00 2001 From: Loup-Garou911XD Date: Fri, 4 Nov 2022 22:22:32 +0000 Subject: [PATCH 19/55] [ci] apply-version-metadata --- plugins/utilities.json | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/plugins/utilities.json b/plugins/utilities.json index 123a780..c146ec6 100644 --- a/plugins/utilities.json +++ b/plugins/utilities.json @@ -114,7 +114,12 @@ } ], "versions": { - "1.2.2": null, + "1.2.2": { + "api_version": 7, + "commit_sha": "490b857", + "released_on": "04-11-2022", + "md5sum": "cb367f877d6360a0e41941b1d0396a9b" + }, "1.2.1": { "api_version": 7, "commit_sha": "1a56b57", @@ -405,4 +410,4 @@ } } } -} +} \ No newline at end of file From 9c35e39a707c01cc93c5a9cb69358ea988a5344e Mon Sep 17 00:00:00 2001 From: Loup <90267658+Loup-Garou911XD@users.noreply.github.com> Date: Sat, 5 Nov 2022 16:40:42 +0530 Subject: [PATCH 20/55] Fixed Print and cprint function --- plugins/utilities/mood_light.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/plugins/utilities/mood_light.py b/plugins/utilities/mood_light.py index 91eb528..f1a8304 100644 --- a/plugins/utilities/mood_light.py +++ b/plugins/utilities/mood_light.py @@ -17,12 +17,18 @@ type ml in chat or use plugin manager to open settings""" def Print(*args): - out = " ".join(str(args)) + out="" + for arg in args: + a=str(arg) + out += a ba.screenmessage(out) def cprint(*args): - out = "\n".join(str(args)) + out="" + for arg in args: + a=str(arg) + out += a _ba.chatmessage(out) From 3a901be3f3eae63b4f0104c1347c22e08265b381 Mon Sep 17 00:00:00 2001 From: Loup-Garou911XD Date: Sat, 5 Nov 2022 11:11:05 +0000 Subject: [PATCH 21/55] [ci] auto-format --- plugins/utilities/mood_light.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/utilities/mood_light.py b/plugins/utilities/mood_light.py index f1a8304..225df54 100644 --- a/plugins/utilities/mood_light.py +++ b/plugins/utilities/mood_light.py @@ -17,17 +17,17 @@ type ml in chat or use plugin manager to open settings""" def Print(*args): - out="" + out = "" for arg in args: - a=str(arg) + a = str(arg) out += a ba.screenmessage(out) def cprint(*args): - out="" + out = "" for arg in args: - a=str(arg) + a = str(arg) out += a _ba.chatmessage(out) From 4aa9052094a9fafbc7ff65a529649fe74b5bb172 Mon Sep 17 00:00:00 2001 From: Loup <90267658+Loup-Garou911XD@users.noreply.github.com> Date: Sat, 5 Nov 2022 18:34:33 +0530 Subject: [PATCH 22/55] Readded accidentally removed data --- plugins/minigames.json | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/plugins/minigames.json b/plugins/minigames.json index d1897cc..a86f4dd 100644 --- a/plugins/minigames.json +++ b/plugins/minigames.json @@ -3,6 +3,25 @@ "description": "Minigames", "plugins_base_url": "http://github.com/bombsquad-community/plugin-manager/{content_type}/{tag}/plugins/minigames", "plugins": { + "soccer": { + "description": "Shoot the ball in left or right edge of the map to score", + "external_url": "", + "authors": [ + { + "name": "Stary_Agent", + "email": "", + "discord": "" + } + ], + "versions": { + "1.0.0": { + "api_version": 7, + "commit_sha": "e59073b", + "released_on": "02-11-2022", + "md5sum": "ceb7ac417c85396722fa9f7fee3cfc01" + } + } + }, "SimonSays": { "description": "You better do what Simon says", "external_url": "", @@ -213,4 +232,4 @@ } } } -} \ No newline at end of file +} From d6def17e7ecadc06ddf263229fd34aea1f10f4a5 Mon Sep 17 00:00:00 2001 From: Loup-Garou911XD Date: Sat, 5 Nov 2022 13:04:53 +0000 Subject: [PATCH 23/55] [ci] apply-version-metadata --- plugins/minigames.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/minigames.json b/plugins/minigames.json index a86f4dd..7b01656 100644 --- a/plugins/minigames.json +++ b/plugins/minigames.json @@ -232,4 +232,4 @@ } } } -} +} \ No newline at end of file From d64237a5cd2e7373c5f2487d277fd4dc177349f3 Mon Sep 17 00:00:00 2001 From: Loup <90267658+Loup-Garou911XD@users.noreply.github.com> Date: Mon, 7 Nov 2022 00:15:03 +0530 Subject: [PATCH 24/55] Add files via upload --- plugins/utilities/custom_death.py | 40 +++ plugins/utilities/max_players.py | 368 ++++++++++++++++++++++++ plugins/utilities/quick_custom_game.py | 381 +++++++++++++++++++++++++ plugins/utilities/random_colors.py | 48 ++++ 4 files changed, 837 insertions(+) create mode 100644 plugins/utilities/custom_death.py create mode 100644 plugins/utilities/max_players.py create mode 100644 plugins/utilities/quick_custom_game.py create mode 100644 plugins/utilities/random_colors.py diff --git a/plugins/utilities/custom_death.py b/plugins/utilities/custom_death.py new file mode 100644 index 0000000..b3730e1 --- /dev/null +++ b/plugins/utilities/custom_death.py @@ -0,0 +1,40 @@ +# ba_meta require api 7 +# (see https://ballistica.net/wiki/meta-tag-system) + +from __future__ import annotations + +from typing import TYPE_CHECKING + +import ba +from bastd.actor.spaz import Spaz + +if TYPE_CHECKING: + from typing import Any + + +Spaz.oldhandlemessage = Spaz.handlemessage + + +def handlemessage(self, msg: Any) -> Any: + if isinstance(msg, ba.DieMessage): + if self.node: + self.node.color_texture = ba.gettexture('bonesColor') + self.node.color_mask_texture = ba.gettexture('bonesColorMask') + self.node.head_model = ba.getmodel('bonesHead') + self.node.torso_model = ba.getmodel('bonesTorso') + self.node.pelvis_model = ba.getmodel('bonesPelvis') + self.node.upper_arm_model = ba.getmodel('bonesUpperArm') + self.node.forearm_model = ba.getmodel('bonesForeArm') + self.node.hand_model = ba.getmodel('bonesHand') + self.node.upper_leg_model = ba.getmodel('bonesUpperLeg') + self.node.lower_leg_model = ba.getmodel('bonesLowerLeg') + self.node.toes_model = ba.getmodel('bonesToes') + self.node.style = 'bones' + self.oldhandlemessage(msg) + else: + return self.oldhandlemessage(msg) + + +# ba_meta export plugin +class CustomDeath(ba.Plugin): + Spaz.handlemessage = handlemessage diff --git a/plugins/utilities/max_players.py b/plugins/utilities/max_players.py new file mode 100644 index 0000000..6d6257a --- /dev/null +++ b/plugins/utilities/max_players.py @@ -0,0 +1,368 @@ +"""===========MAX_PLAYERS===========""" + +# ba_meta require api 7 +# (see https://ballistica.net/wiki/meta-tag-system) + +from __future__ import annotations +from typing import TYPE_CHECKING + +import ba +import _ba +from ba._session import Session +from ba._coopsession import CoopSession, TEAM_COLORS, TEAM_NAMES +from ba._multiteamsession import MultiTeamSession +from bastd.ui.gather import GatherWindow +from bastd.ui.popup import PopupWindow + +if TYPE_CHECKING: + from typing import List, Any, Optional, Sequence + + +cfg = ba.app.config +cmp = {'coop_max_players': 4, + 'teams_max_players': 8, + 'ffa_max_players': 8} + +lang = ba.app.lang.language +if lang == 'Spanish': + title_text = 'Máximo de Jugadores' + title_short_text = 'Jugadores' + coop_text = 'Cooperativo' + teams_text = 'Equipos' + ffa_text = 'Todos Contra Todos' +else: + title_text = 'Max Players' + title_short_text = 'Players' + coop_text = 'Co-op' + teams_text = 'Teams' + ffa_text = 'FFA' + + +class ConfigNumberEdit: + + def __init__(self, + parent: ba.Widget, + position: Tuple[float, float], + value: int, + config: str, + text: str): + self._increment = 1 + self._minval = 1 + self._maxval = 100 + self._value = value + self._config = config + + textscale = 1.0 + self.nametext = ba.textwidget( + parent=parent, + position=(position[0], position[1]), + size=(100, 30), + text=text, + maxwidth=150, + color=(0.8, 0.8, 0.8, 1.0), + h_align='left', + v_align='center', + scale=textscale) + self.valuetext = ba.textwidget( + parent=parent, + position=(position[0]+150, position[1]), + size=(60, 28), + editable=False, + color=(0.3, 1.0, 0.3, 1.0), + h_align='right', + v_align='center', + text=str(value), + padding=2) + self.minusbutton = ba.buttonwidget( + parent=parent, + position=(position[0]+240, position[1]), + size=(28, 28), + label='-', + autoselect=True, + on_activate_call=ba.Call(self._down), + repeat=True) + self.plusbutton = ba.buttonwidget( + parent=parent, + position=(position[0]+290, position[1]), + size=(28, 28), + label='+', + autoselect=True, + on_activate_call=ba.Call(self._up), + repeat=True) + + def _up(self) -> None: + self._value = min(self._maxval, self._value + self._increment) + self._update_display() + + def _down(self) -> None: + self._value = max(self._minval, self._value - self._increment) + self._update_display() + + def _update_display(self) -> None: + ba.textwidget(edit=self.valuetext, text=str(self._value)) + cfg['Config Max Players'][self._config] = self._value + cfg.apply_and_commit() + + +class SettingsMaxPlayers(PopupWindow): + + def __init__(self): + # pylint: disable=too-many-locals + uiscale = ba.app.ui.uiscale + self._transitioning_out = False + self._width = 400 + self._height = 220 + bg_color = (0.5, 0.4, 0.6) + + # creates our _root_widget + PopupWindow.__init__(self, + position=(0.0, 0.0), + size=(self._width, self._height), + scale=1.2, + bg_color=bg_color) + + self._cancel_button = ba.buttonwidget( + parent=self.root_widget, + position=(25, self._height - 40), + size=(50, 50), + scale=0.58, + label='', + color=bg_color, + on_activate_call=self._on_cancel_press, + autoselect=True, + icon=ba.gettexture('crossOut'), + iconscale=1.2) + ba.containerwidget(edit=self.root_widget, + cancel_button=self._cancel_button) + + ba.textwidget( + parent=self.root_widget, + position=(self._width * 0.5, self._height - 30), + size=(0, 0), + h_align='center', + v_align='center', + scale=0.8, + text=title_text, + maxwidth=200, + color=ba.app.ui.title_color) + + posx = 33 + posy = self._height + + # co-op + ConfigNumberEdit(parent=self.root_widget, + position=(posx, posy*0.6), + value=cfg['Config Max Players']['coop_max_players'], + config='coop_max_players', + text=coop_text) + + # teams + ConfigNumberEdit(parent=self.root_widget, + position=(posx, posy*0.38), + value=cfg['Config Max Players']['teams_max_players'], + config='teams_max_players', + text=teams_text) + + # ffa + ConfigNumberEdit(parent=self.root_widget, + position=(posx, posy*0.16), + value=cfg['Config Max Players']['ffa_max_players'], + config='ffa_max_players', + text=ffa_text) + + def _on_cancel_press(self) -> None: + self._transition_out() + + def _transition_out(self) -> None: + if not self._transitioning_out: + self._transitioning_out = True + ba.containerwidget(edit=self.root_widget, transition='out_scale') + + def on_popup_cancel(self) -> None: + ba.playsound(ba.getsound('swish')) + self._transition_out() + + +def __init__(self) -> None: + """Instantiate a co-op mode session.""" + # pylint: disable=cyclic-import + from ba._campaign import getcampaign + from bastd.activity.coopjoin import CoopJoinActivity + + _ba.increment_analytics_count('Co-op session start') + app = _ba.app + + # If they passed in explicit min/max, honor that. + # Otherwise defer to user overrides or defaults. + if 'min_players' in app.coop_session_args: + min_players = app.coop_session_args['min_players'] + else: + min_players = 1 + if 'max_players' in app.coop_session_args: + max_players = app.coop_session_args['max_players'] + else: + max_players = app.config.get( + 'Coop Game Max Players', + cfg['Config Max Players']['coop_max_players']) + + # print('FIXME: COOP SESSION WOULD CALC DEPS.') + depsets: Sequence[ba.DependencySet] = [] + + Session.__init__(self, + depsets, + team_names=TEAM_NAMES, + team_colors=TEAM_COLORS, + min_players=min_players, + max_players=max_players) + + # Tournament-ID if we correspond to a co-op tournament (otherwise None) + self.tournament_id: Optional[str] = ( + app.coop_session_args.get('tournament_id')) + + self.campaign = getcampaign(app.coop_session_args['campaign']) + self.campaign_level_name: str = app.coop_session_args['level'] + + self._ran_tutorial_activity = False + self._tutorial_activity: Optional[ba.Activity] = None + self._custom_menu_ui: List[Dict[str, Any]] = [] + + # Start our joining screen. + self.setactivity(_ba.newactivity(CoopJoinActivity)) + + self._next_game_instance: Optional[ba.GameActivity] = None + self._next_game_level_name: Optional[str] = None + self._update_on_deck_game_instances() + + +def get_max_players(self) -> int: + """Return max number of ba.Players allowed to join the game at once.""" + if self.use_teams: + return _ba.app.config.get( + 'Team Game Max Players', + cfg['Config Max Players']['teams_max_players']) + return _ba.app.config.get( + 'Free-for-All Max Players', + cfg['Config Max Players']['ffa_max_players']) + + +GatherWindow.__old_init__ = GatherWindow.__init__ + + +def __gather_init__(self, + transition: Optional[str] = 'in_right', + origin_widget: ba.Widget = None): + self.__old_init__(transition, origin_widget) + + def _do_max_players(): + SettingsMaxPlayers() + self._max_players_button = ba.buttonwidget( + parent=self._root_widget, + position=(self._width*0.72, self._height*0.91), + size=(220, 60), + scale=1.0, + color=(0.6, 0.0, 0.9), + icon=ba.gettexture('usersButton'), + iconscale=1.5, + autoselect=True, + label=title_short_text, + button_type='regular', + on_activate_call=_do_max_players) + + +def _save_state(self) -> None: + try: + for tab in self._tabs.values(): + tab.save_state() + + sel = self._root_widget.get_selected_child() + selected_tab_ids = [ + tab_id for tab_id, tab in self._tab_row.tabs.items() + if sel == tab.button + ] + if sel == self._back_button: + sel_name = 'Back' + elif sel == self._max_players_button: + sel_name = 'Max Players' + elif selected_tab_ids: + assert len(selected_tab_ids) == 1 + sel_name = f'Tab:{selected_tab_ids[0].value}' + elif sel == self._tab_container: + sel_name = 'TabContainer' + else: + raise ValueError(f'unrecognized selection: \'{sel}\'') + ba.app.ui.window_states[type(self)] = { + 'sel_name': sel_name, + } + except Exception: + ba.print_exception(f'Error saving state for {self}.') + + +def _restore_state(self) -> None: + from efro.util import enum_by_value + try: + for tab in self._tabs.values(): + tab.restore_state() + + sel: Optional[ba.Widget] + winstate = ba.app.ui.window_states.get(type(self), {}) + sel_name = winstate.get('sel_name', None) + assert isinstance(sel_name, (str, type(None))) + current_tab = self.TabID.ABOUT + gather_tab_val = ba.app.config.get('Gather Tab') + try: + stored_tab = enum_by_value(self.TabID, gather_tab_val) + if stored_tab in self._tab_row.tabs: + current_tab = stored_tab + except ValueError: + pass + self._set_tab(current_tab) + if sel_name == 'Back': + sel = self._back_button + elif sel_name == 'Max Players': + sel = self._back_button + elif sel_name == 'TabContainer': + sel = self._tab_container + elif isinstance(sel_name, str) and sel_name.startswith('Tab:'): + try: + sel_tab_id = enum_by_value(self.TabID, + sel_name.split(':')[-1]) + except ValueError: + sel_tab_id = self.TabID.ABOUT + sel = self._tab_row.tabs[sel_tab_id].button + else: + sel = self._tab_row.tabs[current_tab].button + ba.containerwidget(edit=self._root_widget, selected_child=sel) + except Exception: + ba.print_exception('Error restoring gather-win state.') + +# ba_meta export plugin + + +class MaxPlayersPlugin(ba.Plugin): + + def has_settings_ui(self) -> bool: + return True + + def show_settings_ui(self, source_widget: ba.Widget | None) -> None: + SettingsMaxPlayers() + + if 'Config Max Players' in ba.app.config: + old_config = ba.app.config['Config Max Players'] + for setting in cmp: + if setting not in old_config: + ba.app.config['Config Max Players'].update({setting: cmp[setting]}) + remove_list = [] + for setting in old_config: + if setting not in cmp: + remove_list.append(setting) + for element in remove_list: + ba.app.config['Config Max Players'].pop(element) + else: + ba.app.config['Config Max Players'] = cmp + ba.app.config.apply_and_commit() + + CoopSession.__init__ = __init__ + MultiTeamSession.get_max_players = get_max_players + GatherWindow.__init__ = __gather_init__ + GatherWindow._save_state = _save_state + GatherWindow._restore_state = _restore_state diff --git a/plugins/utilities/quick_custom_game.py b/plugins/utilities/quick_custom_game.py new file mode 100644 index 0000000..259dff2 --- /dev/null +++ b/plugins/utilities/quick_custom_game.py @@ -0,0 +1,381 @@ +# ba_meta require api 7 +# (see https://ballistica.net/wiki/meta-tag-system) + +from __future__ import annotations + +from typing import TYPE_CHECKING + +import ba +import _ba +from bastd.ui.play import PlayWindow +from bastd.ui.playlist.addgame import PlaylistAddGameWindow +from ba._freeforallsession import FreeForAllSession +from bastd.activity.multiteamjoin import MultiTeamJoinActivity + +if TYPE_CHECKING: + pass + + +lang = ba.app.lang.language + +if lang == 'Spanish': + custom_txt = 'personalizar...' +else: + custom_txt = 'custom...' + + +if 'quick_game_button' in ba.app.config: + config = ba.app.config['quick_game_button'] +else: + config = {'selected': None, 'config': None} + ba.app.config['quick_game_button'] = config + ba.app.config.commit() + + +def start_game(session: ba.Session, fadeout: bool = True): + def callback(): + if fadeout: + _ba.unlock_all_input() + try: + _ba.new_host_session(session) + except Exception: + from bastd import mainmenu + ba.print_exception('exception running session', session) + + # Drop back into a main menu session. + _ba.new_host_session(mainmenu.MainMenuSession) + + if fadeout: + _ba.fade_screen(False, time=0.25, endcall=callback) + _ba.lock_all_input() + else: + callback() + + +class SimplePlaylist: + + def __init__(self, + settings: dict, + gametype: type[ba.GameActivity]): + self.settings = settings + self.gametype = gametype + + def pull_next(self) -> None: + if 'map' not in self.settings['settings']: + settings = dict( + map=self.settings['map'], **self.settings['settings']) + else: + settings = self.settings['settings'] + return dict(resolved_type=self.gametype, settings=settings) + + +class CustomSession(FreeForAllSession): + + def __init__(self, *args, **kwargs): + # pylint: disable=cyclic-import + self.use_teams = False + self._tutorial_activity_instance = None + ba.Session.__init__(self, depsets=[], + team_names=None, + team_colors=None, + min_players=1, + max_players=self.get_max_players()) + + self._series_length = 1 + self._ffa_series_length = 1 + + # Which game activity we're on. + self._game_number = 0 + self._playlist = SimplePlaylist(self._config, self._gametype) + config['selected'] = self._gametype.__name__ + config['config'] = self._config + ba.app.config.commit() + + # Get a game on deck ready to go. + self._current_game_spec: Optional[Dict[str, Any]] = None + self._next_game_spec: Dict[str, Any] = self._playlist.pull_next() + self._next_game: Type[ba.GameActivity] = ( + self._next_game_spec['resolved_type']) + + # Go ahead and instantiate the next game we'll + # use so it has lots of time to load. + self._instantiate_next_game() + + # Start in our custom join screen. + self.setactivity(_ba.newactivity(MultiTeamJoinActivity)) + + +class SelectGameWindow(PlaylistAddGameWindow): + + def __init__(self, transition: str = 'in_right'): + class EditController: + _sessiontype = ba.FreeForAllSession + + def get_session_type(self) -> Type[ba.Session]: + return self._sessiontype + + self._editcontroller = EditController() + self._r = 'addGameWindow' + uiscale = ba.app.ui.uiscale + self._width = 750 if uiscale is ba.UIScale.SMALL else 650 + x_inset = 50 if uiscale is ba.UIScale.SMALL else 0 + self._height = (346 if uiscale is ba.UIScale.SMALL else + 380 if uiscale is ba.UIScale.MEDIUM else 440) + top_extra = 30 if uiscale is ba.UIScale.SMALL else 20 + self._scroll_width = 210 + + self._root_widget = ba.containerwidget( + size=(self._width, self._height + top_extra), + transition=transition, + scale=(2.17 if uiscale is ba.UIScale.SMALL else + 1.5 if uiscale is ba.UIScale.MEDIUM else 1.0), + stack_offset=(0, 1) if uiscale is ba.UIScale.SMALL else (0, 0)) + + self._back_button = ba.buttonwidget(parent=self._root_widget, + position=(58 + x_inset, + self._height - 53), + size=(165, 70), + scale=0.75, + text_scale=1.2, + label=ba.Lstr(resource='backText'), + autoselect=True, + button_type='back', + on_activate_call=self._back) + self._select_button = select_button = ba.buttonwidget( + parent=self._root_widget, + position=(self._width - (172 + x_inset), self._height - 50), + autoselect=True, + size=(160, 60), + scale=0.75, + text_scale=1.2, + label=ba.Lstr(resource='selectText'), + on_activate_call=self._add) + + if ba.app.ui.use_toolbars: + ba.widget(edit=select_button, + right_widget=_ba.get_special_widget('party_button')) + + ba.textwidget(parent=self._root_widget, + position=(self._width * 0.5, self._height - 28), + size=(0, 0), + scale=1.0, + text=ba.Lstr(resource=self._r + '.titleText'), + h_align='center', + color=ba.app.ui.title_color, + maxwidth=250, + v_align='center') + v = self._height - 64 + + self._selected_title_text = ba.textwidget( + parent=self._root_widget, + position=(x_inset + self._scroll_width + 50 + 30, v - 15), + size=(0, 0), + scale=1.0, + color=(0.7, 1.0, 0.7, 1.0), + maxwidth=self._width - self._scroll_width - 150 - x_inset * 2, + h_align='left', + v_align='center') + v -= 30 + + self._selected_description_text = ba.textwidget( + parent=self._root_widget, + position=(x_inset + self._scroll_width + 50 + 30, v), + size=(0, 0), + scale=0.7, + color=(0.5, 0.8, 0.5, 1.0), + maxwidth=self._width - self._scroll_width - 150 - x_inset * 2, + h_align='left') + + scroll_height = self._height - 100 + + v = self._height - 60 + + self._scrollwidget = ba.scrollwidget(parent=self._root_widget, + position=(x_inset + 61, + v - scroll_height), + size=(self._scroll_width, + scroll_height), + highlight=False) + ba.widget(edit=self._scrollwidget, + up_widget=self._back_button, + left_widget=self._back_button, + right_widget=select_button) + self._column: Optional[ba.Widget] = None + + v -= 35 + ba.containerwidget(edit=self._root_widget, + cancel_button=self._back_button, + start_button=select_button) + self._selected_game_type: Optional[Type[ba.GameActivity]] = None + + ba.containerwidget(edit=self._root_widget, + selected_child=self._scrollwidget) + + self._game_types: list[type[ba.GameActivity]] = [] + + # Get actual games loading in the bg. + ba.app.meta.load_exported_classes(ba.GameActivity, + self._on_game_types_loaded, + completion_cb_in_bg_thread=True) + + # Refresh with our initial empty list. We'll refresh again once + # game loading is complete. + self._refresh() + + if config['selected']: + for gt in self._game_types: + if gt.__name__ == config['selected']: + self._refresh(selected=gt) + self._set_selected_game_type(gt) + + def _refresh(self, + select_get_more_games_button: bool = False, + selected: bool = None) -> None: + # from ba.internal import get_game_types + + if self._column is not None: + self._column.delete() + + self._column = ba.columnwidget(parent=self._scrollwidget, + border=2, + margin=0) + + for i, gametype in enumerate(self._game_types): + + def _doit() -> None: + if self._select_button: + ba.timer(0.1, + self._select_button.activate, + timetype=ba.TimeType.REAL) + + txt = ba.textwidget(parent=self._column, + position=(0, 0), + size=(self._width - 88, 24), + text=gametype.get_display_string(), + h_align='left', + v_align='center', + color=(0.8, 0.8, 0.8, 1.0), + maxwidth=self._scroll_width * 0.8, + on_select_call=ba.Call( + self._set_selected_game_type, gametype), + always_highlight=True, + selectable=True, + on_activate_call=_doit) + if i == 0: + ba.widget(edit=txt, up_widget=self._back_button) + + self._get_more_games_button = ba.buttonwidget( + parent=self._column, + autoselect=True, + label=ba.Lstr(resource=self._r + '.getMoreGamesText'), + color=(0.54, 0.52, 0.67), + textcolor=(0.7, 0.65, 0.7), + on_activate_call=self._on_get_more_games_press, + size=(178, 50)) + if select_get_more_games_button: + ba.containerwidget(edit=self._column, + selected_child=self._get_more_games_button, + visible_child=self._get_more_games_button) + + def _add(self) -> None: + _ba.lock_all_input() # Make sure no more commands happen. + ba.timer(0.1, _ba.unlock_all_input, timetype=ba.TimeType.REAL) + gameconfig = {} + if config['selected'] == self._selected_game_type.__name__: + if config['config']: + gameconfig = config['config'] + if 'map' in gameconfig: + gameconfig['settings']['map'] = gameconfig.pop('map') + self._selected_game_type.create_settings_ui( + self._editcontroller.get_session_type(), + gameconfig, + self._edit_game_done) + + def _edit_game_done(self, config: Optional[Dict[str, Any]]) -> None: + if config: + CustomSession._config = config + CustomSession._gametype = self._selected_game_type + start_game(CustomSession) + else: + ba.app.ui.clear_main_menu_window(transition='out_right') + ba.app.ui.set_main_menu_window( + SelectGameWindow(transition='in_left').get_root_widget()) + + def _back(self) -> None: + ba.containerwidget(edit=self._root_widget, transition='out_right') + ba.app.ui.set_main_menu_window( + PlayWindow(transition='in_left').get_root_widget()) + + +PlayWindow._old_init = PlayWindow.__init__ + + +def __init__(self, *args, **kwargs): + self._old_init() + + width = 800 + height = 550 + + def do_quick_game() -> None: + self._save_state() + ba.containerwidget(edit=self._root_widget, transition='out_left') + ba.app.ui.set_main_menu_window( + SelectGameWindow().get_root_widget()) + + self._quick_game_button = ba.buttonwidget( + parent=self._root_widget, + position=(width - 55 - 120, height - 132), + autoselect=True, + size=(120, 60), + scale=1.1, + text_scale=1.2, + label=custom_txt, + on_activate_call=do_quick_game, + color=(0.54, 0.52, 0.67), + textcolor=(0.7, 0.65, 0.7)) + + self._restore_state() + + +def states(self) -> None: + return { + 'Team Games': self._teams_button, + 'Co-op Games': self._coop_button, + 'Free-for-All Games': self._free_for_all_button, + 'Back': self._back_button, + 'Quick Game': self._quick_game_button + } + + +def _save_state(self) -> None: + swapped = {v: k for k, v in states(self).items()} + if self._root_widget.get_selected_child() in swapped: + ba.app.ui.window_states[ + self.__class__.__name__] = swapped[ + self._root_widget.get_selected_child()] + else: + ba.print_exception(f'Error saving state for {self}.') + + +def _restore_state(self) -> None: + if not hasattr(self, '_quick_game_button'): + return # ensure that our monkey patched init ran + if self.__class__.__name__ not in ba.app.ui.window_states: + ba.containerwidget(edit=self._root_widget, + selected_child=self._coop_button) + return + sel = states(self).get( + ba.app.ui.window_states[self.__class__.__name__], None) + if sel: + ba.containerwidget(edit=self._root_widget, selected_child=sel) + else: + ba.containerwidget(edit=self._root_widget, + selected_child=self._coop_button) + ba.print_exception(f'Error restoring state for {self}.') + + +# ba_meta export plugin +class QuickGamePlugin(ba.Plugin): + PlayWindow.__init__ = __init__ + PlayWindow._save_state = _save_state + PlayWindow._restore_state = _restore_state diff --git a/plugins/utilities/random_colors.py b/plugins/utilities/random_colors.py new file mode 100644 index 0000000..3ea0ba6 --- /dev/null +++ b/plugins/utilities/random_colors.py @@ -0,0 +1,48 @@ +# ba_meta require api 7 +# (see https://ballistica.net/wiki/meta-tag-system) + +from __future__ import annotations + +from typing import TYPE_CHECKING + +import ba +import random +from bastd.actor import bomb + +if TYPE_CHECKING: + from typing import Sequence + + +class NewBlast(bomb.Blast): + def __init__( + self, + position: Sequence[float] = (0.0, 1.0, 0.0), + velocity: Sequence[float] = (0.0, 0.0, 0.0), + blast_radius: float = 2.0, + blast_type: str = 'normal', + source_player: ba.Player | None = None, + hit_type: str = 'explosion', + hit_subtype: str = 'normal', + ): + super().__init__(position, velocity, blast_radius, blast_type, + source_player, hit_type, hit_subtype) + scorch_radius = light_radius = self.radius + if self.blast_type == 'tnt': + scorch_radius *= 1.15 + scorch = ba.newnode( + 'scorch', + attrs={ + 'position': position, + 'size': scorch_radius * 0.5, + 'big': (self.blast_type == 'tnt'), + }, + ) + random_color = (random.random(), random.random(), random.random()) + scorch.color = ba.safecolor(random_color) + ba.animate(scorch, 'presence', {3.000: 1, 13.000: 0}) + ba.timer(13.0, scorch.delete) + + +# ba_meta export plugin +class RandomColorsPlugin(ba.Plugin): + bomb.Blast = NewBlast From 8a8c6210960917dc50807d030624af9d9da26b4c Mon Sep 17 00:00:00 2001 From: Loup <90267658+Loup-Garou911XD@users.noreply.github.com> Date: Mon, 7 Nov 2022 00:22:02 +0530 Subject: [PATCH 25/55] Update utilities.json --- plugins/utilities.json | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/plugins/utilities.json b/plugins/utilities.json index c146ec6..9b67e84 100644 --- a/plugins/utilities.json +++ b/plugins/utilities.json @@ -3,7 +3,21 @@ "description": "Utilities", "plugins_base_url": "http://github.com/bombsquad-community/plugin-manager/{content_type}/{tag}/plugins/utilities", "plugins": { - "CustomDeath": { + "share_replay": { + "description": "Export replays to mods folder and share them with friends or have a backup", + "external_url": null, + "authors": [ + { + "name": "LoupGarou", + "email": "LoupGarou5418@outlook.com", + "discord": "ʟօʊքɢǟʀօʊ#3063" + } + ], + "versions": { + "1.0.0":null + } + }, + "custom_death": { "description": "Characters turn to Bones after death", "external_url": "https://youtube.com/c/JoseANG3LYT", "authors": [ @@ -22,7 +36,7 @@ } } }, - "MaxPlayers": { + "max_players": { "description": "Increase the max player limit of 8 players", "external_url": "https://youtube.com/c/JoseANG3LYT", "authors": [ @@ -41,7 +55,7 @@ } } }, - "QuickCustomGame": { + "quick_custom_game": { "description": "Quckly create a custom game with any gamemode", "external_url": "https://youtube.com/c/JoseANG3LYT", "authors": [ @@ -60,7 +74,7 @@ } } }, - "RandomColors": { + "random_colors": { "description": "Creates patches of random color after bomb explosions", "external_url": "https://youtube.com/c/JoseANG3LYT", "authors": [ @@ -410,4 +424,4 @@ } } } -} \ No newline at end of file +} From ed06dac4b8464dacb5c6f3fe5b62b482c55f1b8e Mon Sep 17 00:00:00 2001 From: Loup <90267658+Loup-Garou911XD@users.noreply.github.com> Date: Mon, 7 Nov 2022 00:22:59 +0530 Subject: [PATCH 26/55] Delete CustomDeath.py --- plugins/utilities/CustomDeath.py | 40 -------------------------------- 1 file changed, 40 deletions(-) delete mode 100644 plugins/utilities/CustomDeath.py diff --git a/plugins/utilities/CustomDeath.py b/plugins/utilities/CustomDeath.py deleted file mode 100644 index b3730e1..0000000 --- a/plugins/utilities/CustomDeath.py +++ /dev/null @@ -1,40 +0,0 @@ -# ba_meta require api 7 -# (see https://ballistica.net/wiki/meta-tag-system) - -from __future__ import annotations - -from typing import TYPE_CHECKING - -import ba -from bastd.actor.spaz import Spaz - -if TYPE_CHECKING: - from typing import Any - - -Spaz.oldhandlemessage = Spaz.handlemessage - - -def handlemessage(self, msg: Any) -> Any: - if isinstance(msg, ba.DieMessage): - if self.node: - self.node.color_texture = ba.gettexture('bonesColor') - self.node.color_mask_texture = ba.gettexture('bonesColorMask') - self.node.head_model = ba.getmodel('bonesHead') - self.node.torso_model = ba.getmodel('bonesTorso') - self.node.pelvis_model = ba.getmodel('bonesPelvis') - self.node.upper_arm_model = ba.getmodel('bonesUpperArm') - self.node.forearm_model = ba.getmodel('bonesForeArm') - self.node.hand_model = ba.getmodel('bonesHand') - self.node.upper_leg_model = ba.getmodel('bonesUpperLeg') - self.node.lower_leg_model = ba.getmodel('bonesLowerLeg') - self.node.toes_model = ba.getmodel('bonesToes') - self.node.style = 'bones' - self.oldhandlemessage(msg) - else: - return self.oldhandlemessage(msg) - - -# ba_meta export plugin -class CustomDeath(ba.Plugin): - Spaz.handlemessage = handlemessage From 8b3e6a8d8418c774d0d4f07f8d6517a2d91fb1dc Mon Sep 17 00:00:00 2001 From: Loup <90267658+Loup-Garou911XD@users.noreply.github.com> Date: Mon, 7 Nov 2022 00:23:12 +0530 Subject: [PATCH 27/55] Delete MaxPlayers.py --- plugins/utilities/MaxPlayers.py | 368 -------------------------------- 1 file changed, 368 deletions(-) delete mode 100644 plugins/utilities/MaxPlayers.py diff --git a/plugins/utilities/MaxPlayers.py b/plugins/utilities/MaxPlayers.py deleted file mode 100644 index 6d6257a..0000000 --- a/plugins/utilities/MaxPlayers.py +++ /dev/null @@ -1,368 +0,0 @@ -"""===========MAX_PLAYERS===========""" - -# ba_meta require api 7 -# (see https://ballistica.net/wiki/meta-tag-system) - -from __future__ import annotations -from typing import TYPE_CHECKING - -import ba -import _ba -from ba._session import Session -from ba._coopsession import CoopSession, TEAM_COLORS, TEAM_NAMES -from ba._multiteamsession import MultiTeamSession -from bastd.ui.gather import GatherWindow -from bastd.ui.popup import PopupWindow - -if TYPE_CHECKING: - from typing import List, Any, Optional, Sequence - - -cfg = ba.app.config -cmp = {'coop_max_players': 4, - 'teams_max_players': 8, - 'ffa_max_players': 8} - -lang = ba.app.lang.language -if lang == 'Spanish': - title_text = 'Máximo de Jugadores' - title_short_text = 'Jugadores' - coop_text = 'Cooperativo' - teams_text = 'Equipos' - ffa_text = 'Todos Contra Todos' -else: - title_text = 'Max Players' - title_short_text = 'Players' - coop_text = 'Co-op' - teams_text = 'Teams' - ffa_text = 'FFA' - - -class ConfigNumberEdit: - - def __init__(self, - parent: ba.Widget, - position: Tuple[float, float], - value: int, - config: str, - text: str): - self._increment = 1 - self._minval = 1 - self._maxval = 100 - self._value = value - self._config = config - - textscale = 1.0 - self.nametext = ba.textwidget( - parent=parent, - position=(position[0], position[1]), - size=(100, 30), - text=text, - maxwidth=150, - color=(0.8, 0.8, 0.8, 1.0), - h_align='left', - v_align='center', - scale=textscale) - self.valuetext = ba.textwidget( - parent=parent, - position=(position[0]+150, position[1]), - size=(60, 28), - editable=False, - color=(0.3, 1.0, 0.3, 1.0), - h_align='right', - v_align='center', - text=str(value), - padding=2) - self.minusbutton = ba.buttonwidget( - parent=parent, - position=(position[0]+240, position[1]), - size=(28, 28), - label='-', - autoselect=True, - on_activate_call=ba.Call(self._down), - repeat=True) - self.plusbutton = ba.buttonwidget( - parent=parent, - position=(position[0]+290, position[1]), - size=(28, 28), - label='+', - autoselect=True, - on_activate_call=ba.Call(self._up), - repeat=True) - - def _up(self) -> None: - self._value = min(self._maxval, self._value + self._increment) - self._update_display() - - def _down(self) -> None: - self._value = max(self._minval, self._value - self._increment) - self._update_display() - - def _update_display(self) -> None: - ba.textwidget(edit=self.valuetext, text=str(self._value)) - cfg['Config Max Players'][self._config] = self._value - cfg.apply_and_commit() - - -class SettingsMaxPlayers(PopupWindow): - - def __init__(self): - # pylint: disable=too-many-locals - uiscale = ba.app.ui.uiscale - self._transitioning_out = False - self._width = 400 - self._height = 220 - bg_color = (0.5, 0.4, 0.6) - - # creates our _root_widget - PopupWindow.__init__(self, - position=(0.0, 0.0), - size=(self._width, self._height), - scale=1.2, - bg_color=bg_color) - - self._cancel_button = ba.buttonwidget( - parent=self.root_widget, - position=(25, self._height - 40), - size=(50, 50), - scale=0.58, - label='', - color=bg_color, - on_activate_call=self._on_cancel_press, - autoselect=True, - icon=ba.gettexture('crossOut'), - iconscale=1.2) - ba.containerwidget(edit=self.root_widget, - cancel_button=self._cancel_button) - - ba.textwidget( - parent=self.root_widget, - position=(self._width * 0.5, self._height - 30), - size=(0, 0), - h_align='center', - v_align='center', - scale=0.8, - text=title_text, - maxwidth=200, - color=ba.app.ui.title_color) - - posx = 33 - posy = self._height - - # co-op - ConfigNumberEdit(parent=self.root_widget, - position=(posx, posy*0.6), - value=cfg['Config Max Players']['coop_max_players'], - config='coop_max_players', - text=coop_text) - - # teams - ConfigNumberEdit(parent=self.root_widget, - position=(posx, posy*0.38), - value=cfg['Config Max Players']['teams_max_players'], - config='teams_max_players', - text=teams_text) - - # ffa - ConfigNumberEdit(parent=self.root_widget, - position=(posx, posy*0.16), - value=cfg['Config Max Players']['ffa_max_players'], - config='ffa_max_players', - text=ffa_text) - - def _on_cancel_press(self) -> None: - self._transition_out() - - def _transition_out(self) -> None: - if not self._transitioning_out: - self._transitioning_out = True - ba.containerwidget(edit=self.root_widget, transition='out_scale') - - def on_popup_cancel(self) -> None: - ba.playsound(ba.getsound('swish')) - self._transition_out() - - -def __init__(self) -> None: - """Instantiate a co-op mode session.""" - # pylint: disable=cyclic-import - from ba._campaign import getcampaign - from bastd.activity.coopjoin import CoopJoinActivity - - _ba.increment_analytics_count('Co-op session start') - app = _ba.app - - # If they passed in explicit min/max, honor that. - # Otherwise defer to user overrides or defaults. - if 'min_players' in app.coop_session_args: - min_players = app.coop_session_args['min_players'] - else: - min_players = 1 - if 'max_players' in app.coop_session_args: - max_players = app.coop_session_args['max_players'] - else: - max_players = app.config.get( - 'Coop Game Max Players', - cfg['Config Max Players']['coop_max_players']) - - # print('FIXME: COOP SESSION WOULD CALC DEPS.') - depsets: Sequence[ba.DependencySet] = [] - - Session.__init__(self, - depsets, - team_names=TEAM_NAMES, - team_colors=TEAM_COLORS, - min_players=min_players, - max_players=max_players) - - # Tournament-ID if we correspond to a co-op tournament (otherwise None) - self.tournament_id: Optional[str] = ( - app.coop_session_args.get('tournament_id')) - - self.campaign = getcampaign(app.coop_session_args['campaign']) - self.campaign_level_name: str = app.coop_session_args['level'] - - self._ran_tutorial_activity = False - self._tutorial_activity: Optional[ba.Activity] = None - self._custom_menu_ui: List[Dict[str, Any]] = [] - - # Start our joining screen. - self.setactivity(_ba.newactivity(CoopJoinActivity)) - - self._next_game_instance: Optional[ba.GameActivity] = None - self._next_game_level_name: Optional[str] = None - self._update_on_deck_game_instances() - - -def get_max_players(self) -> int: - """Return max number of ba.Players allowed to join the game at once.""" - if self.use_teams: - return _ba.app.config.get( - 'Team Game Max Players', - cfg['Config Max Players']['teams_max_players']) - return _ba.app.config.get( - 'Free-for-All Max Players', - cfg['Config Max Players']['ffa_max_players']) - - -GatherWindow.__old_init__ = GatherWindow.__init__ - - -def __gather_init__(self, - transition: Optional[str] = 'in_right', - origin_widget: ba.Widget = None): - self.__old_init__(transition, origin_widget) - - def _do_max_players(): - SettingsMaxPlayers() - self._max_players_button = ba.buttonwidget( - parent=self._root_widget, - position=(self._width*0.72, self._height*0.91), - size=(220, 60), - scale=1.0, - color=(0.6, 0.0, 0.9), - icon=ba.gettexture('usersButton'), - iconscale=1.5, - autoselect=True, - label=title_short_text, - button_type='regular', - on_activate_call=_do_max_players) - - -def _save_state(self) -> None: - try: - for tab in self._tabs.values(): - tab.save_state() - - sel = self._root_widget.get_selected_child() - selected_tab_ids = [ - tab_id for tab_id, tab in self._tab_row.tabs.items() - if sel == tab.button - ] - if sel == self._back_button: - sel_name = 'Back' - elif sel == self._max_players_button: - sel_name = 'Max Players' - elif selected_tab_ids: - assert len(selected_tab_ids) == 1 - sel_name = f'Tab:{selected_tab_ids[0].value}' - elif sel == self._tab_container: - sel_name = 'TabContainer' - else: - raise ValueError(f'unrecognized selection: \'{sel}\'') - ba.app.ui.window_states[type(self)] = { - 'sel_name': sel_name, - } - except Exception: - ba.print_exception(f'Error saving state for {self}.') - - -def _restore_state(self) -> None: - from efro.util import enum_by_value - try: - for tab in self._tabs.values(): - tab.restore_state() - - sel: Optional[ba.Widget] - winstate = ba.app.ui.window_states.get(type(self), {}) - sel_name = winstate.get('sel_name', None) - assert isinstance(sel_name, (str, type(None))) - current_tab = self.TabID.ABOUT - gather_tab_val = ba.app.config.get('Gather Tab') - try: - stored_tab = enum_by_value(self.TabID, gather_tab_val) - if stored_tab in self._tab_row.tabs: - current_tab = stored_tab - except ValueError: - pass - self._set_tab(current_tab) - if sel_name == 'Back': - sel = self._back_button - elif sel_name == 'Max Players': - sel = self._back_button - elif sel_name == 'TabContainer': - sel = self._tab_container - elif isinstance(sel_name, str) and sel_name.startswith('Tab:'): - try: - sel_tab_id = enum_by_value(self.TabID, - sel_name.split(':')[-1]) - except ValueError: - sel_tab_id = self.TabID.ABOUT - sel = self._tab_row.tabs[sel_tab_id].button - else: - sel = self._tab_row.tabs[current_tab].button - ba.containerwidget(edit=self._root_widget, selected_child=sel) - except Exception: - ba.print_exception('Error restoring gather-win state.') - -# ba_meta export plugin - - -class MaxPlayersPlugin(ba.Plugin): - - def has_settings_ui(self) -> bool: - return True - - def show_settings_ui(self, source_widget: ba.Widget | None) -> None: - SettingsMaxPlayers() - - if 'Config Max Players' in ba.app.config: - old_config = ba.app.config['Config Max Players'] - for setting in cmp: - if setting not in old_config: - ba.app.config['Config Max Players'].update({setting: cmp[setting]}) - remove_list = [] - for setting in old_config: - if setting not in cmp: - remove_list.append(setting) - for element in remove_list: - ba.app.config['Config Max Players'].pop(element) - else: - ba.app.config['Config Max Players'] = cmp - ba.app.config.apply_and_commit() - - CoopSession.__init__ = __init__ - MultiTeamSession.get_max_players = get_max_players - GatherWindow.__init__ = __gather_init__ - GatherWindow._save_state = _save_state - GatherWindow._restore_state = _restore_state From 9f817d8ee8422feb02bd6437177768c9a7485236 Mon Sep 17 00:00:00 2001 From: Loup <90267658+Loup-Garou911XD@users.noreply.github.com> Date: Mon, 7 Nov 2022 00:23:27 +0530 Subject: [PATCH 28/55] Delete QuickCustomGame.py --- plugins/utilities/QuickCustomGame.py | 381 --------------------------- 1 file changed, 381 deletions(-) delete mode 100644 plugins/utilities/QuickCustomGame.py diff --git a/plugins/utilities/QuickCustomGame.py b/plugins/utilities/QuickCustomGame.py deleted file mode 100644 index 259dff2..0000000 --- a/plugins/utilities/QuickCustomGame.py +++ /dev/null @@ -1,381 +0,0 @@ -# ba_meta require api 7 -# (see https://ballistica.net/wiki/meta-tag-system) - -from __future__ import annotations - -from typing import TYPE_CHECKING - -import ba -import _ba -from bastd.ui.play import PlayWindow -from bastd.ui.playlist.addgame import PlaylistAddGameWindow -from ba._freeforallsession import FreeForAllSession -from bastd.activity.multiteamjoin import MultiTeamJoinActivity - -if TYPE_CHECKING: - pass - - -lang = ba.app.lang.language - -if lang == 'Spanish': - custom_txt = 'personalizar...' -else: - custom_txt = 'custom...' - - -if 'quick_game_button' in ba.app.config: - config = ba.app.config['quick_game_button'] -else: - config = {'selected': None, 'config': None} - ba.app.config['quick_game_button'] = config - ba.app.config.commit() - - -def start_game(session: ba.Session, fadeout: bool = True): - def callback(): - if fadeout: - _ba.unlock_all_input() - try: - _ba.new_host_session(session) - except Exception: - from bastd import mainmenu - ba.print_exception('exception running session', session) - - # Drop back into a main menu session. - _ba.new_host_session(mainmenu.MainMenuSession) - - if fadeout: - _ba.fade_screen(False, time=0.25, endcall=callback) - _ba.lock_all_input() - else: - callback() - - -class SimplePlaylist: - - def __init__(self, - settings: dict, - gametype: type[ba.GameActivity]): - self.settings = settings - self.gametype = gametype - - def pull_next(self) -> None: - if 'map' not in self.settings['settings']: - settings = dict( - map=self.settings['map'], **self.settings['settings']) - else: - settings = self.settings['settings'] - return dict(resolved_type=self.gametype, settings=settings) - - -class CustomSession(FreeForAllSession): - - def __init__(self, *args, **kwargs): - # pylint: disable=cyclic-import - self.use_teams = False - self._tutorial_activity_instance = None - ba.Session.__init__(self, depsets=[], - team_names=None, - team_colors=None, - min_players=1, - max_players=self.get_max_players()) - - self._series_length = 1 - self._ffa_series_length = 1 - - # Which game activity we're on. - self._game_number = 0 - self._playlist = SimplePlaylist(self._config, self._gametype) - config['selected'] = self._gametype.__name__ - config['config'] = self._config - ba.app.config.commit() - - # Get a game on deck ready to go. - self._current_game_spec: Optional[Dict[str, Any]] = None - self._next_game_spec: Dict[str, Any] = self._playlist.pull_next() - self._next_game: Type[ba.GameActivity] = ( - self._next_game_spec['resolved_type']) - - # Go ahead and instantiate the next game we'll - # use so it has lots of time to load. - self._instantiate_next_game() - - # Start in our custom join screen. - self.setactivity(_ba.newactivity(MultiTeamJoinActivity)) - - -class SelectGameWindow(PlaylistAddGameWindow): - - def __init__(self, transition: str = 'in_right'): - class EditController: - _sessiontype = ba.FreeForAllSession - - def get_session_type(self) -> Type[ba.Session]: - return self._sessiontype - - self._editcontroller = EditController() - self._r = 'addGameWindow' - uiscale = ba.app.ui.uiscale - self._width = 750 if uiscale is ba.UIScale.SMALL else 650 - x_inset = 50 if uiscale is ba.UIScale.SMALL else 0 - self._height = (346 if uiscale is ba.UIScale.SMALL else - 380 if uiscale is ba.UIScale.MEDIUM else 440) - top_extra = 30 if uiscale is ba.UIScale.SMALL else 20 - self._scroll_width = 210 - - self._root_widget = ba.containerwidget( - size=(self._width, self._height + top_extra), - transition=transition, - scale=(2.17 if uiscale is ba.UIScale.SMALL else - 1.5 if uiscale is ba.UIScale.MEDIUM else 1.0), - stack_offset=(0, 1) if uiscale is ba.UIScale.SMALL else (0, 0)) - - self._back_button = ba.buttonwidget(parent=self._root_widget, - position=(58 + x_inset, - self._height - 53), - size=(165, 70), - scale=0.75, - text_scale=1.2, - label=ba.Lstr(resource='backText'), - autoselect=True, - button_type='back', - on_activate_call=self._back) - self._select_button = select_button = ba.buttonwidget( - parent=self._root_widget, - position=(self._width - (172 + x_inset), self._height - 50), - autoselect=True, - size=(160, 60), - scale=0.75, - text_scale=1.2, - label=ba.Lstr(resource='selectText'), - on_activate_call=self._add) - - if ba.app.ui.use_toolbars: - ba.widget(edit=select_button, - right_widget=_ba.get_special_widget('party_button')) - - ba.textwidget(parent=self._root_widget, - position=(self._width * 0.5, self._height - 28), - size=(0, 0), - scale=1.0, - text=ba.Lstr(resource=self._r + '.titleText'), - h_align='center', - color=ba.app.ui.title_color, - maxwidth=250, - v_align='center') - v = self._height - 64 - - self._selected_title_text = ba.textwidget( - parent=self._root_widget, - position=(x_inset + self._scroll_width + 50 + 30, v - 15), - size=(0, 0), - scale=1.0, - color=(0.7, 1.0, 0.7, 1.0), - maxwidth=self._width - self._scroll_width - 150 - x_inset * 2, - h_align='left', - v_align='center') - v -= 30 - - self._selected_description_text = ba.textwidget( - parent=self._root_widget, - position=(x_inset + self._scroll_width + 50 + 30, v), - size=(0, 0), - scale=0.7, - color=(0.5, 0.8, 0.5, 1.0), - maxwidth=self._width - self._scroll_width - 150 - x_inset * 2, - h_align='left') - - scroll_height = self._height - 100 - - v = self._height - 60 - - self._scrollwidget = ba.scrollwidget(parent=self._root_widget, - position=(x_inset + 61, - v - scroll_height), - size=(self._scroll_width, - scroll_height), - highlight=False) - ba.widget(edit=self._scrollwidget, - up_widget=self._back_button, - left_widget=self._back_button, - right_widget=select_button) - self._column: Optional[ba.Widget] = None - - v -= 35 - ba.containerwidget(edit=self._root_widget, - cancel_button=self._back_button, - start_button=select_button) - self._selected_game_type: Optional[Type[ba.GameActivity]] = None - - ba.containerwidget(edit=self._root_widget, - selected_child=self._scrollwidget) - - self._game_types: list[type[ba.GameActivity]] = [] - - # Get actual games loading in the bg. - ba.app.meta.load_exported_classes(ba.GameActivity, - self._on_game_types_loaded, - completion_cb_in_bg_thread=True) - - # Refresh with our initial empty list. We'll refresh again once - # game loading is complete. - self._refresh() - - if config['selected']: - for gt in self._game_types: - if gt.__name__ == config['selected']: - self._refresh(selected=gt) - self._set_selected_game_type(gt) - - def _refresh(self, - select_get_more_games_button: bool = False, - selected: bool = None) -> None: - # from ba.internal import get_game_types - - if self._column is not None: - self._column.delete() - - self._column = ba.columnwidget(parent=self._scrollwidget, - border=2, - margin=0) - - for i, gametype in enumerate(self._game_types): - - def _doit() -> None: - if self._select_button: - ba.timer(0.1, - self._select_button.activate, - timetype=ba.TimeType.REAL) - - txt = ba.textwidget(parent=self._column, - position=(0, 0), - size=(self._width - 88, 24), - text=gametype.get_display_string(), - h_align='left', - v_align='center', - color=(0.8, 0.8, 0.8, 1.0), - maxwidth=self._scroll_width * 0.8, - on_select_call=ba.Call( - self._set_selected_game_type, gametype), - always_highlight=True, - selectable=True, - on_activate_call=_doit) - if i == 0: - ba.widget(edit=txt, up_widget=self._back_button) - - self._get_more_games_button = ba.buttonwidget( - parent=self._column, - autoselect=True, - label=ba.Lstr(resource=self._r + '.getMoreGamesText'), - color=(0.54, 0.52, 0.67), - textcolor=(0.7, 0.65, 0.7), - on_activate_call=self._on_get_more_games_press, - size=(178, 50)) - if select_get_more_games_button: - ba.containerwidget(edit=self._column, - selected_child=self._get_more_games_button, - visible_child=self._get_more_games_button) - - def _add(self) -> None: - _ba.lock_all_input() # Make sure no more commands happen. - ba.timer(0.1, _ba.unlock_all_input, timetype=ba.TimeType.REAL) - gameconfig = {} - if config['selected'] == self._selected_game_type.__name__: - if config['config']: - gameconfig = config['config'] - if 'map' in gameconfig: - gameconfig['settings']['map'] = gameconfig.pop('map') - self._selected_game_type.create_settings_ui( - self._editcontroller.get_session_type(), - gameconfig, - self._edit_game_done) - - def _edit_game_done(self, config: Optional[Dict[str, Any]]) -> None: - if config: - CustomSession._config = config - CustomSession._gametype = self._selected_game_type - start_game(CustomSession) - else: - ba.app.ui.clear_main_menu_window(transition='out_right') - ba.app.ui.set_main_menu_window( - SelectGameWindow(transition='in_left').get_root_widget()) - - def _back(self) -> None: - ba.containerwidget(edit=self._root_widget, transition='out_right') - ba.app.ui.set_main_menu_window( - PlayWindow(transition='in_left').get_root_widget()) - - -PlayWindow._old_init = PlayWindow.__init__ - - -def __init__(self, *args, **kwargs): - self._old_init() - - width = 800 - height = 550 - - def do_quick_game() -> None: - self._save_state() - ba.containerwidget(edit=self._root_widget, transition='out_left') - ba.app.ui.set_main_menu_window( - SelectGameWindow().get_root_widget()) - - self._quick_game_button = ba.buttonwidget( - parent=self._root_widget, - position=(width - 55 - 120, height - 132), - autoselect=True, - size=(120, 60), - scale=1.1, - text_scale=1.2, - label=custom_txt, - on_activate_call=do_quick_game, - color=(0.54, 0.52, 0.67), - textcolor=(0.7, 0.65, 0.7)) - - self._restore_state() - - -def states(self) -> None: - return { - 'Team Games': self._teams_button, - 'Co-op Games': self._coop_button, - 'Free-for-All Games': self._free_for_all_button, - 'Back': self._back_button, - 'Quick Game': self._quick_game_button - } - - -def _save_state(self) -> None: - swapped = {v: k for k, v in states(self).items()} - if self._root_widget.get_selected_child() in swapped: - ba.app.ui.window_states[ - self.__class__.__name__] = swapped[ - self._root_widget.get_selected_child()] - else: - ba.print_exception(f'Error saving state for {self}.') - - -def _restore_state(self) -> None: - if not hasattr(self, '_quick_game_button'): - return # ensure that our monkey patched init ran - if self.__class__.__name__ not in ba.app.ui.window_states: - ba.containerwidget(edit=self._root_widget, - selected_child=self._coop_button) - return - sel = states(self).get( - ba.app.ui.window_states[self.__class__.__name__], None) - if sel: - ba.containerwidget(edit=self._root_widget, selected_child=sel) - else: - ba.containerwidget(edit=self._root_widget, - selected_child=self._coop_button) - ba.print_exception(f'Error restoring state for {self}.') - - -# ba_meta export plugin -class QuickGamePlugin(ba.Plugin): - PlayWindow.__init__ = __init__ - PlayWindow._save_state = _save_state - PlayWindow._restore_state = _restore_state From ba47887e8b4d360a41569b3a0978c7bb7d85d1ab Mon Sep 17 00:00:00 2001 From: Loup <90267658+Loup-Garou911XD@users.noreply.github.com> Date: Mon, 7 Nov 2022 00:23:37 +0530 Subject: [PATCH 29/55] Delete RandomColors.py --- plugins/utilities/RandomColors.py | 48 ------------------------------- 1 file changed, 48 deletions(-) delete mode 100644 plugins/utilities/RandomColors.py diff --git a/plugins/utilities/RandomColors.py b/plugins/utilities/RandomColors.py deleted file mode 100644 index 3ea0ba6..0000000 --- a/plugins/utilities/RandomColors.py +++ /dev/null @@ -1,48 +0,0 @@ -# ba_meta require api 7 -# (see https://ballistica.net/wiki/meta-tag-system) - -from __future__ import annotations - -from typing import TYPE_CHECKING - -import ba -import random -from bastd.actor import bomb - -if TYPE_CHECKING: - from typing import Sequence - - -class NewBlast(bomb.Blast): - def __init__( - self, - position: Sequence[float] = (0.0, 1.0, 0.0), - velocity: Sequence[float] = (0.0, 0.0, 0.0), - blast_radius: float = 2.0, - blast_type: str = 'normal', - source_player: ba.Player | None = None, - hit_type: str = 'explosion', - hit_subtype: str = 'normal', - ): - super().__init__(position, velocity, blast_radius, blast_type, - source_player, hit_type, hit_subtype) - scorch_radius = light_radius = self.radius - if self.blast_type == 'tnt': - scorch_radius *= 1.15 - scorch = ba.newnode( - 'scorch', - attrs={ - 'position': position, - 'size': scorch_radius * 0.5, - 'big': (self.blast_type == 'tnt'), - }, - ) - random_color = (random.random(), random.random(), random.random()) - scorch.color = ba.safecolor(random_color) - ba.animate(scorch, 'presence', {3.000: 1, 13.000: 0}) - ba.timer(13.0, scorch.delete) - - -# ba_meta export plugin -class RandomColorsPlugin(ba.Plugin): - bomb.Blast = NewBlast From 7c52e529443ba914515c33d42d4ec34e40c39cad Mon Sep 17 00:00:00 2001 From: Loup <90267658+Loup-Garou911XD@users.noreply.github.com> Date: Mon, 7 Nov 2022 00:26:16 +0530 Subject: [PATCH 30/55] Add files via upload --- plugins/utilities/share_replay.py | 186 ++++++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 plugins/utilities/share_replay.py diff --git a/plugins/utilities/share_replay.py b/plugins/utilities/share_replay.py new file mode 100644 index 0000000..584803f --- /dev/null +++ b/plugins/utilities/share_replay.py @@ -0,0 +1,186 @@ +# ba_meta require api 7 +from __future__ import annotations +from typing import TYPE_CHECKING, cast +if TYPE_CHECKING: + from typing import Any, Sequence, Callable, List, Dict, Tuple, Optional, Union + +from os import listdir,mkdir +from shutil import copy,copytree +import ba +import _ba +from bastd.ui.watch import WatchWindow as ww +from bastd.ui.popup import PopupWindow + +#mod by ʟօʊքɢǟʀօʊ +#export replays to mods folder and share with your friends or have a backup + +def Print(*args,color=None,top=None): + out="" + for arg in args: + a=str(arg) + out += a + ba.screenmessage(out,color=color,top=top) + +def cprint(*args): + out="" + for arg in args: + a=str(arg) + out += a + _ba.chatmessage(out) + +internal_dir="/data/data/net.froemling.bombsquad/files/bombsquad_config/replays" +external_dir="/storage/emulated/0/Android/data/net.froemling.bombsquad/files/mods/replays" +#colors +pink=(1,0.2,0.8) +green=(0.4,1,0.4) +red=(1,0,0) + +try: + mkdir(external_dir) + Print("You are ready to share replays",color=pink) +except FileExistsError: + pass + +class Help(PopupWindow): + def __init__(self): + uiscale = ba.app.ui.uiscale + self.width = 800 + self.height = 300 + + PopupWindow.__init__(self, + position=(0.0, 0.0), + size=(self.width, self.height), + scale=1.2,) + + ba.containerwidget(edit=self.root_widget,on_outside_click_call=self.close) + ba.textwidget(parent=self.root_widget,position=(0 , self.height * 0.6), text=f"•Replays are exported to\n {external_dir}\n•Importing replay and other features comming in v1.2") + + def close(self): + ba.playsound(ba.getsound('swish')) + ba.containerwidget(edit=self.root_widget, transition="out_right",) + + +class SettingWindow(): + def __init__(self): + self.draw_ui() + self.selected_widget = None + self.selected_name= None + + def on_select_text(self,widget,name): + if self.selected_widget is not None: + ba.textwidget(edit=self.selected_widget,color=(1,1,1)) + ba.textwidget(edit=widget,color=(1,1,0)) + self.selected_name = name + self.selected_widget = widget + + def draw_ui(self): + self.uiscale = ba.app.ui.uiscale + self.root=ba.Window(ba.containerwidget(size=(900, 670),on_outside_click_call=self.close,transition="in_right")).get_root_widget() + + ba.textwidget( + parent=self.root, + size=(200, 100), + position=(150, 550), + scale=2, + selectable=False, + h_align="center", + v_align="center", + text="ShareReplay", + color=green) + + ba.buttonwidget( + parent=self.root, + position=(400,580), + size=(35,35), + label="Help", + on_activate_call=Help) + + ba.buttonwidget( + parent=self.root, + position=(770, 460), + size=(90, 70), + scale=1.5, + label="EXPORT", + on_activate_call=self.export) + + self.close_button = ba.buttonwidget( + parent=self.root, + position=(820, 590), + size=(35, 35), + icon=ba.gettexture("crossOut"), + icon_color=(1, 0.2, 0.2), + scale=2, + color=(1, 0.2, 0.2), + extra_touch_border_scale=3, + on_activate_call=self.close) + + scroll=ba.scrollwidget( + parent=self.root, + size=(500,400), + position=(200,150)) + self.scroll=ba.columnwidget(parent=scroll,size=(500,900),selection_loops_to_parent=True,single_depth=True) + + height=900 + for i in listdir(internal_dir): + height-=40 + a=i + i = ba.textwidget( + parent=self.scroll, + size=(500,50), + text= i.split(".")[0], + position=(10,height), + selectable=True, + max_chars=40, + click_activate=True,) + + ba.textwidget(edit=i,on_activate_call=ba.Call(self.on_select_text,i,a)) + + + def export(self): + if self.selected_name is None: + Print("Select a replay",color=red) + return + copy(internal_dir+"/"+self.selected_name,external_dir+"/"+self.selected_name) + Print(self.selected_name[0:-4]+" exported", top=True,color=pink)#image={"texture":ba.gettexture("bombColor"),"tint_texture":None,"tint_color":None,"tint2_color":None}) + + def close(self): + ba.playsound(ba.getsound('swish')) + ba.containerwidget(edit=self.root, transition="out_right",) + + +# ++++++++++++++++for keyboard navigation++++++++++++++++ + + #ba.widget(edit=self.enable_button, up_widget=decrease_button, down_widget=self.lower_text,left_widget=save_button, right_widget=save_button) + +# -------------------------------------------------------------------------------------------------- + +ww.__old_init__=ww.__init__ + +def new_init(self,transition="in_right",origin_widget=None): + self.__old_init__(transition,origin_widget) + self._share_button = ba.buttonwidget( + parent=self._root_widget, + position=(self._width*0.70, self._height*0.80), + size=(220, 60), + scale=1.0, + color=green, + icon=ba.gettexture('usersButton'), + iconscale=1.5, + label="SHARE REPLAY", + on_activate_call=SettingWindow) + + +# ba_meta export plugin + +class main(ba.Plugin): + def on_app_running(self): + + ww.__init__=new_init + + def has_settings_ui(self): + return True + + def show_settings_ui(self,button): + SettingWindow() + + \ No newline at end of file From 32c6b8361ce61903423c2d334f2f58de3962182d Mon Sep 17 00:00:00 2001 From: Loup-Garou911XD Date: Sun, 6 Nov 2022 18:56:47 +0000 Subject: [PATCH 31/55] [ci] auto-format --- plugins/utilities/share_replay.py | 158 ++++++++++++++++-------------- 1 file changed, 82 insertions(+), 76 deletions(-) diff --git a/plugins/utilities/share_replay.py b/plugins/utilities/share_replay.py index 584803f..61a0029 100644 --- a/plugins/utilities/share_replay.py +++ b/plugins/utilities/share_replay.py @@ -3,58 +3,63 @@ from __future__ import annotations from typing import TYPE_CHECKING, cast if TYPE_CHECKING: from typing import Any, Sequence, Callable, List, Dict, Tuple, Optional, Union - -from os import listdir,mkdir -from shutil import copy,copytree + +from os import listdir, mkdir +from shutil import copy, copytree import ba import _ba from bastd.ui.watch import WatchWindow as ww from bastd.ui.popup import PopupWindow -#mod by ʟօʊքɢǟʀօʊ -#export replays to mods folder and share with your friends or have a backup +# mod by ʟօʊքɢǟʀօʊ +# export replays to mods folder and share with your friends or have a backup -def Print(*args,color=None,top=None): - out="" + +def Print(*args, color=None, top=None): + out = "" for arg in args: - a=str(arg) + a = str(arg) out += a - ba.screenmessage(out,color=color,top=top) + ba.screenmessage(out, color=color, top=top) + def cprint(*args): - out="" + out = "" for arg in args: - a=str(arg) + a = str(arg) out += a _ba.chatmessage(out) - -internal_dir="/data/data/net.froemling.bombsquad/files/bombsquad_config/replays" -external_dir="/storage/emulated/0/Android/data/net.froemling.bombsquad/files/mods/replays" -#colors -pink=(1,0.2,0.8) -green=(0.4,1,0.4) -red=(1,0,0) + + +internal_dir = "/data/data/net.froemling.bombsquad/files/bombsquad_config/replays" +external_dir = "/storage/emulated/0/Android/data/net.froemling.bombsquad/files/mods/replays" +# colors +pink = (1, 0.2, 0.8) +green = (0.4, 1, 0.4) +red = (1, 0, 0) try: mkdir(external_dir) - Print("You are ready to share replays",color=pink) + Print("You are ready to share replays", color=pink) except FileExistsError: pass - + + class Help(PopupWindow): def __init__(self): uiscale = ba.app.ui.uiscale self.width = 800 self.height = 300 - + PopupWindow.__init__(self, position=(0.0, 0.0), size=(self.width, self.height), scale=1.2,) - - ba.containerwidget(edit=self.root_widget,on_outside_click_call=self.close) - ba.textwidget(parent=self.root_widget,position=(0 , self.height * 0.6), text=f"•Replays are exported to\n {external_dir}\n•Importing replay and other features comming in v1.2") - + + ba.containerwidget(edit=self.root_widget, on_outside_click_call=self.close) + ba.textwidget(parent=self.root_widget, position=(0, self.height * 0.6), + text=f"•Replays are exported to\n {external_dir}\n•Importing replay and other features comming in v1.2") + def close(self): ba.playsound(ba.getsound('swish')) ba.containerwidget(edit=self.root_widget, transition="out_right",) @@ -64,18 +69,19 @@ class SettingWindow(): def __init__(self): self.draw_ui() self.selected_widget = None - self.selected_name= None - - def on_select_text(self,widget,name): - if self.selected_widget is not None: - ba.textwidget(edit=self.selected_widget,color=(1,1,1)) - ba.textwidget(edit=widget,color=(1,1,0)) + self.selected_name = None + + def on_select_text(self, widget, name): + if self.selected_widget is not None: + ba.textwidget(edit=self.selected_widget, color=(1, 1, 1)) + ba.textwidget(edit=widget, color=(1, 1, 0)) self.selected_name = name self.selected_widget = widget - + def draw_ui(self): self.uiscale = ba.app.ui.uiscale - self.root=ba.Window(ba.containerwidget(size=(900, 670),on_outside_click_call=self.close,transition="in_right")).get_root_widget() + self.root = ba.Window(ba.containerwidget( + size=(900, 670), on_outside_click_call=self.close, transition="in_right")).get_root_widget() ba.textwidget( parent=self.root, @@ -87,14 +93,14 @@ class SettingWindow(): v_align="center", text="ShareReplay", color=green) - + ba.buttonwidget( parent=self.root, - position=(400,580), - size=(35,35), + position=(400, 580), + size=(35, 35), label="Help", on_activate_call=Help) - + ba.buttonwidget( parent=self.root, position=(770, 460), @@ -102,7 +108,7 @@ class SettingWindow(): scale=1.5, label="EXPORT", on_activate_call=self.export) - + self.close_button = ba.buttonwidget( parent=self.root, position=(820, 590), @@ -113,51 +119,53 @@ class SettingWindow(): color=(1, 0.2, 0.2), extra_touch_border_scale=3, on_activate_call=self.close) - - scroll=ba.scrollwidget( + + scroll = ba.scrollwidget( parent=self.root, - size=(500,400), - position=(200,150)) - self.scroll=ba.columnwidget(parent=scroll,size=(500,900),selection_loops_to_parent=True,single_depth=True) - - height=900 + size=(500, 400), + position=(200, 150)) + self.scroll = ba.columnwidget(parent=scroll, size=( + 500, 900), selection_loops_to_parent=True, single_depth=True) + + height = 900 for i in listdir(internal_dir): - height-=40 - a=i + height -= 40 + a = i i = ba.textwidget( - parent=self.scroll, - size=(500,50), - text= i.split(".")[0], - position=(10,height), + parent=self.scroll, + size=(500, 50), + text=i.split(".")[0], + position=(10, height), selectable=True, max_chars=40, click_activate=True,) - - ba.textwidget(edit=i,on_activate_call=ba.Call(self.on_select_text,i,a)) - - + + ba.textwidget(edit=i, on_activate_call=ba.Call(self.on_select_text, i, a)) + def export(self): - if self.selected_name is None: - Print("Select a replay",color=red) - return - copy(internal_dir+"/"+self.selected_name,external_dir+"/"+self.selected_name) - Print(self.selected_name[0:-4]+" exported", top=True,color=pink)#image={"texture":ba.gettexture("bombColor"),"tint_texture":None,"tint_color":None,"tint2_color":None}) - + if self.selected_name is None: + Print("Select a replay", color=red) + return + copy(internal_dir+"/"+self.selected_name, external_dir+"/"+self.selected_name) + # image={"texture":ba.gettexture("bombColor"),"tint_texture":None,"tint_color":None,"tint2_color":None}) + Print(self.selected_name[0:-4]+" exported", top=True, color=pink) + def close(self): ba.playsound(ba.getsound('swish')) - ba.containerwidget(edit=self.root, transition="out_right",) - + ba.containerwidget(edit=self.root, transition="out_right",) + # ++++++++++++++++for keyboard navigation++++++++++++++++ - #ba.widget(edit=self.enable_button, up_widget=decrease_button, down_widget=self.lower_text,left_widget=save_button, right_widget=save_button) + #ba.widget(edit=self.enable_button, up_widget=decrease_button, down_widget=self.lower_text,left_widget=save_button, right_widget=save_button) # -------------------------------------------------------------------------------------------------- -ww.__old_init__=ww.__init__ +ww.__old_init__ = ww.__init__ -def new_init(self,transition="in_right",origin_widget=None): - self.__old_init__(transition,origin_widget) + +def new_init(self, transition="in_right", origin_widget=None): + self.__old_init__(transition, origin_widget) self._share_button = ba.buttonwidget( parent=self._root_widget, position=(self._width*0.70, self._height*0.80), @@ -168,19 +176,17 @@ def new_init(self,transition="in_right",origin_widget=None): iconscale=1.5, label="SHARE REPLAY", on_activate_call=SettingWindow) - - + + # ba_meta export plugin class main(ba.Plugin): def on_app_running(self): - - ww.__init__=new_init - + + ww.__init__ = new_init + def has_settings_ui(self): return True - - def show_settings_ui(self,button): + + def show_settings_ui(self, button): SettingWindow() - - \ No newline at end of file From fbb965d0ac22633186bc3d2bae39c141900240a6 Mon Sep 17 00:00:00 2001 From: Loup-Garou911XD Date: Sun, 6 Nov 2022 18:56:49 +0000 Subject: [PATCH 32/55] [ci] apply-version-metadata --- plugins/utilities.json | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/plugins/utilities.json b/plugins/utilities.json index 9b67e84..3643231 100644 --- a/plugins/utilities.json +++ b/plugins/utilities.json @@ -14,7 +14,12 @@ } ], "versions": { - "1.0.0":null + "1.0.0": { + "api_version": 7, + "commit_sha": "32c6b83", + "released_on": "06-11-2022", + "md5sum": "b652c675e61332a9e7714342ee83bfce" + } } }, "custom_death": { @@ -424,4 +429,4 @@ } } } -} +} \ No newline at end of file From 34bbd7c8db653159e4e5dc11469ec288aa9d2a24 Mon Sep 17 00:00:00 2001 From: Loup <90267658+Loup-Garou911XD@users.noreply.github.com> Date: Mon, 7 Nov 2022 00:30:48 +0530 Subject: [PATCH 33/55] Rename MeteorShower.py to meteor_shower.py --- plugins/minigames/{MeteorShower.py => meteor_shower.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename plugins/minigames/{MeteorShower.py => meteor_shower.py} (100%) diff --git a/plugins/minigames/MeteorShower.py b/plugins/minigames/meteor_shower.py similarity index 100% rename from plugins/minigames/MeteorShower.py rename to plugins/minigames/meteor_shower.py From 3901d684043b67bc4ef1aa657839b8f0ef56fc23 Mon Sep 17 00:00:00 2001 From: Loup <90267658+Loup-Garou911XD@users.noreply.github.com> Date: Mon, 7 Nov 2022 00:34:27 +0530 Subject: [PATCH 34/55] Rename ZombieHorde.py to zombie_horde.py --- plugins/minigames/{ZombieHorde.py => zombie_horde.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename plugins/minigames/{ZombieHorde.py => zombie_horde.py} (100%) diff --git a/plugins/minigames/ZombieHorde.py b/plugins/minigames/zombie_horde.py similarity index 100% rename from plugins/minigames/ZombieHorde.py rename to plugins/minigames/zombie_horde.py From faba93cfe1bd531bf35707691e33b3040878592a Mon Sep 17 00:00:00 2001 From: Loup <90267658+Loup-Garou911XD@users.noreply.github.com> Date: Mon, 7 Nov 2022 00:35:20 +0530 Subject: [PATCH 35/55] Rename SquidRace.py to squid_race.py --- plugins/minigames/{SquidRace.py => squid_race.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename plugins/minigames/{SquidRace.py => squid_race.py} (100%) diff --git a/plugins/minigames/SquidRace.py b/plugins/minigames/squid_race.py similarity index 100% rename from plugins/minigames/SquidRace.py rename to plugins/minigames/squid_race.py From 3dc9404e58c26315dd62f6404e31b46c372db252 Mon Sep 17 00:00:00 2001 From: Loup <90267658+Loup-Garou911XD@users.noreply.github.com> Date: Mon, 7 Nov 2022 00:36:04 +0530 Subject: [PATCH 36/55] Rename SimonSays.py to simon_says.py --- plugins/minigames/{SimonSays.py => simon_says.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename plugins/minigames/{SimonSays.py => simon_says.py} (100%) diff --git a/plugins/minigames/SimonSays.py b/plugins/minigames/simon_says.py similarity index 100% rename from plugins/minigames/SimonSays.py rename to plugins/minigames/simon_says.py From b2028d6e31c9d75637b28037b1213f8c6b602e8d Mon Sep 17 00:00:00 2001 From: Loup <90267658+Loup-Garou911XD@users.noreply.github.com> Date: Mon, 7 Nov 2022 00:36:47 +0530 Subject: [PATCH 37/55] Rename Boxing.py to boxing.py --- plugins/minigames/{Boxing.py => boxing.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename plugins/minigames/{Boxing.py => boxing.py} (100%) diff --git a/plugins/minigames/Boxing.py b/plugins/minigames/boxing.py similarity index 100% rename from plugins/minigames/Boxing.py rename to plugins/minigames/boxing.py From 6f33276807595c9221c8438facba78fd53ba09e4 Mon Sep 17 00:00:00 2001 From: Loup <90267658+Loup-Garou911XD@users.noreply.github.com> Date: Mon, 7 Nov 2022 00:37:24 +0530 Subject: [PATCH 38/55] Rename BasketBomb.py to basket_bomb.py --- plugins/minigames/{BasketBomb.py => basket_bomb.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename plugins/minigames/{BasketBomb.py => basket_bomb.py} (100%) diff --git a/plugins/minigames/BasketBomb.py b/plugins/minigames/basket_bomb.py similarity index 100% rename from plugins/minigames/BasketBomb.py rename to plugins/minigames/basket_bomb.py From e3d7d310fa07a1ae817e6e940030e29aa1d3d086 Mon Sep 17 00:00:00 2001 From: Loup <90267658+Loup-Garou911XD@users.noreply.github.com> Date: Mon, 7 Nov 2022 00:39:40 +0530 Subject: [PATCH 39/55] Update minigames.json --- plugins/minigames.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/plugins/minigames.json b/plugins/minigames.json index 7b01656..7136458 100644 --- a/plugins/minigames.json +++ b/plugins/minigames.json @@ -22,7 +22,7 @@ } } }, - "SimonSays": { + "simon_says": { "description": "You better do what Simon says", "external_url": "", "authors": [ @@ -41,7 +41,7 @@ } } }, - "SquidRace": { + "squid_race": { "description": "Race inspired by the squid games", "external_url": "https://youtube.com/c/JoseANG3LYT", "authors": [ @@ -60,7 +60,7 @@ } } }, - "ZombieHorde": { + "zombie_horde": { "description": "Fight or defend against horde of zombies", "external_url": "https://youtube.com/c/JoseANG3LYT", "authors": [ @@ -79,7 +79,7 @@ } } }, - "MeteorShower": { + "meteor_shower": { "description": "MeteorShower with many different bombs", "external_url": "https://youtube.com/c/JoseANG3LYT", "authors": [ @@ -98,7 +98,7 @@ } } }, - "Boxing": { + "boxing": { "description": "Simple boxing minigame", "external_url": "https://youtube.com/c/JoseANG3LYT", "authors": [ @@ -117,7 +117,7 @@ } } }, - "BasketBomb": { + "basket_bomb": { "description": "Score all the baskets and be the MVP.", "external_url": "", "authors": [ @@ -232,4 +232,4 @@ } } } -} \ No newline at end of file +} From 56c5e0dca6412120eb54d440c99d88c070d6892b Mon Sep 17 00:00:00 2001 From: Loup-Garou911XD Date: Sun, 6 Nov 2022 19:10:08 +0000 Subject: [PATCH 40/55] [ci] apply-version-metadata --- plugins/minigames.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/minigames.json b/plugins/minigames.json index 7136458..3dc129e 100644 --- a/plugins/minigames.json +++ b/plugins/minigames.json @@ -232,4 +232,4 @@ } } } -} +} \ No newline at end of file From 23eb66093cfa8e00a1a6509af2c1d08bfa15a942 Mon Sep 17 00:00:00 2001 From: Loup <90267658+Loup-Garou911XD@users.noreply.github.com> Date: Mon, 7 Nov 2022 01:18:24 +0530 Subject: [PATCH 41/55] Update utilities.json --- plugins/utilities.json | 57 ++++++------------------------------------ 1 file changed, 8 insertions(+), 49 deletions(-) diff --git a/plugins/utilities.json b/plugins/utilities.json index 3643231..5336f99 100644 --- a/plugins/utilities.json +++ b/plugins/utilities.json @@ -14,12 +14,7 @@ } ], "versions": { - "1.0.0": { - "api_version": 7, - "commit_sha": "32c6b83", - "released_on": "06-11-2022", - "md5sum": "b652c675e61332a9e7714342ee83bfce" - } + "1.0.0":null } }, "custom_death": { @@ -33,12 +28,7 @@ } ], "versions": { - "1.0.0": { - "api_version": 7, - "commit_sha": "7d3d117", - "released_on": "03-11-2022", - "md5sum": "7b1941512532321eec18140087569215" - } + "1.0.0":null } }, "max_players": { @@ -52,12 +42,7 @@ } ], "versions": { - "1.0.0": { - "api_version": 7, - "commit_sha": "7d3d117", - "released_on": "03-11-2022", - "md5sum": "f5e129f009e9732b3179c7edaf75478e" - } + "1.0.0":null } }, "quick_custom_game": { @@ -71,12 +56,7 @@ } ], "versions": { - "1.0.0": { - "api_version": 7, - "commit_sha": "7d3d117", - "released_on": "03-11-2022", - "md5sum": "b691e35afb17cd3b5f6fe21c0194567d" - } + "1.0.0":null } }, "random_colors": { @@ -90,12 +70,7 @@ } ], "versions": { - "1.0.0": { - "api_version": 7, - "commit_sha": "7d3d117", - "released_on": "03-11-2022", - "md5sum": "0c351a0aebed77c3771053cde0c18d7b" - } + "1.0.0":null } }, "chat_cmd": { @@ -114,12 +89,7 @@ } ], "versions": { - "1.0.0": { - "api_version": 7, - "commit_sha": "7d3d117", - "released_on": "03-11-2022", - "md5sum": "c84d9a1c9e63e77949134020e1f11834" - } + "1.0.0":null } }, "mood_light": { @@ -133,18 +103,7 @@ } ], "versions": { - "1.2.2": { - "api_version": 7, - "commit_sha": "490b857", - "released_on": "04-11-2022", - "md5sum": "cb367f877d6360a0e41941b1d0396a9b" - }, - "1.2.1": { - "api_version": 7, - "commit_sha": "1a56b57", - "released_on": "28-10-2022", - "md5sum": "81414a2b497da3d2340a4d7eb004336c" - }, + "1.2.1":null "1.2.0": { "api_version": 7, "commit_sha": "d838115", @@ -429,4 +388,4 @@ } } } -} \ No newline at end of file +} From e7d612d0bf72ff57e91fdc1b5fd1e7798b8f0b2c Mon Sep 17 00:00:00 2001 From: Loup <90267658+Loup-Garou911XD@users.noreply.github.com> Date: Mon, 7 Nov 2022 01:21:10 +0530 Subject: [PATCH 42/55] Update minigames.json --- plugins/minigames.json | 44 +++++++----------------------------------- 1 file changed, 7 insertions(+), 37 deletions(-) diff --git a/plugins/minigames.json b/plugins/minigames.json index 3dc129e..3fd3023 100644 --- a/plugins/minigames.json +++ b/plugins/minigames.json @@ -33,12 +33,7 @@ } ], "versions": { - "1.0.0": { - "api_version": 7, - "commit_sha": "7d3d117", - "released_on": "03-11-2022", - "md5sum": "def39482b339095a7affb574af829ea0" - } + "1.0.0":null } }, "squid_race": { @@ -52,12 +47,7 @@ } ], "versions": { - "1.0.0": { - "api_version": 7, - "commit_sha": "7d3d117", - "released_on": "03-11-2022", - "md5sum": "7ec43481e6b35b4da4f6425977ee0004" - } + "1.0.0":null } }, "zombie_horde": { @@ -71,12 +61,7 @@ } ], "versions": { - "1.0.0": { - "api_version": 7, - "commit_sha": "7d3d117", - "released_on": "03-11-2022", - "md5sum": "671e7b98a9d3eb0aeb7e47448db25af9" - } + "1.0.0":null } }, "meteor_shower": { @@ -90,12 +75,7 @@ } ], "versions": { - "1.0.0": { - "api_version": 7, - "commit_sha": "7d3d117", - "released_on": "03-11-2022", - "md5sum": "1ce8c1a3f3ec240af39b7a73375e7891" - } + "1.0.0":null } }, "boxing": { @@ -109,12 +89,7 @@ } ], "versions": { - "1.0.0": { - "api_version": 7, - "commit_sha": "7d3d117", - "released_on": "03-11-2022", - "md5sum": "c1b615df09886ba05622c4e8b4f6be40" - } + "1.0.0":null } }, "basket_bomb": { @@ -128,12 +103,7 @@ } ], "versions": { - "1.0.0": { - "api_version": 7, - "commit_sha": "7d3d117", - "released_on": "03-11-2022", - "md5sum": "7ec87edbdd5183ec4b2daffad0019820" - } + "1.0.0":null } }, "ultimate_last_stand": { @@ -232,4 +202,4 @@ } } } -} \ No newline at end of file +} From ef99b13364f6bf8f353694e16a96f6390c020d2c Mon Sep 17 00:00:00 2001 From: Loup <90267658+Loup-Garou911XD@users.noreply.github.com> Date: Mon, 7 Nov 2022 02:53:57 +0530 Subject: [PATCH 43/55] Add files via upload --- plugins/utilities/share_replay.py | 162 ++++++++++++++---------------- 1 file changed, 78 insertions(+), 84 deletions(-) diff --git a/plugins/utilities/share_replay.py b/plugins/utilities/share_replay.py index 61a0029..fb49c40 100644 --- a/plugins/utilities/share_replay.py +++ b/plugins/utilities/share_replay.py @@ -3,63 +3,58 @@ from __future__ import annotations from typing import TYPE_CHECKING, cast if TYPE_CHECKING: from typing import Any, Sequence, Callable, List, Dict, Tuple, Optional, Union - -from os import listdir, mkdir -from shutil import copy, copytree + +from os import listdir,mkdir +from shutil import copy,copytree import ba import _ba from bastd.ui.watch import WatchWindow as ww from bastd.ui.popup import PopupWindow -# mod by ʟօʊքɢǟʀօʊ -# export replays to mods folder and share with your friends or have a backup +#mod by ʟօʊքɢǟʀօʊ +#export replays to mods folder and share with your friends or have a backup - -def Print(*args, color=None, top=None): - out = "" +def Print(*args,color=None,top=None): + out="" for arg in args: - a = str(arg) + a=str(arg) out += a - ba.screenmessage(out, color=color, top=top) - + ba.screenmessage(out,color=color,top=top) def cprint(*args): - out = "" + out="" for arg in args: - a = str(arg) + a=str(arg) out += a _ba.chatmessage(out) - - -internal_dir = "/data/data/net.froemling.bombsquad/files/bombsquad_config/replays" -external_dir = "/storage/emulated/0/Android/data/net.froemling.bombsquad/files/mods/replays" -# colors -pink = (1, 0.2, 0.8) -green = (0.4, 1, 0.4) -red = (1, 0, 0) + +internal_dir="/data/data/net.froemling.bombsquad/files/bombsquad_config/replays" +external_dir="/storage/emulated/0/Android/data/net.froemling.bombsquad/files/mods/replays" +#colors +pink=(1,0.2,0.8) +green=(0.4,1,0.4) +red=(1,0,0) try: mkdir(external_dir) - Print("You are ready to share replays", color=pink) + Print("You are ready to share replays",color=pink) except FileExistsError: pass - - + class Help(PopupWindow): def __init__(self): uiscale = ba.app.ui.uiscale self.width = 800 self.height = 300 - + PopupWindow.__init__(self, position=(0.0, 0.0), size=(self.width, self.height), scale=1.2,) - - ba.containerwidget(edit=self.root_widget, on_outside_click_call=self.close) - ba.textwidget(parent=self.root_widget, position=(0, self.height * 0.6), - text=f"•Replays are exported to\n {external_dir}\n•Importing replay and other features comming in v1.2") - + + ba.containerwidget(edit=self.root_widget,on_outside_click_call=self.close) + ba.textwidget(parent=self.root_widget,position=(0 , self.height * 0.6), text=f"•Replays are exported to\n {external_dir}\n•Importing replay and other features comming in v1.2") + def close(self): ba.playsound(ba.getsound('swish')) ba.containerwidget(edit=self.root_widget, transition="out_right",) @@ -69,19 +64,18 @@ class SettingWindow(): def __init__(self): self.draw_ui() self.selected_widget = None - self.selected_name = None - - def on_select_text(self, widget, name): - if self.selected_widget is not None: - ba.textwidget(edit=self.selected_widget, color=(1, 1, 1)) - ba.textwidget(edit=widget, color=(1, 1, 0)) + self.selected_name= None + + def on_select_text(self,widget,name): + if self.selected_widget is not None: + ba.textwidget(edit=self.selected_widget,color=(1,1,1)) + ba.textwidget(edit=widget,color=(1,1,0)) self.selected_name = name self.selected_widget = widget - + def draw_ui(self): self.uiscale = ba.app.ui.uiscale - self.root = ba.Window(ba.containerwidget( - size=(900, 670), on_outside_click_call=self.close, transition="in_right")).get_root_widget() + self.root=ba.Window(ba.containerwidget(size=(900, 670),on_outside_click_call=self.close,transition="in_right")).get_root_widget() ba.textwidget( parent=self.root, @@ -93,14 +87,14 @@ class SettingWindow(): v_align="center", text="ShareReplay", color=green) - + ba.buttonwidget( parent=self.root, - position=(400, 580), - size=(35, 35), + position=(400,580), + size=(35,35), label="Help", on_activate_call=Help) - + ba.buttonwidget( parent=self.root, position=(770, 460), @@ -108,64 +102,62 @@ class SettingWindow(): scale=1.5, label="EXPORT", on_activate_call=self.export) - + self.close_button = ba.buttonwidget( parent=self.root, position=(820, 590), size=(35, 35), - icon=ba.gettexture("crossOut"), - icon_color=(1, 0.2, 0.2), + texture=ba.gettexture("crossOut"), + label="", scale=2, color=(1, 0.2, 0.2), extra_touch_border_scale=3, on_activate_call=self.close) - - scroll = ba.scrollwidget( + + scroll=ba.scrollwidget( parent=self.root, - size=(500, 400), - position=(200, 150)) - self.scroll = ba.columnwidget(parent=scroll, size=( - 500, 900), selection_loops_to_parent=True, single_depth=True) - - height = 900 + size=(500,400), + position=(200,150)) + self.scroll=ba.columnwidget(parent=scroll,size=(500,900),selection_loops_to_parent=True,single_depth=True) + + height=900 for i in listdir(internal_dir): - height -= 40 - a = i + height-=40 + a=i i = ba.textwidget( - parent=self.scroll, - size=(500, 50), - text=i.split(".")[0], - position=(10, height), + parent=self.scroll, + size=(500,50), + text= i.split(".")[0], + position=(10,height), selectable=True, max_chars=40, click_activate=True,) - - ba.textwidget(edit=i, on_activate_call=ba.Call(self.on_select_text, i, a)) - + + ba.textwidget(edit=i,on_activate_call=ba.Call(self.on_select_text,i,a)) + + def export(self): - if self.selected_name is None: - Print("Select a replay", color=red) - return - copy(internal_dir+"/"+self.selected_name, external_dir+"/"+self.selected_name) - # image={"texture":ba.gettexture("bombColor"),"tint_texture":None,"tint_color":None,"tint2_color":None}) - Print(self.selected_name[0:-4]+" exported", top=True, color=pink) - + if self.selected_name is None: + Print("Select a replay",color=red) + return + copy(internal_dir+"/"+self.selected_name,external_dir+"/"+self.selected_name) + Print(self.selected_name[0:-4]+" exported", top=True,color=pink)#image={"texture":ba.gettexture("bombColor"),"tint_texture":None,"tint_color":None,"tint2_color":None}) + def close(self): ba.playsound(ba.getsound('swish')) - ba.containerwidget(edit=self.root, transition="out_right",) - + ba.containerwidget(edit=self.root, transition="out_right",) + # ++++++++++++++++for keyboard navigation++++++++++++++++ - #ba.widget(edit=self.enable_button, up_widget=decrease_button, down_widget=self.lower_text,left_widget=save_button, right_widget=save_button) + #ba.widget(edit=self.enable_button, up_widget=decrease_button, down_widget=self.lower_text,left_widget=save_button, right_widget=save_button) # -------------------------------------------------------------------------------------------------- -ww.__old_init__ = ww.__init__ +ww.__old_init__=ww.__init__ - -def new_init(self, transition="in_right", origin_widget=None): - self.__old_init__(transition, origin_widget) +def new_init(self,transition="in_right",origin_widget=None): + self.__old_init__(transition,origin_widget) self._share_button = ba.buttonwidget( parent=self._root_widget, position=(self._width*0.70, self._height*0.80), @@ -176,17 +168,19 @@ def new_init(self, transition="in_right", origin_widget=None): iconscale=1.5, label="SHARE REPLAY", on_activate_call=SettingWindow) - - + + # ba_meta export plugin class main(ba.Plugin): def on_app_running(self): - - ww.__init__ = new_init - + + ww.__init__=new_init + def has_settings_ui(self): return True - - def show_settings_ui(self, button): + + def show_settings_ui(self,button): SettingWindow() + + \ No newline at end of file From e788b41b740d6fce4eb403c6e81271ee65de05b7 Mon Sep 17 00:00:00 2001 From: Loup-Garou911XD Date: Sun, 6 Nov 2022 21:24:27 +0000 Subject: [PATCH 44/55] [ci] auto-format --- plugins/utilities/share_replay.py | 160 ++++++++++++++++-------------- 1 file changed, 83 insertions(+), 77 deletions(-) diff --git a/plugins/utilities/share_replay.py b/plugins/utilities/share_replay.py index fb49c40..fe66569 100644 --- a/plugins/utilities/share_replay.py +++ b/plugins/utilities/share_replay.py @@ -3,58 +3,63 @@ from __future__ import annotations from typing import TYPE_CHECKING, cast if TYPE_CHECKING: from typing import Any, Sequence, Callable, List, Dict, Tuple, Optional, Union - -from os import listdir,mkdir -from shutil import copy,copytree + +from os import listdir, mkdir +from shutil import copy, copytree import ba import _ba from bastd.ui.watch import WatchWindow as ww from bastd.ui.popup import PopupWindow -#mod by ʟօʊքɢǟʀօʊ -#export replays to mods folder and share with your friends or have a backup +# mod by ʟօʊքɢǟʀօʊ +# export replays to mods folder and share with your friends or have a backup -def Print(*args,color=None,top=None): - out="" + +def Print(*args, color=None, top=None): + out = "" for arg in args: - a=str(arg) + a = str(arg) out += a - ba.screenmessage(out,color=color,top=top) + ba.screenmessage(out, color=color, top=top) + def cprint(*args): - out="" + out = "" for arg in args: - a=str(arg) + a = str(arg) out += a _ba.chatmessage(out) - -internal_dir="/data/data/net.froemling.bombsquad/files/bombsquad_config/replays" -external_dir="/storage/emulated/0/Android/data/net.froemling.bombsquad/files/mods/replays" -#colors -pink=(1,0.2,0.8) -green=(0.4,1,0.4) -red=(1,0,0) + + +internal_dir = "/data/data/net.froemling.bombsquad/files/bombsquad_config/replays" +external_dir = "/storage/emulated/0/Android/data/net.froemling.bombsquad/files/mods/replays" +# colors +pink = (1, 0.2, 0.8) +green = (0.4, 1, 0.4) +red = (1, 0, 0) try: mkdir(external_dir) - Print("You are ready to share replays",color=pink) + Print("You are ready to share replays", color=pink) except FileExistsError: pass - + + class Help(PopupWindow): def __init__(self): uiscale = ba.app.ui.uiscale self.width = 800 self.height = 300 - + PopupWindow.__init__(self, position=(0.0, 0.0), size=(self.width, self.height), scale=1.2,) - - ba.containerwidget(edit=self.root_widget,on_outside_click_call=self.close) - ba.textwidget(parent=self.root_widget,position=(0 , self.height * 0.6), text=f"•Replays are exported to\n {external_dir}\n•Importing replay and other features comming in v1.2") - + + ba.containerwidget(edit=self.root_widget, on_outside_click_call=self.close) + ba.textwidget(parent=self.root_widget, position=(0, self.height * 0.6), + text=f"•Replays are exported to\n {external_dir}\n•Importing replay and other features comming in v1.2") + def close(self): ba.playsound(ba.getsound('swish')) ba.containerwidget(edit=self.root_widget, transition="out_right",) @@ -64,18 +69,19 @@ class SettingWindow(): def __init__(self): self.draw_ui() self.selected_widget = None - self.selected_name= None - - def on_select_text(self,widget,name): - if self.selected_widget is not None: - ba.textwidget(edit=self.selected_widget,color=(1,1,1)) - ba.textwidget(edit=widget,color=(1,1,0)) + self.selected_name = None + + def on_select_text(self, widget, name): + if self.selected_widget is not None: + ba.textwidget(edit=self.selected_widget, color=(1, 1, 1)) + ba.textwidget(edit=widget, color=(1, 1, 0)) self.selected_name = name self.selected_widget = widget - + def draw_ui(self): self.uiscale = ba.app.ui.uiscale - self.root=ba.Window(ba.containerwidget(size=(900, 670),on_outside_click_call=self.close,transition="in_right")).get_root_widget() + self.root = ba.Window(ba.containerwidget( + size=(900, 670), on_outside_click_call=self.close, transition="in_right")).get_root_widget() ba.textwidget( parent=self.root, @@ -87,14 +93,14 @@ class SettingWindow(): v_align="center", text="ShareReplay", color=green) - + ba.buttonwidget( parent=self.root, - position=(400,580), - size=(35,35), + position=(400, 580), + size=(35, 35), label="Help", on_activate_call=Help) - + ba.buttonwidget( parent=self.root, position=(770, 460), @@ -102,62 +108,64 @@ class SettingWindow(): scale=1.5, label="EXPORT", on_activate_call=self.export) - + self.close_button = ba.buttonwidget( parent=self.root, position=(820, 590), size=(35, 35), texture=ba.gettexture("crossOut"), - label="", + label="", scale=2, color=(1, 0.2, 0.2), extra_touch_border_scale=3, on_activate_call=self.close) - - scroll=ba.scrollwidget( + + scroll = ba.scrollwidget( parent=self.root, - size=(500,400), - position=(200,150)) - self.scroll=ba.columnwidget(parent=scroll,size=(500,900),selection_loops_to_parent=True,single_depth=True) - - height=900 + size=(500, 400), + position=(200, 150)) + self.scroll = ba.columnwidget(parent=scroll, size=( + 500, 900), selection_loops_to_parent=True, single_depth=True) + + height = 900 for i in listdir(internal_dir): - height-=40 - a=i + height -= 40 + a = i i = ba.textwidget( - parent=self.scroll, - size=(500,50), - text= i.split(".")[0], - position=(10,height), + parent=self.scroll, + size=(500, 50), + text=i.split(".")[0], + position=(10, height), selectable=True, max_chars=40, click_activate=True,) - - ba.textwidget(edit=i,on_activate_call=ba.Call(self.on_select_text,i,a)) - - + + ba.textwidget(edit=i, on_activate_call=ba.Call(self.on_select_text, i, a)) + def export(self): - if self.selected_name is None: - Print("Select a replay",color=red) - return - copy(internal_dir+"/"+self.selected_name,external_dir+"/"+self.selected_name) - Print(self.selected_name[0:-4]+" exported", top=True,color=pink)#image={"texture":ba.gettexture("bombColor"),"tint_texture":None,"tint_color":None,"tint2_color":None}) - + if self.selected_name is None: + Print("Select a replay", color=red) + return + copy(internal_dir+"/"+self.selected_name, external_dir+"/"+self.selected_name) + # image={"texture":ba.gettexture("bombColor"),"tint_texture":None,"tint_color":None,"tint2_color":None}) + Print(self.selected_name[0:-4]+" exported", top=True, color=pink) + def close(self): ba.playsound(ba.getsound('swish')) - ba.containerwidget(edit=self.root, transition="out_right",) - + ba.containerwidget(edit=self.root, transition="out_right",) + # ++++++++++++++++for keyboard navigation++++++++++++++++ - #ba.widget(edit=self.enable_button, up_widget=decrease_button, down_widget=self.lower_text,left_widget=save_button, right_widget=save_button) + #ba.widget(edit=self.enable_button, up_widget=decrease_button, down_widget=self.lower_text,left_widget=save_button, right_widget=save_button) # -------------------------------------------------------------------------------------------------- -ww.__old_init__=ww.__init__ +ww.__old_init__ = ww.__init__ -def new_init(self,transition="in_right",origin_widget=None): - self.__old_init__(transition,origin_widget) + +def new_init(self, transition="in_right", origin_widget=None): + self.__old_init__(transition, origin_widget) self._share_button = ba.buttonwidget( parent=self._root_widget, position=(self._width*0.70, self._height*0.80), @@ -168,19 +176,17 @@ def new_init(self,transition="in_right",origin_widget=None): iconscale=1.5, label="SHARE REPLAY", on_activate_call=SettingWindow) - - + + # ba_meta export plugin class main(ba.Plugin): def on_app_running(self): - - ww.__init__=new_init - + + ww.__init__ = new_init + def has_settings_ui(self): return True - - def show_settings_ui(self,button): + + def show_settings_ui(self, button): SettingWindow() - - \ No newline at end of file From 5ea82551d15bd952ea02067326eb953900fa7cf7 Mon Sep 17 00:00:00 2001 From: Loup <90267658+Loup-Garou911XD@users.noreply.github.com> Date: Mon, 7 Nov 2022 21:56:22 +0530 Subject: [PATCH 45/55] Fixed utilities.json --- plugins/utilities.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/utilities.json b/plugins/utilities.json index 5336f99..b80c149 100644 --- a/plugins/utilities.json +++ b/plugins/utilities.json @@ -103,7 +103,7 @@ } ], "versions": { - "1.2.1":null + "1.2.1":null, "1.2.0": { "api_version": 7, "commit_sha": "d838115", From 77b702d66f3123b0c32ba9cc9cb4d78270c5a99d Mon Sep 17 00:00:00 2001 From: Loup-Garou911XD Date: Mon, 7 Nov 2022 16:26:45 +0000 Subject: [PATCH 46/55] [ci] apply-version-metadata --- plugins/minigames.json | 44 ++++++++++++++++++++++++++++++------ plugins/utilities.json | 51 +++++++++++++++++++++++++++++++++++------- 2 files changed, 80 insertions(+), 15 deletions(-) diff --git a/plugins/minigames.json b/plugins/minigames.json index 3fd3023..dd9c5a9 100644 --- a/plugins/minigames.json +++ b/plugins/minigames.json @@ -33,7 +33,12 @@ } ], "versions": { - "1.0.0":null + "1.0.0": { + "api_version": 7, + "commit_sha": "5ea8255", + "released_on": "07-11-2022", + "md5sum": "def39482b339095a7affb574af829ea0" + } } }, "squid_race": { @@ -47,7 +52,12 @@ } ], "versions": { - "1.0.0":null + "1.0.0": { + "api_version": 7, + "commit_sha": "5ea8255", + "released_on": "07-11-2022", + "md5sum": "7ec43481e6b35b4da4f6425977ee0004" + } } }, "zombie_horde": { @@ -61,7 +71,12 @@ } ], "versions": { - "1.0.0":null + "1.0.0": { + "api_version": 7, + "commit_sha": "5ea8255", + "released_on": "07-11-2022", + "md5sum": "671e7b98a9d3eb0aeb7e47448db25af9" + } } }, "meteor_shower": { @@ -75,7 +90,12 @@ } ], "versions": { - "1.0.0":null + "1.0.0": { + "api_version": 7, + "commit_sha": "5ea8255", + "released_on": "07-11-2022", + "md5sum": "1ce8c1a3f3ec240af39b7a73375e7891" + } } }, "boxing": { @@ -89,7 +109,12 @@ } ], "versions": { - "1.0.0":null + "1.0.0": { + "api_version": 7, + "commit_sha": "5ea8255", + "released_on": "07-11-2022", + "md5sum": "c1b615df09886ba05622c4e8b4f6be40" + } } }, "basket_bomb": { @@ -103,7 +128,12 @@ } ], "versions": { - "1.0.0":null + "1.0.0": { + "api_version": 7, + "commit_sha": "5ea8255", + "released_on": "07-11-2022", + "md5sum": "7ec87edbdd5183ec4b2daffad0019820" + } } }, "ultimate_last_stand": { @@ -202,4 +232,4 @@ } } } -} +} \ No newline at end of file diff --git a/plugins/utilities.json b/plugins/utilities.json index b80c149..abe0505 100644 --- a/plugins/utilities.json +++ b/plugins/utilities.json @@ -14,7 +14,12 @@ } ], "versions": { - "1.0.0":null + "1.0.0": { + "api_version": 7, + "commit_sha": "5ea8255", + "released_on": "07-11-2022", + "md5sum": "4e160ffde7ea194eea0b8bf2abdfba8e" + } } }, "custom_death": { @@ -28,7 +33,12 @@ } ], "versions": { - "1.0.0":null + "1.0.0": { + "api_version": 7, + "commit_sha": "5ea8255", + "released_on": "07-11-2022", + "md5sum": "7b1941512532321eec18140087569215" + } } }, "max_players": { @@ -42,7 +52,12 @@ } ], "versions": { - "1.0.0":null + "1.0.0": { + "api_version": 7, + "commit_sha": "5ea8255", + "released_on": "07-11-2022", + "md5sum": "f5e129f009e9732b3179c7edaf75478e" + } } }, "quick_custom_game": { @@ -56,7 +71,12 @@ } ], "versions": { - "1.0.0":null + "1.0.0": { + "api_version": 7, + "commit_sha": "5ea8255", + "released_on": "07-11-2022", + "md5sum": "b691e35afb17cd3b5f6fe21c0194567d" + } } }, "random_colors": { @@ -70,7 +90,12 @@ } ], "versions": { - "1.0.0":null + "1.0.0": { + "api_version": 7, + "commit_sha": "5ea8255", + "released_on": "07-11-2022", + "md5sum": "0c351a0aebed77c3771053cde0c18d7b" + } } }, "chat_cmd": { @@ -89,7 +114,12 @@ } ], "versions": { - "1.0.0":null + "1.0.0": { + "api_version": 7, + "commit_sha": "5ea8255", + "released_on": "07-11-2022", + "md5sum": "c84d9a1c9e63e77949134020e1f11834" + } } }, "mood_light": { @@ -103,7 +133,12 @@ } ], "versions": { - "1.2.1":null, + "1.2.1": { + "api_version": 7, + "commit_sha": "5ea8255", + "released_on": "07-11-2022", + "md5sum": "ee8eede4a6c47535ab831abd0111aab0" + }, "1.2.0": { "api_version": 7, "commit_sha": "d838115", @@ -388,4 +423,4 @@ } } } -} +} \ No newline at end of file From a47c5e7d1fafd16d51fd281520de3685c3537c6a Mon Sep 17 00:00:00 2001 From: Loup <90267658+Loup-Garou911XD@users.noreply.github.com> Date: Tue, 8 Nov 2022 01:27:06 +0530 Subject: [PATCH 47/55] Add files via upload --- plugins/utilities/share_replay.py | 164 ++++++++++++++---------------- 1 file changed, 79 insertions(+), 85 deletions(-) diff --git a/plugins/utilities/share_replay.py b/plugins/utilities/share_replay.py index fe66569..449ca3e 100644 --- a/plugins/utilities/share_replay.py +++ b/plugins/utilities/share_replay.py @@ -3,63 +3,58 @@ from __future__ import annotations from typing import TYPE_CHECKING, cast if TYPE_CHECKING: from typing import Any, Sequence, Callable, List, Dict, Tuple, Optional, Union + +from os import listdir,mkdir,path,sep +from shutil import copy,copytree -from os import listdir, mkdir -from shutil import copy, copytree import ba import _ba from bastd.ui.watch import WatchWindow as ww from bastd.ui.popup import PopupWindow -# mod by ʟօʊքɢǟʀօʊ -# export replays to mods folder and share with your friends or have a backup +#mod by ʟօʊքɢǟʀօʊ +#export replays to mods folder and share with your friends or have a backup - -def Print(*args, color=None, top=None): - out = "" +def Print(*args,color=None,top=None): + out="" for arg in args: - a = str(arg) + a=str(arg) out += a - ba.screenmessage(out, color=color, top=top) - + ba.screenmessage(out,color=color,top=top) def cprint(*args): - out = "" + out="" for arg in args: - a = str(arg) + a=str(arg) out += a _ba.chatmessage(out) +internal_dir=path.join("ba_data","..","..","..","files", "bombsquad_config","replays" + sep) +external_dir=path.join(_ba.env()["python_directory_user"],"replays"+sep) -internal_dir = "/data/data/net.froemling.bombsquad/files/bombsquad_config/replays" -external_dir = "/storage/emulated/0/Android/data/net.froemling.bombsquad/files/mods/replays" -# colors -pink = (1, 0.2, 0.8) -green = (0.4, 1, 0.4) -red = (1, 0, 0) +#colors +pink=(1,0.2,0.8) +green=(0.4,1,0.4) +red=(1,0,0) -try: +if not path.exists(external_dir): mkdir(external_dir) - Print("You are ready to share replays", color=pink) -except FileExistsError: - pass - - + Print("You are ready to share replays",color=pink) + class Help(PopupWindow): def __init__(self): uiscale = ba.app.ui.uiscale self.width = 800 self.height = 300 - + PopupWindow.__init__(self, position=(0.0, 0.0), size=(self.width, self.height), scale=1.2,) - - ba.containerwidget(edit=self.root_widget, on_outside_click_call=self.close) - ba.textwidget(parent=self.root_widget, position=(0, self.height * 0.6), - text=f"•Replays are exported to\n {external_dir}\n•Importing replay and other features comming in v1.2") - + + ba.containerwidget(edit=self.root_widget,on_outside_click_call=self.close) + ba.textwidget(parent=self.root_widget,position=(0 , self.height * 0.6), text=f"•Replays are exported to\n {external_dir}\n•Importing replay and other features comming in v1.2") + def close(self): ba.playsound(ba.getsound('swish')) ba.containerwidget(edit=self.root_widget, transition="out_right",) @@ -69,19 +64,18 @@ class SettingWindow(): def __init__(self): self.draw_ui() self.selected_widget = None - self.selected_name = None - - def on_select_text(self, widget, name): - if self.selected_widget is not None: - ba.textwidget(edit=self.selected_widget, color=(1, 1, 1)) - ba.textwidget(edit=widget, color=(1, 1, 0)) + self.selected_name= None + + def on_select_text(self,widget,name): + if self.selected_widget is not None: + ba.textwidget(edit=self.selected_widget,color=(1,1,1)) + ba.textwidget(edit=widget,color=(1,1,0)) self.selected_name = name self.selected_widget = widget - + def draw_ui(self): self.uiscale = ba.app.ui.uiscale - self.root = ba.Window(ba.containerwidget( - size=(900, 670), on_outside_click_call=self.close, transition="in_right")).get_root_widget() + self.root=ba.Window(ba.containerwidget(size=(900, 670),on_outside_click_call=self.close,transition="in_right")).get_root_widget() ba.textwidget( parent=self.root, @@ -93,14 +87,15 @@ class SettingWindow(): v_align="center", text="ShareReplay", color=green) - + ba.buttonwidget( parent=self.root, - position=(400, 580), - size=(35, 35), - label="Help", + position=(400,580), + size=(35,35), + texture=ba.gettexture("achievementEmpty"), + label="", on_activate_call=Help) - + ba.buttonwidget( parent=self.root, position=(770, 460), @@ -108,64 +103,62 @@ class SettingWindow(): scale=1.5, label="EXPORT", on_activate_call=self.export) - + self.close_button = ba.buttonwidget( parent=self.root, position=(820, 590), size=(35, 35), texture=ba.gettexture("crossOut"), - label="", + label="", scale=2, color=(1, 0.2, 0.2), extra_touch_border_scale=3, on_activate_call=self.close) - - scroll = ba.scrollwidget( + + scroll=ba.scrollwidget( parent=self.root, - size=(500, 400), - position=(200, 150)) - self.scroll = ba.columnwidget(parent=scroll, size=( - 500, 900), selection_loops_to_parent=True, single_depth=True) - - height = 900 + size=(500,400), + position=(200,150)) + self.scroll=ba.columnwidget(parent=scroll,size=(500,900),selection_loops_to_parent=True,single_depth=True) + + height=900 for i in listdir(internal_dir): - height -= 40 - a = i + height-=40 + a=i i = ba.textwidget( - parent=self.scroll, - size=(500, 50), - text=i.split(".")[0], - position=(10, height), + parent=self.scroll, + size=(500,50), + text= i.split(".")[0], + position=(10,height), selectable=True, max_chars=40, click_activate=True,) - - ba.textwidget(edit=i, on_activate_call=ba.Call(self.on_select_text, i, a)) - + + ba.textwidget(edit=i,on_activate_call=ba.Call(self.on_select_text,i,a)) + + def export(self): - if self.selected_name is None: - Print("Select a replay", color=red) - return - copy(internal_dir+"/"+self.selected_name, external_dir+"/"+self.selected_name) - # image={"texture":ba.gettexture("bombColor"),"tint_texture":None,"tint_color":None,"tint2_color":None}) - Print(self.selected_name[0:-4]+" exported", top=True, color=pink) - + if self.selected_name is None: + Print("Select a replay",color=red) + return + copy(internal_dir+"/"+self.selected_name,external_dir+"/"+self.selected_name) + Print(self.selected_name[0:-4]+" exported", top=True,color=pink)#image={"texture":ba.gettexture("bombColor"),"tint_texture":None,"tint_color":None,"tint2_color":None}) + def close(self): ba.playsound(ba.getsound('swish')) - ba.containerwidget(edit=self.root, transition="out_right",) - + ba.containerwidget(edit=self.root, transition="out_right",) + # ++++++++++++++++for keyboard navigation++++++++++++++++ - #ba.widget(edit=self.enable_button, up_widget=decrease_button, down_widget=self.lower_text,left_widget=save_button, right_widget=save_button) + #ba.widget(edit=self.enable_button, up_widget=decrease_button, down_widget=self.lower_text,left_widget=save_button, right_widget=save_button) # -------------------------------------------------------------------------------------------------- -ww.__old_init__ = ww.__init__ +ww.__old_init__=ww.__init__ - -def new_init(self, transition="in_right", origin_widget=None): - self.__old_init__(transition, origin_widget) +def new_init(self,transition="in_right",origin_widget=None): + self.__old_init__(transition,origin_widget) self._share_button = ba.buttonwidget( parent=self._root_widget, position=(self._width*0.70, self._height*0.80), @@ -176,17 +169,18 @@ def new_init(self, transition="in_right", origin_widget=None): iconscale=1.5, label="SHARE REPLAY", on_activate_call=SettingWindow) - - + + # ba_meta export plugin -class main(ba.Plugin): +class Loup(ba.Plugin): def on_app_running(self): - - ww.__init__ = new_init - + ww.__init__=new_init + def has_settings_ui(self): return True - - def show_settings_ui(self, button): + + def show_settings_ui(self,button): SettingWindow() + + \ No newline at end of file From 7f155a07d7455f4738d42a2d5e21a5c83d23f427 Mon Sep 17 00:00:00 2001 From: Loup-Garou911XD Date: Mon, 7 Nov 2022 19:58:27 +0000 Subject: [PATCH 48/55] [ci] auto-format --- plugins/utilities/share_replay.py | 156 ++++++++++++++++-------------- 1 file changed, 81 insertions(+), 75 deletions(-) diff --git a/plugins/utilities/share_replay.py b/plugins/utilities/share_replay.py index 449ca3e..705b587 100644 --- a/plugins/utilities/share_replay.py +++ b/plugins/utilities/share_replay.py @@ -3,58 +3,63 @@ from __future__ import annotations from typing import TYPE_CHECKING, cast if TYPE_CHECKING: from typing import Any, Sequence, Callable, List, Dict, Tuple, Optional, Union - -from os import listdir,mkdir,path,sep -from shutil import copy,copytree + +from os import listdir, mkdir, path, sep +from shutil import copy, copytree import ba import _ba from bastd.ui.watch import WatchWindow as ww from bastd.ui.popup import PopupWindow -#mod by ʟօʊքɢǟʀօʊ -#export replays to mods folder and share with your friends or have a backup +# mod by ʟօʊքɢǟʀօʊ +# export replays to mods folder and share with your friends or have a backup -def Print(*args,color=None,top=None): - out="" + +def Print(*args, color=None, top=None): + out = "" for arg in args: - a=str(arg) + a = str(arg) out += a - ba.screenmessage(out,color=color,top=top) + ba.screenmessage(out, color=color, top=top) + def cprint(*args): - out="" + out = "" for arg in args: - a=str(arg) + a = str(arg) out += a _ba.chatmessage(out) -internal_dir=path.join("ba_data","..","..","..","files", "bombsquad_config","replays" + sep) -external_dir=path.join(_ba.env()["python_directory_user"],"replays"+sep) -#colors -pink=(1,0.2,0.8) -green=(0.4,1,0.4) -red=(1,0,0) +internal_dir = path.join("ba_data", "..", "..", "..", "files", "bombsquad_config", "replays" + sep) +external_dir = path.join(_ba.env()["python_directory_user"], "replays"+sep) + +# colors +pink = (1, 0.2, 0.8) +green = (0.4, 1, 0.4) +red = (1, 0, 0) if not path.exists(external_dir): mkdir(external_dir) - Print("You are ready to share replays",color=pink) - + Print("You are ready to share replays", color=pink) + + class Help(PopupWindow): def __init__(self): uiscale = ba.app.ui.uiscale self.width = 800 self.height = 300 - + PopupWindow.__init__(self, position=(0.0, 0.0), size=(self.width, self.height), scale=1.2,) - - ba.containerwidget(edit=self.root_widget,on_outside_click_call=self.close) - ba.textwidget(parent=self.root_widget,position=(0 , self.height * 0.6), text=f"•Replays are exported to\n {external_dir}\n•Importing replay and other features comming in v1.2") - + + ba.containerwidget(edit=self.root_widget, on_outside_click_call=self.close) + ba.textwidget(parent=self.root_widget, position=(0, self.height * 0.6), + text=f"•Replays are exported to\n {external_dir}\n•Importing replay and other features comming in v1.2") + def close(self): ba.playsound(ba.getsound('swish')) ba.containerwidget(edit=self.root_widget, transition="out_right",) @@ -64,18 +69,19 @@ class SettingWindow(): def __init__(self): self.draw_ui() self.selected_widget = None - self.selected_name= None - - def on_select_text(self,widget,name): - if self.selected_widget is not None: - ba.textwidget(edit=self.selected_widget,color=(1,1,1)) - ba.textwidget(edit=widget,color=(1,1,0)) + self.selected_name = None + + def on_select_text(self, widget, name): + if self.selected_widget is not None: + ba.textwidget(edit=self.selected_widget, color=(1, 1, 1)) + ba.textwidget(edit=widget, color=(1, 1, 0)) self.selected_name = name self.selected_widget = widget - + def draw_ui(self): self.uiscale = ba.app.ui.uiscale - self.root=ba.Window(ba.containerwidget(size=(900, 670),on_outside_click_call=self.close,transition="in_right")).get_root_widget() + self.root = ba.Window(ba.containerwidget( + size=(900, 670), on_outside_click_call=self.close, transition="in_right")).get_root_widget() ba.textwidget( parent=self.root, @@ -87,15 +93,15 @@ class SettingWindow(): v_align="center", text="ShareReplay", color=green) - + ba.buttonwidget( parent=self.root, - position=(400,580), - size=(35,35), + position=(400, 580), + size=(35, 35), texture=ba.gettexture("achievementEmpty"), label="", on_activate_call=Help) - + ba.buttonwidget( parent=self.root, position=(770, 460), @@ -103,62 +109,64 @@ class SettingWindow(): scale=1.5, label="EXPORT", on_activate_call=self.export) - + self.close_button = ba.buttonwidget( parent=self.root, position=(820, 590), size=(35, 35), texture=ba.gettexture("crossOut"), - label="", + label="", scale=2, color=(1, 0.2, 0.2), extra_touch_border_scale=3, on_activate_call=self.close) - - scroll=ba.scrollwidget( + + scroll = ba.scrollwidget( parent=self.root, - size=(500,400), - position=(200,150)) - self.scroll=ba.columnwidget(parent=scroll,size=(500,900),selection_loops_to_parent=True,single_depth=True) - - height=900 + size=(500, 400), + position=(200, 150)) + self.scroll = ba.columnwidget(parent=scroll, size=( + 500, 900), selection_loops_to_parent=True, single_depth=True) + + height = 900 for i in listdir(internal_dir): - height-=40 - a=i + height -= 40 + a = i i = ba.textwidget( - parent=self.scroll, - size=(500,50), - text= i.split(".")[0], - position=(10,height), + parent=self.scroll, + size=(500, 50), + text=i.split(".")[0], + position=(10, height), selectable=True, max_chars=40, click_activate=True,) - - ba.textwidget(edit=i,on_activate_call=ba.Call(self.on_select_text,i,a)) - - + + ba.textwidget(edit=i, on_activate_call=ba.Call(self.on_select_text, i, a)) + def export(self): - if self.selected_name is None: - Print("Select a replay",color=red) - return - copy(internal_dir+"/"+self.selected_name,external_dir+"/"+self.selected_name) - Print(self.selected_name[0:-4]+" exported", top=True,color=pink)#image={"texture":ba.gettexture("bombColor"),"tint_texture":None,"tint_color":None,"tint2_color":None}) - + if self.selected_name is None: + Print("Select a replay", color=red) + return + copy(internal_dir+"/"+self.selected_name, external_dir+"/"+self.selected_name) + # image={"texture":ba.gettexture("bombColor"),"tint_texture":None,"tint_color":None,"tint2_color":None}) + Print(self.selected_name[0:-4]+" exported", top=True, color=pink) + def close(self): ba.playsound(ba.getsound('swish')) - ba.containerwidget(edit=self.root, transition="out_right",) - + ba.containerwidget(edit=self.root, transition="out_right",) + # ++++++++++++++++for keyboard navigation++++++++++++++++ - #ba.widget(edit=self.enable_button, up_widget=decrease_button, down_widget=self.lower_text,left_widget=save_button, right_widget=save_button) + #ba.widget(edit=self.enable_button, up_widget=decrease_button, down_widget=self.lower_text,left_widget=save_button, right_widget=save_button) # -------------------------------------------------------------------------------------------------- -ww.__old_init__=ww.__init__ +ww.__old_init__ = ww.__init__ -def new_init(self,transition="in_right",origin_widget=None): - self.__old_init__(transition,origin_widget) + +def new_init(self, transition="in_right", origin_widget=None): + self.__old_init__(transition, origin_widget) self._share_button = ba.buttonwidget( parent=self._root_widget, position=(self._width*0.70, self._height*0.80), @@ -169,18 +177,16 @@ def new_init(self,transition="in_right",origin_widget=None): iconscale=1.5, label="SHARE REPLAY", on_activate_call=SettingWindow) - - + + # ba_meta export plugin class Loup(ba.Plugin): def on_app_running(self): - ww.__init__=new_init - + ww.__init__ = new_init + def has_settings_ui(self): return True - - def show_settings_ui(self,button): + + def show_settings_ui(self, button): SettingWindow() - - \ No newline at end of file From 1f973f5228d1604fbbdc541c7a14658ccb3135f1 Mon Sep 17 00:00:00 2001 From: Loup <90267658+Loup-Garou911XD@users.noreply.github.com> Date: Tue, 8 Nov 2022 02:50:09 +0530 Subject: [PATCH 49/55] Update utilities.json --- plugins/utilities.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/plugins/utilities.json b/plugins/utilities.json index 5336f99..9f0930c 100644 --- a/plugins/utilities.json +++ b/plugins/utilities.json @@ -23,7 +23,7 @@ "authors": [ { "name": "JoseAng3l", - "email": null, + "email": "", "discord": "! JoseANG3L#0268" } ], @@ -37,7 +37,7 @@ "authors": [ { "name": "JoseAng3l", - "email": null, + "email": "", "discord": "! JoseANG3L#0268" } ], @@ -51,7 +51,7 @@ "authors": [ { "name": "JoseAng3l", - "email": null, + "email": "", "discord": "! JoseANG3L#0268" } ], @@ -65,7 +65,7 @@ "authors": [ { "name": "JoseAng3l", - "email": null, + "email": "", "discord": "! JoseANG3L#0268" } ], @@ -79,12 +79,12 @@ "authors": [ { "name": "IM_NOT_PRANAV#7874", - "email": null, + "email": "", "discord": "IM_NOT_PRANAV#7874" }, { "name": "FireFighter1037 ", - "email": null, + "email": "", "discord": null } ], From a44841424f5ab0eb4262744dcdc7ff29dfeb3463 Mon Sep 17 00:00:00 2001 From: Loup <90267658+Loup-Garou911XD@users.noreply.github.com> Date: Tue, 8 Nov 2022 02:55:39 +0530 Subject: [PATCH 50/55] Update minigames.json --- plugins/minigames.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/plugins/minigames.json b/plugins/minigames.json index 3fd3023..ea9f0ea 100644 --- a/plugins/minigames.json +++ b/plugins/minigames.json @@ -28,7 +28,7 @@ "authors": [ { "name": "Unknown", - "email": null, + "email": "", "discord": null } ], @@ -42,7 +42,7 @@ "authors": [ { "name": "JoseAng3l", - "email": null, + "email": "", "discord": "! JoseANG3L#0268" } ], @@ -56,7 +56,7 @@ "authors": [ { "name": "JoseAng3l", - "email": null, + "email": "", "discord": "! JoseANG3L#0268" } ], @@ -70,7 +70,7 @@ "authors": [ { "name": "JoseAng3l", - "email": null, + "email": "", "discord": "! JoseANG3L#0268" } ], @@ -84,7 +84,7 @@ "authors": [ { "name": "JoseAng3l", - "email": null, + "email": "", "discord": "! JoseANG3L#0268" } ], @@ -98,7 +98,7 @@ "authors": [ { "name": "Unknown", - "email": null, + "email": "", "discord": null } ], From 2fda676de9afcff6a644bf680d8f257600938b54 Mon Sep 17 00:00:00 2001 From: Loup <90267658+Loup-Garou911XD@users.noreply.github.com> Date: Tue, 8 Nov 2022 03:03:15 +0530 Subject: [PATCH 51/55] Update utilities.json --- plugins/utilities.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/utilities.json b/plugins/utilities.json index 9f0930c..db81c11 100644 --- a/plugins/utilities.json +++ b/plugins/utilities.json @@ -103,7 +103,7 @@ } ], "versions": { - "1.2.1":null + "1.2.1":null, "1.2.0": { "api_version": 7, "commit_sha": "d838115", From d5324a768ae37549dcebc240ddf2ca731251d8fc Mon Sep 17 00:00:00 2001 From: Loup-Garou911XD Date: Mon, 7 Nov 2022 21:33:46 +0000 Subject: [PATCH 52/55] [ci] apply-version-metadata --- plugins/minigames.json | 44 ++++++++++++++++++++++++++++++------ plugins/utilities.json | 51 +++++++++++++++++++++++++++++++++++------- 2 files changed, 80 insertions(+), 15 deletions(-) diff --git a/plugins/minigames.json b/plugins/minigames.json index ea9f0ea..71af6c3 100644 --- a/plugins/minigames.json +++ b/plugins/minigames.json @@ -33,7 +33,12 @@ } ], "versions": { - "1.0.0":null + "1.0.0": { + "api_version": 7, + "commit_sha": "2fda676", + "released_on": "07-11-2022", + "md5sum": "def39482b339095a7affb574af829ea0" + } } }, "squid_race": { @@ -47,7 +52,12 @@ } ], "versions": { - "1.0.0":null + "1.0.0": { + "api_version": 7, + "commit_sha": "2fda676", + "released_on": "07-11-2022", + "md5sum": "7ec43481e6b35b4da4f6425977ee0004" + } } }, "zombie_horde": { @@ -61,7 +71,12 @@ } ], "versions": { - "1.0.0":null + "1.0.0": { + "api_version": 7, + "commit_sha": "2fda676", + "released_on": "07-11-2022", + "md5sum": "671e7b98a9d3eb0aeb7e47448db25af9" + } } }, "meteor_shower": { @@ -75,7 +90,12 @@ } ], "versions": { - "1.0.0":null + "1.0.0": { + "api_version": 7, + "commit_sha": "2fda676", + "released_on": "07-11-2022", + "md5sum": "1ce8c1a3f3ec240af39b7a73375e7891" + } } }, "boxing": { @@ -89,7 +109,12 @@ } ], "versions": { - "1.0.0":null + "1.0.0": { + "api_version": 7, + "commit_sha": "2fda676", + "released_on": "07-11-2022", + "md5sum": "c1b615df09886ba05622c4e8b4f6be40" + } } }, "basket_bomb": { @@ -103,7 +128,12 @@ } ], "versions": { - "1.0.0":null + "1.0.0": { + "api_version": 7, + "commit_sha": "2fda676", + "released_on": "07-11-2022", + "md5sum": "7ec87edbdd5183ec4b2daffad0019820" + } } }, "ultimate_last_stand": { @@ -202,4 +232,4 @@ } } } -} +} \ No newline at end of file diff --git a/plugins/utilities.json b/plugins/utilities.json index db81c11..1588313 100644 --- a/plugins/utilities.json +++ b/plugins/utilities.json @@ -14,7 +14,12 @@ } ], "versions": { - "1.0.0":null + "1.0.0": { + "api_version": 7, + "commit_sha": "2fda676", + "released_on": "07-11-2022", + "md5sum": "d475487c221d78c7f1278410d5ce229e" + } } }, "custom_death": { @@ -28,7 +33,12 @@ } ], "versions": { - "1.0.0":null + "1.0.0": { + "api_version": 7, + "commit_sha": "2fda676", + "released_on": "07-11-2022", + "md5sum": "7b1941512532321eec18140087569215" + } } }, "max_players": { @@ -42,7 +52,12 @@ } ], "versions": { - "1.0.0":null + "1.0.0": { + "api_version": 7, + "commit_sha": "2fda676", + "released_on": "07-11-2022", + "md5sum": "f5e129f009e9732b3179c7edaf75478e" + } } }, "quick_custom_game": { @@ -56,7 +71,12 @@ } ], "versions": { - "1.0.0":null + "1.0.0": { + "api_version": 7, + "commit_sha": "2fda676", + "released_on": "07-11-2022", + "md5sum": "b691e35afb17cd3b5f6fe21c0194567d" + } } }, "random_colors": { @@ -70,7 +90,12 @@ } ], "versions": { - "1.0.0":null + "1.0.0": { + "api_version": 7, + "commit_sha": "2fda676", + "released_on": "07-11-2022", + "md5sum": "0c351a0aebed77c3771053cde0c18d7b" + } } }, "chat_cmd": { @@ -89,7 +114,12 @@ } ], "versions": { - "1.0.0":null + "1.0.0": { + "api_version": 7, + "commit_sha": "2fda676", + "released_on": "07-11-2022", + "md5sum": "c84d9a1c9e63e77949134020e1f11834" + } } }, "mood_light": { @@ -103,7 +133,12 @@ } ], "versions": { - "1.2.1":null, + "1.2.1": { + "api_version": 7, + "commit_sha": "2fda676", + "released_on": "07-11-2022", + "md5sum": "ee8eede4a6c47535ab831abd0111aab0" + }, "1.2.0": { "api_version": 7, "commit_sha": "d838115", @@ -388,4 +423,4 @@ } } } -} +} \ No newline at end of file From 09962e81197b99b99992050ce202f604e5165510 Mon Sep 17 00:00:00 2001 From: Loup <90267658+Loup-Garou911XD@users.noreply.github.com> Date: Tue, 8 Nov 2022 03:32:00 +0530 Subject: [PATCH 53/55] Update utilities.json --- plugins/utilities.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/plugins/utilities.json b/plugins/utilities.json index 62b0fcf..c772acb 100644 --- a/plugins/utilities.json +++ b/plugins/utilities.json @@ -81,9 +81,7 @@ "versions": { "1.0.0": { "api_version": 7, -<< "commit_sha": "2fda676", -== "released_on": "07-11-2022", "md5sum": "b691e35afb17cd3b5f6fe21c0194567d" } @@ -438,4 +436,4 @@ } } } -} \ No newline at end of file +} From c485ea1f3a279ed1881e575372373bdeb9491308 Mon Sep 17 00:00:00 2001 From: Loup-Garou911XD Date: Mon, 7 Nov 2022 22:02:24 +0000 Subject: [PATCH 54/55] [ci] apply-version-metadata --- plugins/minigames.json | 12 ------------ plugins/utilities.json | 15 +-------------- 2 files changed, 1 insertion(+), 26 deletions(-) diff --git a/plugins/minigames.json b/plugins/minigames.json index db95113..71af6c3 100644 --- a/plugins/minigames.json +++ b/plugins/minigames.json @@ -35,9 +35,7 @@ "versions": { "1.0.0": { "api_version": 7, - "commit_sha": "2fda676", - "released_on": "07-11-2022", "md5sum": "def39482b339095a7affb574af829ea0" } @@ -56,9 +54,7 @@ "versions": { "1.0.0": { "api_version": 7, - "commit_sha": "2fda676", - "released_on": "07-11-2022", "md5sum": "7ec43481e6b35b4da4f6425977ee0004" } @@ -77,9 +73,7 @@ "versions": { "1.0.0": { "api_version": 7, - "commit_sha": "2fda676", - "released_on": "07-11-2022", "md5sum": "671e7b98a9d3eb0aeb7e47448db25af9" } @@ -98,9 +92,7 @@ "versions": { "1.0.0": { "api_version": 7, - "commit_sha": "2fda676", - "released_on": "07-11-2022", "md5sum": "1ce8c1a3f3ec240af39b7a73375e7891" } @@ -119,9 +111,7 @@ "versions": { "1.0.0": { "api_version": 7, - "commit_sha": "2fda676", - "released_on": "07-11-2022", "md5sum": "c1b615df09886ba05622c4e8b4f6be40" } @@ -140,9 +130,7 @@ "versions": { "1.0.0": { "api_version": 7, - "commit_sha": "2fda676", - "released_on": "07-11-2022", "md5sum": "7ec87edbdd5183ec4b2daffad0019820" } diff --git a/plugins/utilities.json b/plugins/utilities.json index c772acb..1588313 100644 --- a/plugins/utilities.json +++ b/plugins/utilities.json @@ -16,11 +16,9 @@ "versions": { "1.0.0": { "api_version": 7, - "commit_sha": "2fda676", "released_on": "07-11-2022", "md5sum": "d475487c221d78c7f1278410d5ce229e" - } } }, @@ -37,9 +35,7 @@ "versions": { "1.0.0": { "api_version": 7, - "commit_sha": "2fda676", - "released_on": "07-11-2022", "md5sum": "7b1941512532321eec18140087569215" } @@ -58,11 +54,7 @@ "versions": { "1.0.0": { "api_version": 7, - "commit_sha": "2fda676", - - - "released_on": "07-11-2022", "md5sum": "f5e129f009e9732b3179c7edaf75478e" } @@ -100,9 +92,7 @@ "versions": { "1.0.0": { "api_version": 7, - "commit_sha": "2fda676", - "released_on": "07-11-2022", "md5sum": "0c351a0aebed77c3771053cde0c18d7b" } @@ -127,7 +117,6 @@ "1.0.0": { "api_version": 7, "commit_sha": "2fda676", - "released_on": "07-11-2022", "md5sum": "c84d9a1c9e63e77949134020e1f11834" } @@ -146,9 +135,7 @@ "versions": { "1.2.1": { "api_version": 7, - "commit_sha": "2fda676", - "released_on": "07-11-2022", "md5sum": "ee8eede4a6c47535ab831abd0111aab0" }, @@ -436,4 +423,4 @@ } } } -} +} \ No newline at end of file From f68c48d24711199b760ed8bb1f41096a11fab62a Mon Sep 17 00:00:00 2001 From: Rikko Date: Tue, 8 Nov 2022 03:47:33 +0530 Subject: [PATCH 55/55] Correct meta entries --- plugins/minigames.json | 4 ++-- plugins/utilities.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/minigames.json b/plugins/minigames.json index 71af6c3..210e4fe 100644 --- a/plugins/minigames.json +++ b/plugins/minigames.json @@ -29,7 +29,7 @@ { "name": "Unknown", "email": "", - "discord": null + "discord": "" } ], "versions": { @@ -124,7 +124,7 @@ { "name": "Unknown", "email": "", - "discord": null + "discord": "" } ], "versions": { diff --git a/plugins/utilities.json b/plugins/utilities.json index 1588313..4f69da8 100644 --- a/plugins/utilities.json +++ b/plugins/utilities.json @@ -5,7 +5,7 @@ "plugins": { "share_replay": { "description": "Export replays to mods folder and share them with friends or have a backup", - "external_url": null, + "external_url": "", "authors": [ { "name": "LoupGarou", @@ -110,7 +110,7 @@ { "name": "FireFighter1037 ", "email": "", - "discord": null + "discord": "" } ], "versions": {