Issue #23695: Automatrons assigned to supply lines occasionally reset, causing supply lines to stick (+fix?)
This is a fairly well-known issue, but surprisingly I can't find anything on the tracker here about it, so here it is.
The result of this bug is that Automatron robots who have been assigned to supply lines occasionally get reset to back to their base form state, i.e. DLC01LvlCompWorkbenchBot [NPC_:01001EED], and all of the data stored on the actor itself by e.g.
gets reset along with it. Obviously this means that any mods and names and so on applied to the automaton go missing, but this also means that the next time the supply line they actor used to belong to gets cleaned back up, the call to
assignedActor.GetCaravanDestinationID() fails, because there isn't a WorkshopParent.WorkshopCaravanDestination AV stored on the actor anymore. The code that runs when a provisioner gets reassigned, and even the WorkshopParentScript.ClearCaravansFromWorkshopPUBLIC() function both fail because they rely on the AV information still being present on the provisioner. As a result, the supply line becomes "stuck", and there are no vanilla mechanisms for cleaning the supply lines back up (which are, of course, just linked locations set via workshopStart.myLocation.AddLinkedLocation(workshopDestination.myLocation, WorkshopCaravanKeyword) in WorkshopParentScript)
My best guess as to what exactly is happening here is that an engine-level issue resets these actors the next time they're loaded after they've spent enough time unloaded in a respawning cell. I haven't figured out why this happens to automatrons and not to normal provisioners, though.
Anyway, a speculative fix for this issue is to force automatron provisioners into a script property, which puts them into a higher level of persistence than if they're just in a ref collection alias. I'm not entirely sure why this works, but after writing a mod that automates supply line creation, I noticed that all of my Automatron provisioners have stopped resetting even after, like, 50 hours of playtime, and additionally none of the users of my mod have mentioned that their automatron provisioners have reset on them either. Since the only thing being done differently in my mod compared to vanilla is that all provisioners are stored in a script property, I assume that this is the thing preventing them from resetting.
A standalone script to do this would look something like this
Scriptname AutomatronProvisionerAntiResetScript extends Quest WorkshopParentScript Property WorkshopParent Auto Const Mandatory RefCollectionAlias Property CaravanActors Auto Const Mandatory DLC01:WorkshopRobotScript Property RobotProvisioners Auto bool editLock = false Event OnQuestInit() RegisterForCustomEvent(WorkshopParent, "WorkshopActorCaravanAssign") RegisterForCustomEvent(WorkshopParent, "WorkshopActorCaravanUnassign") RobotProvisioners = new DLC01:WorkshopRobotScript GetEditLock() ; Force existing robot provisioners into the array, so the fix is retroactive to already-assigned provisioners int caravanActorCount = CaravanActors.GetCount() int i = 0 while (i < caravanActorCount) WorkshopNPCScript thisActor = CaravanActors.GetAt(i) as WorkshopNPCScript if (thisActor is DLC01:WorkshopRobotScript) RobotProvisioners.Add(thisActor as DLC01:WorkshopRobotScript) Debug.Trace("Added " + thisActor + " to RobotProvisioners.") else Debug.Trace("Skipped " + thisActor + " because they do not appear to be an automatron.") endif i += 1 endwhile editLock = false EndEvent Event WorkshopParentScript.WorkshopActorCaravanAssign(WorkshopParentScript akSender, Var akArgs) if (akArgs.Length > 0 && akArgs is DLC01:WorkshopRobotScript) GetEditLock() ; edit locks might not be required when adding? probably doesn't hurt just to be safe RobotProvisioners.Add(akArgs as DLC01:WorkshopRobotScript) editLock = false endif EndEvent Event WorkshopParentScript.WorkshopActorCaravanUnassign(WorkshopParentScript akSender, Var akArgs) if (akArgs.Length > 0 && akArgs is DLC01:WorkshopRobotScript) GetEditLock() RobotProvisioners.Remove(RobotProvisioners.Find(akArgs as DLC01:WorkshopRobotScript)) editLock = false endif EndEvent Function GetEditLock() while (editLock) Utility.WaitMenuMode(0.1) endwhile editLock = true EndFunction
Attached is also a quick mod implementing this script. If anyone wants to test it, just load it and play the game normally, see if any of your robot provisioners still reset sometimes. It wouldn't really do me any good to test it myself since my other (proper) mod seems to have fixed the problem already, and I'm not going to waste many hours of my time playing without it.
int index = RobotProvisioners.Find(akArgs as DLC01:WorkshopRobotScript) if (index > -1) RobotProvisioners.Remove(index) endif