Closed Decane closed 1 year ago
Are all references to time_global()
prone to be broken with saveload / game being relaunched? on_timer
is very frequently used in xr_logic
scripts, but I haven't yet seen it causing such issues. I even tested to see if Beanpolev's animation change behaviour (that happens every 15000 real milliseconds) is going to be disrupted after making a save, restarting the engine and then loading it, and everything seemed to continue working correctly.
on_timer
is safe; it compares time_global()
to db.storage[obj:id()].activation_time
and their delta is saved/loaded instead of time_global()
being saved/loaded directly.
E.g. suppose activation_time is 7 minutes' worth of milliseconds and time_global()
at the point of saving is 10 minutes' worth of milliseconds. Then the 3-minute difference is saved. And on load, the 3-minute offset is added to / subtracted from time_global()
to arrive at an activation_time that is correctly adjusted for the time_global()
prevailing at the time of loading. That activation_time probably won't match the original, but that doesn't matter because the delta is what determines whether on_timer
behaves correctly, not the absolute numbers being compared.
NPCs are meant to self-heal 60 real seconds after becoming heavily wounded - a state that manifests as them falling to the ground in a fetal position and vying for a medkit.
So, if an NPC is heavily wounded 5 minutes after the game is launched and a save is created 20 seconds later in the same session, you might expect that, upon loading the save, there would still be 40 seconds remaining of the NPC's heavily wounded state before the NPC self-heals and gets up.
However, the wounded start time saved by xr_wounded.script for savegame persistence is time_global(), which returns the number of milliseconds since the game was launched. The time against which it compares this to determine if 60 seconds have elapsed is the contemporary time_global().
So, to continue the example above: suppose that after saving, you exit the game to the desktop and launch it again, thus resetting time_global(). Suppose you load the save with the wounded NPC 10 minutes after launching the game, perhaps because you first went to make tea or something.
The NPC would self-heal immediately upon the save being loaded. Why? Because the contemporary time_global() after loading would be
10 * 60 * 1000
(10 minutes), which exceeds the saved time_global() of5 * 60 * 1000 + 20 * 1000
(5 minutes 20 seconds) by more than60 * 1000
(60 seconds). Conversely, if the save were loaded 1 minute since the game was launched, the heavily wounded NPC would remain in a heavily wounded state for much longer than intended - 4 minutes and 20 seconds.See the SRP version of release_body_manager.script for a good solution to this.