Jump to content

Issues with random encounters


Sclerocephalus

Recommended Posts

Doing it once is sufficient.

 

 

There's another quest that won't stop running for as yet unknown reasons (the problem is not trigger-related):

[12/08/2016 - 09:45:15AM] [rescript <DLC01MQ04_01RadiantAssault (01000803)>] received RECheckForCleanup event
[12/08/2016 - 09:45:15AM] [rescript <DLC01MQ04_01RadiantAssault (01000803)>]registeredRefCount = 9 iDeadCount = 7 iUnloadedCount = 9
[12/08/2016 - 10:01:05AM] [rescript <DLC01MQ04_01RadiantAssault (01000803)>] received RECheckForCleanup event
[12/08/2016 - 10:01:06AM] [rescript <DLC01MQ04_01RadiantAssault (01000803)>]registeredRefCount = 9 iDeadCount = 7 iUnloadedCount = 9
[12/08/2016 - 10:11:11AM] [rescript <DLC01MQ04_01RadiantAssault (01000803)>] received RECheckForCleanup event
[12/08/2016 - 10:11:11AM] [rescript <DLC01MQ04_01RadiantAssault (01000803)>]registeredRefCount = 9 iDeadCount = 7 iUnloadedCount = 9
[12/08/2016 - 10:27:40AM] [rescript <DLC01MQ04_01RadiantAssault (01000803)>] received RECheckForCleanup event
[12/08/2016 - 10:27:41AM] [rescript <DLC01MQ04_01RadiantAssault (01000803)>]registeredRefCount = 9 iDeadCount = 7 iUnloadedCount = 9

This quest is from the early stages of the automatron quest line: Ada sends the player to get an item from a robot. Once you give her the item, the quest is marked as completed. That part worked apparently, as the quest is in fact marked as completed in my quest log. But it is still running ....

 

A side note: this quest has both StopQuestWhenAliasesDead and StopQuestWhenAliasesUnloaded set to 'false', which makes sense here because the quest should complete when the player turns the item in, NOT when all robots are destroyed or unloaded. Which means that this quest should actually not even have registered for a cleanup event.

Link to comment
Share on other sites

This happened when a trigger started DLC01RESceneKMK02:

[12/09/2016 - 09:03:56AM] [retriggerscript < (0023F1D7)>] State = On: OnCellLoad: Calling StartEncounter ...
[12/09/2016 - 09:03:56AM] [retriggerscript < (0023F1D7)>] State = Triggered: StartEncounter - Starting encounter ...
[12/09/2016 - 09:03:56AM] [retriggerscript < (0023F1D7)>] State = Triggered: StartEncounter - Player distance from trigger: 8067.519043
[12/09/2016 - 09:03:56AM] [rescript <DLC01RESceneKMK02 (0100354C)>] REScript Startup
[12/09/2016 - 09:03:56AM] [rescript <DLC01RESceneKMK02 (0100354C)>] OnStoryScript TriggerRef = [retriggerscript < (0023F1D7)>]

[12/09/2016 - 09:03:56AM] [retriggerscript < (0023F1D7)>] State = Triggered: QuestStarted - New quest = [rescript <DLC01RESceneKMK02 (0100354C)>]
[12/09/2016 - 09:03:56AM] [retriggerscript < (0023F1D7)>] State = Off: QuestStarted - New quest = [DLC01:Fragments:Quests:QF_DLC01MQ03RadiantScene01_0100354C <DLC01RESceneKMK02 (0100354C)>]

[12/09/2016 - 09:03:56AM] [rescript <DLC01RESceneKMK02 (0100354C)>] REScript bFinishedOnStoryEvent = True; counts = 1
[12/09/2016 - 09:04:34AM] [rescript <DLC01RESceneKMK02 (0100354C)>] OnTimer: startup timer expired: registeredAliasCount = 9
[12/09/2016 - 09:04:34AM] [rescript <DLC01RESceneKMK02 (0100354C)>] OnTimer: registering for RECheckForCleanup events

