mirror of
https://github.com/hypervortex/VH-Bombsquad-Modded-Server-Files
synced 2025-11-07 17:36:08 +00:00
Added new files
This commit is contained in:
parent
5e004af549
commit
77ccb73089
1783 changed files with 566966 additions and 0 deletions
267
dist/ba_data/python/ba/_account.py
vendored
Normal file
267
dist/ba_data/python/ba/_account.py
vendored
Normal file
|
|
@ -0,0 +1,267 @@
|
|||
# Released under the MIT License. See LICENSE for details.
|
||||
#
|
||||
"""Account related functionality."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import copy
|
||||
import time
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import _ba
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Optional
|
||||
import ba
|
||||
|
||||
|
||||
class AccountSubsystem:
|
||||
"""Subsystem for account handling in the app.
|
||||
|
||||
Category: App Classes
|
||||
|
||||
Access the single shared instance of this class at 'ba.app.plugins'.
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.account_tournament_list: Optional[tuple[int, list[str]]] = None
|
||||
|
||||
# FIXME: should abstract/structure these.
|
||||
self.tournament_info: dict = {}
|
||||
self.league_rank_cache: dict = {}
|
||||
self.last_post_purchase_message_time: Optional[float] = None
|
||||
|
||||
# If we try to run promo-codes due to launch-args/etc we might
|
||||
# not be signed in yet; go ahead and queue them up in that case.
|
||||
self.pending_promo_codes: list[str] = []
|
||||
|
||||
def on_app_launch(self) -> None:
|
||||
"""Called when the app is done bootstrapping."""
|
||||
|
||||
# Auto-sign-in to a local account in a moment if we're set to.
|
||||
def do_auto_sign_in() -> None:
|
||||
if _ba.app.headless_mode or _ba.app.config.get(
|
||||
'Auto Account State') == 'Local':
|
||||
_ba.sign_in('Local')
|
||||
|
||||
_ba.pushcall(do_auto_sign_in)
|
||||
|
||||
def on_app_resume(self) -> None:
|
||||
"""Should be called when the app is resumed."""
|
||||
|
||||
# Mark our cached tourneys as invalid so anyone using them knows
|
||||
# they might be out of date.
|
||||
for entry in list(self.tournament_info.values()):
|
||||
entry['valid'] = False
|
||||
|
||||
def handle_account_gained_tickets(self, count: int) -> None:
|
||||
"""Called when the current account has been awarded tickets.
|
||||
|
||||
(internal)
|
||||
"""
|
||||
from ba._language import Lstr
|
||||
_ba.screenmessage(Lstr(resource='getTicketsWindow.receivedTicketsText',
|
||||
subs=[('${COUNT}', str(count))]),
|
||||
color=(0, 1, 0))
|
||||
_ba.playsound(_ba.getsound('cashRegister'))
|
||||
|
||||
def cache_league_rank_data(self, data: Any) -> None:
|
||||
"""(internal)"""
|
||||
self.league_rank_cache['info'] = copy.deepcopy(data)
|
||||
|
||||
def get_cached_league_rank_data(self) -> Any:
|
||||
"""(internal)"""
|
||||
return self.league_rank_cache.get('info', None)
|
||||
|
||||
def get_league_rank_points(self,
|
||||
data: Optional[dict[str, Any]],
|
||||
subset: str = None) -> int:
|
||||
"""(internal)"""
|
||||
if data is None:
|
||||
return 0
|
||||
|
||||
# If the data contains an achievement total, use that. otherwise calc
|
||||
# locally.
|
||||
if data['at'] is not None:
|
||||
total_ach_value = data['at']
|
||||
else:
|
||||
total_ach_value = 0
|
||||
for ach in _ba.app.ach.achievements:
|
||||
if ach.complete:
|
||||
total_ach_value += ach.power_ranking_value
|
||||
|
||||
trophies_total: int = (data['t0a'] * data['t0am'] +
|
||||
data['t0b'] * data['t0bm'] +
|
||||
data['t1'] * data['t1m'] +
|
||||
data['t2'] * data['t2m'] +
|
||||
data['t3'] * data['t3m'] +
|
||||
data['t4'] * data['t4m'])
|
||||
if subset == 'trophyCount':
|
||||
val: int = (data['t0a'] + data['t0b'] + data['t1'] + data['t2'] +
|
||||
data['t3'] + data['t4'])
|
||||
assert isinstance(val, int)
|
||||
return val
|
||||
if subset == 'trophies':
|
||||
assert isinstance(trophies_total, int)
|
||||
return trophies_total
|
||||
if subset is not None:
|
||||
raise ValueError('invalid subset value: ' + str(subset))
|
||||
|
||||
if data['p']:
|
||||
pro_mult = 1.0 + float(
|
||||
_ba.get_account_misc_read_val('proPowerRankingBoost',
|
||||
0.0)) * 0.01
|
||||
else:
|
||||
pro_mult = 1.0
|
||||
|
||||
# For final value, apply our pro mult and activeness-mult.
|
||||
return int(
|
||||
(total_ach_value + trophies_total) *
|
||||
(data['act'] if data['act'] is not None else 1.0) * pro_mult)
|
||||
|
||||
def cache_tournament_info(self, info: Any) -> None:
|
||||
"""(internal)"""
|
||||
from ba._generated.enums import TimeType, TimeFormat
|
||||
for entry in info:
|
||||
cache_entry = self.tournament_info[entry['tournamentID']] = (
|
||||
copy.deepcopy(entry))
|
||||
|
||||
# Also store the time we received this, so we can adjust
|
||||
# time-remaining values/etc.
|
||||
cache_entry['timeReceived'] = _ba.time(TimeType.REAL,
|
||||
TimeFormat.MILLISECONDS)
|
||||
cache_entry['valid'] = True
|
||||
|
||||
def get_purchased_icons(self) -> list[str]:
|
||||
"""(internal)"""
|
||||
# pylint: disable=cyclic-import
|
||||
from ba import _store
|
||||
if _ba.get_account_state() != 'signed_in':
|
||||
return []
|
||||
icons = []
|
||||
store_items = _store.get_store_items()
|
||||
for item_name, item in list(store_items.items()):
|
||||
if item_name.startswith('icons.') and _ba.get_purchased(item_name):
|
||||
icons.append(item['icon'])
|
||||
return icons
|
||||
|
||||
def ensure_have_account_player_profile(self) -> None:
|
||||
"""
|
||||
Ensure the standard account-named player profile exists;
|
||||
creating if needed.
|
||||
|
||||
(internal)
|
||||
"""
|
||||
# This only applies when we're signed in.
|
||||
if _ba.get_account_state() != 'signed_in':
|
||||
return
|
||||
|
||||
# If the short version of our account name currently cant be
|
||||
# displayed by the game, cancel.
|
||||
if not _ba.have_chars(_ba.get_account_display_string(full=False)):
|
||||
return
|
||||
|
||||
config = _ba.app.config
|
||||
if ('Player Profiles' not in config
|
||||
or '__account__' not in config['Player Profiles']):
|
||||
|
||||
# Create a spaz with a nice default purply color.
|
||||
_ba.add_transaction({
|
||||
'type': 'ADD_PLAYER_PROFILE',
|
||||
'name': '__account__',
|
||||
'profile': {
|
||||
'character': 'Spaz',
|
||||
'color': [0.5, 0.25, 1.0],
|
||||
'highlight': [0.5, 0.25, 1.0]
|
||||
}
|
||||
})
|
||||
_ba.run_transactions()
|
||||
|
||||
def have_pro(self) -> bool:
|
||||
"""Return whether pro is currently unlocked."""
|
||||
|
||||
# Check our tickets-based pro upgrade and our two real-IAP based
|
||||
# upgrades. Also always unlock this stuff in ballistica-core builds.
|
||||
return bool(
|
||||
_ba.get_purchased('upgrades.pro')
|
||||
or _ba.get_purchased('static.pro')
|
||||
or _ba.get_purchased('static.pro_sale')
|
||||
or 'ballistica' + 'core' == _ba.appname())
|
||||
|
||||
def have_pro_options(self) -> bool:
|
||||
"""Return whether pro-options are present.
|
||||
|
||||
This is True for owners of Pro or for old installs
|
||||
before Pro was a requirement for these options.
|
||||
"""
|
||||
|
||||
# We expose pro options if the server tells us to
|
||||
# (which is generally just when we own pro),
|
||||
# or also if we've been grandfathered in or are using ballistica-core
|
||||
# builds.
|
||||
return self.have_pro() or bool(
|
||||
_ba.get_account_misc_read_val_2('proOptionsUnlocked', False)
|
||||
or _ba.app.config.get('lc14292', 0) > 1)
|
||||
|
||||
def show_post_purchase_message(self) -> None:
|
||||
"""(internal)"""
|
||||
from ba._language import Lstr
|
||||
from ba._generated.enums import TimeType
|
||||
cur_time = _ba.time(TimeType.REAL)
|
||||
if (self.last_post_purchase_message_time is None
|
||||
or cur_time - self.last_post_purchase_message_time > 3.0):
|
||||
self.last_post_purchase_message_time = cur_time
|
||||
with _ba.Context('ui'):
|
||||
_ba.screenmessage(Lstr(resource='updatingAccountText',
|
||||
fallback_resource='purchasingText'),
|
||||
color=(0, 1, 0))
|
||||
_ba.playsound(_ba.getsound('click01'))
|
||||
|
||||
def on_account_state_changed(self) -> None:
|
||||
"""(internal)"""
|
||||
from ba._language import Lstr
|
||||
|
||||
# Run any pending promo codes we had queued up while not signed in.
|
||||
if _ba.get_account_state() == 'signed_in' and self.pending_promo_codes:
|
||||
for code in self.pending_promo_codes:
|
||||
_ba.screenmessage(Lstr(resource='submittingPromoCodeText'),
|
||||
color=(0, 1, 0))
|
||||
_ba.add_transaction({
|
||||
'type': 'PROMO_CODE',
|
||||
'expire_time': time.time() + 5,
|
||||
'code': code
|
||||
})
|
||||
_ba.run_transactions()
|
||||
self.pending_promo_codes = []
|
||||
|
||||
def add_pending_promo_code(self, code: str) -> None:
|
||||
"""(internal)"""
|
||||
from ba._language import Lstr
|
||||
from ba._generated.enums import TimeType
|
||||
|
||||
# If we're not signed in, queue up the code to run the next time we
|
||||
# are and issue a warning if we haven't signed in within the next
|
||||
# few seconds.
|
||||
if _ba.get_account_state() != 'signed_in':
|
||||
|
||||
def check_pending_codes() -> None:
|
||||
"""(internal)"""
|
||||
|
||||
# If we're still not signed in and have pending codes,
|
||||
# inform the user that they need to sign in to use them.
|
||||
if self.pending_promo_codes:
|
||||
_ba.screenmessage(Lstr(resource='signInForPromoCodeText'),
|
||||
color=(1, 0, 0))
|
||||
_ba.playsound(_ba.getsound('error'))
|
||||
|
||||
self.pending_promo_codes.append(code)
|
||||
_ba.timer(6.0, check_pending_codes, timetype=TimeType.REAL)
|
||||
return
|
||||
_ba.screenmessage(Lstr(resource='submittingPromoCodeText'),
|
||||
color=(0, 1, 0))
|
||||
_ba.add_transaction({
|
||||
'type': 'PROMO_CODE',
|
||||
'expire_time': time.time() + 5,
|
||||
'code': code
|
||||
})
|
||||
_ba.run_transactions()
|
||||
Loading…
Add table
Add a link
Reference in a new issue