mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-01-23 23:49:47 +08:00
Merge pull request #650 from 3alTemp/tournament_entry
Practice in Tournaments! + Multi-entry bug fix
This commit is contained in:
commit
623b49375b
@ -61,6 +61,10 @@ class CoopSession(Session):
|
||||
max_players = classic.coop_session_args['max_players']
|
||||
else:
|
||||
max_players = app.config.get('Coop Game Max Players', 4)
|
||||
if 'submit_score' in classic.coop_session_args:
|
||||
submit_score = classic.coop_session_args['submit_score']
|
||||
else:
|
||||
submit_score = True
|
||||
|
||||
# print('FIXME: COOP SESSION WOULD CALC DEPS.')
|
||||
depsets: Sequence[bascenev1.DependencySet] = []
|
||||
@ -71,6 +75,7 @@ class CoopSession(Session):
|
||||
team_colors=TEAM_COLORS,
|
||||
min_players=min_players,
|
||||
max_players=max_players,
|
||||
submit_score=submit_score,
|
||||
)
|
||||
|
||||
# Tournament-ID if we correspond to a co-op tournament (otherwise None)
|
||||
@ -346,7 +351,10 @@ class CoopSession(Session):
|
||||
self.setactivity(next_game)
|
||||
|
||||
if not (env.demo or env.arcade):
|
||||
if self.tournament_id is not None:
|
||||
if (
|
||||
self.tournament_id is not None
|
||||
and classic.coop_session_args['submit_score']
|
||||
):
|
||||
self._custom_menu_ui = [
|
||||
{
|
||||
'label': babase.Lstr(resource='restartText'),
|
||||
|
||||
@ -100,6 +100,7 @@ class Session:
|
||||
team_colors: Sequence[Sequence[float]] | None = None,
|
||||
min_players: int = 1,
|
||||
max_players: int = 8,
|
||||
submit_score: bool = True,
|
||||
):
|
||||
"""Instantiate a session.
|
||||
|
||||
@ -175,6 +176,7 @@ class Session:
|
||||
if _max_players_override is None
|
||||
else _max_players_override
|
||||
)
|
||||
self.submit_score = submit_score
|
||||
|
||||
self.customdata = {}
|
||||
self._in_set_activity = False
|
||||
|
||||
@ -125,6 +125,7 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]):
|
||||
self._tournament_time_remaining: float | None = None
|
||||
self._tournament_time_remaining_text: Text | None = None
|
||||
self._tournament_time_remaining_text_timer: bs.BaseTimer | None = None
|
||||
self._submit_score = self.session.submit_score
|
||||
|
||||
# Stuff for activity skip by pressing button
|
||||
self._birth_time = bs.time()
|
||||
@ -789,7 +790,7 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]):
|
||||
transition_delay=2.0,
|
||||
)
|
||||
|
||||
if self._score is not None:
|
||||
if self._score is not None and self._submit_score:
|
||||
bs.timer(0.4, bs.WeakCall(self._play_drumroll))
|
||||
|
||||
# Add us to high scores, filter, and store.
|
||||
@ -1396,7 +1397,7 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]):
|
||||
assert self._show_info is not None
|
||||
available = self._show_info['results'] is not None
|
||||
|
||||
if available:
|
||||
if available and self._submit_score:
|
||||
error = (
|
||||
self._show_info['results']['error']
|
||||
if 'error' in self._show_info['results']
|
||||
@ -1529,7 +1530,7 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]):
|
||||
maxwidth=400,
|
||||
transition_delay=1.0,
|
||||
).autoretain()
|
||||
else:
|
||||
elif self._submit_score:
|
||||
ZoomText(
|
||||
(
|
||||
('#' + str(player_rank))
|
||||
@ -1752,9 +1753,10 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]):
|
||||
transition_delay=0,
|
||||
).autoretain()
|
||||
|
||||
bs.timer(0.35, self._score_display_sound.play)
|
||||
if not error:
|
||||
bs.timer(0.35, self.cymbal_sound.play)
|
||||
if self._submit_score:
|
||||
bs.timer(0.35, self._score_display_sound.play)
|
||||
if not error:
|
||||
bs.timer(0.35, self.cymbal_sound.play)
|
||||
|
||||
def _show_fail(self) -> None:
|
||||
ZoomText(
|
||||
|
||||
@ -14,7 +14,6 @@ import bauiv1 as bui
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Callable
|
||||
|
||||
import bascenev1 as bs
|
||||
|
||||
|
||||
@ -32,6 +31,7 @@ class TournamentEntryWindow(PopupWindow):
|
||||
on_close_call: Callable[[], Any] | None = None,
|
||||
):
|
||||
# Needs some tidying.
|
||||
# pylint: disable=too-many-locals
|
||||
# pylint: disable=too-many-branches
|
||||
# pylint: disable=too-many-statements
|
||||
|
||||
@ -80,11 +80,21 @@ class TournamentEntryWindow(PopupWindow):
|
||||
|
||||
self._tournament_activity = tournament_activity
|
||||
|
||||
self._width = 340
|
||||
self._height = 225
|
||||
self._width: float = 340.0
|
||||
self._height: float = 225.0
|
||||
|
||||
bg_color = (0.5, 0.4, 0.6)
|
||||
|
||||
# Show the practice button as long as we're not
|
||||
# restarting while on a paid tournament run.
|
||||
self._do_practice = (
|
||||
self._tournament_activity is None and
|
||||
bui.app.config.get('tournament_practice_enabled', False)
|
||||
)
|
||||
|
||||
off_p = 0 if not self._do_practice else 48
|
||||
self._height += off_p * 0.933
|
||||
|
||||
# Creates our root_widget.
|
||||
super().__init__(
|
||||
position=position,
|
||||
@ -107,7 +117,7 @@ class TournamentEntryWindow(PopupWindow):
|
||||
|
||||
self._cancel_button = bui.buttonwidget(
|
||||
parent=self.root_widget,
|
||||
position=(20, self._height - 34),
|
||||
position=(40, self._height - 34),
|
||||
size=(60, 60),
|
||||
scale=0.5,
|
||||
label='',
|
||||
@ -132,15 +142,15 @@ class TournamentEntryWindow(PopupWindow):
|
||||
|
||||
btn = self._pay_with_tickets_button = bui.buttonwidget(
|
||||
parent=self.root_widget,
|
||||
position=(30 + x_offs, 60),
|
||||
position=(30 + x_offs, 60 + off_p),
|
||||
autoselect=True,
|
||||
button_type='square',
|
||||
size=(120, 120),
|
||||
label='',
|
||||
on_activate_call=self._on_pay_with_tickets_press,
|
||||
)
|
||||
self._ticket_img_pos = (50 + x_offs, 94)
|
||||
self._ticket_img_pos_free = (50 + x_offs, 80)
|
||||
self._ticket_img_pos = (50 + x_offs, 94 + off_p)
|
||||
self._ticket_img_pos_free = (50 + x_offs, 80 + off_p)
|
||||
self._ticket_img = bui.imagewidget(
|
||||
parent=self.root_widget,
|
||||
draw_controller=btn,
|
||||
@ -148,8 +158,8 @@ class TournamentEntryWindow(PopupWindow):
|
||||
position=self._ticket_img_pos,
|
||||
texture=bui.gettexture('tickets'),
|
||||
)
|
||||
self._ticket_cost_text_position = (87 + x_offs, 88)
|
||||
self._ticket_cost_text_position_free = (87 + x_offs, 120)
|
||||
self._ticket_cost_text_position = (87 + x_offs, 88 + off_p)
|
||||
self._ticket_cost_text_position_free = (87 + x_offs, 120 + off_p)
|
||||
self._ticket_cost_text = bui.textwidget(
|
||||
parent=self.root_widget,
|
||||
draw_controller=btn,
|
||||
@ -165,7 +175,7 @@ class TournamentEntryWindow(PopupWindow):
|
||||
self._free_plays_remaining_text = bui.textwidget(
|
||||
parent=self.root_widget,
|
||||
draw_controller=btn,
|
||||
position=(87 + x_offs, 78),
|
||||
position=(87 + x_offs, 78 + off_p),
|
||||
size=(0, 0),
|
||||
h_align='center',
|
||||
v_align='center',
|
||||
@ -178,7 +188,7 @@ class TournamentEntryWindow(PopupWindow):
|
||||
if self._do_ad_btn:
|
||||
btn = self._pay_with_ad_btn = bui.buttonwidget(
|
||||
parent=self.root_widget,
|
||||
position=(190, 60),
|
||||
position=(190, 60 + off_p),
|
||||
autoselect=True,
|
||||
button_type='square',
|
||||
size=(120, 120),
|
||||
@ -189,12 +199,12 @@ class TournamentEntryWindow(PopupWindow):
|
||||
parent=self.root_widget,
|
||||
draw_controller=btn,
|
||||
size=(80, 80),
|
||||
position=(210, 94),
|
||||
position=(210, 94 + off_p),
|
||||
texture=bui.gettexture('tv'),
|
||||
)
|
||||
|
||||
self._ad_text_position = (251, 88)
|
||||
self._ad_text_position_remaining = (251, 92)
|
||||
self._ad_text_position = (251, 88 + off_p)
|
||||
self._ad_text_position_remaining = (251, 92 + off_p)
|
||||
have_ad_tries_remaining = (
|
||||
self._tournament_info['adTriesRemaining'] is not None
|
||||
)
|
||||
@ -224,7 +234,7 @@ class TournamentEntryWindow(PopupWindow):
|
||||
self._ad_plays_remaining_text = bui.textwidget(
|
||||
parent=self.root_widget,
|
||||
draw_controller=btn,
|
||||
position=(251, 78),
|
||||
position=(251, 78 + off_p),
|
||||
size=(0, 0),
|
||||
h_align='center',
|
||||
v_align='center',
|
||||
@ -236,7 +246,7 @@ class TournamentEntryWindow(PopupWindow):
|
||||
|
||||
bui.textwidget(
|
||||
parent=self.root_widget,
|
||||
position=(self._width * 0.5, 120),
|
||||
position=(self._width * 0.5, 120 + off_p),
|
||||
size=(0, 0),
|
||||
h_align='center',
|
||||
v_align='center',
|
||||
@ -250,13 +260,26 @@ class TournamentEntryWindow(PopupWindow):
|
||||
else:
|
||||
self._pay_with_ad_btn = None
|
||||
|
||||
btn_size = (150, 45)
|
||||
btn_pos = (self._width / 2 - btn_size[0] / 2, self._width / 2 - 110)
|
||||
self._practice_button = None
|
||||
if self._do_practice:
|
||||
self._practice_button = bui.buttonwidget(
|
||||
parent=self.root_widget,
|
||||
position=btn_pos,
|
||||
autoselect=True,
|
||||
size=btn_size,
|
||||
label=bui.Lstr(resource='practiceText'),
|
||||
on_activate_call=self._on_practice_press,
|
||||
)
|
||||
|
||||
self._get_tickets_button: bui.Widget | None = None
|
||||
self._ticket_count_text: bui.Widget | None = None
|
||||
if not bui.app.ui_v1.use_toolbars:
|
||||
if bui.app.classic.allow_ticket_purchases:
|
||||
self._get_tickets_button = bui.buttonwidget(
|
||||
parent=self.root_widget,
|
||||
position=(self._width - 190 + 125, self._height - 34),
|
||||
position=(self._width - 190 + 105, self._height - 34),
|
||||
autoselect=True,
|
||||
scale=0.5,
|
||||
size=(120, 60),
|
||||
@ -372,6 +395,8 @@ class TournamentEntryWindow(PopupWindow):
|
||||
sel = self.root_widget.get_selected_child()
|
||||
if sel == self._pay_with_ad_btn:
|
||||
sel_name = 'Ad'
|
||||
elif sel == self._practice_button:
|
||||
sel_name = 'Practice'
|
||||
else:
|
||||
sel_name = 'Tickets'
|
||||
cfg = bui.app.config
|
||||
@ -382,6 +407,8 @@ class TournamentEntryWindow(PopupWindow):
|
||||
sel_name = bui.app.config.get('Tournament Pay Selection', 'Tickets')
|
||||
if sel_name == 'Ad' and self._pay_with_ad_btn is not None:
|
||||
sel = self._pay_with_ad_btn
|
||||
elif sel_name == 'Practice' and self._practice_button is not None:
|
||||
sel = self._practice_button
|
||||
else:
|
||||
sel = self._pay_with_tickets_button
|
||||
bui.containerwidget(edit=self.root_widget, selected_child=sel)
|
||||
@ -537,29 +564,37 @@ class TournamentEntryWindow(PopupWindow):
|
||||
text=bui.charstr(bui.SpecialChar.TICKET) + t_str,
|
||||
)
|
||||
|
||||
def _launch(self) -> None:
|
||||
def _launch(self, practice: bool = False) -> None:
|
||||
assert bui.app.classic is not None
|
||||
if self._launched:
|
||||
return
|
||||
self._launched = True
|
||||
launched = False
|
||||
|
||||
# If they gave us an existing activity, just restart it.
|
||||
if self._tournament_activity is not None:
|
||||
# If they gave us an existing, non-consistent
|
||||
# practice activity, just restart it.
|
||||
if (
|
||||
self._tournament_activity is not None
|
||||
and not practice == self._tournament_activity.session.submit_score
|
||||
):
|
||||
try:
|
||||
bui.apptimer(0.1, bui.getsound('cashRegister').play)
|
||||
if not practice:
|
||||
bui.apptimer(0.1, bui.getsound('cashRegister').play)
|
||||
bui.screenmessage(
|
||||
bui.Lstr(
|
||||
translate=(
|
||||
'serverResponses',
|
||||
'Entering tournament...',
|
||||
)
|
||||
),
|
||||
color=(0, 1, 0),
|
||||
)
|
||||
bui.apptimer(0 if practice else 0.3, self._transition_out)
|
||||
launched = True
|
||||
with self._tournament_activity.context:
|
||||
self._tournament_activity.end(
|
||||
{'outcome': 'restart'}, force=True
|
||||
)
|
||||
bui.apptimer(0.3, self._transition_out)
|
||||
launched = True
|
||||
bui.screenmessage(
|
||||
bui.Lstr(
|
||||
translate=('serverResponses', 'Entering tournament...')
|
||||
),
|
||||
color=(0, 1, 0),
|
||||
)
|
||||
|
||||
# We can hit exceptions here if _tournament_activity ends before
|
||||
# our restart attempt happens.
|
||||
@ -572,29 +607,28 @@ class TournamentEntryWindow(PopupWindow):
|
||||
# If we had no existing activity (or were unable to restart it)
|
||||
# launch a new session.
|
||||
if not launched:
|
||||
bui.apptimer(0.1, bui.getsound('cashRegister').play)
|
||||
if not practice:
|
||||
bui.apptimer(0.1, bui.getsound('cashRegister').play)
|
||||
bui.screenmessage(
|
||||
bui.Lstr(
|
||||
translate=('serverResponses', 'Entering tournament...')
|
||||
),
|
||||
color=(0, 1, 0),
|
||||
)
|
||||
bui.apptimer(
|
||||
1.0,
|
||||
lambda: (
|
||||
bui.app.classic.launch_coop_game(
|
||||
self._tournament_info['game'],
|
||||
args={
|
||||
'min_players': self._tournament_info['minPlayers'],
|
||||
'max_players': self._tournament_info['maxPlayers'],
|
||||
'tournament_id': self._tournament_id,
|
||||
},
|
||||
)
|
||||
if bui.app.classic is not None
|
||||
else None
|
||||
),
|
||||
)
|
||||
bui.apptimer(0.7, self._transition_out)
|
||||
bui.screenmessage(
|
||||
bui.Lstr(
|
||||
translate=('serverResponses', 'Entering tournament...')
|
||||
),
|
||||
color=(0, 1, 0),
|
||||
0 if practice else 1.0,
|
||||
lambda: bui.app.classic.launch_coop_game(
|
||||
self._tournament_info['game'],
|
||||
args={
|
||||
'min_players': self._tournament_info['minPlayers'],
|
||||
'max_players': self._tournament_info['maxPlayers'],
|
||||
'tournament_id': self._tournament_id,
|
||||
'submit_score': not practice,
|
||||
},
|
||||
) if bui.app.classic is not None
|
||||
else None
|
||||
)
|
||||
bui.apptimer(0 if practice else 1.25, self._transition_out)
|
||||
|
||||
def _on_pay_with_tickets_press(self) -> None:
|
||||
from bauiv1lib import getcurrency
|
||||
@ -691,6 +725,25 @@ class TournamentEntryWindow(PopupWindow):
|
||||
on_completion_call=bui.WeakCall(self._on_ad_complete),
|
||||
)
|
||||
|
||||
def _on_practice_press(self) -> None:
|
||||
plus = bui.app.plus
|
||||
assert plus is not None
|
||||
|
||||
# If we're already entering, ignore.
|
||||
if self._entering:
|
||||
return
|
||||
|
||||
# Deny if it looks like the tourney has ended.
|
||||
if self._seconds_remaining == 0:
|
||||
bui.screenmessage(
|
||||
bui.Lstr(resource='tournamentEndedText'), color=(1, 0, 0)
|
||||
)
|
||||
bui.getsound('error').play()
|
||||
return
|
||||
|
||||
self._entering = True
|
||||
self._launch(practice=True)
|
||||
|
||||
def _on_ad_complete(self, actually_showed: bool) -> None:
|
||||
plus = bui.app.plus
|
||||
assert plus is not None
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user