Jump to content

[Script-related Question] Intelligent Recruitment System


pepperman35

Recommended Posts

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:


  1. Count the number of workshop work objects within the settlement
  2. Since NPCs can farm more than one work object, the count gets adjusted based on the number of food-related work objects
  3. 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.
  4. Assign NPCs to the work objects
  5. 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 by pepperman35
Link to comment
Share on other sites

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

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

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

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

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

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

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...