Skip to content

Commit

Permalink
Tourneys now require their maps/game types to be unlocked
Browse files Browse the repository at this point in the history
  • Loading branch information
efroemling committed Jan 18, 2025
1 parent 091b369 commit 6c8611a
Show file tree
Hide file tree
Showing 9 changed files with 216 additions and 180 deletions.
48 changes: 24 additions & 24 deletions .efrocachemap

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
### 1.7.37 (build 22202, api 9, 2025-01-18)
### 1.7.37 (build 22204, api 9, 2025-01-18)
- Bumping api version to 9. As you'll see below, there's some UI changes that
will require a bit of work for any UI mods to adapt to. If your mods don't
touch UI stuff at all you can simply bump your api version and call it a day.
Expand Down
64 changes: 64 additions & 0 deletions src/assets/ba_data/python/baclassic/_appsubsystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -906,3 +906,67 @@ def basic_client_ui_button_label_str(
assert_never(label)

return babase.Lstr(resource=rsrc)

def required_purchase_for_game(self, game: str) -> str | None:
"""Return which purchase (if any) is required for a game."""
# pylint: disable=too-many-return-statements

if game in (
'Challenges:Infinite Runaround',
'Challenges:Tournament Infinite Runaround',
):
# Special case: Pro used to unlock this.
return (
None
if self.accounts.have_pro()
else 'upgrades.infinite_runaround'
)
if game in (
'Challenges:Infinite Onslaught',
'Challenges:Tournament Infinite Onslaught',
):
# Special case: Pro used to unlock this.
return (
None
if self.accounts.have_pro()
else 'upgrades.infinite_onslaught'
)
if game in (
'Challenges:Meteor Shower',
'Challenges:Epic Meteor Shower',
):
return 'games.meteor_shower'

if game in (
'Challenges:Target Practice',
'Challenges:Target Practice B',
):
return 'games.target_practice'

if game in (
'Challenges:Ninja Fight',
'Challenges:Pro Ninja Fight',
):
return 'games.ninja_fight'

if game in ('Challenges:Lake Frigid Race',):
return 'maps.lake_frigid'

if game in (
'Challenges:Easter Egg Hunt',
'Challenges:Pro Easter Egg Hunt',
):
return 'games.easter_egg_hunt'

return None

def is_game_unlocked(self, game: str) -> bool:
"""Is a particular game unlocked?"""
plus = babase.app.plus
assert plus is not None

purchase = self.required_purchase_for_game(game)
if purchase is None:
return True

return plus.get_v1_account_product_purchased(purchase)
2 changes: 1 addition & 1 deletion src/assets/ba_data/python/baenv.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@

# Build number and version of the ballistica binary we expect to be
# using.
TARGET_BALLISTICA_BUILD = 22202
TARGET_BALLISTICA_BUILD = 22204
TARGET_BALLISTICA_VERSION = '1.7.37'


Expand Down
73 changes: 33 additions & 40 deletions src/assets/ba_data/python/bauiv1lib/coop/browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -326,8 +326,10 @@ def _update(self) -> None:
):
self._tourney_data_up_to_date = False

# If our account state has changed, do a full request.
# If our account login state has changed, do a
# full request.
account_state_num = plus.get_v1_account_state_num()

if account_state_num != self._account_state_num:
self._account_state_num = account_state_num
self._save_state()
Expand Down Expand Up @@ -405,6 +407,7 @@ def _update_hard_mode_lock_image(self) -> None:
logging.exception('Error updating campaign lock.')

def _update_for_data(self, data: list[dict[str, Any]] | None) -> None:

# If the number of tournaments or challenges in the data differs
# from our current arrangement, refresh with the new number.
if (data is None and self._tournament_button_count != 0) or (
Expand Down Expand Up @@ -985,9 +988,10 @@ def is_tourney_data_up_to_date(self) -> bool:
"""Return whether our tourney data is up to date."""
return self._tourney_data_up_to_date

def run_game(self, game: str) -> None:
def run_game(
self, game: str, origin_widget: bui.Widget | None = None
) -> None:
"""Run the provided game."""
# pylint: disable=too-many-branches
# pylint: disable=cyclic-import
from bauiv1lib.confirm import ConfirmWindow
from bauiv1lib.purchase import PurchaseWindow
Expand All @@ -1012,38 +1016,7 @@ def run_game(self, game: str) -> None:
)
return

required_purchase: str | None

# Infinite onslaught requires pro or the newer standalone
# upgrade.
if (
game in ['Challenges:Infinite Runaround']
and not bui.app.classic.accounts.have_pro()
):
required_purchase = 'upgrades.infinite_runaround'
elif (
game in ['Challenges:Infinite Onslaught']
and not bui.app.classic.accounts.have_pro()
):
required_purchase = 'upgrades.infinite_onslaught'
elif game in ['Challenges:Meteor Shower']:
required_purchase = 'games.meteor_shower'
elif game in [
'Challenges:Target Practice',
'Challenges:Target Practice B',
]:
required_purchase = 'games.target_practice'
elif game in ['Challenges:Ninja Fight']:
required_purchase = 'games.ninja_fight'
elif game in ['Challenges:Pro Ninja Fight']:
required_purchase = 'games.ninja_fight'
elif game in [
'Challenges:Easter Egg Hunt',
'Challenges:Pro Easter Egg Hunt',
]:
required_purchase = 'games.easter_egg_hunt'
else:
required_purchase = None
required_purchase = bui.app.classic.required_purchase_for_game(game)

