Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Signals table in scheme storage does not persist across saves #154

Open
Decane opened this issue Oct 15, 2023 · 3 comments
Open

Signals table in scheme storage does not persist across saves #154

Decane opened this issue Oct 15, 2023 · 3 comments
Assignees

Comments

@Decane
Copy link
Owner

Decane commented Oct 15, 2023

This can cause e.g. the main storyline to break per this Steam thread:

After inspecting the game's audio scripts, I can see that the sound_end signal does not persist across saves. Usually this isn't a problem, but it can be if a save gets created during the short time window after the object binder update() call that triggers the sound callback that registers the signal but before the subsequent object binder update() call that would trigger xr_logic.try_switch_to_another_section() and actually respond to that signal. If this happens, then upon loading the affected save, the signal will have been lost and any logic script that relies on it can get stuck.

The sound_end and theme_end signals may not be the only ones susceptible to being lost in the event of an unfortunately timed save.

@Decane Decane self-assigned this Oct 15, 2023
@Decane
Copy link
Owner Author

Decane commented Oct 15, 2023

There is a work-around for processing the sound_end and theme_end signals specifically that does not require saving/loading the scheme storage signals table in xr_logic.script - and hence obviates introducing a new game requirement to fix the specific issue reported in the Steam thread.

Consider e.g. the update routine in bind_restrictor.script, which currently calls the active scheme's update routine before executing the update routine in xr_sound.script:

	if obj_st.active_scheme then
		xr_logic.issue_event(nil, obj_st[obj_st.active_scheme], "update", delta)
	end

	xr_sound.update(self.object:id())

If we instead flip the order of these statements, there should be no opportunity to save between the following two event chains:

  • xr_sound.update()active_sound:callback()obj_st[obj_st.active_scheme].signals["sound_end"] = true
  • obj_st[obj_st.active_scheme]:update()xr_logic.try_switch_to_another_section()

... provided the order is also flipped in every other relevant object binder. That's because all of the above code would then run within the same, single invocation of the object binder update routine instead of being spread across two invocations thereof, as previously (which allowed the possibility of a save happening between invocations).

Update: Implemented in bcc6616.

@SurDno
Copy link
Contributor

SurDno commented Oct 18, 2023

How often do object binder update() calls happen? Just interested in how long is the window for the save that breaks the logic.

@Decane
Copy link
Owner Author

Decane commented Oct 20, 2023

The object binder update() frequency for a space restrictor decreases with the restrictor's distance from the player. At the southern entrance to the Cordon where the level changer from the Swamps positions the player, I recorded the following real seconds elapsed since launching the game for the first 20 bind_restrictor update() instances for esc_space_restrictor_scene1_script (i.e. the space restrictor that binds the esc_quest_line.ltx logic that was discovered to be stuck in the Steam thread) - without moving:

  • 75.103
  • 75.964 (+0.861)
  • 76.283 (+0.319)
  • 76.565 (+0.282)
  • 76.859 (+0.294)
  • 77.172 (+0.313)
  • 77.464 (+0.292)
  • 77.767 (+0.303)
  • 78.067 (+0.300)
  • 78.355 (+0.288)
  • 78.639 (+0.284)
  • 78.923 (+0.284)
  • 79.223 (+0.300)
  • 79.519 (+0.296)
  • 79.808 (+0.289)
  • 80.186 (+0.378)
  • 80.469 (+0.283)
  • 80.756 (+0.287)
  • 81.039 (+0.283)
  • 81.336 (+0.297)

As you can see, if we ignore the first update after load (which is an outlier), the difference between the rest hovers at around 0.3 seconds. So there would be about a 0.3 second time window during which the storyline break reported in the Steam thread could happen.

However, as there are many instances of sound_end and theme_end signals in the game's logic scripts, the logic break reported in the Steam thread is just one of several possible similar logic breaks with the same root cause.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants