Welcome to the AFK Mods bug tracker. In order to report an issue, you need to have a VALIDATED account to post one. Once you have followed the link the registration email sent you, please select a project from the drop down menu below. Select “Open New Issue” and fill out the form with as many details as possible.

Please also consider sending your bug report to Bethesda if you are reporting on an issue with Skyrim Special Edition, Fallout 4, or Starfield. Doing so will help everyone on all platforms.

Issue Data
Status: Closed
Issue Type: Bug Report
Project: Unofficial Fallout 4 Patch
Component: Fallout 4: Vanilla
Category: Settlements & Workshops
Assigned To: Sclerocephalus
Platform: All
Severity: Medium
Votes: 0
Watching: N/A
Opened By Sclerocephalus on Mar 20, 2018 1:47 am
Last Edited By Sclerocephalus on Mar 20, 2018 1:48 am
Closed By Sclerocephalus on May 18, 2018 9:20 pm
Resolution: Fixed
Comment: Fixed for UFO4P 2.0.4

Issue #24122: WorkshopScript, WorkshopParentScript: Fixes for #23016 and #23469 need to be improved

 
#23469 aimed at fixing an issue with the RecalculateWorkshopResources() function on WorkshopScript. That function needs to check whether a workshop is loaded before proceeding, and the vanilla script did this by running an IsLoaded() check on the location. However, since that function has been conceived to return ' true' if any cell of a location is loaded, it may return 'true' if only one cell is loaded (in the worst case). Which means that the function may proceed with recalculating the workshop resource values if most of the location is actually not loaded, and as a result, some or all of the workshop stats would evaluate as zero.

To improve this, the current fix checks instead whether the player is currently at the workshop's location (i.e. if Game:GetPlayer().GetCurrentLocation() == WorkshopLocation). If this returns 'true', the player is in a corner cell of the workshop in the worst case, so there should be at least 3x3 cells of the workshop loaded (on the standard 5x5 grid). For small workshops, this means that they are completely loaded; large workshops may still not be loaded completely, but this is nevertheless a big improvement compared to the vanilla check that would return 'true' if only one cell was loaded - if it works, that is ...

Unfortunately though, it doesn't.This check is unreliable because GetCurrentLocation() returns 'none' if the player is currently in workshop mode. Likewise, entering(exiting workshop mode triggers location change events, and these bogus events were the cause of at least two serious bugs we had to fix in the past. I actually should have remembered this, but it escaped me when I implemented the fix for #23469.

With the current fix in place, the check never returns 'true' if the player is in workshop mode, and since this is what most players do for extended periods of time while they are at their workshops, chances are high that the resource recalculation never runs at all.

To improve this, I conceived a workaround: if the player enters or leaves workshop mode, an event is sent to the respective workshop. WorkshopScript handled this event already but it did not store information on the current status. I added a tracking bool for this purpose (made it a hidden property, so it can also be checked by external scripts). If this bool is checked in addition to the player's location, things will be working as intended (since it is safe to assume that the workshop location is loaded if workshop mode is active).

#23016 was a fix on WorkshopParentScript that needed to check whether a workshop has started to unload That fix is still using the IsLoaded() check on the workshop location. Using the improved check instead makes that operation significantly more reliable too.

Related Issues: 23016  23469  

Comments

9 comment(s) [Closed]
EyeDeck said:
 
Unfortunately though, it doesn't.This check is unreliable because GetCurrentLocation() returns 'none' if the player is currently in workshop mode.

Is that what's causing the bogus location change events to fire? The engine forcibly sets the player's location to 'none' while in workshop mode? Man, Bethesda, what a bug that is.

Sclerocephalus said:
 
Yes. WorkshopParentScript interpreted the bogus location changes as valid events and started a workshop reset whenever the player left the workshop menu or workshop mode. This in turn could cause the settler assignment issue to affect even workshops with very low resource object counts.

Comment #2 Mar 21, 2018 3:31 pm  Edited by Sclerocephalus on Mar 21, 2018 3:31 pm
EyeDeck said:
 
Hmm... I tried testing this myself with a function that would do this for a bit when I ran it
for int i = 0 to 20
	Debug.Trace("loc: " + PlayerRef.GetCurrentLocation())
	Debug.Trace(Game.GetPlayer().GetCurrentLocation())
	Utility.Wait(1)
endfor

