mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-02-07 16:13:23 +08:00
Tourneys now require their maps/game types to be unlocked
This commit is contained in:
parent
091b369942
commit
6c8611a02b
48
.efrocachemap
generated
48
.efrocachemap
generated
@ -4174,22 +4174,22 @@
|
|||||||
"build/assets/windows/Win32/ucrtbased.dll": "bfd1180c269d3950b76f35a63655e9e1",
|
"build/assets/windows/Win32/ucrtbased.dll": "bfd1180c269d3950b76f35a63655e9e1",
|
||||||
"build/assets/windows/Win32/vc_redist.x86.exe": "15a5f1f876503885adbdf5b3989b3718",
|
"build/assets/windows/Win32/vc_redist.x86.exe": "15a5f1f876503885adbdf5b3989b3718",
|
||||||
"build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599",
|
"build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599",
|
||||||
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "31209ca509f46fde3450eb8b7a39a520",
|
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "ce8f860eca1987d08245184f86996182",
|
||||||
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "03ec26492ef7dc28370cbb7f9902b0b9",
|
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "50d39660fa219c8d6cf2efb61685a61a",
|
||||||
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "9331d3a163409aa08b5b1e681d923231",
|
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "6ba96618dd57e6937abe9d1919dfa572",
|
||||||
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "7aeb21b72648fa81d27d18251fb60f68",
|
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "cecc7cee479a3d34f9b2fc9e9d9ded23",
|
||||||
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "cecba50ac68398a3c4f8ddbaa9211d48",
|
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "e62e0586da50386f4f363ec018a5db5e",
|
||||||
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "683ff26a659c420a3738b5c58e17b37e",
|
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "60c86684724816e72fe123a4181e9b5e",
|
||||||
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "5e2f2dc71bd451900d7ece96e098dc00",
|
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "652e6dad52ffa1c7166ffad2da52e5cd",
|
||||||
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "4745da922028681b1b5cc63a584030b3",
|
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "7a54b3311d70edc58f6f2953df088e92",
|
||||||
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "a6527c54deee04b51029b1023a0b27fd",
|
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "2e43eceb3930606383de961285d539d5",
|
||||||
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "c6ceb3702ea22a2e187145a86bd51a13",
|
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "02967dc5ba24c1b85ff0626934c3e1ae",
|
||||||
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "4ee039201fdaa4c9a5afbefd5a31c064",
|
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "e93d6a9a363e7b769c1b4504bd24e34d",
|
||||||
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "15f71fc2ee8e71c657c159edceaec719",
|
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "f65ae7e22fba795c6368fd4d652eeff1",
|
||||||
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "1a56770399e5f6c91c25be77a68f38da",
|
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "5c6b347ac1a4f2a9cd0e253520355e66",
|
||||||
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "bcb3448df41f7a7e91f2823e55253a57",
|
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "5ee86d89f53f1da49e9f35f6bb510ec5",
|
||||||
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "6805beb9c0d1f967fe6a4344b5735aad",
|
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "eb531ec851c84295fad13f48d420a673",
|
||||||
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "b15bc3743c8021d1069568071e734a13",
|
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "9d55662daa82013b697d0715002fd950",
|
||||||
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "cbacac5a846cf8a0f6db760aaddcd13a",
|
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "cbacac5a846cf8a0f6db760aaddcd13a",
|
||||||
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "3d16bac10d8f15bac7fe20e3a927b275",
|
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "3d16bac10d8f15bac7fe20e3a927b275",
|
||||||
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "cbacac5a846cf8a0f6db760aaddcd13a",
|
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "cbacac5a846cf8a0f6db760aaddcd13a",
|
||||||
@ -4202,14 +4202,14 @@
|
|||||||
"build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "7dd182733a34da0ca5f5c97e5cb0b7f0",
|
"build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "7dd182733a34da0ca5f5c97e5cb0b7f0",
|
||||||
"build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "6121591b94d920ee541194b65d93958a",
|
"build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "6121591b94d920ee541194b65d93958a",
|
||||||
"build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "7dd182733a34da0ca5f5c97e5cb0b7f0",
|
"build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "7dd182733a34da0ca5f5c97e5cb0b7f0",
|
||||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "c512e7bacb6c8654b517a38604e0ccf2",
|
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "3aae8d5bb14498fa8c38a90f92e6eb61",
|
||||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "21b911b0ee5e354d25e8acf740140188",
|
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "8ca4eb60a623835aedded88a2c43d786",
|
||||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "6313af7210edecf7e9cf026550bbb161",
|
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "4d69eddf79b7e53a354b0148ba3af821",
|
||||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "dc7d359250c39d0e636da2bf7d859deb",
|
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "2d283c2d49f668594e858c33831354e8",
|
||||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "4c4c93e32beb69743b63f963748e1136",
|
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "bd3a90924b3dd122143cc99b9d054eaf",
|
||||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "70f5185b13ab6e799dbfc9bdd0a9e997",
|
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "4a9d7d32618519f04c4cc7b1cbdfb028",
|
||||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "f6adec2b792bc36c2cea2b395e827471",
|
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "4ff97a62a991a2af73bfcf23faeac8fe",
|
||||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "e674baf0049c634e6342cae5a266b567",
|
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "dbf2ed253e622c90939ce31cec3f04e8",
|
||||||
"src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c",
|
"src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c",
|
||||||
"src/assets/ba_data/python/babase/_mgen/enums.py": "794d258d59fd17a61752843a9a0551ad",
|
"src/assets/ba_data/python/babase/_mgen/enums.py": "794d258d59fd17a61752843a9a0551ad",
|
||||||
"src/ballistica/base/mgen/pyembed/binding_base.inc": "06042d31df0ff9af96b99477162e2a91",
|
"src/ballistica/base/mgen/pyembed/binding_base.inc": "06042d31df0ff9af96b99477162e2a91",
|
||||||
|
|||||||
@ -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
|
- 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
|
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.
|
touch UI stuff at all you can simply bump your api version and call it a day.
|
||||||
|
|||||||
@ -906,3 +906,67 @@ class ClassicAppSubsystem(babase.AppSubsystem):
|
|||||||
assert_never(label)
|
assert_never(label)
|
||||||
|
|
||||||
return babase.Lstr(resource=rsrc)
|
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)
|
||||||
|
|||||||
@ -53,7 +53,7 @@ if TYPE_CHECKING:
|
|||||||
|
|
||||||
# Build number and version of the ballistica binary we expect to be
|
# Build number and version of the ballistica binary we expect to be
|
||||||
# using.
|
# using.
|
||||||
TARGET_BALLISTICA_BUILD = 22202
|
TARGET_BALLISTICA_BUILD = 22204
|
||||||
TARGET_BALLISTICA_VERSION = '1.7.37'
|
TARGET_BALLISTICA_VERSION = '1.7.37'
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -326,8 +326,10 @@ class CoopBrowserWindow(bui.MainWindow):
|
|||||||
):
|
):
|
||||||
self._tourney_data_up_to_date = False
|
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()
|
account_state_num = plus.get_v1_account_state_num()
|
||||||
|
|
||||||
if account_state_num != self._account_state_num:
|
if account_state_num != self._account_state_num:
|
||||||
self._account_state_num = account_state_num
|
self._account_state_num = account_state_num
|
||||||
self._save_state()
|
self._save_state()
|
||||||
@ -405,6 +407,7 @@ class CoopBrowserWindow(bui.MainWindow):
|
|||||||
logging.exception('Error updating campaign lock.')
|
logging.exception('Error updating campaign lock.')
|
||||||
|
|
||||||
def _update_for_data(self, data: list[dict[str, Any]] | None) -> None:
|
def _update_for_data(self, data: list[dict[str, Any]] | None) -> None:
|
||||||
|
|
||||||
# If the number of tournaments or challenges in the data differs
|
# If the number of tournaments or challenges in the data differs
|
||||||
# from our current arrangement, refresh with the new number.
|
# from our current arrangement, refresh with the new number.
|
||||||
if (data is None and self._tournament_button_count != 0) or (
|
if (data is None and self._tournament_button_count != 0) or (
|
||||||
@ -985,9 +988,10 @@ class CoopBrowserWindow(bui.MainWindow):
|
|||||||
"""Return whether our tourney data is up to date."""
|
"""Return whether our tourney data is up to date."""
|
||||||
return self._tourney_data_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."""
|
"""Run the provided game."""
|
||||||
# pylint: disable=too-many-branches
|
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.confirm import ConfirmWindow
|
from bauiv1lib.confirm import ConfirmWindow
|
||||||
from bauiv1lib.purchase import PurchaseWindow
|
from bauiv1lib.purchase import PurchaseWindow
|
||||||
@ -1012,38 +1016,7 @@ class CoopBrowserWindow(bui.MainWindow):
|
|||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
required_purchase: str | None
|
required_purchase = bui.app.classic.required_purchase_for_game(game)
|
||||||
|
|
||||||
# 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
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
required_purchase is not None
|
required_purchase is not None
|
||||||
@ -1052,7 +1025,9 @@ class CoopBrowserWindow(bui.MainWindow):
|
|||||||
if plus.get_v1_account_state() != 'signed_in':
|
if plus.get_v1_account_state() != 'signed_in':
|
||||||
show_sign_in_prompt()
|
show_sign_in_prompt()
|
||||||
else:
|
else:
|
||||||
PurchaseWindow(items=[required_purchase])
|
PurchaseWindow(
|
||||||
|
items=[required_purchase], origin_widget=origin_widget
|
||||||
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
self._save_state()
|
self._save_state()
|
||||||
@ -1062,12 +1037,18 @@ class CoopBrowserWindow(bui.MainWindow):
|
|||||||
|
|
||||||
def run_tournament(self, tournament_button: TournamentButton) -> None:
|
def run_tournament(self, tournament_button: TournamentButton) -> None:
|
||||||
"""Run the provided tournament game."""
|
"""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.account.signin import show_sign_in_prompt
|
||||||
from bauiv1lib.tournamententry import TournamentEntryWindow
|
from bauiv1lib.tournamententry import TournamentEntryWindow
|
||||||
|
|
||||||
plus = bui.app.plus
|
plus = bui.app.plus
|
||||||
assert plus is not None
|
assert plus is not None
|
||||||
|
|
||||||
|
classic = bui.app.classic
|
||||||
|
assert classic is not None
|
||||||
|
|
||||||
if plus.get_v1_account_state() != 'signed_in':
|
if plus.get_v1_account_state() != 'signed_in':
|
||||||
show_sign_in_prompt()
|
show_sign_in_prompt()
|
||||||
return
|
return
|
||||||
@ -1117,6 +1098,22 @@ class CoopBrowserWindow(bui.MainWindow):
|
|||||||
bui.getsound('error').play()
|
bui.getsound('error').play()
|
||||||
return
|
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:
|
if tournament_button.time_remaining <= 0:
|
||||||
bui.screenmessage(
|
bui.screenmessage(
|
||||||
bui.Lstr(resource='tournamentEndedText'), color=(1, 0, 0)
|
bui.Lstr(resource='tournamentEndedText'), color=(1, 0, 0)
|
||||||
@ -1138,10 +1135,6 @@ class CoopBrowserWindow(bui.MainWindow):
|
|||||||
sel = self._root_widget.get_selected_child()
|
sel = self._root_widget.get_selected_child()
|
||||||
if sel == self._back_button:
|
if sel == self._back_button:
|
||||||
sel_name = 'Back'
|
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:
|
elif sel == self._scrollwidget:
|
||||||
sel_name = 'Scroll'
|
sel_name = 'Scroll'
|
||||||
else:
|
else:
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import random
|
import random
|
||||||
|
import weakref
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
import bauiv1 as bui
|
import bauiv1 as bui
|
||||||
@ -59,12 +60,15 @@ class GameButton:
|
|||||||
else:
|
else:
|
||||||
stars = 1
|
stars = 1
|
||||||
|
|
||||||
|
self._window = weakref.ref(window)
|
||||||
|
self._game = game
|
||||||
|
|
||||||
self._button = btn = bui.buttonwidget(
|
self._button = btn = bui.buttonwidget(
|
||||||
parent=parent,
|
parent=parent,
|
||||||
position=(x + 23, y + 4),
|
position=(x + 23, y + 4),
|
||||||
size=(sclx, scly),
|
size=(sclx, scly),
|
||||||
label='',
|
label='',
|
||||||
on_activate_call=bui.Call(window.run_game, game),
|
on_activate_call=bui.WeakCall(self._on_press),
|
||||||
button_type='square',
|
button_type='square',
|
||||||
autoselect=True,
|
autoselect=True,
|
||||||
on_select_call=bui.Call(window.sel_change, row, game),
|
on_select_call=bui.Call(window.sel_change, row, game),
|
||||||
@ -187,12 +191,16 @@ class GameButton:
|
|||||||
)
|
)
|
||||||
self._update()
|
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:
|
def get_button(self) -> bui.Widget:
|
||||||
"""Return the underlying button bui.Widget."""
|
"""Return the underlying button bui.Widget."""
|
||||||
return self._button
|
return self._button
|
||||||
|
|
||||||
def _update(self) -> None:
|
def _update(self) -> None:
|
||||||
# pylint: disable=too-many-boolean-expressions
|
|
||||||
|
|
||||||
plus = bui.app.plus
|
plus = bui.app.plus
|
||||||
assert plus is not None
|
assert plus is not None
|
||||||
@ -232,64 +240,7 @@ class GameButton:
|
|||||||
|
|
||||||
# Hard-code games we haven't unlocked.
|
# Hard-code games we haven't unlocked.
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
if (
|
if not bui.app.classic.is_game_unlocked(game):
|
||||||
(
|
|
||||||
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'
|
|
||||||
)
|
|
||||||
)
|
|
||||||
):
|
|
||||||
unlocked = False
|
unlocked = False
|
||||||
|
|
||||||
# Let's tint levels a slightly different color when easy mode
|
# Let's tint levels a slightly different color when easy mode
|
||||||
|
|||||||
@ -39,6 +39,7 @@ class TournamentButton:
|
|||||||
self.lsbo = bui.getmesh('level_select_button_opaque')
|
self.lsbo = bui.getmesh('level_select_button_opaque')
|
||||||
self.allow_ads = False
|
self.allow_ads = False
|
||||||
self.tournament_id: str | None = None
|
self.tournament_id: str | None = None
|
||||||
|
self.game: str | None = None
|
||||||
self.time_remaining: int = 0
|
self.time_remaining: int = 0
|
||||||
self.has_time_remaining: bool = False
|
self.has_time_remaining: bool = False
|
||||||
self.leader: Any = None
|
self.leader: Any = None
|
||||||
@ -400,6 +401,9 @@ class TournamentButton:
|
|||||||
color=(0.4, 0.4, 0.5),
|
color=(0.4, 0.4, 0.5),
|
||||||
flatness=1.0,
|
flatness=1.0,
|
||||||
)
|
)
|
||||||
|
self._lock_update_timer = bui.AppTimer(
|
||||||
|
1.03, bui.WeakCall(self._update_lock_state), repeat=True
|
||||||
|
)
|
||||||
|
|
||||||
def _pressed(self) -> None:
|
def _pressed(self) -> None:
|
||||||
self.on_pressed(self)
|
self.on_pressed(self)
|
||||||
@ -440,6 +444,33 @@ class TournamentButton:
|
|||||||
position=self.more_scores_button.get_screen_space_center(),
|
position=self.more_scores_button.get_screen_space_center(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _update_lock_state(self) -> None:
|
||||||
|
|
||||||
|
if self.game is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
assert bui.app.classic is not None
|
||||||
|
|
||||||
|
campaignname, levelname = self.game.split(':')
|
||||||
|
campaign = bui.app.classic.getcampaign(campaignname)
|
||||||
|
|
||||||
|
enabled = (
|
||||||
|
self.required_league is None
|
||||||
|
and bui.app.classic.is_game_unlocked(self.game)
|
||||||
|
)
|
||||||
|
bui.buttonwidget(
|
||||||
|
edit=self.button,
|
||||||
|
color=(0.5, 0.7, 0.2) if enabled else (0.5, 0.5, 0.5),
|
||||||
|
)
|
||||||
|
bui.imagewidget(edit=self.lock_image, opacity=0.0 if enabled else 1.0)
|
||||||
|
bui.imagewidget(
|
||||||
|
edit=self.image,
|
||||||
|
texture=bui.gettexture(
|
||||||
|
campaign.getlevel(levelname).preview_texture_name
|
||||||
|
),
|
||||||
|
opacity=1.0 if enabled else 0.5,
|
||||||
|
)
|
||||||
|
|
||||||
def update_for_data(self, entry: dict[str, Any]) -> None:
|
def update_for_data(self, entry: dict[str, Any]) -> None:
|
||||||
"""Update for new incoming data."""
|
"""Update for new incoming data."""
|
||||||
# pylint: disable=too-many-statements
|
# pylint: disable=too-many-statements
|
||||||
@ -470,12 +501,22 @@ class TournamentButton:
|
|||||||
entry, include_tickets=False
|
entry, include_tickets=False
|
||||||
)
|
)
|
||||||
|
|
||||||
enabled = 'requiredLeague' not in entry
|
self.time_remaining = entry['timeRemaining']
|
||||||
bui.buttonwidget(
|
self.has_time_remaining = entry is not None
|
||||||
edit=self.button,
|
self.tournament_id = entry['tournamentID']
|
||||||
color=(0.5, 0.7, 0.2) if enabled else (0.5, 0.5, 0.5),
|
self.required_league = entry.get('requiredLeague')
|
||||||
)
|
|
||||||
bui.imagewidget(edit=self.lock_image, opacity=0.0 if enabled else 1.0)
|
assert bui.app.classic is not None
|
||||||
|
self.game = bui.app.classic.accounts.tournament_info[
|
||||||
|
self.tournament_id
|
||||||
|
]['game']
|
||||||
|
assert isinstance(self.game, str)
|
||||||
|
|
||||||
|
campaignname, levelname = self.game.split(':')
|
||||||
|
campaign = bui.app.classic.getcampaign(campaignname)
|
||||||
|
|
||||||
|
self._update_lock_state()
|
||||||
|
|
||||||
bui.textwidget(
|
bui.textwidget(
|
||||||
edit=self.prize_range_1_text,
|
edit=self.prize_range_1_text,
|
||||||
text='-' if pr1 == '' else pr1,
|
text='-' if pr1 == '' else pr1,
|
||||||
@ -604,51 +645,30 @@ class TournamentButton:
|
|||||||
edit=self.time_remaining_out_of_text, text=out_of_time_text
|
edit=self.time_remaining_out_of_text, text=out_of_time_text
|
||||||
)
|
)
|
||||||
|
|
||||||
self.time_remaining = entry['timeRemaining']
|
# if self.game is None:
|
||||||
self.has_time_remaining = entry is not None
|
# bui.textwidget(edit=self.button_text, text='-')
|
||||||
self.tournament_id = entry['tournamentID']
|
# bui.imagewidget(
|
||||||
self.required_league = (
|
# edit=self.image, texture=bui.gettexture('black'), opacity=0.2
|
||||||
None if 'requiredLeague' not in entry else entry['requiredLeague']
|
# )
|
||||||
)
|
# else:
|
||||||
|
max_players = bui.app.classic.accounts.tournament_info[
|
||||||
|
self.tournament_id
|
||||||
|
]['maxPlayers']
|
||||||
|
|
||||||
assert bui.app.classic is not None
|
txt = bui.Lstr(
|
||||||
game = bui.app.classic.accounts.tournament_info[self.tournament_id][
|
value='${A} ${B}',
|
||||||
'game'
|
subs=[
|
||||||
]
|
('${A}', campaign.getlevel(levelname).displayname),
|
||||||
|
(
|
||||||
if game is None:
|
'${B}',
|
||||||
bui.textwidget(edit=self.button_text, text='-')
|
bui.Lstr(
|
||||||
bui.imagewidget(
|
resource='playerCountAbbreviatedText',
|
||||||
edit=self.image, texture=bui.gettexture('black'), opacity=0.2
|
subs=[('${COUNT}', str(max_players))],
|
||||||
)
|
|
||||||
else:
|
|
||||||
campaignname, levelname = game.split(':')
|
|
||||||
campaign = bui.app.classic.getcampaign(campaignname)
|
|
||||||
max_players = bui.app.classic.accounts.tournament_info[
|
|
||||||
self.tournament_id
|
|
||||||
]['maxPlayers']
|
|
||||||
|
|
||||||
txt = bui.Lstr(
|
|
||||||
value='${A} ${B}',
|
|
||||||
subs=[
|
|
||||||
('${A}', campaign.getlevel(levelname).displayname),
|
|
||||||
(
|
|
||||||
'${B}',
|
|
||||||
bui.Lstr(
|
|
||||||
resource='playerCountAbbreviatedText',
|
|
||||||
subs=[('${COUNT}', str(max_players))],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
|
||||||
)
|
|
||||||
bui.textwidget(edit=self.button_text, text=txt)
|
|
||||||
bui.imagewidget(
|
|
||||||
edit=self.image,
|
|
||||||
texture=bui.gettexture(
|
|
||||||
campaign.getlevel(levelname).preview_texture_name
|
|
||||||
),
|
),
|
||||||
opacity=1.0 if enabled else 0.5,
|
],
|
||||||
)
|
)
|
||||||
|
bui.textwidget(edit=self.button_text, text=txt)
|
||||||
|
|
||||||
fee = entry['fee']
|
fee = entry['fee']
|
||||||
assert isinstance(fee, int | None)
|
assert isinstance(fee, int | None)
|
||||||
|
|||||||
@ -18,7 +18,7 @@ class PurchaseWindow(bui.Window):
|
|||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
items: list[str],
|
items: list[str],
|
||||||
transition: str = 'in_right',
|
origin_widget: bui.Widget | None = None,
|
||||||
header_text: bui.Lstr | None = None,
|
header_text: bui.Lstr | None = None,
|
||||||
):
|
):
|
||||||
from bauiv1lib.store.item import instantiate_store_item_display
|
from bauiv1lib.store.item import instantiate_store_item_display
|
||||||
@ -40,16 +40,24 @@ class PurchaseWindow(bui.Window):
|
|||||||
self._width = 580
|
self._width = 580
|
||||||
self._height = 520
|
self._height = 520
|
||||||
uiscale = bui.app.ui_v1.uiscale
|
uiscale = bui.app.ui_v1.uiscale
|
||||||
|
|
||||||
|
if origin_widget is not None:
|
||||||
|
scale_origin = origin_widget.get_screen_space_center()
|
||||||
|
else:
|
||||||
|
scale_origin = None
|
||||||
|
|
||||||
super().__init__(
|
super().__init__(
|
||||||
root_widget=bui.containerwidget(
|
root_widget=bui.containerwidget(
|
||||||
|
parent=bui.get_special_widget('overlay_stack'),
|
||||||
size=(self._width, self._height),
|
size=(self._width, self._height),
|
||||||
transition=transition,
|
transition='in_scale',
|
||||||
toolbar_visibility='menu_store',
|
toolbar_visibility='menu_store',
|
||||||
scale=(
|
scale=(
|
||||||
1.2
|
1.2
|
||||||
if uiscale is bui.UIScale.SMALL
|
if uiscale is bui.UIScale.SMALL
|
||||||
else 1.1 if uiscale is bui.UIScale.MEDIUM else 1.0
|
else 1.1 if uiscale is bui.UIScale.MEDIUM else 1.0
|
||||||
),
|
),
|
||||||
|
scale_origin_stack_offset=scale_origin,
|
||||||
stack_offset=(
|
stack_offset=(
|
||||||
(0, -15) if uiscale is bui.UIScale.SMALL else (0, 0)
|
(0, -15) if uiscale is bui.UIScale.SMALL else (0, 0)
|
||||||
),
|
),
|
||||||
@ -159,7 +167,7 @@ class PurchaseWindow(bui.Window):
|
|||||||
can_die = True
|
can_die = True
|
||||||
|
|
||||||
if can_die:
|
if can_die:
|
||||||
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
bui.containerwidget(edit=self._root_widget, transition='out_scale')
|
||||||
|
|
||||||
def _purchase(self) -> None:
|
def _purchase(self) -> None:
|
||||||
|
|
||||||
@ -192,4 +200,4 @@ class PurchaseWindow(bui.Window):
|
|||||||
do_it()
|
do_it()
|
||||||
|
|
||||||
def _cancel(self) -> None:
|
def _cancel(self) -> None:
|
||||||
bui.containerwidget(edit=self._root_widget, transition='out_right')
|
bui.containerwidget(edit=self._root_widget, transition='out_scale')
|
||||||
|
|||||||
@ -39,7 +39,7 @@ auto main(int argc, char** argv) -> int {
|
|||||||
namespace ballistica {
|
namespace ballistica {
|
||||||
|
|
||||||
// These are set automatically via script; don't modify them here.
|
// These are set automatically via script; don't modify them here.
|
||||||
const int kEngineBuildNumber = 22202;
|
const int kEngineBuildNumber = 22204;
|
||||||
const char* kEngineVersion = "1.7.37";
|
const char* kEngineVersion = "1.7.37";
|
||||||
const int kEngineApiVersion = 9;
|
const int kEngineApiVersion = 9;
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user