Merge branch 'efroemling:master' into master

This commit is contained in:
Loup 2024-03-14 06:03:11 +05:30 committed by GitHub
commit 3b7b1ea79c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 416 additions and 40 deletions

42
.efrocachemap generated
View File

@ -421,7 +421,7 @@
"build/assets/ba_data/audio/zoeOw.ogg": "74befe45a8417e95b6a2233c51992a26", "build/assets/ba_data/audio/zoeOw.ogg": "74befe45a8417e95b6a2233c51992a26",
"build/assets/ba_data/audio/zoePickup01.ogg": "48ab8cddfcde36a750856f3f81dd20c8", "build/assets/ba_data/audio/zoePickup01.ogg": "48ab8cddfcde36a750856f3f81dd20c8",
"build/assets/ba_data/audio/zoeScream01.ogg": "2b468aedfa8741090247f04eb9e6df55", "build/assets/ba_data/audio/zoeScream01.ogg": "2b468aedfa8741090247f04eb9e6df55",
"build/assets/ba_data/data/langdata.json": "0d9f610cd2284cad4316cc2cb131a08b", "build/assets/ba_data/data/langdata.json": "8409781047f46ca6627eacdfc0b4d3d3",
"build/assets/ba_data/data/languages/arabic.json": "2c2915e10124bb8f69206da9c608d57c", "build/assets/ba_data/data/languages/arabic.json": "2c2915e10124bb8f69206da9c608d57c",
"build/assets/ba_data/data/languages/belarussian.json": "09954e550d13d3d9cb5a635a1d32a151", "build/assets/ba_data/data/languages/belarussian.json": "09954e550d13d3d9cb5a635a1d32a151",
"build/assets/ba_data/data/languages/chinese.json": "bb51b5aa614830c561e8fe2542a9ab8a", "build/assets/ba_data/data/languages/chinese.json": "bb51b5aa614830c561e8fe2542a9ab8a",
@ -4061,26 +4061,26 @@
"build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1", "build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1",
"build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae", "build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae",
"build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599", "build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599",
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "88c4aa547dd4715a2e272f3738587b6d", "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "db921cf43e8ebf733712fb5bbc673f66",
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "f16453fcad766fec901df5b49c30f3c8", "build/prefab/full/linux_arm64_gui/release/ballisticakit": "4be0f3a7a88da423847863af41ac9c63",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "b70afa60a1a41edab49b1aaa3a5c64bb", "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "7c92d738e7cc724de2ca31cb876224e6",
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "604ec018ae78313c48536ed729d27466", "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "c2f69ed83f77b602e2a2b2b1c1c78cc6",
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "4902925ae1a5e1d985ce96071af3aade", "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "b1c766d4ce567f965c53ff2a4c5c85f4",
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "d3d70106be65df66be7ac08a6b486e37", "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "86ebbd9111f8a0fe7905cef7aba1f6db",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "d086c930efa95aad560591f76188620e", "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "8182f4e00ad579eb4c7be5ec1ddca8cb",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "55c591cc3150103361816404a6b39f93", "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "3d9e0e7ad8706133e61fb7f7127c3ff5",
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "3fc3fb6d92f28ac3a2cadf00e3a9a69b", "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "20373ee90f8987bed980143d5377ae44",
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "403004d2b9a7a0a051e5943a8c1d423a", "build/prefab/full/mac_arm64_gui/release/ballisticakit": "99d7d247a422eaa46737e3232408e879",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "5de045f8c27357a3123f5e9f81a1019a", "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "079c4fd0b6f8aa50510064704466904b",
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "5dbea7c2327da665dd3ec3a99c81b3b2", "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "216efc77915b75f39f0f15c2806bfbb9",
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "89c5f534a3ebf919d3cf095f15abf2dd", "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "204320756307e1833b284c3180e70319",
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "3b45bc9d1be09e8236a2b9f11331026e", "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "3e9e4e1761fd763eb584598fc0a3ad0a",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "6e7174e340c82df192385b8a828a6dcd", "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "b8f587f21f39f35072d6c83116c9ae96",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "5ddcb009ae84e70ef82dc13b4952f706", "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "0c92e386ab7406da6a719131321bf592",
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "fd35547e009f1f7237b057a1dc5ba043", "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "ce48b60be52023e1942cb493bb2f58fb",
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "6f68f2749227bc3c0774bc3e6b16d520", "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "d53ee4e8eed3e1a218db2f927a62c353",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "1073911522710591baa6d37fe0dbcb2c", "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "6597b00a07975230cb3f5b0fa19e0ed4",
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "a7986fae95855606844a9ad39bd0ec00", "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "0ff41b8dc440c0490e9ae3bc22c3d201",
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "d9865523059d8cf11b2bef4b9da9a8c9", "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "d9865523059d8cf11b2bef4b9da9a8c9",
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "56d6440f62c271c4ce9ef520400395a3", "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "56d6440f62c271c4ce9ef520400395a3",
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "d9865523059d8cf11b2bef4b9da9a8c9", "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "d9865523059d8cf11b2bef4b9da9a8c9",

