Quick Reply
Search this Thread
Test Subject
Original Poster
#1 Old 25th Sep 2026 at 6:06 PM
Default Adding an OnKeyEvent when Game is paused
I'm experimenting with a script mod that adds a key binding. Any time the player presses a key on the keyboard, my method should be called. So far, I have used the following code snippet:

Code:
static MyMod() {
            World.OnWorldLoadFinishedEventHandler += OnWorldLoadFinished;
}

private static void OnWorldLoadFinished(object sender, EventArgs e) {
  SceneMgrWindow window = UIManager.GetSceneWindow();
                if (window != null) {
                    window.TriggerDown -= OnKeyEvent;
                    window.TriggerDown += OnKeyEvent;
  }
}

However, window is always null. Only if I postpone the execution of the code with AlarmManager.Global.AddAlarm(), the window is present and the keybinding works. Then again, the alarm is only triggered if the game has been unpaused and the keybinding is not present if the game starts in a paused state.

Is there any eventHandler which triggers when the window is initialized/present or an eventHandler where I can be 100% certain, that the window will already be present? Or is there some other way I can register my method to be called on key events? I appreciate any help!
Reaper
staff: moderator
#2 Old 25th Sep 2026 at 8:28 PM
The scene window is initialized during InWorldState, and InWorldState doesn't start up until after OnWorldLoadFinished; meanwhile, ToInWorldState, or its derivative TravelArrivalState, is active.

To understand this, see:
Sims3.Gameplay.ToInWorldState::Startup inside Sims3GameplaySystems.dll,
Sims3.Gameplay.InWorldState::Startup inside Sims3GameplaySystems.dll,
PostWorldInitializers.xml inside GameplayData.package.

The best is to wait for the first in-world substate via Sims3.Gameplay.InWorldState::InWorldSubStateChanging or Sims3.UI.IResponder::GameStateChanging. I have a snippet for this:
Code:
static Main() => World.sOnWorldLoadFinishedEventHandler += OnWorldLoadFinished;

static void OnWorldLoadFinished(object sender, EventArgs e) => InWorldState.InWorldSubStateChanging += OnFirstInWorldSubState;

static void OnFirstInWorldSubState(InWorldState.SubState previousState, InWorldState.SubState newState)
{
    // This check is just in case it's called prematurely, although that shouldn't be possible in vanilla.
    if (!GameStates.IsInWorld())
        return;
    // We need this method called once per world load, so we unsubscribe from it here.
    InWorldState.InWorldSubStateChanging -= OnFirstInWorldSubState;
    // Right here, the scene window isn't null.
}
Alternatively, you could have used the main window by calling Sims3.UI.UIManager::GetMainWindow, which I believe is always active.

Lastly, please don't forget to remove listeners before you close the game. Otherwise, it can cause preset saving issues.
Code:
sceneWindow.InternalWindowShutdown += OnInternalWindowShutdown;

static void OnInternalWindowShutdown(WindowBase sender, UIEventArgs eventArgs)
{
    UIManager.GetSceneWindow().InternalWindowShutdown -= OnInternalWindowShutdown;
    UIManager.RemoveTriggerHook(handle);
}

This is a signature.
Test Subject
Original Poster
#3 Old 26th Sep 2026 at 1:07 PM
Thank you so much, this is working perfectly! I had tried using GetMainWindow before but it was null as well and the OnKeyEvent was not bound.


Quote: Originally posted by Eca
Lastly, please don't forget to remove listeners before you close the game. Otherwise, it can cause preset saving issues.
Code:
sceneWindow.InternalWindowShutdown += OnInternalWindowShutdown;

static void OnInternalWindowShutdown(WindowBase sender, UIEventArgs eventArgs)
{
    UIManager.GetSceneWindow().InternalWindowShutdown -= OnInternalWindowShutdown;
    UIManager.RemoveTriggerHook(handle);
}

How are you accessing sceneWindow.InternalWindowShutdown, since it is an internal method?
Reaper
staff: moderator
#4 Old 27th Sep 2026 at 12:09 AM
Quote: Originally posted by Shadowsun252
I had tried using GetMainWindow before but it was null as well and the OnKeyEvent was not bound.

At what point did you use it? I thought it wasn't null.

Quote: Originally posted by Shadowsun252
How are you accessing sceneWindow.InternalWindowShutdown, since it is an internal method?

You can use unprotected assemblies so that they are public and accessible.

This is a signature.
Test Subject
Original Poster
#5 Old 27th Sep 2026 at 7:13 PM
Quote: Originally posted by Eca
At what point did you use it? I thought it wasn't null.


At the same point like SceneMgrWindow window = UIManager.GetSceneWindow(), directly inside the OnWordLoadFinished Method.

Quote: Originally posted by Eca
You can use unprotected assemblies so that they are public and accessible.


Oh my goodness, I didn't know those existed! That's an absolute game changer, thank you for the hint/link!
Back to top