pepperman35 Posted February 24, 2023 Share Posted February 24, 2023 (edited) Okay so I wanted to try something a little different within my settlement…a terminal-based recruitment schema. For shits and giggles, I’ll call it the Intelligent Recruitment System (IRS) and it will be launched from a terminal of course. Now the IRS will perform the following: Count the number of workshop work objects within the settlement Since NPCs can farm more than one work object, the count gets adjusted based on the number of food-related work objects Recruit the necessary number of NPCs to fill the workshop work objects. An NPC would be recruited approximately every 15 game minutes (no one want to wait hours/days for the help to show up. Assign NPCs to the work objects Outfit the NPCs based on their assignment. For example, safety-related NPCS might get a nice set of armor and a good weapon. Vendor-related NPCs might get a suit if they are male, or a dress if they are female. Vendor-related NPCS would be given a modest stash of caps. Script isn’t finished but here is what I have to date. But I do have a question. As you can see I am using the (pWorkshopParent as workshopparentscript).CreateActorPUBLIC(ThisWorkshop as workshopscript) method, but is there a way to add addition controls to this. For example, ideally I’d like to have a 50-50 mix of male and female. I’d like for all of the NPC to be human, and I’d prefer there not to be any Synths in the mix. Not seeing an immediate way to amend the CreateActorPUBLIC to add these qualifiers so I wonder if I need to go another route such as SpawnMarker.PlaceAtMe(WorkshopNPCMale) or as SpawnMarker.PlaceAtMe(WorkshopNPCFemale). Thoughts welcome. Scriptname FO4:IntelligentRecruitmentSystemScript 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 FO4Mod GlobalVariable Property pFO4_NPCSpawnState Auto Const Mandatory GlobalVariable Property pFO4_TurretStatus Auto Const Mandatory Message Property pFO4_NoWorkshopMsg Auto Const Mandatory ;Outfit Property FO4_CombatUniform01 Auto Const Mandatory ;ObjectReference Property FO4_TemporaryChest01 Auto Const Mandatory ObjectReference Property pFO4_TurretsEnable Auto Const Mandatory EndGroup ;-- Variables --------------------------------------- int WRFOAdj = 0 int TotalWRS = 0 int FoodCounter = 0 int ScavengeCounter = 0 int DefenderCounter = 0 int VendorCounter = 0 int myCooldownTimerID = 10 ; Give our timer an ID we can remember ;-- Functions --------------------------------------- Function IntelligentRecruitment () ; This is the main function where all the work occurs ; If (pFO4_NPCSpawnState.GetValue() == 0 as float) ObjectReference ThisWorkshop = Self.GetLinkedRef(pWorkshopItemKeyword) If (ThisWorkshop == None) || ((ThisWorkshop as WorkshopScript).OwnedByPlayer == FALSE) Debug.Trace("FO4:IRSScript.IntelligentRecruitment" +" ERROR NoWorkshop", 0) pFO4_NoWorkshopMsg.Show(0, 0, 0, 0, 0, 0, 0, 0, 0) Else ; THe script hasn't been run before and the terminal is connected to the workshop so we ; can proceed ; Set the global so the script can only run once pFO4_NPCSpawnState.SetValue(1 as float) ; ; Determine the number of available workshop work objects ; Check and disable the turrets so they don't get counted If (pFO4_TurretStatus.GetValue() == 1 as float) pFO4_TurretsEnable.disable() EndIf ; ; Get all of the work resources objects and then count the total amount ; ObjectReference[] PotentialFood = ThisWorkshop.GetWorkshopResourceObjects(Food) Debug.MessageBox(self + "FO4: No of Workshop Resource Food Objects = " + PotentialFood.Length) ; Each NPC can farm six food so adjust the food value WRFOAdj = PotentialFood.Length/6 Debug.Trace(self + "FO4: Adj No of Workshop Resource Food Objects = " + WRFOAdj) ObjectReference[] PotentialScavenge = ThisWorkshop.GetWorkshopResourceObjects(WorkshopRatingScavengeGeneral) Debug.Trace(self + "FO4: No of Workshop Resource Scavenge Objects = " + PotentialScavenge.Length) ObjectReference[] PotentialDefense = ThisWorkshop.GetWorkshopResourceObjects(Safety) Debug.Trace(self + "FO4: No of Workshop Resource Defense Objects = " + PotentialDefense.Length) ObjectReference[] PotentialStores = ThisWorkshop.GetWorkshopResourceObjects(VendorIncome) Debug.Trace(self + "FO4: Workshop Resource Vendor Objects = " + PotentialStores.Length) TotalWRS = WRFOAdj + PotentialScavenge.Length + PotentialDefense.Length + PotentialStores.Length Debug.Trace(self + "FO4: Total Number of Workshop Resource Objects = " + TotalWRS) ; ; Call the function to recruit the required number of NPCs needed to fill work objects ; SettlerRecruitment(TotalWRS, ThisWorkshop) EndIf EndIf EndFunction Function SettlerRecruitment(int NPCMaxCount, ObjectReference ThisWorkshop) Debug.Trace("FO4:Function NPCRecruitment Called, Total # of Workshop Resource Objects = " + NPCMaxCount) ; ; This function recruits the necessary NPCs to fill the available work objects ; int iCountNPCIndex = 0 While (iCountNPCIndex < NPCMaxCount) (pWorkshopParent as workshopparentscript).CreateActorPUBLIC(ThisWorkshop as workshopscript) iCountNPCIndex += 1 Debug.Notification("Settler onboarding in-progress ... please wait") RecruitmentCooldown() EndWhile Debug.Notification("Settler onboarding is complete") EndFunction function RecruitmentCooldown() StartTimerGameTime(0.25, myCooldownTimerID) ; Create the timer with a 15 minute game-time duration endFunction Edited February 24, 2023 by pepperman35 Link to comment Share on other sites More sharing options...
niston Posted February 24, 2023 Share Posted February 24, 2023 One thing to keep in mind: WSFW allows to adjust the number of multiresource objects a settler can farm; I have mine set to 12 or 18 or whatever the max is.As for spawning settlers, you probably want to do whatever CreateActor() does, but draw from your own LLs instead of WorkshopNPC/WorkshopNPCGuard. Link to comment Share on other sites More sharing options...
pepperman35 Posted February 24, 2023 Author Share Posted February 24, 2023 Not used Workshop Framework but it is on my list to check out. Thanks for the reminder. Need to look at CreateActor() in more depth. Must not understand StartTimerGameTime either as I just tested the posted script and I am not seeing the dwell/pause at all. Link to comment Share on other sites More sharing options...
niston Posted February 24, 2023 Share Posted February 24, 2023 The scheme is that you start the timer with an interval, and when that interval has elapsed, the timer will raise an event. Utility.Wait() & co can be used to delay synchronous execution flow for a specific amount of real time (might have to calculate real time from gametime and timescale yourself tho).The alternative would be to restyle your code so that it supports event driven flow. So instead of a while loop you'd start the timer and wait for it's event.The event handler then creates one actor whenever it is invoked, before it restarts the timer. This repeats until NPCMaxCount actors have been created, in which case the timer is not being restarted. Link to comment Share on other sites More sharing options...
pepperman35 Posted February 25, 2023 Author Share Posted February 25, 2023 Yep, looks like it is back to the white board for me....baby steps. Link to comment Share on other sites More sharing options...
pepperman35 Posted February 25, 2023 Author Share Posted February 25, 2023 Okay, I think I got the event aspect sorted out. Next up, research into create actor () to ascertain how to get a 50-50 or 60-40 ratio of human female to male balance. Scriptname IntelligentRecruitmentSystemScript extends ObjectReference ;/Script designed to automatically recruit and assign NPCs to settlement workshop work objects. Script resides on a terminal and is designed to be run only once. /; ; ╔═════════════════════════════════════════════════╗ ; ║ 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 FO4Mod GlobalVariable Property pFO4_NPCSpawnState Auto Const Mandatory GlobalVariable Property pFO4_TurretStatus Auto Const Mandatory Message Property pFO4_NoWorkshopMsg Auto Const Mandatory ;Outfit Property FO4_CombatUniform01 Auto Const Mandatory ;ObjectReference Property FO4_TemporaryChest01 Auto Const Mandatory ObjectReference Property pFO4_TurretsEnable Auto Const Mandatory EndGroup ; ╔═════════════════════════════════════════════════╗ ; ║ Initialize Variables ║ ; ╚═════════════════════════════════════════════════╝ int WRFOAdj = 0 int TotalWRS = 0 int FoodCounter = 0 int ScavengeCounter = 0 int DefenderCounter = 0 int VendorCounter = 0 int iRecruitmentTimerID = 10 ; Give the recruitment timer an ID float fTimerDuration = 0.0625 ; the timer will have a 3.75 minute game-time duration int iCountNPCIndex = 0 int iNPCMaxCount = 0 ; ╔═════════════════════════════════════════════════╗ ; ║ Functions ║ ; ╚═════════════════════════════════════════════════╝ Function IntelligentRecruitment () ; This is the main function where all the work occurs ; If (pFO4_NPCSpawnState.GetValue() == 0 as float) ObjectReference ThisWorkshop = Self.GetLinkedRef(pWorkshopItemKeyword) If (ThisWorkshop == None) || ((ThisWorkshop as WorkshopScript).OwnedByPlayer == FALSE) Debug.Trace("FO4:IRSScript.IntelligentRecruitment" +" ERROR NoWorkshop", 0) pFO4_NoWorkshopMsg.Show(0, 0, 0, 0, 0, 0, 0, 0, 0) Else ; The script hasn't been run before and the terminal is connected to the workshop so we ; can proceed ; Set the global so the script can only run once pFO4_NPCSpawnState.SetValue(1 as float) ; ; Call function to determine the number of available workshop work objects ; WorkResources (ThisWorkshop) Debug.MessageBox("This settlement has " + TotalWRS + "work objects") Debug.Trace(self + "FO4: IRSScript Total Number of Workshop Resource Objects = " + TotalWRS) ; ; Call the function to start the recruitment process and recruit the required number of NPCs ; iNPCMaxCount = TotalWRS StartupRecruitment(ThisWorkshop) EndIf EndIf EndFunction Function WorkResources (ObjectReference ThisWorkshop) ; This function serves to determine how many work objects are available throughout the settlement ; Check and disable the turrets so they don't get counted If (pFO4_TurretStatus.GetValue() == 1 as float) pFO4_TurretsEnable.disable() EndIf ; ; Get all of the work resources objects and then count the total amount ; ObjectReference[] PotentialFood = ThisWorkshop.GetWorkshopResourceObjects(Food) Debug.MessageBox(self + "FO4: No of Workshop Resource Food Objects = " + PotentialFood.Length) ; Each NPC can farm six food so adjust the food value WRFOAdj = PotentialFood.Length/6 Debug.Trace(self + "FO4: Adj No of Workshop Resource Food Objects = " + WRFOAdj) ObjectReference[] PotentialScavenge = ThisWorkshop.GetWorkshopResourceObjects(WorkshopRatingScavengeGeneral) Debug.Trace(self + "FO4: No of Workshop Resource Scavenge Objects = " + PotentialScavenge.Length) ObjectReference[] PotentialDefense = ThisWorkshop.GetWorkshopResourceObjects(Safety) Debug.Trace(self + "FO4: No of Workshop Resource Defense Objects = " + PotentialDefense.Length) ObjectReference[] PotentialStores = ThisWorkshop.GetWorkshopResourceObjects(VendorIncome) Debug.Trace(self + "FO4: Workshop Resource Vendor Objects = " + PotentialStores.Length) TotalWRS = WRFOAdj + PotentialScavenge.Length + PotentialDefense.Length + PotentialStores.Length Debug.Trace(self + "FO4: Total Number of Workshop Resource Objects = " + TotalWRS) Debug.MessageBox("Work Resources function has fired.") EndFunction Function StartupRecruitment(ObjectReference ThisWorkshop) StartTimerGameTime(fTimerDuration, iRecruitmentTimerID) ; Create the timer with a specified game-time duration EndFunction ; ╔═════════════════════════════════════════════════╗ ; ║ Events ║ ; ╚═════════════════════════════════════════════════╝ Event OnTimerGameTime(int aiTimerID) If (aiTimerID == iRecruitmentTimerID) && (iCountNPCIndex < iNPCMaxCount) ObjectReference ThisWorkshop = Self.GetLinkedRef(pWorkshopItemKeyword) iCountNPCIndex = iCountNPCIndex + 1 Debug.Notification("Recruiting setter # " + iCountNPCIndex + ", Onboarding in-progress ... please wait") (pWorkshopParent as workshopparentscript).CreateActorPUBLIC(ThisWorkshop as workshopscript) ; Has the desired number of NPCs been recruited. If not, start the do StartTimerGameTime again... If (iCountNPCIndex < iNPCMaxCount) StartTimerGameTime(fTimerDuration, iRecruitmentTimerID) Else Utility.Wait(5) Debug.Notification("Settler onboarding is now complete") EndIf EndIf EndEvent Link to comment Share on other sites More sharing options...
pepperman35 Posted February 26, 2023 Author Share Posted February 26, 2023 A bit more progress made. The script now will try give you a 50-50 ratio of male to female npcs. So far so good/ Scriptname IntelligentRecruitmentSystemScript extends ObjectReference ;/Script designed to automatically recruit and assign NPCs to settlement workshop work objects. Script resides on a terminal and is designed to be run only once. /; ; ╔═════════════════════════════════════════════════╗ ; ║ Properties ║ ; ╚═════════════════════════════════════════════════╝ Group BaseGame WorkshopParentScript Property WorkshopParent Auto Const Mandatory Quest Property pWorkshopParent Auto Const mandatory Keyword Property pWorkshopItemKeyword Auto Const Mandatory Keyword Property pWorkshopLinkSpawn 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 ActorBase property FO4_WorkshopNPCFemaleHuman Auto Mandatory ActorBase property FO4_WorkshopNPCMaleHuman Auto Mandatory EndGroup Group FO4Mod GlobalVariable Property pFO4_NPCSpawnState Auto Const Mandatory GlobalVariable Property pFO4_TurretStatus Auto Const Mandatory Message Property pFO4_NoWorkshopMsg Auto Const Mandatory ;Outfit Property FO4_CombatUniform01 Auto Const Mandatory ;ObjectReference Property FO4_TemporaryChest01 Auto Const Mandatory ObjectReference Property pFO4_TurretsEnable Auto Const Mandatory ObjectReference Property pBartonville_SpawnMarker Auto Const Mandatory EndGroup ; ╔═════════════════════════════════════════════════╗ ; ║ Initialize Variables ║ ; ╚═════════════════════════════════════════════════╝ int WRFOAdj = 0 int TotalWRS = 0 int FoodCounter = 0 int ScavengeCounter = 0 int DefenderCounter = 0 int VendorCounter = 0 int iRecruitmentTimerID = 10 ; Give the recruitment timer an ID float fTimerDuration = 0.0625 ; the timer will have a 3.75 minute game-time duration int iCountNPCIndex = 0 int iNPCMaxCount = 0 int iMaleNPCCount = 0 int iFemaleNPCCount = 0 ; ╔═════════════════════════════════════════════════╗ ; ║ Functions ║ ; ╚═════════════════════════════════════════════════╝ Function IntelligentRecruitment () ; This is the main function where all the work occurs ; If (pFO4_NPCSpawnState.GetValue() == 0 as float) ObjectReference ThisWorkshop = Self.GetLinkedRef(pWorkshopItemKeyword) If (ThisWorkshop == None) || ((ThisWorkshop as WorkshopScript).OwnedByPlayer == FALSE) Debug.Trace("FO4:IRSScript.IntelligentRecruitment" +" ERROR NoWorkshop", 0) pFO4_NoWorkshopMsg.Show(0, 0, 0, 0, 0, 0, 0, 0, 0) Else ; The script hasn't been run before and the terminal is connected to the workshop so we ; can proceed ; Set the global so the script can only run once pFO4_NPCSpawnState.SetValue(1 as float) ; ; Call function to determine the number of available workshop work objects ; WorkResources (ThisWorkshop) Debug.MessageBox("This settlement has " + TotalWRS + "work objects") Debug.Trace(self + "FO4: IRSScript Total Number of Workshop Resource Objects = " + TotalWRS) ; ; Call the function to start the recruitment process and recruit the required number of NPCs ; iNPCMaxCount = TotalWRS StartupRecruitment(ThisWorkshop) EndIf EndIf EndFunction Function WorkResources (ObjectReference ThisWorkshop) ; This function serves to determine how many work objects are available throughout the settlement ; Check and disable the turrets so they don't get counted If (pFO4_TurretStatus.GetValue() == 1 as float) pFO4_TurretsEnable.disable() EndIf ; ; Get all of the work resources objects and then count the total amount ; ObjectReference[] PotentialFood = ThisWorkshop.GetWorkshopResourceObjects(Food) Debug.MessageBox(self + "FO4: No of Workshop Resource Food Objects = " + PotentialFood.Length) ; Each NPC can farm six food so adjust the food value WRFOAdj = PotentialFood.Length/6 Debug.Trace(self + "FO4: Adj No of Workshop Resource Food Objects = " + WRFOAdj) ObjectReference[] PotentialScavenge = ThisWorkshop.GetWorkshopResourceObjects(WorkshopRatingScavengeGeneral) Debug.Trace(self + "FO4: No of Workshop Resource Scavenge Objects = " + PotentialScavenge.Length) ObjectReference[] PotentialDefense = ThisWorkshop.GetWorkshopResourceObjects(Safety) Debug.Trace(self + "FO4: No of Workshop Resource Defense Objects = " + PotentialDefense.Length) ObjectReference[] PotentialStores = ThisWorkshop.GetWorkshopResourceObjects(VendorIncome) Debug.Trace(self + "FO4: Workshop Resource Vendor Objects = " + PotentialStores.Length) TotalWRS = WRFOAdj + PotentialScavenge.Length + PotentialDefense.Length + PotentialStores.Length Debug.Trace(self + "FO4: Total Number of Workshop Resource Objects = " + TotalWRS) Debug.MessageBox("Work Resources function has fired.") EndFunction Function StartupRecruitment(ObjectReference ThisWorkshop) StartTimerGameTime(fTimerDuration, iRecruitmentTimerID) ; Create the timer with a specified game-time duration EndFunction ; ╔═════════════════════════════════════════════════╗ ; ║ Events ║ ; ╚═════════════════════════════════════════════════╝ Event OnTimerGameTime(int aiTimerID) If (aiTimerID == iRecruitmentTimerID) && (iCountNPCIndex < iNPCMaxCount) ObjectReference ThisWorkshop = Self.GetLinkedRef(pWorkshopItemKeyword) ; ObjectReference SpawnMarker = ThisWorkshop.GetLinkedRef(pWorkshopParent.pWorkshopLinkSpawn) iCountNPCIndex = iCountNPCIndex + 1 Debug.Notification("Recruiting setter # " + iCountNPCIndex + ", Onboarding in-progress ... please wait") If (iCountNPCIndex % 2) == 0 ; Debug.Notification("The number " + iCountNPCIndex + " is even") ; Spawn in a new male settler Actor newActor = pBartonville_SpawnMarker.PlaceAtMe(FO4_WorkshopNPCMaleHuman, abDeleteWhenAble = false) as Actor iMaleNPCCount = iMaleNPCCount + 1 WorkshopNPCScript newWorkshopActor = newActor as WorkShopNPCScript newWorkshopActor.bNewSettler = true (pWorkshopParent as WorkshopParentScript).AddActorToWorkshopPUBLIC((newWorkshopActor as WorkshopNPCScript), (ThisWorkshop as WorkshopScript)) ; try to automatically assign new NPC to do something (pWorkshopParent as WorkshopParentScript).TryToAutoAssignActor((ThisWorkshop as WorkshopScript), (newWorkshopActor as WorkshopNPCScript)) Else ; Debug.Notification("The number " + iCountNPCIndex + " is odd") ; Spawn in a new female settler Actor newActor = pBartonville_SpawnMarker.PlaceAtMe(FO4_WorkshopNPCFemaleHuman, abDeleteWhenAble = false) as Actor iFemaleNPCCount = iFemaleNPCCount + 1 WorkshopNPCScript newWorkshopActor = newActor as WorkShopNPCScript newWorkshopActor.bNewSettler = true (pWorkshopParent as WorkshopParentScript).AddActorToWorkshopPUBLIC((newWorkshopActor as WorkshopNPCScript), (ThisWorkshop as WorkshopScript)) ; try to automatically assign new NPC to do something (pWorkshopParent as WorkshopParentScript).TryToAutoAssignActor((ThisWorkshop as WorkshopScript), (newWorkshopActor as WorkshopNPCScript)) EndIf ;(pWorkshopParent as workshopparentscript).CreateActorPUBLIC(ThisWorkshop as workshopscript) ; Has the desired number of NPCs been recruited. If not, start the do StartTimerGameTime again... If (iCountNPCIndex < iNPCMaxCount) StartTimerGameTime(fTimerDuration, iRecruitmentTimerID) Else Utility.Wait(5) Debug.Notification("Settler onboarding is now complete") Debug.Notification("The number of male NPCs recruited is " + iMaleNPCCount) Debug.Notification("The number of female NPCs recruited is " + iFemaleNPCCount) EndIf EndIf EndEvent Link to comment Share on other sites More sharing options...
pepperman35 Posted February 28, 2023 Author Share Posted February 28, 2023 Okay, I seem to have hit a snag trying to assign npcs to worksop work object. I trying to get the Function AssignActorToWorkObject() to accomplish this but it doesn’t seem to be working. To keep it simple for tested I limited the function to the assignment of npcs to vendor work objects. The vendors get a designed outfit but do not appear to get assigned. Insight would be appreciated. Scriptname FO4:IntelligentRecruitmentSystemScript extends ObjectReference ;/Script designed to automatically recruit and assign NPCs to settlement workshop work objects. Script resides on a terminal and is designed to be run only once. /; ; ╔═════════════════════════════════════════════════╗ ; ║ Properties ║ ; ╚═════════════════════════════════════════════════╝ Group BaseGame WorkshopParentScript Property WorkshopParent Auto Const Mandatory Quest Property pWorkshopParent Auto Const mandatory Keyword Property pWorkshopItemKeyword Auto Const Mandatory Keyword Property pWorkshopLinkSpawn 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 FO4Mod GlobalVariable Property pFO4_NPCSpawnState Auto Const Mandatory GlobalVariable Property pFO4_TurretStatus Auto Const Mandatory Message Property pFO4_NoWorkshopMsg Auto Const Mandatory Outfit Property FO4_CombatUniform01 Auto Const Mandatory ObjectReference Property FO4_TemporaryChest01 Auto Const Mandatory ObjectReference Property pFO4_TurretsEnable Auto Const Mandatory ActorBase property FO4_WorkshopNPCFemaleHuman Auto Mandatory ActorBase property FO4_WorkshopNPCMaleHuman Auto Mandatory EndGroup ; ╔═════════════════════════════════════════════════╗ ; ║ Initialize Variables ║ ; ╚═════════════════════════════════════════════════╝ int WRFOAdj = 0 int TotalWRS = 0 int FoodCounter = 0 int ScavengeCounter = 0 int DefenderCounter = 0 int VendorCounter = 0 int iRecruitmentTimerID = 10 ; Give the recruitment timer an ID float fTimerDuration = 0.0625 ; the timer will have a 3.75 minute game-time duration int iCountNPCIndex = 0 int iNPCMaxCount = 0 int iMaleNPCCount = 0 int iFemaleNPCCount = 0 ObjectReference[] PotentialFood ObjectReference[] PotentialScavenge ObjectReference[] PotentialDefense ObjectReference[] PotentialStores ; ╔═════════════════════════════════════════════════╗ ; ║ Functions ║ ; ╚═════════════════════════════════════════════════╝ Function IntelligentRecruitment () ; This is the main function where all the work occurs ; If (pFO4_NPCSpawnState.GetValue() == 0 as float) ObjectReference ThisWorkshop = Self.GetLinkedRef(pWorkshopItemKeyword) If (ThisWorkshop == None) || ((ThisWorkshop as WorkshopScript).OwnedByPlayer == FALSE) Debug.Trace("FO4:IRSScript.IntelligentRecruitment" +" ERROR NoWorkshop", 0) pFO4_NoWorkshopMsg.Show(0, 0, 0, 0, 0, 0, 0, 0, 0) Else ; The script hasn't been run before and the terminal is connected to the workshop so we ; can proceed ; Set the global so the script can only run once pFO4_NPCSpawnState.SetValue(1 as float) ; ; Call function to determine the number of available workshop work objects ; WorkResources (ThisWorkshop) Debug.MessageBox("This settlement has " + TotalWRS + "work objects") Debug.Trace(self + "FO4: IRSScript Total Number of Workshop Resource Objects = " + TotalWRS) ; ; Call the function to start the recruitment process and recruit the required number of NPCs ; iNPCMaxCount = TotalWRS StartupRecruitment(ThisWorkshop) EndIf EndIf EndFunction Function WorkResources (ObjectReference ThisWorkshop) ; This function serves to determine how many work objects are available throughout the settlement ; Check and disable the turrets so they don't get counted If (pFO4_TurretStatus.GetValue() == 1 as float) pFO4_TurretsEnable.disable() EndIf ; ; Get all of the work resources objects and then count the total amount ; PotentialFood = ThisWorkshop.GetWorkshopResourceObjects(Food) Debug.MessageBox(self + "FO4: No of Workshop Resource Food Objects = " + PotentialFood.Length) ; Each NPC can farm six food so adjust the food value WRFOAdj = PotentialFood.Length/6 Debug.Trace(self + "FO4: Adj No of Workshop Resource Food Objects = " + WRFOAdj) PotentialScavenge = ThisWorkshop.GetWorkshopResourceObjects(WorkshopRatingScavengeGeneral) Debug.Trace(self + "FO4: No of Workshop Resource Scavenge Objects = " + PotentialScavenge.Length) PotentialDefense = ThisWorkshop.GetWorkshopResourceObjects(Safety) Debug.Trace(self + "FO4: No of Workshop Resource Defense Objects = " + PotentialDefense.Length) PotentialStores = ThisWorkshop.GetWorkshopResourceObjects(VendorIncome) Debug.Trace(self + "FO4: Workshop Resource Vendor Objects = " + PotentialStores.Length) TotalWRS = WRFOAdj + PotentialScavenge.Length + PotentialDefense.Length + PotentialStores.Length Debug.Trace(self + "FO4: Total Number of Workshop Resource Objects = " + TotalWRS) Debug.MessageBox("Work Resources function has fired.") EndFunction Function DischargeNPCs(ObjectReference ThisWorkshop) ; ; This function dischages all the NPCs from their current jobs ; Debug.MessageBox("DischargeNPCs Function has been called") ; Unassign all NPCs from their current jobs ActorsAll.Clear() ActorsAll = ThisWorkshop.GetWorkshopResourceObjects(WorkshopParent.WorkshopRatingValues[2]) Debug.Trace("FO4:Function DischargeNPCs, Total # of Workshop Resource Objects = " + ActorsAll.Length) Debug.MessageBox("We have this many actors assigned to the workshop " + ActorsAll.Length) 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() == (ThisWorkshop as WorkshopScript).GetWorkshopID()) && ((pWorkshopParent as WorkshopParentScript).IsEditLocked() == FALSE) (pWorkshopParent as WorkshopParentScript).ResetWorkshop(ThisWorkshop as WorkshopScript) EndIf Debug.MessageBox("All actors have now be unassigned") EndFunction ; This function assigns jobs Function AssignActorToWorkObject() Debug.MessageBox("Ready to assign NPCs to vendor stations") int ii = 0 ; Assign NPCs to vendor stations Debug.Notification("The length of the potential stores array is " + PotentialStores.Length) While ii < PotentialStores.Length WorkshopNPCScript theActor = ActorsAll[ii] as WorkShopNPCScript ObjectReference theVendorStore = PotentialStores[ii] If (theVendorStore != None) && (theVendorStore is WorkshopObjectScript) && ((theVendorStore as WorkshopObjectScript).IsActorAssigned() == FALSE) Debug.Notification("The vendor test has passed so we are proceeding") theActor.RemoveAllItems() ; Add select items to the temporary container FO4_TemporaryChest01.AddItem(GaussRifle, 1, true) FO4_TemporaryChest01.AddItem(Ammo2mmEC, 5, true) FO4_TemporaryChest01.AddItem(Caps001, 100, true) FO4_TemporaryChest01.AddItem(Stimpak, 3, true) FO4_TemporaryChest01.RemoveAllItems(theActor, abKeepOwnership = false) theActor.EquipItem(GaussRifle, false, false) theActor.EquipItem(Ammo2mmEC, false, false) theActor.SetOutfit(FO4_CombatUniform01) (pWorkshopParent as WorkshopParentScript).AssignActorToObjectPUBLIC((theActor as WorkshopNPCScript), (theVendorStore as WorkshopObjectScript), bResetMode = false) Else Debug.Notification("The vendor test has failed so we are not able to assign npc") EndIf ii = ii + 1 VendorCounter = VendorCounter + 1 EndWhile Debug.MessageBox(VendorCounter + " of the settlers have been assigned to vendor stores") EndFunction Function StartupRecruitment(ObjectReference ThisWorkshop) StartTimerGameTime(fTimerDuration, iRecruitmentTimerID) ; Create the timer with a specified game-time duration EndFunction ; ╔═════════════════════════════════════════════════╗ ; ║ Events ║ ; ╚═════════════════════════════════════════════════╝ Event OnTimerGameTime(int aiTimerID) If (aiTimerID == iRecruitmentTimerID) && (iCountNPCIndex < iNPCMaxCount) ObjectReference ThisWorkshop = Self.GetLinkedRef(pWorkshopItemKeyword) ObjectReference SpawnMarker = ThisWorkshop.GetLinkedRef(pWorkshopLinkSpawn) iCountNPCIndex = iCountNPCIndex + 1 Debug.Notification("Recruiting setter # " + iCountNPCIndex + ", Onboarding in-progress ... please wait") If (iCountNPCIndex % 2) == 0 ; Debug.Notification("The number " + iCountNPCIndex + " is even") ; Spawn in a new male settler Actor newActor = SpawnMarker.PlaceAtMe(FO4_WorkshopNPCMaleHuman, abDeleteWhenAble = false) as Actor iMaleNPCCount = iMaleNPCCount + 1 WorkshopNPCScript newWorkshopActor = newActor as WorkShopNPCScript ActorsAll.Add(newWorkshopActor) newWorkshopActor.bNewSettler = true (pWorkshopParent as WorkshopParentScript).AddActorToWorkshopPUBLIC((newWorkshopActor as WorkshopNPCScript), (ThisWorkshop as WorkshopScript)) ; try to automatically assign new NPC to do something (pWorkshopParent as WorkshopParentScript).TryToAutoAssignActor((ThisWorkshop as WorkshopScript), (newWorkshopActor as WorkshopNPCScript)) Else ; Debug.Notification("The number " + iCountNPCIndex + " is odd") ; Spawn in a new female settler Actor newActor = SpawnMarker.PlaceAtMe(FO4_WorkshopNPCFemaleHuman, abDeleteWhenAble = false) as Actor iFemaleNPCCount = iFemaleNPCCount + 1 WorkshopNPCScript newWorkshopActor = newActor as WorkShopNPCScript ActorsAll.Add(newWorkshopActor) newWorkshopActor.bNewSettler = true (pWorkshopParent as WorkshopParentScript).AddActorToWorkshopPUBLIC((newWorkshopActor as WorkshopNPCScript), (ThisWorkshop as WorkshopScript)) ; try to automatically assign new NPC to do something (pWorkshopParent as WorkshopParentScript).TryToAutoAssignActor((ThisWorkshop as WorkshopScript), (newWorkshopActor as WorkshopNPCScript)) EndIf ;(pWorkshopParent as workshopparentscript).CreateActorPUBLIC(ThisWorkshop as workshopscript) ; Has the desired number of NPCs been recruited. If not, start the do StartTimerGameTime again... If (iCountNPCIndex < iNPCMaxCount) StartTimerGameTime(fTimerDuration, iRecruitmentTimerID) Else Utility.Wait(5) Debug.Notification("Settler onboarding is now complete") Utility.Wait(5) Debug.Notification("The number of male NPCs recruited is " + iMaleNPCCount) Utility.Wait(5) Debug.Notification("The number of female NPCs recruited is " + iFemaleNPCCount) Utility.Wait(5) ; ; ; Call the discharge function to unassign all the workers from workshop objects ; because we want to start with a clean slate ; DischargeNPCs(ThisWorkshop) ; AssignActorToWorkObject() EndIf EndIf EndEvent Link to comment Share on other sites More sharing options...
pepperman35 Posted March 1, 2023 Author Share Posted March 1, 2023 While I am sure the script could be improved, I believe the final version accomplishes the design goals. So basically it counts the settlements work objects, recruits roughly 1-1 ratio of male and female NPCs, and outfits all the settles with a core loadout. Settlers are then assigned to the workshop workobjects and given an outfit based on function (merchant, guard, scavenger, or farmer). All in all, I am pleased with the results, and I got to try out and learn a few new scripting tidbits (e.g., 1-1 ration business, gender testing, etc). Scriptname Bart:IntelligentRecruitmentSystemScript extends ObjectReference ;/Script designed to automatically recruit and assign NPCs to settlement workshop work objects. Script resides on a terminal and is designed to be run only once. /; ; ╔═════════════════════════════════════════════════╗ ; ║ Properties ║ ; ╚═════════════════════════════════════════════════╝ Group BaseGame WorkshopParentScript Property WorkshopParent Auto Const Mandatory Quest Property pWorkshopParent Auto Const mandatory Keyword Property pWorkshopItemKeyword Auto Const Mandatory Keyword Property pWorkshopLinkSpawn 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 FO4Mod GlobalVariable Property pFO4_NPCSpawnState Auto Const Mandatory GlobalVariable Property pFO4_TurretStatus Auto Const Mandatory Message Property pFO4_NoWorkshopMsg Auto Const Mandatory Outfit Property FO4_CombatUniform01 Auto Const Mandatory Outfit Property FO4_MaleVendorUniform Auto Const Mandatory Outfit Property FO4_FemaleVendorUniform Auto Const Mandatory Outfit Property FO4_FarmingOutfit Auto Const Mandatory Outfit Property FO4_ScavOutfit Auto Const Mandatory Outfit Property FO4_DoctorUniform Auto Const Mandatory ObjectReference Property FO4_TemporaryChest01 Auto Const Mandatory ObjectReference Property pFO4_TurretsEnable Auto Const Mandatory ActorBase property FO4_WorkshopNPCFemaleHuman Auto Mandatory ActorBase property FO4_WorkshopNPCMaleHuman Auto Mandatory EndGroup ; ╔═════════════════════════════════════════════════╗ ; ║ Initialize Variables ║ ; ╚═════════════════════════════════════════════════╝ int WRFOAdj = 0 int TotalWRS = 0 int FoodCounter = 0 int ScavengeCounter = 0 int DefenderCounter = 0 int VendorCounter = 0 int iRecruitmentTimerID = 10 ; Give the recruitment timer an ID float fTimerDuration = 0.0625 ; the timer will have a 3.75 minute game-time duration int iCountNPCIndex = 0 int iNPCMaxCount = 0 int iMaleNPCCount = 0 int iFemaleNPCCount = 0 ObjectReference[] PotentialFood ObjectReference[] PotentialScavenge ObjectReference[] PotentialDefense ObjectReference[] PotentialStores ; ╔═════════════════════════════════════════════════╗ ; ║ Functions ║ ; ╚═════════════════════════════════════════════════╝ Function IntelligentRecruitment () ; This is the main function where all the work occurs ; If (pFO4_NPCSpawnState.GetValue() == 0 as float) ObjectReference ThisWorkshop = Self.GetLinkedRef(pWorkshopItemKeyword) If (ThisWorkshop == None) || ((ThisWorkshop as WorkshopScript).OwnedByPlayer == FALSE) Debug.Trace("FO4:IRSScript.IntelligentRecruitment" +" ERROR NoWorkshop", 0) pFO4_NoWorkshopMsg.Show(0, 0, 0, 0, 0, 0, 0, 0, 0) Else ; The script hasn't been run before and the terminal is connected to the workshop so we ; can proceed ; Set the global so the script can only run once pFO4_NPCSpawnState.SetValue(1 as float) ; ; Call function to determine the number of available workshop work objects ; WorkResources (ThisWorkshop) ; Debug.MessageBox("This settlement has " + TotalWRS + "work objects") Debug.Trace(self + "FO4: IRSScript Total Number of Workshop Resource Objects = " + TotalWRS) ; ; Call the function to start the recruitment process and recruit the required number of NPCs ; iNPCMaxCount = TotalWRS StartupRecruitment(ThisWorkshop) EndIf EndIf EndFunction Function WorkResources (ObjectReference ThisWorkshop) ; This function serves to determine how many work objects are available throughout the settlement ; Check and disable the turrets so they don't get counted If (pFO4_TurretStatus.GetValue() == 1 as float) pFO4_TurretsEnable.disable() EndIf ; ; Get all of the work resources objects and then count the total amount ; PotentialFood = ThisWorkshop.GetWorkshopResourceObjects(Food) Debug.Trace(self + "FO4: No of Workshop Resource Food Objects = " + PotentialFood.Length) ; Each NPC can farm six food so adjust the food value WRFOAdj = PotentialFood.Length/6 Debug.Trace(self + "FO4: Adj No of Workshop Resource Food Objects = " + WRFOAdj) PotentialScavenge = ThisWorkshop.GetWorkshopResourceObjects(WorkshopRatingScavengeGeneral) Debug.Trace(self + "FO4: No of Workshop Resource Scavenge Objects = " + PotentialScavenge.Length) PotentialDefense = ThisWorkshop.GetWorkshopResourceObjects(Safety) Debug.Trace(self + "FO4: No of Workshop Resource Defense Objects = " + PotentialDefense.Length) PotentialStores = ThisWorkshop.GetWorkshopResourceObjects(VendorIncome) Debug.Trace(self + "FO4: Workshop Resource Vendor Objects = " + PotentialStores.Length) TotalWRS = WRFOAdj + PotentialScavenge.Length + PotentialDefense.Length + PotentialStores.Length Debug.Trace(self + "FO4: Total Number of Workshop Resource Objects = " + TotalWRS) Debug.Trace("Work Resources function has fired.") EndFunction Function DischargeNPCs(ObjectReference ThisWorkshop) ; ; This function dischages all the NPCs from their current jobs ; ; Debug.Trace("IntelligentRecruitmentSystemScript DischargeNPCs Function has been called") ; Unassign all NPCs from their current jobs ActorsAll.Clear() ActorsAll = ThisWorkshop.GetWorkshopResourceObjects(WorkshopParent.WorkshopRatingValues[2]) Debug.Trace("FO4:Function DischargeNPCs, Total # of Workshop Resource Objects = " + ActorsAll.Length) ; Debug.Trace("We have this many actors assigned to the workshop " + ActorsAll.Length) 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 Utility.Wait(0.5) Debug.Notification("Processing settler's paperwork ... please standby") EndWhile Utility.Wait(1) Debug.Notification("The recruitment phase has completed") Utility.Wait(1) ;If (pWorkshopCurrentWorkshopID.GetValue() == (ThisWorkshop as WorkshopScript).GetWorkshopID()) && ((pWorkshopParent as WorkshopParentScript).IsEditLocked() == FALSE) Debug.MessageBox("The IRS will now deploy a deep neural network to analyze the settlement. This process could take several minutes") Debug.Notification("Settlement analysis underway ... please standby") (pWorkshopParent as WorkshopParentScript).ResetWorkshop(ThisWorkshop as WorkshopScript) Debug.Notification("Settlement analysis completed") ;EndIf ; Debug.Trace("IntelligentRecruitmentSystemScript - All actors have now be unassigned from work objects") EndFunction ; This function assigns jobs Function AssignActorToWorkObject() Debug.Notification("Beginning employment phase ... please standby") 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 int iVendorType ; Assign NPCs to vendor stations ; Debug.Trace("The length of the potential stores array is " + PotentialStores.Length) Debug.Notification("The IRS is outfitting and employing the merchants") While ii < PotentialStores.Length ObjectReference theActor = ActorsAll[ii] ObjectReference theVendorStore = PotentialStores[ii] iVendorType = (theVendorStore as WorkshopObjectScript).VendorType If (theVendorStore != None) && (theVendorStore is WorkshopObjectScript) && ((theVendorStore as WorkshopObjectScript).IsActorAssigned() == FALSE) ; Debug.Trace("The vendor test has passed so we are proceeding") (theActor as WorkshopNPCScript).RemoveAllItems() if ((theActor as WorkshopNPCScript).GetLeveledActorBase().GetSex() == 0) ; ; Call the function to outfit the settlers with a common loadout ; OutfitSettlers(theActor) ; ; Add an approproiate outfit for male actor ; (theActor as WorkshopNPCScript).SetOutfit(FO4_MaleVendorUniform) (pWorkshopParent as WorkshopParentScript).AssignActorToObjectPUBLIC((theActor as WorkshopNPCScript), (theVendorStore as WorkshopObjectScript), False) Else ; ; Call the function to outfit the settlers with a common loadout ; OutfitSettlers(theActor) ; ; Add an approproiate outfit for male actor ; (theActor as WorkshopNPCScript).SetOutfit(FO4_FemaleVendorUniform) (pWorkshopParent as WorkshopParentScript).AssignActorToObjectPUBLIC((theActor as WorkshopNPCScript), (theVendorStore as WorkshopObjectScript), False) EndIf If (iVendorType == 4) ; 4 is for Clinic/Doctor ; ; Call the function to outfit the settlers with a common loadout ; OutfitSettlers(theActor) ; ; Add an approproiate outfit for male actor ; (theActor as WorkshopNPCScript).SetOutfit(FO4_DoctorUniform) (pWorkshopParent as WorkshopParentScript).AssignActorToObjectPUBLIC((theActor as WorkshopNPCScript), (theVendorStore as WorkshopObjectScript), False) EndIf Else ;Debug.Trace("The vendor test has failed so we are not able to assign npc") EndIf ii = ii + 1 Debug.Notification("Outfitting and assigning merchant # " + ii) VendorCounter = VendorCounter + 1 EndWhile Debug.Notification(VendorCounter + " of the settlers have been assigned as merchants") Utility.Wait(3.0) ; ; Outfit and assign our guards ; Debug.Notification("The IRS is outfitting and employing the guards") jj = ii While jj < WRS2 ObjectReference theActor = ActorsAll[jj] theActor.SetValue(pWorkshopGuardPreference, 1 as float) OutfitSettlers(theActor) (theActor as WorkshopNPCScript).SetOutfit(FO4_CombatUniform01) ObjectReference theDefender = PotentialDefense[iii] (pWorkshopParent as workshopparentscript).AssignActorToObjectPUBLIC(theActor as workshopnpcscript, theDefender as workshopobjectscript, False) jj = jj + 1 iii = iii + 1 DefenderCounter = DefenderCounter + 1 Debug.Notification("Outfitting and assigning guard # " + DefenderCounter) EndWhile Debug.Notification(DefenderCounter + " of the settlers have been assigned as guards") Utility.Wait(3.0) ; ; Outfit and assign our scavengers ; Debug.Notification("The IRS is outfitting and employing the scavengers") kk = jj While kk < WRS3 ObjectReference theActor = ActorsAll[kk] (theActor as workshopnpcscript).SetScavenger(true) OutfitSettlers(theActor) (theActor as WorkshopNPCScript).SetOutfit(FO4_ScavOutfit) ObjectReference theScavengeSta = PotentialScavenge[jjj] (pWorkshopParent as workshopparentscript).AssignActorToObjectPUBLIC(theActor as workshopnpcscript, theScavengeSta as workshopobjectscript, False) kk = kk + 1 jjj = jjj + 1 ScavengeCounter = ScavengeCounter + 1 Debug.Notification("Outfitting and assigning scavenger # " + ScavengeCounter) EndWhile Debug.Notification(ScavengeCounter + " of the settlers have been assigned to scavenging") Utility.Wait(3.0) ; ; Outfit and assign our farmers ; Debug.Notification("The IRS is outfitting and employing the farmers") mm = kk While mm < ActorsAll.Length ObjectReference theActor = ActorsAll[mm] ObjectReference thePlant = PotentialFood[kkk] OutfitSettlers(theActor) (theActor as WorkshopNPCScript).SetOutfit(FO4_FarmingOutfit) (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 Debug.Notification("Outfitting and assigning farmer # " + FoodCounter) EndWhile Debug.Notification(FoodCounter + " of the settlers have been assigned to farming") Utility.Wait(2) ; ; Evaluate packages on the NPCs ; ii = 0 While ii < ActorsAll.Length ObjectReference theActor = ActorsAll[ii] (theActor as workshopnpcscript).EvaluatePackage() ii = ii + 1 ; Debug.Notification("Evaluating AI package on actor " + theActor) EndWhile If (pFO4_TurretStatus.GetValue() == 1 as float) pFO4_TurretsEnable.enable() EndIf Debug.Notification("The employment phase has completed") Utility.Wait(2) Debug.Notification("All IRS activites have completed, system shutting down") EndFunction Function OutfitSettlers(ObjectReference theNPC) ; ; This function serves to outfit the settlers with a common loadout ; FO4_TemporaryChest01.AddItem(GaussRifle, 1, true) FO4_TemporaryChest01.AddItem(Ammo2mmEC, 5, true) FO4_TemporaryChest01.AddItem(Caps001, 100, true) FO4_TemporaryChest01.AddItem(Stimpak, 3, true) FO4_TemporaryChest01.RemoveAllItems(theNPC, abKeepOwnership = false) (theNPC as WorkshopNPCScript).EquipItem(GaussRifle, false, false) (theNPC as WorkshopNPCScript).EquipItem(Ammo2mmEC, false, false) EndFunction Function StartupRecruitment(ObjectReference ThisWorkshop) Debug.Notification("The Intelligence recruitment System has been activated ... please standby") StartTimerGameTime(fTimerDuration, iRecruitmentTimerID) ; Create the timer with a specified game-time duration EndFunction ; ╔═════════════════════════════════════════════════╗ ; ║ Events ║ ; ╚═════════════════════════════════════════════════╝ Event OnTimerGameTime(int aiTimerID) If (aiTimerID == iRecruitmentTimerID) && (iCountNPCIndex < iNPCMaxCount) ObjectReference ThisWorkshop = Self.GetLinkedRef(pWorkshopItemKeyword) ObjectReference SpawnMarker = ThisWorkshop.GetLinkedRef(pWorkshopLinkSpawn) iCountNPCIndex = iCountNPCIndex + 1 Debug.Notification("Recruiting settler # " + iCountNPCIndex + " of " + iNPCMaxCount + ", onboarding in-progress ... please standby") If (iCountNPCIndex % 2) == 0 ; Debug.Notification("The number " + iCountNPCIndex + " is even") ; Spawn in a new male settler Actor newActor = SpawnMarker.PlaceAtMe(FO4_WorkshopNPCMaleHuman, abDeleteWhenAble = false) as Actor iMaleNPCCount = iMaleNPCCount + 1 WorkshopNPCScript newWorkshopActor = newActor as WorkShopNPCScript ActorsAll.Add(newWorkshopActor) newWorkshopActor.bNewSettler = true (pWorkshopParent as WorkshopParentScript).AddActorToWorkshopPUBLIC((newWorkshopActor as WorkshopNPCScript), (ThisWorkshop as WorkshopScript)) ; try to automatically assign new NPC to do something ;(pWorkshopParent as WorkshopParentScript).TryToAutoAssignActor((ThisWorkshop as WorkshopScript), (newWorkshopActor as WorkshopNPCScript)) Else ; Debug.Notification("The number " + iCountNPCIndex + " is odd") ; Spawn in a new female settler Actor newActor = SpawnMarker.PlaceAtMe(FO4_WorkshopNPCFemaleHuman, abDeleteWhenAble = false) as Actor iFemaleNPCCount = iFemaleNPCCount + 1 WorkshopNPCScript newWorkshopActor = newActor as WorkShopNPCScript ActorsAll.Add(newWorkshopActor) newWorkshopActor.bNewSettler = true (pWorkshopParent as WorkshopParentScript).AddActorToWorkshopPUBLIC((newWorkshopActor as WorkshopNPCScript), (ThisWorkshop as WorkshopScript)) ; try to automatically assign new NPC to do something ;(pWorkshopParent as WorkshopParentScript).TryToAutoAssignActor((ThisWorkshop as WorkshopScript), (newWorkshopActor as WorkshopNPCScript)) EndIf ;(pWorkshopParent as workshopparentscript).CreateActorPUBLIC(ThisWorkshop as workshopscript) ; Has the desired number of NPCs been recruited. If not, start the do StartTimerGameTime again... If (iCountNPCIndex < iNPCMaxCount) StartTimerGameTime(fTimerDuration, iRecruitmentTimerID) Else Utility.Wait(5) Debug.Notification("Settler onboarding is now complete") Utility.Wait(2) Debug.Notification("The IRS has recruited " + iMaleNPCCount + " male settlers") Utility.Wait(2) Debug.Notification("The IRS has recruited " + iFemaleNPCCount + " female settlers") Utility.Wait(2) ; ; ; Call the discharge function to unassign all the workers from workshop objects ; because we want to start with a clean slate ; DischargeNPCs(ThisWorkshop) ; AssignActorToWorkObject() EndIf EndIf EndEvent Link to comment Share on other sites More sharing options...
Recommended Posts