View File

@ -1,4 +1,4 @@
### 1.7.33 (build 21777, api 8, 2024-03-13) ### 1.7.33 (build 21778, api 8, 2024-03-13)
- Stress test input-devices are now a bit smarter; they won't press any buttons - Stress test input-devices are now a bit smarter; they won't press any buttons
while UIs are up (this could cause lots of chaos if it happened). while UIs are up (this could cause lots of chaos if it happened).
- Added a 'Show Demos When Idle' option in advanced settings. If enabled, the - Added a 'Show Demos When Idle' option in advanced settings. If enabled, the
@ -20,6 +20,8 @@
languages; I feel it helps keep logic more understandable and should help us languages; I feel it helps keep logic more understandable and should help us
catch problems where a base class changes or removes a method and child catch problems where a base class changes or removes a method and child
classes forget to adapt to the change. classes forget to adapt to the change.
- Respawn icons now have dotted steps showing decimal progress to assist
players on calculating when they are gonna respawn. (Thanks 3alTemp!)
- Replays now have rewind/fast-forward buttons!! (Thanks Dliwk, vishal332008!) - Replays now have rewind/fast-forward buttons!! (Thanks Dliwk, vishal332008!)
- Custom spaz "curse_time" values now work properly. (Thanks Temp!) - Custom spaz "curse_time" values now work properly. (Thanks Temp!)
- Implemented `efro.dataclassio.IOMultiType` which will make my life a lot - Implemented `efro.dataclassio.IOMultiType` which will make my life a lot

View File

@ -51,6 +51,10 @@
### Rikko ### Rikko
- Created the original "reject_recently_left_players" plugin - Created the original "reject_recently_left_players" plugin
### SoK
- Modder
- BSE Heartbeat mechanic port
### Temp (3alTemp) ### Temp (3alTemp)
- Original idea for customizable series length on GUI builds - Original idea for customizable series length on GUI builds
- Modder & Bug Fixer - Modder & Bug Fixer
@ -60,4 +64,3 @@
### Loup Garou ### Loup Garou
- Added sphinx documentation generation - Added sphinx documentation generation

View File

@ -513,6 +513,7 @@
"ba_data/python/bauiv1lib/settings/__pycache__/gamepadselect.cpython-311.opt-1.pyc", "ba_data/python/bauiv1lib/settings/__pycache__/gamepadselect.cpython-311.opt-1.pyc",
"ba_data/python/bauiv1lib/settings/__pycache__/graphics.cpython-311.opt-1.pyc", "ba_data/python/bauiv1lib/settings/__pycache__/graphics.cpython-311.opt-1.pyc",
"ba_data/python/bauiv1lib/settings/__pycache__/keyboard.cpython-311.opt-1.pyc", "ba_data/python/bauiv1lib/settings/__pycache__/keyboard.cpython-311.opt-1.pyc",
"ba_data/python/bauiv1lib/settings/__pycache__/moddingtools.cpython-311.opt-1.pyc",
"ba_data/python/bauiv1lib/settings/__pycache__/nettesting.cpython-311.opt-1.pyc", "ba_data/python/bauiv1lib/settings/__pycache__/nettesting.cpython-311.opt-1.pyc",
"ba_data/python/bauiv1lib/settings/__pycache__/plugins.cpython-311.opt-1.pyc", "ba_data/python/bauiv1lib/settings/__pycache__/plugins.cpython-311.opt-1.pyc",
"ba_data/python/bauiv1lib/settings/__pycache__/pluginsettings.cpython-311.opt-1.pyc", "ba_data/python/bauiv1lib/settings/__pycache__/pluginsettings.cpython-311.opt-1.pyc",
@ -529,6 +530,7 @@
"ba_data/python/bauiv1lib/settings/gamepadselect.py", "ba_data/python/bauiv1lib/settings/gamepadselect.py",
"ba_data/python/bauiv1lib/settings/graphics.py", "ba_data/python/bauiv1lib/settings/graphics.py",
"ba_data/python/bauiv1lib/settings/keyboard.py", "ba_data/python/bauiv1lib/settings/keyboard.py",
"ba_data/python/bauiv1lib/settings/moddingtools.py",
"ba_data/python/bauiv1lib/settings/nettesting.py", "ba_data/python/bauiv1lib/settings/nettesting.py",
"ba_data/python/bauiv1lib/settings/plugins.py", "ba_data/python/bauiv1lib/settings/plugins.py",
"ba_data/python/bauiv1lib/settings/pluginsettings.py", "ba_data/python/bauiv1lib/settings/pluginsettings.py",

