From 44db9b2387e5bf9f1b3f16544dccb9ec98d3ceb9 Mon Sep 17 00:00:00 2001 From: Eric Froemling Date: Mon, 6 Apr 2020 12:55:01 -0700 Subject: [PATCH 01/16] changed ci to run on pull-requests --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4b33ee25..33ba820f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,6 +3,7 @@ name: CI on: # Run on pushes and also once per day (in case deps change under us) push: + pull_request: schedule: # Note: '*' is a special character in YAML so we have to quote the str. - cron: '0 12 * * *' From 9a6c0948247470bd273b6c97259c1cb6e55a8ecd Mon Sep 17 00:00:00 2001 From: Eric Froemling Date: Mon, 6 Apr 2020 14:05:58 -0700 Subject: [PATCH 02/16] Fixed spurious time value warnings and general tidying --- .github/workflows/ci.yml | 3 +- .../ba_data/python/bastd/ui/coop/browser.py | 87 +++++++++---------- 2 files changed, 45 insertions(+), 45 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 33ba820f..5a0a64d4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,7 +1,8 @@ name: CI on: - # Run on pushes and also once per day (in case deps change under us) + # Run on pushes, pull-requests, and also once per day + # (in case deps change under us, etc.) push: pull_request: schedule: diff --git a/assets/src/ba_data/python/bastd/ui/coop/browser.py b/assets/src/ba_data/python/bastd/ui/coop/browser.py index 491bc6c4..47cdf9e1 100644 --- a/assets/src/ba_data/python/bastd/ui/coop/browser.py +++ b/assets/src/ba_data/python/bastd/ui/coop/browser.py @@ -61,7 +61,7 @@ class CoopBrowserWindow(ba.Window): app = ba.app cfg = app.config - # if they provided an origin-widget, scale up from that + # If they provided an origin-widget, scale up from that. scale_origin: Optional[Tuple[float, float]] if origin_widget is not None: self._transition_out = 'out_scale' @@ -71,8 +71,8 @@ class CoopBrowserWindow(ba.Window): self._transition_out = 'out_right' scale_origin = None - # try to recreate the same number of buttons we had last time so our - # re-selection code works + # Try to recreate the same number of buttons we had last time so our + # re-selection code works. try: self._tournament_button_count = app.config['Tournament Rows'] except Exception: @@ -159,7 +159,7 @@ class CoopBrowserWindow(ba.Window): self._store_button_widget = None self._league_rank_button_widget = None - # move our corner buttons dynamically to keep them out of the way of + # Move our corner buttons dynamically to keep them out of the way of # the party icon :-( self._update_corner_button_positions() self._update_corner_button_positions_timer = ba.Timer( @@ -179,7 +179,7 @@ class CoopBrowserWindow(ba.Window): 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 v = self._height - 95 txt = ba.textwidget( @@ -229,22 +229,23 @@ class CoopBrowserWindow(ba.Window): simple_culling_v=10.0) self._subcontainer: Optional[ba.Widget] = None - # take note of our account state; we'll refresh later if this changes + # Take note of our account state; we'll refresh later if this changes. self._account_state_num = _ba.get_account_state_num() - # same for fg/bg state.. + + # Same for fg/bg state. self._fg_state = app.fg_state self._refresh() self._restore_state() - # even though we might display cached tournament data immediately, we - # don't consider it valid until we've pinged + # Even though we might display cached tournament data immediately, we + # don't consider it valid until we've pinged. # the server for an update self._tourney_data_up_to_date = False - # if we've got a cached tournament list for our account and info for - # each one of those tournaments, - # go ahead and display it as a starting point... + # If we've got a cached tournament list for our account and info for + # each one of those tournaments, go ahead and display it as a + # starting point. if (app.account_tournament_list is not None and app.account_tournament_list[0] == _ba.get_account_state_num() and all([ @@ -257,7 +258,7 @@ class CoopBrowserWindow(ba.Window): ] self._update_for_data(tourney_data) - # this will pull new data periodically, update timers, etc.. + # This will pull new data periodically, update timers, etc. self._update_timer = ba.Timer(1.0, ba.WeakCall(self._update), timetype=ba.TimeType.REAL, @@ -267,31 +268,32 @@ class CoopBrowserWindow(ba.Window): def _update(self) -> None: cur_time = ba.time(ba.TimeType.REAL) - # if its been a while since we got a tournament update, consider the + # If its been a while since we got a tournament update, consider the # data invalid (prevents us from joining tournaments if our internet - # connection goes down for a while) + # connection goes down for a while). if (self._last_tournament_query_response_time is None or ba.time(ba.TimeType.REAL) - self._last_tournament_query_response_time > 60.0 * 2): self._tourney_data_up_to_date = False - # if our account state has changed, do a full request + # If our account state has changed, do a full request. account_state_num = _ba.get_account_state_num() if account_state_num != self._account_state_num: self._account_state_num = account_state_num self._save_state() self._refresh() - # also encourage a new tournament query since this will clear out - # our current results.. + + # Also encourage a new tournament query since this will clear out + # our current results. if not self._doing_tournament_query: self._last_tournament_query_time = None - # if we've been backgrounded/foregrounded, invalidate our - # tournament entries (they will be refreshed below asap) + # If we've been backgrounded/foregrounded, invalidate our + # tournament entries (they will be refreshed below asap). if self._fg_state != ba.app.fg_state: self._tourney_data_up_to_date = False - # send off a new tournament query if its been long enough or whatnot.. + # Send off a new tournament query if its been long enough or whatnot. if not self._doing_tournament_query and ( self._last_tournament_query_time is None or cur_time - self._last_tournament_query_time > 30.0 @@ -306,17 +308,20 @@ class CoopBrowserWindow(ba.Window): callback=ba.WeakCall( self._on_tournament_query_response)) - # decrement time on our tournament buttons.. + # Decrement time on our tournament buttons. ads_enabled = _ba.have_incentivized_ad() for tbtn in self._tournament_buttons: tbtn['time_remaining'] = max(0, tbtn['time_remaining'] - 1) if tbtn['time_remaining_value_text'] is not None: ba.textwidget( edit=tbtn['time_remaining_value_text'], - text=ba.timestring(tbtn['time_remaining'], centi=False) if + text=ba.timestring(tbtn['time_remaining'], + centi=False, + suppress_format_warning=True) if (tbtn['has_time_remaining'] 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(): ba.imagewidget(edit=tbtn['entry_fee_ad_image'], opacity=1.0 if ads_enabled else 0.25) @@ -427,7 +432,8 @@ class CoopBrowserWindow(ba.Window): leader_score = ( ba.timestring(score[0] * 10, centi=True, - timeformat=ba.TimeFormat.MILLISECONDS) + timeformat=ba.TimeFormat.MILLISECONDS, + suppress_format_warning=True) if entry['scoreType'] == 'time' else str(score[0])) else: tbtn['leader'] = None @@ -445,7 +451,9 @@ class CoopBrowserWindow(ba.Window): '-' if entry is None or 'totalTime' not in entry else ba.Lstr( resource=self._r + '.ofTotalTimeText', subs=[('${TOTAL}', - ba.timestring(entry['totalTime'], centi=False))])) + ba.timestring(entry['totalTime'], + centi=False, + suppress_format_warning=True))])) ba.textwidget(edit=tbtn['time_remaining_out_of_text'], text=out_of_time_text) @@ -516,18 +524,14 @@ class CoopBrowserWindow(ba.Window): final_fee_str = ( ba.charstr(ba.SpecialChar.TICKET_BACKING) + str(final_fee)) - # final_fee_str: Union[str, ba.Lstr] = ( - # '' if fee_var is None else ba.Lstr( - # resource='getTicketsWindow.freeText') if final_fee == 0 - # else (ba.specialchar('ticket_backing') + str(final_fee))) ad_tries_remaining = ba.app.tournament_info[ tbtn['tournament_id']]['adTriesRemaining'] free_tries_remaining = ba.app.tournament_info[ tbtn['tournament_id']]['freeTriesRemaining'] - # now, if this fee allows ads and we support video ads, show - # the 'or ad' version + # 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'], @@ -542,7 +546,8 @@ class CoopBrowserWindow(ba.Window): tbtn['button_y'] + tbtn['button_scale_y'] - 60), scale=1.3, text=final_fee_str) - # possibly show number of ad-plays remaining + + # Possibly show number of ad-plays remaining. ba.textwidget( edit=tbtn['entry_fee_text_remaining'], position=(tbtn['button_x'] + 360, @@ -559,7 +564,8 @@ class CoopBrowserWindow(ba.Window): tbtn['button_y'] + tbtn['button_scale_y'] - 80), scale=1.3, text=final_fee_str) - # possibly show number of free-plays remaining + + # Possibly show number of free-plays remaining. ba.textwidget( edit=tbtn['entry_fee_text_remaining'], position=(tbtn['button_x'] + 360, @@ -927,15 +933,8 @@ class CoopBrowserWindow(ba.Window): 'Challenges:Meteor Shower', 'Challenges:Target Practice B', 'Challenges:Target Practice', - # 'Challenges:Lake Frigid Race', - # 'Challenges:Uber Runaround', - # 'Challenges:Runaround', - # 'Challenges:Pro Race', - # 'Challenges:Pro Football', - # 'Challenges:Epic Meteor Shower', - # 'Challenges:Testing', - # 'User:Ninja Fight', ] + # Show easter-egg-hunt either if its easter or we own it. if _ba.get_account_misc_read_val( 'easter', False) or _ba.get_purchased('games.easter_egg_hunt'): @@ -1456,7 +1455,7 @@ class CoopBrowserWindow(ba.Window): ba.playsound(ba.getsound('error')) return - # game is whatever the tournament tells us it is + # Game is whatever the tournament tells us it is. game = ba.app.tournament_info[ tournament_button['tournament_id']]['game'] @@ -1469,7 +1468,7 @@ class CoopBrowserWindow(ba.Window): height=130) return - # infinite onslaught/runaround require pro; bring up a store link if + # Infinite onslaught/runaround require pro; bring up a store link if # need be. if tournament_button is None and game in ( 'Challenges:Infinite Runaround', From 8b0b332f1ab7fd129f8c154855eb14c9cf08e9dd Mon Sep 17 00:00:00 2001 From: Eric Froemling Date: Mon, 6 Apr 2020 15:18:19 -0700 Subject: [PATCH 03/16] Added a proper DeathType enum to replace string values --- assets/src/ba_data/python/ba/__init__.py | 10 ++-- assets/src/ba_data/python/ba/_gameactivity.py | 5 +- assets/src/ba_data/python/ba/_messages.py | 18 +++++-- assets/src/ba_data/python/bastd/actor/flag.py | 2 +- .../ba_data/python/bastd/actor/playerspaz.py | 5 +- assets/src/ba_data/python/bastd/actor/spaz.py | 48 +++++++++++-------- .../src/ba_data/python/bastd/actor/spazbot.py | 2 +- .../ba_data/python/bastd/game/runaround.py | 5 +- .../ba_data/python/bastd/ui/coop/browser.py | 13 ++--- 9 files changed, 65 insertions(+), 43 deletions(-) diff --git a/assets/src/ba_data/python/ba/__init__.py b/assets/src/ba_data/python/ba/__init__.py index 47742952..4478b4d2 100644 --- a/assets/src/ba_data/python/ba/__init__.py +++ b/assets/src/ba_data/python/ba/__init__.py @@ -74,11 +74,11 @@ from ba._general import WeakCall, Call from ba._level import Level from ba._lobby import Lobby, Chooser from ba._math import normalized_color, is_point_in_box, vec3validate -from ba._messages import (OutOfBoundsMessage, DieMessage, StandMessage, - PickUpMessage, DropMessage, PickedUpMessage, - DroppedMessage, ShouldShatterMessage, - ImpactDamageMessage, FreezeMessage, ThawMessage, - HitMessage) +from ba._messages import (OutOfBoundsMessage, DeathType, DieMessage, + StandMessage, PickUpMessage, DropMessage, + PickedUpMessage, DroppedMessage, + ShouldShatterMessage, ImpactDamageMessage, + FreezeMessage, ThawMessage, HitMessage) from ba._music import setmusic, MusicPlayer, MusicType, MusicPlayMode from ba._powerup import PowerupMessage, PowerupAcceptMessage from ba._teambasesession import TeamBaseSession diff --git a/assets/src/ba_data/python/ba/_gameactivity.py b/assets/src/ba_data/python/ba/_gameactivity.py index 8f817f63..60857ede 100644 --- a/assets/src/ba_data/python/ba/_gameactivity.py +++ b/assets/src/ba_data/python/ba/_gameactivity.py @@ -658,7 +658,7 @@ class GameActivity(Activity): def on_player_leave(self, player: ba.Player) -> None: from ba._general import Call - from ba._messages import DieMessage + from ba._messages import DieMessage, DeathType super().on_player_leave(player) @@ -668,7 +668,8 @@ class GameActivity(Activity): # will incorrectly try to respawn them, etc. actor = player.actor if actor is not None: - _ba.pushcall(Call(actor.handlemessage, DieMessage(how='leftGame'))) + _ba.pushcall( + Call(actor.handlemessage, DieMessage(how=DeathType.LEFT_GAME))) player.set_actor(None) def handlemessage(self, msg: Any) -> Any: diff --git a/assets/src/ba_data/python/ba/_messages.py b/assets/src/ba_data/python/ba/_messages.py index ad06a1c9..a82bd481 100644 --- a/assets/src/ba_data/python/ba/_messages.py +++ b/assets/src/ba_data/python/ba/_messages.py @@ -24,6 +24,7 @@ from __future__ import annotations from dataclasses import dataclass from typing import TYPE_CHECKING +from enum import Enum import _ba @@ -40,6 +41,18 @@ class OutOfBoundsMessage: """ +class DeathType(Enum): + """A reason for a death. + + Category: Enums + """ + GENERIC = 'generic' + IMPACT = 'impact' + FALL = 'fall' + REACHED_GOAL = 'reached_goal' + LEFT_GAME = 'left_game' + + @dataclass class DieMessage: """A message telling an object to die. @@ -57,12 +70,11 @@ class DieMessage: its time with lingering corpses, sound effects, etc. how - The particular reason for death; 'fall', 'impact', 'leftGame', etc. - This can be examined for scoring or other purposes. + The particular reason for death. """ immediate: bool = False - how: str = 'generic' + how: DeathType = DeathType.GENERIC @dataclass diff --git a/assets/src/ba_data/python/bastd/actor/flag.py b/assets/src/ba_data/python/bastd/actor/flag.py index b62055fd..6ef08a63 100644 --- a/assets/src/ba_data/python/bastd/actor/flag.py +++ b/assets/src/ba_data/python/bastd/actor/flag.py @@ -350,7 +350,7 @@ class Flag(ba.Actor): elif isinstance(msg, ba.OutOfBoundsMessage): # We just kill ourselves when out-of-bounds.. would we ever not # want this?.. - self.handlemessage(ba.DieMessage(how='fall')) + self.handlemessage(ba.DieMessage(how=ba.DeathType.FALL)) elif isinstance(msg, ba.PickedUpMessage): self._held_count += 1 if self._held_count == 1 and self._counter is not None: diff --git a/assets/src/ba_data/python/bastd/actor/playerspaz.py b/assets/src/ba_data/python/bastd/actor/playerspaz.py index 1af781fc..a600f3a9 100644 --- a/assets/src/ba_data/python/bastd/actor/playerspaz.py +++ b/assets/src/ba_data/python/bastd/actor/playerspaz.py @@ -53,7 +53,7 @@ class PlayerSpazDeathMessage: """ def __init__(self, spaz: PlayerSpaz, was_killed: bool, - killerplayer: Optional[ba.Player], how: str): + killerplayer: Optional[ba.Player], how: ba.DeathType): """Instantiate a message with the given values.""" self.spaz = spaz self.killed = was_killed @@ -252,7 +252,8 @@ class PlayerSpaz(basespaz.Spaz): if not self._dead: # Immediate-mode or left-game deaths don't count as 'kills'. - killed = (not msg.immediate and msg.how != 'leftGame') + killed = (not msg.immediate + and msg.how is not ba.DeathType.LEFT_GAME) activity = self._activity() diff --git a/assets/src/ba_data/python/bastd/actor/spaz.py b/assets/src/ba_data/python/bastd/actor/spaz.py index 565bfa1b..28d06e1e 100644 --- a/assets/src/ba_data/python/bastd/actor/spaz.py +++ b/assets/src/ba_data/python/bastd/actor/spaz.py @@ -588,11 +588,12 @@ class Spaz(ba.Actor): def on_punched(self, damage: int) -> None: """Called when this spaz gets punched.""" - def get_death_points(self, how: str) -> Tuple[int, int]: + def get_death_points(self, how: ba.DeathType) -> Tuple[int, int]: """Get the points awarded for killing this spaz.""" - del how # unused arg + del how # Unused. num_hits = float(max(1, self._num_times_hit)) - # base points is simply 10 for 1-hit-kills and 5 otherwise + + # Base points is simply 10 for 1-hit-kills and 5 otherwise. importance = 2 if num_hits < 2 else 1 return (10 if num_hits < 2 else 5) * self.points_mult, importance @@ -604,7 +605,8 @@ class Spaz(ba.Actor): if not self._cursed: factory = get_factory() self._cursed = True - # add the curse material.. + + # Add the curse material. for attr in ['materials', 'roller_materials']: materials = getattr(self.node, attr) if factory.curse_material not in materials: @@ -616,7 +618,7 @@ class Spaz(ba.Actor): if self.curse_time is None: self.node.curse_death_time = -1 else: - # note: curse-death-time takes milliseconds + # Note: curse-death-time takes milliseconds. tval = ba.time() assert isinstance(tval, int) self.node.curse_death_time = int(1000.0 * @@ -629,7 +631,7 @@ class Spaz(ba.Actor): """ assert self.node self.node.boxing_gloves = True - if self._demo_mode: # preserve old behavior + if self._demo_mode: # Preserve old behavior. self._punch_power_scale = 1.7 self._punch_cooldown = 300 else: @@ -664,7 +666,7 @@ class Spaz(ba.Actor): self.shield_decay_timer = ba.Timer(0.5, ba.WeakCall(self.shield_decay), repeat=True) - # so user can see the decay + # So user can see the decay. self.shield.always_show_health_bar = True def shield_decay(self) -> None: @@ -698,17 +700,18 @@ class Spaz(ba.Actor): if self.node: self.node.handlemessage("hurt_sound") self.node.handlemessage("picked_up") - # this counts as a hit + + # This counts as a hit. self._num_times_hit += 1 elif isinstance(msg, ba.ShouldShatterMessage): - # eww; seems we have to do this in a timer or it wont work right + # Eww; seems we have to do this in a timer or it wont work right. # (since we're getting called from within update() perhaps?..) - # NOTE: should test to see if that's still the case + # NOTE: should test to see if that's still the case. ba.timer(0.001, ba.WeakCall(self.shatter)) elif isinstance(msg, ba.ImpactDamageMessage): - # eww; seems we have to do this in a timer or it wont work right + # Eww; seems we have to do this in a timer or it wont work right. # (since we're getting called from within update() perhaps?..) ba.timer(0.001, ba.WeakCall(self._hit_self, msg.intensity)) @@ -799,7 +802,8 @@ class Spaz(ba.Actor): timeformat=ba.TimeFormat.MILLISECONDS)) elif msg.poweruptype == 'shield': factory = get_factory() - # let's allow powerup-equipped shields to lose hp over time + + # Let's allow powerup-equipped shields to lose hp over time. self.equip_shields(decay=factory.shield_decay_rate > 0) elif msg.poweruptype == 'curse': self.curse() @@ -825,7 +829,8 @@ class Spaz(ba.Actor): elif msg.poweruptype == 'health': if self._cursed: self._cursed = False - # remove cursed material + + # Remove cursed material. factory = get_factory() for attr in ['materials', 'roller_materials']: materials = getattr(self.node, attr) @@ -861,7 +866,7 @@ class Spaz(ba.Actor): self.node.frozen = True ba.timer(5.0, ba.WeakCall(self.handlemessage, ba.ThawMessage())) - # instantly shatter if we're already dead + # Instantly shatter if we're already dead. # (otherwise its hard to tell we're dead) if self.hitpoints <= 0: self.shatter() @@ -880,7 +885,7 @@ class Spaz(ba.Actor): position=self.node.position) return True - # if we were recently hit, don't count this as another + # If we were recently hit, don't count this as another. # (so punch flurries and bomb pileups essentially count as 1 hit) local_time = ba.time(timeformat=ba.TimeFormat.MILLISECONDS) assert isinstance(local_time, int) @@ -893,13 +898,13 @@ class Spaz(ba.Actor): velocity_mag = msg.velocity_magnitude * self.impact_scale damage_scale = 0.22 - # if they've got a shield, deliver it to that instead.. + # If they've got a shield, deliver it to that instead. if self.shield: if msg.flat_damage: damage = msg.flat_damage * self.impact_scale else: - # hit our spaz with an impulse but tell it to only return - # theoretical damage; not apply the impulse.. + # Hit our spaz with an impulse but tell it to only return + # theoretical damage; not apply the impulse. assert msg.force_direction is not None self.node.handlemessage( "impulse", msg.pos[0], msg.pos[1], msg.pos[2], @@ -1086,7 +1091,8 @@ class Spaz(ba.Actor): if self.frozen and (damage > 200 or self.hitpoints <= 0): self.shatter() elif self.hitpoints <= 0: - self.node.handlemessage(ba.DieMessage(how='impact')) + self.node.handlemessage( + ba.DieMessage(how=ba.DeathType.IMPACT)) # if we're dead, take a look at the smoothed damage val # (which gives us a smoothed average of recent damage) and shatter @@ -1114,8 +1120,8 @@ class Spaz(ba.Actor): ba.timer(2.0, self.node.delete) elif isinstance(msg, ba.OutOfBoundsMessage): - # by default we just die here - self.handlemessage(ba.DieMessage(how='fall')) + # By default we just die here. + self.handlemessage(ba.DieMessage(how=ba.DeathType.FALL)) elif isinstance(msg, ba.StandMessage): self._last_stand_pos = (msg.position[0], msg.position[1], msg.position[2]) diff --git a/assets/src/ba_data/python/bastd/actor/spazbot.py b/assets/src/ba_data/python/bastd/actor/spazbot.py index cc5ea5fb..c2a4d734 100644 --- a/assets/src/ba_data/python/bastd/actor/spazbot.py +++ b/assets/src/ba_data/python/bastd/actor/spazbot.py @@ -80,7 +80,7 @@ class SpazBotDeathMessage: """ def __init__(self, badguy: SpazBot, killerplayer: Optional[ba.Player], - how: str): + how: ba.DeathType): """Instantiate with given values.""" self.badguy = badguy self.killerplayer = killerplayer diff --git a/assets/src/ba_data/python/bastd/game/runaround.py b/assets/src/ba_data/python/bastd/game/runaround.py index d0dbf2f3..923db3ac 100644 --- a/assets/src/ba_data/python/bastd/game/runaround.py +++ b/assets/src/ba_data/python/bastd/game/runaround.py @@ -415,7 +415,8 @@ class RunaroundGame(ba.CoopGameActivity): }) ba.animate(light, 'intensity', {0.0: 0, 0.1: 1, 0.5: 0}, loop=False) ba.timer(1.0, light.delete) - spaz.handlemessage(ba.DieMessage(immediate=True, how='goal')) + spaz.handlemessage( + ba.DieMessage(immediate=True, how=ba.DeathType.REACHED_GOAL)) if self._lives > 0: self._lives -= 1 @@ -1141,7 +1142,7 @@ class RunaroundGame(ba.CoopGameActivity): player, respawn_time) elif isinstance(msg, spazbot.SpazBotDeathMessage): - if msg.how == 'goal': + if msg.how is ba.DeathType.REACHED_GOAL: return pts, importance = msg.badguy.get_death_points(msg.how) if msg.killerplayer is not None: diff --git a/assets/src/ba_data/python/bastd/ui/coop/browser.py b/assets/src/ba_data/python/bastd/ui/coop/browser.py index 47cdf9e1..902fcd02 100644 --- a/assets/src/ba_data/python/bastd/ui/coop/browser.py +++ b/assets/src/ba_data/python/bastd/ui/coop/browser.py @@ -301,12 +301,13 @@ class CoopBrowserWindow(ba.Window): self._fg_state = ba.app.fg_state self._last_tournament_query_time = cur_time self._doing_tournament_query = True - _ba.tournament_query(args={ - 'source': 'coop window refresh', - 'numScores': 1 - }, - callback=ba.WeakCall( - self._on_tournament_query_response)) + _ba.tournament_query( + args={ + 'source': 'coop window refresh', + 'numScores': 1 + }, + callback=ba.WeakCall(self._on_tournament_query_response), + ) # Decrement time on our tournament buttons. ads_enabled = _ba.have_incentivized_ad() From 5638debcc9beea01a580599fb291a036ddbc1847 Mon Sep 17 00:00:00 2001 From: Eric Froemling Date: Mon, 6 Apr 2020 15:25:18 -0700 Subject: [PATCH 04/16] latest binaries, assets, and docs --- docs/ba_module.md | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/docs/ba_module.md b/docs/ba_module.md index 9d798d85..76b8d165 100644 --- a/docs/ba_module.md +++ b/docs/ba_module.md @@ -1,5 +1,5 @@ -

