Skip to content

Several dialog & subtitle improvements in the way Scenes / Cutscenes …#854

Open
rfortier wants to merge 2 commits intotiltedphoques:devfrom
rfortier:fix/Scene-dialog-subtitle-sync
Open

Several dialog & subtitle improvements in the way Scenes / Cutscenes …#854
rfortier wants to merge 2 commits intotiltedphoques:devfrom
rfortier:fix/Scene-dialog-subtitle-sync

Conversation

@rfortier
Copy link
Copy Markdown
Contributor

@rfortier rfortier commented Feb 5, 2026

…work in a party.

Updated PR with a new approach that syncs better. Turned down all the logging for release.

If the cutscene design is that all party members (or all inrange) play the scene, the Leader's dialog sync would step on and cancel the copies running in the party members. This would mess up the scene phase timing, causing the members to race ahead and abort actions of the Leader, potentially hanging the scene. Found with the Finn/Carbos scene in Enderal.

If the cutscene design is only the person(s) who trigger the scene play the scene, and the scene is triggered by a non-Leader, no one except the scene-initiator got any dialog. This is an uncommon case; usually the start of a scene triggers a quest stage change that brings everyone into the scene, or the scene is just random encounter / idle chatter that is just fine to sync to just the triggering player.

Because scenes that don't trigger quest stage changes but also would be desirable to sync are rare, and because there is no good way to distinguish them from scenes where syncing the audio will cause dialog cancels and timing problems, this case is left as unsolved, have to live with it.

There is some logic in the quest sync PR #848 to trigger scenes in the rest of the party when one starts the scene. This solves some cases. In others, there are scene start conditions that just stop the scene again. Best known example is the Companions Brotherhood quest stage C02. Unless the entire party stands on the tiny hotspot where the initiator triggers the scene, it just stops again.

It's not perfect, but the selected (surviving experiment) solution is:

  1. Try to trigger the scene for the entire party, which often works.
  2. Each party member plays the scene to themselves, generally with decent audio sync. The party Leader is still controlling the NPCs and motion / animation sync handles most cases.
  3. If the scene triggers TaskDialogues (those NPC dialogues where you answer with a menu pick), that dialog is individual to the SceneMaster (they who triggered), so that is synced to party (PlayersInRange).
  4. Only flaw known is AI packages.

Subtitle sync follows the same rules as Dialogue sync.

AI package handling is left for a future iteration, since it also is tricky. Current state: AI packages only run on Leader, so if Member triggers a scene, the AI packages doesn't run. If it is anything of consequence (more than "look at player", say, having to do something and then interact with player), the scene will get stuck and Leader will have to take over. If Leader is close, NPC will just switch to Leader. If farther away or not in scene, Leader will have to get closer, possibly having to unlock the Leader with the EPC (EnablePlayerControls) console command.

For the next round, the two big options I see for fixing AI is for

  1. SceneMaster to take ownership of NPCs in-scene. They can be released at end of scene, or just wait for a cell change. This will solve the scene getting stuck problem, but not the dialog sync problem.
  2. Find a way to reactivate AI on "remote" NPCs for the duration of the scene, This sounds more fragile, but since everyone is playing the scene again, dialogue will sync.
  3. Switch model to "everyone listens to SceneMaster." This combines the first option with changing the dialog sync so the scene ONLY plays on the SceneMaster, and diaglog / motion / animation is synced as usual from the NPC owner. This one is fragile because the way Skyrim works the scene is often started on all players, and trying to stop / interrupt it is sure to cause new issues.

Thanks to @miredirex and @powerof3 CommonLibSSE for help with some of the RE:: trickery.

This was extracted from a bigger PR #848 in the works, so draft until we get a bit more mileage using this version.

@rfortier rfortier force-pushed the fix/Scene-dialog-subtitle-sync branch 2 times, most recently from b92c4dc to 46034d1 Compare February 7, 2026 02:00
@rfortier
Copy link
Copy Markdown
Contributor Author

rfortier commented Feb 7, 2026

Updated with improved dialogue and subtitle sync.

In particular, there is an engine bug or something in our hooking / RE that causes HookSpeakSoundFunction() to be invoked twice for most spoken lines, about 5-10ms apart and on separate threads. Looks like it is probably a Bethesda bug.

