47 return std::unexpected(
"Paddywagon siren variant is outside retail 0..1 range");
75 if (creditsMusicStatus_ == 0)
76 creditsMusicStatus_ = 1;
77 else if (creditsMusicStatus_ == 1 &&
79 creditsMusicStatus_ = 2;
82 loop = creditsMusicStatus_ == 2;
86 creditsMusicStatus_ = 0;
87 if (!gameInProgress || !
musicOn)
90 currentMusic_.reset();
93 const auto safeTune = std::min<std::uint8_t>(
100 if (currentMusic_ && *currentMusic_ !=
desired)
114 bool Runtime::anyTalking(
const audio::Runtime& audio)
const noexcept
118 if (tokenVoiceActive(audio,
token))
return true;
127 watchedTokenVoices_.fill(
false);
128 watchedPennybags_ =
false;
129 pendingTalkingVoice_.reset();
132 void Runtime::watchTalking(
const audio::Runtime& audio)
noexcept
134 if (audio.active(
PennybagsKey)) watchedPennybags_ =
true;
136 if (tokenVoiceActive(audio,
token)) watchedTokenVoices_[
token] =
true;
139 std::expected<void, std::string> Runtime::startTalkingVoice(
140 audio::Runtime& audio,
const PendingTalkingVoice& voice)
145 return std::unexpected(
"token voice token is out of range");
146 return audio.play(
tokenVoiceKey(*voice.token), voice.wave, voice.gain,
false);
148 return audio.play(
PennybagsKey, voice.wave, voice.gain,
false);
151 std::expected<TokenVoicePlayResult, std::string> Runtime::playTalkingVoice(
152 audio::Runtime& audio, PendingTalkingVoice voice,
155 TokenVoicePlayResult result{};
156 const bool talking = anyTalking(audio);
164 if (
talking || pendingTalkingVoice_)
166 result.skipped =
true;
172 if (
talking || pendingTalkingVoice_)
175 pendingTalkingVoice_ = voice;
176 result.queued =
true;
182 const auto started = startTalkingVoice(audio, voice);
183 if (!started)
return std::unexpected(started.error());
184 result.started =
true;
190 if (voice.token) watchedTokenVoices_[*voice.token] =
true;
191 else watchedPennybags_ =
true;
206 result.skipped =
true;
209 return playTalkingVoice(audio, PendingTalkingVoice{
token, *wave, 1.0F}, policy);
220 result.skipped =
true;
223 return playTalkingVoice(audio,
224 PendingTalkingVoice{std::nullopt, *wave,
PennybagsGain}, policy);
233 return playTalkingVoice(audio,
234 PendingTalkingVoice{std::nullopt, wave,
PennybagsGain}, policy);
241 watchedTokenVoices_[
token] =
false;
243 watchedPennybags_ =
false;
245 if (pendingTalkingVoice_ && !anyTalking(audio))
247 const auto pending = *pendingTalkingVoice_;
248 pendingTalkingVoice_.reset();
249 const auto started = startTalkingVoice(audio, pending);
250 if (!started)
return std::unexpected(started.error());
255 const bool watchedToken = std::any_of(watchedTokenVoices_.begin(),
256 watchedTokenVoices_.end(), [](
bool value) { return value; });
262 return !anyTalking(audio) && !pendingTalkingVoice_;
268 watchedTokenVoices_[
token] =
true;
273 if (audio.active(
PennybagsKey)) watchedPennybags_ =
true;
277 if (audio !=
nullptr)
285 currentMusic_.reset();
286 creditsMusicStatus_ = 0;
287 pendingTalkingVoice_.reset();
288 watchedTokenVoices_.fill(
false);
289 watchedPennybags_ =
false;
data::BoardEdition boardEdition() const noexcept
void stop(PlaybackKey key) noexcept
bool active(PlaybackKey key) const noexcept
std::expected< void, std::string > play(PlaybackKey key, data::DataId waveDataId, float gain=1.0F, bool loop=false, std::uint32_t pitchHertz=0U, std::int32_t panPercentage=0)
std::expected< void, std::string > saveFailure(audio::Runtime &audio)
std::expected< void, std::string > click(audio::Runtime &audio)
std::expected< void, std::string > syncCash(audio::Runtime &audio, ibar::ScoreCashChange change)
std::expected< void, std::string > syncMusic(audio::Runtime &audio, bool gameInProgress, bool musicOn, std::uint8_t tuneIndex, bool creditsActive=false)
std::expected< void, std::string > cashDown(audio::Runtime &audio)
void watchTokenVoice(audio::Runtime &audio, std::uint8_t token) noexcept
std::expected< void, std::string > build(audio::Runtime &audio)
void watchPennybags(audio::Runtime &audio) noexcept
bool talkingQueueIdle(const audio::Runtime &audio) const noexcept
std::expected< void, std::string > siren(audio::Runtime &audio, std::uint8_t variant)
std::expected< bool, std::string > syncTokenVoices(audio::Runtime &audio)
std::expected< TokenVoicePlayResult, std::string > pennybagsSpecific(audio::Runtime &audio, bool hostCommentsOn, data::DataId wave, TokenVoiceClipPolicy policy)
std::expected< void, std::string > unbuild(audio::Runtime &audio)
std::expected< TokenVoicePlayResult, std::string > pennybagsVoice(audio::Runtime &audio, bool hostCommentsOn, PennybagsVoice voice, TokenVoiceClipPolicy policy, std::uint32_t randomValue)
void reset(audio::Runtime *audio=nullptr) noexcept
std::expected< TokenVoicePlayResult, std::string > tokenVoice(audio::Runtime &audio, bool voicesOn, std::uint8_t token, TokenVoiceLine line, TokenVoiceClipPolicy policy, std::uint32_t randomValue)
bool tokenVoiceActive(const audio::Runtime &audio, std::uint8_t token) const noexcept
std::expected< void, std::string > cashUp(audio::Runtime &audio)
std::expected< void, std::string > warning(audio::Runtime &audio)
constexpr DataId EmptyDataId
constexpr DataId packDataId(std::uint16_t group, DataTag tag) noexcept
std::optional< data::DataId > choosePennybagsVoice(data::BoardEdition edition, PennybagsVoice voice, std::uint32_t randomValue) noexcept
constexpr data::DataTag SaveFailureTag
constexpr data::DataTag BuildTag
constexpr data::DataTag SirenBaseTag
constexpr std::uint8_t MusicTuneCount
constexpr data::DataTag UnbuildTag
@ ClipOldSoundIfPlayingWithLock
@ WaitForAnyOldSoundThenPlayWithLock
@ WaitForAnyOldSoundThenPlay
constexpr std::uint8_t SirenCount
constexpr data::DataTag CreditsTag
constexpr data::DataTag WarningTag
constexpr data::DataTag MusicBaseTag
constexpr data::DataTag CashUpTag
std::optional< data::DataId > chooseTokenVoice(data::BoardEdition edition, TokenVoiceLine line, std::uint8_t token, std::uint32_t randomValue) noexcept
constexpr std::uint8_t TokenVoiceTokenCount
constexpr data::DataTag CashDownTag
constexpr data::DataTag ClickTag