diff --git a/ArtemisRoleplayingKit/Voice/AddonTalkHandler.cs b/ArtemisRoleplayingKit/Voice/AddonTalkHandler.cs index 7b959e1..d7b11df 100644 --- a/ArtemisRoleplayingKit/Voice/AddonTalkHandler.cs +++ b/ArtemisRoleplayingKit/Voice/AddonTalkHandler.cs @@ -602,7 +602,7 @@ private void Framework_Update(IFramework framework) { if (_currentDialoguePaths.Count > 0) { _currentDialoguePaths[_currentDialoguePaths.ElementAt(_currentDialoguePaths.Count - 1).Key] = true; } - _blockAudioGeneration = false; + ClearConsumedAudioGenerationBlock("talk state handled"); } } else if (stateSnapshot != null) { TraceNpcTtsDebug($"Ignored talk state speaker='{stateSnapshot.Speaker}' textPresent={!string.IsNullOrEmpty(stateSnapshot.Text)} text='{PreviewText(stateSnapshot.Text)}'"); @@ -717,6 +717,18 @@ private async void AutoAdvancePauseOnlyDialogue(string pauseText, long sequence) } } + private void ClearConsumedAudioGenerationBlock(string reason) { + if (!_blockAudioGeneration) { + return; + } + + // Cutscene audio blocks are intended to suppress one matching NPC line. + // Clear the flag once that block has been consumed so it cannot leak into + // later manually advanced dialogue after the voiced scene has ended. + _blockAudioGeneration = false; + TraceNpcTts($"Cleared consumed cutscene audio block reason='{reason}' blockCount={_blockAudioGenerationCount}"); + } + private bool ShouldSkipNpcText(string npcName, string message) { if (!VerifyIsEnglish(message, out var languageRejectionReason)) { Plugin.PluginLog.Information($"[NPC TTS] Skipping text for npc='{npcName}' reason='{languageRejectionReason}' text='{PreviewText(message)}'"); @@ -1411,6 +1423,9 @@ await _plugin.NpcVoiceManager.GetCharacterAudio(stream, value, arcValue, initial }, _plugin.Config.NPCSpeechSpeed, values.Item2 == "Elevenlabs" ? 0.5f : (values.Item2 == "XTTS" ? 1.8f : 1.8f)); } else { TraceNpcTts($"Audio ready but playback suppressed by blockAudioGeneration sequence={request.Sequence} npc='{nameToUse}' text='{PreviewText(value)}'"); + // A cutscene SCD can arrive while a relay request is in flight. + // Once that late response is suppressed, the block has done its job. + ClearConsumedAudioGenerationBlock("npc audio playback suppressed"); } } break;