mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-01-25 08:23:35 +08:00
Consolidated achievement functionality into AchievementSubsystem obj at ba.app.ach
This commit is contained in:
parent
2d5c2dda9a
commit
0f9fe41542
@ -3932,24 +3932,24 @@
|
||||
"assets/build/windows/Win32/ucrtbased.dll": "https://files.ballistica.net/cache/ba1/b5/85/f8b6d0558ddb87267f34254b1450",
|
||||
"assets/build/windows/Win32/vc_redist.x86.exe": "https://files.ballistica.net/cache/ba1/1c/e1/4a1a2eddda2f4aebd5f8b64ab08e",
|
||||
"assets/build/windows/Win32/vcruntime140d.dll": "https://files.ballistica.net/cache/ba1/50/8d/bc2600ac9491f1b14d659709451f",
|
||||
"build/prefab/full/linux_x86_64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/68/70/ecdec08c0236f5bebbf298c9f4cd",
|
||||
"build/prefab/full/linux_x86_64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/85/7f/53fb1e3f1414b4865315d815b17a",
|
||||
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/9e/ae/586229f233660b6b49ca655b7c1b",
|
||||
"build/prefab/full/linux_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/e5/a5/c6b90e3629a8041a68827aafec3f",
|
||||
"build/prefab/full/mac_x86_64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/d3/66/82b2cab9b1438c30cfd33eefba5e",
|
||||
"build/prefab/full/mac_x86_64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/52/37/253765404b79740cd4a7ac5fe325",
|
||||
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/c7/69/ecdbcee9df40225475391beb4cb2",
|
||||
"build/prefab/full/mac_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/34/51/cb528ea6eb5ac853794922a0cc34",
|
||||
"build/prefab/full/windows_x86/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/d4/b8/d3a690970ca379d805432bde8533",
|
||||
"build/prefab/full/windows_x86/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/4d/16/b9014f5d983481731b54f7045dd9",
|
||||
"build/prefab/full/windows_x86_server/debug/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/1e/11/d3c478923937f376eecb25561ae9",
|
||||
"build/prefab/full/windows_x86_server/release/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/d6/b4/b7854676ec826e42aa3ecb394b49",
|
||||
"build/prefab/lib/linux_x86_64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/7a/76/bf185c1ea65f3c25cfa63666511b",
|
||||
"build/prefab/lib/linux_x86_64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/49/30/5acd0d56b736a3729e7689cd4e18",
|
||||
"build/prefab/lib/linux_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/f7/e8/197874ac6d756c341628ea4bb518",
|
||||
"build/prefab/lib/linux_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/50/6f/140a3d77288e2355605c9d0c942a",
|
||||
"build/prefab/lib/mac_x86_64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/1c/ca/62d29425e0ad0b17c145ecbc97fe",
|
||||
"build/prefab/lib/mac_x86_64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/c0/fa/52a38fc153714bff3bcda077ed75",
|
||||
"build/prefab/lib/mac_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/75/5b/e84edb24f5df313bb6ebafa91b19",
|
||||
"build/prefab/lib/mac_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/0f/2e/af28c0026c0379e5441e789e9721"
|
||||
"build/prefab/full/linux_x86_64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/4c/74/73bd143107ea1bc1cc150cf1d9a0",
|
||||
"build/prefab/full/linux_x86_64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/d8/1f/b71688ce17abe2f1750d3b98c1a3",
|
||||
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/7b/f5/0fb038ef5e8c9cb22f8487213622",
|
||||
"build/prefab/full/linux_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/a7/22/7582b2dc2eb28e8c9b05c7860c83",
|
||||
"build/prefab/full/mac_x86_64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/01/6a/6787038c5a2fe07be6dd08d6df5f",
|
||||
"build/prefab/full/mac_x86_64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/eb/c3/12a2c00732a90af63ae853b76a3b",
|
||||
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/63/e7/795fd31307cda51524ea0cfc4055",
|
||||
"build/prefab/full/mac_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/92/48/1bfcef97e05d641771a934e312f3",
|
||||
"build/prefab/full/windows_x86/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/cf/25/4ef41f30fb1380505759a16a7302",
|
||||
"build/prefab/full/windows_x86/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/78/eb/9ee7487ac9d633020c02bcdd475b",
|
||||
"build/prefab/full/windows_x86_server/debug/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/4e/59/bd1e3f68c9ccf0180187dbf60ce1",
|
||||
"build/prefab/full/windows_x86_server/release/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/3c/f2/e0eb7217dba038dd146421b0bf5e",
|
||||
"build/prefab/lib/linux_x86_64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/66/0f/34874cece602328e1a2b27efbe09",
|
||||
"build/prefab/lib/linux_x86_64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/ee/58/ccc75a3b2679f01a9e9b9f693ab0",
|
||||
"build/prefab/lib/linux_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/2a/82/a34db5a370d695fb52891b0a7c54",
|
||||
"build/prefab/lib/linux_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/1b/c4/0b7f73a301f24177650efb8cfa69",
|
||||
"build/prefab/lib/mac_x86_64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/e6/55/d4819d9a2e5dcd48c2b2641c57df",
|
||||
"build/prefab/lib/mac_x86_64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/21/3f/8c9d1590314cd5172e944f64e41c",
|
||||
"build/prefab/lib/mac_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/91/72/b037555786dfb8a5ebc36467e60f",
|
||||
"build/prefab/lib/mac_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/e3/e1/c9e61438f6458b9ce4ac4cfe66ed"
|
||||
}
|
||||
@ -52,7 +52,7 @@ from ba._stats import PlayerScoredMessage, PlayerRecord, Stats
|
||||
from ba._team import SessionTeam, Team, EmptyTeam
|
||||
from ba._teamgame import TeamGameActivity
|
||||
from ba._dualteamsession import DualTeamSession
|
||||
from ba._achievement import Achievement
|
||||
from ba._achievement import Achievement, AchievementSubsystem
|
||||
from ba._appconfig import AppConfig
|
||||
from ba._appdelegate import AppDelegate
|
||||
from ba._apputils import is_browser_likely_available
|
||||
|
||||
@ -47,7 +47,7 @@ def get_league_rank_points(data: Optional[Dict[str, Any]],
|
||||
total_ach_value = data['at']
|
||||
else:
|
||||
total_ach_value = 0
|
||||
for ach in _ba.app.achievements:
|
||||
for ach in _ba.app.ach.achievements:
|
||||
if ach.complete:
|
||||
total_ach_value += ach.power_ranking_value
|
||||
|
||||
|
||||
@ -6,9 +6,10 @@ from __future__ import annotations
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import _ba
|
||||
from ba._error import print_exception
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Sequence, List, Dict, Union, Optional
|
||||
from typing import Any, Sequence, List, Dict, Union, Optional, Tuple, Set
|
||||
import ba
|
||||
|
||||
# This could use some cleanup.
|
||||
@ -61,69 +62,346 @@ ACH_LEVEL_NAMES = {
|
||||
}
|
||||
|
||||
|
||||
def award_local_achievement(achname: str) -> None:
|
||||
"""For non-game-based achievements such as controller-connection ones."""
|
||||
try:
|
||||
ach = get_achievement(achname)
|
||||
if not ach.complete:
|
||||
class AchievementSubsystem:
|
||||
"""Subsystem for achievement handling.
|
||||
|
||||
# Report new achievements to the game-service.
|
||||
_ba.report_achievement(achname)
|
||||
Category: App Classes
|
||||
|
||||
# And to our account.
|
||||
_ba.add_transaction({'type': 'ACHIEVEMENT', 'name': achname})
|
||||
|
||||
# Now attempt to show a banner.
|
||||
display_achievement_banner(achname)
|
||||
|
||||
except Exception:
|
||||
from ba import _error
|
||||
_error.print_exception()
|
||||
|
||||
|
||||
def display_achievement_banner(achname: str) -> None:
|
||||
"""Display a completion banner for an achievement.
|
||||
|
||||
Used for server-driven achievements.
|
||||
Access the single shared instance of this class at 'ba.app.ach'.
|
||||
"""
|
||||
try:
|
||||
# FIXME: Need to get these using the UI context or some other
|
||||
# purely local context somehow instead of trying to inject these
|
||||
# into whatever activity happens to be active
|
||||
# (since that won't work while in client mode).
|
||||
activity = _ba.get_foreground_host_activity()
|
||||
if activity is not None:
|
||||
with _ba.Context(activity):
|
||||
get_achievement(achname).announce_completion()
|
||||
except Exception:
|
||||
from ba import _error
|
||||
_error.print_exception('error showing server ach')
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.achievements: List[Achievement] = []
|
||||
self.achievements_to_display: (List[Tuple[ba.Achievement, bool]]) = []
|
||||
self.achievement_display_timer: Optional[_ba.Timer] = None
|
||||
self.last_achievement_display_time: float = 0.0
|
||||
self.achievement_completion_banner_slots: Set[int] = set()
|
||||
self._init_achievements()
|
||||
|
||||
# This gets called whenever game-center/game-circle/etc tells us which
|
||||
# achievements we currently have. We always defer to them, even if that
|
||||
# means we have to un-set an achievement we think we have
|
||||
def _init_achievements(self) -> None:
|
||||
"""Fill in available achievements."""
|
||||
|
||||
achs = self.achievements
|
||||
|
||||
def set_completed_achievements(achs: Sequence[str]) -> None:
|
||||
"""Set the current state of completed achievements.
|
||||
# 5
|
||||
achs.append(
|
||||
Achievement('In Control', 'achievementInControl', (1, 1, 1), '',
|
||||
5))
|
||||
# 15
|
||||
achs.append(
|
||||
Achievement('Sharing is Caring', 'achievementSharingIsCaring',
|
||||
(1, 1, 1), '', 15))
|
||||
# 10
|
||||
achs.append(
|
||||
Achievement('Dual Wielding', 'achievementDualWielding', (1, 1, 1),
|
||||
'', 10))
|
||||
|
||||
All achievements not included here will be set incomplete.
|
||||
"""
|
||||
cfg = _ba.app.config
|
||||
cfg['Achievements'] = {}
|
||||
for a_name in achs:
|
||||
get_achievement(a_name).set_complete(True)
|
||||
cfg.commit()
|
||||
# 10
|
||||
achs.append(
|
||||
Achievement('Free Loader', 'achievementFreeLoader', (1, 1, 1), '',
|
||||
10))
|
||||
# 20
|
||||
achs.append(
|
||||
Achievement('Team Player', 'achievementTeamPlayer', (1, 1, 1), '',
|
||||
20))
|
||||
|
||||
# 5
|
||||
achs.append(
|
||||
Achievement('Onslaught Training Victory', 'achievementOnslaught',
|
||||
(1, 1, 1), 'Default:Onslaught Training', 5))
|
||||
# 5
|
||||
achs.append(
|
||||
Achievement('Off You Go Then', 'achievementOffYouGo',
|
||||
(1, 1.1, 1.3), 'Default:Onslaught Training', 5))
|
||||
# 10
|
||||
achs.append(
|
||||
Achievement('Boxer',
|
||||
'achievementBoxer', (1, 0.6, 0.6),
|
||||
'Default:Onslaught Training',
|
||||
10,
|
||||
hard_mode_only=True))
|
||||
|
||||
def get_achievement(name: str) -> Achievement:
|
||||
"""Return an Achievement by name."""
|
||||
achs = [a for a in _ba.app.achievements if a.name == name]
|
||||
assert len(achs) < 2
|
||||
if not achs:
|
||||
raise ValueError("Invalid achievement name: '" + name + "'")
|
||||
return achs[0]
|
||||
# 10
|
||||
achs.append(
|
||||
Achievement('Rookie Onslaught Victory', 'achievementOnslaught',
|
||||
(0.5, 1.4, 0.6), 'Default:Rookie Onslaught', 10))
|
||||
# 10
|
||||
achs.append(
|
||||
Achievement('Mine Games', 'achievementMine', (1, 1, 1.4),
|
||||
'Default:Rookie Onslaught', 10))
|
||||
# 15
|
||||
achs.append(
|
||||
Achievement('Flawless Victory',
|
||||
'achievementFlawlessVictory', (1, 1, 1),
|
||||
'Default:Rookie Onslaught',
|
||||
15,
|
||||
hard_mode_only=True))
|
||||
|
||||
# 10
|
||||
achs.append(
|
||||
Achievement('Rookie Football Victory',
|
||||
'achievementFootballVictory', (1.0, 1, 0.6),
|
||||
'Default:Rookie Football', 10))
|
||||
# 10
|
||||
achs.append(
|
||||
Achievement('Super Punch', 'achievementSuperPunch', (1, 1, 1.8),
|
||||
'Default:Rookie Football', 10))
|
||||
# 15
|
||||
achs.append(
|
||||
Achievement('Rookie Football Shutout',
|
||||
'achievementFootballShutout', (1, 1, 1),
|
||||
'Default:Rookie Football',
|
||||
15,
|
||||
hard_mode_only=True))
|
||||
|
||||
# 15
|
||||
achs.append(
|
||||
Achievement('Pro Onslaught Victory', 'achievementOnslaught',
|
||||
(0.3, 1, 2.0), 'Default:Pro Onslaught', 15))
|
||||
# 15
|
||||
achs.append(
|
||||
Achievement('Boom Goes the Dynamite', 'achievementTNT',
|
||||
(1.4, 1.2, 0.8), 'Default:Pro Onslaught', 15))
|
||||
# 20
|
||||
achs.append(
|
||||
Achievement('Pro Boxer',
|
||||
'achievementBoxer', (2, 2, 0),
|
||||
'Default:Pro Onslaught',
|
||||
20,
|
||||
hard_mode_only=True))
|
||||
|
||||
# 15
|
||||
achs.append(
|
||||
Achievement('Pro Football Victory', 'achievementFootballVictory',
|
||||
(1.3, 1.3, 2.0), 'Default:Pro Football', 15))
|
||||
# 15
|
||||
achs.append(
|
||||
Achievement('Super Mega Punch', 'achievementSuperPunch',
|
||||
(2, 1, 0.6), 'Default:Pro Football', 15))
|
||||
# 20
|
||||
achs.append(
|
||||
Achievement('Pro Football Shutout',
|
||||
'achievementFootballShutout', (0.7, 0.7, 2.0),
|
||||
'Default:Pro Football',
|
||||
20,
|
||||
hard_mode_only=True))
|
||||
|
||||
# 15
|
||||
achs.append(
|
||||
Achievement('Pro Runaround Victory', 'achievementRunaround',
|
||||
(1, 1, 1), 'Default:Pro Runaround', 15))
|
||||
# 20
|
||||
achs.append(
|
||||
Achievement('Precision Bombing',
|
||||
'achievementCrossHair', (1, 1, 1.3),
|
||||
'Default:Pro Runaround',
|
||||
20,
|
||||
hard_mode_only=True))
|
||||
# 25
|
||||
achs.append(
|
||||
Achievement('The Wall',
|
||||
'achievementWall', (1, 0.7, 0.7),
|
||||
'Default:Pro Runaround',
|
||||
25,
|
||||
hard_mode_only=True))
|
||||
|
||||
# 30
|
||||
achs.append(
|
||||
Achievement('Uber Onslaught Victory', 'achievementOnslaught',
|
||||
(2, 2, 1), 'Default:Uber Onslaught', 30))
|
||||
# 30
|
||||
achs.append(
|
||||
Achievement('Gold Miner',
|
||||
'achievementMine', (2, 1.6, 0.2),
|
||||
'Default:Uber Onslaught',
|
||||
30,
|
||||
hard_mode_only=True))
|
||||
# 30
|
||||
achs.append(
|
||||
Achievement('TNT Terror',
|
||||
'achievementTNT', (2, 1.8, 0.3),
|
||||
'Default:Uber Onslaught',
|
||||
30,
|
||||
hard_mode_only=True))
|
||||
|
||||
# 30
|
||||
achs.append(
|
||||
Achievement('Uber Football Victory', 'achievementFootballVictory',
|
||||
(1.8, 1.4, 0.3), 'Default:Uber Football', 30))
|
||||
# 30
|
||||
achs.append(
|
||||
Achievement('Got the Moves',
|
||||
'achievementGotTheMoves', (2, 1, 0),
|
||||
'Default:Uber Football',
|
||||
30,
|
||||
hard_mode_only=True))
|
||||
# 40
|
||||
achs.append(
|
||||
Achievement('Uber Football Shutout',
|
||||
'achievementFootballShutout', (2, 2, 0),
|
||||
'Default:Uber Football',
|
||||
40,
|
||||
hard_mode_only=True))
|
||||
|
||||
# 30
|
||||
achs.append(
|
||||
Achievement('Uber Runaround Victory', 'achievementRunaround',
|
||||
(1.5, 1.2, 0.2), 'Default:Uber Runaround', 30))
|
||||
# 40
|
||||
achs.append(
|
||||
Achievement('The Great Wall',
|
||||
'achievementWall', (2, 1.7, 0.4),
|
||||
'Default:Uber Runaround',
|
||||
40,
|
||||
hard_mode_only=True))
|
||||
# 40
|
||||
achs.append(
|
||||
Achievement('Stayin\' Alive',
|
||||
'achievementStayinAlive', (2, 2, 1),
|
||||
'Default:Uber Runaround',
|
||||
40,
|
||||
hard_mode_only=True))
|
||||
|
||||
# 20
|
||||
achs.append(
|
||||
Achievement('Last Stand Master',
|
||||
'achievementMedalSmall', (2, 1.5, 0.3),
|
||||
'Default:The Last Stand',
|
||||
20,
|
||||
hard_mode_only=True))
|
||||
# 40
|
||||
achs.append(
|
||||
Achievement('Last Stand Wizard',
|
||||
'achievementMedalMedium', (2, 1.5, 0.3),
|
||||
'Default:The Last Stand',
|
||||
40,
|
||||
hard_mode_only=True))
|
||||
# 60
|
||||
achs.append(
|
||||
Achievement('Last Stand God',
|
||||
'achievementMedalLarge', (2, 1.5, 0.3),
|
||||
'Default:The Last Stand',
|
||||
60,
|
||||
hard_mode_only=True))
|
||||
|
||||
# 5
|
||||
achs.append(
|
||||
Achievement('Onslaught Master', 'achievementMedalSmall',
|
||||
(0.7, 1, 0.7), 'Challenges:Infinite Onslaught', 5))
|
||||
# 15
|
||||
achs.append(
|
||||
Achievement('Onslaught Wizard', 'achievementMedalMedium',
|
||||
(0.7, 1.0, 0.7), 'Challenges:Infinite Onslaught', 15))
|
||||
# 30
|
||||
achs.append(
|
||||
Achievement('Onslaught God', 'achievementMedalLarge',
|
||||
(0.7, 1.0, 0.7), 'Challenges:Infinite Onslaught', 30))
|
||||
|
||||
# 5
|
||||
achs.append(
|
||||
Achievement('Runaround Master', 'achievementMedalSmall',
|
||||
(1.0, 1.0, 1.2), 'Challenges:Infinite Runaround', 5))
|
||||
# 15
|
||||
achs.append(
|
||||
Achievement('Runaround Wizard', 'achievementMedalMedium',
|
||||
(1.0, 1.0, 1.2), 'Challenges:Infinite Runaround', 15))
|
||||
# 30
|
||||
achs.append(
|
||||
Achievement('Runaround God', 'achievementMedalLarge',
|
||||
(1.0, 1.0, 1.2), 'Challenges:Infinite Runaround', 30))
|
||||
|
||||
def award_local_achievement(self, achname: str) -> None:
|
||||
"""For non-game-based achievements such as controller-connection."""
|
||||
try:
|
||||
ach = self.get_achievement(achname)
|
||||
if not ach.complete:
|
||||
|
||||
# Report new achievements to the game-service.
|
||||
_ba.report_achievement(achname)
|
||||
|
||||
# And to our account.
|
||||
_ba.add_transaction({'type': 'ACHIEVEMENT', 'name': achname})
|
||||
|
||||
# Now attempt to show a banner.
|
||||
self.display_achievement_banner(achname)
|
||||
|
||||
except Exception:
|
||||
print_exception()
|
||||
|
||||
def display_achievement_banner(self, achname: str) -> None:
|
||||
"""Display a completion banner for an achievement.
|
||||
|
||||
(internal)
|
||||
|
||||
Used for server-driven achievements.
|
||||
"""
|
||||
try:
|
||||
# FIXME: Need to get these using the UI context or some other
|
||||
# purely local context somehow instead of trying to inject these
|
||||
# into whatever activity happens to be active
|
||||
# (since that won't work while in client mode).
|
||||
activity = _ba.get_foreground_host_activity()
|
||||
if activity is not None:
|
||||
with _ba.Context(activity):
|
||||
self.get_achievement(achname).announce_completion()
|
||||
except Exception:
|
||||
print_exception('error showing server ach')
|
||||
|
||||
def set_completed_achievements(self, achs: Sequence[str]) -> None:
|
||||
"""Set the current state of completed achievements.
|
||||
|
||||
(internal)
|
||||
|
||||
All achievements not included here will be set incomplete.
|
||||
"""
|
||||
|
||||
# Note: This gets called whenever game-center/game-circle/etc tells
|
||||
# us which achievements we currently have. We always defer to them,
|
||||
# even if that means we have to un-set an achievement we think we have.
|
||||
|
||||
cfg = _ba.app.config
|
||||
cfg['Achievements'] = {}
|
||||
for a_name in achs:
|
||||
self.get_achievement(a_name).set_complete(True)
|
||||
cfg.commit()
|
||||
|
||||
def get_achievement(self, name: str) -> Achievement:
|
||||
"""Return an Achievement by name."""
|
||||
achs = [a for a in self.achievements if a.name == name]
|
||||
assert len(achs) < 2
|
||||
if not achs:
|
||||
raise ValueError("Invalid achievement name: '" + name + "'")
|
||||
return achs[0]
|
||||
|
||||
def achievements_for_coop_level(self,
|
||||
level_name: str) -> List[Achievement]:
|
||||
"""Given a level name, return achievements available for it."""
|
||||
|
||||
# For the Easy campaign we return achievements for the Default
|
||||
# campaign too. (want the user to see what achievements are part of the
|
||||
# level even if they can't unlock them all on easy mode).
|
||||
return [
|
||||
a for a in self.achievements
|
||||
if a.level_name in (level_name,
|
||||
level_name.replace('Easy', 'Default'))
|
||||
]
|
||||
|
||||
def _test(self) -> None:
|
||||
"""For testing achievement animations."""
|
||||
from ba._enums import TimeType
|
||||
|
||||
def testcall1() -> None:
|
||||
self.achievements[0].announce_completion()
|
||||
self.achievements[1].announce_completion()
|
||||
self.achievements[2].announce_completion()
|
||||
|
||||
def testcall2() -> None:
|
||||
self.achievements[3].announce_completion()
|
||||
self.achievements[4].announce_completion()
|
||||
self.achievements[5].announce_completion()
|
||||
|
||||
_ba.timer(3.0, testcall1, timetype=TimeType.BASE)
|
||||
_ba.timer(7.0, testcall2, timetype=TimeType.BASE)
|
||||
|
||||
|
||||
def _get_ach_mult(include_pro_bonus: bool = False) -> int:
|
||||
@ -139,34 +417,21 @@ def _get_ach_mult(include_pro_bonus: bool = False) -> int:
|
||||
return val
|
||||
|
||||
|
||||
def get_achievements_for_coop_level(level_name: str) -> List[Achievement]:
|
||||
"""Given a level name, return achievements available for it."""
|
||||
|
||||
# For the Easy campaign we return achievements for the Default
|
||||
# campaign too. (want the user to see what achievements are part of the
|
||||
# level even if they can't unlock them all on easy mode).
|
||||
return [
|
||||
a for a in _ba.app.achievements
|
||||
if a.level_name in (level_name, level_name.replace('Easy', 'Default'))
|
||||
]
|
||||
|
||||
|
||||
def _display_next_achievement() -> None:
|
||||
|
||||
# Pull the first achievement off the list and display it, or kill the
|
||||
# display-timer if the list is empty.
|
||||
app = _ba.app
|
||||
if app.achievements_to_display:
|
||||
if app.ach.achievements_to_display:
|
||||
try:
|
||||
ach, sound = app.achievements_to_display.pop(0)
|
||||
ach, sound = app.ach.achievements_to_display.pop(0)
|
||||
ach.show_completion_banner(sound)
|
||||
except Exception:
|
||||
from ba import _error
|
||||
_error.print_exception('error showing next achievement')
|
||||
app.achievements_to_display = []
|
||||
app.achievement_display_timer = None
|
||||
print_exception('error showing next achievement')
|
||||
app.ach.achievements_to_display = []
|
||||
app.ach.achievement_display_timer = None
|
||||
else:
|
||||
app.achievement_display_timer = None
|
||||
app.ach.achievement_display_timer = None
|
||||
|
||||
|
||||
class Achievement:
|
||||
@ -236,18 +501,18 @@ class Achievement:
|
||||
return
|
||||
|
||||
# If we're being freshly complete, display/report it and whatnot.
|
||||
if (self, sound) not in app.achievements_to_display:
|
||||
app.achievements_to_display.append((self, sound))
|
||||
if (self, sound) not in app.ach.achievements_to_display:
|
||||
app.ach.achievements_to_display.append((self, sound))
|
||||
|
||||
# If there's no achievement display timer going, kick one off
|
||||
# (if one's already running it will pick this up before it dies).
|
||||
|
||||
# Need to check last time too; its possible our timer wasn't able to
|
||||
# clear itself if an activity died and took it down with it.
|
||||
if ((app.achievement_display_timer is None or
|
||||
_ba.time(TimeType.REAL) - app.last_achievement_display_time > 2.0)
|
||||
and _ba.getactivity(doraise=False) is not None):
|
||||
app.achievement_display_timer = _ba.Timer(
|
||||
if ((app.ach.achievement_display_timer is None
|
||||
or _ba.time(TimeType.REAL) - app.ach.last_achievement_display_time
|
||||
> 2.0) and _ba.getactivity(doraise=False) is not None):
|
||||
app.ach.achievement_display_timer = _ba.Timer(
|
||||
1.0,
|
||||
_display_next_achievement,
|
||||
repeat=True,
|
||||
@ -280,9 +545,8 @@ class Achievement:
|
||||
else:
|
||||
name = ''
|
||||
except Exception:
|
||||
from ba import _error
|
||||
name = ''
|
||||
_error.print_exception()
|
||||
print_exception()
|
||||
return Lstr(resource='achievements.' + self._name + '.name',
|
||||
subs=[('${LEVEL}', name)])
|
||||
|
||||
@ -397,8 +661,7 @@ class Achievement:
|
||||
else:
|
||||
hmo = False
|
||||
except Exception:
|
||||
from ba import _error
|
||||
_error.print_exception('Error determining campaign')
|
||||
print_exception('Error determining campaign.')
|
||||
hmo = False
|
||||
|
||||
objs: List[ba.Actor]
|
||||
@ -648,7 +911,7 @@ class Achievement:
|
||||
|
||||
def _remove_banner_slot(self) -> None:
|
||||
assert self._completion_banner_slot is not None
|
||||
_ba.app.achievement_completion_banner_slots.remove(
|
||||
_ba.app.ach.achievement_completion_banner_slots.remove(
|
||||
self._completion_banner_slot)
|
||||
self._completion_banner_slot = None
|
||||
|
||||
@ -663,7 +926,7 @@ class Achievement:
|
||||
from ba._messages import DieMessage
|
||||
from ba._enums import TimeType, SpecialChar
|
||||
app = _ba.app
|
||||
app.last_achievement_display_time = _ba.time(TimeType.REAL)
|
||||
app.ach.last_achievement_display_time = _ba.time(TimeType.REAL)
|
||||
|
||||
# Just piggy-back onto any current activity
|
||||
# (should we use the session instead?..)
|
||||
@ -694,8 +957,8 @@ class Achievement:
|
||||
# Find the first free slot.
|
||||
i = 0
|
||||
while True:
|
||||
if i not in app.achievement_completion_banner_slots:
|
||||
app.achievement_completion_banner_slots.add(i)
|
||||
if i not in app.ach.achievement_completion_banner_slots:
|
||||
app.ach.achievement_completion_banner_slots.add(i)
|
||||
self._completion_banner_slot = i
|
||||
|
||||
# Remove us from that slot when we close.
|
||||
@ -953,252 +1216,3 @@ class Achievement:
|
||||
for actor in objs:
|
||||
_ba.timer(out_time + 1.000,
|
||||
WeakCall(actor.handlemessage, DieMessage()))
|
||||
|
||||
|
||||
def init_achievements() -> None:
|
||||
"""Fill in available achievements."""
|
||||
|
||||
achs = _ba.app.achievements
|
||||
|
||||
# 5
|
||||
achs.append(
|
||||
Achievement('In Control', 'achievementInControl', (1, 1, 1), '', 5))
|
||||
# 15
|
||||
achs.append(
|
||||
Achievement('Sharing is Caring', 'achievementSharingIsCaring',
|
||||
(1, 1, 1), '', 15))
|
||||
# 10
|
||||
achs.append(
|
||||
Achievement('Dual Wielding', 'achievementDualWielding', (1, 1, 1), '',
|
||||
10))
|
||||
|
||||
# 10
|
||||
achs.append(
|
||||
Achievement('Free Loader', 'achievementFreeLoader', (1, 1, 1), '', 10))
|
||||
# 20
|
||||
achs.append(
|
||||
Achievement('Team Player', 'achievementTeamPlayer', (1, 1, 1), '', 20))
|
||||
|
||||
# 5
|
||||
achs.append(
|
||||
Achievement('Onslaught Training Victory', 'achievementOnslaught',
|
||||
(1, 1, 1), 'Default:Onslaught Training', 5))
|
||||
# 5
|
||||
achs.append(
|
||||
Achievement('Off You Go Then', 'achievementOffYouGo', (1, 1.1, 1.3),
|
||||
'Default:Onslaught Training', 5))
|
||||
# 10
|
||||
achs.append(
|
||||
Achievement('Boxer',
|
||||
'achievementBoxer', (1, 0.6, 0.6),
|
||||
'Default:Onslaught Training',
|
||||
10,
|
||||
hard_mode_only=True))
|
||||
|
||||
# 10
|
||||
achs.append(
|
||||
Achievement('Rookie Onslaught Victory', 'achievementOnslaught',
|
||||
(0.5, 1.4, 0.6), 'Default:Rookie Onslaught', 10))
|
||||
# 10
|
||||
achs.append(
|
||||
Achievement('Mine Games', 'achievementMine', (1, 1, 1.4),
|
||||
'Default:Rookie Onslaught', 10))
|
||||
# 15
|
||||
achs.append(
|
||||
Achievement('Flawless Victory',
|
||||
'achievementFlawlessVictory', (1, 1, 1),
|
||||
'Default:Rookie Onslaught',
|
||||
15,
|
||||
hard_mode_only=True))
|
||||
|
||||
# 10
|
||||
achs.append(
|
||||
Achievement('Rookie Football Victory', 'achievementFootballVictory',
|
||||
(1.0, 1, 0.6), 'Default:Rookie Football', 10))
|
||||
# 10
|
||||
achs.append(
|
||||
Achievement('Super Punch', 'achievementSuperPunch', (1, 1, 1.8),
|
||||
'Default:Rookie Football', 10))
|
||||
# 15
|
||||
achs.append(
|
||||
Achievement('Rookie Football Shutout',
|
||||
'achievementFootballShutout', (1, 1, 1),
|
||||
'Default:Rookie Football',
|
||||
15,
|
||||
hard_mode_only=True))
|
||||
|
||||
# 15
|
||||
achs.append(
|
||||
Achievement('Pro Onslaught Victory', 'achievementOnslaught',
|
||||
(0.3, 1, 2.0), 'Default:Pro Onslaught', 15))
|
||||
# 15
|
||||
achs.append(
|
||||
Achievement('Boom Goes the Dynamite', 'achievementTNT',
|
||||
(1.4, 1.2, 0.8), 'Default:Pro Onslaught', 15))
|
||||
# 20
|
||||
achs.append(
|
||||
Achievement('Pro Boxer',
|
||||
'achievementBoxer', (2, 2, 0),
|
||||
'Default:Pro Onslaught',
|
||||
20,
|
||||
hard_mode_only=True))
|
||||
|
||||
# 15
|
||||
achs.append(
|
||||
Achievement('Pro Football Victory', 'achievementFootballVictory',
|
||||
(1.3, 1.3, 2.0), 'Default:Pro Football', 15))
|
||||
# 15
|
||||
achs.append(
|
||||
Achievement('Super Mega Punch', 'achievementSuperPunch', (2, 1, 0.6),
|
||||
'Default:Pro Football', 15))
|
||||
# 20
|
||||
achs.append(
|
||||
Achievement('Pro Football Shutout',
|
||||
'achievementFootballShutout', (0.7, 0.7, 2.0),
|
||||
'Default:Pro Football',
|
||||
20,
|
||||
hard_mode_only=True))
|
||||
|
||||
# 15
|
||||
achs.append(
|
||||
Achievement('Pro Runaround Victory', 'achievementRunaround', (1, 1, 1),
|
||||
'Default:Pro Runaround', 15))
|
||||
# 20
|
||||
achs.append(
|
||||
Achievement('Precision Bombing',
|
||||
'achievementCrossHair', (1, 1, 1.3),
|
||||
'Default:Pro Runaround',
|
||||
20,
|
||||
hard_mode_only=True))
|
||||
# 25
|
||||
achs.append(
|
||||
Achievement('The Wall',
|
||||
'achievementWall', (1, 0.7, 0.7),
|
||||
'Default:Pro Runaround',
|
||||
25,
|
||||
hard_mode_only=True))
|
||||
|
||||
# 30
|
||||
achs.append(
|
||||
Achievement('Uber Onslaught Victory', 'achievementOnslaught',
|
||||
(2, 2, 1), 'Default:Uber Onslaught', 30))
|
||||
# 30
|
||||
achs.append(
|
||||
Achievement('Gold Miner',
|
||||
'achievementMine', (2, 1.6, 0.2),
|
||||
'Default:Uber Onslaught',
|
||||
30,
|
||||
hard_mode_only=True))
|
||||
# 30
|
||||
achs.append(
|
||||
Achievement('TNT Terror',
|
||||
'achievementTNT', (2, 1.8, 0.3),
|
||||
'Default:Uber Onslaught',
|
||||
30,
|
||||
hard_mode_only=True))
|
||||
|
||||
# 30
|
||||
achs.append(
|
||||
Achievement('Uber Football Victory', 'achievementFootballVictory',
|
||||
(1.8, 1.4, 0.3), 'Default:Uber Football', 30))
|
||||
# 30
|
||||
achs.append(
|
||||
Achievement('Got the Moves',
|
||||
'achievementGotTheMoves', (2, 1, 0),
|
||||
'Default:Uber Football',
|
||||
30,
|
||||
hard_mode_only=True))
|
||||
# 40
|
||||
achs.append(
|
||||
Achievement('Uber Football Shutout',
|
||||
'achievementFootballShutout', (2, 2, 0),
|
||||
'Default:Uber Football',
|
||||
40,
|
||||
hard_mode_only=True))
|
||||
|
||||
# 30
|
||||
achs.append(
|
||||
Achievement('Uber Runaround Victory', 'achievementRunaround',
|
||||
(1.5, 1.2, 0.2), 'Default:Uber Runaround', 30))
|
||||
# 40
|
||||
achs.append(
|
||||
Achievement('The Great Wall',
|
||||
'achievementWall', (2, 1.7, 0.4),
|
||||
'Default:Uber Runaround',
|
||||
40,
|
||||
hard_mode_only=True))
|
||||
# 40
|
||||
achs.append(
|
||||
Achievement('Stayin\' Alive',
|
||||
'achievementStayinAlive', (2, 2, 1),
|
||||
'Default:Uber Runaround',
|
||||
40,
|
||||
hard_mode_only=True))
|
||||
|
||||
# 20
|
||||
achs.append(
|
||||
Achievement('Last Stand Master',
|
||||
'achievementMedalSmall', (2, 1.5, 0.3),
|
||||
'Default:The Last Stand',
|
||||
20,
|
||||
hard_mode_only=True))
|
||||
# 40
|
||||
achs.append(
|
||||
Achievement('Last Stand Wizard',
|
||||
'achievementMedalMedium', (2, 1.5, 0.3),
|
||||
'Default:The Last Stand',
|
||||
40,
|
||||
hard_mode_only=True))
|
||||
# 60
|
||||
achs.append(
|
||||
Achievement('Last Stand God',
|
||||
'achievementMedalLarge', (2, 1.5, 0.3),
|
||||
'Default:The Last Stand',
|
||||
60,
|
||||
hard_mode_only=True))
|
||||
|
||||
# 5
|
||||
achs.append(
|
||||
Achievement('Onslaught Master', 'achievementMedalSmall', (0.7, 1, 0.7),
|
||||
'Challenges:Infinite Onslaught', 5))
|
||||
# 15
|
||||
achs.append(
|
||||
Achievement('Onslaught Wizard', 'achievementMedalMedium',
|
||||
(0.7, 1.0, 0.7), 'Challenges:Infinite Onslaught', 15))
|
||||
# 30
|
||||
achs.append(
|
||||
Achievement('Onslaught God', 'achievementMedalLarge', (0.7, 1.0, 0.7),
|
||||
'Challenges:Infinite Onslaught', 30))
|
||||
|
||||
# 5
|
||||
achs.append(
|
||||
Achievement('Runaround Master', 'achievementMedalSmall',
|
||||
(1.0, 1.0, 1.2), 'Challenges:Infinite Runaround', 5))
|
||||
# 15
|
||||
achs.append(
|
||||
Achievement('Runaround Wizard', 'achievementMedalMedium',
|
||||
(1.0, 1.0, 1.2), 'Challenges:Infinite Runaround', 15))
|
||||
# 30
|
||||
achs.append(
|
||||
Achievement('Runaround God', 'achievementMedalLarge', (1.0, 1.0, 1.2),
|
||||
'Challenges:Infinite Runaround', 30))
|
||||
|
||||
|
||||
def _test() -> None:
|
||||
"""For testing achievement animations."""
|
||||
from ba._enums import TimeType
|
||||
|
||||
def testcall1() -> None:
|
||||
app = _ba.app
|
||||
app.achievements[0].announce_completion()
|
||||
app.achievements[1].announce_completion()
|
||||
app.achievements[2].announce_completion()
|
||||
|
||||
def testcall2() -> None:
|
||||
app = _ba.app
|
||||
app.achievements[3].announce_completion()
|
||||
app.achievements[4].announce_completion()
|
||||
app.achievements[5].announce_completion()
|
||||
|
||||
_ba.timer(3.0, testcall1, timetype=TimeType.BASE)
|
||||
_ba.timer(7.0, testcall2, timetype=TimeType.BASE)
|
||||
|
||||
@ -99,7 +99,6 @@ class App:
|
||||
"""Path where the app looks for its bundled scripts."""
|
||||
assert isinstance(self._env['python_directory_app'], str)
|
||||
return self._env['python_directory_app']
|
||||
# return self._python_directory_app
|
||||
|
||||
@property
|
||||
def python_directory_app_site(self) -> str:
|
||||
@ -175,6 +174,7 @@ class App:
|
||||
from ba._music import MusicSubsystem
|
||||
from ba._language import LanguageSubsystem
|
||||
from ba._ui import UISubsystem
|
||||
from ba._achievement import AchievementSubsystem
|
||||
|
||||
# Config.
|
||||
self.config_file_healthy = False
|
||||
@ -241,18 +241,10 @@ class App:
|
||||
self.last_ad_purpose = 'invalid'
|
||||
self.attempted_first_ad = False
|
||||
|
||||
# Music.
|
||||
self.music = MusicSubsystem()
|
||||
|
||||
# Language.
|
||||
self.lang = LanguageSubsystem()
|
||||
|
||||
# Achievements.
|
||||
self.achievements: List[ba.Achievement] = []
|
||||
self.achievements_to_display: (List[Tuple[ba.Achievement, bool]]) = []
|
||||
self.achievement_display_timer: Optional[_ba.Timer] = None
|
||||
self.last_achievement_display_time: float = 0.0
|
||||
self.achievement_completion_banner_slots: Set[int] = set()
|
||||
self.ach = AchievementSubsystem()
|
||||
self.ui = UISubsystem()
|
||||
|
||||
# Lobby.
|
||||
self.lobby_random_profile_index: int = 1
|
||||
@ -275,9 +267,6 @@ class App:
|
||||
self.ffa_series_length = 24
|
||||
self.coop_session_args: Dict = {}
|
||||
|
||||
# UI.
|
||||
self.ui = UISubsystem()
|
||||
|
||||
self.value_test_defaults: dict = {}
|
||||
self.first_main_menu = True # FIXME: Move to mainmenu class.
|
||||
self.did_menu_intro = False # FIXME: Move to mainmenu class.
|
||||
@ -320,7 +309,7 @@ class App:
|
||||
|
||||
self.ui.on_app_launch()
|
||||
|
||||
_achievement.init_achievements()
|
||||
# _achievement.init_achievements()
|
||||
spazappearance.register_appearances()
|
||||
_campaign.init_campaigns()
|
||||
|
||||
|
||||
@ -130,21 +130,19 @@ class CoopGameActivity(GameActivity[PlayerType, TeamType]):
|
||||
player.actor.handlemessage(CelebrateMessage(duration))
|
||||
|
||||
def _preload_achievements(self) -> None:
|
||||
from ba import _achievement
|
||||
achievements = _achievement.get_achievements_for_coop_level(
|
||||
achievements = _ba.app.ach.achievements_for_coop_level(
|
||||
self._get_coop_level_name())
|
||||
for ach in achievements:
|
||||
ach.get_icon_texture(True)
|
||||
|
||||
def _show_remaining_achievements(self) -> None:
|
||||
# pylint: disable=cyclic-import
|
||||
from ba._achievement import get_achievements_for_coop_level
|
||||
from ba._language import Lstr
|
||||
from bastd.actor.text import Text
|
||||
ts_h_offs = 30
|
||||
v_offs = -200
|
||||
achievements = [
|
||||
a for a in get_achievements_for_coop_level(
|
||||
a for a in _ba.app.ach.achievements_for_coop_level(
|
||||
self._get_coop_level_name()) if not a.complete
|
||||
]
|
||||
vrmode = _ba.app.vr_mode
|
||||
@ -193,12 +191,11 @@ class CoopGameActivity(GameActivity[PlayerType, TeamType]):
|
||||
Returns True if a banner will be shown;
|
||||
False otherwise
|
||||
"""
|
||||
from ba._achievement import get_achievement
|
||||
|
||||
if achievement_name in self._achievements_awarded:
|
||||
return
|
||||
|
||||
ach = get_achievement(achievement_name)
|
||||
ach = _ba.app.ach.get_achievement(achievement_name)
|
||||
|
||||
# If we're in the easy campaign and this achievement is hard-mode-only,
|
||||
# ignore it.
|
||||
|
||||
@ -138,13 +138,11 @@ def language_test_toggle() -> None:
|
||||
|
||||
|
||||
def award_in_control_achievement() -> None:
|
||||
from ba._achievement import award_local_achievement
|
||||
award_local_achievement('In Control')
|
||||
_ba.app.ach.award_local_achievement('In Control')
|
||||
|
||||
|
||||
def award_dual_wielding_achievement() -> None:
|
||||
from ba._achievement import award_local_achievement
|
||||
award_local_achievement('Dual Wielding')
|
||||
_ba.app.ach.award_local_achievement('Dual Wielding')
|
||||
|
||||
|
||||
def play_gong_sound() -> None:
|
||||
|
||||
@ -121,7 +121,7 @@ class MusicSubsystem:
|
||||
|
||||
Category: App Classes
|
||||
|
||||
To use this class, access the single instance of it at 'ba.app.music'.
|
||||
Access the single shared instance of this class at 'ba.app.music'.
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
|
||||
@ -6,11 +6,11 @@ from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING, TypeVar
|
||||
|
||||
import _ba
|
||||
from ba._freeforallsession import FreeForAllSession
|
||||
from ba._gameactivity import GameActivity
|
||||
from ba._gameresults import GameResults
|
||||
from ba._dualteamsession import DualTeamSession
|
||||
import _ba
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Dict, Type, Sequence
|
||||
@ -78,12 +78,11 @@ class TeamGameActivity(GameActivity[PlayerType, TeamType]):
|
||||
# Award a few achievements.
|
||||
if isinstance(self.session, FreeForAllSession):
|
||||
if len(self.players) >= 2:
|
||||
from ba import _achievement
|
||||
_achievement.award_local_achievement('Free Loader')
|
||||
_ba.app.ach.award_local_achievement('Free Loader')
|
||||
elif isinstance(self.session, DualTeamSession):
|
||||
if len(self.players) >= 4:
|
||||
from ba import _achievement
|
||||
_achievement.award_local_achievement('Team Player')
|
||||
_ba.app.ach.award_local_achievement('Team Player')
|
||||
except Exception:
|
||||
from ba import _error
|
||||
_error.print_exception()
|
||||
|
||||
@ -23,9 +23,6 @@ from ba._account import (on_account_state_changed,
|
||||
get_purchased_icons, get_cached_league_rank_data,
|
||||
get_league_rank_points, cache_league_rank_data)
|
||||
from ba._activitytypes import JoinActivity, ScoreScreenActivity
|
||||
from ba._achievement import (get_achievement, set_completed_achievements,
|
||||
display_achievement_banner,
|
||||
get_achievements_for_coop_level)
|
||||
from ba._apputils import (is_browser_likely_available, get_remote_app_name,
|
||||
should_submit_debug_info, show_ad, show_ad_2)
|
||||
from ba._benchmark import (run_gpu_benchmark, run_cpu_benchmark,
|
||||
|
||||
@ -59,7 +59,6 @@ class CoopJoinActivity(JoinActivity):
|
||||
# pylint: disable=too-many-statements
|
||||
from efro.util import asserttype
|
||||
from bastd.actor.text import Text
|
||||
from ba.internal import get_achievements_for_coop_level
|
||||
|
||||
# Sort by originating date so that the most recent is first.
|
||||
if scores is not None:
|
||||
@ -159,7 +158,8 @@ class CoopJoinActivity(JoinActivity):
|
||||
|
||||
if not (ba.app.demo_mode or ba.app.arcade_mode):
|
||||
achievements = [
|
||||
a for a in get_achievements_for_coop_level(levelname)
|
||||
a
|
||||
for a in ba.app.ach.achievements_for_coop_level(levelname)
|
||||
if not a.complete
|
||||
]
|
||||
have_achievements = bool(achievements)
|
||||
|
||||
@ -10,7 +10,6 @@ from typing import TYPE_CHECKING
|
||||
|
||||
import _ba
|
||||
import ba
|
||||
from ba.internal import get_achievements_for_coop_level
|
||||
from bastd.actor.text import Text
|
||||
from bastd.actor.zoomtext import ZoomText
|
||||
|
||||
@ -50,8 +49,8 @@ class CoopScoreScreen(ba.Activity[ba.Player, ba.Team]):
|
||||
self._campaign: ba.Campaign = settings['campaign']
|
||||
|
||||
self._have_achievements = bool(
|
||||
get_achievements_for_coop_level(self._campaign.name + ':' +
|
||||
settings['level']))
|
||||
ba.app.ach.achievements_for_coop_level(self._campaign.name + ':' +
|
||||
settings['level']))
|
||||
|
||||
self._account_type = (_ba.get_account_type() if
|
||||
_ba.get_account_state() == 'signed_in' else None)
|
||||
@ -847,7 +846,8 @@ class CoopScoreScreen(ba.Activity[ba.Player, ba.Team]):
|
||||
transition_delay=2.8).autoretain()
|
||||
|
||||
assert self._game_name_str is not None
|
||||
achievements = get_achievements_for_coop_level(self._game_name_str)
|
||||
achievements = ba.app.ach.achievements_for_coop_level(
|
||||
self._game_name_str)
|
||||
hval = -455
|
||||
vval = -100
|
||||
tdelay = 0.0
|
||||
|
||||
@ -319,7 +319,8 @@ class MainMenuActivity(ba.Activity[ba.Player, ba.Team]):
|
||||
transition_out_delay=self._message_duration
|
||||
).autoretain()
|
||||
achs = [
|
||||
a for a in app.achievements if not a.complete
|
||||
a for a in app.ach.achievements
|
||||
if not a.complete
|
||||
]
|
||||
if achs:
|
||||
ach = achs.pop(
|
||||
|
||||
@ -995,8 +995,8 @@ class AccountSettingsWindow(ba.Window):
|
||||
if (self._achievements_text is None
|
||||
and self._achievements_button is None):
|
||||
return
|
||||
complete = sum(1 if a.complete else 0 for a in ba.app.achievements)
|
||||
total = len(ba.app.achievements)
|
||||
complete = sum(1 if a.complete else 0 for a in ba.app.ach.achievements)
|
||||
total = len(ba.app.ach.achievements)
|
||||
txt_final = ba.Lstr(resource=self._r + '.achievementProgressText',
|
||||
subs=[('${COUNT}', str(complete)),
|
||||
('${TOTAL}', str(total))])
|
||||
|
||||
@ -426,7 +426,7 @@ class AccountViewerWindow(popup.PopupWindow):
|
||||
v_align='center',
|
||||
scale=0.55,
|
||||
text=str(data['achievementsCompleted']) + ' / ' +
|
||||
str(len(ba.app.achievements)),
|
||||
str(len(ba.app.ach.achievements)),
|
||||
maxwidth=sub_width * maxwidth_scale)
|
||||
v -= 25
|
||||
|
||||
|
||||
@ -47,7 +47,7 @@ class AchievementsWindow(popup.PopupWindow):
|
||||
icon=ba.gettexture('crossOut'),
|
||||
iconscale=1.2)
|
||||
|
||||
achievements = ba.app.achievements
|
||||
achievements = ba.app.ach.achievements
|
||||
num_complete = len([a for a in achievements if a.complete])
|
||||
|
||||
txt_final = ba.Lstr(
|
||||
|
||||
@ -22,7 +22,7 @@ class GameButton:
|
||||
x: float, y: float, select: bool, row: str):
|
||||
# pylint: disable=too-many-statements
|
||||
# pylint: disable=too-many-locals
|
||||
from ba.internal import (get_achievements_for_coop_level, getcampaign)
|
||||
from ba.internal import getcampaign
|
||||
self._game = game
|
||||
sclx = 195.0
|
||||
scly = 195.0
|
||||
@ -81,7 +81,7 @@ class GameButton:
|
||||
mask_texture=ba.gettexture('mapPreviewMask'))
|
||||
|
||||
translated = campaign.getlevel(levelname).displayname
|
||||
self._achievements = (get_achievements_for_coop_level(game))
|
||||
self._achievements = ba.app.ach.achievements_for_coop_level(game)
|
||||
|
||||
self._name_widget = ba.textwidget(parent=parent,
|
||||
draw_controller=btn,
|
||||
|
||||
@ -808,7 +808,7 @@ class LeagueRankWindow(ba.Window):
|
||||
# for the achievement value, use the number they gave us for
|
||||
# non-current seasons; otherwise calc our own
|
||||
total_ach_value = 0
|
||||
for ach in ba.app.achievements:
|
||||
for ach in ba.app.ach.achievements:
|
||||
if ach.complete:
|
||||
total_ach_value += ach.power_ranking_value
|
||||
if self._season != 'a' and not self._is_current_season:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<!-- THIS FILE IS AUTO GENERATED; DO NOT EDIT BY HAND -->
|
||||
<h4><em>last updated on 2020-10-15 for Ballistica version 1.5.27 build 20218</em></h4>
|
||||
<h4><em>last updated on 2020-10-16 for Ballistica version 1.5.27 build 20219</em></h4>
|
||||
<p>This page documents the Python classes and functions in the 'ba' module,
|
||||
which are the ones most relevant to modding in Ballistica. If you come across something you feel should be included here or could be better explained, please <a href="mailto:support@froemling.net">let me know</a>. Happy modding!</p>
|
||||
<hr>
|
||||
@ -148,6 +148,7 @@
|
||||
<h4><a name="class_category_App_Classes">App Classes</a></h4>
|
||||
<ul>
|
||||
<li><a href="#class_ba_Achievement">ba.Achievement</a></li>
|
||||
<li><a href="#class_ba_AchievementSubsystem">ba.AchievementSubsystem</a></li>
|
||||
<li><a href="#class_ba_App">ba.App</a></li>
|
||||
<li><a href="#class_ba_AppConfig">ba.AppConfig</a></li>
|
||||
<li><a href="#class_ba_AppDelegate">ba.AppDelegate</a></li>
|
||||
@ -350,6 +351,43 @@ actually award achievements.</p>
|
||||
|
||||
<p>Create the banner/sound for an acquired achievement announcement.</p>
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
<hr>
|
||||
<h2><strong><a name="class_ba_AchievementSubsystem">ba.AchievementSubsystem</a></strong></h3>
|
||||
<p><em><top level class></em>
|
||||
</p>
|
||||
<p>Subsystem for achievement handling.</p>
|
||||
|
||||
<p>Category: <a href="#class_category_App_Classes">App Classes</a></p>
|
||||
|
||||
<p> Access the single shared instance of this class at 'ba.app.ach'.
|
||||
</p>
|
||||
|
||||
<h3>Methods:</h3>
|
||||
<h5><a href="#method_ba_AchievementSubsystem____init__"><constructor></a>, <a href="#method_ba_AchievementSubsystem__achievements_for_coop_level">achievements_for_coop_level()</a>, <a href="#method_ba_AchievementSubsystem__award_local_achievement">award_local_achievement()</a>, <a href="#method_ba_AchievementSubsystem__get_achievement">get_achievement()</a></h5>
|
||||
<dl>
|
||||
<dt><h4><a name="method_ba_AchievementSubsystem____init__"><constructor></a></dt></h4><dd>
|
||||
<p><span>ba.AchievementSubsystem()</span></p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="method_ba_AchievementSubsystem__achievements_for_coop_level">achievements_for_coop_level()</a></dt></h4><dd>
|
||||
<p><span>achievements_for_coop_level(self, level_name: str) -> List[Achievement]</span></p>
|
||||
|
||||
<p>Given a level name, return achievements available for it.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="method_ba_AchievementSubsystem__award_local_achievement">award_local_achievement()</a></dt></h4><dd>
|
||||
<p><span>award_local_achievement(self, achname: str) -> None</span></p>
|
||||
|
||||
<p>For non-game-based achievements such as controller-connection.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="method_ba_AchievementSubsystem__get_achievement">get_achievement()</a></dt></h4><dd>
|
||||
<p><span>get_achievement(self, name: str) -> Achievement</span></p>
|
||||
|
||||
<p>Return an Achievement by name.</p>
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
<hr>
|
||||
@ -3974,7 +4012,7 @@ signify that the default soundtrack should be used..</p>
|
||||
|
||||
<p>Category: <a href="#class_category_App_Classes">App Classes</a></p>
|
||||
|
||||
<p> To use this class, access the single instance of it at 'ba.app.music'.
|
||||
<p> Access the single shared instance of this class at 'ba.app.music'.
|
||||
</p>
|
||||
|
||||
<h3>Methods:</h3>
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
namespace ballistica {
|
||||
|
||||
// These are set automatically via script; don't change here.
|
||||
const int kAppBuildNumber = 20218;
|
||||
const int kAppBuildNumber = 20219;
|
||||
const char* kAppVersion = "1.5.27";
|
||||
|
||||
// Our standalone globals.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user