mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-02-06 15:47:06 +08:00
Cleaned up music playback
This commit is contained in:
parent
6f3f1644b4
commit
2a2e64b7ab
5
.idea/dictionaries/ericf.xml
generated
5
.idea/dictionaries/ericf.xml
generated
@ -436,6 +436,7 @@
|
|||||||
<w>domreg</w>
|
<w>domreg</w>
|
||||||
<w>domsg</w>
|
<w>domsg</w>
|
||||||
<w>dont</w>
|
<w>dont</w>
|
||||||
|
<w>doplay</w>
|
||||||
<w>doraise</w>
|
<w>doraise</w>
|
||||||
<w>dosend</w>
|
<w>dosend</w>
|
||||||
<w>dosomething</w>
|
<w>dosomething</w>
|
||||||
@ -1066,6 +1067,7 @@
|
|||||||
<w>mtime</w>
|
<w>mtime</w>
|
||||||
<w>mtrans</w>
|
<w>mtrans</w>
|
||||||
<w>mtvos</w>
|
<w>mtvos</w>
|
||||||
|
<w>mtype</w>
|
||||||
<w>mult</w>
|
<w>mult</w>
|
||||||
<w>multibytecodec</w>
|
<w>multibytecodec</w>
|
||||||
<w>multikillcount</w>
|
<w>multikillcount</w>
|
||||||
@ -1074,6 +1076,8 @@
|
|||||||
<w>multiteamendscreen</w>
|
<w>multiteamendscreen</w>
|
||||||
<w>multiteamjoinscreen</w>
|
<w>multiteamjoinscreen</w>
|
||||||
<w>multithreaded</w>
|
<w>multithreaded</w>
|
||||||
|
<w>musicinfo</w>
|
||||||
|
<w>musicinfos</w>
|
||||||
<w>musicplayer</w>
|
<w>musicplayer</w>
|
||||||
<w>musictype</w>
|
<w>musictype</w>
|
||||||
<w>musopen</w>
|
<w>musopen</w>
|
||||||
@ -1526,6 +1530,7 @@
|
|||||||
<w>socketmodule</w>
|
<w>socketmodule</w>
|
||||||
<w>socketserver</w>
|
<w>socketserver</w>
|
||||||
<w>somevar</w>
|
<w>somevar</w>
|
||||||
|
<w>soundtrackname</w>
|
||||||
<w>sourceimages</w>
|
<w>sourceimages</w>
|
||||||
<w>sourcelines</w>
|
<w>sourcelines</w>
|
||||||
<w>spacelen</w>
|
<w>spacelen</w>
|
||||||
|
|||||||
@ -50,6 +50,9 @@
|
|||||||
- The bs.Vector class is no more; in its place is a shiny new ba.Vec3 which is implemented internally in C++ so its nice and speedy. Will probably update certain things like vector node attrs to support this class in the future since it makes vector math nice and convenient.
|
- The bs.Vector class is no more; in its place is a shiny new ba.Vec3 which is implemented internally in C++ so its nice and speedy. Will probably update certain things like vector node attrs to support this class in the future since it makes vector math nice and convenient.
|
||||||
- Ok you get the point..
|
- Ok you get the point..
|
||||||
|
|
||||||
|
### 1.4.151 (14371)
|
||||||
|
- Added Chinese-Traditional language and improved translations for others.
|
||||||
|
|
||||||
### 1.4.150 (14369)
|
### 1.4.150 (14369)
|
||||||
- Telnet port can now be specified in the config
|
- Telnet port can now be specified in the config
|
||||||
- Telnet socket no longer opens on headless build when telnet access is off (reduces DoS attack potential)
|
- Telnet socket no longer opens on headless build when telnet access is off (reduces DoS attack potential)
|
||||||
|
|||||||
@ -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)
|
# (hash we can use to see if this file is out of date)
|
||||||
# SOURCES_HASH=107308741262112812748560676667362932520
|
# SOURCES_HASH=237130603961569354119127975507628873256
|
||||||
|
|
||||||
# I'm sorry Pylint. I know this file saddens you. Be strong.
|
# I'm sorry Pylint. I know this file saddens you. Be strong.
|
||||||
# pylint: disable=useless-suppression
|
# pylint: disable=useless-suppression
|
||||||
@ -2737,62 +2737,6 @@ def is_running_on_ouya() -> bool:
|
|||||||
return bool()
|
return bool()
|
||||||
|
|
||||||
|
|
||||||
def itunes_get_library_source() -> None:
|
|
||||||
"""itunes_get_library_source() -> None
|
|
||||||
|
|
||||||
(internal)
|
|
||||||
"""
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def itunes_get_playlists() -> List[str]:
|
|
||||||
"""itunes_get_playlists() -> List[str]
|
|
||||||
|
|
||||||
(internal)
|
|
||||||
"""
|
|
||||||
return ["blah", "blah2"]
|
|
||||||
|
|
||||||
|
|
||||||
def itunes_get_volume() -> int:
|
|
||||||
"""itunes_get_volume() -> int
|
|
||||||
|
|
||||||
(internal)
|
|
||||||
"""
|
|
||||||
return int()
|
|
||||||
|
|
||||||
|
|
||||||
def itunes_init() -> None:
|
|
||||||
"""itunes_init() -> None
|
|
||||||
|
|
||||||
(internal)
|
|
||||||
"""
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def itunes_play_playlist(playlist: str) -> bool:
|
|
||||||
"""itunes_play_playlist(playlist: str) -> bool
|
|
||||||
|
|
||||||
(internal)
|
|
||||||
"""
|
|
||||||
return bool()
|
|
||||||
|
|
||||||
|
|
||||||
def itunes_set_volume(volume: int) -> None:
|
|
||||||
"""itunes_set_volume(volume: int) -> None
|
|
||||||
|
|
||||||
(internal)
|
|
||||||
"""
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def itunes_stop() -> None:
|
|
||||||
"""itunes_stop() -> None
|
|
||||||
|
|
||||||
(internal)
|
|
||||||
"""
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def lock_all_input() -> None:
|
def lock_all_input() -> None:
|
||||||
"""lock_all_input() -> None
|
"""lock_all_input() -> None
|
||||||
|
|
||||||
@ -2825,6 +2769,62 @@ def log(message: str,
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def mac_music_app_get_library_source() -> None:
|
||||||
|
"""mac_music_app_get_library_source() -> None
|
||||||
|
|
||||||
|
(internal)
|
||||||
|
"""
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def mac_music_app_get_playlists() -> List[str]:
|
||||||
|
"""mac_music_app_get_playlists() -> List[str]
|
||||||
|
|
||||||
|
(internal)
|
||||||
|
"""
|
||||||
|
return ["blah", "blah2"]
|
||||||
|
|
||||||
|
|
||||||
|
def mac_music_app_get_volume() -> int:
|
||||||
|
"""mac_music_app_get_volume() -> int
|
||||||
|
|
||||||
|
(internal)
|
||||||
|
"""
|
||||||
|
return int()
|
||||||
|
|
||||||
|
|
||||||
|
def mac_music_app_init() -> None:
|
||||||
|
"""mac_music_app_init() -> None
|
||||||
|
|
||||||
|
(internal)
|
||||||
|
"""
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def mac_music_app_play_playlist(playlist: str) -> bool:
|
||||||
|
"""mac_music_app_play_playlist(playlist: str) -> bool
|
||||||
|
|
||||||
|
(internal)
|
||||||
|
"""
|
||||||
|
return bool()
|
||||||
|
|
||||||
|
|
||||||
|
def mac_music_app_set_volume(volume: int) -> None:
|
||||||
|
"""mac_music_app_set_volume(volume: int) -> None
|
||||||
|
|
||||||
|
(internal)
|
||||||
|
"""
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def mac_music_app_stop() -> None:
|
||||||
|
"""mac_music_app_stop() -> None
|
||||||
|
|
||||||
|
(internal)
|
||||||
|
"""
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def mark_config_dirty() -> None:
|
def mark_config_dirty() -> None:
|
||||||
"""mark_config_dirty() -> None
|
"""mark_config_dirty() -> None
|
||||||
|
|
||||||
|
|||||||
@ -78,7 +78,7 @@ from ba._messages import (OutOfBoundsMessage, DieMessage, StandMessage,
|
|||||||
DroppedMessage, ShouldShatterMessage,
|
DroppedMessage, ShouldShatterMessage,
|
||||||
ImpactDamageMessage, FreezeMessage, ThawMessage,
|
ImpactDamageMessage, FreezeMessage, ThawMessage,
|
||||||
HitMessage)
|
HitMessage)
|
||||||
from ba._music import setmusic, MusicPlayer
|
from ba._music import setmusic, MusicPlayer, MusicType, MusicPlayMode
|
||||||
from ba._powerup import PowerupMessage, PowerupAcceptMessage
|
from ba._powerup import PowerupMessage, PowerupAcceptMessage
|
||||||
from ba._teambasesession import TeamBaseSession
|
from ba._teambasesession import TeamBaseSession
|
||||||
from ba.ui import (OldWindow, UILocation, UILocationWindow, UIController,
|
from ba.ui import (OldWindow, UILocation, UILocationWindow, UIController,
|
||||||
|
|||||||
@ -25,7 +25,8 @@ import time
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
import _ba
|
import _ba
|
||||||
from ba import _activity
|
from ba._activity import Activity
|
||||||
|
from ba._music import setmusic, MusicType
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Any, Dict, Optional
|
from typing import Any, Dict, Optional
|
||||||
@ -33,7 +34,7 @@ if TYPE_CHECKING:
|
|||||||
from ba._lobby import JoinInfo
|
from ba._lobby import JoinInfo
|
||||||
|
|
||||||
|
|
||||||
class EndSessionActivity(_activity.Activity):
|
class EndSessionActivity(Activity):
|
||||||
"""Special ba.Activity to fade out and end the current ba.Session."""
|
"""Special ba.Activity to fade out and end the current ba.Session."""
|
||||||
|
|
||||||
def __init__(self, settings: Dict[str, Any]):
|
def __init__(self, settings: Dict[str, Any]):
|
||||||
@ -61,7 +62,7 @@ class EndSessionActivity(_activity.Activity):
|
|||||||
call_after_ad(Call(_ba.new_host_session, MainMenuSession))
|
call_after_ad(Call(_ba.new_host_session, MainMenuSession))
|
||||||
|
|
||||||
|
|
||||||
class JoiningActivity(_activity.Activity):
|
class JoiningActivity(Activity):
|
||||||
"""Standard activity for waiting for players to join.
|
"""Standard activity for waiting for players to join.
|
||||||
|
|
||||||
It shows tips and other info and waits for all players to check ready.
|
It shows tips and other info and waits for all players to check ready.
|
||||||
@ -88,18 +89,17 @@ class JoiningActivity(_activity.Activity):
|
|||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bastd.actor.tipstext import TipsText
|
from bastd.actor.tipstext import TipsText
|
||||||
from bastd.actor.background import Background
|
from bastd.actor.background import Background
|
||||||
from ba import _music
|
|
||||||
super().on_transition_in()
|
super().on_transition_in()
|
||||||
self._background = Background(fade_time=0.5,
|
self._background = Background(fade_time=0.5,
|
||||||
start_faded=True,
|
start_faded=True,
|
||||||
show_logo=True)
|
show_logo=True)
|
||||||
self._tips_text = TipsText()
|
self._tips_text = TipsText()
|
||||||
_music.setmusic('CharSelect')
|
setmusic(MusicType.CHAR_SELECT)
|
||||||
self._join_info = self.session.lobby.create_join_info()
|
self._join_info = self.session.lobby.create_join_info()
|
||||||
_ba.set_analytics_screen('Joining Screen')
|
_ba.set_analytics_screen('Joining Screen')
|
||||||
|
|
||||||
|
|
||||||
class TransitionActivity(_activity.Activity):
|
class TransitionActivity(Activity):
|
||||||
"""A simple overlay fade out/in.
|
"""A simple overlay fade out/in.
|
||||||
|
|
||||||
Useful as a bare minimum transition between two level based activities.
|
Useful as a bare minimum transition between two level based activities.
|
||||||
@ -132,7 +132,7 @@ class TransitionActivity(_activity.Activity):
|
|||||||
_ba.timer(0.1, self.end)
|
_ba.timer(0.1, self.end)
|
||||||
|
|
||||||
|
|
||||||
class ScoreScreenActivity(_activity.Activity):
|
class ScoreScreenActivity(Activity):
|
||||||
"""A standard score screen that fades in and shows stuff for a while.
|
"""A standard score screen that fades in and shows stuff for a while.
|
||||||
|
|
||||||
After a specified delay, player input is assigned to end the activity.
|
After a specified delay, player input is assigned to end the activity.
|
||||||
@ -151,7 +151,7 @@ class ScoreScreenActivity(_activity.Activity):
|
|||||||
self._tips_text: Optional[ba.Actor] = None
|
self._tips_text: Optional[ba.Actor] = None
|
||||||
self._kicked_off_server_shutdown = False
|
self._kicked_off_server_shutdown = False
|
||||||
self._kicked_off_server_restart = False
|
self._kicked_off_server_restart = False
|
||||||
self._default_music: Optional[str] = 'Scores'
|
self._default_music: Optional[MusicType] = MusicType.SCORES
|
||||||
self._default_show_tips = True
|
self._default_show_tips = True
|
||||||
|
|
||||||
def on_player_join(self, player: ba.Player) -> None:
|
def on_player_join(self, player: ba.Player) -> None:
|
||||||
@ -168,14 +168,13 @@ class ScoreScreenActivity(_activity.Activity):
|
|||||||
def on_transition_in(self) -> None:
|
def on_transition_in(self) -> None:
|
||||||
from bastd.actor.tipstext import TipsText
|
from bastd.actor.tipstext import TipsText
|
||||||
from bastd.actor.background import Background
|
from bastd.actor.background import Background
|
||||||
from ba import _music
|
|
||||||
super().on_transition_in()
|
super().on_transition_in()
|
||||||
self._background = Background(fade_time=0.5,
|
self._background = Background(fade_time=0.5,
|
||||||
start_faded=False,
|
start_faded=False,
|
||||||
show_logo=True)
|
show_logo=True)
|
||||||
if self._default_show_tips:
|
if self._default_show_tips:
|
||||||
self._tips_text = TipsText()
|
self._tips_text = TipsText()
|
||||||
_music.setmusic(self._default_music)
|
setmusic(self._default_music)
|
||||||
|
|
||||||
def on_begin(self, custom_continue_message: ba.Lstr = None) -> None:
|
def on_begin(self, custom_continue_message: ba.Lstr = None) -> None:
|
||||||
# FIXME: Unify args.
|
# FIXME: Unify args.
|
||||||
|
|||||||
@ -259,6 +259,7 @@ class App:
|
|||||||
the single shared instance.
|
the single shared instance.
|
||||||
"""
|
"""
|
||||||
# pylint: disable=too-many-statements
|
# pylint: disable=too-many-statements
|
||||||
|
from ba._music import MusicPlayMode
|
||||||
|
|
||||||
# _test_https()
|
# _test_https()
|
||||||
|
|
||||||
@ -270,26 +271,44 @@ class App:
|
|||||||
# refreshed/etc.
|
# refreshed/etc.
|
||||||
self.fg_state = 0
|
self.fg_state = 0
|
||||||
|
|
||||||
# Environment stuff (pulling these out as attrs so we can type-check
|
# Environment stuff.
|
||||||
# them).
|
# (pulling these into attrs so we can type-check them)
|
||||||
|
|
||||||
env = _ba.env()
|
env = _ba.env()
|
||||||
self._build_number: int = env['build_number']
|
self._build_number: int = env['build_number']
|
||||||
|
assert isinstance(self._build_number, int)
|
||||||
self._config_file_path: str = env['config_file_path']
|
self._config_file_path: str = env['config_file_path']
|
||||||
|
assert isinstance(self._config_file_path, str)
|
||||||
self._locale: str = env['locale']
|
self._locale: str = env['locale']
|
||||||
|
assert isinstance(self._locale, str)
|
||||||
self._user_agent_string: str = env['user_agent_string']
|
self._user_agent_string: str = env['user_agent_string']
|
||||||
|
assert isinstance(self._user_agent_string, str)
|
||||||
self._version: str = env['version']
|
self._version: str = env['version']
|
||||||
|
assert isinstance(self._version, str)
|
||||||
self._debug_build: bool = env['debug_build']
|
self._debug_build: bool = env['debug_build']
|
||||||
|
assert isinstance(self._debug_build, bool)
|
||||||
self._test_build: bool = env['test_build']
|
self._test_build: bool = env['test_build']
|
||||||
|
assert isinstance(self._test_build, bool)
|
||||||
self._user_scripts_directory: str = env['user_scripts_directory']
|
self._user_scripts_directory: str = env['user_scripts_directory']
|
||||||
|
assert isinstance(self._user_scripts_directory, str)
|
||||||
self._system_scripts_directory: str = env['system_scripts_directory']
|
self._system_scripts_directory: str = env['system_scripts_directory']
|
||||||
|
assert isinstance(self._system_scripts_directory, str)
|
||||||
self._platform: str = env['platform']
|
self._platform: str = env['platform']
|
||||||
|
assert isinstance(self._platform, str)
|
||||||
self._subplatform: str = env['subplatform']
|
self._subplatform: str = env['subplatform']
|
||||||
|
assert isinstance(self._subplatform, str)
|
||||||
self._interface_type: str = env['interface_type']
|
self._interface_type: str = env['interface_type']
|
||||||
|
assert isinstance(self._interface_type, str)
|
||||||
self._on_tv: bool = env['on_tv']
|
self._on_tv: bool = env['on_tv']
|
||||||
|
assert isinstance(self._on_tv, bool)
|
||||||
self._vr_mode: bool = env['vr_mode']
|
self._vr_mode: bool = env['vr_mode']
|
||||||
|
assert isinstance(self._vr_mode, bool)
|
||||||
self.protocol_version: int = env['protocol_version']
|
self.protocol_version: int = env['protocol_version']
|
||||||
|
assert isinstance(self.protocol_version, int)
|
||||||
self.toolbar_test: bool = env['toolbar_test']
|
self.toolbar_test: bool = env['toolbar_test']
|
||||||
|
assert isinstance(self.toolbar_test, bool)
|
||||||
self.kiosk_mode: bool = env['kiosk_mode']
|
self.kiosk_mode: bool = env['kiosk_mode']
|
||||||
|
assert isinstance(self.kiosk_mode, bool)
|
||||||
|
|
||||||
# Misc.
|
# Misc.
|
||||||
self.default_language = self._get_default_language()
|
self.default_language = self._get_default_language()
|
||||||
@ -339,12 +358,12 @@ class App:
|
|||||||
|
|
||||||
# Music.
|
# Music.
|
||||||
self.music: Optional[ba.Node] = None
|
self.music: Optional[ba.Node] = None
|
||||||
self.music_mode: str = 'regular'
|
self.music_mode: ba.MusicPlayMode = MusicPlayMode.REGULAR
|
||||||
self.music_player: Optional[ba.MusicPlayer] = None
|
self.music_player: Optional[ba.MusicPlayer] = None
|
||||||
self.music_player_type: Optional[Type[ba.MusicPlayer]] = None
|
self.music_player_type: Optional[Type[ba.MusicPlayer]] = None
|
||||||
self.music_types: Dict[str, Optional[str]] = {
|
self.music_types: Dict[ba.MusicPlayMode, Optional[ba.MusicType]] = {
|
||||||
'regular': None,
|
MusicPlayMode.REGULAR: None,
|
||||||
'test': None
|
MusicPlayMode.TEST: None
|
||||||
}
|
}
|
||||||
|
|
||||||
# Language.
|
# Language.
|
||||||
@ -443,15 +462,16 @@ class App:
|
|||||||
|
|
||||||
cfg = self.config
|
cfg = self.config
|
||||||
|
|
||||||
# Set up our app delegate.
|
|
||||||
self.delegate = appdelegate.AppDelegate()
|
self.delegate = appdelegate.AppDelegate()
|
||||||
|
|
||||||
self.uicontroller = bsui.UIController()
|
self.uicontroller = bsui.UIController()
|
||||||
_achievement.init_achievements()
|
_achievement.init_achievements()
|
||||||
spazappearance.register_appearances()
|
spazappearance.register_appearances()
|
||||||
_campaign.init_campaigns()
|
_campaign.init_campaigns()
|
||||||
if _ba.env()['platform'] == 'android':
|
if _ba.env()['platform'] == 'android':
|
||||||
self.music_player_type = _music.InternalMusicPlayer
|
self.music_player_type = _music.InternalMusicPlayer
|
||||||
elif _ba.env()['platform'] == 'mac' and hasattr(_ba, 'itunes_init'):
|
elif _ba.env()['platform'] == 'mac' and hasattr(
|
||||||
|
_ba, 'mac_music_app_init'):
|
||||||
self.music_player_type = _music.MacITunesMusicPlayer
|
self.music_player_type = _music.MacITunesMusicPlayer
|
||||||
|
|
||||||
# FIXME: This should not be hard-coded.
|
# FIXME: This should not be hard-coded.
|
||||||
@ -550,6 +570,8 @@ class App:
|
|||||||
launch_count = cfg.get('launchCount', 0)
|
launch_count = cfg.get('launchCount', 0)
|
||||||
launch_count += 1
|
launch_count += 1
|
||||||
|
|
||||||
|
# So we know how many times we've run the game at various
|
||||||
|
# version milestones.
|
||||||
for key in ('lc14173', 'lc14292'):
|
for key in ('lc14173', 'lc14292'):
|
||||||
cfg.setdefault(key, launch_count)
|
cfg.setdefault(key, launch_count)
|
||||||
|
|
||||||
@ -615,7 +637,6 @@ class App:
|
|||||||
If there's a foreground host-activity that says it's pausable, tell it
|
If there's a foreground host-activity that says it's pausable, tell it
|
||||||
to pause ..we now no longer pause if there are connected clients.
|
to pause ..we now no longer pause if there are connected clients.
|
||||||
"""
|
"""
|
||||||
# pylint: disable=cyclic-import
|
|
||||||
activity = _ba.get_foreground_host_activity()
|
activity = _ba.get_foreground_host_activity()
|
||||||
if (activity is not None and activity.allow_pausing
|
if (activity is not None and activity.allow_pausing
|
||||||
and not _ba.have_connected_clients()):
|
and not _ba.have_connected_clients()):
|
||||||
|
|||||||
@ -308,7 +308,7 @@ class GameActivity(Activity):
|
|||||||
|
|
||||||
# Music that should play in on_transition_in()
|
# Music that should play in on_transition_in()
|
||||||
# (unless overridden by the map).
|
# (unless overridden by the map).
|
||||||
self._default_music: Optional[str] = None
|
self._default_music: Optional[ba.MusicType] = None
|
||||||
|
|
||||||
# Go ahead and get our map loading.
|
# Go ahead and get our map loading.
|
||||||
map_name: str
|
map_name: str
|
||||||
|
|||||||
@ -196,7 +196,7 @@ class Map(Actor):
|
|||||||
return cls.name
|
return cls.name
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_music_type(cls) -> Optional[str]:
|
def get_music_type(cls) -> Optional[ba.MusicType]:
|
||||||
"""Return a music-type string that should be played on this map.
|
"""Return a music-type string that should be played on this map.
|
||||||
|
|
||||||
If None is returned, default music will be used.
|
If None is returned, default music will be used.
|
||||||
|
|||||||
@ -26,11 +26,44 @@ import os
|
|||||||
import random
|
import random
|
||||||
import threading
|
import threading
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
import _ba
|
import _ba
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Callable, Any, List, Optional, Dict, Union
|
from typing import Callable, Any, List, Optional, Dict, Union, Tuple
|
||||||
|
|
||||||
|
|
||||||
|
class MusicType(Enum):
|
||||||
|
"""Types of music available to play in-game."""
|
||||||
|
MENU = 'Menu'
|
||||||
|
VICTORY = 'Victory'
|
||||||
|
CHAR_SELECT = 'CharSelect'
|
||||||
|
RUN_AWAY = 'RunAway'
|
||||||
|
ONSLAUGHT = 'Onslaught'
|
||||||
|
KEEP_AWAY = 'Keep Away'
|
||||||
|
RACE = 'Race'
|
||||||
|
EPIC_RACE = 'Epic Race'
|
||||||
|
SCORES = 'Scores'
|
||||||
|
GRAND_ROMP = 'GrandRomp'
|
||||||
|
TO_THE_DEATH = 'ToTheDeath'
|
||||||
|
CHOSEN_ONE = 'Chosen One'
|
||||||
|
FORWARD_MARCH = 'ForwardMarch'
|
||||||
|
FLAG_CATCHER = 'FlagCatcher'
|
||||||
|
SURVIVAL = 'Survival'
|
||||||
|
EPIC = 'Epic'
|
||||||
|
SPORTS = 'Sports'
|
||||||
|
HOCKEY = 'Hockey'
|
||||||
|
FOOTBALL = 'Football'
|
||||||
|
FLYING = 'Flying'
|
||||||
|
SCARY = 'Scary'
|
||||||
|
MARCHING = 'Marching'
|
||||||
|
|
||||||
|
|
||||||
|
class MusicPlayMode(Enum):
|
||||||
|
"""Influences behavior when playing music."""
|
||||||
|
REGULAR = 'regular'
|
||||||
|
TEST = 'test'
|
||||||
|
|
||||||
|
|
||||||
class MusicPlayer:
|
class MusicPlayer:
|
||||||
@ -229,12 +262,13 @@ class InternalMusicPlayer(MusicPlayer):
|
|||||||
|
|
||||||
|
|
||||||
# For internal music player.
|
# For internal music player.
|
||||||
|
# FIXME: this only applies to Android currently.
|
||||||
def get_valid_music_file_extensions() -> List[str]:
|
def get_valid_music_file_extensions() -> List[str]:
|
||||||
"""Return file extensions for types playable on this device."""
|
"""Return file extensions for types playable on this device."""
|
||||||
return ['mp3', 'ogg', 'm4a', 'wav', 'flac', 'mid']
|
return ['mp3', 'ogg', 'm4a', 'wav', 'flac', 'mid']
|
||||||
|
|
||||||
|
|
||||||
class ITunesThread(threading.Thread):
|
class MacMusicAppThread(threading.Thread):
|
||||||
"""Thread which wrangles iTunes/Music.app playback"""
|
"""Thread which wrangles iTunes/Music.app playback"""
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
@ -246,16 +280,16 @@ class ITunesThread(threading.Thread):
|
|||||||
self._orig_volume: Optional[int] = None
|
self._orig_volume: Optional[int] = None
|
||||||
|
|
||||||
def run(self) -> None:
|
def run(self) -> None:
|
||||||
"""Run the iTunes/Music.app thread."""
|
"""Run the Music.app thread."""
|
||||||
from ba._general import Call
|
from ba._general import Call
|
||||||
from ba._lang import Lstr
|
from ba._lang import Lstr
|
||||||
from ba._enums import TimeType
|
from ba._enums import TimeType
|
||||||
_ba.set_thread_name("BA_ITunesThread")
|
_ba.set_thread_name("BA_MacMusicAppThread")
|
||||||
_ba.itunes_init()
|
_ba.mac_music_app_init()
|
||||||
|
|
||||||
# It looks like launching iTunes here on 10.7/10.8 knocks us
|
# Let's mention to the user we're launching Music.app in case
|
||||||
# out of fullscreen; ick. That might be a bug, but for now we
|
# it causes any funny business (this used to background the app
|
||||||
# can work around it by reactivating ourself after.
|
# sometimes, though I think that is fixed now)
|
||||||
def do_print() -> None:
|
def do_print() -> None:
|
||||||
_ba.timer(1.0,
|
_ba.timer(1.0,
|
||||||
Call(_ba.screenmessage, Lstr(resource='usingItunesText'),
|
Call(_ba.screenmessage, Lstr(resource='usingItunesText'),
|
||||||
@ -265,12 +299,8 @@ class ITunesThread(threading.Thread):
|
|||||||
_ba.pushcall(do_print, from_other_thread=True)
|
_ba.pushcall(do_print, from_other_thread=True)
|
||||||
|
|
||||||
# Here we grab this to force the actual launch.
|
# Here we grab this to force the actual launch.
|
||||||
# Currently (on 10.8 at least) this is causing a switch
|
_ba.mac_music_app_get_volume()
|
||||||
# away from our fullscreen window. to work around this we
|
_ba.mac_music_app_get_library_source()
|
||||||
# explicitly focus our main window to bring ourself back.
|
|
||||||
_ba.itunes_get_volume()
|
|
||||||
_ba.pushcall(_ba.focus_window, from_other_thread=True)
|
|
||||||
_ba.itunes_get_library_source()
|
|
||||||
done = False
|
done = False
|
||||||
while not done:
|
while not done:
|
||||||
self._commands_available.wait()
|
self._commands_available.wait()
|
||||||
@ -307,8 +337,8 @@ class ITunesThread(threading.Thread):
|
|||||||
if old_volume > 0.0 and volume == 0.0:
|
if old_volume > 0.0 and volume == 0.0:
|
||||||
try:
|
try:
|
||||||
assert self._orig_volume is not None
|
assert self._orig_volume is not None
|
||||||
_ba.itunes_stop()
|
_ba.mac_music_app_stop()
|
||||||
_ba.itunes_set_volume(self._orig_volume)
|
_ba.mac_music_app_set_volume(self._orig_volume)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
print('Error stopping iTunes music:', exc)
|
print('Error stopping iTunes music:', exc)
|
||||||
elif self._volume > 0:
|
elif self._volume > 0:
|
||||||
@ -316,8 +346,8 @@ class ITunesThread(threading.Thread):
|
|||||||
# If volume was zero, store pre-playing volume and start
|
# If volume was zero, store pre-playing volume and start
|
||||||
# playing.
|
# playing.
|
||||||
if old_volume == 0.0:
|
if old_volume == 0.0:
|
||||||
self._orig_volume = _ba.itunes_get_volume()
|
self._orig_volume = _ba.mac_music_app_get_volume()
|
||||||
self._update_itunes_volume()
|
self._update_mac_music_app_volume()
|
||||||
if old_volume == 0.0:
|
if old_volume == 0.0:
|
||||||
self._play_current_playlist()
|
self._play_current_playlist()
|
||||||
|
|
||||||
@ -341,7 +371,7 @@ class ITunesThread(threading.Thread):
|
|||||||
self, target: Callable[[List[str]], None]) -> None:
|
self, target: Callable[[List[str]], None]) -> None:
|
||||||
from ba._general import Call
|
from ba._general import Call
|
||||||
try:
|
try:
|
||||||
playlists = _ba.itunes_get_playlists()
|
playlists = _ba.mac_music_app_get_playlists()
|
||||||
playlists = [
|
playlists = [
|
||||||
p for p in playlists if p not in [
|
p for p in playlists if p not in [
|
||||||
'Music', 'Movies', 'TV Shows', 'Podcasts', 'iTunes\xa0U',
|
'Music', 'Movies', 'TV Shows', 'Podcasts', 'iTunes\xa0U',
|
||||||
@ -360,8 +390,8 @@ class ITunesThread(threading.Thread):
|
|||||||
if self._current_playlist is not None and self._volume > 0:
|
if self._current_playlist is not None and self._volume > 0:
|
||||||
try:
|
try:
|
||||||
assert self._orig_volume is not None
|
assert self._orig_volume is not None
|
||||||
_ba.itunes_stop()
|
_ba.mac_music_app_stop()
|
||||||
_ba.itunes_set_volume(self._orig_volume)
|
_ba.mac_music_app_set_volume(self._orig_volume)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
print('Error stopping iTunes music:', exc)
|
print('Error stopping iTunes music:', exc)
|
||||||
self._current_playlist = None
|
self._current_playlist = None
|
||||||
@ -371,16 +401,16 @@ class ITunesThread(threading.Thread):
|
|||||||
if self._current_playlist is not None and self._volume > 0:
|
if self._current_playlist is not None and self._volume > 0:
|
||||||
try:
|
try:
|
||||||
assert self._orig_volume is not None
|
assert self._orig_volume is not None
|
||||||
_ba.itunes_stop()
|
_ba.mac_music_app_stop()
|
||||||
_ba.itunes_set_volume(self._orig_volume)
|
_ba.mac_music_app_set_volume(self._orig_volume)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
print('Error stopping iTunes music:', exc)
|
print('Error stopping iTunes music:', exc)
|
||||||
|
|
||||||
# Set our playlist and play it if our volume is up.
|
# Set our playlist and play it if our volume is up.
|
||||||
self._current_playlist = target
|
self._current_playlist = target
|
||||||
if self._volume > 0:
|
if self._volume > 0:
|
||||||
self._orig_volume = (_ba.itunes_get_volume())
|
self._orig_volume = (_ba.mac_music_app_get_volume())
|
||||||
self._update_itunes_volume()
|
self._update_mac_music_app_volume()
|
||||||
self._play_current_playlist()
|
self._play_current_playlist()
|
||||||
|
|
||||||
def _handle_die_command(self) -> None:
|
def _handle_die_command(self) -> None:
|
||||||
@ -390,8 +420,8 @@ class ITunesThread(threading.Thread):
|
|||||||
if self._current_playlist is not None and self._volume > 0:
|
if self._current_playlist is not None and self._volume > 0:
|
||||||
try:
|
try:
|
||||||
assert self._orig_volume is not None
|
assert self._orig_volume is not None
|
||||||
_ba.itunes_stop()
|
_ba.mac_music_app_stop()
|
||||||
_ba.itunes_set_volume(self._orig_volume)
|
_ba.mac_music_app_set_volume(self._orig_volume)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
print('Error stopping iTunes music:', exc)
|
print('Error stopping iTunes music:', exc)
|
||||||
|
|
||||||
@ -400,7 +430,7 @@ class ITunesThread(threading.Thread):
|
|||||||
from ba import _lang
|
from ba import _lang
|
||||||
from ba._general import Call
|
from ba._general import Call
|
||||||
assert self._current_playlist is not None
|
assert self._current_playlist is not None
|
||||||
if _ba.itunes_play_playlist(self._current_playlist):
|
if _ba.mac_music_app_play_playlist(self._current_playlist):
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
_ba.pushcall(Call(
|
_ba.pushcall(Call(
|
||||||
@ -413,8 +443,9 @@ class ITunesThread(threading.Thread):
|
|||||||
_error.print_exception(
|
_error.print_exception(
|
||||||
f"error playing playlist {self._current_playlist}")
|
f"error playing playlist {self._current_playlist}")
|
||||||
|
|
||||||
def _update_itunes_volume(self) -> None:
|
def _update_mac_music_app_volume(self) -> None:
|
||||||
_ba.itunes_set_volume(max(0, min(100, int(100.0 * self._volume))))
|
_ba.mac_music_app_set_volume(
|
||||||
|
max(0, min(100, int(100.0 * self._volume))))
|
||||||
|
|
||||||
|
|
||||||
class MacITunesMusicPlayer(MusicPlayer):
|
class MacITunesMusicPlayer(MusicPlayer):
|
||||||
@ -425,7 +456,7 @@ class MacITunesMusicPlayer(MusicPlayer):
|
|||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self._thread = ITunesThread()
|
self._thread = MacMusicAppThread()
|
||||||
self._thread.start()
|
self._thread.start()
|
||||||
|
|
||||||
def on_select_entry(self, callback: Callable[[Any], None],
|
def on_select_entry(self, callback: Callable[[Any], None],
|
||||||
@ -479,7 +510,8 @@ def music_volume_changed(val: float) -> None:
|
|||||||
app.music_player.set_volume(val)
|
app.music_player.set_volume(val)
|
||||||
|
|
||||||
|
|
||||||
def set_music_play_mode(mode: str, force_restart: bool = False) -> None:
|
def set_music_play_mode(mode: MusicPlayMode,
|
||||||
|
force_restart: bool = False) -> None:
|
||||||
"""Sets music play mode; used for soundtrack testing/etc."""
|
"""Sets music play mode; used for soundtrack testing/etc."""
|
||||||
app = _ba.app
|
app = _ba.app
|
||||||
old_mode = app.music_mode
|
old_mode = app.music_mode
|
||||||
@ -490,8 +522,9 @@ def set_music_play_mode(mode: str, force_restart: bool = False) -> None:
|
|||||||
# actually play anything until its requested.
|
# actually play anything until its requested.
|
||||||
# If we're switching *out* of test mode though
|
# If we're switching *out* of test mode though
|
||||||
# we want to go back to whatever the normal song was.
|
# we want to go back to whatever the normal song was.
|
||||||
if mode == 'regular':
|
if mode is MusicPlayMode.REGULAR:
|
||||||
do_play_music(app.music_types['regular'])
|
mtype = app.music_types[MusicPlayMode.REGULAR]
|
||||||
|
do_play_music(None if mtype is None else mtype.value)
|
||||||
|
|
||||||
|
|
||||||
def supports_soundtrack_entry_type(entry_type: str) -> bool:
|
def supports_soundtrack_entry_type(entry_type: str) -> bool:
|
||||||
@ -556,17 +589,11 @@ def get_soundtrack_entry_name(entry: Any) -> str:
|
|||||||
return 'default'
|
return 'default'
|
||||||
|
|
||||||
|
|
||||||
def setmusic(musictype: Optional[str], continuous: bool = False) -> None:
|
def setmusic(musictype: Optional[MusicType], continuous: bool = False) -> None:
|
||||||
"""Set or stop the current music based on a string musictype.
|
"""Set or stop the current music based on a string musictype.
|
||||||
|
|
||||||
category: Gameplay Functions
|
category: Gameplay Functions
|
||||||
|
|
||||||
Current valid values for 'musictype': 'Menu', 'Victory', 'CharSelect',
|
|
||||||
'RunAway', 'Onslaught', 'Keep Away', 'Race', 'Epic Race', 'Scores',
|
|
||||||
'GrandRomp', 'ToTheDeath', 'Chosen One', 'ForwardMarch', 'FlagCatcher',
|
|
||||||
'Survival', 'Epic', 'Sports', 'Hockey', 'Football', 'Flying', 'Scary',
|
|
||||||
'Marching'.
|
|
||||||
|
|
||||||
This function will handle loading and playing sound media as necessary,
|
This function will handle loading and playing sound media as necessary,
|
||||||
and also supports custom user soundtracks on specific platforms so the
|
and also supports custom user soundtracks on specific platforms so the
|
||||||
user can override particular game music with their own.
|
user can override particular game music with their own.
|
||||||
@ -585,7 +612,7 @@ def setmusic(musictype: Optional[str], continuous: bool = False) -> None:
|
|||||||
# not an actual sound node create.
|
# not an actual sound node create.
|
||||||
gnode = _gameutils.sharedobj('globals')
|
gnode = _gameutils.sharedobj('globals')
|
||||||
gnode.music_continuous = continuous
|
gnode.music_continuous = continuous
|
||||||
gnode.music = '' if musictype is None else musictype
|
gnode.music = '' if musictype is None else musictype.value
|
||||||
gnode.music_count += 1
|
gnode.music_count += 1
|
||||||
|
|
||||||
|
|
||||||
@ -595,27 +622,33 @@ def handle_app_resume() -> None:
|
|||||||
do_play_music(None)
|
do_play_music(None)
|
||||||
|
|
||||||
|
|
||||||
def do_play_music(musictype: Optional[str],
|
def do_play_music(musictype: Union[MusicType, str, None],
|
||||||
continuous: bool = False,
|
continuous: bool = False,
|
||||||
mode: str = 'regular',
|
mode: MusicPlayMode = MusicPlayMode.REGULAR,
|
||||||
testsoundtrack: Dict = None) -> None:
|
testsoundtrack: Dict[str, Any] = None) -> None:
|
||||||
"""Plays the requested music type/mode.
|
"""Plays the requested music type/mode.
|
||||||
|
|
||||||
For most cases setmusic() is the proper call to use, which itself calls
|
For most cases setmusic() is the proper call to use, which itself calls
|
||||||
this. Certain cases, however, such as soundtrack testing, may require
|
this. Certain cases, however, such as soundtrack testing, may require
|
||||||
calling this directly.
|
calling this directly.
|
||||||
"""
|
"""
|
||||||
# pylint: disable=too-many-branches
|
|
||||||
# pylint: disable=too-many-statements
|
# We can be passed a MusicType or the string value of one.
|
||||||
|
if musictype is not None:
|
||||||
|
try:
|
||||||
|
musictype = MusicType(musictype)
|
||||||
|
except ValueError:
|
||||||
|
print(f"Invalid music type: '{musictype}'")
|
||||||
|
musictype = None
|
||||||
|
|
||||||
app = _ba.app
|
app = _ba.app
|
||||||
with _ba.Context('ui'):
|
with _ba.Context('ui'):
|
||||||
|
|
||||||
# If they don't want to restart music and we're already
|
# If they don't want to restart music and we're already
|
||||||
# playing what's requested, we're done.
|
# playing what's requested, we're done.
|
||||||
if continuous and app.music_types[mode] == musictype:
|
if continuous and app.music_types[mode] is musictype:
|
||||||
return
|
return
|
||||||
app.music_types[mode] = musictype
|
app.music_types[mode] = musictype
|
||||||
cfg = app.config
|
|
||||||
|
|
||||||
# If the OS tells us there's currently music playing,
|
# If the OS tells us there's currently music playing,
|
||||||
# all our operations default to playing nothing.
|
# all our operations default to playing nothing.
|
||||||
@ -632,127 +665,104 @@ def do_play_music(musictype: Optional[str],
|
|||||||
# entry for this music-type, and if we have one, have the music-player
|
# entry for this music-type, and if we have one, have the music-player
|
||||||
# play it. If not, we'll play game music ourself.
|
# play it. If not, we'll play game music ourself.
|
||||||
if musictype is not None and app.music_player_type is not None:
|
if musictype is not None and app.music_player_type is not None:
|
||||||
try:
|
if testsoundtrack is not None:
|
||||||
soundtrack: Dict
|
soundtrack = testsoundtrack
|
||||||
if testsoundtrack is not None:
|
else:
|
||||||
soundtrack = testsoundtrack
|
soundtrack = _get_user_soundtrack()
|
||||||
else:
|
entry = soundtrack.get(musictype.value)
|
||||||
soundtrack = cfg['Soundtracks'][cfg['Soundtrack']]
|
|
||||||
entry = soundtrack[musictype]
|
|
||||||
except Exception:
|
|
||||||
entry = None
|
|
||||||
else:
|
else:
|
||||||
entry = None
|
entry = None
|
||||||
|
|
||||||
# Go through music-player.
|
# Go through music-player.
|
||||||
if entry is not None:
|
if entry is not None:
|
||||||
|
_play_music_player_music(entry)
|
||||||
# Stop any existing internal music.
|
|
||||||
if app.music is not None:
|
|
||||||
app.music.delete()
|
|
||||||
app.music = None
|
|
||||||
|
|
||||||
# Play music-player music.
|
|
||||||
get_music_player().play(entry)
|
|
||||||
|
|
||||||
# Handle via internal music.
|
# Handle via internal music.
|
||||||
else:
|
else:
|
||||||
if musictype is not None:
|
_play_internal_music(musictype)
|
||||||
loop = True
|
|
||||||
if musictype == 'Menu':
|
|
||||||
filename = 'menuMusic'
|
|
||||||
volume = 5.0
|
|
||||||
elif musictype == 'Victory':
|
|
||||||
filename = 'victoryMusic'
|
|
||||||
volume = 6.0
|
|
||||||
loop = False
|
|
||||||
elif musictype == 'CharSelect':
|
|
||||||
filename = 'charSelectMusic'
|
|
||||||
volume = 2.0
|
|
||||||
elif musictype == 'RunAway':
|
|
||||||
filename = 'runAwayMusic'
|
|
||||||
volume = 6.0
|
|
||||||
elif musictype == 'Onslaught':
|
|
||||||
filename = 'runAwayMusic'
|
|
||||||
volume = 6.0
|
|
||||||
elif musictype == 'Keep Away':
|
|
||||||
filename = 'runAwayMusic'
|
|
||||||
volume = 6.0
|
|
||||||
elif musictype == 'Race':
|
|
||||||
filename = 'runAwayMusic'
|
|
||||||
volume = 6.0
|
|
||||||
elif musictype == 'Epic Race':
|
|
||||||
filename = 'slowEpicMusic'
|
|
||||||
volume = 6.0
|
|
||||||
elif musictype == 'Scores':
|
|
||||||
filename = 'scoresEpicMusic'
|
|
||||||
volume = 3.0
|
|
||||||
loop = False
|
|
||||||
elif musictype == 'GrandRomp':
|
|
||||||
filename = 'grandRompMusic'
|
|
||||||
volume = 6.0
|
|
||||||
elif musictype == 'ToTheDeath':
|
|
||||||
filename = 'toTheDeathMusic'
|
|
||||||
volume = 6.0
|
|
||||||
elif musictype == 'Chosen One':
|
|
||||||
filename = 'survivalMusic'
|
|
||||||
volume = 4.0
|
|
||||||
elif musictype == 'ForwardMarch':
|
|
||||||
filename = 'forwardMarchMusic'
|
|
||||||
volume = 4.0
|
|
||||||
elif musictype == 'FlagCatcher':
|
|
||||||
filename = 'flagCatcherMusic'
|
|
||||||
volume = 6.0
|
|
||||||
elif musictype == 'Survival':
|
|
||||||
filename = 'survivalMusic'
|
|
||||||
volume = 4.0
|
|
||||||
elif musictype == 'Epic':
|
|
||||||
filename = 'slowEpicMusic'
|
|
||||||
volume = 6.0
|
|
||||||
elif musictype == 'Sports':
|
|
||||||
filename = 'sportsMusic'
|
|
||||||
volume = 4.0
|
|
||||||
elif musictype == 'Hockey':
|
|
||||||
filename = 'sportsMusic'
|
|
||||||
volume = 4.0
|
|
||||||
elif musictype == 'Football':
|
|
||||||
filename = 'sportsMusic'
|
|
||||||
volume = 4.0
|
|
||||||
elif musictype == 'Flying':
|
|
||||||
filename = 'flyingMusic'
|
|
||||||
volume = 4.0
|
|
||||||
elif musictype == 'Scary':
|
|
||||||
filename = 'scaryMusic'
|
|
||||||
volume = 4.0
|
|
||||||
elif musictype == 'Marching':
|
|
||||||
filename = 'whenJohnnyComesMarchingHomeMusic'
|
|
||||||
volume = 4.0
|
|
||||||
else:
|
|
||||||
print("Unknown music: '" + musictype + "'")
|
|
||||||
filename = 'flagCatcherMusic'
|
|
||||||
volume = 6.0
|
|
||||||
|
|
||||||
# Stop any existing music-player playback.
|
|
||||||
if app.music_player is not None:
|
|
||||||
app.music_player.stop()
|
|
||||||
|
|
||||||
# Stop any existing internal music.
|
def _get_user_soundtrack() -> Dict[str, Any]:
|
||||||
if app.music:
|
"""Return current user soundtrack or empty dict otherwise."""
|
||||||
app.music.delete()
|
cfg = _ba.app.config
|
||||||
app.music = None
|
soundtrack: Dict[str, Any] = {}
|
||||||
|
soundtrackname = cfg.get('Soundtrack')
|
||||||
|
if soundtrackname is not None:
|
||||||
|
try:
|
||||||
|
soundtrack = cfg['Soundtracks'][soundtrackname]
|
||||||
|
except Exception as exc:
|
||||||
|
print(f"Error looking up user soundtrack: {exc}")
|
||||||
|
soundtrack = {}
|
||||||
|
return soundtrack
|
||||||
|
|
||||||
# Start up new internal music.
|
|
||||||
if musictype is not None:
|
|
||||||
|
|
||||||
# FIXME: Currently this won't start playing if we're paused
|
def _play_music_player_music(entry: Any) -> None:
|
||||||
# since attr values don't get updated until
|
app = _ba.app
|
||||||
# node updates happen. :-(
|
|
||||||
# Update: hmm I don't think that's true anymore. Should check.
|
# Stop any existing internal music.
|
||||||
app.music = _ba.newnode(type='sound',
|
if app.music is not None:
|
||||||
attrs={
|
app.music.delete()
|
||||||
'sound': _ba.getsound(filename),
|
app.music = None
|
||||||
'positional': False,
|
|
||||||
'music': True,
|
# Do the thing.
|
||||||
'volume': volume,
|
get_music_player().play(entry)
|
||||||
'loop': loop
|
|
||||||
})
|
|
||||||
|
def _play_internal_music(musictype: Optional[MusicType]) -> None:
|
||||||
|
app = _ba.app
|
||||||
|
|
||||||
|
# Stop any existing music-player playback.
|
||||||
|
if app.music_player is not None:
|
||||||
|
app.music_player.stop()
|
||||||
|
|
||||||
|
# Stop any existing internal music.
|
||||||
|
if app.music:
|
||||||
|
app.music.delete()
|
||||||
|
app.music = None
|
||||||
|
|
||||||
|
# Start up new internal music.
|
||||||
|
if musictype is not None:
|
||||||
|
|
||||||
|
# Filenames/volume/loop for our built-in music.
|
||||||
|
musicinfos: Dict[MusicType, Tuple[str, float, bool]] = {
|
||||||
|
MusicType.MENU: ('menuMusic', 5.0, True),
|
||||||
|
MusicType.VICTORY: ('victoryMusic', 6.0, False),
|
||||||
|
MusicType.CHAR_SELECT: ('charSelectMusic', 2.0, True),
|
||||||
|
MusicType.RUN_AWAY: ('runAwayMusic', 6.0, True),
|
||||||
|
MusicType.ONSLAUGHT: ('runAwayMusic', 6.0, True),
|
||||||
|
MusicType.KEEP_AWAY: ('runAwayMusic', 6.0, True),
|
||||||
|
MusicType.RACE: ('runAwayMusic', 6.0, True),
|
||||||
|
MusicType.EPIC_RACE: ('slowEpicMusic', 6.0, True),
|
||||||
|
MusicType.SCORES: ('scoresEpicMusic', 3.0, False),
|
||||||
|
MusicType.GRAND_ROMP: ('grandRompMusic', 6.0, True),
|
||||||
|
MusicType.TO_THE_DEATH: ('toTheDeathMusic', 6.0, True),
|
||||||
|
MusicType.CHOSEN_ONE: ('survivalMusic', 4.0, True),
|
||||||
|
MusicType.FORWARD_MARCH: ('forwardMarchMusic', 4.0, True),
|
||||||
|
MusicType.FLAG_CATCHER: ('flagCatcherMusic', 6.0, True),
|
||||||
|
MusicType.SURVIVAL: ('survivalMusic', 4.0, True),
|
||||||
|
MusicType.EPIC: ('slowEpicMusic', 6.0, True),
|
||||||
|
MusicType.SPORTS: ('sportsMusic', 4.0, True),
|
||||||
|
MusicType.HOCKEY: ('sportsMusic', 4.0, True),
|
||||||
|
MusicType.FOOTBALL: ('sportsMusic', 4.0, True),
|
||||||
|
MusicType.FLYING: ('flyingMusic', 4.0, True),
|
||||||
|
MusicType.SCARY: ('scaryMusic', 4.0, True),
|
||||||
|
MusicType.MARCHING:
|
||||||
|
('whenJohnnyComesMarchingHomeMusic', 4.0, True),
|
||||||
|
}
|
||||||
|
musicinfo = musicinfos.get(musictype)
|
||||||
|
if musicinfo is None:
|
||||||
|
print(f"Unknown music: '{musictype}'")
|
||||||
|
filename = 'flagCatcherMusic'
|
||||||
|
volume = 6.0
|
||||||
|
loop = True
|
||||||
|
else:
|
||||||
|
filename, volume, loop = musicinfo
|
||||||
|
|
||||||
|
app.music = _ba.newnode(type='sound',
|
||||||
|
attrs={
|
||||||
|
'sound': _ba.getsound(filename),
|
||||||
|
'positional': False,
|
||||||
|
'music': True,
|
||||||
|
'volume': volume,
|
||||||
|
'loop': loop
|
||||||
|
})
|
||||||
|
|||||||
@ -340,7 +340,7 @@ class TeamSeriesVictoryScoreScreenActivity(TeamsScoreScreenActivity):
|
|||||||
|
|
||||||
# Make sure we don't stomp on the next activity's music choice.
|
# Make sure we don't stomp on the next activity's music choice.
|
||||||
if not self.is_transitioning_out():
|
if not self.is_transitioning_out():
|
||||||
ba.setmusic('Victory')
|
ba.setmusic(ba.MusicType.VICTORY)
|
||||||
|
|
||||||
def _show_winner(self, team: ba.Team) -> None:
|
def _show_winner(self, team: ba.Team) -> None:
|
||||||
from bastd.actor.image import Image
|
from bastd.actor.image import Image
|
||||||
|
|||||||
@ -94,8 +94,8 @@ class AssaultGame(ba.TeamGameActivity):
|
|||||||
return 'touch ${ARG1} flags', self.settings['Score to Win']
|
return 'touch ${ARG1} flags', self.settings['Score to Win']
|
||||||
|
|
||||||
def on_transition_in(self) -> None:
|
def on_transition_in(self) -> None:
|
||||||
self._default_music = ('Epic' if self.settings['Epic Mode'] else
|
self._default_music = (ba.MusicType.EPIC if self.settings['Epic Mode']
|
||||||
'ForwardMarch')
|
else ba.MusicType.FORWARD_MARCH)
|
||||||
super().on_transition_in()
|
super().on_transition_in()
|
||||||
|
|
||||||
def on_team_join(self, team: ba.Team) -> None:
|
def on_team_join(self, team: ba.Team) -> None:
|
||||||
|
|||||||
@ -135,8 +135,8 @@ class CaptureTheFlagGame(ba.TeamGameActivity):
|
|||||||
return 'return ${ARG1} flags', self.settings['Score to Win']
|
return 'return ${ARG1} flags', self.settings['Score to Win']
|
||||||
|
|
||||||
def on_transition_in(self) -> None:
|
def on_transition_in(self) -> None:
|
||||||
self._default_music = ('Epic' if self.settings['Epic Mode'] else
|
self._default_music = (ba.MusicType.EPIC if self.settings['Epic Mode']
|
||||||
'FlagCatcher')
|
else ba.MusicType.FLAG_CATCHER)
|
||||||
super().on_transition_in()
|
super().on_transition_in()
|
||||||
|
|
||||||
def on_team_join(self, team: ba.Team) -> None:
|
def on_team_join(self, team: ba.Team) -> None:
|
||||||
|
|||||||
@ -118,8 +118,8 @@ class ChosenOneGame(ba.TeamGameActivity):
|
|||||||
return 'There can be only one.'
|
return 'There can be only one.'
|
||||||
|
|
||||||
def on_transition_in(self) -> None:
|
def on_transition_in(self) -> None:
|
||||||
self._default_music = ('Epic'
|
self._default_music = (ba.MusicType.EPIC if self.settings['Epic Mode']
|
||||||
if self.settings['Epic Mode'] else 'Chosen One')
|
else ba.MusicType.CHOSEN_ONE)
|
||||||
super().on_transition_in()
|
super().on_transition_in()
|
||||||
|
|
||||||
def on_team_join(self, team: ba.Team) -> None:
|
def on_team_join(self, team: ba.Team) -> None:
|
||||||
|
|||||||
@ -123,8 +123,8 @@ class ConquestGame(ba.TeamGameActivity):
|
|||||||
return 'secure all ${ARG1} flags', len(self.map.flag_points)
|
return 'secure all ${ARG1} flags', len(self.map.flag_points)
|
||||||
|
|
||||||
def on_transition_in(self) -> None:
|
def on_transition_in(self) -> None:
|
||||||
self._default_music = ('Epic'
|
self._default_music = (ba.MusicType.EPIC if self.settings['Epic Mode']
|
||||||
if self.settings['Epic Mode'] else 'GrandRomp')
|
else ba.MusicType.GRAND_ROMP)
|
||||||
super().on_transition_in()
|
super().on_transition_in()
|
||||||
|
|
||||||
def on_team_join(self, team: ba.Team) -> None:
|
def on_team_join(self, team: ba.Team) -> None:
|
||||||
|
|||||||
@ -115,8 +115,8 @@ class DeathMatchGame(ba.TeamGameActivity):
|
|||||||
return 'kill ${ARG1} enemies', self._score_to_win
|
return 'kill ${ARG1} enemies', self._score_to_win
|
||||||
|
|
||||||
def on_transition_in(self) -> None:
|
def on_transition_in(self) -> None:
|
||||||
self._default_music = ('Epic'
|
self._default_music = (ba.MusicType.EPIC if self.settings['Epic Mode']
|
||||||
if self.settings['Epic Mode'] else 'ToTheDeath')
|
else ba.MusicType.TO_THE_DEATH)
|
||||||
super().on_transition_in()
|
super().on_transition_in()
|
||||||
|
|
||||||
def on_team_join(self, team: ba.Team) -> None:
|
def on_team_join(self, team: ba.Team) -> None:
|
||||||
|
|||||||
@ -97,7 +97,7 @@ class EasterEggHuntGame(ba.TeamGameActivity):
|
|||||||
# ..we can go ahead and set our music and whatnot.
|
# ..we can go ahead and set our music and whatnot.
|
||||||
|
|
||||||
def on_transition_in(self) -> None:
|
def on_transition_in(self) -> None:
|
||||||
self._default_music = 'ForwardMarch'
|
self._default_music = ba.MusicType.FORWARD_MARCH
|
||||||
super().on_transition_in()
|
super().on_transition_in()
|
||||||
|
|
||||||
def on_team_join(self, team: ba.Team) -> None:
|
def on_team_join(self, team: ba.Team) -> None:
|
||||||
|
|||||||
@ -244,8 +244,8 @@ class EliminationGame(ba.TeamGameActivity):
|
|||||||
self.session, ba.TeamsSession) else 'last one standing wins'
|
self.session, ba.TeamsSession) else 'last one standing wins'
|
||||||
|
|
||||||
def on_transition_in(self) -> None:
|
def on_transition_in(self) -> None:
|
||||||
self._default_music = ('Epic'
|
self._default_music = (ba.MusicType.EPIC if self.settings['Epic Mode']
|
||||||
if self.settings['Epic Mode'] else 'Survival')
|
else ba.MusicType.SURVIVAL)
|
||||||
super().on_transition_in()
|
super().on_transition_in()
|
||||||
self._start_time = ba.time()
|
self._start_time = ba.time()
|
||||||
|
|
||||||
|
|||||||
@ -146,7 +146,7 @@ class FootballTeamGame(ba.TeamGameActivity):
|
|||||||
return 'score a touchdown'
|
return 'score a touchdown'
|
||||||
|
|
||||||
def on_transition_in(self) -> None:
|
def on_transition_in(self) -> None:
|
||||||
self._default_music = 'Football'
|
self._default_music = ba.MusicType.FOOTBALL
|
||||||
super().on_transition_in()
|
super().on_transition_in()
|
||||||
|
|
||||||
def on_begin(self) -> None:
|
def on_begin(self) -> None:
|
||||||
@ -397,7 +397,7 @@ class FootballCoopGame(ba.CoopGameActivity):
|
|||||||
self._flag: Optional[FootballFlag] = None
|
self._flag: Optional[FootballFlag] = None
|
||||||
|
|
||||||
def on_transition_in(self) -> None:
|
def on_transition_in(self) -> None:
|
||||||
self._default_music = 'Football'
|
self._default_music = ba.MusicType.FOOTBALL
|
||||||
super().on_transition_in()
|
super().on_transition_in()
|
||||||
self._scoreboard = Scoreboard()
|
self._scoreboard = Scoreboard()
|
||||||
self._flag_spawn_pos = self.map.get_flag_position(None)
|
self._flag_spawn_pos = self.map.get_flag_position(None)
|
||||||
@ -748,7 +748,7 @@ class FootballCoopGame(ba.CoopGameActivity):
|
|||||||
if team is self._bot_team:
|
if team is self._bot_team:
|
||||||
self.continue_or_end_game()
|
self.continue_or_end_game()
|
||||||
else:
|
else:
|
||||||
ba.setmusic('Victory')
|
ba.setmusic(ba.MusicType.VICTORY)
|
||||||
|
|
||||||
# Completion achievements.
|
# Completion achievements.
|
||||||
assert self._bot_team is not None
|
assert self._bot_team is not None
|
||||||
|
|||||||
@ -207,7 +207,7 @@ class HockeyGame(ba.TeamGameActivity):
|
|||||||
return 'score ${ARG1} goals', self.settings['Score to Win']
|
return 'score ${ARG1} goals', self.settings['Score to Win']
|
||||||
|
|
||||||
def on_transition_in(self) -> None:
|
def on_transition_in(self) -> None:
|
||||||
self._default_music = 'Hockey'
|
self._default_music = ba.MusicType.HOCKEY
|
||||||
super().on_transition_in()
|
super().on_transition_in()
|
||||||
|
|
||||||
def on_begin(self) -> None:
|
def on_begin(self) -> None:
|
||||||
|
|||||||
@ -124,7 +124,7 @@ class KeepAwayGame(ba.TeamGameActivity):
|
|||||||
self.settings['Hold Time'])
|
self.settings['Hold Time'])
|
||||||
|
|
||||||
def on_transition_in(self) -> None:
|
def on_transition_in(self) -> None:
|
||||||
self._default_music = 'Keep Away'
|
self._default_music = ba.MusicType.KEEP_AWAY
|
||||||
super().on_transition_in()
|
super().on_transition_in()
|
||||||
|
|
||||||
def on_team_join(self, team: ba.Team) -> None:
|
def on_team_join(self, team: ba.Team) -> None:
|
||||||
|
|||||||
@ -133,7 +133,7 @@ class KingOfTheHillGame(ba.TeamGameActivity):
|
|||||||
self.settings['Hold Time'])
|
self.settings['Hold Time'])
|
||||||
|
|
||||||
def on_transition_in(self) -> None:
|
def on_transition_in(self) -> None:
|
||||||
self._default_music = 'Scary'
|
self._default_music = ba.MusicType.SCARY
|
||||||
super().on_transition_in()
|
super().on_transition_in()
|
||||||
|
|
||||||
def on_team_join(self, team: ba.Team) -> None:
|
def on_team_join(self, team: ba.Team) -> None:
|
||||||
|
|||||||
@ -91,8 +91,8 @@ class MeteorShowerGame(ba.TeamGameActivity):
|
|||||||
# Called when our game is transitioning in but not ready to start;
|
# Called when our game is transitioning in but not ready to start;
|
||||||
# ..we can go ahead and set our music and whatnot.
|
# ..we can go ahead and set our music and whatnot.
|
||||||
def on_transition_in(self) -> None:
|
def on_transition_in(self) -> None:
|
||||||
self._default_music = ('Epic'
|
self._default_music = (ba.MusicType.EPIC if self.settings['Epic Mode']
|
||||||
if self.settings['Epic Mode'] else 'Survival')
|
else ba.MusicType.SURVIVAL)
|
||||||
super().on_transition_in()
|
super().on_transition_in()
|
||||||
|
|
||||||
# Called when our game actually starts.
|
# Called when our game actually starts.
|
||||||
|
|||||||
@ -84,7 +84,7 @@ class NinjaFightGame(ba.TeamGameActivity):
|
|||||||
# Called when our game is transitioning in but not ready to begin;
|
# Called when our game is transitioning in but not ready to begin;
|
||||||
# we can go ahead and start creating stuff, playing music, etc.
|
# we can go ahead and start creating stuff, playing music, etc.
|
||||||
def on_transition_in(self) -> None:
|
def on_transition_in(self) -> None:
|
||||||
self._default_music = 'ToTheDeath'
|
self._default_music = ba.MusicType.TO_THE_DEATH
|
||||||
super().on_transition_in()
|
super().on_transition_in()
|
||||||
|
|
||||||
# Called when our game actually begins.
|
# Called when our game actually begins.
|
||||||
|
|||||||
@ -180,7 +180,7 @@ class OnslaughtGame(ba.CoopGameActivity):
|
|||||||
'color': (0.3, 0.8, 0.3, 1.0),
|
'color': (0.3, 0.8, 0.3, 1.0),
|
||||||
'text': ''
|
'text': ''
|
||||||
}))
|
}))
|
||||||
ba.setmusic('Onslaught')
|
ba.setmusic(ba.MusicType.ONSLAUGHT)
|
||||||
|
|
||||||
self._scoreboard = Scoreboard(label=ba.Lstr(resource='scoreText'),
|
self._scoreboard = Scoreboard(label=ba.Lstr(resource='scoreText'),
|
||||||
score_split=0.5)
|
score_split=0.5)
|
||||||
@ -769,7 +769,7 @@ class OnslaughtGame(ba.CoopGameActivity):
|
|||||||
base_delay += 0.85
|
base_delay += 0.85
|
||||||
ba.playsound(self._winsound)
|
ba.playsound(self._winsound)
|
||||||
ba.cameraflash()
|
ba.cameraflash()
|
||||||
ba.setmusic('Victory')
|
ba.setmusic(ba.MusicType.VICTORY)
|
||||||
self._game_over = True
|
self._game_over = True
|
||||||
|
|
||||||
# Can't just pass delay to do_end because our extra bonuses
|
# Can't just pass delay to do_end because our extra bonuses
|
||||||
|
|||||||
@ -172,8 +172,9 @@ class RaceGame(ba.TeamGameActivity):
|
|||||||
return 'run 1 lap'
|
return 'run 1 lap'
|
||||||
|
|
||||||
def on_transition_in(self) -> None:
|
def on_transition_in(self) -> None:
|
||||||
self._default_music = ('Epic Race'
|
self._default_music = (ba.MusicType.EPIC_RACE
|
||||||
if self.settings['Epic Mode'] else 'Race')
|
if self.settings['Epic Mode'] else
|
||||||
|
ba.MusicType.RACE)
|
||||||
super().on_transition_in()
|
super().on_transition_in()
|
||||||
|
|
||||||
pts = self.map.get_def_points('race_point')
|
pts = self.map.get_def_points('race_point')
|
||||||
|
|||||||
@ -130,7 +130,7 @@ class RunaroundGame(ba.CoopGameActivity):
|
|||||||
self._wave_update_timer: Optional[ba.Timer] = None
|
self._wave_update_timer: Optional[ba.Timer] = None
|
||||||
|
|
||||||
def on_transition_in(self) -> None:
|
def on_transition_in(self) -> None:
|
||||||
self._default_music = 'Marching'
|
self._default_music = ba.MusicType.MARCHING
|
||||||
super().on_transition_in()
|
super().on_transition_in()
|
||||||
self._scoreboard = Scoreboard(label=ba.Lstr(resource='scoreText'),
|
self._scoreboard = Scoreboard(label=ba.Lstr(resource='scoreText'),
|
||||||
score_split=0.5)
|
score_split=0.5)
|
||||||
@ -630,7 +630,7 @@ class RunaroundGame(ba.CoopGameActivity):
|
|||||||
base_delay += 0.85
|
base_delay += 0.85
|
||||||
ba.playsound(self._winsound)
|
ba.playsound(self._winsound)
|
||||||
ba.cameraflash()
|
ba.cameraflash()
|
||||||
ba.setmusic('Victory')
|
ba.setmusic(ba.MusicType.VICTORY)
|
||||||
self._game_over = True
|
self._game_over = True
|
||||||
ba.timer(base_delay, ba.Call(self.do_end, 'victory'))
|
ba.timer(base_delay, ba.Call(self.do_end, 'victory'))
|
||||||
return
|
return
|
||||||
|
|||||||
@ -81,7 +81,7 @@ class TargetPracticeGame(ba.TeamGameActivity):
|
|||||||
self._countdown: Optional[OnScreenCountdown] = None
|
self._countdown: Optional[OnScreenCountdown] = None
|
||||||
|
|
||||||
def on_transition_in(self) -> None:
|
def on_transition_in(self) -> None:
|
||||||
self._default_music = 'ForwardMarch'
|
self._default_music = ba.MusicType.FORWARD_MARCH
|
||||||
super().on_transition_in()
|
super().on_transition_in()
|
||||||
|
|
||||||
def on_team_join(self, team: ba.Team) -> None:
|
def on_team_join(self, team: ba.Team) -> None:
|
||||||
|
|||||||
@ -98,7 +98,7 @@ class TheLastStandGame(ba.CoopGameActivity):
|
|||||||
|
|
||||||
def on_transition_in(self) -> None:
|
def on_transition_in(self) -> None:
|
||||||
from bastd.actor.scoreboard import Scoreboard
|
from bastd.actor.scoreboard import Scoreboard
|
||||||
self._default_music = 'Epic'
|
self._default_music = ba.MusicType.EPIC
|
||||||
super().on_transition_in()
|
super().on_transition_in()
|
||||||
ba.timer(1.3, ba.Call(ba.playsound, self._new_wave_sound))
|
ba.timer(1.3, ba.Call(ba.playsound, self._new_wave_sound))
|
||||||
self._scoreboard = Scoreboard(label=ba.Lstr(resource='scoreText'),
|
self._scoreboard = Scoreboard(label=ba.Lstr(resource='scoreText'),
|
||||||
|
|||||||
@ -822,7 +822,7 @@ class MainMenuActivity(ba.Activity):
|
|||||||
with ba.Context(self):
|
with ba.Context(self):
|
||||||
_preload1()
|
_preload1()
|
||||||
|
|
||||||
ba.timer(0.5, lambda: ba.setmusic('Menu'))
|
ba.timer(0.5, lambda: ba.setmusic(ba.MusicType.MENU))
|
||||||
|
|
||||||
|
|
||||||
def _preload1() -> None:
|
def _preload1() -> None:
|
||||||
|
|||||||
@ -1216,8 +1216,8 @@ class HappyThoughts(ba.Map):
|
|||||||
return data
|
return data
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_music_type(cls) -> str:
|
def get_music_type(cls) -> ba.MusicType:
|
||||||
return 'Flying'
|
return ba.MusicType.FLYING
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
super().__init__(vr_overlay_offset=(0, -3.7, 2.5))
|
super().__init__(vr_overlay_offset=(0, -3.7, 2.5))
|
||||||
|
|||||||
@ -234,7 +234,7 @@ class TutorialActivity(ba.Activity):
|
|||||||
|
|
||||||
def on_transition_in(self) -> None:
|
def on_transition_in(self) -> None:
|
||||||
super().on_transition_in()
|
super().on_transition_in()
|
||||||
ba.setmusic('CharSelect', continuous=True)
|
ba.setmusic(ba.MusicType.CHAR_SELECT, continuous=True)
|
||||||
self._map = self._map_type()
|
self._map = self._map_type()
|
||||||
|
|
||||||
def on_begin(self) -> None:
|
def on_begin(self) -> None:
|
||||||
|
|||||||
@ -188,7 +188,7 @@ class SoundtrackBrowserWindow(ba.OldWindow):
|
|||||||
ba.widget(edit=btn,
|
ba.widget(edit=btn,
|
||||||
left_widget=_ba.get_special_widget('back_button'))
|
left_widget=_ba.get_special_widget('back_button'))
|
||||||
|
|
||||||
# keep our lock images up to date/etc.
|
# Keep our lock images up to date/etc.
|
||||||
self._update_timer = ba.Timer(1.0,
|
self._update_timer = ba.Timer(1.0,
|
||||||
ba.WeakCall(self._update),
|
ba.WeakCall(self._update),
|
||||||
timetype=ba.TimeType.REAL,
|
timetype=ba.TimeType.REAL,
|
||||||
@ -282,10 +282,10 @@ class SoundtrackBrowserWindow(ba.OldWindow):
|
|||||||
else:
|
else:
|
||||||
sdtk = cfg['Soundtracks'][self._selected_soundtrack]
|
sdtk = cfg['Soundtracks'][self._selected_soundtrack]
|
||||||
|
|
||||||
# find a valid dup name that doesn't exist
|
# Find a valid dup name that doesn't exist.
|
||||||
test_index = 1
|
test_index = 1
|
||||||
copy_text = ba.Lstr(resource='copyOfText').evaluate()
|
copy_text = ba.Lstr(resource='copyOfText').evaluate()
|
||||||
# get just 'Copy' or whatnot
|
# Get just 'Copy' or whatnot.
|
||||||
copy_word = copy_text.replace('${NAME}', '').strip()
|
copy_word = copy_text.replace('${NAME}', '').strip()
|
||||||
base_name = self._get_soundtrack_display_name(
|
base_name = self._get_soundtrack_display_name(
|
||||||
self._selected_soundtrack).evaluate()
|
self._selected_soundtrack).evaluate()
|
||||||
@ -294,7 +294,7 @@ class SoundtrackBrowserWindow(ba.OldWindow):
|
|||||||
assert isinstance(base_name, bytes)
|
assert isinstance(base_name, bytes)
|
||||||
base_name = base_name.decode('utf-8')
|
base_name = base_name.decode('utf-8')
|
||||||
|
|
||||||
# if it looks like a copy, strip digits and spaces off the end
|
# If it looks like a copy, strip digits and spaces off the end.
|
||||||
if copy_word in base_name:
|
if copy_word in base_name:
|
||||||
while base_name[-1].isdigit() or base_name[-1] == ' ':
|
while base_name[-1].isdigit() or base_name[-1] == ' ':
|
||||||
base_name = base_name[:-1]
|
base_name = base_name[:-1]
|
||||||
@ -320,14 +320,14 @@ class SoundtrackBrowserWindow(ba.OldWindow):
|
|||||||
cfg = ba.app.config
|
cfg = ba.app.config
|
||||||
current_soundtrack = cfg.setdefault('Soundtrack', '__default__')
|
current_soundtrack = cfg.setdefault('Soundtrack', '__default__')
|
||||||
|
|
||||||
# if it varies from current, commit and play
|
# If it varies from current, commit and play.
|
||||||
if current_soundtrack != name and self._allow_changing_soundtracks:
|
if current_soundtrack != name and self._allow_changing_soundtracks:
|
||||||
ba.playsound(ba.getsound('gunCocking'))
|
ba.playsound(ba.getsound('gunCocking'))
|
||||||
cfg['Soundtrack'] = self._selected_soundtrack
|
cfg['Soundtrack'] = self._selected_soundtrack
|
||||||
cfg.commit()
|
cfg.commit()
|
||||||
# just play whats already playing.. this'll grab it from the
|
# Just play whats already playing.. this'll grab it from the
|
||||||
# new soundtrack
|
# new soundtrack.
|
||||||
do_play_music(ba.app.music_types['regular'])
|
do_play_music(ba.app.music_types[ba.MusicPlayMode.REGULAR])
|
||||||
|
|
||||||
def _back(self) -> None:
|
def _back(self) -> None:
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
|
|||||||
@ -280,7 +280,7 @@ class SoundtrackEditWindow(ba.OldWindow):
|
|||||||
size=(50, 32),
|
size=(50, 32),
|
||||||
label=ba.Lstr(resource=self._r + '.testText'),
|
label=ba.Lstr(resource=self._r + '.testText'),
|
||||||
text_scale=0.6,
|
text_scale=0.6,
|
||||||
on_activate_call=ba.Call(self._test, song_type),
|
on_activate_call=ba.Call(self._test, ba.MusicType(song_type)),
|
||||||
up_widget=prev_test_button
|
up_widget=prev_test_button
|
||||||
if prev_test_button is not None else self._text_field)
|
if prev_test_button is not None else self._text_field)
|
||||||
if prev_test_button is not None:
|
if prev_test_button is not None:
|
||||||
@ -330,7 +330,7 @@ class SoundtrackEditWindow(ba.OldWindow):
|
|||||||
ba.Call(self._restore_editor, state, song_type), entry,
|
ba.Call(self._restore_editor, state, song_type), entry,
|
||||||
selection_target_name).get_root_widget())
|
selection_target_name).get_root_widget())
|
||||||
|
|
||||||
def _test(self, song_type: str) -> None:
|
def _test(self, song_type: ba.MusicType) -> None:
|
||||||
from ba.internal import set_music_play_mode, do_play_music
|
from ba.internal import set_music_play_mode, do_play_music
|
||||||
|
|
||||||
# Warn if volume is zero.
|
# Warn if volume is zero.
|
||||||
@ -339,8 +339,10 @@ class SoundtrackEditWindow(ba.OldWindow):
|
|||||||
ba.screenmessage(ba.Lstr(resource=self._r +
|
ba.screenmessage(ba.Lstr(resource=self._r +
|
||||||
'.musicVolumeZeroWarning'),
|
'.musicVolumeZeroWarning'),
|
||||||
color=(1, 0.5, 0))
|
color=(1, 0.5, 0))
|
||||||
set_music_play_mode('test')
|
set_music_play_mode(ba.MusicPlayMode.TEST)
|
||||||
do_play_music(song_type, mode='test', testsoundtrack=self._soundtrack)
|
do_play_music(song_type,
|
||||||
|
mode=ba.MusicPlayMode.TEST,
|
||||||
|
testsoundtrack=self._soundtrack)
|
||||||
|
|
||||||
def _get_entry_button_display_name(self,
|
def _get_entry_button_display_name(self,
|
||||||
entry: Any) -> Union[str, ba.Lstr]:
|
entry: Any) -> Union[str, ba.Lstr]:
|
||||||
@ -369,7 +371,7 @@ class SoundtrackEditWindow(ba.OldWindow):
|
|||||||
from ba.internal import set_music_play_mode
|
from ba.internal import set_music_play_mode
|
||||||
from bastd.ui.soundtrack import browser as stb
|
from bastd.ui.soundtrack import browser as stb
|
||||||
# Resets music back to normal.
|
# Resets music back to normal.
|
||||||
set_music_play_mode('regular')
|
set_music_play_mode(ba.MusicPlayMode.REGULAR)
|
||||||
ba.containerwidget(edit=self._root_widget, transition='out_right')
|
ba.containerwidget(edit=self._root_widget, transition='out_right')
|
||||||
ba.app.main_menu_window = (stb.SoundtrackBrowserWindow(
|
ba.app.main_menu_window = (stb.SoundtrackBrowserWindow(
|
||||||
transition='in_left').get_root_widget())
|
transition='in_left').get_root_widget())
|
||||||
@ -411,7 +413,7 @@ class SoundtrackEditWindow(ba.OldWindow):
|
|||||||
ba.containerwidget(edit=self._root_widget, transition='out_right')
|
ba.containerwidget(edit=self._root_widget, transition='out_right')
|
||||||
|
|
||||||
# Resets music back to normal.
|
# Resets music back to normal.
|
||||||
set_music_play_mode('regular', force_restart=True)
|
set_music_play_mode(ba.MusicPlayMode.REGULAR, force_restart=True)
|
||||||
|
|
||||||
ba.app.main_menu_window = (stb.SoundtrackBrowserWindow(
|
ba.app.main_menu_window = (stb.SoundtrackBrowserWindow(
|
||||||
transition='in_left').get_root_widget())
|
transition='in_left').get_root_widget())
|
||||||
|
|||||||
@ -51,11 +51,12 @@ class SoundtrackEntryTypeSelectWindow(ba.OldWindow):
|
|||||||
spacing = 80
|
spacing = 80
|
||||||
|
|
||||||
do_default = True
|
do_default = True
|
||||||
do_itunes_playlist = supports_soundtrack_entry_type('iTunesPlaylist')
|
do_mac_music_app_playlist = supports_soundtrack_entry_type(
|
||||||
|
'iTunesPlaylist')
|
||||||
do_music_file = supports_soundtrack_entry_type('musicFile')
|
do_music_file = supports_soundtrack_entry_type('musicFile')
|
||||||
do_music_folder = supports_soundtrack_entry_type('musicFolder')
|
do_music_folder = supports_soundtrack_entry_type('musicFolder')
|
||||||
|
|
||||||
if do_itunes_playlist:
|
if do_mac_music_app_playlist:
|
||||||
self._height += spacing
|
self._height += spacing
|
||||||
if do_music_file:
|
if do_music_file:
|
||||||
self._height += spacing
|
self._height += spacing
|
||||||
@ -108,13 +109,13 @@ class SoundtrackEntryTypeSelectWindow(ba.OldWindow):
|
|||||||
ba.containerwidget(edit=self._root_widget, selected_child=btn)
|
ba.containerwidget(edit=self._root_widget, selected_child=btn)
|
||||||
v -= spacing
|
v -= spacing
|
||||||
|
|
||||||
if do_itunes_playlist:
|
if do_mac_music_app_playlist:
|
||||||
btn = ba.buttonwidget(
|
btn = ba.buttonwidget(
|
||||||
parent=self._root_widget,
|
parent=self._root_widget,
|
||||||
size=(self._width - 100, 60),
|
size=(self._width - 100, 60),
|
||||||
position=(50, v),
|
position=(50, v),
|
||||||
label=ba.Lstr(resource=self._r + '.useITunesPlaylistText'),
|
label=ba.Lstr(resource=self._r + '.useITunesPlaylistText'),
|
||||||
on_activate_call=self._on_itunes_playlist_press,
|
on_activate_call=self._on_mac_music_app_playlist_press,
|
||||||
icon=None)
|
icon=None)
|
||||||
if current_entry_type == 'iTunesPlaylist':
|
if current_entry_type == 'iTunesPlaylist':
|
||||||
ba.containerwidget(edit=self._root_widget, selected_child=btn)
|
ba.containerwidget(edit=self._root_widget, selected_child=btn)
|
||||||
@ -145,7 +146,7 @@ class SoundtrackEntryTypeSelectWindow(ba.OldWindow):
|
|||||||
ba.containerwidget(edit=self._root_widget, selected_child=btn)
|
ba.containerwidget(edit=self._root_widget, selected_child=btn)
|
||||||
v -= spacing
|
v -= spacing
|
||||||
|
|
||||||
def _on_itunes_playlist_press(self) -> None:
|
def _on_mac_music_app_playlist_press(self) -> None:
|
||||||
from ba.internal import (get_soundtrack_entry_type,
|
from ba.internal import (get_soundtrack_entry_type,
|
||||||
get_soundtrack_entry_name)
|
get_soundtrack_entry_name)
|
||||||
from bastd.ui.soundtrack import itunes
|
from bastd.ui.soundtrack import itunes
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<!-- THIS FILE IS AUTO GENERATED; DO NOT EDIT BY HAND -->
|
<!-- THIS FILE IS AUTO GENERATED; DO NOT EDIT BY HAND -->
|
||||||
<h4><em>last updated on 2020-03-31 for Ballistica version 1.5.0 build 20001</em></h4>
|
<h4><em>last updated on 2020-04-01 for Ballistica version 1.5.0 build 20001</em></h4>
|
||||||
<p>This page documents the Python classes and functions in the 'ba' module,
|
<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>
|
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>
|
<hr>
|
||||||
@ -174,7 +174,7 @@
|
|||||||
<li><a href="#class_ba_WidgetNotFoundError">ba.WidgetNotFoundError</a></li>
|
<li><a href="#class_ba_WidgetNotFoundError">ba.WidgetNotFoundError</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</ul>
|
</ul>
|
||||||
<h4><a name="class_category_Misc">Misc</a></h4>
|
<h4><a name="class_category_Misc_Classes">Misc Classes</a></h4>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#class_ba_Achievement">ba.Achievement</a></li>
|
<li><a href="#class_ba_Achievement">ba.Achievement</a></li>
|
||||||
<li><a href="#class_ba_AppDelegate">ba.AppDelegate</a></li>
|
<li><a href="#class_ba_AppDelegate">ba.AppDelegate</a></li>
|
||||||
@ -184,10 +184,12 @@
|
|||||||
<li><a href="#class_ba_DependencySet">ba.DependencySet</a></li>
|
<li><a href="#class_ba_DependencySet">ba.DependencySet</a></li>
|
||||||
<li><a href="#class_ba_Lobby">ba.Lobby</a></li>
|
<li><a href="#class_ba_Lobby">ba.Lobby</a></li>
|
||||||
<li><a href="#class_ba_MusicPlayer">ba.MusicPlayer</a></li>
|
<li><a href="#class_ba_MusicPlayer">ba.MusicPlayer</a></li>
|
||||||
|
<li><a href="#class_ba_MusicPlayMode">ba.MusicPlayMode</a></li>
|
||||||
|
<li><a href="#class_ba_MusicType">ba.MusicType</a></li>
|
||||||
<li><a href="#class_ba_OldWindow">ba.OldWindow</a></li>
|
<li><a href="#class_ba_OldWindow">ba.OldWindow</a></li>
|
||||||
<li><a href="#class_ba_UIController">ba.UIController</a></li>
|
<li><a href="#class_ba_UIController">ba.UIController</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<h4><a name="function_category_Misc">Misc</a></h4>
|
<h4><a name="function_category_Misc_Functions">Misc Functions</a></h4>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#function_ba_show_damage_count">ba.show_damage_count()</a></li>
|
<li><a href="#function_ba_show_damage_count">ba.show_damage_count()</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
@ -2806,7 +2808,7 @@ as far from these players as possible.</p>
|
|||||||
</dd>
|
</dd>
|
||||||
<dt><h4><a name="method_ba_Map__get_music_type">get_music_type()</a></dt></h4><dd>
|
<dt><h4><a name="method_ba_Map__get_music_type">get_music_type()</a></dt></h4><dd>
|
||||||
<h5><span><em><class method></span></em></h5>
|
<h5><span><em><class method></span></em></h5>
|
||||||
<p><span>get_music_type() -> Optional[str] </span></p>
|
<p><span>get_music_type() -> Optional[<a href="#class_ba_MusicType">ba.MusicType</a>] </span></p>
|
||||||
|
|
||||||
<p>Return a music-type string that should be played on this map.</p>
|
<p>Return a music-type string that should be played on this map.</p>
|
||||||
|
|
||||||
@ -3146,6 +3148,46 @@ signify that the default soundtrack should be used..</p>
|
|||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
<hr>
|
<hr>
|
||||||
|
<h2><strong><a name="class_ba_MusicPlayMode">ba.MusicPlayMode</a></strong></h3>
|
||||||
|
<p>inherits from: enum.Enum</p>
|
||||||
|
<p>Influences behavior when playing music.</p>
|
||||||
|
|
||||||
|
<h3>Values:</h3>
|
||||||
|
<ul>
|
||||||
|
<li>REGULAR</li>
|
||||||
|
<li>TEST</li>
|
||||||
|
</ul>
|
||||||
|
<hr>
|
||||||
|
<h2><strong><a name="class_ba_MusicType">ba.MusicType</a></strong></h3>
|
||||||
|
<p>inherits from: enum.Enum</p>
|
||||||
|
<p>Types of music available to play in-game.</p>
|
||||||
|
|
||||||
|
<h3>Values:</h3>
|
||||||
|
<ul>
|
||||||
|
<li>MENU</li>
|
||||||
|
<li>VICTORY</li>
|
||||||
|
<li>CHAR_SELECT</li>
|
||||||
|
<li>RUN_AWAY</li>
|
||||||
|
<li>ONSLAUGHT</li>
|
||||||
|
<li>KEEP_AWAY</li>
|
||||||
|
<li>RACE</li>
|
||||||
|
<li>EPIC_RACE</li>
|
||||||
|
<li>SCORES</li>
|
||||||
|
<li>GRAND_ROMP</li>
|
||||||
|
<li>TO_THE_DEATH</li>
|
||||||
|
<li>CHOSEN_ONE</li>
|
||||||
|
<li>FORWARD_MARCH</li>
|
||||||
|
<li>FLAG_CATCHER</li>
|
||||||
|
<li>SURVIVAL</li>
|
||||||
|
<li>EPIC</li>
|
||||||
|
<li>SPORTS</li>
|
||||||
|
<li>HOCKEY</li>
|
||||||
|
<li>FOOTBALL</li>
|
||||||
|
<li>FLYING</li>
|
||||||
|
<li>SCARY</li>
|
||||||
|
<li>MARCHING</li>
|
||||||
|
</ul>
|
||||||
|
<hr>
|
||||||
<h2><strong><a name="class_ba_Node">ba.Node</a></strong></h3>
|
<h2><strong><a name="class_ba_Node">ba.Node</a></strong></h3>
|
||||||
<p><em><top level class></em>
|
<p><em><top level class></em>
|
||||||
</p>
|
</p>
|
||||||
@ -5627,18 +5669,12 @@ are applied to the Widget.</p>
|
|||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
<h2><strong><a name="function_ba_setmusic">ba.setmusic()</a></strong></h3>
|
<h2><strong><a name="function_ba_setmusic">ba.setmusic()</a></strong></h3>
|
||||||
<p><span>setmusic(musictype: Optional[str], continuous: bool = False) -> None</span></p>
|
<p><span>setmusic(musictype: Optional[MusicType], continuous: bool = False) -> None</span></p>
|
||||||
|
|
||||||
<p>Set or stop the current music based on a string musictype.</p>
|
<p>Set or stop the current music based on a string musictype.</p>
|
||||||
|
|
||||||
<p>Category: <a href="#function_category_Gameplay_Functions">Gameplay Functions</a></p>
|
<p>Category: <a href="#function_category_Gameplay_Functions">Gameplay Functions</a></p>
|
||||||
|
|
||||||
<p>Current valid values for 'musictype': 'Menu', 'Victory', 'CharSelect',
|
|
||||||
'RunAway', 'Onslaught', 'Keep Away', 'Race', 'Epic Race', 'Scores',
|
|
||||||
'GrandRomp', 'ToTheDeath', 'Chosen One', 'ForwardMarch', 'FlagCatcher',
|
|
||||||
'Survival', 'Epic', 'Sports', 'Hockey', 'Football', 'Flying', 'Scary',
|
|
||||||
'Marching'.</p>
|
|
||||||
|
|
||||||
<p>This function will handle loading and playing sound media as necessary,
|
<p>This function will handle loading and playing sound media as necessary,
|
||||||
and also supports custom user soundtracks on specific platforms so the
|
and also supports custom user soundtracks on specific platforms so the
|
||||||
user can override particular game music with their own.</p>
|
user can override particular game music with their own.</p>
|
||||||
|
|||||||
@ -105,6 +105,9 @@ class App:
|
|||||||
self._check_sync_states()
|
self._check_sync_states()
|
||||||
|
|
||||||
self._find_sources_and_headers('src/ballistica')
|
self._find_sources_and_headers('src/ballistica')
|
||||||
|
|
||||||
|
# FIXME: It might make more sense to have some of these checks
|
||||||
|
# run via 'make check' rather than here through 'make update'.
|
||||||
self._check_source_files()
|
self._check_source_files()
|
||||||
self._check_headers()
|
self._check_headers()
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user