last updated on 2020-04-05 for Ballistica version 1.5.0 build 20001

+

last updated on 2020-04-06 for Ballistica version 1.5.0 build 20001

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 let me know. Happy modding!


@@ -165,6 +165,7 @@

Enums

    +
  • ba.DeathType
  • ba.MusicPlayMode
  • ba.MusicType
  • ba.Permission
  • @@ -1575,6 +1576,22 @@ the data object is requested and when it's value is accessed.


    +

    ba.DeathType

    +

    inherits from: enum.Enum

    +

    A reason for a death.

    + +

    Category: Enums +

    + +

    Values:

    +
      +
    • GENERIC
    • +
    • IMPACT
    • +
    • FALL
    • +
    • REACHED_GOAL
    • +
    • LEFT_GAME
    • +
    +

    ba.Dependency

    inherits from: typing.Generic

    A dependency on a DependencyComponent (with an optional config).

    @@ -1747,9 +1764,8 @@ Exception types on other errors).

    how, immediate

    how

    -

    str

    -

    The particular reason for death; 'fall', 'impact', 'leftGame', etc. -This can be examined for scoring or other purposes.

    +

    DeathType

    +

    The particular reason for death.

    immediate

    @@ -1764,7 +1780,7 @@ its time with lingering corpses, sound effects, etc.

    Methods:

    <constructor>

    -

    ba.DieMessage(immediate: 'bool' = False, how: 'str' = 'generic')

    +

    ba.DieMessage(immediate: bool = False, how: DeathType = <DeathType.GENERIC: generic>)

    From b3f656ade731adafc0e4a726f332c32260dc86e4 Mon Sep 17 00:00:00 2001 From: Eric Froemling Date: Mon, 6 Apr 2020 16:20:14 -0700 Subject: [PATCH 05/16] Fixed if __debug__ statements so they are properly optimized out --- .idea/inspectionProfiles/Default.xml | 1 + assets/src/ba_data/python/ba/_coopsession.py | 2 +- assets/src/ba_data/python/bastd/actor/background.py | 2 +- .../src/ba_data/python/bastd/actor/controlsguide.py | 2 +- assets/src/ba_data/python/bastd/actor/image.py | 9 +++++---- assets/src/ba_data/python/bastd/actor/popuptext.py | 2 +- assets/src/ba_data/python/bastd/actor/spaz.py | 11 ++++++++--- assets/src/ba_data/python/bastd/actor/text.py | 2 +- assets/src/ba_data/python/bastd/actor/tipstext.py | 2 +- assets/src/ba_data/python/bastd/actor/zoomtext.py | 2 +- assets/src/ba_data/python/efro/entity/_field.py | 2 +- 11 files changed, 22 insertions(+), 15 deletions(-) diff --git a/.idea/inspectionProfiles/Default.xml b/.idea/inspectionProfiles/Default.xml index 2831a6dc..5639f88f 100644 --- a/.idea/inspectionProfiles/Default.xml +++ b/.idea/inspectionProfiles/Default.xml @@ -48,6 +48,7 @@ +

    Methods:

    -
    <constructor>, associate_with_player(), cancel_multi_kill_timer(), get_icon(), get_last_player(), get_name(), get_spaz(), getactivity(), submit_kill()
    +
    <constructor>, associate_with_player(), cancel_multi_kill_timer(), get_icon(), get_last_player(), get_name(), getactivity(), submit_kill()

    <constructor>

    ba.PlayerRecord(name: str, name_full: str, player: ba.Player, stats: ba.Stats)

    @@ -3717,12 +3717,6 @@ other players.

    Return the player entry's name.

    -
    -

    get_spaz()

    -

    get_spaz(self) -> Optional[ba.Actor]

    - -

    Return the player entry's spaz.

    -

    getactivity()

    getactivity(self) -> Optional[ba.Activity]

    @@ -4161,7 +4155,7 @@ session.set_activity(foo) and then ba.newnode

    Methods:

    -
    <constructor>, get_records(), getactivity(), player_got_hit(), player_got_new_spaz(), player_lost_spaz(), player_scored(), register_player(), reset(), reset_accum(), set_activity()
    +
    <constructor>, get_records(), getactivity(), player_got_hit(), player_scored(), player_was_killed(), register_player(), reset(), reset_accum(), set_activity()

    <constructor>

    ba.Stats()

    @@ -4186,18 +4180,6 @@ session.set_activity(foo) and then ba.newnode

    Call this when a player got hit.

    -
    -

    player_got_new_spaz()

    -

    player_got_new_spaz(self, player: ba.Player, spaz: ba.Actor) -> None

    - -

    Call this when a player gets a new Spaz.

    - -
    -

    player_lost_spaz()

    -

    player_lost_spaz(self, player: ba.Player, killed: bool = False, killer: ba.Player = None) -> None

    - -

    Should be called when a player loses a spaz.

    -

    player_scored()

    player_scored(self, player: ba.Player, base_points: int = 1, target: Sequence[float] = None, kill: bool = False, victim_player: ba.Player = None, scale: float = 1.0, color: Sequence[float] = None, title: Union[str, ba.Lstr] = None, screenmessage: bool = True, display: bool = True, importance: int = 1, showpoints: bool = True, big_message: bool = False) -> int

    @@ -4206,6 +4188,12 @@ session.set_activity(foo) and then ba.newnode

    Return value is actual score with multipliers and such factored in.

    +
    +

    player_was_killed()

    +

    player_was_killed(self, player: ba.Player, killed: bool = False, killer: ba.Player = None) -> None

    + +

    Should be called when a player is killed.

    +

    register_player()

    register_player(self, player: ba.Player) -> None

    From a3168f609eaf1f00ab54c0795fceddbde5452036 Mon Sep 17 00:00:00 2001 From: Eric Froemling Date: Mon, 6 Apr 2020 21:29:32 -0700 Subject: [PATCH 11/16] More submit_score annotation fixes --- assets/src/ba_data/python/_ba.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/assets/src/ba_data/python/_ba.py b/assets/src/ba_data/python/_ba.py index 10b89d06..2c9e72c0 100644 --- a/assets/src/ba_data/python/_ba.py +++ b/assets/src/ba_data/python/_ba.py @@ -34,7 +34,7 @@ NOTE: This file was autogenerated by gendummymodule; do not edit by hand. """ # (hash we can use to see if this file is out of date) -# SOURCES_HASH=98060135444187925075927346963557892275 +# SOURCES_HASH=107090811089111809221805243334294892547 # I'm sorry Pylint. I know this file saddens you. Be strong. # pylint: disable=useless-suppression @@ -3613,14 +3613,14 @@ def submit_score(game: str, order: str = 'increasing', tournament_id: Optional[str] = None, score_type: str = 'points', - campaign: Optional[ba.Campaign] = None, - level: Optional[ba.Level] = None) -> None: + campaign: Optional[str] = None, + level: Optional[str] = None) -> None: """submit_score(game: str, config: str, name: Any, score: Optional[int], callback: Callable, friend_callback: Optional[Callable], order: str = 'increasing', tournament_id: Optional[str] = None, score_type: str = 'points', - campaign: Optional[ba.Campaign] = None, - level: Optional[ba.Level] = None) -> None + campaign: Optional[str] = None, + level: Optional[str] = None) -> None (internal) From 3b0233c6fcb8fc24d10f910393e7f7cc19f11c73 Mon Sep 17 00:00:00 2001 From: Eric Froemling Date: Mon, 6 Apr 2020 21:34:43 -0700 Subject: [PATCH 12/16] latest binaries, assets, and docs --- .efrocachemap | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.efrocachemap b/.efrocachemap index b92d8ca6..4d07766f 100644 --- a/.efrocachemap +++ b/.efrocachemap @@ -4114,10 +4114,10 @@ "assets/build/windows/x64/python.exe": "https://files.ballistica.net/cache/ba1/25/a7/dc87c1be41605eb6fefd0145144c", "assets/build/windows/x64/python37.dll": "https://files.ballistica.net/cache/ba1/b9/e4/d912f56e42e9991bcbb4c804cfcb", "assets/build/windows/x64/pythonw.exe": "https://files.ballistica.net/cache/ba1/6c/bb/b6f52c306aa4e88061510e96cefe", - "build/prefab/linux/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/ed/b0/9d9f5dcb6988d619b15e0cb93332", - "build/prefab/linux/release/ballisticacore": "https://files.ballistica.net/cache/ba1/2d/fc/b1108eff8fba32109b90d8a792e5", - "build/prefab/mac/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/d1/0a/b8c7a6c6726ff2a5278c21b28893", - "build/prefab/mac/release/ballisticacore": "https://files.ballistica.net/cache/ba1/ac/c3/9f998f2820894a1e9cf91c2c0e38", - "build/prefab/windows/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/48/09/342e1e1fd1f6b75ed14e40e82315", - "build/prefab/windows/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/87/a0/4f5b746c9496b43b5d1b6ad7f895" + "build/prefab/linux/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/66/08/19630024c471684ea791edd5a923", + "build/prefab/linux/release/ballisticacore": "https://files.ballistica.net/cache/ba1/c8/f3/787fc36ae2b95202232927d55568", + "build/prefab/mac/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/af/db/1979a698d94bb9b10b96f835ec38", + "build/prefab/mac/release/ballisticacore": "https://files.ballistica.net/cache/ba1/ca/51/f09d8ff4818e955a8439a703db49", + "build/prefab/windows/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/8f/db/4260aa0ea989c12e7622934b46c6", + "build/prefab/windows/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/af/7a/e752d1d53b3e09beb95d4a4bcf75" } \ No newline at end of file From dcba94072da3760dadffd545b6d9e53774960670 Mon Sep 17 00:00:00 2001 From: Eric Froemling Date: Mon, 6 Apr 2020 21:56:51 -0700 Subject: [PATCH 13/16] latest binaries, assets, and docs --- .efrocachemap | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.efrocachemap b/.efrocachemap index 4d07766f..4843efaa 100644 --- a/.efrocachemap +++ b/.efrocachemap @@ -4114,10 +4114,10 @@ "assets/build/windows/x64/python.exe": "https://files.ballistica.net/cache/ba1/25/a7/dc87c1be41605eb6fefd0145144c", "assets/build/windows/x64/python37.dll": "https://files.ballistica.net/cache/ba1/b9/e4/d912f56e42e9991bcbb4c804cfcb", "assets/build/windows/x64/pythonw.exe": "https://files.ballistica.net/cache/ba1/6c/bb/b6f52c306aa4e88061510e96cefe", - "build/prefab/linux/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/66/08/19630024c471684ea791edd5a923", - "build/prefab/linux/release/ballisticacore": "https://files.ballistica.net/cache/ba1/c8/f3/787fc36ae2b95202232927d55568", - "build/prefab/mac/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/af/db/1979a698d94bb9b10b96f835ec38", - "build/prefab/mac/release/ballisticacore": "https://files.ballistica.net/cache/ba1/ca/51/f09d8ff4818e955a8439a703db49", - "build/prefab/windows/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/8f/db/4260aa0ea989c12e7622934b46c6", - "build/prefab/windows/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/af/7a/e752d1d53b3e09beb95d4a4bcf75" + "build/prefab/linux/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/3c/35/3da15c0f86b988ddeb45e51ec22f", + "build/prefab/linux/release/ballisticacore": "https://files.ballistica.net/cache/ba1/25/d3/1f181ad16b5e5b46b89a9feec4e8", + "build/prefab/mac/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/73/a1/41440d4deeff94db0ad1dc94a1ed", + "build/prefab/mac/release/ballisticacore": "https://files.ballistica.net/cache/ba1/ca/9e/a6c455fc9c980be58d2b67685db1", + "build/prefab/windows/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/cf/65/db941276fa358d64bb5ea5a22ef4", + "build/prefab/windows/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/d0/a0/c9ac53752e659b72b6f1fb173a07" } \ No newline at end of file From dba81dc71c2c5ea582af6345a8f7e07bbce9ce38 Mon Sep 17 00:00:00 2001 From: Eric Froemling Date: Mon, 6 Apr 2020 22:18:16 -0700 Subject: [PATCH 14/16] More misc engine fixes. --- assets/src/ba_data/python/_ba.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/src/ba_data/python/_ba.py b/assets/src/ba_data/python/_ba.py index 2c9e72c0..71267d9e 100644 --- a/assets/src/ba_data/python/_ba.py +++ b/assets/src/ba_data/python/_ba.py @@ -34,7 +34,7 @@ NOTE: This file was autogenerated by gendummymodule; do not edit by hand. """ # (hash we can use to see if this file is out of date) -# SOURCES_HASH=107090811089111809221805243334294892547 +# SOURCES_HASH=262346642235815908245289158414705543661 # I'm sorry Pylint. I know this file saddens you. Be strong. # pylint: disable=useless-suppression From 77c050b7713c04f30f96b85d7ac64364a45e8dd9 Mon Sep 17 00:00:00 2001 From: Eric Froemling Date: Mon, 6 Apr 2020 22:23:40 -0700 Subject: [PATCH 15/16] latest binaries, assets, and docs --- .efrocachemap | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.efrocachemap b/.efrocachemap index 4843efaa..6a883a28 100644 --- a/.efrocachemap +++ b/.efrocachemap @@ -4114,10 +4114,10 @@ "assets/build/windows/x64/python.exe": "https://files.ballistica.net/cache/ba1/25/a7/dc87c1be41605eb6fefd0145144c", "assets/build/windows/x64/python37.dll": "https://files.ballistica.net/cache/ba1/b9/e4/d912f56e42e9991bcbb4c804cfcb", "assets/build/windows/x64/pythonw.exe": "https://files.ballistica.net/cache/ba1/6c/bb/b6f52c306aa4e88061510e96cefe", - "build/prefab/linux/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/3c/35/3da15c0f86b988ddeb45e51ec22f", - "build/prefab/linux/release/ballisticacore": "https://files.ballistica.net/cache/ba1/25/d3/1f181ad16b5e5b46b89a9feec4e8", - "build/prefab/mac/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/73/a1/41440d4deeff94db0ad1dc94a1ed", - "build/prefab/mac/release/ballisticacore": "https://files.ballistica.net/cache/ba1/ca/9e/a6c455fc9c980be58d2b67685db1", - "build/prefab/windows/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/cf/65/db941276fa358d64bb5ea5a22ef4", - "build/prefab/windows/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/d0/a0/c9ac53752e659b72b6f1fb173a07" + "build/prefab/linux/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/01/9f/6ce9331a09f15f2da1087d4ffba9", + "build/prefab/linux/release/ballisticacore": "https://files.ballistica.net/cache/ba1/99/74/1709486aaf04f5fdd3f90ca0aab9", + "build/prefab/mac/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/27/a6/5749795ec376cb5cdaf652dacdaa", + "build/prefab/mac/release/ballisticacore": "https://files.ballistica.net/cache/ba1/e9/ef/82e9a50695f333d68847585aa9a6", + "build/prefab/windows/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/c8/24/ac5bb7409ae0c5274e26a355a526", + "build/prefab/windows/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/18/2e/cfa42c79a5024bb2111dfe347b51" } \ No newline at end of file From db29a3ec5a97c159e7efd3cd2fdfd08fb455d2a0 Mon Sep 17 00:00:00 2001 From: Eric Froemling Date: Mon, 6 Apr 2020 22:29:54 -0700 Subject: [PATCH 16/16] First level should complete mostly successfully now --- .../python/bastd/activity/coopscorescreen.py | 73 +++++++++++-------- 1 file changed, 42 insertions(+), 31 deletions(-) diff --git a/assets/src/ba_data/python/bastd/activity/coopscorescreen.py b/assets/src/ba_data/python/bastd/activity/coopscorescreen.py index b0ef4ab4..b0fb56f8 100644 --- a/assets/src/ba_data/python/bastd/activity/coopscorescreen.py +++ b/assets/src/ba_data/python/bastd/activity/coopscorescreen.py @@ -66,9 +66,11 @@ class CoopScoreScreen(ba.Activity): self._menu_icon_texture = ba.gettexture('menuIcon') self._next_level_icon_texture = ba.gettexture('nextLevelIcon') + self._campaign: ba.Campaign = settings['campaign'] + self._have_achievements = bool( - get_achievements_for_coop_level(settings['campaign'].get_name() + - ":" + settings['level'])) + get_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) @@ -122,12 +124,12 @@ class CoopScoreScreen(ba.Activity): self._next_level_error: Optional[ba.Actor] = None # Score/gameplay bits. - self._was_complete = None - self._is_complete = None - self._newly_complete = None - self._is_more_levels = None - self._next_level_name = None - self._show_friend_scores = None + self._was_complete: Optional[bool] = None + self._is_complete: Optional[bool] = None + self._newly_complete: Optional[bool] = None + self._is_more_levels: Optional[bool] = None + self._next_level_name: Optional[str] = None + self._show_friend_scores: Optional[bool] = None self._show_info: Optional[Dict[str, Any]] = None self._name_str: Optional[str] = None self._friends_loading_status: Optional[ba.Actor] = None @@ -135,9 +137,15 @@ class CoopScoreScreen(ba.Activity): self._tournament_time_remaining_text_timer: Optional[ba.Timer] = None self._player_info = settings['player_info'] - self._score = settings['score'] - self._fail_message = settings['fail_message'] + self._score: Optional[int] = settings['score'] + assert isinstance(self._score, (int, type(None))) + + self._fail_message: Optional[str] = settings['fail_message'] + assert isinstance(self._fail_message, (str, type(None))) + self._begin_time = ba.time() + + self._score_order: str if 'score_order' in settings: if not settings['score_order'] in ['increasing', 'decreasing']: raise Exception("Invalid score order: " + @@ -145,7 +153,9 @@ class CoopScoreScreen(ba.Activity): self._score_order = settings['score_order'] else: self._score_order = 'increasing' + assert isinstance(self._score_order, str) + self._score_type: str if 'score_type' in settings: if not settings['score_type'] in ['points', 'time']: raise Exception("Invalid score type: " + @@ -153,12 +163,12 @@ class CoopScoreScreen(ba.Activity): self._score_type = settings['score_type'] else: self._score_type = 'points' + assert isinstance(self._score_type, str) - self._campaign = settings['campaign'] - self._level_name = settings['level'] + self._level_name: str = settings['level'] + assert isinstance(self._level_name, str) - self._game_name_str = self._campaign.get_name( - ) + ":" + self._level_name + self._game_name_str = self._campaign.name + ":" + self._level_name self._game_config_str = str(len( self._player_info)) + "p" + self._campaign.get_level( self._level_name).get_score_version_string().replace(' ', '_') @@ -170,11 +180,11 @@ class CoopScoreScreen(ba.Activity): try: self._old_best_rank = self._campaign.get_level( - self._level_name).get_rating() + self._level_name).rating except Exception: self._old_best_rank = 0.0 - self._victory = (settings['outcome'] == 'victory') + self._victory: bool = settings['outcome'] == 'victory' def __del__(self) -> None: super().__del__() @@ -255,6 +265,7 @@ class CoopScoreScreen(ba.Activity): # next one, set it as current (this won't happen otherwise). if (self._is_complete and self._is_more_levels and not self._newly_complete): + assert self._next_level_name is not None self._campaign.set_selected_level(self._next_level_name) ba.containerwidget(edit=self._root_ui, transition='out_left') with ba.Context(self): @@ -294,7 +305,7 @@ class CoopScoreScreen(ba.Activity): ba.DieMessage())) def _should_show_worlds_best_button(self) -> bool: - # link is too complicated to display with no browser + # Link is too complicated to display with no browser. return ba.is_browser_likely_available() def request_ui(self) -> None: @@ -511,26 +522,26 @@ class CoopScoreScreen(ba.Activity): # Calc whether the level is complete and other stuff. levels = self._campaign.get_levels() level = self._campaign.get_level(self._level_name) - self._was_complete = level.get_complete() + self._was_complete = level.complete self._is_complete = (self._was_complete or self._victory) self._newly_complete = (self._is_complete and not self._was_complete) - self._is_more_levels = ((level.get_index() < len(levels) - 1) - and self._campaign.is_sequential()) + self._is_more_levels = ((level.index < len(levels) - 1) + and self._campaign.sequential) # Any time we complete a level, set the next one as unlocked. if self._is_complete and self._is_more_levels: _ba.add_transaction({ 'type': 'COMPLETE_LEVEL', - 'campaign': self._campaign.get_name(), + 'campaign': self._campaign.name, 'level': self._level_name }) - self._next_level_name = levels[level.get_index() + 1].get_name() + self._next_level_name = levels[level.index + 1].name # If this is the first time we completed it, set the next one # as current. if self._newly_complete: cfg = ba.app.config - cfg['Selected Coop Game'] = (self._campaign.get_name() + ":" + + cfg['Selected Coop Game'] = (self._campaign.name + ":" + self._next_level_name) cfg.commit() self._campaign.set_selected_level(self._next_level_name) @@ -577,8 +588,7 @@ class CoopScoreScreen(ba.Activity): pstr = ba.Lstr(value='- ${A} -', subs=[('${A}', ba.Lstr(resource='singlePlayerCountText'))]) - ZoomText(self._campaign.get_level( - self._level_name).get_display_string(), + ZoomText(self._campaign.get_level(self._level_name).displayname, maxwidth=800, flash=False, trail=False, @@ -614,7 +624,7 @@ class CoopScoreScreen(ba.Activity): ba.timer(0.35, ba.Call(ba.playsound, self._score_display_sound_small)) - # Vestigial remain.. this stuff should just be instance vars. + # Vestigial remain; this stuff should just be instance vars. self._show_info = {} if self._score is not None: @@ -678,13 +688,13 @@ class CoopScoreScreen(ba.Activity): self._level_name).get_score_version_string()) _ba.add_transaction({ 'type': 'SET_LEVEL_LOCAL_HIGH_SCORES', - 'campaign': self._campaign.get_name(), + 'campaign': self._campaign.name, 'level': self._level_name, 'scoreVersion': sver, 'scores': our_high_scores_all }) if _ba.get_account_state() != 'signed_in': - # we expect this only in kiosk mode; complain otherwise.. + # We expect this only in kiosk mode; complain otherwise. if not ba.app.kiosk_mode: print('got not-signed-in at score-submit; unexpected') if self._show_friend_scores: @@ -703,7 +713,7 @@ class CoopScoreScreen(ba.Activity): order=self._score_order, tournament_id=self.session.tournament_id, score_type=self._score_type, - campaign=self._campaign.get_name() + campaign=self._campaign.name if self._campaign is not None else None, level=self._level_name) @@ -1373,8 +1383,7 @@ class CoopScoreScreen(ba.Activity): dostar(2, 10 - 30, -112, '7.5') dostar(3, 77 - 30, -112, '9.5') try: - best_rank = self._campaign.get_level( - self._level_name).get_rating() + best_rank = self._campaign.get_level(self._level_name).rating except Exception: best_rank = 0.0 @@ -1449,6 +1458,8 @@ class CoopScoreScreen(ba.Activity): def _show_score_val(self, offs_x: float) -> None: from bastd.actor.text import Text from bastd.actor.zoomtext import ZoomText + assert self._score_type is not None + assert self._score is not None ZoomText((str(self._score) if self._score_type == 'points' else ba.timestring(self._score * 10, timeformat=ba.TimeFormat.MILLISECONDS)),