bombsquad-plugin-manager/plugins/utilities/MaxPlayers.py
2022-11-03 17:08:09 +00:00

368 lines
12 KiB
Python

"""===========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