if (
required_purchase is not None
Expand All @@ -1052,7 +1025,9 @@ def run_game(self, game: str) -> None:
if plus.get_v1_account_state() != 'signed_in':
show_sign_in_prompt()
else:
PurchaseWindow(items=[required_purchase])
PurchaseWindow(
items=[required_purchase], origin_widget=origin_widget
)
return

self._save_state()
Expand All @@ -1062,12 +1037,18 @@ def run_game(self, game: str) -> None:

def run_tournament(self, tournament_button: TournamentButton) -> None:
"""Run the provided tournament game."""
# pylint: disable=too-many-return-statements

from bauiv1lib.purchase import PurchaseWindow
from bauiv1lib.account.signin import show_sign_in_prompt
from bauiv1lib.tournamententry import TournamentEntryWindow

plus = bui.app.plus
assert plus is not None

classic = bui.app.classic
assert classic is not None

if plus.get_v1_account_state() != 'signed_in':
show_sign_in_prompt()
return
Expand Down Expand Up @@ -1117,6 +1098,22 @@ def run_tournament(self, tournament_button: TournamentButton) -> None:
bui.getsound('error').play()
return

if tournament_button.game is not None and not classic.is_game_unlocked(
tournament_button.game
):
required_purchase = classic.required_purchase_for_game(
tournament_button.game
)
assert required_purchase is not None
if plus.get_v1_account_state() != 'signed_in':
show_sign_in_prompt()
else:
PurchaseWindow(
items=[required_purchase],
origin_widget=tournament_button.button,
)
return

if tournament_button.time_remaining <= 0:
bui.screenmessage(
bui.Lstr(resource='tournamentEndedText'), color=(1, 0, 0)
Expand All @@ -1138,10 +1135,6 @@ def _save_state(self) -> None:
sel = self._root_widget.get_selected_child()
if sel == self._back_button:
sel_name = 'Back'
# elif sel == self._store_button_widget:
# sel_name = 'Store'
# elif sel == self._league_rank_button_widget:
# sel_name = 'PowerRanking'
elif sel == self._scrollwidget:
sel_name = 'Scroll'
else:
Expand Down
71 changes: 11 additions & 60 deletions src/assets/ba_data/python/bauiv1lib/coop/gamebutton.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from __future__ import annotations

import random
import weakref
from typing import TYPE_CHECKING

import bauiv1 as bui
Expand Down Expand Up @@ -59,12 +60,15 @@ def __init__(
else:
stars = 1

self._window = weakref.ref(window)
self._game = game

self._button = btn = bui.buttonwidget(
parent=parent,
position=(x + 23, y + 4),
size=(sclx, scly),
label='',
on_activate_call=bui.Call(window.run_game, game),
on_activate_call=bui.WeakCall(self._on_press),
button_type='square',
autoselect=True,
on_select_call=bui.Call(window.sel_change, row, game),
Expand Down Expand Up @@ -187,12 +191,16 @@ def __init__(
)
self._update()

def _on_press(self) -> None:
window = self._window()
if window is not None:
window.run_game(self._game, origin_widget=self._button)

def get_button(self) -> bui.Widget:
"""Return the underlying button bui.Widget."""
return self._button

def _update(self) -> None:
# pylint: disable=too-many-boolean-expressions

plus = bui.app.plus
assert plus is not None
Expand Down Expand Up @@ -232,64 +240,7 @@ def _update(self) -> None:

# Hard-code games we haven't unlocked.
assert bui.app.classic is not None
if (
(
game in ('Challenges:Infinite Runaround',)
and not (
bui.app.classic.accounts.have_pro()
or plus.get_v1_account_product_purchased(
'upgrades.infinite_runaround'
)
)
)
or (
game in ('Challenges:Infinite Onslaught',)
and not (
bui.app.classic.accounts.have_pro()
or plus.get_v1_account_product_purchased(
'upgrades.infinite_onslaught'
)
)
)
or (
game in ('Challenges:Meteor Shower',)
and not plus.get_v1_account_product_purchased(
'games.meteor_shower'
)
)
or (
game
in (
'Challenges:Target Practice',
'Challenges:Target Practice B',
)
and not plus.get_v1_account_product_purchased(
'games.target_practice'
)
)
or (
game in ('Challenges:Ninja Fight',)
and not plus.get_v1_account_product_purchased(
'games.ninja_fight'
)
)
or (
game in ('Challenges:Pro Ninja Fight',)
and not plus.get_v1_account_product_purchased(
'games.ninja_fight'
)
)
or (
game
in (
'Challenges:Easter Egg Hunt',
'Challenges:Pro Easter Egg Hunt',
)
and not plus.get_v1_account_product_purchased(
'games.easter_egg_hunt'
)
)
):
if not bui.app.classic.is_game_unlocked(game):
unlocked = False

# Let's tint levels a slightly different color when easy mode
Expand Down
Loading

0 comments on commit 6c8611a

Please sign in to comment.