[12/09/2016 - 09:09:36AM] [retriggerscript < (0023F1D7)>] State = Off: OnCellLoad
[12/09/2016 - 09:09:36AM] [retriggerscript < (0023F1D7)>]    Last quest started = [DLC01:Fragments:Quests:QF_DLC01MQ03RadiantScene01_0100354C <None>]
[12/09/2016 - 09:09:36AM] [retriggerscript < (0023F1D7)>]    CurrentStageID = 0; IsRunning = False
[12/09/2016 - 09:09:36AM] [retriggerscript < (0023F1D7)>]    Starting timer to rearm ...

[12/09/2016 - 09:09:36AM] [rescript <DLC01RESceneKMK02 (0100354C)>] received RECheckForCleanup event; currentStageID = 50
[12/09/2016 - 09:09:36AM] [rescript <DLC01RESceneKMK02 (0100354C)>]registeredRefCount = 9 iDeadCount = 8 iUnloadedCount = 0
[12/09/2016 - 09:10:48AM] [rescript <DLC01RESceneKMK02 (0100354C)>] received RECheckForCleanup event; currentStageID = 50
[12/09/2016 - 09:10:49AM] [rescript <DLC01RESceneKMK02 (0100354C)>]registeredRefCount = 9 iDeadCount = 8 iUnloadedCount = 0

[12/09/2016 - 09:16:13AM] [retriggerscript < (0023F1D7)>] State = Off: RearmTrigger

[12/09/2016 - 09:17:50AM] [rescript <DLC01RESceneKMK02 (0100354C)>] received RECheckForCleanup event; currentStageID = 50
[12/09/2016 - 09:17:51AM] [rescript <DLC01RESceneKMK02 (0100354C)>]registeredRefCount = 9 iDeadCount = 8 iUnloadedCount = 1

