Repository navigation
Conversation
The vectored exception handler held a non-recursive mutex for every exception, so a second fault while it ran deadlocked the thread and every other thread that faulted after it. It also shut down spdlog even when the exception was later handled, after which any log call crashed. Use an atomic flag instead of the mutex and flush the logs instead of shutting spdlog down. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018fvQxSuYsY5Nn19wykLCiD
absol89
force-pushed
the
claude/project-thread-9f2vwo
branch
from
November 4, 2026 18:28
d148b86 to
c43915c
Compare
When another player's save has an actor enabled and dead but ours has it disabled, the spawn request enabled it and then killed it, which ran its OnDeath scripts again. With quest dragons that replayed quest stages and rewards. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018fvQxSuYsY5Nn19wykLCiD
A party member who hadn't finished a run once quest, like Dragon Rising, sent its start and stages to players who already had. That restarted the quest for them and replayed its rewards, such as the Axe of Whiterun and the Fus shout. Ignore starts and stages for run once quests that are already completed locally, as the game itself would. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018fvQxSuYsY5Nn19wykLCiD
When an owner gives up its actors, the server sends their positions to every player. A player in an interior then loaded those exterior cells and moved the actors there, which crashed a QueuedPromoteLargeReferencesTask with a null cell. It also left quest actors like dead dragons in the wrong place in that player's save. Skip the move when the target worldspace isn't the player's; the actor is placed when it spawns. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018fvQxSuYsY5Nn19wykLCiD
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Requested by Eric · project thread
Summary
Four fixes from the same playtest.
1. Don't teleport remote actors into a worldspace the player isn't in
When an owner gives up an actor, the server sends its position to every player (
NotifyActorTeleport).MoveActorthen callsLoadCellon the receiving client even when that player is somewhere else entirely. The playtest crashed this way: a player inside Embershard Mine received a burst of teleports for Riverwood actors, and 16 ms later aQueuedPromoteLargeReferencesTaskcrashed reading a null pointer atSkyrimSE+294230(test byte ptr [rcx+0x40]) while promoting the Riverwood cell.The same path leaves persistent actors in the wrong place in the receiving player's save. One log shows dead Mirmulnir (
5A6CA) and the Bleak Falls dragon (263CE) being teleported intoWhiterunWorldwhile that player was in Tamriel. That save now churns Mirmulnir's 3D nonstop on the worker threads, even offline.The move is now skipped when the target worldspace isn't the player's. The actor is still placed by its spawn request once it becomes relevant.
2. Don't restart completed run once quests from party updates
A player who had finished Dragon Rising (MQ104,
2610C) received the Axe of Whiterun and the Fus prompt again afterRemote quest started: 2610C, stage: 0. A remoteStartedwent straight toScriptSetStage, which restarts the quest. Starts and stage updates are now ignored for quests flaggedRunOncethat areCompletedlocally. Radiant and repeatable quests aren't run once, so they're unaffected.3. Don't spawn dead actors that are disabled locally
OnCharacterSpawnenabled a locally disabled actor and then calledKill()on it whenever the owner had it dead. That put the Bleak Falls dragon on the road (Disabled actor is being re-enabled: 263CE). Those actors are now skipped. Reconciliation (WaitingForDisable) behaves as before.4. Don't block in the crash handler
This was a guess at the quit hang, and it turned out not to be the cause. It's still a safe change. The vectored exception handler now uses an atomic flag instead of a non-recursive mutex, and it flushes the logs instead of calling
spdlog::shutdown().Still open
InitDeferredForms, waiting for promote tasks to drain, while a worker spins on a lock. The save with the churning Mirmulnir is the likely trigger. Fix 1 should stop new saves getting into that state, but saves that are already affected keep it.Testing
Not run in game yet. All four commits are merged into
API-playtestfor verification.🤖 Generated with Claude Code
https://claude.ai/code/session_018fvQxSuYsY5Nn19wykLCiD