Posts: 299
Thanks: 2367 in 17 Posts
10 Achievements
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.