Several things are noteworthy:

  1. The REScript running on DLC01RESceneKMK02 writes that quest in the myQuest property of the trigger script. That's fine. Then, the quest fragment QF_DLC01MQ03RadiantScene01_0100354C overwrites this (note: QF_DLC01MQ03RadiantScene01_0100354C is the fragment that runs on DLC01RESceneKMK02). That's a bug, as it should not be doing that (that line needs to be removed). Note that, at this point, the trigger script still has a valid pointer in the myQuest property. Then, the trigger unloads, and when it reloads, the pointer is broken ! (a 'none' check returned 'false', see below). Why ?
  2. Debug.Trace (or, Debug.TraceUser in this case, but this shouldn't matter) happily prints brahmin shit on the log for CurrentStageID and the IsRunning check, without even indicating that something went horribly wrong (the papyrus log spilled a bunch of errors at the same time).

Problem is that the broken pointer passed a 'none' check (this is part of the checks carried out to discern whether the trigger should be rearmed) and the trigger got rearmed while the quest was still running. I added a couple of failsafes in the meantime, so this won't be happening again.

 

EDIT: Its evil sibling DLC01RETravelKMK02 has the same problem.

 

EDIT2: I created a tracker entry for the problems with these quests (bug #21692). The fixes are included in my RE trigger fix.

Link to comment
Share on other sites

Impressive work!  Do you have contacts within Bethesda that you can tell them about this issue?  Though to be honest, I have more confidence in the UFO4 team to fix than Bethesda. 

Link to comment
Share on other sites

No, we don't have any insider contacts unfortunately. We'd end up having to report stuff like this through the same channels as everyone else and given the amount of work that goes into a lot of what we do, and how much stuff it touches, they'd probably not want to bother due to the QA time required.

Link to comment
Share on other sites

The vertibird encounters are causing trouble. Papyrus throws an 'attempting to start event scoped quest outside of story manager' error every time one of them stops running. The offending code is in the end fragments of those quests (this is from QF_REObject_VertibirdKMK01_0018C360):

;BEGIN FRAGMENT Fragment_Stage_1000_Item_00
Function Fragment_Stage_1000_Item_00()
;BEGIN CODE
debug.trace(self + " STOPPING")
setStage(100)
;END CODE
EndFunction
;END FRAGMENT

When this fragment calls SetStage(100), the quest obviously stopped running already, and trying to do it anyway means trying to start the quest again. More evidence that anything that's in a 'Run on Stop' flagged fragment may not work as expected.

 

This occurs with all vertibird encounters, and there is already a tracker entry for this issue.

 

Stage 100 is supposed to run a fragment that sets the StopQuestWhenAliasesUnloaded bool on REScript to 'true':

;BEGIN FRAGMENT Fragment_Stage_0100_Item_00
Function Fragment_Stage_0100_Item_00()
;BEGIN AUTOCAST TYPE REScript
Quest __temp = self as Quest
REScript kmyQuest = __temp as REScript
;END AUTOCAST
;BEGIN CODE
; now can shut down when everything unloads
kmyQuest.StopQuestWhenAliasesUnloaded = true
; set vertibird flag to return to airport
Alias_Vertibird.TryToSetValue(REVertibirdLandAirport, 1)
;END CODE
EndFunction
;END FRAGMENT

This encounter spawns a vertibird that is supposed to pick up a BoS patrol and then return to the airport. Stage 100 is set when the vertibird has successfully picked up the patrol. It thus appears that they wanted to prevent the quest from stopping on unload until the vertibird has completed this objective. That's not that simple though, as it requires separate tracking of the vertibird status: What if the vertibird is destroyed before the objective is completed ? This would require the player to search the area for remaining BoS soldiers and to kill them all for the quest to stop. Radiant quests are working that way (go to place X and kill all enemies) but random encounters don't. Anyway - they must eventually have decided for not doing it that way, because both StopQuestWhenAliasesUnloaded and StopQuestWhenAliasesDead are set to 'true' on the REScript. Consequently, there's no reason anymore to call stage 100 from the end fragment. The vertibird variable will already have been set when stage 100 was called on the running quest, and if it wasn't, the vertibird didn't complete its objective and that variable does not need to be set anyway. The only logical reason to call stage 100 again when the quest is going to stop would have been to make sure that StopQuestWhenAliasesUnloaded is set to 'true', but this is always true here.

 

Thus, the SetStage(100) line should be commented out of the end fragments.

Link to comment
Share on other sites

  • 2 weeks later...

Very impressive work, what are the in-game overall consequences of this mess? I noticed most of my random encounters spawn points have dried up and the few ones that still generate RE yield mostly rust devil patrols, I also noticed that corpses from settlement raids are not removed, is these symptoms of this glitch? Hope you guys can figure out a solution and thanks for your efforts.

Link to comment
Share on other sites

I also noticed that corpses from settlement raids are not removed, is these symptoms of this glitch?

 

Yes.

 

When the after attack message appears on the screen (success when all enemies are dead or failure if the player didn't make it to the settlement in good time, whichever applies), the quest is marked as completed and removed from the task list. It may appear to the player therefore that the quest is over then, but it is actually still running and may continue to do so for quite some time.

 

Actors who are created at run time will be deleted by the engine after a short period of time unless they are in a quest alias. Therefore, quests that send the player to kill a bunch of enemies at a certain location usually wait for all corpses to unload and only then stop running. When they stop, all quest aliases are cleared and only then the actors can be removed by the engine. Simply speaking, the game tries to avoid situations where bodies are culled right in front of the player's eyes.

 

To accomplish this, the quests need to check their stop conditions in more or less regular intervals. If you do this from the quest script however, that script would either have to run permanently or have a timer running at all times. Considering that there may easily be a dozen of such quests running at the same time, this would cost significant performance. Therefore, the quest scripts are doing nothing most of the time and are just waiting for a cleanup event being sent. That event wakes the script up, so to say, to check its stop conditions, and if the stop conditions are not fulfilled it will fall back in a state of inactivity until another cleanup event fires and it checks the conditions again. Thus, this strategy is basically a good idea. It was a bad idea however to send the event from active RE triggers.

 

Now, when there are no active triggers left, there will be no events, and when there are no events, quests that rely on them will never stop running. In the game, this manifests itself by corpses not being removed.

Link to comment
Share on other sites

  • 3 weeks later...

This is the icing on the cake of the RE cleanup system:

 

Settlement attacks on Far Harbor settlements still need an exceedingly long time to get their mess cleaned up. Of course, they are waiting for cleanup events that are sent when the player hits an active RE trigger. Turned out however that there are no RE triggers on fog island ...

 

This means that you have to return to the Commonwealth and hit an active trigger there for these quests to stop running and cleaning up their mess. Since there are four settlements on the island, it should even be possible to 'saturate' the workshop attack node so you could end up with several workshop attacks starting to run at the same time again when you have spent a long enough time on the island and the backlog of Far Harbour attack quests stops running at once. Chances for this are low, but it's not impossible.

 

This issue required an update to my fix:

 

(1) Cleanup events will now be sent in regular intervals from a timer on REParentScript (RE triggers will not send any events anymore).

(2) This timer needs to be started once (once it is running, it will automatically set a new timer when an event has been sent). To accomplish this, a function has been added to REParentScript, which needs to be called from the UFO4P retroactive script. I also added an OnInit() event to REParentScript to call the startup function when a new game is started.

Link to comment
Share on other sites

A note on DLC01MQ04_01RadiantAssault (this is the quest from post #26 that doesn't stop running for some reason):

 

Having looked in the meantime at how the StopQuestWhenAliasesDead and StopQuestWhenAliasesUnloaded properties are handled by other quests, I suppose that StopQuestWhenAliasesUnloaded should have been set to 'true' by a quest fragment once the player turned the item in.

 

Workshop attacks are doing it that way: both StopQuestWhenAliasesDead and StopQuestWhenAliasesUnloaded start 'false' and StopQuestWhenAliasesUnloaded is set to 'true' some time after the attack end message has been displayed on the screen, and only then the quest will stop running once all aliases have unloaded.

 

In the scripts of DLC01MQ04_01RadiantAssault however, this line is completely missing. To fix this, the stage 200 fragment needs to be modified as follows:

kmyQuest.RemoveItemFromPlayer()
((self as Quest) as REScript).StopQuestWhenAliasesUnloaded = true
CompleteAllObjectives()
kmyQuest.CompleteQuest()

Note that the cast is needed here because kmyQuest is pointing to a different script.

Also note that the CompleteQuest function that is called here will NOT complete this quest (but calls a function on DLC01MQ00Script instead to track how many items have been turned in to Ada). This quest will not stop running until REScript sets the stop stage, and this will never happen without the line added above.

 

To make this work retroactively, an UFO4P script needs to check whether this quest is running and stage 200 is done, and if so, set the StopQuestWhenAliasesUnloaded property on the REScript to 'true'.

 

EDIT: This is now listed as on the tracker as bug #21866.

Link to comment
Share on other sites

The fix is working but is not intended to be released as a standalone. It will be included in the upcoming UFO4P 2.0.

Link to comment
Share on other sites

I was going through the thread... since I really am not a coder I guess I'm asking for clarification: This will be a retroactive fix that will close existing RE quests in current games in addition to keeping new random events from causing the same problem?

Asking because I am about to start up some new games and hoping I can simply update to UFO4P 2.0 to fix any quests (Automatron does leave a lot of robot corpses when I run into Rust Devils and the like) in the game and not have to start over.

Link to comment
Share on other sites

18 minutes ago, Sinapus said:

I was going through the thread... since I really am not a coder I guess I'm asking for clarification: This will be a retroactive fix that will close existing RE quests in current games in addition to keeping new random events from causing the same problem?

Yes.

Link to comment
Share on other sites

Hm. I guess I have other questions about what it's going to do to an existing game, like will it cause a massive lag when it starts finding quests to cleanup, but I suspect that will be mentioned in the release notes when 2.0 is completed.

 

Hopefully, I will remember to read those first. :-)

Link to comment
Share on other sites

Sorry for late reply.  I have been very busy during the last week to put the fixes for the current beta together.

 

Potential performance issues caused by reactivating all inactive triggers as soon as they are spotted (i.e. when they load) has been a concern indeed. There are two sorts of inactive triggers:

(1) Triggers that are just completely inactive because they were never properly rearmed. Those triggers would try to start new quests as soon as they are reactivated.

(2) Triggers that are blocked by a quest that doesn't stop running because it waits for a cleanup call that is only sent by active triggers (the longer you play the game, the more this becomes a problem since the number of active triggers is steadily decreasing as a result of issue 1).

In the worst case, your story manager is 'saturated' (or nearly so) with hanging quests. That is, it would be unable to handle any calls for starting new quests anyway. If not, it would try to start as many new quests as possible, and this might be too much as well. When you run around in the wilderness and a random encounter quest starts running, you get a short stutter (even on fast computers) because the engine has to set up around a dozen of actors whose AI will start running almost at once (and this draws apparently a significant bit of performance). In areas with a high trigger density (most notably the suburbs: Cambridge and South Boston), you easily get into situations where half a dozen of new quests could start running within a short period of time, and this would almost certainly lead to stability problems.

The game is using cool-down timers to minimize stability issues. That is, a trigger will not start a new quest immediately after getting rearmed but wait until that timer runs out. This is futile though when all triggers have been inactive for a long period of time because those timers will all have expired.

To minimize stability issues after activating the patch, we implemented the following procedures:

(1) As soon ast the patch is activated, an UFO4P script makes REParentScript send out a cleanup call and then starts a timer on that script to send more calls at intervals of two game hours (once activated, the timer will send another cleanup call and restart itself after it runs out). This means that the game immediately starts getting rid of its backlog of hanging quests: this is a prerequisite before trying to start new quests makes any sense.

(2) Inactive triggers will not be reactivated immediately, but with a variable delay of 2-4 game hours.

This improves matters considerably. Nonetheless, you sill may experience more frequent fps drops in certain areas after the patch has been activated, but they will slowly disappear within a couple of game days.

Link to comment
Share on other sites

Well, right now I have nothing but fresh games (i.e., characters who just woke up in Vault 111) so I probably won't hit much lag at all. Most of the "stuck" quests I ran into seemed to be from Automatron but your patch notes states others were doing it too. Now that I think of it there was what looked like a vanilla RE, a brahmin/radstag corpse with a few bugs, that never seemed to despawn after I killed the bugs so that may have been one of them.

 

I may try the beta though I'm not sure I can give very good feedback. I guess I can try to find if one of my many mods interferes with the beta patch or similar. :-)

 

Thank you and the rest of the UFO4P team for your hard work on this.

Link to comment
Share on other sites

There is a certain type of encounters that was not supposed to rearm its triggers anyway (according to designer notes on some quest fragments), and we didn't change that. Those encounters (so-called 'object type' encounters) are used to place items or lootable containers in the game world that are considered useful at lower levels. Not all of them are intended to get cleared up either - and some corpses may fall into this category.

We can't say for sure though whether every single encounter quest does now behave as expected. There are more than a hundred of them (DLCs included) and checking that stuff consumes a lot of time. For the time being, we only took care of the very broken ones (i.e. those that would fail to stop or threw errors on the log to be concerned about).

Link to comment
Share on other sites

Is that "gassy settler" guy that puts that cannery on your pipboy map one of the ones that's not supposed to re-arm it's triggers?

Would be interesting if that were so. I know Doc Anderson will show up at different "campsite" style areas since she did, even after I finished Automatron.

Link to comment
Share on other sites

  • 2 weeks later...

Hello I noticed this issue with my FO4 too :( , is there a way to fix it mid play through atm? or at least a way to prevent it reverting to an older save ? its a long way until UFOP 2,0 :(

Link to comment
Share on other sites

15 hours ago, Sora_ said:

Hello I noticed this issue with my FO4 too :( , is there a way to fix it mid play through atm? or at least a way to prevent it reverting to an older save ? its a long way until UFOP 2,0 :(

Well, UFO4P 2.0 does fix it  retroactively on running games.  Why not give the beta a try ?

Link to comment
Share on other sites

7 hours ago, Sclerocephalus said:

Well, UFO4P 2.0 does fix it  retroactively on running games.  Why not give the beta a try ?

 

Oh thank you <3 I didn't see the update !

Edit: I have to download from here,not nexus, right?

 

Link to comment
Share on other sites

Correct, it's only available here.  Version 2.0.0 -- see Arthmoor's second post under Unofficial FO4 Patch.  I started a new game with it and seems to work great.  So many more random encounters now.  And maybe it's just my imagination, but the encounters seem much more dangerous.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...