View File

@ -406,6 +406,7 @@ SCRIPT_TARGETS_PY_PUBLIC = \
$(BUILD_DIR)/ba_data/python/bauiv1lib/settings/gamepadselect.py \ $(BUILD_DIR)/ba_data/python/bauiv1lib/settings/gamepadselect.py \
$(BUILD_DIR)/ba_data/python/bauiv1lib/settings/graphics.py \ $(BUILD_DIR)/ba_data/python/bauiv1lib/settings/graphics.py \
$(BUILD_DIR)/ba_data/python/bauiv1lib/settings/keyboard.py \ $(BUILD_DIR)/ba_data/python/bauiv1lib/settings/keyboard.py \
$(BUILD_DIR)/ba_data/python/bauiv1lib/settings/moddingtools.py \
$(BUILD_DIR)/ba_data/python/bauiv1lib/settings/nettesting.py \ $(BUILD_DIR)/ba_data/python/bauiv1lib/settings/nettesting.py \
$(BUILD_DIR)/ba_data/python/bauiv1lib/settings/plugins.py \ $(BUILD_DIR)/ba_data/python/bauiv1lib/settings/plugins.py \
$(BUILD_DIR)/ba_data/python/bauiv1lib/settings/pluginsettings.py \ $(BUILD_DIR)/ba_data/python/bauiv1lib/settings/pluginsettings.py \
@ -681,6 +682,7 @@ SCRIPT_TARGETS_PYC_PUBLIC = \
$(BUILD_DIR)/ba_data/python/bauiv1lib/settings/__pycache__/gamepadselect.cpython-311.opt-1.pyc \ $(BUILD_DIR)/ba_data/python/bauiv1lib/settings/__pycache__/gamepadselect.cpython-311.opt-1.pyc \
$(BUILD_DIR)/ba_data/python/bauiv1lib/settings/__pycache__/graphics.cpython-311.opt-1.pyc \ $(BUILD_DIR)/ba_data/python/bauiv1lib/settings/__pycache__/graphics.cpython-311.opt-1.pyc \
$(BUILD_DIR)/ba_data/python/bauiv1lib/settings/__pycache__/keyboard.cpython-311.opt-1.pyc \ $(BUILD_DIR)/ba_data/python/bauiv1lib/settings/__pycache__/keyboard.cpython-311.opt-1.pyc \
$(BUILD_DIR)/ba_data/python/bauiv1lib/settings/__pycache__/moddingtools.cpython-311.opt-1.pyc \
$(BUILD_DIR)/ba_data/python/bauiv1lib/settings/__pycache__/nettesting.cpython-311.opt-1.pyc \ $(BUILD_DIR)/ba_data/python/bauiv1lib/settings/__pycache__/nettesting.cpython-311.opt-1.pyc \
$(BUILD_DIR)/ba_data/python/bauiv1lib/settings/__pycache__/plugins.cpython-311.opt-1.pyc \ $(BUILD_DIR)/ba_data/python/bauiv1lib/settings/__pycache__/plugins.cpython-311.opt-1.pyc \
$(BUILD_DIR)/ba_data/python/bauiv1lib/settings/__pycache__/pluginsettings.cpython-311.opt-1.pyc \ $(BUILD_DIR)/ba_data/python/bauiv1lib/settings/__pycache__/pluginsettings.cpython-311.opt-1.pyc \

View File

@ -136,8 +136,11 @@ def create_user_system_scripts() -> None:
path = f'{env.python_directory_user}/sys/{env.version}' path = f'{env.python_directory_user}/sys/{env.version}'
pathtmp = path + '_tmp' pathtmp = path + '_tmp'
if os.path.exists(path): if os.path.exists(path):
print('Delete Existing User Scripts and try again.') print('Delete Existing User Scripts first!')
_babase.screenmessage('Delete Existing User Scripts and try again.') _babase.screenmessage(
'Delete Existing User Scripts first!',
color=(1, 0, 0),
)
return return
if os.path.exists(pathtmp): if os.path.exists(pathtmp):
shutil.rmtree(pathtmp) shutil.rmtree(pathtmp)
@ -161,7 +164,7 @@ def create_user_system_scripts() -> None:
f"'\nRestart {_babase.appname()} to use them." f"'\nRestart {_babase.appname()} to use them."
f' (use babase.quit() to exit the game)' f' (use babase.quit() to exit the game)'
) )
_babase.screenmessage('Created User System Scripts') _babase.screenmessage('Created User System Scripts', color=(0, 1, 0))
if app.classic is not None and app.classic.platform == 'android': if app.classic is not None and app.classic.platform == 'android':
print( print(
'Note: the new files may not be visible via ' 'Note: the new files may not be visible via '
@ -186,9 +189,14 @@ def delete_user_system_scripts() -> None:
f'Restart {_babase.appname()} to use internal' f'Restart {_babase.appname()} to use internal'
f' scripts. (use babase.quit() to exit the game)' f' scripts. (use babase.quit() to exit the game)'
) )
_babase.screenmessage('Deleted User System Scripts') _babase.screenmessage('Deleted User System Scripts', color=(0, 1, 0))
_babase.screenmessage(
f'Restart {_babase.appname()} to take effect.',
color=(0, 1, 0),
)
else: else:
print(f"User system scripts not found at '{path}'.") print(f"User system scripts not found at '{path}'.")
_babase.screenmessage('User Scripts Not Found', color=(1, 0, 0))
# If the sys path is empty, kill it. # If the sys path is empty, kill it.
dpath = env.python_directory_user + '/sys' dpath = env.python_directory_user + '/sys'