(that's using Caprica language extensions for the for loop because I use it as my primary compiler anyway)
Anyway, I ran that function and went into workshop mode, and the printout always returned the correct location.

Additionally, I uncommented a bit of debug code I already had in an Actor.OnLocationChange event, where the only actor I had registered for remote events on was the player, so it would dump akNewLoc to the log every time that event fired. I tried entering/exiting workshop mode in a few different settlements, building/scrapping a few different things, and using some crafting stations, and my script never picked up any bogus location change events, only ever real ones when I actually did change locations.

Could it be that the bug was fixed in a newer version of the game? Or perhaps it's install-dependent somehow?

Comment #3 Mar 22, 2018 7:43 am  Edited by EyeDeck on Mar 22, 2018 7:49 am
Sclerocephalus said:
 
Now you beat me.

I honestly couldn't remember whether it ever was 'none' or just another inappropriate value, so I turned the traces in the OnLocationChange event of WorkshopParentScript back on. This is what I get on the log while staying INSIDE the boundaries of Oberland Station. I entered and left workshop mode a couple of times and also activated the workbench:

[03/25/2018 - 12:49:00PM] OnLocationChange: akOldLoc = [Location < (0009B1C2)>]
[03/25/2018 - 12:49:00PM] OnLocationChange: akNewLoc = [Location < (00002CF0)>]
[03/25/2018 - 12:49:00PM] OnLocationChange: UFO4P_PreviousWorkshopLocation = [Location < (0009B1C2)>]; IsLoaded = True
[03/25/2018 - 12:49:00PM] OnLocationChange: exited workshop location [Location < (0009B1C2)>]
[03/25/2018 - 12:49:19PM] OnLocationChange: akOldLoc = [Location < (00002CF0)>]
[03/25/2018 - 12:49:19PM] OnLocationChange: akNewLoc = [Location < (0009B1C2)>]
[03/25/2018 - 12:49:19PM] OnLocationChange: UFO4P_PreviousWorkshopLocation = [Location < (0009B1C2)>]; IsLoaded = True
[03/25/2018 - 12:49:19PM] OnLocationChange: entered workshop settlement location [Location < (0009B1C2)>]
[03/25/2018 - 12:49:19PM] OnLocationChange: New workshop location is the same as the last workshop location left by the player.
[03/25/2018 - 12:49:19PM] OnLocationChange: Game time since last reset = 0.339600
[03/25/2018 - 12:49:19PM] OnLocationChange: Skipping reset.
[03/25/2018 - 12:49:21PM] OnLocationChange: akOldLoc = [Location < (0009B1C2)>]
[03/25/2018 - 12:49:21PM] OnLocationChange: akNewLoc = [Location < (00002CF0)>]
[03/25/2018 - 12:49:21PM] OnLocationChange: UFO4P_PreviousWorkshopLocation = [Location < (0009B1C2)>]; IsLoaded = True
[03/25/2018 - 12:49:21PM] OnLocationChange: exited workshop location [Location < (0009B1C2)>]
[03/25/2018 - 12:49:29PM] OnLocationChange: akOldLoc = [Location < (00002CF0)>]
[03/25/2018 - 12:49:29PM] OnLocationChange: akNewLoc = [Location < (0009B1C2)>]
[03/25/2018 - 12:49:29PM] OnLocationChange: UFO4P_PreviousWorkshopLocation = [Location < (0009B1C2)>]; IsLoaded = True
[03/25/2018 - 12:49:29PM] OnLocationChange: entered workshop settlement location [Location < (0009B1C2)>]
[03/25/2018 - 12:49:29PM] OnLocationChange: New workshop location is the same as the last workshop location left by the player.
[03/25/2018 - 12:49:29PM] OnLocationChange: Game time since last reset = 0.341949
[03/25/2018 - 12:49:29PM] OnLocationChange: Skipping reset.
[03/25/2018 - 12:49:34PM] OnLocationChange: akOldLoc = [Location < (0009B1C2)>]
[03/25/2018 - 12:49:34PM] OnLocationChange: akNewLoc = [Location < (00002CF0)>]
[03/25/2018 - 12:49:34PM] OnLocationChange: UFO4P_PreviousWorkshopLocation = [Location < (0009B1C2)>]; IsLoaded = True
[03/25/2018 - 12:49:34PM] OnLocationChange: exited workshop location [Location < (0009B1C2)>]
[03/25/2018 - 12:49:35PM] OnLocationChange: akOldLoc = [Location < (00002CF0)>]
[03/25/2018 - 12:49:35PM] OnLocationChange: akNewLoc = [Location < (0009B1C2)>]
[03/25/2018 - 12:49:35PM] OnLocationChange: UFO4P_PreviousWorkshopLocation = [Location < (0009B1C2)>]; IsLoaded = True
[03/25/2018 - 12:49:35PM] OnLocationChange: entered workshop settlement location [Location < (0009B1C2)>]
[03/25/2018 - 12:49:35PM] OnLocationChange: New workshop location is the same as the last workshop location left by the player.
[03/25/2018 - 12:49:35PM] OnLocationChange: Game time since last reset = 0.343307
[03/25/2018 - 12:49:35PM] OnLocationChange: Skipping reset.
[03/25/2018 - 12:53:33PM] OnLocationChange: akOldLoc = [Location < (0009B1C2)>]
[03/25/2018 - 12:53:33PM] OnLocationChange: akNewLoc = [Location < (00002CF0)>]
[03/25/2018 - 12:53:33PM] OnLocationChange: UFO4P_PreviousWorkshopLocation = [Location < (0009B1C2)>]; IsLoaded = True
[03/25/2018 - 12:53:33PM] OnLocationChange: exited workshop location [Location < (0009B1C2)>]
[03/25/2018 - 12:53:38PM] OnLocationChange: akOldLoc = [Location < (00002CF0)>]
[03/25/2018 - 12:53:38PM] OnLocationChange: akNewLoc = [Location < (0009B1C2)>]
[03/25/2018 - 12:53:38PM] OnLocationChange: UFO4P_PreviousWorkshopLocation = [Location < (0009B1C2)>]; IsLoaded = True
[03/25/2018 - 12:53:38PM] OnLocationChange: entered workshop settlement location [Location < (0009B1C2)>]
[03/25/2018 - 12:53:38PM] OnLocationChange: New workshop location is the same as the last workshop location left by the player.
[03/25/2018 - 12:53:38PM] OnLocationChange: Game time since last reset = 0.387939
[03/25/2018 - 12:53:38PM] OnLocationChange: Skipping reset.
[03/25/2018 - 12:53:51PM] OnLocationChange: akOldLoc = [Location < (0009B1C2)>]
[03/25/2018 - 12:53:51PM] OnLocationChange: akNewLoc = [Location < (00002CF0)>]
[03/25/2018 - 12:53:51PM] OnLocationChange: UFO4P_PreviousWorkshopLocation = [Location < (0009B1C2)>]; IsLoaded = True
[03/25/2018 - 12:53:51PM] OnLocationChange: exited workshop location [Location < (0009B1C2)>]

Which means that the check for the player's current location being the same as the workshop location will definitely fail.

If that's really dependent on specific installs, trying to fix that stuff would actually be a big waste of time, since you cannot say whether a bug that affects you does affect others nor whether others may have bugs that don't affect you for myterious reasons.

Another explantion that may come to mind, namely that this behaviour is specific to workshop related scripts (for whatever reason) can be safely excluded, since the script on DIalogueBunkerHill quest was affected by the same issue.

Comment #4 Mar 25, 2018 5:57 pm  Edited by Sclerocephalus on Mar 25, 2018 6:09 pm
EyeDeck said:
 
Okay, that makes sense. 2CF0 is CommonwealthLocation; what's likely is that the workshop boundaries for Oberland Station don't actually properly correspond with the location data on its constituent cells. Me, I have a mod that increases the cell footprint of nearly every settlement to ~2x3 or 3x3, which would certainly make it less likely for me to accidentally stumble into such a cell since I believe the same mod fixes this problem in every settlement it edits too.

I've had related issues with workshop objects before, where it's possible to place objects near the boundaries of many (vanilla) settlements so that the cell they're in isn't actually part of the settlement's location anymore. If I want to get a workshop object's location, it's necessary to run GetLinkedRef(WorkshopItemKeyword) on it to find its parent workbench, then run GetCurrentLocation() on that, because just doing GetCurrentLocation() on the object itself isn't reliable. Obviously this approach doesn't work on the player, though.

Unfortunately the underlying problem here, that being settlement cells not having proper location data set, isn't something that UFO4P can really reliably fix, simply because UFO4P's location high in the load order makes it likely for mods to overwrite cell-level location data changes. Ignoring that, it would be a massive pain to go over every single settlement and check that every single cell inside a given workshop boundary has correct location data, and then to make sure that the cell location footprint of each corrected settlement doesn't exceed 3x3 (except in the ones where it already does, namely Sanctuary, Spectacle Island and Boston Airport). It might still not be a bad idea, though, in case anyone wants to volunteer for that task (ugh).

Comment #5 Mar 25, 2018 10:05 pm  Edited by EyeDeck on Mar 25, 2018 10:13 pm
Sclerocephalus said:
 
I don't think that this is related to improper location data. As you can see in the log posted above, exiting workshop mode results in the player location (= newLocation) being instantly registered as the correct workshop locatio, so it can't be a problem of the cell I was standing in while I left workshop mode. And you always get that bogus event, irrespective of whether you are close to or far from the workshop boundaries.

You can easily test this yourself by recompling UFO4Ps WorkshopParentScript in debug mode. Before you do, you'll have to re-enable the traces in the OnLocationChange event. I commented them out a long while ago, once we had made sure that the procedure works as intended.

Recording the player's location as Commonwealth location while in workshop mode is worse than recording it as 'none', because it makes valid leave events (where the player changes into a wilderness cell that has no other parent location than the commonwealth location) indiscernible from invalid ones. Fortunatley, the fix didn't require to record a valid leave event; we only had to make sure that the workshop reset call is skipped if the player "re-enters" within a sufficiently short period of time.

EyeDeck said:
 
Before I fiddle with WorkshopParentScript, I took a look at Oberland Station in the CK:
http://idek.chir.uno/fo4/oberland-station.JPG
There are only two cells tagged with the correct location (Farm03Location) out of the four that make up the workshop's boundary, which I marked in the image. You should be able to confirm this in-game by walking across the cell boundaries and seeing if location change events fire. Assuming that the event only fires when crossing over in or out of the two untagged cells, the game engine is doing it's job, but Bethesda messed up the cell data. This is definitely looking like a case of "garbage in, garbage out" to me, and not a malfunction of the scripts or engine itself.

Edit: I have also had a go at disabling all of my mod plugins (except for one, mine), and enabling some debug printouts to show a message box any time the player gets an OnLocationChange event, and print some stuff to the log:
[03/26/2018 - 09:45:28AM] Loaded a new location: [Location < (00002CF0)>], [Location < (0009B1C2)>]
[03/26/2018 - 09:45:30AM] Loaded a new location: [Location < (0009B1C2)>], [Location < (00002CF0)>]
[03/26/2018 - 09:45:31AM] Loaded a new location: [Location < (00002CF0)>], [Location < (0009B1C2)>]
[03/26/2018 - 09:45:34AM] Loaded a new location: [Location < (0009B1C2)>], [Location < (00002CF0)>]
(etc), anyway I can confirm that I only ever got these events when passing over the cell boundary I highlighted in the above image. This behavior is correct, but as mentioned, garbage in, garbage out.

Comment #7 Mar 26, 2018 8:20 am  Edited by EyeDeck on Mar 26, 2018 8:51 am
Sclerocephalus said:
 
It appears that you still didn't get the point. I did not check for faulty cells (yet), i.e. I did not run around while I recorded the log I posted above. I was standing near the workbench and entered /exited workshop mode a couple of times. In the meantime, I swapped items with some settlers in and around the tato field, and I did certainly not move outside of the cells that are still properly tagged, according to the image.

Anyway, checking for workshop mode being active will improve things in either case. If there a faulty cells where the location check alone would fail, the check for workshop mode can make it that there's a 'true' returned. If you aren't in workshop mode either, nothing will help though.

EyeDeck said:
 
I'm still trying to understand the nature of the alleged bogus OnLocationChange events, since this sort of thing is relevant to my interests. I've now tried both listening for location change events sent from the player via an external script, as well as uncommenting the bits in WorkshopParentScript and recompiling. I've even added additional debug to WorkshopParentScript so I'd get a message box any time the location change event fires, and yet the events are still exclusively limited to me actually passing over a cell boundary and into a different location. Long load order, or one with only official DLC and UFO4P... nothing, no bogus events.

Have you tried adding a message box (or some other real-time feedback mechanism) to WorkshopParentScript yourself, to confirm 100% for sure that you're really getting them while standing still? Given that there's no sanity checking for this, maybe try adding akSender to your debug printouts to be sure that WorkshopParentScript didn't somehow get registered for OnLocationChange events from other actors?

I suppose the OnWorkshopMode-based checks can't hurt in any case, but it's strange that I'm completely unable to reproduce an ostensibly well-documented bug such as this one myself.

I posted the image about Farm03Location etc, because in that particular settlement, it's possible to cross unto untagged cells after only walking, like, 10 feet away from the workbench. You don't even need to go near any of the edges of the workshop boundary to leave the location there. Perhaps it would be prudent to open a separate bug report about that issue, since there are definitely improvements to be made there. If that one, and only, settlement I've looked at is that bad about its boundaries, I wonder what other settlements are similar, or worse.

Comment #9 Apr 1, 2018 10:45 pm  Edited by EyeDeck on Apr 1, 2018 11:42 pm
Showing Comments 1 - 9 of 9