Active effect time imprecision bug

The active effect time imprecision bug, more commonly known as the ability condition bug, is an issue that causes long-lasting magic effects to stop re-processing their conditions after a long enough time has passed. This most often affects ability spells that have been added to the player. Skyrim's handling of magic effect duration suffers from two issues, both related to the effects of floating-point imprecision on an active effect's elapsed time (measured in seconds). Once the elapsed time reaches a high enough value, it cannot be reliably increased, which breaks both the handling of effect durations and the handling of effect conditions.

DetailsEdit

Skyrim re-processes an active effect's conditions at one-second intervals after the effect is applied. (This is not a global interval; it's based on the active effect's elapsed time, which allows each effect to update independently of the others and prevents the game from having to do tons of work on a single frame.) It does so when this calculation is true:

floor(elapsed_time / interval) ≠ floor((elapsed_time + frame_time) / interval)

However, the active effect's elapsed time is stored as a single-precision floating-point number. This means that once it reaches a high enough value, the frame time (the seconds per frame) may be too small for the addition to actually work and change the elapsed time. This prevents conditions from ever being re-processed — an issue that affects all active effects, even if they do not have a duration limit. The same problem can cause the game to fail to advance the elapsed time itself: if a temporary effect has an especially long duration, then the elapsed time may stop being reliably counted before that duration is reached, making the effect endless.

There is a wrinkle: when you fast-travel, sleep, wait, or serve time in prison, the game will simulate the passage of real-time. If your timescale is 20, the default, then 900 seconds of real-world time represents five hours (18000 seconds) of in-game time. If you wait for five hours in-game, then the game performs that conversion in reverse and simulates 900 seconds of real-world time. This affects active effects' elapsed time, and the simulated blocks of time may be large enough to overcome floating-point imprecision when normal frame times would not.

As such, below are the elapsed time values at which time can no longer (reliably) pass for varying frame rates. Once an active effect reaches the listed elapsed time for your frame rate, its elapsed time can no longer be reliably tracked, and its conditions will no longer reliably update.

Elapsed time imprecision thresholds, by frame rate
Frames per second Seconds per frame Threshold (seconds) Threshold (friendly)
120 0.0083 131072 1 day, 12 hr, 24 min, 32 sec
60 0.0160 262144 3 days, 0 hr, 49 min, 4 sec
30 0.0330 524288 6 days, 1 hr, 38 min, 8 sec
25 0.0400 524288 6 days, 1 hr, 38 min, 8 sec
20 0.0500 524288 6 days, 1 hr, 38 min, 8 sec
15 0.0660 1048576 12 days, 3 hr, 16 min, 16 sec

WorkaroundsEdit

  • If you are applying a long-lasting spell or ability to an actor, and you need that spell's effects to re-process conditions indefinitely, then you will need to build a scripted mechanism to remove and re-apply the spell on an interval shorter than the elapsed time imprecision threshold.


Sein schatten (talk) 2021-02-25T09:11:28 (EST)

NotesEdit

  • This bug has been confirmed to exist in both Skyrim Classic and Skyrim Special. The affected subroutines are:
    • void ActiveEffect::DoConditionUpdate(float, bool) located at 0x00655BA0 in Skyrim Classic, responsible for checking the update interval
    • void ActiveEffect::AdvanceTime(float realTimeSeconds) located at 0x00656CB0 in Skyrim Classic, responsible for advancing the elapsed time and calling DoConditionUpdate (by way of virtual method 0x05 on ActiveEffect)