Repository navigation
Several dialog & subtitle improvements in the way Scenes / Cutscenes work in a party - #854
Conversation
b92c4dc to
46034d1
Compare
|
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. |
5437e9a to
2191f82
Compare
|
Force-pushed to fix log(s) that should have been spdlog::debug for release, and delete some dead debug code no longer needed. |
|
Returning this to draft, I probably have a better algorithm incoming. |
7f42bee to
525c5c5
Compare
|
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. |
525c5c5 to
b45b630
Compare
… quest progression PR tiltedphoques#769, includes tiltedphoques#854) # Conflicts: # Code/client/Games/Misc/SubtitleManager.cpp # Code/client/Games/Skyrim/Actor.cpp # Code/client/Games/Skyrim/Forms/TESQuest.cpp # Code/client/Games/Skyrim/Forms/TESQuest.h # Code/client/Services/Generic/CharacterService.cpp # Code/client/Services/Generic/QuestService.cpp # Code/encoding/Messages/ClientMessageFactory.h # Code/encoding/Messages/ServerMessageFactory.h # Code/server/Services/QuestService.cpp
Scenes, dialogue and subtitle improvements (tiltedphoques#854, rfortier), validated in game by Sergio on 17 September 2026. Conflicts in Actor.cpp, SubtitleManager.cpp and CharacterService.cpp resolved as in fix/810-weapon-state-restore (ea5d875).
… merge follow-up)
…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.
…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.
a8c6472 to
c62f8f5
Compare
Every client plays a quest's scenes itself, so relaying the owner's scene lines made other clients stop their own copy of the line, ending the scene phase early and letting members race ahead or hang. Dialogue and subtitle messages now carry the `GameId` of the scene a line belongs to, and receivers skip lines from a scene they are playing too. Lines from the player dialogue menu, or from a scene that isn't playing on the receiver, still play. Subtitles needed the same skip: only the speaker's own line ending hides a subtitle, so a remote one arriving after that would stay on screen.
c62f8f5 to
7a9b48a
Compare
…oques#854) * Several dialog & subtitle improvements in the way Scenes / Cutscenes 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. * Delete #if 0 code, failed attempt to handle TaskDialogue "goodbye" lines. Getting the failed attempt out of the code, but keeping the commit so you can it was attempted, but there's not enough info. * Skip remote voice lines and subtitles for scenes played locally This is a new approach: every client plays a quest's scenes itself, so relaying the owner's scene lines made other clients stop their own copy of the line, ending the scene phase early and letting members race ahead or hang. Dialogue and subtitle messages now carry the `GameId` of the scene a line belongs to, and receivers skip lines from a scene they are playing too. Lines from the player dialogue menu, or from a scene that isn't playing on the receiver, still play. Subtitles needed the same skip: only the speaker's own line ending hides a subtitle, so a remote one arriving after that would stay on screen. --------- Co-authored-by: Daniil Zakharov <miredirex@gmail.com> (cherry picked from commit ea0f6c3 on tiltedphoques/TiltedEvolution dev) Ported onto 1.8-playtest. Conflict resolution: this branch already had the earlier willSync version of tiltedphoques#854 (b45b630); took the merged upstream approach (always send SceneId, receiver skips lines for a scene it plays locally) for OnDialogueEvent/OnNotifyDialogue/OnSubtitleEvent and BGSSceneAction, kept this branch's logging and BGSScene script helpers. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019Mdy6FmrJTc1m7KuVM1n3H
…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:
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
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.