pepperman35 Posted January 11, 2022 Share Posted January 11, 2022 Okay, I have made a little script that does the following at a new settlement: 1) counts the number of work objects (food, defense, scavenger, vendors); 2) spawns in an equal amount of NPCs; 3) Unassigns all the NPCs (i.e., makes them unemployed); outfits the NPCs with a select outfit and gear; and final assigns the NPCS to the work object. A few checks needs to be added to the script, especially the assignment functionality; however, it will work. Upon testing the various function, I noticed something that I could not overcome or correct. Unassigning the NPCs will do just that but I noticed that the food value in workshop mode doesn’t go to zero like I expect with no one assigned to the food objects. Is there a way to overcome this? ;-- Properties -------------------------------------- Group BaseGame WorkshopParentScript Property WorkshopParent Auto Const Mandatory Quest Property pWorkshopParent Auto Const mandatory Keyword Property pWorkshopItemKeyword Auto Const Mandatory ActorValue Property Food Auto Const Mandatory ActorValue Property WorkshopRatingScavengeGeneral Auto Const Mandatory ActorValue Property Safety Auto Const Mandatory ActorValue Property vendorIncome Auto Const Mandatory ActorValue Property pWorkshopRatingPopulation Auto Const mandatory ActorValue Property pWorkshopGuardPreference Auto Const mandatory Weapon Property GaussRifle Auto Const Mandatory Ammo Property Ammo2mmEC Auto Const Mandatory MiscObject Property Caps001 Auto Const Mandatory Potion Property Stimpak Auto Const Mandatory EndGroup Group WorkshopActors ObjectReference[] Property ActorsAll auto hidden EndGroup Group NWCP2 GlobalVariable Property pNWCP2_NPCSpawnState Auto Const Mandatory Message Property pNWCP2_NoWorkshopMsg Auto Const Mandatory Outfit Property NWCP2_CombatUniform01 Auto Const Mandatory ObjectReference Property NWCP2_TemporaryChest01 Auto Const Mandatory EndGroup ;-- Variables --------------------------------------- int WRFOAdj = 0 int TotalWRS = 0 ;-- Functions --------------------------------------- Function PotentialWorkObjects() ; ; This function identifies the number of available work objects ; within the settlement ; If (pNWCP2_NPCSpawnState.GetValue() == 0 as float) WorkshopScript workshopRef = GetLinkedRef(pWorkshopItemKeyword) as WorkshopScript If (workshopRef == None) Debug.Trace("NWCP2:NPCRequisitionScript.PotentialWorkObjects" +" ERROR NoWorkshop", 0) pNWCP2_NoWorkshopMsg.Show(0, 0, 0, 0, 0, 0, 0, 0, 0) Else ; Do lots of cool stuff here ; Set the global so it can only be run once pNWCP2_NPCSpawnState.SetValue(1 as float) ; Get all of the resources objects and then count the total amount ObjectReference[] PotentialFood = workshopRef.GetWorkshopResourceObjects(Food) Debug.Trace(self + "NWCP2: No of Workshop Resource Food Objects = " + PotentialFood.Length) ; Each NPC can farm six food so adjust the value WRFOAdj = PotentialFood.Length/6 Debug.Trace(self + "NWCP2: Adj No of Workshop Resource Food Objects = " + WRFOAdj) ObjectReference[] PotentialScavenge = workshopRef.GetWorkshopResourceObjects(WorkshopRatingScavengeGeneral) Debug.Trace(self + "NWCP2: No of Workshop Resource Scavenge Objects = " + PotentialScavenge.Length) ObjectReference[] PotentialDefense = workshopRef.GetWorkshopResourceObjects(Safety) Debug.Trace(self + "NWCP2: No of Workshop Resource Defense Objects = " + PotentialDefense.Length) ObjectReference[] PotentialStores = workshopRef.GetWorkshopResourceObjects(VendorIncome) Debug.Trace(self + "NWCP2: Workshop Resource Vendor Objects = " + PotentialStores.Length) TotalWRS = WRFOAdj + PotentialScavenge.Length + PotentialDefense.Length + PotentialStores.Length Debug.Trace(self + "NWCP2: Total Number of Workshop Resource Objects = " + TotalWRS) ; Call the function to requisition the required number of NPCs NPCRequisition(TotalWRS, workshopRef) ; Call the function to unassign all the workers DischargeNPCs(workshopRef) ; Call the funcrion to equip all of the NPCs with a select outfit and weapons EquipNPCs() ; Call the function to assign NPCs to workshop resource objects EmployNPCs(PotentialStores, PotentialDefense, PotentialScavenge, PotentialFood) EndIf EndIf EndFunction Function NPCRequisition(int NPCMaxCount, WorkshopScript workshopRef) ; ; This function requisition the necessary NPC to fill the available work objects ; int iCountNPCIndex = 0 While (iCountNPCIndex < NPCMaxCount) WorkshopParent.CreateActorPUBLIC(workshopRef) iCountNPCIndex += 1 Debug.Notification("A settler has been recruited for the Command Post") EndWhile EndFunction Function DischargeNPCs(WorkshopScript workshopRef) ; ; This function dischages all the NPCs from their current jobs ; ; Unassign all NPCs from their current jobs ActorsAll.Clear() ActorsAll = workshopRef.GetWorkshopResourceObjects(WorkshopParent.WorkshopRatingValues[2]) int j = 0 While j < ActorsAll.Length WorkshopNPCScript theNPC = ActorsAll[j] as WorkShopNPCScript theNPC.Enable(False) theNPC.SetValue(pWorkshopRatingPopulation, 1 as float) theNPC.SetValue(pWorkshopGuardPreference, 0 as float) (theNPC as workshopnpcscript).SetCommandable(True) (theNPC as workshopnpcscript).SetAllowCaravan(False) (theNPC as workshopnpcscript).SetAllowMove(False) WorkshopParent.UnassignActor(theNPC) ;Debug.Trace(self + "AssignJob: Unassigning " + theNPC) j += 1 EndWhile EndFunction Function EquipNPCs() ; ; This function equips all the NPCs with a select outfilt and weapons ; ; Equip all of our NPCs with a select outfit and gear int i = 0 Debug.Notification("The settlers are being equipped for service") while i < ActorsAll.Length WorkshopNPCScript theActor = ActorsAll[i] as WorkShopNPCScript ; Remove all items from the NPC's inventory theActor.RemoveAllItems() ; Add select items to the temporary container NWCP2_TemporaryChest01.AddItem(GaussRifle, 1, true) NWCP2_TemporaryChest01.AddItem(Ammo2mmEC, 5, true) NWCP2_TemporaryChest01.AddItem(Caps001, 100, true) NWCP2_TemporaryChest01.AddItem(Stimpak, 3, true) NWCP2_TemporaryChest01.RemoveAllItems(theActor, abKeepOwnership = false) theActor.EquipItem(GaussRifle, false, false) theActor.SetOutfit(NWCP2_CombatUniform01) i += 1 EndWhile EndFunction Function EmployNPCs(ObjectReference[] PotentialStores, ObjectReference[] PotentialDefense, ObjectReference[] PotentialScavenge, ObjectReference[] PotentialFood) ; ; This function assigns the NPCs to available work objects ; int ii = 0 int iii = 0 int jj = 0 int jjj = 0 int kk = 0 int kkk = 0 int mm = 0 int nn = 0 int WRS2 = PotentialStores.Length + PotentialDefense.Length int WRS3 = WRS2 + PotentialScavenge.Length ; Assign NPCs to vendor stations While ii < PotentialStores.Length ObjectReference theActor = ActorsAll[ii] ObjectReference theVendor = PotentialStores[ii] ;WorkshopScript.AssignActorToObjectPUBLIC(WorkshopNPCScript theActor, WorkshopObjectScript theVendor, false) (pWorkshopParent as workshopparentscript).AssignActorToObjectPUBLIC(theActor as workshopnpcscript, theVendor as workshopobjectscript, False) ii = ii + 1 EndWhile Debug.Notification(PotentialStores.Length + " settlers have been assigned to vendor stores") jj = ii While jj < WRS2 ObjectReference theActor = ActorsAll[jj] theActor.SetValue(pWorkshopGuardPreference, 1 as float) ObjectReference theDefender = PotentialDefense[iii] (pWorkshopParent as workshopparentscript).AssignActorToObjectPUBLIC(theActor as workshopnpcscript, theDefender as workshopobjectscript, False) jj = jj + 1 iii = iii + 1 EndWhile Debug.Notification(PotentialDefense.Length + " settlers have been assigned to guard stations") kk = jj While kk < WRS3 ObjectReference theActor = ActorsAll[kk] (theActor as workshopnpcscript).SetScavenger(true) ObjectReference theScavengeSta = PotentialScavenge[jjj] (pWorkshopParent as workshopparentscript).AssignActorToObjectPUBLIC(theActor as workshopnpcscript, theScavengeSta as workshopobjectscript, False) kk = kk + 1 jjj = jjj + 1 EndWhile Debug.Notification(PotentialScavenge.Length + " settlers have been assigned to scavenger stations") mm = kk While mm < ActorsAll.Length ObjectReference theActor = ActorsAll[mm] ObjectReference thePlant = PotentialFood[kkk] (pWorkshopParent as workshopparentscript).AssignActorToObjectPUBLIC(theActor as workshopnpcscript, thePlant as workshopobjectscript, False) mm = mm + 1 kkk = kkk + 6 Debug.Notification(PotentialScavenge.Length/6 + " settlers have been assigned to farming") EndWhile ii = 0 While ii < ActorsAll.Length ObjectReference theActor = ActorsAll[ii] (theActor as workshopnpcscript).EvaluatePackage() ii = ii + 1 EndWhile EndFunction Link to comment Share on other sites More sharing options...
SKKmods Posted January 11, 2022 Share Posted January 11, 2022 It may be the script call to unassign actors does not trigger the stats to update or recalculate. Add something line this; GlobalVariable Property pWorkshopCurrentWorkshopID Auto Const Mandatory If (pWorkshopCurrentWorkshopID.GetValue() == (ThisWorkshop as WorkshopScript).GetWorkshopID()) && ((pWorkshopParent as WorkshopParentScript).IsEditLocked() == FALSE) (pWorkshopParent as WorkshopParentScript).ResetWorkshop(ThisWorkshop as WorkshopScript) EndIf Link to comment Share on other sites More sharing options...
pepperman35 Posted January 11, 2022 Author Share Posted January 11, 2022 (edited) Ok SKK50, I shall give that a try. Much appreciated! BTW, when you master programmer us the prefix p and the like in front of properties (e.g., pWorkshopCurrentWorkshopID and pWorkshopParent) could you explain what the prefix mean/do? Edited January 11, 2022 by pepperman35 Link to comment Share on other sites More sharing options...
SKKmods Posted January 11, 2022 Share Posted January 11, 2022 The letter p reminds us it is an external property/pointer rather than a script variable. Its a standard in most of the (better quality) base game scripts. pPropertyiIntegerfFloatsString & etc Link to comment Share on other sites More sharing options...
pepperman35 Posted January 12, 2022 Author Share Posted January 12, 2022 (edited) Great, the solves that mystery. BTW, your ResetWorkshop seemed to do the trip. First, test showed the values one would expect. I'll run it a few more times, and in a few more checks and declare victory. Updated code as it currently stands. Scriptname NWCP2:NPCRequisitionScript extends ObjectReference ;-- Properties -------------------------------------- Group BaseGame WorkshopParentScript Property WorkshopParent Auto Const Mandatory Quest Property pWorkshopParent Auto Const mandatory Keyword Property pWorkshopItemKeyword Auto Const Mandatory ActorValue Property Food Auto Const Mandatory ActorValue Property WorkshopRatingScavengeGeneral Auto Const Mandatory ActorValue Property Safety Auto Const Mandatory ActorValue Property vendorIncome Auto Const Mandatory ActorValue Property pWorkshopRatingPopulation Auto Const mandatory ActorValue Property pWorkshopGuardPreference Auto Const mandatory Weapon Property GaussRifle Auto Const Mandatory Ammo Property Ammo2mmEC Auto Const Mandatory MiscObject Property Caps001 Auto Const Mandatory Potion Property Stimpak Auto Const Mandatory GlobalVariable Property pWorkshopCurrentWorkshopID Auto Const Mandatory EndGroup Group WorkshopActors ObjectReference[] Property ActorsAll auto hidden EndGroup Group NWCP2 GlobalVariable Property pNWCP2_NPCSpawnState Auto Const Mandatory Message Property pNWCP2_NoWorkshopMsg Auto Const Mandatory Outfit Property NWCP2_CombatUniform01 Auto Const Mandatory ObjectReference Property NWCP2_TemporaryChest01 Auto Const Mandatory EndGroup ;-- Variables --------------------------------------- int WRFOAdj = 0 int TotalWRS = 0 int FoodCounter = 0 int ScavengeCounter = 0 int DefenderCounter = 0 int VendorCounter = 0 ;-- Functions --------------------------------------- Function PotentialWorkObjects() ; ; This function identifies the number of available work objects ; within the settlement ; If (pNWCP2_NPCSpawnState.GetValue() == 0 as float) WorkshopScript workshopRef = GetLinkedRef(pWorkshopItemKeyword) as WorkshopScript If (workshopRef == None) Debug.Trace("NWCP2:NPCRequisitionScript.PotentialWorkObjects" +" ERROR NoWorkshop", 0) pNWCP2_NoWorkshopMsg.Show(0, 0, 0, 0, 0, 0, 0, 0, 0) Else ; Set the global so the script can only run once pNWCP2_NPCSpawnState.SetValue(1 as float) ; ; Get all of the resources objects and then count the total amount ; ObjectReference[] PotentialFood = workshopRef.GetWorkshopResourceObjects(Food) Debug.Trace(self + "NWCP2: No of Workshop Resource Food Objects = " + PotentialFood.Length) ; Each NPC can farm six food so adjust the value WRFOAdj = PotentialFood.Length/6 Debug.Trace(self + "NWCP2: Adj No of Workshop Resource Food Objects = " + WRFOAdj) ObjectReference[] PotentialScavenge = workshopRef.GetWorkshopResourceObjects(WorkshopRatingScavengeGeneral) Debug.Trace(self + "NWCP2: No of Workshop Resource Scavenge Objects = " + PotentialScavenge.Length) ObjectReference[] PotentialDefense = workshopRef.GetWorkshopResourceObjects(Safety) Debug.Trace(self + "NWCP2: No of Workshop Resource Defense Objects = " + PotentialDefense.Length) ObjectReference[] PotentialStores = workshopRef.GetWorkshopResourceObjects(VendorIncome) Debug.Trace(self + "NWCP2: Workshop Resource Vendor Objects = " + PotentialStores.Length) TotalWRS = WRFOAdj + PotentialScavenge.Length + PotentialDefense.Length + PotentialStores.Length Debug.Trace(self + "NWCP2: Total Number of Workshop Resource Objects = " + TotalWRS) ; ; Call the function to requisition the required number of NPCs ; NPCRequisition(TotalWRS, workshopRef) ; ; Call the function to unassign all the workers ; DischargeNPCs(workshopRef) ; ; Call the funcrion to equip all of the NPCs with a select outfit and weapons EquipNPCs() ; ; Call the function to assign NPCs to workshop resource objects ; EmployNPCs(PotentialStores, PotentialDefense, PotentialScavenge, PotentialFood) EndIf EndIf EndFunction Function NPCRequisition(int NPCMaxCount, WorkshopScript workshopRef) ; ; This function requisition the necessary NPC to fill the available work objects ; int iCountNPCIndex = 0 While (iCountNPCIndex < NPCMaxCount) Debug.Notification("Onboarding in-progress ... please wait") WorkshopParent.CreateActorPUBLIC(workshopRef) iCountNPCIndex += 1 Utility.Wait(1.0) Debug.Notification("A settler has been successfully recruited") EndWhile EndFunction Function DischargeNPCs(WorkshopScript workshopRef) ; ; This function dischages all the NPCs from their current jobs ; ; Unassign all NPCs from their current jobs ActorsAll.Clear() ActorsAll = workshopRef.GetWorkshopResourceObjects(WorkshopParent.WorkshopRatingValues[2]) int j = 0 While j < ActorsAll.Length WorkshopNPCScript theNPC = ActorsAll[j] as WorkShopNPCScript theNPC.Enable(False) theNPC.SetValue(pWorkshopRatingPopulation, 1 as float) theNPC.SetValue(pWorkshopGuardPreference, 0 as float) (theNPC as workshopnpcscript).SetCommandable(True) (theNPC as workshopnpcscript).SetAllowCaravan(False) (theNPC as workshopnpcscript).SetAllowMove(False) WorkshopParent.UnassignActor(theNPC) ;Debug.Trace(self + "AssignJob: Unassigning " + theNPC) j += 1 EndWhile If (pWorkshopCurrentWorkshopID.GetValue() == (workshopRef as WorkshopScript).GetWorkshopID()) && ((pWorkshopParent as WorkshopParentScript).IsEditLocked() == FALSE) (pWorkshopParent as WorkshopParentScript).ResetWorkshop(workshopRef as WorkshopScript) EndIf EndFunction Function EquipNPCs() ; ; This function equips all the NPCs with a select outfilt and weapons ; ; Equip all of our NPCs with a select outfit and gear int i = 0 while i < ActorsAll.Length WorkshopNPCScript theActor = ActorsAll[i] as WorkShopNPCScript ; Remove all items from the NPC's inventory theActor.RemoveAllItems() ; Add select items to the temporary container NWCP2_TemporaryChest01.AddItem(GaussRifle, 1, true) NWCP2_TemporaryChest01.AddItem(Ammo2mmEC, 5, true) NWCP2_TemporaryChest01.AddItem(Caps001, 100, true) NWCP2_TemporaryChest01.AddItem(Stimpak, 3, true) NWCP2_TemporaryChest01.RemoveAllItems(theActor, abKeepOwnership = false) theActor.EquipItem(GaussRifle, false, false) theActor.SetOutfit(NWCP2_CombatUniform01) i += 1 EndWhile Debug.Notification("All of the settlers have beed equipped for service") EndFunction Function EmployNPCs(ObjectReference[] PotentialStores, ObjectReference[] PotentialDefense, ObjectReference[] PotentialScavenge, ObjectReference[] PotentialFood) ; ; This function assigns the NPCs to available work objects ; int ii = 0 int iii = 0 int jj = 0 int jjj = 0 int kk = 0 int kkk = 0 int mm = 0 int nn = 0 int WRS2 = PotentialStores.Length + PotentialDefense.Length int WRS3 = WRS2 + PotentialScavenge.Length ; Assign NPCs to vendor stations While ii < PotentialStores.Length ObjectReference theActor = ActorsAll[ii] ObjectReference theVendor = PotentialStores[ii] ;WorkshopScript.AssignActorToObjectPUBLIC(WorkshopNPCScript theActor, WorkshopObjectScript theVendor, false) (pWorkshopParent as workshopparentscript).AssignActorToObjectPUBLIC(theActor as workshopnpcscript, theVendor as workshopobjectscript, False) ii = ii + 1 VendorCounter = VendorCounter + 1 EndWhile Debug.Notification(VendorCounter + " of the settlers have been assigned to vendor stores") jj = ii While jj < WRS2 ObjectReference theActor = ActorsAll[jj] theActor.SetValue(pWorkshopGuardPreference, 1 as float) ObjectReference theDefender = PotentialDefense[iii] (pWorkshopParent as workshopparentscript).AssignActorToObjectPUBLIC(theActor as workshopnpcscript, theDefender as workshopobjectscript, False) jj = jj + 1 iii = iii + 1 DefenderCounter = DefenderCounter + 1 Utility.Wait(1.0) EndWhile Debug.Notification(DefenderCounter + " of the settlers have been assigned to guard stations") kk = jj While kk < WRS3 ObjectReference theActor = ActorsAll[kk] (theActor as workshopnpcscript).SetScavenger(true) ObjectReference theScavengeSta = PotentialScavenge[jjj] (pWorkshopParent as workshopparentscript).AssignActorToObjectPUBLIC(theActor as workshopnpcscript, theScavengeSta as workshopobjectscript, False) kk = kk + 1 jjj = jjj + 1 ScavengeCounter = ScavengeCounter + 1 Utility.Wait(1.0) EndWhile Debug.Notification(ScavengeCounter + " of the settlers have been assigned to scavenging") mm = kk While mm < ActorsAll.Length ObjectReference theActor = ActorsAll[mm] ObjectReference thePlant = PotentialFood[kkk] (pWorkshopParent as workshopparentscript).AssignActorToObjectPUBLIC(theActor as workshopnpcscript, thePlant as workshopobjectscript, False) mm = mm + 1 kkk = kkk + 6 If kkk >= PotentialFood.Length kkk = PotentialFood.Length - 1 EndIf FoodCounter = FoodCounter + 1 EndWhile Debug.Notification(FoodCounter + " of the settlers have been assigned to farming") ; ; Evaluate packages on the NPCs ; ii = 0 While ii < ActorsAll.Length ObjectReference theActor = ActorsAll[ii] (theActor as workshopnpcscript).EvaluatePackage() ii = ii + 1 EndWhile EndFunction Edited January 12, 2022 by pepperman35 Link to comment Share on other sites More sharing options...
SKKmods Posted January 12, 2022 Share Posted January 12, 2022 If you would like to lean more about ResetWorkshop as the cause of many workshop resource issues read this https://www.nexusmods.com/fallout4/articles/2612 Link to comment Share on other sites More sharing options...
pepperman35 Posted January 12, 2022 Author Share Posted January 12, 2022 Thanks SKK50, that was a good informative read. Thanks for taking the time to write it and share. I saw the reset option in your workshop utilities but wasn't exactly sure what it did so didn't try it there. Now I am better informed. Link to comment Share on other sites More sharing options...
Recommended Posts