View File

@ -52,7 +52,7 @@ if TYPE_CHECKING:
# Build number and version of the ballistica binary we expect to be # Build number and version of the ballistica binary we expect to be
# using. # using.
TARGET_BALLISTICA_BUILD = 21777 TARGET_BALLISTICA_BUILD = 21778
TARGET_BALLISTICA_VERSION = '1.7.33' TARGET_BALLISTICA_VERSION = '1.7.33'

View File

@ -22,7 +22,9 @@ class RespawnIcon:
def __init__(self, player: bs.Player, respawn_time: float): def __init__(self, player: bs.Player, respawn_time: float):
"""Instantiate with a Player and respawn_time (in seconds).""" """Instantiate with a Player and respawn_time (in seconds)."""
# pylint: disable=too-many-locals
self._visible = True self._visible = True
self._dots_epic_only = False
on_right, offs_extra, respawn_icons = self._get_context(player) on_right, offs_extra, respawn_icons = self._get_context(player)
@ -92,7 +94,7 @@ class RespawnIcon:
assert self._name.node assert self._name.node
bs.animate(self._name.node, 'scale', {0: 0, 0.1: 0.5}) bs.animate(self._name.node, 'scale', {0: 0, 0.1: 0.5})
tpos = (-60 - h_offs if on_right else 60 + h_offs, -192 + offs) tpos = (-60 - h_offs if on_right else 60 + h_offs, -193 + offs)
self._text: bs.NodeActor | None = bs.NodeActor( self._text: bs.NodeActor | None = bs.NodeActor(
bs.newnode( bs.newnode(
'text', 'text',
@ -109,11 +111,37 @@ class RespawnIcon:
}, },
) )
) )
dpos = [ipos[0] + (7 if on_right else -7), ipos[1] - 16]
self._dec_text: bs.NodeActor | None = None
if (
self._dots_epic_only
and bs.getactivity().globalsnode.slow_motion
or not self._dots_epic_only
):
self._dec_text = bs.NodeActor(
bs.newnode(
'text',
attrs={
'position': dpos,
'h_attach': 'right' if on_right else 'left',
'h_align': 'right' if on_right else 'left',
'scale': 0.65,
'shadow': 0.5,
'flatness': 0.5,
'v_attach': 'top',
'color': bs.safecolor(icon['tint_color']),
'text': '',
},
)
)
assert self._text.node assert self._text.node
bs.animate(self._text.node, 'scale', {0: 0, 0.1: 0.9}) bs.animate(self._text.node, 'scale', {0: 0, 0.1: 0.9})
if self._dec_text:
bs.animate(self._dec_text.node, 'scale', {0: 0, 0.1: 0.65})
self._respawn_time = bs.time() + respawn_time self._respawn_time = bs.time() + respawn_time
self._dec_timer: bs.Timer | None = None
self._update() self._update()
self._timer: bs.Timer | None = bs.Timer( self._timer: bs.Timer | None = bs.Timer(
1.0, bs.WeakCall(self._update), repeat=True 1.0, bs.WeakCall(self._update), repeat=True
@ -128,7 +156,7 @@ class RespawnIcon:
"""Return info on where we should be shown and stored.""" """Return info on where we should be shown and stored."""
activity = bs.getactivity() activity = bs.getactivity()
if isinstance(bs.getsession(), bs.DualTeamSession): if isinstance(activity.session, bs.DualTeamSession):
on_right = player.team.id % 2 == 1 on_right = player.team.id % 2 == 1
# Store a list of icons in the team. # Store a list of icons in the team.
@ -153,12 +181,43 @@ class RespawnIcon:
offs_extra = -20 offs_extra = -20
return on_right, offs_extra, icons return on_right, offs_extra, icons
def _dec_step(self, display: list) -> None:
if not self._dec_text:
self._dec_timer = None
return
old_text: bs.Lstr | str = self._dec_text.node.text
iterate: int
# Get the following display text using our current one.
try:
iterate = display.index(old_text) + 1
# If we don't match any in the display list, we
# can assume we've just started iterating.
except ValueError:
iterate = 0
# Kill the timer if we're at the last iteration.
if iterate >= len(display):
self._dec_timer = None
return
self._dec_text.node.text = display[iterate]
def _update(self) -> None: def _update(self) -> None:
remaining = int(round(self._respawn_time - bs.time())) remaining = int(round(self._respawn_time - bs.time()))
if remaining > 0: if remaining > 0:
assert self._text is not None assert self._text is not None
if self._text.node: if self._text.node:
self._text.node.text = str(remaining) self._text.node.text = str(remaining)
if self._dec_text:
# Display our decimal dots.
self._dec_text.node.text = '...'
# Start the timer to tick down.
self._dec_timer = bs.Timer(
0.25,
bs.WeakCall(self._dec_step, ['..', '.', '']),
repeat=True,
)
else: else:
self._visible = False self._visible = False
self._image = self._text = self._timer = self._name = None self._image = self._text = self._dec_text = self._timer = (
self._name
) = None

View File

@ -776,7 +776,6 @@ class ChargerBotPro(ChargerBot):
color = PRO_BOT_COLOR color = PRO_BOT_COLOR
highlight = PRO_BOT_HIGHLIGHT highlight = PRO_BOT_HIGHLIGHT
default_shields = True
default_boxing_gloves = True default_boxing_gloves = True
points_mult = 3 points_mult = 3

View File

@ -190,6 +190,7 @@ class RunaroundGame(bs.CoopGameActivity[Player, Team]):
self._lives_text: bs.NodeActor | None = None self._lives_text: bs.NodeActor | None = None
self._flawless = True self._flawless = True
self._time_bonus_timer: bs.Timer | None = None self._time_bonus_timer: bs.Timer | None = None
self._lives_hbtime: bs.Timer | None = None
self._time_bonus_text: bs.NodeActor | None = None self._time_bonus_text: bs.NodeActor | None = None
self._time_bonus_mult: float | None = None self._time_bonus_mult: float | None = None
self._wave_text: bs.NodeActor | None = None self._wave_text: bs.NodeActor | None = None
@ -551,6 +552,20 @@ class RunaroundGame(bs.CoopGameActivity[Player, Team]):
if self._lives == 0: if self._lives == 0:
self._bots.stop_moving() self._bots.stop_moving()
self.continue_or_end_game() self.continue_or_end_game()
# Heartbeat behavior
if self._lives < 5:
hbtime = 0.39 + (0.21 * self._lives)
self._lives_hbtime = bs.Timer(
hbtime,
lambda: self.heart_dyin(True, hbtime),
repeat=True
)
self.heart_dyin(True)
else:
self._lives_hbtime = None
self.heart_dyin(False)
assert self._lives_text is not None assert self._lives_text is not None
assert self._lives_text.node assert self._lives_text.node
self._lives_text.node.text = str(self._lives) self._lives_text.node.text = str(self._lives)
@ -1392,3 +1407,31 @@ class RunaroundGame(bs.CoopGameActivity[Player, Team]):
def _set_can_end_wave(self) -> None: def _set_can_end_wave(self) -> None:
self._can_end_wave = True self._can_end_wave = True
def heart_dyin(self,
status: bool,
time: float = 1.22) -> None:
""" Makes the UI heart beat at low health. """
assert self._lives_bg is not None
if self._lives_bg.node.exists():
return
heart = self._lives_bg.node
# Make the heart beat intensely!
if status:
bs.animate_array(heart, 'scale', 2, {
0:(90,90),
time*0.1:(105,105),
time*0.21:(88,88),
time*0.42:(90,90),
time*0.52:(105,105),
time*0.63:(88,88),
time:(90,90),
})
# Neutralize heartbeat (Done did when dead.)
else:
bs.animate_array(heart, 'scale', 2, {
0.0: list(heart.scale),
time: (90,90),
})

View File

@ -43,7 +43,10 @@ class UIV1Subsystem(babase.AppSubsystem):
self._uiscale: babase.UIScale self._uiscale: babase.UIScale
interfacetype = env['ui_scale'] interfacetype = babase.app.config.get('UI Scale', env['ui_scale'])
if interfacetype == 'auto':
interfacetype = env['ui_scale']
if interfacetype == 'large': if interfacetype == 'large':
self._uiscale = babase.UIScale.LARGE self._uiscale = babase.UIScale.LARGE
elif interfacetype == 'medium': elif interfacetype == 'medium':

View File

@ -454,7 +454,7 @@ class MainMenuWindow(bui.Window):
resource='watchWindow.playbackSpeedText', resource='watchWindow.playbackSpeedText',
subs=[('${SPEED}', str(1.23))], subs=[('${SPEED}', str(1.23))],
), ),
position=(h, v + v_offs + 7 * t_scale), position=(h, v + v_offs + 15 * t_scale),
h_align='center', h_align='center',
v_align='center', v_align='center',
size=(0, 0), size=(0, 0),
@ -543,7 +543,8 @@ class MainMenuWindow(bui.Window):
bui.textwidget( bui.textwidget(
parent=self._root_widget, parent=self._root_widget,
draw_controller=btn, draw_controller=btn,
text='<<', # text='<<',
text=bui.charstr(bui.SpecialChar.REWIND_BUTTON),
position=( position=(
h - b_size - b_buffer_1 * 2, h - b_size - b_buffer_1 * 2,
v - b_size * 0.5 - b_buffer_2 + 5 * t_scale + v_offs, v - b_size * 0.5 - b_buffer_2 + 5 * t_scale + v_offs,
@ -568,7 +569,8 @@ class MainMenuWindow(bui.Window):
bui.textwidget( bui.textwidget(
parent=self._root_widget, parent=self._root_widget,
draw_controller=btn, draw_controller=btn,
text='>>', # text='>>',
text=bui.charstr(bui.SpecialChar.FAST_FORWARD_BUTTON),
position=( position=(
h + b_size + b_buffer_1 * 2, h + b_size + b_buffer_1 * 2,
v - b_size * 0.5 - b_buffer_2 + 5 * t_scale + v_offs, v - b_size * 0.5 - b_buffer_2 + 5 * t_scale + v_offs,
@ -1454,8 +1456,9 @@ class MainMenuWindow(bui.Window):
def _resume(self) -> None: def _resume(self) -> None:
assert bui.app.classic is not None assert bui.app.classic is not None
bui.app.classic.resume() bui.app.classic.resume()
if self._root_widget: # if self._root_widget:
bui.containerwidget(edit=self._root_widget, transition='out_right') # bui.containerwidget(edit=self._root_widget,
# transition='out_right')
bui.app.ui_v1.clear_main_menu_window(transition='out_right') bui.app.ui_v1.clear_main_menu_window(transition='out_right')
# If there's callbacks waiting for this window to go away, call them. # If there's callbacks waiting for this window to go away, call them.

View File

@ -1,6 +1,7 @@
# Released under the MIT License. See LICENSE for details. # Released under the MIT License. See LICENSE for details.
# #
"""UI functionality for advanced settings.""" """UI functionality for advanced settings."""
# pylint: disable=too-many-lines
from __future__ import annotations from __future__ import annotations
@ -108,6 +109,7 @@ class AdvancedSettingsWindow(bui.Window):
if self._do_net_test_button: if self._do_net_test_button:
self._sub_height += self._extra_button_spacing self._sub_height += self._extra_button_spacing
self._sub_height += self._spacing * 2.0 # plugins self._sub_height += self._spacing * 2.0 # plugins
self._sub_height += self._spacing * 2.0 # modding tools
self._r = 'settingsWindowAdvanced' self._r = 'settingsWindowAdvanced'
@ -192,6 +194,7 @@ class AdvancedSettingsWindow(bui.Window):
from bauiv1lib import promocode as _unused7 from bauiv1lib import promocode as _unused7
from bauiv1lib import debug as _unused8 from bauiv1lib import debug as _unused8
from bauiv1lib.settings import plugins as _unused9 from bauiv1lib.settings import plugins as _unused9
from bauiv1lib.settings import moddingtools as _unused10
def _update_lang_status(self) -> None: def _update_lang_status(self) -> None:
if self._complete_langs_list is not None: if self._complete_langs_list is not None:
@ -579,6 +582,19 @@ class AdvancedSettingsWindow(bui.Window):
bui.open_url, 'https://ballistica.net/wiki/modding-guide' bui.open_url, 'https://ballistica.net/wiki/modding-guide'
), ),
) )
v -= self._spacing * 2.0
self._modding_tools_button = bui.buttonwidget(
parent=self._subcontainer,
position=(self._sub_width / 2 - this_button_width / 2, v - 10),
size=(this_button_width, 60),
autoselect=True,
label=bui.Lstr(resource=f'{self._r}.moddingToolsText'),
text_scale=1.0,
on_activate_call=self._on_modding_tools_button_press,
)
if self._show_always_use_internal_keyboard: if self._show_always_use_internal_keyboard:
assert self._always_use_internal_keyboard_check_box is not None assert self._always_use_internal_keyboard_check_box is not None
bui.widget( bui.widget(
@ -767,6 +783,24 @@ class AdvancedSettingsWindow(bui.Window):
from_window=self._root_widget, from_window=self._root_widget,
) )
def _on_modding_tools_button_press(self) -> None:
# pylint: disable=cyclic-import
from bauiv1lib.settings.moddingtools import ModdingToolsWindow
# no-op if our underlying widget is dead or on its way out.
if not self._root_widget or self._root_widget.transitioning_out:
return
self._save_state()
bui.containerwidget(edit=self._root_widget, transition='out_left')
assert bui.app.classic is not None
bui.app.ui_v1.set_main_menu_window(
ModdingToolsWindow(
origin_widget=self._modding_tools_button
).get_root_widget(),
from_window=self._root_widget,
)
def _on_promo_code_press(self) -> None: def _on_promo_code_press(self) -> None:
from bauiv1lib.promocode import PromoCodeWindow from bauiv1lib.promocode import PromoCodeWindow
from bauiv1lib.account import show_sign_in_prompt from bauiv1lib.account import show_sign_in_prompt
@ -810,6 +844,7 @@ class AdvancedSettingsWindow(bui.Window):
def _save_state(self) -> None: def _save_state(self) -> None:
# pylint: disable=too-many-branches # pylint: disable=too-many-branches
# pylint: disable=too-many-statements
try: try:
sel = self._root_widget.get_selected_child() sel = self._root_widget.get_selected_child()
if sel == self._scrollwidget: if sel == self._scrollwidget:
@ -852,6 +887,8 @@ class AdvancedSettingsWindow(bui.Window):
sel_name = 'ShowUserMods' sel_name = 'ShowUserMods'
elif sel == self._plugins_button: elif sel == self._plugins_button:
sel_name = 'Plugins' sel_name = 'Plugins'
elif sel == self._modding_tools_button:
sel_name = 'ModdingTools'
elif sel == self._modding_guide_button: elif sel == self._modding_guide_button:
sel_name = 'ModdingGuide' sel_name = 'ModdingGuide'
elif sel == self._language_inform_checkbox: elif sel == self._language_inform_checkbox:
@ -919,6 +956,8 @@ class AdvancedSettingsWindow(bui.Window):
sel = self._show_user_mods_button sel = self._show_user_mods_button
elif sel_name == 'Plugins': elif sel_name == 'Plugins':
sel = self._plugins_button sel = self._plugins_button
elif sel_name == 'ModdingTools':
sel = self._modding_tools_button
elif sel_name == 'ModdingGuide': elif sel_name == 'ModdingGuide':
sel = self._modding_guide_button sel = self._modding_guide_button
elif sel_name == 'LangInform': elif sel_name == 'LangInform':

View File

@ -0,0 +1,207 @@
# Released under the MIT License. See LICENSE for details.
#
"""UI functionality for Modding Tools."""
from __future__ import annotations
import babase
import bauiv1 as bui
from bauiv1lib.popup import PopupMenu
from bauiv1lib.confirm import ConfirmWindow
class ModdingToolsWindow(bui.Window):
"""Window for accessing modding tools."""
def __init__(
self,
transition: str = 'in_right',
origin_widget: bui.Widget | None = None,
):
app = bui.app
assert app.classic is not None
# If they provided an origin-widget, scale up from that.
scale_origin: tuple[float, float] | None
if origin_widget is not None:
self._transition_out = 'out_scale'
scale_origin = origin_widget.get_screen_space_center()
transition = 'in_scale'
else:
self._transition_out = 'out_right'
scale_origin = None
uiscale = app.ui_v1.uiscale
self._width = 970.0 if uiscale is bui.UIScale.SMALL else 670.0
x_inset = 150 if uiscale is bui.UIScale.SMALL else 0
self._height = (
390.0
if uiscale is bui.UIScale.SMALL
else 450.0 if uiscale is bui.UIScale.MEDIUM else 520.0
)
self._spacing = 32
top_extra = 10 if uiscale is bui.UIScale.SMALL else 0
self._scroll_width = self._width - (100 + 2 * x_inset)
self._scroll_height = self._height - 115.0
self._sub_width = self._scroll_width * 0.95
self._sub_height = 100.0
super().__init__(
root_widget=bui.containerwidget(
size=(self._width, self._height + top_extra),
transition=transition,
toolbar_visibility='menu_minimal',
scale_origin_stack_offset=scale_origin,
scale=(
2.06
if uiscale is bui.UIScale.SMALL
else 1.4 if uiscale is bui.UIScale.MEDIUM else 1.0
),
stack_offset=(
(0, -25) if uiscale is bui.UIScale.SMALL else (0, 0)
),
)
)
self._r = 'settingsModdingTools'
if app.ui_v1.use_toolbars and uiscale is bui.UIScale.SMALL:
bui.containerwidget(
edit=self._root_widget, on_cancel_call=self._do_back
)
self._back_button = None
else:
self._back_button = bui.buttonwidget(
parent=self._root_widget,
position=(53 + x_inset, self._height - 60),
size=(140, 60),
scale=0.8,
autoselect=True,
label=bui.Lstr(resource='backText'),
button_type='back',
on_activate_call=self._do_back,
)
bui.containerwidget(
edit=self._root_widget, cancel_button=self._back_button
)
self._title_text = bui.textwidget(
parent=self._root_widget,
position=(0, self._height - 52),
size=(self._width, 25),
text=bui.Lstr(resource='moddingToolsTitleText'),
color=app.ui_v1.title_color,
h_align='center',
v_align='top',
)
if self._back_button is not None:
bui.buttonwidget(
edit=self._back_button,
button_type='backSmall',
size=(60, 60),
label=bui.charstr(bui.SpecialChar.BACK),
)
self._scrollwidget = bui.scrollwidget(
parent=self._root_widget,
position=(50 + x_inset, 50),
simple_culling_v=20.0,
highlight=False,
size=(self._scroll_width, self._scroll_height),
selection_loops_to_parent=True,
)
bui.widget(edit=self._scrollwidget, right_widget=self._scrollwidget)
self._subcontainer = bui.containerwidget(
parent=self._scrollwidget,
size=(self._sub_width, self._sub_height),
background=False,
selection_loops_to_parent=True,
)
v = self._sub_height - 35
this_button_width = 410
v -= self._spacing * 1.2
self._create_user_system_scripts_button = bui.buttonwidget(
parent=self._subcontainer,
position=(self._sub_width / 2 - this_button_width / 2, v - 10),
size=(this_button_width, 60),
autoselect=True,
label=bui.Lstr(resource='createUserSystemScriptsText'),
text_scale=1.0,
on_activate_call=babase.modutils.create_user_system_scripts,
)
v -= self._spacing * 2.5
self._delete_user_system_scripts_button = bui.buttonwidget(
parent=self._subcontainer,
position=(self._sub_width / 2 - this_button_width / 2, v - 10),
size=(this_button_width, 60),
autoselect=True,
label=bui.Lstr(resource='deleteUserSystemScriptsText'),
text_scale=1.0,
on_activate_call=lambda: ConfirmWindow(
action=babase.modutils.delete_user_system_scripts,
),
)
v -= self._spacing * 2.5
bui.textwidget(
parent=self._subcontainer,
position=(170, v + 10),
size=(0, 0),
text=bui.Lstr(value='UI SIZE :'),
color=app.ui_v1.title_color,
h_align='center',
v_align='center',
)
PopupMenu(
parent=self._subcontainer,
position=(230, v - 20),
button_size=(200.0, 60.0),
choices=[
'auto',
'small',
'medium',
'large',
],
choices_display=[
bui.Lstr(resource='autoText'),
bui.Lstr(resource='smallText'),
bui.Lstr(resource='mediumText'),
bui.Lstr(resource='largeText'),
],
current_choice=app.config.get('UI Scale', 'auto'),
on_value_change_call=self._set_uiscale,
)
def _set_uiscale(self, val: str) -> None:
cfg = bui.app.config
cfg['UI Scale'] = val
cfg.apply_and_commit()
if bui.app.ui_v1.uiscale.name != val.upper():
bui.screenmessage(
bui.Lstr(resource='settingsWindowAdvanced.mustRestartText'),
color=(1.0, 0.5, 0.0),
)
def _do_back(self) -> None:
from bauiv1lib.settings.advanced import AdvancedSettingsWindow
# no-op if our underlying widget is dead or on its way out.
if not self._root_widget or self._root_widget.transitioning_out:
return
bui.containerwidget(
edit=self._root_widget, transition=self._transition_out
)
assert bui.app.classic is not None
bui.app.ui_v1.set_main_menu_window(
AdvancedSettingsWindow(transition='in_left').get_root_widget(),
from_window=self._root_widget,
)

View File

@ -47,6 +47,12 @@ TextGraphics::TextGraphics() {
g.pen_offset_y -= 0.1f; g.pen_offset_y -= 0.1f;
} }
// Bring Fast Forward & Rewind down and to the left a bit.
if (index == 13 || index == 15) {
g.pen_offset_y -= 0.055;
g.pen_offset_x -= 0.01;
}
// Shrink account logos and move them up a bit. // Shrink account logos and move them up a bit.
if (index == 29 || index == 32 || index == 33 || index == 38 if (index == 29 || index == 32 || index == 33 || index == 38
|| index == 40 || index == 48 || index == 49) { || index == 40 || index == 48 || index == 49) {

View File

@ -39,7 +39,7 @@ auto main(int argc, char** argv) -> int {
namespace ballistica { namespace ballistica {
// These are set automatically via script; don't modify them here. // These are set automatically via script; don't modify them here.
const int kEngineBuildNumber = 21777; const int kEngineBuildNumber = 21778;
const char* kEngineVersion = "1.7.33"; const char* kEngineVersion = "1.7.33";
const int kEngineApiVersion = 8; const int kEngineApiVersion = 8;