But it caused us to send DialogueEvent twice, too, trying to sync twice when relevant. Added a non-pretty fix to watch for duplicates within 20ms, and drop the duplicate send of DialogueEvent. That's the only functional change. It still calls RealSpeakSoundFunction both times; didn't want to change that behavior because the engine might actually depend on it.

@rfortier rfortier marked this pull request as ready for review February 7, 2026 02:06
@rfortier rfortier force-pushed the fix/Scene-dialog-subtitle-sync branch 2 times, most recently from 5437e9a to 2191f82 Compare February 7, 2026 15:20
@rfortier
Copy link
Copy Markdown
Contributor Author

rfortier commented Feb 7, 2026

Force-pushed to fix log(s) that should have been spdlog::debug for release, and delete some dead debug code no longer needed.

@rfortier
Copy link
Copy Markdown
Contributor Author

Returning this to draft, I probably have a better algorithm incoming.

@rfortier rfortier marked this pull request as draft February 15, 2026 15:29
@rfortier rfortier force-pushed the fix/Scene-dialog-subtitle-sync branch 2 times, most recently from 7f42bee to 525c5c5 Compare February 17, 2026 21:28
@rfortier
Copy link
Copy Markdown
Contributor Author

Clean this up (again), found a syncing model that works properly more often and supports a way to get "unstuck" when an AI package requires the Leader to take over a scene to unstick the NPCs.

@rfortier rfortier marked this pull request as ready for review February 17, 2026 21:40
…work in a party.

If the cutscene design is that all party members (or all inrange) play the scene, the Leader's dialog actions would step on and cancel the copies running in the party members. This would mess up the scene phase timing, causing the members to race ahead and abort actions of the Leader, potentially hanging the scene. Found with the Finn/Carbos scene in Enderal.

If the cutscene design is only the person(s) who trigger the scene play the scene, and the scene is triggered by a non-Leader, no one except the scene-initiator got any dialog. This is an uncommon case; usually the start of a scene triggers a quest stage change that brings everyone into the scene, or the scene is just random encounter / idle chatter that is just fine to sync to just the triggering player.

Because scenes that don't trigger quest stage changes but also would be desirable to sync are rare, and because there is no good way to distinguish them from scenes where syncing the audio will cause dialog cancels and timing problems, this case is left as unsolved, have to live with it.

There is some logic to trigger scenes in the rest of the party when one starts the scene. This solves some cases. In others, there are scene start conditions that just stop the scene again. Best known example is the Companions Brotherhood quest stage C02. Unless the entire party stands on the tiny hotspot where the initiator triggers the scene, it just stops again.

It's not perfect, but the selected (surviving experiment) solution is:
1) Try to trigger the scene for  the entire party, which often works.
2) Each party member plays the scene to themselves, generally with decent audio sync. The party Leader is still controlling the NPCs and motion / animation sync handles most cases.
3) If the scene triggers TaskDialogues (those NPC dialogues where you answer with a menu pick), that dialog is individual to the SceneMaster (they who triggered), so that is synced to party (PlayersInRange).
4) Only flaw known is AI packages.

Subtitle sync follows the same rules as Dialogue sync.

AI package handling is left for a future iteration, since it also is tricky. Current state: AI packages only run on Leader, so if Member triggers a scene, the AI packages doesn't run. If it is anything of consequence (more than "look at player", say, having to do something and then interact with player), the scene will get stuck and Leader will have to take over. If Leader is close, NPC will just switch to Leader. If farther away or not in scene, Leader will have to get closer, possibly having to unlock the Leader with the EPC (EnablePlayerControls) console command.

For the next round, the two big options I see for fixing AI is for
1. SceneMaster to take ownership of NPCs in-scene. They can be released at end of scene, or just wait for a cell change.
2. Find a way to reactivate AI on "remote" NPCs for the duration of the scene, This sounds more fragile.
@rfortier rfortier force-pushed the fix/Scene-dialog-subtitle-sync branch from 525c5c5 to b45b630 Compare February 20, 2026 20:22
…nes.

Getting the failed attempt out of the code, but keeping the commit so you can it was attempted, but there's not enough info.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant