Jump to content

How to add Packages to AI Driven player?


Roggvir

Recommended Posts

2 hours ago, CPU said:

Send an event in the OnEnd.

It is the cleaner way.

Yes, in theory - if it would even work, it would be a cleaner solution.

Except regarding the OnEnd EVENT, the wiki says this:

  • This event runs in parallel with the scene end fragment.
  • The scene will not be considered finished until the fragment and events on all scripts (on the quest or remotely registered) have finished running.

...that means even the On End FRAGMENT is run (and must finish) before the Scene is considered finished, so sending custom event from there wouldn't be any better than just relying on the Scene.OnEnd Event itself - i'd be still in the same situation.

 

Anyway, in this particular case it takes one 0.1s timer (if not none), so it isn't that bad.

(send one custom event vs. set one timer - considering that it is simpler to setup the timer, i'll go with the timer, but yeah it is not the "proper" way).

Link to comment

Let me be clear.

 

Do your event EnEnd()

inside the fragment.

 

Like that:

 

Event OnEnd()

 ; Do some boring and long stuff

 -> sendevent when you are done

endEvent

 

In this case you send your own event when the OnEnd is completing, so when you will receive it the scene will be completed for good.

If you wanna be triple sure, in your own event management (not inside the OnEnd, the other event manager) add a Utility.wait(0.1) just to give time to clean up the scene.

Link to comment

Thanks, i understand what you mean.

But you mentioned it yourself, that to make triple sure, i should add Utility.Wait(0.1), and i do not like that...

 

I understand why it behaves this way, and why introducing slight delay before sending custom event from OnEnd (be it the Fragment, or the Event) is solving the problem in most cases, but even though it works, i consider it a bad practice to introduce artificial delays and rely on them if it can be avoided.

 

Right now i have this:

event OnEnd(scene _scene)
	DoStuff()
endEvent

event OnTimer(int i)
	DoStuff()
endEvent

function DoStuff()
	if scene.IsPlaying()
		StartTimer(0.1, 0)
	else
		// ...do stuff...
endFunction

 

The above is 100% reliable, and i find it actually cleaner than doing something like:

CustomEvent evtOnSceneEnd

event OnEnd(scene _scene)
	RegisterForCustomEvent(self, "evtOnSceneEnd")
	SendCustomEvent("evtOnSceneEnd", new var[0])
endEvent

event type_self.evtOnSceneEnd(type_self sender, var[] args)
	UnregisterForCustomEvent(self, "evtOnSceneEnd")
	Utility.Wait(0.1)
	DoStuff()
endEvent

function DoStuff()
	if scene.IsPlaying()
		// ...NOW WHAT? if this happens? (near zero chance, but still a chance)
	else
		// ...do stuff...
endFunction

 

...maybe i am too "strict" in some regards, too set in my ways :smile:

(btw. i hope i do not sound ungratefull, the discussion and your help is much appreciated)

Link to comment

The first code is not 100% reliable because if you call a function DoStuff during the OnEnd event, the scene will actually not be ended.

While sending an event allows the OnEnd event to fully complete, so the IsPlaying should give you the right result.

 

Also, the "OnTimer" should not be inside the Scene code, or (until the Timer event is generated) the scene will not actually end because the thread will still be inside the papyrus VM.

 

The "Utility.wait(0.1)" is the best way to give the time to the Papyrus VM to check if another thread can be run.

So pretty much this will call the task scheduler of the VM.

 

In Skyrim, by default, you can have just one thread running on the VM in parallel. Not 100% sure about FO4, but I doubt they gave by default the multi-threading (one thread per CPU) enabled. Too risky if you have just two cores.

Link to comment
59 minutes ago, CPU said:

The first code is not 100% reliable because if you call a function DoStuff during the OnEnd event, the scene will actually not be ended.

While sending an event allows the OnEnd event to fully complete, so the IsPlaying should give you the right result.

 

Also, the "OnTimer" should not be inside the Scene code, or (until the Timer event is generated) the scene will not actually end because the thread will still be inside the papyrus VM.

 

The "Utility.wait(0.1)" is the best way to give the time to the Papyrus VM to check if another thread can be run.

So pretty much this will call the task scheduler of the VM.

 

In Skyrim, by default, you can have just one thread running on the VM in parallel. Not 100% sure about FO4, but I doubt they gave by default the multi-threading (one thread per CPU) enabled. Too risky if you have just two cores.

I "oversimplified" it to a point of breaking the whole thing.

But otherwise the pseudocode i posted is not on a Scene script, but a quest script, so nothing from there is "in the scene code".

 

This is how it actually should be:

Scriptname myTest extends Quest conditional

event scene.OnEnd(scene _scene)
	StartTimer(0.0, 0)
endEvent

event OnTimer(int i)
	DoStuff()
endEvent

function DoStuff()
	if scene.IsPlaying()
		StartTimer(0.1, 0)
	else
		// ...do stuff...
endFunction

 

Link to comment

Archived

This topic is now archived and is closed to further replies.

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. For more information, see our Privacy Policy & Terms of Use