mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-02-05 15:03:33 +08:00
cleaning up coop ui code
This commit is contained in:
parent
4bb10a0d3d
commit
e5e54a64e6
1194
.efrocachemap
1194
.efrocachemap
File diff suppressed because it is too large
Load Diff
2
.idea/dictionaries/ericf.xml
generated
2
.idea/dictionaries/ericf.xml
generated
@ -2153,6 +2153,7 @@
|
|||||||
<w>sbwht</w>
|
<w>sbwht</w>
|
||||||
<w>sbylw</w>
|
<w>sbylw</w>
|
||||||
<w>sbytes</w>
|
<w>sbytes</w>
|
||||||
|
<w>scanresults</w>
|
||||||
<w>scenefile</w>
|
<w>scenefile</w>
|
||||||
<w>scenefiles</w>
|
<w>scenefiles</w>
|
||||||
<w>scenename</w>
|
<w>scenename</w>
|
||||||
@ -2567,6 +2568,7 @@
|
|||||||
<w>totalwaves</w>
|
<w>totalwaves</w>
|
||||||
<w>totype</w>
|
<w>totype</w>
|
||||||
<w>touchpad</w>
|
<w>touchpad</w>
|
||||||
|
<w>tournamentbutton</w>
|
||||||
<w>tournamententry</w>
|
<w>tournamententry</w>
|
||||||
<w>tournamentscores</w>
|
<w>tournamentscores</w>
|
||||||
<w>tpartial</w>
|
<w>tpartial</w>
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
### 1.7.4 (20637, 2022-07-07)
|
### 1.7.4 (20638, 2022-07-07)
|
||||||
- Fixed the trophies list showing an incorrect total (Thanks itsre3!)
|
- Fixed the trophies list showing an incorrect total (Thanks itsre3!)
|
||||||
|
- ba.app.meta.metascan is now ba.app.meta.scanresults
|
||||||
|
|
||||||
### 1.7.3 (20634, 2022-07-06)
|
### 1.7.3 (20634, 2022-07-06)
|
||||||
- Fixed an issue with King of the Hill flag regions not working when players entered them (Thanks itsre3!)
|
- Fixed an issue with King of the Hill flag regions not working when players entered them (Thanks itsre3!)
|
||||||
|
|||||||
@ -374,9 +374,11 @@
|
|||||||
"ba_data/python/bastd/ui/coop/__pycache__/browser.cpython-310.opt-1.pyc",
|
"ba_data/python/bastd/ui/coop/__pycache__/browser.cpython-310.opt-1.pyc",
|
||||||
"ba_data/python/bastd/ui/coop/__pycache__/gamebutton.cpython-310.opt-1.pyc",
|
"ba_data/python/bastd/ui/coop/__pycache__/gamebutton.cpython-310.opt-1.pyc",
|
||||||
"ba_data/python/bastd/ui/coop/__pycache__/level.cpython-310.opt-1.pyc",
|
"ba_data/python/bastd/ui/coop/__pycache__/level.cpython-310.opt-1.pyc",
|
||||||
|
"ba_data/python/bastd/ui/coop/__pycache__/tournamentbutton.cpython-310.opt-1.pyc",
|
||||||
"ba_data/python/bastd/ui/coop/browser.py",
|
"ba_data/python/bastd/ui/coop/browser.py",
|
||||||
"ba_data/python/bastd/ui/coop/gamebutton.py",
|
"ba_data/python/bastd/ui/coop/gamebutton.py",
|
||||||
"ba_data/python/bastd/ui/coop/level.py",
|
"ba_data/python/bastd/ui/coop/level.py",
|
||||||
|
"ba_data/python/bastd/ui/coop/tournamentbutton.py",
|
||||||
"ba_data/python/bastd/ui/creditslist.py",
|
"ba_data/python/bastd/ui/creditslist.py",
|
||||||
"ba_data/python/bastd/ui/debug.py",
|
"ba_data/python/bastd/ui/debug.py",
|
||||||
"ba_data/python/bastd/ui/feedback.py",
|
"ba_data/python/bastd/ui/feedback.py",
|
||||||
|
|||||||
@ -298,6 +298,7 @@ SCRIPT_TARGETS_PY_PUBLIC = \
|
|||||||
build/ba_data/python/bastd/ui/coop/browser.py \
|
build/ba_data/python/bastd/ui/coop/browser.py \
|
||||||
build/ba_data/python/bastd/ui/coop/gamebutton.py \
|
build/ba_data/python/bastd/ui/coop/gamebutton.py \
|
||||||
build/ba_data/python/bastd/ui/coop/level.py \
|
build/ba_data/python/bastd/ui/coop/level.py \
|
||||||
|
build/ba_data/python/bastd/ui/coop/tournamentbutton.py \
|
||||||
build/ba_data/python/bastd/ui/creditslist.py \
|
build/ba_data/python/bastd/ui/creditslist.py \
|
||||||
build/ba_data/python/bastd/ui/debug.py \
|
build/ba_data/python/bastd/ui/debug.py \
|
||||||
build/ba_data/python/bastd/ui/feedback.py \
|
build/ba_data/python/bastd/ui/feedback.py \
|
||||||
@ -546,6 +547,7 @@ SCRIPT_TARGETS_PYC_PUBLIC = \
|
|||||||
build/ba_data/python/bastd/ui/coop/__pycache__/browser.cpython-310.opt-1.pyc \
|
build/ba_data/python/bastd/ui/coop/__pycache__/browser.cpython-310.opt-1.pyc \
|
||||||
build/ba_data/python/bastd/ui/coop/__pycache__/gamebutton.cpython-310.opt-1.pyc \
|
build/ba_data/python/bastd/ui/coop/__pycache__/gamebutton.cpython-310.opt-1.pyc \
|
||||||
build/ba_data/python/bastd/ui/coop/__pycache__/level.cpython-310.opt-1.pyc \
|
build/ba_data/python/bastd/ui/coop/__pycache__/level.cpython-310.opt-1.pyc \
|
||||||
|
build/ba_data/python/bastd/ui/coop/__pycache__/tournamentbutton.cpython-310.opt-1.pyc \
|
||||||
build/ba_data/python/bastd/ui/__pycache__/creditslist.cpython-310.opt-1.pyc \
|
build/ba_data/python/bastd/ui/__pycache__/creditslist.cpython-310.opt-1.pyc \
|
||||||
build/ba_data/python/bastd/ui/__pycache__/debug.cpython-310.opt-1.pyc \
|
build/ba_data/python/bastd/ui/__pycache__/debug.cpython-310.opt-1.pyc \
|
||||||
build/ba_data/python/bastd/ui/__pycache__/feedback.cpython-310.opt-1.pyc \
|
build/ba_data/python/bastd/ui/__pycache__/feedback.cpython-310.opt-1.pyc \
|
||||||
|
|||||||
@ -28,10 +28,16 @@ class Campaign:
|
|||||||
Category: **App Classes**
|
Category: **App Classes**
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, name: str, sequential: bool = True):
|
def __init__(self,
|
||||||
|
name: str,
|
||||||
|
sequential: bool = True,
|
||||||
|
levels: list[ba.Level] | None = None):
|
||||||
self._name = name
|
self._name = name
|
||||||
self._levels: list[ba.Level] = []
|
|
||||||
self._sequential = sequential
|
self._sequential = sequential
|
||||||
|
self._levels: list[ba.Level] = []
|
||||||
|
if levels is not None:
|
||||||
|
for level in levels:
|
||||||
|
self.addlevel(level)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self) -> str:
|
def name(self) -> str:
|
||||||
@ -91,9 +97,8 @@ class Campaign:
|
|||||||
|
|
||||||
def init_campaigns() -> None:
|
def init_campaigns() -> None:
|
||||||
"""Fill out initial default Campaigns."""
|
"""Fill out initial default Campaigns."""
|
||||||
# pylint: disable=too-many-statements
|
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from ba import _level
|
from ba._level import Level
|
||||||
from bastd.game.onslaught import OnslaughtGame
|
from bastd.game.onslaught import OnslaughtGame
|
||||||
from bastd.game.football import FootballCoopGame
|
from bastd.game.football import FootballCoopGame
|
||||||
from bastd.game.runaround import RunaroundGame
|
from bastd.game.runaround import RunaroundGame
|
||||||
@ -109,244 +114,218 @@ def init_campaigns() -> None:
|
|||||||
|
|
||||||
# FIXME: Once translations catch up, we can convert these to use the
|
# FIXME: Once translations catch up, we can convert these to use the
|
||||||
# generic display-name '${GAME} Training' type stuff.
|
# generic display-name '${GAME} Training' type stuff.
|
||||||
campaign = Campaign('Easy')
|
register_campaign(
|
||||||
campaign.addlevel(
|
Campaign(
|
||||||
_level.Level('Onslaught Training',
|
'Easy',
|
||||||
gametype=OnslaughtGame,
|
levels=[
|
||||||
settings={'preset': 'training_easy'},
|
Level('Onslaught Training',
|
||||||
preview_texture_name='doomShroomPreview'))
|
gametype=OnslaughtGame,
|
||||||
campaign.addlevel(
|
settings={'preset': 'training_easy'},
|
||||||
_level.Level('Rookie Onslaught',
|
preview_texture_name='doomShroomPreview'),
|
||||||
gametype=OnslaughtGame,
|
Level('Rookie Onslaught',
|
||||||
settings={'preset': 'rookie_easy'},
|
gametype=OnslaughtGame,
|
||||||
preview_texture_name='courtyardPreview'))
|
settings={'preset': 'rookie_easy'},
|
||||||
campaign.addlevel(
|
preview_texture_name='courtyardPreview'),
|
||||||
_level.Level('Rookie Football',
|
Level('Rookie Football',
|
||||||
gametype=FootballCoopGame,
|
gametype=FootballCoopGame,
|
||||||
settings={'preset': 'rookie_easy'},
|
settings={'preset': 'rookie_easy'},
|
||||||
preview_texture_name='footballStadiumPreview'))
|
preview_texture_name='footballStadiumPreview'),
|
||||||
campaign.addlevel(
|
Level('Pro Onslaught',
|
||||||
_level.Level('Pro Onslaught',
|
gametype=OnslaughtGame,
|
||||||
gametype=OnslaughtGame,
|
settings={'preset': 'pro_easy'},
|
||||||
settings={'preset': 'pro_easy'},
|
preview_texture_name='doomShroomPreview'),
|
||||||
preview_texture_name='doomShroomPreview'))
|
Level('Pro Football',
|
||||||
campaign.addlevel(
|
gametype=FootballCoopGame,
|
||||||
_level.Level('Pro Football',
|
settings={'preset': 'pro_easy'},
|
||||||
gametype=FootballCoopGame,
|
preview_texture_name='footballStadiumPreview'),
|
||||||
settings={'preset': 'pro_easy'},
|
Level('Pro Runaround',
|
||||||
preview_texture_name='footballStadiumPreview'))
|
gametype=RunaroundGame,
|
||||||
campaign.addlevel(
|
settings={'preset': 'pro_easy'},
|
||||||
_level.Level('Pro Runaround',
|
preview_texture_name='towerDPreview'),
|
||||||
gametype=RunaroundGame,
|
Level('Uber Onslaught',
|
||||||
settings={'preset': 'pro_easy'},
|
gametype=OnslaughtGame,
|
||||||
preview_texture_name='towerDPreview'))
|
settings={'preset': 'uber_easy'},
|
||||||
campaign.addlevel(
|
preview_texture_name='courtyardPreview'),
|
||||||
_level.Level('Uber Onslaught',
|
Level('Uber Football',
|
||||||
gametype=OnslaughtGame,
|
gametype=FootballCoopGame,
|
||||||
settings={'preset': 'uber_easy'},
|
settings={'preset': 'uber_easy'},
|
||||||
preview_texture_name='courtyardPreview'))
|
preview_texture_name='footballStadiumPreview'),
|
||||||
campaign.addlevel(
|
Level('Uber Runaround',
|
||||||
_level.Level('Uber Football',
|
gametype=RunaroundGame,
|
||||||
gametype=FootballCoopGame,
|
settings={'preset': 'uber_easy'},
|
||||||
settings={'preset': 'uber_easy'},
|
preview_texture_name='towerDPreview')
|
||||||
preview_texture_name='footballStadiumPreview'))
|
],
|
||||||
campaign.addlevel(
|
))
|
||||||
_level.Level('Uber Runaround',
|
|
||||||
gametype=RunaroundGame,
|
|
||||||
settings={'preset': 'uber_easy'},
|
|
||||||
preview_texture_name='towerDPreview'))
|
|
||||||
register_campaign(campaign)
|
|
||||||
|
|
||||||
# "hard" mode
|
# "hard" mode
|
||||||
campaign = Campaign('Default')
|
register_campaign(
|
||||||
campaign.addlevel(
|
Campaign(
|
||||||
_level.Level('Onslaught Training',
|
'Default',
|
||||||
gametype=OnslaughtGame,
|
levels=[
|
||||||
settings={'preset': 'training'},
|
Level('Onslaught Training',
|
||||||
preview_texture_name='doomShroomPreview'))
|
gametype=OnslaughtGame,
|
||||||
campaign.addlevel(
|
settings={'preset': 'training'},
|
||||||
_level.Level('Rookie Onslaught',
|
preview_texture_name='doomShroomPreview'),
|
||||||
gametype=OnslaughtGame,
|
Level('Rookie Onslaught',
|
||||||
settings={'preset': 'rookie'},
|
gametype=OnslaughtGame,
|
||||||
preview_texture_name='courtyardPreview'))
|
settings={'preset': 'rookie'},
|
||||||
campaign.addlevel(
|
preview_texture_name='courtyardPreview'),
|
||||||
_level.Level('Rookie Football',
|
Level('Rookie Football',
|
||||||
gametype=FootballCoopGame,
|
gametype=FootballCoopGame,
|
||||||
settings={'preset': 'rookie'},
|
settings={'preset': 'rookie'},
|
||||||
preview_texture_name='footballStadiumPreview'))
|
preview_texture_name='footballStadiumPreview'),
|
||||||
campaign.addlevel(
|
Level('Pro Onslaught',
|
||||||
_level.Level('Pro Onslaught',
|
gametype=OnslaughtGame,
|
||||||
gametype=OnslaughtGame,
|
settings={'preset': 'pro'},
|
||||||
settings={'preset': 'pro'},
|
preview_texture_name='doomShroomPreview'),
|
||||||
preview_texture_name='doomShroomPreview'))
|
Level('Pro Football',
|
||||||
campaign.addlevel(
|
gametype=FootballCoopGame,
|
||||||
_level.Level('Pro Football',
|
settings={'preset': 'pro'},
|
||||||
gametype=FootballCoopGame,
|
preview_texture_name='footballStadiumPreview'),
|
||||||
settings={'preset': 'pro'},
|
Level('Pro Runaround',
|
||||||
preview_texture_name='footballStadiumPreview'))
|
gametype=RunaroundGame,
|
||||||
campaign.addlevel(
|
settings={'preset': 'pro'},
|
||||||
_level.Level('Pro Runaround',
|
preview_texture_name='towerDPreview'),
|
||||||
gametype=RunaroundGame,
|
Level('Uber Onslaught',
|
||||||
settings={'preset': 'pro'},
|
gametype=OnslaughtGame,
|
||||||
preview_texture_name='towerDPreview'))
|
settings={'preset': 'uber'},
|
||||||
campaign.addlevel(
|
preview_texture_name='courtyardPreview'),
|
||||||
_level.Level('Uber Onslaught',
|
Level('Uber Football',
|
||||||
gametype=OnslaughtGame,
|
gametype=FootballCoopGame,
|
||||||
settings={'preset': 'uber'},
|
settings={'preset': 'uber'},
|
||||||
preview_texture_name='courtyardPreview'))
|
preview_texture_name='footballStadiumPreview'),
|
||||||
campaign.addlevel(
|
Level('Uber Runaround',
|
||||||
_level.Level('Uber Football',
|
gametype=RunaroundGame,
|
||||||
gametype=FootballCoopGame,
|
settings={'preset': 'uber'},
|
||||||
settings={'preset': 'uber'},
|
preview_texture_name='towerDPreview'),
|
||||||
preview_texture_name='footballStadiumPreview'))
|
Level('The Last Stand',
|
||||||
campaign.addlevel(
|
gametype=TheLastStandGame,
|
||||||
_level.Level('Uber Runaround',
|
settings={},
|
||||||
gametype=RunaroundGame,
|
preview_texture_name='rampagePreview')
|
||||||
settings={'preset': 'uber'},
|
],
|
||||||
preview_texture_name='towerDPreview'))
|
))
|
||||||
campaign.addlevel(
|
|
||||||
_level.Level('The Last Stand',
|
|
||||||
gametype=TheLastStandGame,
|
|
||||||
settings={},
|
|
||||||
preview_texture_name='rampagePreview'))
|
|
||||||
register_campaign(campaign)
|
|
||||||
|
|
||||||
# challenges: our 'official' random extra co-op levels
|
# challenges: our 'official' random extra co-op levels
|
||||||
campaign = Campaign('Challenges', sequential=False)
|
register_campaign(
|
||||||
campaign.addlevel(
|
Campaign(
|
||||||
_level.Level('Infinite Onslaught',
|
'Challenges',
|
||||||
gametype=OnslaughtGame,
|
sequential=False,
|
||||||
settings={'preset': 'endless'},
|
levels=[
|
||||||
preview_texture_name='doomShroomPreview'))
|
Level('Infinite Onslaught',
|
||||||
campaign.addlevel(
|
gametype=OnslaughtGame,
|
||||||
_level.Level('Infinite Runaround',
|
settings={'preset': 'endless'},
|
||||||
gametype=RunaroundGame,
|
preview_texture_name='doomShroomPreview'),
|
||||||
settings={'preset': 'endless'},
|
Level('Infinite Runaround',
|
||||||
preview_texture_name='towerDPreview'))
|
gametype=RunaroundGame,
|
||||||
campaign.addlevel(
|
settings={'preset': 'endless'},
|
||||||
_level.Level('Race',
|
preview_texture_name='towerDPreview'),
|
||||||
displayname='${GAME}',
|
Level('Race',
|
||||||
gametype=RaceGame,
|
displayname='${GAME}',
|
||||||
settings={
|
gametype=RaceGame,
|
||||||
'map': 'Big G',
|
settings={
|
||||||
'Laps': 3,
|
'map': 'Big G',
|
||||||
'Bomb Spawning': 0
|
'Laps': 3,
|
||||||
},
|
'Bomb Spawning': 0
|
||||||
preview_texture_name='bigGPreview'))
|
},
|
||||||
campaign.addlevel(
|
preview_texture_name='bigGPreview'),
|
||||||
_level.Level('Pro Race',
|
Level('Pro Race',
|
||||||
displayname='Pro ${GAME}',
|
displayname='Pro ${GAME}',
|
||||||
gametype=RaceGame,
|
gametype=RaceGame,
|
||||||
settings={
|
settings={
|
||||||
'map': 'Big G',
|
'map': 'Big G',
|
||||||
'Laps': 3,
|
'Laps': 3,
|
||||||
'Bomb Spawning': 1000
|
'Bomb Spawning': 1000
|
||||||
},
|
},
|
||||||
preview_texture_name='bigGPreview'))
|
preview_texture_name='bigGPreview'),
|
||||||
campaign.addlevel(
|
Level('Lake Frigid Race',
|
||||||
_level.Level('Lake Frigid Race',
|
displayname='${GAME}',
|
||||||
displayname='${GAME}',
|
gametype=RaceGame,
|
||||||
gametype=RaceGame,
|
settings={
|
||||||
settings={
|
'map': 'Lake Frigid',
|
||||||
'map': 'Lake Frigid',
|
'Laps': 6,
|
||||||
'Laps': 6,
|
'Mine Spawning': 2000,
|
||||||
'Mine Spawning': 2000,
|
'Bomb Spawning': 0
|
||||||
'Bomb Spawning': 0
|
},
|
||||||
},
|
preview_texture_name='lakeFrigidPreview'),
|
||||||
preview_texture_name='lakeFrigidPreview'))
|
Level('Football',
|
||||||
campaign.addlevel(
|
displayname='${GAME}',
|
||||||
_level.Level('Football',
|
gametype=FootballCoopGame,
|
||||||
displayname='${GAME}',
|
settings={'preset': 'tournament'},
|
||||||
gametype=FootballCoopGame,
|
preview_texture_name='footballStadiumPreview'),
|
||||||
settings={'preset': 'tournament'},
|
Level('Pro Football',
|
||||||
preview_texture_name='footballStadiumPreview'))
|
displayname='Pro ${GAME}',
|
||||||
campaign.addlevel(
|
gametype=FootballCoopGame,
|
||||||
_level.Level('Pro Football',
|
settings={'preset': 'tournament_pro'},
|
||||||
displayname='Pro ${GAME}',
|
preview_texture_name='footballStadiumPreview'),
|
||||||
gametype=FootballCoopGame,
|
Level('Runaround',
|
||||||
settings={'preset': 'tournament_pro'},
|
displayname='${GAME}',
|
||||||
preview_texture_name='footballStadiumPreview'))
|
gametype=RunaroundGame,
|
||||||
campaign.addlevel(
|
settings={'preset': 'tournament'},
|
||||||
_level.Level('Runaround',
|
preview_texture_name='towerDPreview'),
|
||||||
displayname='${GAME}',
|
Level('Uber Runaround',
|
||||||
gametype=RunaroundGame,
|
displayname='Uber ${GAME}',
|
||||||
settings={'preset': 'tournament'},
|
gametype=RunaroundGame,
|
||||||
preview_texture_name='towerDPreview'))
|
settings={'preset': 'tournament_uber'},
|
||||||
campaign.addlevel(
|
preview_texture_name='towerDPreview'),
|
||||||
_level.Level('Uber Runaround',
|
Level('The Last Stand',
|
||||||
displayname='Uber ${GAME}',
|
displayname='${GAME}',
|
||||||
gametype=RunaroundGame,
|
gametype=TheLastStandGame,
|
||||||
settings={'preset': 'tournament_uber'},
|
settings={'preset': 'tournament'},
|
||||||
preview_texture_name='towerDPreview'))
|
preview_texture_name='rampagePreview'),
|
||||||
campaign.addlevel(
|
Level('Tournament Infinite Onslaught',
|
||||||
_level.Level('The Last Stand',
|
displayname='Infinite Onslaught',
|
||||||
displayname='${GAME}',
|
gametype=OnslaughtGame,
|
||||||
gametype=TheLastStandGame,
|
settings={'preset': 'endless_tournament'},
|
||||||
settings={'preset': 'tournament'},
|
preview_texture_name='doomShroomPreview'),
|
||||||
preview_texture_name='rampagePreview'))
|
Level('Tournament Infinite Runaround',
|
||||||
campaign.addlevel(
|
displayname='Infinite Runaround',
|
||||||
_level.Level('Tournament Infinite Onslaught',
|
gametype=RunaroundGame,
|
||||||
displayname='Infinite Onslaught',
|
settings={'preset': 'endless_tournament'},
|
||||||
gametype=OnslaughtGame,
|
preview_texture_name='towerDPreview'),
|
||||||
settings={'preset': 'endless_tournament'},
|
Level('Target Practice',
|
||||||
preview_texture_name='doomShroomPreview'))
|
displayname='Pro ${GAME}',
|
||||||
campaign.addlevel(
|
gametype=TargetPracticeGame,
|
||||||
_level.Level('Tournament Infinite Runaround',
|
settings={},
|
||||||
displayname='Infinite Runaround',
|
preview_texture_name='doomShroomPreview'),
|
||||||
gametype=RunaroundGame,
|
Level('Target Practice B',
|
||||||
settings={'preset': 'endless_tournament'},
|
displayname='${GAME}',
|
||||||
preview_texture_name='towerDPreview'))
|
gametype=TargetPracticeGame,
|
||||||
campaign.addlevel(
|
settings={
|
||||||
_level.Level('Target Practice',
|
'Target Count': 2,
|
||||||
displayname='Pro ${GAME}',
|
'Enable Impact Bombs': False,
|
||||||
gametype=TargetPracticeGame,
|
'Enable Triple Bombs': False
|
||||||
settings={},
|
},
|
||||||
preview_texture_name='doomShroomPreview'))
|
preview_texture_name='doomShroomPreview'),
|
||||||
campaign.addlevel(
|
Level('Meteor Shower',
|
||||||
_level.Level('Target Practice B',
|
displayname='${GAME}',
|
||||||
displayname='${GAME}',
|
gametype=MeteorShowerGame,
|
||||||
gametype=TargetPracticeGame,
|
settings={},
|
||||||
settings={
|
preview_texture_name='rampagePreview'),
|
||||||
'Target Count': 2,
|
Level('Epic Meteor Shower',
|
||||||
'Enable Impact Bombs': False,
|
displayname='${GAME}',
|
||||||
'Enable Triple Bombs': False
|
gametype=MeteorShowerGame,
|
||||||
},
|
settings={'Epic Mode': True},
|
||||||
preview_texture_name='doomShroomPreview'))
|
preview_texture_name='rampagePreview'),
|
||||||
campaign.addlevel(
|
Level('Easter Egg Hunt',
|
||||||
_level.Level('Meteor Shower',
|
displayname='${GAME}',
|
||||||
displayname='${GAME}',
|
gametype=EasterEggHuntGame,
|
||||||
gametype=MeteorShowerGame,
|
settings={},
|
||||||
settings={},
|
preview_texture_name='towerDPreview'),
|
||||||
preview_texture_name='rampagePreview'))
|
Level('Pro Easter Egg Hunt',
|
||||||
campaign.addlevel(
|
displayname='Pro ${GAME}',
|
||||||
_level.Level('Epic Meteor Shower',
|
gametype=EasterEggHuntGame,
|
||||||
displayname='${GAME}',
|
settings={'Pro Mode': True},
|
||||||
gametype=MeteorShowerGame,
|
preview_texture_name='towerDPreview'),
|
||||||
settings={'Epic Mode': True},
|
Level(
|
||||||
preview_texture_name='rampagePreview'))
|
name='Ninja Fight', # (unique id not seen by player)
|
||||||
campaign.addlevel(
|
displayname='${GAME}', # (readable name seen by player)
|
||||||
_level.Level('Easter Egg Hunt',
|
gametype=NinjaFightGame,
|
||||||
displayname='${GAME}',
|
settings={'preset': 'regular'},
|
||||||
gametype=EasterEggHuntGame,
|
preview_texture_name='courtyardPreview'),
|
||||||
settings={},
|
Level(name='Pro Ninja Fight',
|
||||||
preview_texture_name='towerDPreview'))
|
displayname='Pro ${GAME}',
|
||||||
campaign.addlevel(
|
gametype=NinjaFightGame,
|
||||||
_level.Level('Pro Easter Egg Hunt',
|
settings={'preset': 'pro'},
|
||||||
displayname='Pro ${GAME}',
|
preview_texture_name='courtyardPreview')
|
||||||
gametype=EasterEggHuntGame,
|
],
|
||||||
settings={'Pro Mode': True},
|
))
|
||||||
preview_texture_name='towerDPreview'))
|
|
||||||
campaign.addlevel(
|
|
||||||
_level.Level(
|
|
||||||
name='Ninja Fight', # (unique id not seen by player)
|
|
||||||
displayname='${GAME}', # (readable name seen by player)
|
|
||||||
gametype=NinjaFightGame,
|
|
||||||
settings={'preset': 'regular'},
|
|
||||||
preview_texture_name='courtyardPreview'))
|
|
||||||
campaign.addlevel(
|
|
||||||
_level.Level(name='Pro Ninja Fight',
|
|
||||||
displayname='Pro ${GAME}',
|
|
||||||
gametype=NinjaFightGame,
|
|
||||||
settings={'preset': 'pro'},
|
|
||||||
preview_texture_name='courtyardPreview'))
|
|
||||||
register_campaign(campaign)
|
|
||||||
|
|||||||
@ -42,7 +42,7 @@ class MetadataSubsystem:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.metascan: ScanResults | None = None
|
self.scanresults: ScanResults | None = None
|
||||||
self.extra_scan_dirs: list[str] = []
|
self.extra_scan_dirs: list[str] = []
|
||||||
|
|
||||||
def on_app_running(self) -> None:
|
def on_app_running(self) -> None:
|
||||||
@ -56,7 +56,7 @@ class MetadataSubsystem:
|
|||||||
|
|
||||||
Should be called only once at launch."""
|
Should be called only once at launch."""
|
||||||
app = _ba.app
|
app = _ba.app
|
||||||
if self.metascan is not None:
|
if self.scanresults is not None:
|
||||||
print('WARNING: meta scan run more than once.')
|
print('WARNING: meta scan run more than once.')
|
||||||
pythondirs = ([app.python_directory_app, app.python_directory_user] +
|
pythondirs = ([app.python_directory_app, app.python_directory_user] +
|
||||||
self.extra_scan_dirs)
|
self.extra_scan_dirs)
|
||||||
@ -131,7 +131,7 @@ class MetadataSubsystem:
|
|||||||
|
|
||||||
def get_scan_results(self) -> ScanResults:
|
def get_scan_results(self) -> ScanResults:
|
||||||
"""Return meta scan results; block if the scan is not yet complete."""
|
"""Return meta scan results; block if the scan is not yet complete."""
|
||||||
if self.metascan is None:
|
if self.scanresults is None:
|
||||||
print('WARNING: ba.meta.get_scan_results()'
|
print('WARNING: ba.meta.get_scan_results()'
|
||||||
' called before scan completed.'
|
' called before scan completed.'
|
||||||
' This can cause hitches.')
|
' This can cause hitches.')
|
||||||
@ -139,12 +139,12 @@ class MetadataSubsystem:
|
|||||||
# Now wait a bit for the scan to complete.
|
# Now wait a bit for the scan to complete.
|
||||||
# Eventually error though if it doesn't.
|
# Eventually error though if it doesn't.
|
||||||
starttime = time.time()
|
starttime = time.time()
|
||||||
while self.metascan is None:
|
while self.scanresults is None:
|
||||||
time.sleep(0.05)
|
time.sleep(0.05)
|
||||||
if time.time() - starttime > 10.0:
|
if time.time() - starttime > 10.0:
|
||||||
raise TimeoutError(
|
raise TimeoutError(
|
||||||
'timeout waiting for meta scan to complete.')
|
'timeout waiting for meta scan to complete.')
|
||||||
return self.metascan
|
return self.scanresults
|
||||||
|
|
||||||
def get_game_types(self) -> list[type[ba.GameActivity]]:
|
def get_game_types(self) -> list[type[ba.GameActivity]]:
|
||||||
"""Return available game types."""
|
"""Return available game types."""
|
||||||
@ -204,7 +204,7 @@ class ScanThread(threading.Thread):
|
|||||||
# We also, however, immediately make results available.
|
# We also, however, immediately make results available.
|
||||||
# This is because the game thread may be blocked waiting
|
# This is because the game thread may be blocked waiting
|
||||||
# for them so we can't push a call or we'd get deadlock.
|
# for them so we can't push a call or we'd get deadlock.
|
||||||
_ba.app.meta.metascan = results
|
_ba.app.meta.scanresults = results
|
||||||
|
|
||||||
|
|
||||||
class DirectoryScan:
|
class DirectoryScan:
|
||||||
|
|||||||
@ -6,7 +6,6 @@
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import copy
|
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
import _ba
|
import _ba
|
||||||
@ -18,6 +17,8 @@ from bastd.ui.store.browser import StoreBrowserWindow
|
|||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
|
from bastd.ui.coop.tournamentbutton import TournamentButton
|
||||||
|
|
||||||
|
|
||||||
class CoopBrowserWindow(ba.Window):
|
class CoopBrowserWindow(ba.Window):
|
||||||
"""Window for browsing co-op levels/games/etc."""
|
"""Window for browsing co-op levels/games/etc."""
|
||||||
@ -175,8 +176,6 @@ class CoopBrowserWindow(ba.Window):
|
|||||||
'Selected Coop Campaign Level', None))
|
'Selected Coop Campaign Level', None))
|
||||||
self._selected_custom_level = (cfg.get('Selected Coop Custom Level',
|
self._selected_custom_level = (cfg.get('Selected Coop Custom Level',
|
||||||
None))
|
None))
|
||||||
self._selected_challenge_level = (cfg.get(
|
|
||||||
'Selected Coop Challenge Level', None))
|
|
||||||
|
|
||||||
# Don't want initial construction affecting our last-selected.
|
# Don't want initial construction affecting our last-selected.
|
||||||
self._do_selection_callbacks = False
|
self._do_selection_callbacks = False
|
||||||
@ -283,6 +282,7 @@ class CoopBrowserWindow(ba.Window):
|
|||||||
import bastd.ui.tournamentscores as _unused8
|
import bastd.ui.tournamentscores as _unused8
|
||||||
import bastd.ui.tournamententry as _unused9
|
import bastd.ui.tournamententry as _unused9
|
||||||
import bastd.ui.play as _unused10
|
import bastd.ui.play as _unused10
|
||||||
|
import bastd.ui.coop.tournamentbutton as _unused11
|
||||||
|
|
||||||
def _update(self) -> None:
|
def _update(self) -> None:
|
||||||
# Do nothing if we've somehow outlived our actual UI.
|
# Do nothing if we've somehow outlived our actual UI.
|
||||||
@ -335,21 +335,21 @@ class CoopBrowserWindow(ba.Window):
|
|||||||
# Decrement time on our tournament buttons.
|
# Decrement time on our tournament buttons.
|
||||||
ads_enabled = _ba.have_incentivized_ad()
|
ads_enabled = _ba.have_incentivized_ad()
|
||||||
for tbtn in self._tournament_buttons:
|
for tbtn in self._tournament_buttons:
|
||||||
tbtn['time_remaining'] = max(0, tbtn['time_remaining'] - 1)
|
tbtn.time_remaining = max(0, tbtn.time_remaining - 1)
|
||||||
if tbtn['time_remaining_value_text'] is not None:
|
if tbtn.time_remaining_value_text is not None:
|
||||||
ba.textwidget(
|
ba.textwidget(
|
||||||
edit=tbtn['time_remaining_value_text'],
|
edit=tbtn.time_remaining_value_text,
|
||||||
text=ba.timestring(tbtn['time_remaining'],
|
text=ba.timestring(tbtn.time_remaining,
|
||||||
centi=False,
|
centi=False,
|
||||||
suppress_format_warning=True) if
|
suppress_format_warning=True) if
|
||||||
(tbtn['has_time_remaining']
|
(tbtn.has_time_remaining
|
||||||
and self._tourney_data_up_to_date) else '-')
|
and self._tourney_data_up_to_date) else '-')
|
||||||
|
|
||||||
# Also adjust the ad icon visibility.
|
# Also adjust the ad icon visibility.
|
||||||
if tbtn.get('allow_ads', False) and _ba.has_video_ads():
|
if tbtn.allow_ads and _ba.has_video_ads():
|
||||||
ba.imagewidget(edit=tbtn['entry_fee_ad_image'],
|
ba.imagewidget(edit=tbtn.entry_fee_ad_image,
|
||||||
opacity=1.0 if ads_enabled else 0.25)
|
opacity=1.0 if ads_enabled else 0.25)
|
||||||
ba.textwidget(edit=tbtn['entry_fee_text_remaining'],
|
ba.textwidget(edit=tbtn.entry_fee_text_remaining,
|
||||||
color=(0.6, 0.6, 0.6, 1 if ads_enabled else 0.2))
|
color=(0.6, 0.6, 0.6, 1 if ads_enabled else 0.2))
|
||||||
|
|
||||||
self._update_hard_mode_lock_image()
|
self._update_hard_mode_lock_image()
|
||||||
@ -363,232 +363,21 @@ class CoopBrowserWindow(ba.Window):
|
|||||||
ba.print_exception('Error updating campaign lock.')
|
ba.print_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:
|
||||||
# pylint: disable=too-many-statements
|
|
||||||
# pylint: disable=too-many-locals
|
|
||||||
# pylint: disable=too-many-branches
|
|
||||||
from ba.internal import getcampaign, get_tournament_prize_strings
|
|
||||||
|
|
||||||
# If the number of tournaments or challenges in the data differs from
|
# If the number of tournaments or challenges in the data differs from
|
||||||
# our current arrangement, refresh with the new number.
|
# our current arrangement, refresh with the new number.
|
||||||
if ((data is None and self._tournament_button_count != 0)
|
if ((data is None and self._tournament_button_count != 0)
|
||||||
or (data is not None and
|
or (data is not None and
|
||||||
(len(data) != self._tournament_button_count))):
|
(len(data) != self._tournament_button_count))):
|
||||||
self._tournament_button_count = len(
|
self._tournament_button_count = (len(data)
|
||||||
data) if data is not None else 0
|
if data is not None else 0)
|
||||||
ba.app.config['Tournament Rows'] = self._tournament_button_count
|
ba.app.config['Tournament Rows'] = self._tournament_button_count
|
||||||
self._refresh()
|
self._refresh()
|
||||||
|
|
||||||
# Update all of our tourney buttons based on whats in data.
|
# Update all of our tourney buttons based on whats in data.
|
||||||
for i, tbtn in enumerate(self._tournament_buttons):
|
for i, tbtn in enumerate(self._tournament_buttons):
|
||||||
assert data is not None
|
assert data is not None
|
||||||
entry: dict[str, Any] = data[i]
|
tbtn.update_for_data(data[i])
|
||||||
prize_y_offs = (34 if 'prizeRange3' in entry else
|
|
||||||
20 if 'prizeRange2' in entry else 12)
|
|
||||||
x_offs = 90
|
|
||||||
|
|
||||||
# This seems to be a false alarm.
|
|
||||||
# pylint: disable=unbalanced-tuple-unpacking
|
|
||||||
pr1, pv1, pr2, pv2, pr3, pv3 = (
|
|
||||||
get_tournament_prize_strings(entry))
|
|
||||||
# pylint: enable=unbalanced-tuple-unpacking
|
|
||||||
enabled = 'requiredLeague' not in entry
|
|
||||||
ba.buttonwidget(edit=tbtn['button'],
|
|
||||||
color=(0.5, 0.7, 0.2) if enabled else
|
|
||||||
(0.5, 0.5, 0.5))
|
|
||||||
ba.imagewidget(edit=tbtn['lock_image'],
|
|
||||||
opacity=0.0 if enabled else 1.0)
|
|
||||||
ba.textwidget(edit=tbtn['prize_range_1_text'],
|
|
||||||
text='-' if pr1 == '' else pr1,
|
|
||||||
position=(tbtn['button_x'] + 365 + x_offs,
|
|
||||||
tbtn['button_y'] + tbtn['button_scale_y'] -
|
|
||||||
93 + prize_y_offs))
|
|
||||||
|
|
||||||
# We want to draw values containing tickets a bit smaller
|
|
||||||
# (scratch that; we now draw medals a bit bigger).
|
|
||||||
ticket_char = ba.charstr(ba.SpecialChar.TICKET_BACKING)
|
|
||||||
prize_value_scale_large = 1.0
|
|
||||||
prize_value_scale_small = 1.0
|
|
||||||
|
|
||||||
ba.textwidget(edit=tbtn['prize_value_1_text'],
|
|
||||||
text='-' if pv1 == '' else pv1,
|
|
||||||
scale=prize_value_scale_large if ticket_char
|
|
||||||
not in pv1 else prize_value_scale_small,
|
|
||||||
position=(tbtn['button_x'] + 380 + x_offs,
|
|
||||||
tbtn['button_y'] + tbtn['button_scale_y'] -
|
|
||||||
93 + prize_y_offs))
|
|
||||||
|
|
||||||
ba.textwidget(edit=tbtn['prize_range_2_text'],
|
|
||||||
text=pr2,
|
|
||||||
position=(tbtn['button_x'] + 365 + x_offs,
|
|
||||||
tbtn['button_y'] + tbtn['button_scale_y'] -
|
|
||||||
93 - 45 + prize_y_offs))
|
|
||||||
ba.textwidget(edit=tbtn['prize_value_2_text'],
|
|
||||||
text=pv2,
|
|
||||||
scale=prize_value_scale_large if ticket_char
|
|
||||||
not in pv2 else prize_value_scale_small,
|
|
||||||
position=(tbtn['button_x'] + 380 + x_offs,
|
|
||||||
tbtn['button_y'] + tbtn['button_scale_y'] -
|
|
||||||
93 - 45 + prize_y_offs))
|
|
||||||
|
|
||||||
ba.textwidget(edit=tbtn['prize_range_3_text'],
|
|
||||||
text=pr3,
|
|
||||||
position=(tbtn['button_x'] + 365 + x_offs,
|
|
||||||
tbtn['button_y'] + tbtn['button_scale_y'] -
|
|
||||||
93 - 90 + prize_y_offs))
|
|
||||||
ba.textwidget(edit=tbtn['prize_value_3_text'],
|
|
||||||
text=pv3,
|
|
||||||
scale=prize_value_scale_large if ticket_char
|
|
||||||
not in pv3 else prize_value_scale_small,
|
|
||||||
position=(tbtn['button_x'] + 380 + x_offs,
|
|
||||||
tbtn['button_y'] + tbtn['button_scale_y'] -
|
|
||||||
93 - 90 + prize_y_offs))
|
|
||||||
|
|
||||||
leader_name = '-'
|
|
||||||
leader_score: str | ba.Lstr = '-'
|
|
||||||
if entry['scores']:
|
|
||||||
score = tbtn['leader'] = copy.deepcopy(entry['scores'][0])
|
|
||||||
leader_name = score[1]
|
|
||||||
leader_score = (ba.timestring(
|
|
||||||
score[0] * 10,
|
|
||||||
centi=True,
|
|
||||||
timeformat=ba.TimeFormat.MILLISECONDS,
|
|
||||||
suppress_format_warning=True) if entry['scoreType']
|
|
||||||
== 'time' else str(score[0]))
|
|
||||||
else:
|
|
||||||
tbtn['leader'] = None
|
|
||||||
|
|
||||||
ba.textwidget(edit=tbtn['current_leader_name_text'],
|
|
||||||
text=ba.Lstr(value=leader_name))
|
|
||||||
self._tournament_leader_score_type = (entry['scoreType'])
|
|
||||||
ba.textwidget(edit=tbtn['current_leader_score_text'],
|
|
||||||
text=leader_score)
|
|
||||||
ba.buttonwidget(edit=tbtn['more_scores_button'],
|
|
||||||
label=ba.Lstr(resource=self._r + '.seeMoreText'))
|
|
||||||
out_of_time_text: str | ba.Lstr = (
|
|
||||||
'-' if 'totalTime' not in entry else ba.Lstr(
|
|
||||||
resource=self._r + '.ofTotalTimeText',
|
|
||||||
subs=[('${TOTAL}',
|
|
||||||
ba.timestring(entry['totalTime'],
|
|
||||||
centi=False,
|
|
||||||
suppress_format_warning=True))]))
|
|
||||||
ba.textwidget(edit=tbtn['time_remaining_out_of_text'],
|
|
||||||
text=out_of_time_text)
|
|
||||||
|
|
||||||
tbtn['time_remaining'] = entry['timeRemaining']
|
|
||||||
tbtn['has_time_remaining'] = entry is not None
|
|
||||||
tbtn['tournament_id'] = entry['tournamentID']
|
|
||||||
tbtn['required_league'] = (None if 'requiredLeague' not in entry
|
|
||||||
else entry['requiredLeague'])
|
|
||||||
|
|
||||||
game = ba.app.accounts_v1.tournament_info[
|
|
||||||
tbtn['tournament_id']]['game']
|
|
||||||
|
|
||||||
if game is None:
|
|
||||||
ba.textwidget(edit=tbtn['button_text'], text='-')
|
|
||||||
ba.imagewidget(edit=tbtn['image'],
|
|
||||||
texture=ba.gettexture('black'),
|
|
||||||
opacity=0.2)
|
|
||||||
else:
|
|
||||||
campaignname, levelname = game.split(':')
|
|
||||||
campaign = getcampaign(campaignname)
|
|
||||||
max_players = ba.app.accounts_v1.tournament_info[
|
|
||||||
tbtn['tournament_id']]['maxPlayers']
|
|
||||||
txt = ba.Lstr(
|
|
||||||
value='${A} ${B}',
|
|
||||||
subs=[('${A}', campaign.getlevel(levelname).displayname),
|
|
||||||
('${B}',
|
|
||||||
ba.Lstr(resource='playerCountAbbreviatedText',
|
|
||||||
subs=[('${COUNT}', str(max_players))]))])
|
|
||||||
ba.textwidget(edit=tbtn['button_text'], text=txt)
|
|
||||||
ba.imagewidget(
|
|
||||||
edit=tbtn['image'],
|
|
||||||
texture=campaign.getlevel(levelname).get_preview_texture(),
|
|
||||||
opacity=1.0 if enabled else 0.5)
|
|
||||||
|
|
||||||
fee = entry['fee']
|
|
||||||
|
|
||||||
if fee is None:
|
|
||||||
fee_var = None
|
|
||||||
elif fee == 4:
|
|
||||||
fee_var = 'price.tournament_entry_4'
|
|
||||||
elif fee == 3:
|
|
||||||
fee_var = 'price.tournament_entry_3'
|
|
||||||
elif fee == 2:
|
|
||||||
fee_var = 'price.tournament_entry_2'
|
|
||||||
elif fee == 1:
|
|
||||||
fee_var = 'price.tournament_entry_1'
|
|
||||||
else:
|
|
||||||
if fee != 0:
|
|
||||||
print('Unknown fee value:', fee)
|
|
||||||
fee_var = 'price.tournament_entry_0'
|
|
||||||
|
|
||||||
tbtn['allow_ads'] = allow_ads = entry['allowAds']
|
|
||||||
|
|
||||||
final_fee: int | None = (None if fee_var is None else
|
|
||||||
_ba.get_v1_account_misc_read_val(
|
|
||||||
fee_var, '?'))
|
|
||||||
|
|
||||||
final_fee_str: str | ba.Lstr
|
|
||||||
if fee_var is None:
|
|
||||||
final_fee_str = ''
|
|
||||||
else:
|
|
||||||
if final_fee == 0:
|
|
||||||
final_fee_str = ba.Lstr(
|
|
||||||
resource='getTicketsWindow.freeText')
|
|
||||||
else:
|
|
||||||
final_fee_str = (
|
|
||||||
ba.charstr(ba.SpecialChar.TICKET_BACKING) +
|
|
||||||
str(final_fee))
|
|
||||||
|
|
||||||
ad_tries_remaining = ba.app.accounts_v1.tournament_info[
|
|
||||||
tbtn['tournament_id']]['adTriesRemaining']
|
|
||||||
free_tries_remaining = ba.app.accounts_v1.tournament_info[
|
|
||||||
tbtn['tournament_id']]['freeTriesRemaining']
|
|
||||||
|
|
||||||
# Now, if this fee allows ads and we support video ads, show
|
|
||||||
# the 'or ad' version.
|
|
||||||
if allow_ads and _ba.has_video_ads():
|
|
||||||
ads_enabled = _ba.have_incentivized_ad()
|
|
||||||
ba.imagewidget(edit=tbtn['entry_fee_ad_image'],
|
|
||||||
opacity=1.0 if ads_enabled else 0.25)
|
|
||||||
or_text = ba.Lstr(resource='orText',
|
|
||||||
subs=[('${A}', ''),
|
|
||||||
('${B}', '')]).evaluate().strip()
|
|
||||||
ba.textwidget(edit=tbtn['entry_fee_text_or'], text=or_text)
|
|
||||||
ba.textwidget(
|
|
||||||
edit=tbtn['entry_fee_text_top'],
|
|
||||||
position=(tbtn['button_x'] + 360,
|
|
||||||
tbtn['button_y'] + tbtn['button_scale_y'] - 60),
|
|
||||||
scale=1.3,
|
|
||||||
text=final_fee_str)
|
|
||||||
|
|
||||||
# Possibly show number of ad-plays remaining.
|
|
||||||
ba.textwidget(
|
|
||||||
edit=tbtn['entry_fee_text_remaining'],
|
|
||||||
position=(tbtn['button_x'] + 360,
|
|
||||||
tbtn['button_y'] + tbtn['button_scale_y'] - 146),
|
|
||||||
text='' if ad_tries_remaining in [None, 0] else
|
|
||||||
('' + str(ad_tries_remaining)),
|
|
||||||
color=(0.6, 0.6, 0.6, 1 if ads_enabled else 0.2))
|
|
||||||
else:
|
|
||||||
ba.imagewidget(edit=tbtn['entry_fee_ad_image'], opacity=0.0)
|
|
||||||
ba.textwidget(edit=tbtn['entry_fee_text_or'], text='')
|
|
||||||
ba.textwidget(
|
|
||||||
edit=tbtn['entry_fee_text_top'],
|
|
||||||
position=(tbtn['button_x'] + 360,
|
|
||||||
tbtn['button_y'] + tbtn['button_scale_y'] - 80),
|
|
||||||
scale=1.3,
|
|
||||||
text=final_fee_str)
|
|
||||||
|
|
||||||
# Possibly show number of free-plays remaining.
|
|
||||||
ba.textwidget(
|
|
||||||
edit=tbtn['entry_fee_text_remaining'],
|
|
||||||
position=(tbtn['button_x'] + 360,
|
|
||||||
tbtn['button_y'] + tbtn['button_scale_y'] - 100),
|
|
||||||
text=('' if (free_tries_remaining in [None, 0]
|
|
||||||
or final_fee != 0) else
|
|
||||||
('' + str(free_tries_remaining))),
|
|
||||||
color=(0.6, 0.6, 0.6, 1))
|
|
||||||
|
|
||||||
def _on_tournament_query_response(self,
|
def _on_tournament_query_response(self,
|
||||||
data: dict[str, Any] | None) -> None:
|
data: dict[str, Any] | None) -> None:
|
||||||
@ -715,10 +504,13 @@ class CoopBrowserWindow(ba.Window):
|
|||||||
items = [
|
items = [
|
||||||
campaignname + ':Onslaught Training',
|
campaignname + ':Onslaught Training',
|
||||||
campaignname + ':Rookie Onslaught',
|
campaignname + ':Rookie Onslaught',
|
||||||
campaignname + ':Rookie Football', campaignname + ':Pro Onslaught',
|
campaignname + ':Rookie Football',
|
||||||
campaignname + ':Pro Football', campaignname + ':Pro Runaround',
|
campaignname + ':Pro Onslaught',
|
||||||
campaignname + ':Uber Onslaught', campaignname + ':Uber Football',
|
campaignname + ':Pro Football',
|
||||||
campaignname + ':Uber Runaround'
|
campaignname + ':Pro Runaround',
|
||||||
|
campaignname + ':Uber Onslaught',
|
||||||
|
campaignname + ':Uber Football',
|
||||||
|
campaignname + ':Uber Runaround',
|
||||||
]
|
]
|
||||||
items += [campaignname + ':The Last Stand']
|
items += [campaignname + ':The Last Stand']
|
||||||
if self._selected_campaign_level is None:
|
if self._selected_campaign_level is None:
|
||||||
@ -772,6 +564,7 @@ class CoopBrowserWindow(ba.Window):
|
|||||||
# pylint: disable=too-many-locals
|
# pylint: disable=too-many-locals
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bastd.ui.coop.gamebutton import GameButton
|
from bastd.ui.coop.gamebutton import GameButton
|
||||||
|
from bastd.ui.coop.tournamentbutton import TournamentButton
|
||||||
|
|
||||||
# (Re)create the sub-container if need be.
|
# (Re)create the sub-container if need be.
|
||||||
if self._subcontainer is not None:
|
if self._subcontainer is not None:
|
||||||
@ -839,7 +632,7 @@ class CoopBrowserWindow(ba.Window):
|
|||||||
|
|
||||||
# Tournaments
|
# Tournaments
|
||||||
|
|
||||||
self._tournament_buttons: list[dict[str, Any]] = []
|
self._tournament_buttons: list[TournamentButton] = []
|
||||||
|
|
||||||
v -= 53
|
v -= 53
|
||||||
# FIXME shouldn't use hard-coded strings here.
|
# FIXME shouldn't use hard-coded strings here.
|
||||||
@ -919,7 +712,12 @@ class CoopBrowserWindow(ba.Window):
|
|||||||
v2 = -2
|
v2 = -2
|
||||||
is_last_sel = True
|
is_last_sel = True
|
||||||
self._tournament_buttons.append(
|
self._tournament_buttons.append(
|
||||||
self._tournament_button(sc2, h, v2, is_last_sel))
|
TournamentButton(sc2,
|
||||||
|
h,
|
||||||
|
v2,
|
||||||
|
is_last_sel,
|
||||||
|
on_pressed=ba.WeakCall(
|
||||||
|
self.run_tournament)))
|
||||||
v -= 200
|
v -= 200
|
||||||
|
|
||||||
# Custom Games.
|
# Custom Games.
|
||||||
@ -949,7 +747,8 @@ class CoopBrowserWindow(ba.Window):
|
|||||||
if _ba.get_v1_account_misc_read_val(
|
if _ba.get_v1_account_misc_read_val(
|
||||||
'easter', False) or _ba.get_purchased('games.easter_egg_hunt'):
|
'easter', False) or _ba.get_purchased('games.easter_egg_hunt'):
|
||||||
items = [
|
items = [
|
||||||
'Challenges:Easter Egg Hunt', 'Challenges:Pro Easter Egg Hunt'
|
'Challenges:Easter Egg Hunt',
|
||||||
|
'Challenges:Pro Easter Egg Hunt',
|
||||||
] + items
|
] + items
|
||||||
|
|
||||||
# add all custom user levels here..
|
# add all custom user levels here..
|
||||||
@ -995,19 +794,19 @@ class CoopBrowserWindow(ba.Window):
|
|||||||
|
|
||||||
for i, tbutton in enumerate(self._tournament_buttons):
|
for i, tbutton in enumerate(self._tournament_buttons):
|
||||||
ba.widget(
|
ba.widget(
|
||||||
edit=tbutton['button'],
|
edit=tbutton.button,
|
||||||
up_widget=self._tournament_info_button
|
up_widget=self._tournament_info_button
|
||||||
if i == 0 else self._tournament_buttons[i - 1]['button'],
|
if i == 0 else self._tournament_buttons[i - 1].button,
|
||||||
down_widget=self._tournament_buttons[(i + 1)]['button']
|
down_widget=self._tournament_buttons[(i + 1)].button
|
||||||
if i + 1 < len(self._tournament_buttons) else custom_h_scroll)
|
if i + 1 < len(self._tournament_buttons) else custom_h_scroll)
|
||||||
ba.widget(
|
ba.widget(
|
||||||
edit=tbutton['more_scores_button'],
|
edit=tbutton.more_scores_button,
|
||||||
down_widget=self._tournament_buttons[(
|
down_widget=self._tournament_buttons[(
|
||||||
i + 1)]['current_leader_name_text']
|
i + 1)].current_leader_name_text
|
||||||
if i + 1 < len(self._tournament_buttons) else custom_h_scroll)
|
if i + 1 < len(self._tournament_buttons) else custom_h_scroll)
|
||||||
ba.widget(edit=tbutton['current_leader_name_text'],
|
ba.widget(edit=tbutton.current_leader_name_text,
|
||||||
up_widget=self._tournament_info_button if i == 0 else
|
up_widget=self._tournament_info_button if i == 0 else
|
||||||
self._tournament_buttons[i - 1]['more_scores_button'])
|
self._tournament_buttons[i - 1].more_scores_button)
|
||||||
|
|
||||||
for btn in self._custom_buttons:
|
for btn in self._custom_buttons:
|
||||||
try:
|
try:
|
||||||
@ -1037,314 +836,6 @@ class CoopBrowserWindow(ba.Window):
|
|||||||
def _enable_selectable_callback(self) -> None:
|
def _enable_selectable_callback(self) -> None:
|
||||||
self._do_selection_callbacks = True
|
self._do_selection_callbacks = True
|
||||||
|
|
||||||
def _tournament_button(self, parent: ba.Widget, x: float, y: float,
|
|
||||||
select: bool) -> dict[str, Any]:
|
|
||||||
sclx = 300
|
|
||||||
scly = 195.0
|
|
||||||
data: dict[str, Any] = {
|
|
||||||
'tournament_id': None,
|
|
||||||
'time_remaining': 0,
|
|
||||||
'has_time_remaining': False,
|
|
||||||
'leader': None
|
|
||||||
}
|
|
||||||
data['button'] = btn = ba.buttonwidget(
|
|
||||||
parent=parent,
|
|
||||||
position=(x + 23, y + 4),
|
|
||||||
size=(sclx, scly),
|
|
||||||
label='',
|
|
||||||
button_type='square',
|
|
||||||
autoselect=True,
|
|
||||||
on_activate_call=lambda: self.run(None, tournament_button=data))
|
|
||||||
ba.widget(edit=btn,
|
|
||||||
show_buffer_bottom=50,
|
|
||||||
show_buffer_top=50,
|
|
||||||
show_buffer_left=400,
|
|
||||||
show_buffer_right=200)
|
|
||||||
if select:
|
|
||||||
ba.containerwidget(edit=parent,
|
|
||||||
selected_child=btn,
|
|
||||||
visible_child=btn)
|
|
||||||
image_width = sclx * 0.85 * 0.75
|
|
||||||
|
|
||||||
data['image'] = ba.imagewidget(
|
|
||||||
parent=parent,
|
|
||||||
draw_controller=btn,
|
|
||||||
position=(x + 21 + sclx * 0.5 - image_width * 0.5, y + scly - 150),
|
|
||||||
size=(image_width, image_width * 0.5),
|
|
||||||
model_transparent=self.lsbt,
|
|
||||||
model_opaque=self.lsbo,
|
|
||||||
texture=ba.gettexture('black'),
|
|
||||||
opacity=0.2,
|
|
||||||
mask_texture=ba.gettexture('mapPreviewMask'))
|
|
||||||
|
|
||||||
data['lock_image'] = ba.imagewidget(
|
|
||||||
parent=parent,
|
|
||||||
draw_controller=btn,
|
|
||||||
position=(x + 21 + sclx * 0.5 - image_width * 0.25,
|
|
||||||
y + scly - 150),
|
|
||||||
size=(image_width * 0.5, image_width * 0.5),
|
|
||||||
texture=ba.gettexture('lock'),
|
|
||||||
opacity=0.0)
|
|
||||||
|
|
||||||
data['button_text'] = ba.textwidget(parent=parent,
|
|
||||||
draw_controller=btn,
|
|
||||||
position=(x + 20 + sclx * 0.5,
|
|
||||||
y + scly - 35),
|
|
||||||
size=(0, 0),
|
|
||||||
h_align='center',
|
|
||||||
text='-',
|
|
||||||
v_align='center',
|
|
||||||
maxwidth=sclx * 0.76,
|
|
||||||
scale=0.85,
|
|
||||||
color=(0.8, 1.0, 0.8, 1.0))
|
|
||||||
|
|
||||||
header_color = (0.43, 0.4, 0.5, 1)
|
|
||||||
value_color = (0.6, 0.6, 0.6, 1)
|
|
||||||
|
|
||||||
x_offs = 0
|
|
||||||
ba.textwidget(parent=parent,
|
|
||||||
draw_controller=btn,
|
|
||||||
position=(x + 360, y + scly - 20),
|
|
||||||
size=(0, 0),
|
|
||||||
h_align='center',
|
|
||||||
text=ba.Lstr(resource=self._r + '.entryFeeText'),
|
|
||||||
v_align='center',
|
|
||||||
maxwidth=100,
|
|
||||||
scale=0.9,
|
|
||||||
color=header_color,
|
|
||||||
flatness=1.0)
|
|
||||||
|
|
||||||
data['entry_fee_text_top'] = ba.textwidget(parent=parent,
|
|
||||||
draw_controller=btn,
|
|
||||||
position=(x + 360,
|
|
||||||
y + scly - 60),
|
|
||||||
size=(0, 0),
|
|
||||||
h_align='center',
|
|
||||||
text='-',
|
|
||||||
v_align='center',
|
|
||||||
maxwidth=60,
|
|
||||||
scale=1.3,
|
|
||||||
color=value_color,
|
|
||||||
flatness=1.0)
|
|
||||||
data['entry_fee_text_or'] = ba.textwidget(parent=parent,
|
|
||||||
draw_controller=btn,
|
|
||||||
position=(x + 360,
|
|
||||||
y + scly - 90),
|
|
||||||
size=(0, 0),
|
|
||||||
h_align='center',
|
|
||||||
text='',
|
|
||||||
v_align='center',
|
|
||||||
maxwidth=60,
|
|
||||||
scale=0.5,
|
|
||||||
color=value_color,
|
|
||||||
flatness=1.0)
|
|
||||||
data['entry_fee_text_remaining'] = ba.textwidget(parent=parent,
|
|
||||||
draw_controller=btn,
|
|
||||||
position=(x + 360, y +
|
|
||||||
scly - 90),
|
|
||||||
size=(0, 0),
|
|
||||||
h_align='center',
|
|
||||||
text='',
|
|
||||||
v_align='center',
|
|
||||||
maxwidth=60,
|
|
||||||
scale=0.5,
|
|
||||||
color=value_color,
|
|
||||||
flatness=1.0)
|
|
||||||
|
|
||||||
data['entry_fee_ad_image'] = ba.imagewidget(
|
|
||||||
parent=parent,
|
|
||||||
size=(40, 40),
|
|
||||||
draw_controller=btn,
|
|
||||||
position=(x + 360 - 20, y + scly - 140),
|
|
||||||
opacity=0.0,
|
|
||||||
texture=ba.gettexture('tv'))
|
|
||||||
|
|
||||||
x_offs += 50
|
|
||||||
|
|
||||||
ba.textwidget(parent=parent,
|
|
||||||
draw_controller=btn,
|
|
||||||
position=(x + 447 + x_offs, y + scly - 20),
|
|
||||||
size=(0, 0),
|
|
||||||
h_align='center',
|
|
||||||
text=ba.Lstr(resource=self._r + '.prizesText'),
|
|
||||||
v_align='center',
|
|
||||||
maxwidth=130,
|
|
||||||
scale=0.9,
|
|
||||||
color=header_color,
|
|
||||||
flatness=1.0)
|
|
||||||
|
|
||||||
data['button_x'] = x
|
|
||||||
data['button_y'] = y
|
|
||||||
data['button_scale_y'] = scly
|
|
||||||
|
|
||||||
xo2 = 0
|
|
||||||
prize_value_scale = 1.5
|
|
||||||
|
|
||||||
data['prize_range_1_text'] = ba.textwidget(
|
|
||||||
parent=parent,
|
|
||||||
draw_controller=btn,
|
|
||||||
position=(x + 355 + xo2 + x_offs, y + scly - 93),
|
|
||||||
size=(0, 0),
|
|
||||||
h_align='right',
|
|
||||||
v_align='center',
|
|
||||||
maxwidth=50,
|
|
||||||
text='-',
|
|
||||||
scale=0.8,
|
|
||||||
color=header_color,
|
|
||||||
flatness=1.0)
|
|
||||||
data['prize_value_1_text'] = ba.textwidget(
|
|
||||||
parent=parent,
|
|
||||||
draw_controller=btn,
|
|
||||||
position=(x + 380 + xo2 + x_offs, y + scly - 93),
|
|
||||||
size=(0, 0),
|
|
||||||
h_align='left',
|
|
||||||
text='-',
|
|
||||||
v_align='center',
|
|
||||||
maxwidth=100,
|
|
||||||
scale=prize_value_scale,
|
|
||||||
color=value_color,
|
|
||||||
flatness=1.0)
|
|
||||||
|
|
||||||
data['prize_range_2_text'] = ba.textwidget(
|
|
||||||
parent=parent,
|
|
||||||
draw_controller=btn,
|
|
||||||
position=(x + 355 + xo2 + x_offs, y + scly - 93),
|
|
||||||
size=(0, 0),
|
|
||||||
h_align='right',
|
|
||||||
v_align='center',
|
|
||||||
maxwidth=50,
|
|
||||||
scale=0.8,
|
|
||||||
color=header_color,
|
|
||||||
flatness=1.0)
|
|
||||||
data['prize_value_2_text'] = ba.textwidget(
|
|
||||||
parent=parent,
|
|
||||||
draw_controller=btn,
|
|
||||||
position=(x + 380 + xo2 + x_offs, y + scly - 93),
|
|
||||||
size=(0, 0),
|
|
||||||
h_align='left',
|
|
||||||
text='',
|
|
||||||
v_align='center',
|
|
||||||
maxwidth=100,
|
|
||||||
scale=prize_value_scale,
|
|
||||||
color=value_color,
|
|
||||||
flatness=1.0)
|
|
||||||
|
|
||||||
data['prize_range_3_text'] = ba.textwidget(
|
|
||||||
parent=parent,
|
|
||||||
draw_controller=btn,
|
|
||||||
position=(x + 355 + xo2 + x_offs, y + scly - 93),
|
|
||||||
size=(0, 0),
|
|
||||||
h_align='right',
|
|
||||||
v_align='center',
|
|
||||||
maxwidth=50,
|
|
||||||
scale=0.8,
|
|
||||||
color=header_color,
|
|
||||||
flatness=1.0)
|
|
||||||
data['prize_value_3_text'] = ba.textwidget(
|
|
||||||
parent=parent,
|
|
||||||
draw_controller=btn,
|
|
||||||
position=(x + 380 + xo2 + x_offs, y + scly - 93),
|
|
||||||
size=(0, 0),
|
|
||||||
h_align='left',
|
|
||||||
text='',
|
|
||||||
v_align='center',
|
|
||||||
maxwidth=100,
|
|
||||||
scale=prize_value_scale,
|
|
||||||
color=value_color,
|
|
||||||
flatness=1.0)
|
|
||||||
|
|
||||||
ba.textwidget(parent=parent,
|
|
||||||
draw_controller=btn,
|
|
||||||
position=(x + 620 + x_offs, y + scly - 20),
|
|
||||||
size=(0, 0),
|
|
||||||
h_align='center',
|
|
||||||
text=ba.Lstr(resource=self._r + '.currentBestText'),
|
|
||||||
v_align='center',
|
|
||||||
maxwidth=180,
|
|
||||||
scale=0.9,
|
|
||||||
color=header_color,
|
|
||||||
flatness=1.0)
|
|
||||||
data['current_leader_name_text'] = ba.textwidget(
|
|
||||||
parent=parent,
|
|
||||||
draw_controller=btn,
|
|
||||||
position=(x + 620 + x_offs - (170 / 1.4) * 0.5,
|
|
||||||
y + scly - 60 - 40 * 0.5),
|
|
||||||
selectable=True,
|
|
||||||
click_activate=True,
|
|
||||||
autoselect=True,
|
|
||||||
on_activate_call=lambda: self._show_leader(tournament_button=data),
|
|
||||||
size=(170 / 1.4, 40),
|
|
||||||
h_align='center',
|
|
||||||
text='-',
|
|
||||||
v_align='center',
|
|
||||||
maxwidth=170,
|
|
||||||
scale=1.4,
|
|
||||||
color=value_color,
|
|
||||||
flatness=1.0)
|
|
||||||
data['current_leader_score_text'] = ba.textwidget(
|
|
||||||
parent=parent,
|
|
||||||
draw_controller=btn,
|
|
||||||
position=(x + 620 + x_offs, y + scly - 113 + 10),
|
|
||||||
size=(0, 0),
|
|
||||||
h_align='center',
|
|
||||||
text='-',
|
|
||||||
v_align='center',
|
|
||||||
maxwidth=170,
|
|
||||||
scale=1.8,
|
|
||||||
color=value_color,
|
|
||||||
flatness=1.0)
|
|
||||||
|
|
||||||
data['more_scores_button'] = ba.buttonwidget(
|
|
||||||
parent=parent,
|
|
||||||
position=(x + 620 + x_offs - 60, y + scly - 50 - 125),
|
|
||||||
color=(0.5, 0.5, 0.6),
|
|
||||||
textcolor=(0.7, 0.7, 0.8),
|
|
||||||
label='-',
|
|
||||||
size=(120, 40),
|
|
||||||
autoselect=True,
|
|
||||||
up_widget=data['current_leader_name_text'],
|
|
||||||
text_scale=0.6,
|
|
||||||
on_activate_call=lambda: self._show_scores(tournament_button=data))
|
|
||||||
ba.widget(edit=data['current_leader_name_text'],
|
|
||||||
down_widget=data['more_scores_button'])
|
|
||||||
|
|
||||||
ba.textwidget(parent=parent,
|
|
||||||
draw_controller=btn,
|
|
||||||
position=(x + 820 + x_offs, y + scly - 20),
|
|
||||||
size=(0, 0),
|
|
||||||
h_align='center',
|
|
||||||
text=ba.Lstr(resource=self._r + '.timeRemainingText'),
|
|
||||||
v_align='center',
|
|
||||||
maxwidth=180,
|
|
||||||
scale=0.9,
|
|
||||||
color=header_color,
|
|
||||||
flatness=1.0)
|
|
||||||
data['time_remaining_value_text'] = ba.textwidget(
|
|
||||||
parent=parent,
|
|
||||||
draw_controller=btn,
|
|
||||||
position=(x + 820 + x_offs, y + scly - 68),
|
|
||||||
size=(0, 0),
|
|
||||||
h_align='center',
|
|
||||||
text='-',
|
|
||||||
v_align='center',
|
|
||||||
maxwidth=180,
|
|
||||||
scale=2.0,
|
|
||||||
color=value_color,
|
|
||||||
flatness=1.0)
|
|
||||||
data['time_remaining_out_of_text'] = ba.textwidget(
|
|
||||||
parent=parent,
|
|
||||||
draw_controller=btn,
|
|
||||||
position=(x + 820 + x_offs, y + scly - 110),
|
|
||||||
size=(0, 0),
|
|
||||||
h_align='center',
|
|
||||||
text='-',
|
|
||||||
v_align='center',
|
|
||||||
maxwidth=120,
|
|
||||||
scale=0.72,
|
|
||||||
color=(0.4, 0.4, 0.5),
|
|
||||||
flatness=1.0)
|
|
||||||
return data
|
|
||||||
|
|
||||||
def _switch_to_league_rankings(self) -> None:
|
def _switch_to_league_rankings(self) -> None:
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bastd.ui.account import show_sign_in_prompt
|
from bastd.ui.account import show_sign_in_prompt
|
||||||
@ -1378,100 +869,20 @@ class CoopBrowserWindow(ba.Window):
|
|||||||
show_tab=show_tab,
|
show_tab=show_tab,
|
||||||
back_location='CoopBrowserWindow').get_root_widget())
|
back_location='CoopBrowserWindow').get_root_widget())
|
||||||
|
|
||||||
def _show_leader(self, tournament_button: dict[str, Any]) -> None:
|
|
||||||
# pylint: disable=cyclic-import
|
|
||||||
from bastd.ui.account.viewer import AccountViewerWindow
|
|
||||||
tournament_id = tournament_button['tournament_id']
|
|
||||||
|
|
||||||
# FIXME: This assumes a single player entry in leader; should expand
|
|
||||||
# this to work with multiple.
|
|
||||||
if tournament_id is None or tournament_button['leader'] is None or len(
|
|
||||||
tournament_button['leader'][2]) != 1:
|
|
||||||
ba.playsound(ba.getsound('error'))
|
|
||||||
return
|
|
||||||
ba.playsound(ba.getsound('swish'))
|
|
||||||
AccountViewerWindow(
|
|
||||||
account_id=tournament_button['leader'][2][0].get('a', None),
|
|
||||||
profile_id=tournament_button['leader'][2][0].get('p', None),
|
|
||||||
position=tournament_button['current_leader_name_text'].
|
|
||||||
get_screen_space_center())
|
|
||||||
|
|
||||||
def _show_scores(self, tournament_button: dict[str, Any]) -> None:
|
|
||||||
# pylint: disable=cyclic-import
|
|
||||||
from bastd.ui.tournamentscores import TournamentScoresWindow
|
|
||||||
tournament_id = tournament_button['tournament_id']
|
|
||||||
if tournament_id is None:
|
|
||||||
ba.playsound(ba.getsound('error'))
|
|
||||||
return
|
|
||||||
|
|
||||||
TournamentScoresWindow(
|
|
||||||
tournament_id=tournament_id,
|
|
||||||
position=tournament_button['more_scores_button'].
|
|
||||||
get_screen_space_center())
|
|
||||||
|
|
||||||
def is_tourney_data_up_to_date(self) -> bool:
|
def is_tourney_data_up_to_date(self) -> bool:
|
||||||
"""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(self,
|
def run_game(self, game: str) -> None:
|
||||||
game: str | None,
|
|
||||||
tournament_button: dict[str, Any] | None = None) -> None:
|
|
||||||
"""Run the provided game."""
|
"""Run the provided game."""
|
||||||
# pylint: disable=too-many-branches
|
# pylint: disable=too-many-branches
|
||||||
# pylint: disable=too-many-statements
|
|
||||||
# pylint: disable=too-many-return-statements
|
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bastd.ui.confirm import ConfirmWindow
|
from bastd.ui.confirm import ConfirmWindow
|
||||||
from bastd.ui.tournamententry import TournamentEntryWindow
|
|
||||||
from bastd.ui.purchase import PurchaseWindow
|
from bastd.ui.purchase import PurchaseWindow
|
||||||
from bastd.ui.account import show_sign_in_prompt
|
from bastd.ui.account import show_sign_in_prompt
|
||||||
args: dict[str, Any] = {}
|
args: dict[str, Any] = {}
|
||||||
|
|
||||||
# Do a bit of pre-flight for tournament options.
|
if game == 'Easy:The Last Stand':
|
||||||
if tournament_button is not None:
|
|
||||||
|
|
||||||
if _ba.get_v1_account_state() != 'signed_in':
|
|
||||||
show_sign_in_prompt()
|
|
||||||
return
|
|
||||||
|
|
||||||
if not self._tourney_data_up_to_date:
|
|
||||||
ba.screenmessage(
|
|
||||||
ba.Lstr(resource='tournamentCheckingStateText'),
|
|
||||||
color=(1, 1, 0))
|
|
||||||
ba.playsound(ba.getsound('error'))
|
|
||||||
return
|
|
||||||
|
|
||||||
if tournament_button['tournament_id'] is None:
|
|
||||||
ba.screenmessage(
|
|
||||||
ba.Lstr(resource='internal.unavailableNoConnectionText'),
|
|
||||||
color=(1, 0, 0))
|
|
||||||
ba.playsound(ba.getsound('error'))
|
|
||||||
return
|
|
||||||
|
|
||||||
if tournament_button['required_league'] is not None:
|
|
||||||
ba.screenmessage(ba.Lstr(
|
|
||||||
resource='league.tournamentLeagueText',
|
|
||||||
subs=[
|
|
||||||
('${NAME}',
|
|
||||||
ba.Lstr(
|
|
||||||
translate=('leagueNames',
|
|
||||||
tournament_button['required_league'])))
|
|
||||||
]),
|
|
||||||
color=(1, 0, 0))
|
|
||||||
ba.playsound(ba.getsound('error'))
|
|
||||||
return
|
|
||||||
|
|
||||||
if tournament_button['time_remaining'] <= 0:
|
|
||||||
ba.screenmessage(ba.Lstr(resource='tournamentEndedText'),
|
|
||||||
color=(1, 0, 0))
|
|
||||||
ba.playsound(ba.getsound('error'))
|
|
||||||
return
|
|
||||||
|
|
||||||
# Game is whatever the tournament tells us it is.
|
|
||||||
game = ba.app.accounts_v1.tournament_info[
|
|
||||||
tournament_button['tournament_id']]['game']
|
|
||||||
|
|
||||||
if tournament_button is None and game == 'Easy:The Last Stand':
|
|
||||||
ConfirmWindow(ba.Lstr(resource='difficultyHardUnlockOnlyText',
|
ConfirmWindow(ba.Lstr(resource='difficultyHardUnlockOnlyText',
|
||||||
fallback_resource='difficultyHardOnlyText'),
|
fallback_resource='difficultyHardOnlyText'),
|
||||||
cancel_button=False,
|
cancel_button=False,
|
||||||
@ -1479,12 +890,11 @@ class CoopBrowserWindow(ba.Window):
|
|||||||
height=130)
|
height=130)
|
||||||
return
|
return
|
||||||
|
|
||||||
# Infinite onslaught/runaround require pro; bring up a store link if
|
# Infinite onslaught/runaround require pro; bring up a store link
|
||||||
# need be.
|
# if need be.
|
||||||
if tournament_button is None and game in (
|
if game in ('Challenges:Infinite Runaround',
|
||||||
'Challenges:Infinite Runaround',
|
'Challenges:Infinite Onslaught'
|
||||||
'Challenges:Infinite Onslaught'
|
) and not ba.app.accounts_v1.have_pro():
|
||||||
) and not ba.app.accounts_v1.have_pro():
|
|
||||||
if _ba.get_v1_account_state() != 'signed_in':
|
if _ba.get_v1_account_state() != 'signed_in':
|
||||||
show_sign_in_prompt()
|
show_sign_in_prompt()
|
||||||
else:
|
else:
|
||||||
@ -1495,7 +905,8 @@ class CoopBrowserWindow(ba.Window):
|
|||||||
if game in ['Challenges:Meteor Shower']:
|
if game in ['Challenges:Meteor Shower']:
|
||||||
required_purchase = 'games.meteor_shower'
|
required_purchase = 'games.meteor_shower'
|
||||||
elif game in [
|
elif game in [
|
||||||
'Challenges:Target Practice', 'Challenges:Target Practice B'
|
'Challenges:Target Practice',
|
||||||
|
'Challenges:Target Practice B',
|
||||||
]:
|
]:
|
||||||
required_purchase = 'games.target_practice'
|
required_purchase = 'games.target_practice'
|
||||||
elif game in ['Challenges:Ninja Fight']:
|
elif game in ['Challenges:Ninja Fight']:
|
||||||
@ -1503,13 +914,14 @@ class CoopBrowserWindow(ba.Window):
|
|||||||
elif game in ['Challenges:Pro Ninja Fight']:
|
elif game in ['Challenges:Pro Ninja Fight']:
|
||||||
required_purchase = 'games.ninja_fight'
|
required_purchase = 'games.ninja_fight'
|
||||||
elif game in [
|
elif game in [
|
||||||
'Challenges:Easter Egg Hunt', 'Challenges:Pro Easter Egg Hunt'
|
'Challenges:Easter Egg Hunt',
|
||||||
|
'Challenges:Pro Easter Egg Hunt',
|
||||||
]:
|
]:
|
||||||
required_purchase = 'games.easter_egg_hunt'
|
required_purchase = 'games.easter_egg_hunt'
|
||||||
else:
|
else:
|
||||||
required_purchase = None
|
required_purchase = None
|
||||||
|
|
||||||
if (tournament_button is None and required_purchase is not None
|
if (required_purchase is not None
|
||||||
and not _ba.get_purchased(required_purchase)):
|
and not _ba.get_purchased(required_purchase)):
|
||||||
if _ba.get_v1_account_state() != 'signed_in':
|
if _ba.get_v1_account_state() != 'signed_in':
|
||||||
show_sign_in_prompt()
|
show_sign_in_prompt()
|
||||||
@ -1519,17 +931,57 @@ class CoopBrowserWindow(ba.Window):
|
|||||||
|
|
||||||
self._save_state()
|
self._save_state()
|
||||||
|
|
||||||
# For tournaments, we pop up the entry window.
|
if ba.app.launch_coop_game(game, args=args):
|
||||||
if tournament_button is not None:
|
ba.containerwidget(edit=self._root_widget, transition='out_left')
|
||||||
TournamentEntryWindow(
|
|
||||||
tournament_id=tournament_button['tournament_id'],
|
def run_tournament(self, tournament_button: TournamentButton) -> None:
|
||||||
position=tournament_button['button'].get_screen_space_center())
|
"""Run the provided tournament game."""
|
||||||
else:
|
from bastd.ui.account import show_sign_in_prompt
|
||||||
# Otherwise just dive right in.
|
from bastd.ui.tournamententry import TournamentEntryWindow
|
||||||
assert game is not None
|
|
||||||
if ba.app.launch_coop_game(game, args=args):
|
if _ba.get_v1_account_state() != 'signed_in':
|
||||||
ba.containerwidget(edit=self._root_widget,
|
show_sign_in_prompt()
|
||||||
transition='out_left')
|
return
|
||||||
|
|
||||||
|
if not self._tourney_data_up_to_date:
|
||||||
|
ba.screenmessage(ba.Lstr(resource='tournamentCheckingStateText'),
|
||||||
|
color=(1, 1, 0))
|
||||||
|
ba.playsound(ba.getsound('error'))
|
||||||
|
return
|
||||||
|
|
||||||
|
if tournament_button.tournament_id is None:
|
||||||
|
ba.screenmessage(
|
||||||
|
ba.Lstr(resource='internal.unavailableNoConnectionText'),
|
||||||
|
color=(1, 0, 0))
|
||||||
|
ba.playsound(ba.getsound('error'))
|
||||||
|
return
|
||||||
|
|
||||||
|
if tournament_button.required_league is not None:
|
||||||
|
ba.screenmessage(
|
||||||
|
ba.Lstr(
|
||||||
|
resource='league.tournamentLeagueText',
|
||||||
|
subs=[('${NAME}',
|
||||||
|
ba.Lstr(
|
||||||
|
translate=('leagueNames',
|
||||||
|
tournament_button.required_league)))
|
||||||
|
]),
|
||||||
|
color=(1, 0, 0),
|
||||||
|
)
|
||||||
|
ba.playsound(ba.getsound('error'))
|
||||||
|
return
|
||||||
|
|
||||||
|
if tournament_button.time_remaining <= 0:
|
||||||
|
ba.screenmessage(ba.Lstr(resource='tournamentEndedText'),
|
||||||
|
color=(1, 0, 0))
|
||||||
|
ba.playsound(ba.getsound('error'))
|
||||||
|
return
|
||||||
|
|
||||||
|
self._save_state()
|
||||||
|
|
||||||
|
assert tournament_button.tournament_id is not None
|
||||||
|
TournamentEntryWindow(
|
||||||
|
tournament_id=tournament_button.tournament_id,
|
||||||
|
position=tournament_button.button.get_screen_space_center())
|
||||||
|
|
||||||
def _back(self) -> None:
|
def _back(self) -> None:
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
@ -1542,24 +994,6 @@ class CoopBrowserWindow(ba.Window):
|
|||||||
ba.app.ui.set_main_menu_window(
|
ba.app.ui.set_main_menu_window(
|
||||||
PlayWindow(transition='in_left').get_root_widget())
|
PlayWindow(transition='in_left').get_root_widget())
|
||||||
|
|
||||||
def _restore_state(self) -> None:
|
|
||||||
try:
|
|
||||||
sel_name = ba.app.ui.window_states.get(type(self),
|
|
||||||
{}).get('sel_name')
|
|
||||||
if sel_name == 'Back':
|
|
||||||
sel = self._back_button
|
|
||||||
elif sel_name == 'Scroll':
|
|
||||||
sel = self._scrollwidget
|
|
||||||
elif sel_name == 'PowerRanking':
|
|
||||||
sel = self._league_rank_button_widget
|
|
||||||
elif sel_name == 'Store':
|
|
||||||
sel = self._store_button_widget
|
|
||||||
else:
|
|
||||||
sel = self._scrollwidget
|
|
||||||
ba.containerwidget(edit=self._root_widget, selected_child=sel)
|
|
||||||
except Exception:
|
|
||||||
ba.print_exception(f'Error restoring state for {self}.')
|
|
||||||
|
|
||||||
def _save_state(self) -> None:
|
def _save_state(self) -> None:
|
||||||
cfg = ba.app.config
|
cfg = ba.app.config
|
||||||
try:
|
try:
|
||||||
@ -1580,16 +1014,31 @@ class CoopBrowserWindow(ba.Window):
|
|||||||
|
|
||||||
cfg['Selected Coop Row'] = self._selected_row
|
cfg['Selected Coop Row'] = self._selected_row
|
||||||
cfg['Selected Coop Custom Level'] = self._selected_custom_level
|
cfg['Selected Coop Custom Level'] = self._selected_custom_level
|
||||||
cfg['Selected Coop Challenge Level'] = self._selected_challenge_level
|
|
||||||
cfg['Selected Coop Campaign Level'] = self._selected_campaign_level
|
cfg['Selected Coop Campaign Level'] = self._selected_campaign_level
|
||||||
cfg.commit()
|
cfg.commit()
|
||||||
|
|
||||||
|
def _restore_state(self) -> None:
|
||||||
|
try:
|
||||||
|
sel_name = ba.app.ui.window_states.get(type(self),
|
||||||
|
{}).get('sel_name')
|
||||||
|
if sel_name == 'Back':
|
||||||
|
sel = self._back_button
|
||||||
|
elif sel_name == 'Scroll':
|
||||||
|
sel = self._scrollwidget
|
||||||
|
elif sel_name == 'PowerRanking':
|
||||||
|
sel = self._league_rank_button_widget
|
||||||
|
elif sel_name == 'Store':
|
||||||
|
sel = self._store_button_widget
|
||||||
|
else:
|
||||||
|
sel = self._scrollwidget
|
||||||
|
ba.containerwidget(edit=self._root_widget, selected_child=sel)
|
||||||
|
except Exception:
|
||||||
|
ba.print_exception(f'Error restoring state for {self}.')
|
||||||
|
|
||||||
def sel_change(self, row: str, game: str) -> None:
|
def sel_change(self, row: str, game: str) -> None:
|
||||||
"""(internal)"""
|
"""(internal)"""
|
||||||
if self._do_selection_callbacks:
|
if self._do_selection_callbacks:
|
||||||
if row == 'custom':
|
if row == 'custom':
|
||||||
self._selected_custom_level = game
|
self._selected_custom_level = game
|
||||||
if row == 'challenges':
|
|
||||||
self._selected_challenge_level = game
|
|
||||||
elif row == 'campaign':
|
elif row == 'campaign':
|
||||||
self._selected_campaign_level = game
|
self._selected_campaign_level = game
|
||||||
|
|||||||
@ -55,7 +55,7 @@ class GameButton:
|
|||||||
position=(x + 23, y + 4),
|
position=(x + 23, y + 4),
|
||||||
size=(sclx, scly),
|
size=(sclx, scly),
|
||||||
label='',
|
label='',
|
||||||
on_activate_call=ba.Call(window.run, game),
|
on_activate_call=ba.Call(window.run_game, game),
|
||||||
button_type='square',
|
button_type='square',
|
||||||
autoselect=True,
|
autoselect=True,
|
||||||
on_select_call=ba.Call(window.sel_change, row, game))
|
on_select_call=ba.Call(window.sel_change, row, game))
|
||||||
|
|||||||
561
assets/src/ba_data/python/bastd/ui/coop/tournamentbutton.py
Normal file
561
assets/src/ba_data/python/bastd/ui/coop/tournamentbutton.py
Normal file
@ -0,0 +1,561 @@
|
|||||||
|
# Released under the MIT License. See LICENSE for details.
|
||||||
|
#
|
||||||
|
"""Defines button for co-op games."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
import copy
|
||||||
|
|
||||||
|
import ba
|
||||||
|
import _ba
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from typing import Any, Callable
|
||||||
|
|
||||||
|
|
||||||
|
class TournamentButton:
|
||||||
|
"""Button showing a tournament in coop window."""
|
||||||
|
|
||||||
|
def __init__(self, parent: ba.Widget, x: float, y: float, select: bool,
|
||||||
|
on_pressed: Callable[[TournamentButton], None]) -> None:
|
||||||
|
self._r = 'coopSelectWindow'
|
||||||
|
sclx = 300
|
||||||
|
scly = 195.0
|
||||||
|
self.on_pressed = on_pressed
|
||||||
|
self.lsbt = ba.getmodel('level_select_button_transparent')
|
||||||
|
self.lsbo = ba.getmodel('level_select_button_opaque')
|
||||||
|
self.allow_ads = False
|
||||||
|
self.tournament_id: str | None = None
|
||||||
|
self.time_remaining: int = 0
|
||||||
|
self.has_time_remaining: bool = False
|
||||||
|
self.leader: Any = None
|
||||||
|
self.required_league: str | None = None
|
||||||
|
self.button = btn = ba.buttonwidget(
|
||||||
|
parent=parent,
|
||||||
|
position=(x + 23, y + 4),
|
||||||
|
size=(sclx, scly),
|
||||||
|
label='',
|
||||||
|
button_type='square',
|
||||||
|
autoselect=True,
|
||||||
|
# on_activate_call=lambda: self.run(None, tournament_button=data)
|
||||||
|
on_activate_call=ba.WeakCall(self._pressed))
|
||||||
|
ba.widget(edit=btn,
|
||||||
|
show_buffer_bottom=50,
|
||||||
|
show_buffer_top=50,
|
||||||
|
show_buffer_left=400,
|
||||||
|
show_buffer_right=200)
|
||||||
|
if select:
|
||||||
|
ba.containerwidget(edit=parent,
|
||||||
|
selected_child=btn,
|
||||||
|
visible_child=btn)
|
||||||
|
image_width = sclx * 0.85 * 0.75
|
||||||
|
|
||||||
|
self.image = ba.imagewidget(
|
||||||
|
parent=parent,
|
||||||
|
draw_controller=btn,
|
||||||
|
position=(x + 21 + sclx * 0.5 - image_width * 0.5, y + scly - 150),
|
||||||
|
size=(image_width, image_width * 0.5),
|
||||||
|
model_transparent=self.lsbt,
|
||||||
|
model_opaque=self.lsbo,
|
||||||
|
texture=ba.gettexture('black'),
|
||||||
|
opacity=0.2,
|
||||||
|
mask_texture=ba.gettexture('mapPreviewMask'))
|
||||||
|
|
||||||
|
self.lock_image = ba.imagewidget(
|
||||||
|
parent=parent,
|
||||||
|
draw_controller=btn,
|
||||||
|
position=(x + 21 + sclx * 0.5 - image_width * 0.25,
|
||||||
|
y + scly - 150),
|
||||||
|
size=(image_width * 0.5, image_width * 0.5),
|
||||||
|
texture=ba.gettexture('lock'),
|
||||||
|
opacity=0.0)
|
||||||
|
|
||||||
|
self.button_text = ba.textwidget(parent=parent,
|
||||||
|
draw_controller=btn,
|
||||||
|
position=(x + 20 + sclx * 0.5,
|
||||||
|
y + scly - 35),
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='center',
|
||||||
|
text='-',
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=sclx * 0.76,
|
||||||
|
scale=0.85,
|
||||||
|
color=(0.8, 1.0, 0.8, 1.0))
|
||||||
|
|
||||||
|
header_color = (0.43, 0.4, 0.5, 1)
|
||||||
|
value_color = (0.6, 0.6, 0.6, 1)
|
||||||
|
|
||||||
|
x_offs = 0
|
||||||
|
ba.textwidget(parent=parent,
|
||||||
|
draw_controller=btn,
|
||||||
|
position=(x + 360, y + scly - 20),
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='center',
|
||||||
|
text=ba.Lstr(resource=self._r + '.entryFeeText'),
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=100,
|
||||||
|
scale=0.9,
|
||||||
|
color=header_color,
|
||||||
|
flatness=1.0)
|
||||||
|
|
||||||
|
self.entry_fee_text_top = ba.textwidget(parent=parent,
|
||||||
|
draw_controller=btn,
|
||||||
|
position=(x + 360,
|
||||||
|
y + scly - 60),
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='center',
|
||||||
|
text='-',
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=60,
|
||||||
|
scale=1.3,
|
||||||
|
color=value_color,
|
||||||
|
flatness=1.0)
|
||||||
|
self.entry_fee_text_or = ba.textwidget(parent=parent,
|
||||||
|
draw_controller=btn,
|
||||||
|
position=(x + 360,
|
||||||
|
y + scly - 90),
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='center',
|
||||||
|
text='',
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=60,
|
||||||
|
scale=0.5,
|
||||||
|
color=value_color,
|
||||||
|
flatness=1.0)
|
||||||
|
self.entry_fee_text_remaining = ba.textwidget(parent=parent,
|
||||||
|
draw_controller=btn,
|
||||||
|
position=(x + 360,
|
||||||
|
y + scly - 90),
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='center',
|
||||||
|
text='',
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=60,
|
||||||
|
scale=0.5,
|
||||||
|
color=value_color,
|
||||||
|
flatness=1.0)
|
||||||
|
|
||||||
|
self.entry_fee_ad_image = ba.imagewidget(parent=parent,
|
||||||
|
size=(40, 40),
|
||||||
|
draw_controller=btn,
|
||||||
|
position=(x + 360 - 20,
|
||||||
|
y + scly - 140),
|
||||||
|
opacity=0.0,
|
||||||
|
texture=ba.gettexture('tv'))
|
||||||
|
|
||||||
|
x_offs += 50
|
||||||
|
|
||||||
|
ba.textwidget(parent=parent,
|
||||||
|
draw_controller=btn,
|
||||||
|
position=(x + 447 + x_offs, y + scly - 20),
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='center',
|
||||||
|
text=ba.Lstr(resource=self._r + '.prizesText'),
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=130,
|
||||||
|
scale=0.9,
|
||||||
|
color=header_color,
|
||||||
|
flatness=1.0)
|
||||||
|
|
||||||
|
self.button_x = x
|
||||||
|
self.button_y = y
|
||||||
|
self.button_scale_y = scly
|
||||||
|
|
||||||
|
xo2 = 0
|
||||||
|
prize_value_scale = 1.5
|
||||||
|
|
||||||
|
self.prize_range_1_text = ba.textwidget(
|
||||||
|
parent=parent,
|
||||||
|
draw_controller=btn,
|
||||||
|
position=(x + 355 + xo2 + x_offs, y + scly - 93),
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='right',
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=50,
|
||||||
|
text='-',
|
||||||
|
scale=0.8,
|
||||||
|
color=header_color,
|
||||||
|
flatness=1.0)
|
||||||
|
self.prize_value_1_text = ba.textwidget(
|
||||||
|
parent=parent,
|
||||||
|
draw_controller=btn,
|
||||||
|
position=(x + 380 + xo2 + x_offs, y + scly - 93),
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='left',
|
||||||
|
text='-',
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=100,
|
||||||
|
scale=prize_value_scale,
|
||||||
|
color=value_color,
|
||||||
|
flatness=1.0)
|
||||||
|
|
||||||
|
self.prize_range_2_text = ba.textwidget(
|
||||||
|
parent=parent,
|
||||||
|
draw_controller=btn,
|
||||||
|
position=(x + 355 + xo2 + x_offs, y + scly - 93),
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='right',
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=50,
|
||||||
|
scale=0.8,
|
||||||
|
color=header_color,
|
||||||
|
flatness=1.0)
|
||||||
|
self.prize_value_2_text = ba.textwidget(
|
||||||
|
parent=parent,
|
||||||
|
draw_controller=btn,
|
||||||
|
position=(x + 380 + xo2 + x_offs, y + scly - 93),
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='left',
|
||||||
|
text='',
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=100,
|
||||||
|
scale=prize_value_scale,
|
||||||
|
color=value_color,
|
||||||
|
flatness=1.0)
|
||||||
|
|
||||||
|
self.prize_range_3_text = ba.textwidget(
|
||||||
|
parent=parent,
|
||||||
|
draw_controller=btn,
|
||||||
|
position=(x + 355 + xo2 + x_offs, y + scly - 93),
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='right',
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=50,
|
||||||
|
scale=0.8,
|
||||||
|
color=header_color,
|
||||||
|
flatness=1.0)
|
||||||
|
self.prize_value_3_text = ba.textwidget(
|
||||||
|
parent=parent,
|
||||||
|
draw_controller=btn,
|
||||||
|
position=(x + 380 + xo2 + x_offs, y + scly - 93),
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='left',
|
||||||
|
text='',
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=100,
|
||||||
|
scale=prize_value_scale,
|
||||||
|
color=value_color,
|
||||||
|
flatness=1.0)
|
||||||
|
|
||||||
|
ba.textwidget(parent=parent,
|
||||||
|
draw_controller=btn,
|
||||||
|
position=(x + 620 + x_offs, y + scly - 20),
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='center',
|
||||||
|
text=ba.Lstr(resource=self._r + '.currentBestText'),
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=180,
|
||||||
|
scale=0.9,
|
||||||
|
color=header_color,
|
||||||
|
flatness=1.0)
|
||||||
|
self.current_leader_name_text = ba.textwidget(
|
||||||
|
parent=parent,
|
||||||
|
draw_controller=btn,
|
||||||
|
position=(x + 620 + x_offs - (170 / 1.4) * 0.5,
|
||||||
|
y + scly - 60 - 40 * 0.5),
|
||||||
|
selectable=True,
|
||||||
|
click_activate=True,
|
||||||
|
autoselect=True,
|
||||||
|
on_activate_call=ba.WeakCall(self._show_leader),
|
||||||
|
size=(170 / 1.4, 40),
|
||||||
|
h_align='center',
|
||||||
|
text='-',
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=170,
|
||||||
|
scale=1.4,
|
||||||
|
color=value_color,
|
||||||
|
flatness=1.0)
|
||||||
|
self.current_leader_score_text = ba.textwidget(
|
||||||
|
parent=parent,
|
||||||
|
draw_controller=btn,
|
||||||
|
position=(x + 620 + x_offs, y + scly - 113 + 10),
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='center',
|
||||||
|
text='-',
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=170,
|
||||||
|
scale=1.8,
|
||||||
|
color=value_color,
|
||||||
|
flatness=1.0)
|
||||||
|
|
||||||
|
self.more_scores_button = ba.buttonwidget(
|
||||||
|
parent=parent,
|
||||||
|
position=(x + 620 + x_offs - 60, y + scly - 50 - 125),
|
||||||
|
color=(0.5, 0.5, 0.6),
|
||||||
|
textcolor=(0.7, 0.7, 0.8),
|
||||||
|
label='-',
|
||||||
|
size=(120, 40),
|
||||||
|
autoselect=True,
|
||||||
|
up_widget=self.current_leader_name_text,
|
||||||
|
text_scale=0.6,
|
||||||
|
on_activate_call=ba.WeakCall(self._show_scores))
|
||||||
|
ba.widget(edit=self.current_leader_name_text,
|
||||||
|
down_widget=self.more_scores_button)
|
||||||
|
|
||||||
|
ba.textwidget(parent=parent,
|
||||||
|
draw_controller=btn,
|
||||||
|
position=(x + 820 + x_offs, y + scly - 20),
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='center',
|
||||||
|
text=ba.Lstr(resource=self._r + '.timeRemainingText'),
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=180,
|
||||||
|
scale=0.9,
|
||||||
|
color=header_color,
|
||||||
|
flatness=1.0)
|
||||||
|
self.time_remaining_value_text = ba.textwidget(
|
||||||
|
parent=parent,
|
||||||
|
draw_controller=btn,
|
||||||
|
position=(x + 820 + x_offs, y + scly - 68),
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='center',
|
||||||
|
text='-',
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=180,
|
||||||
|
scale=2.0,
|
||||||
|
color=value_color,
|
||||||
|
flatness=1.0)
|
||||||
|
self.time_remaining_out_of_text = ba.textwidget(
|
||||||
|
parent=parent,
|
||||||
|
draw_controller=btn,
|
||||||
|
position=(x + 820 + x_offs, y + scly - 110),
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='center',
|
||||||
|
text='-',
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=120,
|
||||||
|
scale=0.72,
|
||||||
|
color=(0.4, 0.4, 0.5),
|
||||||
|
flatness=1.0)
|
||||||
|
|
||||||
|
def _pressed(self) -> None:
|
||||||
|
self.on_pressed(self)
|
||||||
|
|
||||||
|
def _show_leader(self) -> None:
|
||||||
|
# pylint: disable=cyclic-import
|
||||||
|
from bastd.ui.account.viewer import AccountViewerWindow
|
||||||
|
tournament_id = self.tournament_id
|
||||||
|
|
||||||
|
# FIXME: This assumes a single player entry in leader; should expand
|
||||||
|
# this to work with multiple.
|
||||||
|
if tournament_id is None or self.leader is None or len(
|
||||||
|
self.leader[2]) != 1:
|
||||||
|
ba.playsound(ba.getsound('error'))
|
||||||
|
return
|
||||||
|
ba.playsound(ba.getsound('swish'))
|
||||||
|
AccountViewerWindow(
|
||||||
|
account_id=self.leader[2][0].get('a', None),
|
||||||
|
profile_id=self.leader[2][0].get('p', None),
|
||||||
|
position=self.current_leader_name_text.get_screen_space_center())
|
||||||
|
|
||||||
|
def _show_scores(self) -> None:
|
||||||
|
# pylint: disable=cyclic-import
|
||||||
|
from bastd.ui.tournamentscores import TournamentScoresWindow
|
||||||
|
tournament_id = self.tournament_id
|
||||||
|
if tournament_id is None:
|
||||||
|
ba.playsound(ba.getsound('error'))
|
||||||
|
return
|
||||||
|
|
||||||
|
TournamentScoresWindow(
|
||||||
|
tournament_id=tournament_id,
|
||||||
|
position=self.more_scores_button.get_screen_space_center())
|
||||||
|
|
||||||
|
def update_for_data(self, entry: dict[str, Any]) -> None:
|
||||||
|
"""Update for new incoming data."""
|
||||||
|
# pylint: disable=too-many-statements
|
||||||
|
# pylint: disable=too-many-locals
|
||||||
|
# pylint: disable=too-many-branches
|
||||||
|
from ba.internal import getcampaign, get_tournament_prize_strings
|
||||||
|
prize_y_offs = (34 if 'prizeRange3' in entry else
|
||||||
|
20 if 'prizeRange2' in entry else 12)
|
||||||
|
x_offs = 90
|
||||||
|
|
||||||
|
# This seems to be a false alarm.
|
||||||
|
# pylint: disable=unbalanced-tuple-unpacking
|
||||||
|
pr1, pv1, pr2, pv2, pr3, pv3 = (get_tournament_prize_strings(entry))
|
||||||
|
# pylint: enable=unbalanced-tuple-unpacking
|
||||||
|
enabled = 'requiredLeague' not in entry
|
||||||
|
ba.buttonwidget(edit=self.button,
|
||||||
|
color=(0.5, 0.7, 0.2) if enabled else (0.5, 0.5, 0.5))
|
||||||
|
ba.imagewidget(edit=self.lock_image, opacity=0.0 if enabled else 1.0)
|
||||||
|
ba.textwidget(edit=self.prize_range_1_text,
|
||||||
|
text='-' if pr1 == '' else pr1,
|
||||||
|
position=(self.button_x + 365 + x_offs, self.button_y +
|
||||||
|
self.button_scale_y - 93 + prize_y_offs))
|
||||||
|
|
||||||
|
# We want to draw values containing tickets a bit smaller
|
||||||
|
# (scratch that; we now draw medals a bit bigger).
|
||||||
|
ticket_char = ba.charstr(ba.SpecialChar.TICKET_BACKING)
|
||||||
|
prize_value_scale_large = 1.0
|
||||||
|
prize_value_scale_small = 1.0
|
||||||
|
|
||||||
|
ba.textwidget(edit=self.prize_value_1_text,
|
||||||
|
text='-' if pv1 == '' else pv1,
|
||||||
|
scale=prize_value_scale_large
|
||||||
|
if ticket_char not in pv1 else prize_value_scale_small,
|
||||||
|
position=(self.button_x + 380 + x_offs, self.button_y +
|
||||||
|
self.button_scale_y - 93 + prize_y_offs))
|
||||||
|
|
||||||
|
ba.textwidget(edit=self.prize_range_2_text,
|
||||||
|
text=pr2,
|
||||||
|
position=(self.button_x + 365 + x_offs, self.button_y +
|
||||||
|
self.button_scale_y - 93 - 45 + prize_y_offs))
|
||||||
|
ba.textwidget(edit=self.prize_value_2_text,
|
||||||
|
text=pv2,
|
||||||
|
scale=prize_value_scale_large
|
||||||
|
if ticket_char not in pv2 else prize_value_scale_small,
|
||||||
|
position=(self.button_x + 380 + x_offs, self.button_y +
|
||||||
|
self.button_scale_y - 93 - 45 + prize_y_offs))
|
||||||
|
|
||||||
|
ba.textwidget(edit=self.prize_range_3_text,
|
||||||
|
text=pr3,
|
||||||
|
position=(self.button_x + 365 + x_offs, self.button_y +
|
||||||
|
self.button_scale_y - 93 - 90 + prize_y_offs))
|
||||||
|
ba.textwidget(edit=self.prize_value_3_text,
|
||||||
|
text=pv3,
|
||||||
|
scale=prize_value_scale_large
|
||||||
|
if ticket_char not in pv3 else prize_value_scale_small,
|
||||||
|
position=(self.button_x + 380 + x_offs, self.button_y +
|
||||||
|
self.button_scale_y - 93 - 90 + prize_y_offs))
|
||||||
|
|
||||||
|
leader_name = '-'
|
||||||
|
leader_score: str | ba.Lstr = '-'
|
||||||
|
if entry['scores']:
|
||||||
|
score = self.leader = copy.deepcopy(entry['scores'][0])
|
||||||
|
leader_name = score[1]
|
||||||
|
leader_score = (ba.timestring(
|
||||||
|
score[0] * 10,
|
||||||
|
centi=True,
|
||||||
|
timeformat=ba.TimeFormat.MILLISECONDS,
|
||||||
|
suppress_format_warning=True)
|
||||||
|
if entry['scoreType'] == 'time' else str(score[0]))
|
||||||
|
else:
|
||||||
|
self.leader = None
|
||||||
|
|
||||||
|
ba.textwidget(edit=self.current_leader_name_text,
|
||||||
|
text=ba.Lstr(value=leader_name))
|
||||||
|
ba.textwidget(edit=self.current_leader_score_text, text=leader_score)
|
||||||
|
ba.buttonwidget(edit=self.more_scores_button,
|
||||||
|
label=ba.Lstr(resource=self._r + '.seeMoreText'))
|
||||||
|
out_of_time_text: str | ba.Lstr = (
|
||||||
|
'-' if 'totalTime' not in entry else ba.Lstr(
|
||||||
|
resource=self._r + '.ofTotalTimeText',
|
||||||
|
subs=[('${TOTAL}',
|
||||||
|
ba.timestring(entry['totalTime'],
|
||||||
|
centi=False,
|
||||||
|
suppress_format_warning=True))]))
|
||||||
|
ba.textwidget(edit=self.time_remaining_out_of_text,
|
||||||
|
text=out_of_time_text)
|
||||||
|
|
||||||
|
self.time_remaining = entry['timeRemaining']
|
||||||
|
self.has_time_remaining = entry is not None
|
||||||
|
self.tournament_id = entry['tournamentID']
|
||||||
|
self.required_league = (None if 'requiredLeague' not in entry else
|
||||||
|
entry['requiredLeague'])
|
||||||
|
|
||||||
|
game = ba.app.accounts_v1.tournament_info[self.tournament_id]['game']
|
||||||
|
|
||||||
|
if game is None:
|
||||||
|
ba.textwidget(edit=self.button_text, text='-')
|
||||||
|
ba.imagewidget(edit=self.image,
|
||||||
|
texture=ba.gettexture('black'),
|
||||||
|
opacity=0.2)
|
||||||
|
else:
|
||||||
|
campaignname, levelname = game.split(':')
|
||||||
|
campaign = getcampaign(campaignname)
|
||||||
|
max_players = ba.app.accounts_v1.tournament_info[
|
||||||
|
self.tournament_id]['maxPlayers']
|
||||||
|
txt = ba.Lstr(value='${A} ${B}',
|
||||||
|
subs=[('${A}',
|
||||||
|
campaign.getlevel(levelname).displayname),
|
||||||
|
('${B}',
|
||||||
|
ba.Lstr(resource='playerCountAbbreviatedText',
|
||||||
|
subs=[('${COUNT}', str(max_players))
|
||||||
|
]))])
|
||||||
|
ba.textwidget(edit=self.button_text, text=txt)
|
||||||
|
ba.imagewidget(
|
||||||
|
edit=self.image,
|
||||||
|
texture=campaign.getlevel(levelname).get_preview_texture(),
|
||||||
|
opacity=1.0 if enabled else 0.5)
|
||||||
|
|
||||||
|
fee = entry['fee']
|
||||||
|
|
||||||
|
if fee is None:
|
||||||
|
fee_var = None
|
||||||
|
elif fee == 4:
|
||||||
|
fee_var = 'price.tournament_entry_4'
|
||||||
|
elif fee == 3:
|
||||||
|
fee_var = 'price.tournament_entry_3'
|
||||||
|
elif fee == 2:
|
||||||
|
fee_var = 'price.tournament_entry_2'
|
||||||
|
elif fee == 1:
|
||||||
|
fee_var = 'price.tournament_entry_1'
|
||||||
|
else:
|
||||||
|
if fee != 0:
|
||||||
|
print('Unknown fee value:', fee)
|
||||||
|
fee_var = 'price.tournament_entry_0'
|
||||||
|
|
||||||
|
self.allow_ads = allow_ads = entry['allowAds']
|
||||||
|
|
||||||
|
final_fee: int | None = (None if fee_var is None else
|
||||||
|
_ba.get_v1_account_misc_read_val(
|
||||||
|
fee_var, '?'))
|
||||||
|
|
||||||
|
final_fee_str: str | ba.Lstr
|
||||||
|
if fee_var is None:
|
||||||
|
final_fee_str = ''
|
||||||
|
else:
|
||||||
|
if final_fee == 0:
|
||||||
|
final_fee_str = ba.Lstr(resource='getTicketsWindow.freeText')
|
||||||
|
else:
|
||||||
|
final_fee_str = (ba.charstr(ba.SpecialChar.TICKET_BACKING) +
|
||||||
|
str(final_fee))
|
||||||
|
|
||||||
|
ad_tries_remaining = ba.app.accounts_v1.tournament_info[
|
||||||
|
self.tournament_id]['adTriesRemaining']
|
||||||
|
free_tries_remaining = ba.app.accounts_v1.tournament_info[
|
||||||
|
self.tournament_id]['freeTriesRemaining']
|
||||||
|
|
||||||
|
# Now, if this fee allows ads and we support video ads, show
|
||||||
|
# the 'or ad' version.
|
||||||
|
if allow_ads and _ba.has_video_ads():
|
||||||
|
ads_enabled = _ba.have_incentivized_ad()
|
||||||
|
ba.imagewidget(edit=self.entry_fee_ad_image,
|
||||||
|
opacity=1.0 if ads_enabled else 0.25)
|
||||||
|
or_text = ba.Lstr(resource='orText',
|
||||||
|
subs=[('${A}', ''),
|
||||||
|
('${B}', '')]).evaluate().strip()
|
||||||
|
ba.textwidget(edit=self.entry_fee_text_or, text=or_text)
|
||||||
|
ba.textwidget(edit=self.entry_fee_text_top,
|
||||||
|
position=(self.button_x + 360,
|
||||||
|
self.button_y + self.button_scale_y - 60),
|
||||||
|
scale=1.3,
|
||||||
|
text=final_fee_str)
|
||||||
|
|
||||||
|
# Possibly show number of ad-plays remaining.
|
||||||
|
ba.textwidget(edit=self.entry_fee_text_remaining,
|
||||||
|
position=(self.button_x + 360,
|
||||||
|
self.button_y + self.button_scale_y - 146),
|
||||||
|
text='' if ad_tries_remaining in [None, 0] else
|
||||||
|
('' + str(ad_tries_remaining)),
|
||||||
|
color=(0.6, 0.6, 0.6, 1 if ads_enabled else 0.2))
|
||||||
|
else:
|
||||||
|
ba.imagewidget(edit=self.entry_fee_ad_image, opacity=0.0)
|
||||||
|
ba.textwidget(edit=self.entry_fee_text_or, text='')
|
||||||
|
ba.textwidget(edit=self.entry_fee_text_top,
|
||||||
|
position=(self.button_x + 360,
|
||||||
|
self.button_y + self.button_scale_y - 80),
|
||||||
|
scale=1.3,
|
||||||
|
text=final_fee_str)
|
||||||
|
|
||||||
|
# Possibly show number of free-plays remaining.
|
||||||
|
ba.textwidget(
|
||||||
|
edit=self.entry_fee_text_remaining,
|
||||||
|
position=(self.button_x + 360,
|
||||||
|
self.button_y + self.button_scale_y - 100),
|
||||||
|
text=('' if (free_tries_remaining in [None, 0]
|
||||||
|
or final_fee != 0) else
|
||||||
|
('' + str(free_tries_remaining))),
|
||||||
|
color=(0.6, 0.6, 0.6, 1),
|
||||||
|
)
|
||||||
@ -213,8 +213,8 @@ class OnScreenKeyboardWindow(ba.Window):
|
|||||||
|
|
||||||
# Show change instructions only if we have more than one
|
# Show change instructions only if we have more than one
|
||||||
# keyboard option.
|
# keyboard option.
|
||||||
if (ba.app.meta.metascan is not None
|
if (ba.app.meta.scanresults is not None
|
||||||
and len(ba.app.meta.metascan.keyboards) > 1):
|
and len(ba.app.meta.scanresults.keyboards) > 1):
|
||||||
ba.textwidget(
|
ba.textwidget(
|
||||||
parent=self._root_widget,
|
parent=self._root_widget,
|
||||||
h_align='center',
|
h_align='center',
|
||||||
@ -238,8 +238,8 @@ class OnScreenKeyboardWindow(ba.Window):
|
|||||||
self._refresh()
|
self._refresh()
|
||||||
|
|
||||||
def _get_keyboard(self) -> ba.Keyboard:
|
def _get_keyboard(self) -> ba.Keyboard:
|
||||||
assert ba.app.meta.metascan is not None
|
assert ba.app.meta.scanresults is not None
|
||||||
classname = ba.app.meta.metascan.keyboards[self._keyboard_index]
|
classname = ba.app.meta.scanresults.keyboards[self._keyboard_index]
|
||||||
kbclass = ba.getclass(classname, ba.Keyboard)
|
kbclass = ba.getclass(classname, ba.Keyboard)
|
||||||
return kbclass()
|
return kbclass()
|
||||||
|
|
||||||
@ -317,11 +317,11 @@ class OnScreenKeyboardWindow(ba.Window):
|
|||||||
self._refresh()
|
self._refresh()
|
||||||
|
|
||||||
def _next_keyboard(self) -> None:
|
def _next_keyboard(self) -> None:
|
||||||
assert ba.app.meta.metascan is not None
|
assert ba.app.meta.scanresults is not None
|
||||||
self._keyboard_index = (self._keyboard_index + 1) % len(
|
self._keyboard_index = (self._keyboard_index + 1) % len(
|
||||||
ba.app.meta.metascan.keyboards)
|
ba.app.meta.scanresults.keyboards)
|
||||||
self._load_keyboard()
|
self._load_keyboard()
|
||||||
if len(ba.app.meta.metascan.keyboards) < 2:
|
if len(ba.app.meta.scanresults.keyboards) < 2:
|
||||||
ba.playsound(ba.getsound('error'))
|
ba.playsound(ba.getsound('error'))
|
||||||
ba.screenmessage(ba.Lstr(resource='keyboardNoOthersAvailableText'),
|
ba.screenmessage(ba.Lstr(resource='keyboardNoOthersAvailableText'),
|
||||||
color=(1, 0, 0))
|
color=(1, 0, 0))
|
||||||
|
|||||||
@ -93,7 +93,7 @@ class PluginSettingsWindow(ba.Window):
|
|||||||
self._subcontainer = ba.columnwidget(parent=self._scrollwidget,
|
self._subcontainer = ba.columnwidget(parent=self._scrollwidget,
|
||||||
selection_loops_to_parent=True)
|
selection_loops_to_parent=True)
|
||||||
|
|
||||||
if ba.app.meta.metascan is None:
|
if ba.app.meta.scanresults is None:
|
||||||
ba.screenmessage('Still scanning plugins; please try again.',
|
ba.screenmessage('Still scanning plugins; please try again.',
|
||||||
color=(1, 0, 0))
|
color=(1, 0, 0))
|
||||||
ba.playsound(ba.getsound('error'))
|
ba.playsound(ba.getsound('error'))
|
||||||
|
|||||||
@ -1101,6 +1101,7 @@
|
|||||||
<w>savebutton</w>
|
<w>savebutton</w>
|
||||||
<w>sbytes</w>
|
<w>sbytes</w>
|
||||||
<w>scancode</w>
|
<w>scancode</w>
|
||||||
|
<w>scanresults</w>
|
||||||
<w>scenetime</w>
|
<w>scenetime</w>
|
||||||
<w>screenmessage</w>
|
<w>screenmessage</w>
|
||||||
<w>scrollwidget</w>
|
<w>scrollwidget</w>
|
||||||
@ -1287,6 +1288,7 @@
|
|||||||
<w>topos</w>
|
<w>topos</w>
|
||||||
<w>touchpad</w>
|
<w>touchpad</w>
|
||||||
<w>toucs</w>
|
<w>toucs</w>
|
||||||
|
<w>tournamentbutton</w>
|
||||||
<w>toutf</w>
|
<w>toutf</w>
|
||||||
<w>tpartial</w>
|
<w>tpartial</w>
|
||||||
<w>tpimport</w>
|
<w>tpimport</w>
|
||||||
|
|||||||
@ -21,7 +21,7 @@
|
|||||||
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 kAppBuildNumber = 20637;
|
const int kAppBuildNumber = 20638;
|
||||||
const char* kAppVersion = "1.7.4";
|
const char* kAppVersion = "1.7.4";
|
||||||
|
|
||||||
// Our standalone globals.
|
// Our standalone globals.
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/env python3.10
|
|
||||||
# Released under the MIT License. See LICENSE for details.
|
# Released under the MIT License. See LICENSE for details.
|
||||||
#
|
#
|
||||||
"""Updates assets/Makefile based on source assets present."""
|
"""Updates assets/Makefile based on source assets present."""
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/env python3.10
|
|
||||||
# Released under the MIT License. See LICENSE for details.
|
# Released under the MIT License. See LICENSE for details.
|
||||||
#
|
#
|
||||||
"""Stage assets for a build."""
|
"""Stage assets for a build."""
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/env python3.10
|
|
||||||
# Released under the MIT License. See LICENSE for details.
|
# Released under the MIT License. See LICENSE for details.
|
||||||
#
|
#
|
||||||
"""General project related functionality."""
|
"""General project related functionality."""
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user