Jump to content

Implementation Question


pepperman35

Recommended Posts

Good copy on the assignMultiResource. I had formed an incorrect conclusion on its use based on an examination of the actors at Abernathy farm.



HOW ARE YOU SPAWNING OR INSTANTIATING THE ACTORS ? Are you calling script function like ObjectReference ThisActor = PlaceActorAtMe(blah blah), or something else? The six NPCs are placed in the greenhouse in the CK. Each NPC is hooked to an EnableMarker (SIIR_RecruitBSController) via the EnableParent tab. The SIIR_RecruitBSController (EnableMarker) is set for Initially Disabled. The six NPCs are enabled via a terminal. This is accomplished via the following fragment:

SIIR_RecruitBSBTGlobal.SetValueInt(1)

SIIR_RecruitBSController.enable()


IS THERE ANYTHING UNIQUE ABOUT THE OBJECTS ? Do you apply a keyword or actor value you can use to identify them as yours or the ones you are interested in? At present no, they are strictly vanilla assets; however, I could easily make them unique.


Not sure how relevant it is but I noticed in my testing that when I tried to manually assign these six NPCs to the planters it was not successful, which seemed very odd to me.
Link to comment
Share on other sites

Job #1 is to figure out how to get ObjectReferences for your actors. Without them you can not call the workshop script functions to assign them to a workshop or workshop objects.

 

The reason you can not assign the actors manually is probably becuase the Actors and Objects script WorkshopID is still at the default -1 because you have not called any workshop scripts to register them. Yes despite having WorkshopItemLink.

 

Script WorkshopID assignment is the MASSIVE and FUNDAMENTAL difference between having an isolated non reource producing workshop and a WorkshopParentScript registered resource producting workshop. No WorkshopID ... no resource scripting. Aside: and thats excatly what mod authors tend to f*** up and break when messing about with the Workshops array.

 

Fixing that in script is easy once you have the ObjectReferences for your actors and resurces. Fixing that without script is not possible beacuse WorkshopIDs are dynamic, a workshop can have a different WorkshopID in each game. No, this is not the ObjectReference it is a dynamic script variable exposed as a property;

(WorkshopREF as WorkshopScript).WorkshopID
(ActorREF as WorkshopNPCScript).WorkshopID
(ResourceObjectREF as WorkshopObjectScript).WorkshopID

Solution #A Apply a unique keyword to my actors and another unique keyword to my resources. Have a start game enabled quest script run FindAllReferencesWithKeyword() on the keywords and run the workshop registration and resource assignment scripts on the results. Easy-as. Except that it may only work when the player is present and objects are loaded due to Object Persistence.

 

Solution #B Attach scripts direct to the Actors and Resources that fire Event OnLoad() to run the workshop registration and resource assignment scripts on themselves. Downside is if the resources are not unique to you and are base game forms, your modifying shared assets which will affect every instance in the game which can be a disaster. Have to make them unique for this to work.

 

Solution #C something else, getting bored now ...

Link to comment
Share on other sites

Well, nothing in this game is quite as easy as it appears. Both proposed solutions require the requires the NPCs and resources to be unique; therefore, it appears solution B more desirable from a layman's viewpoint. Therefore, I will assume the first step is to make the NPCs and planters unique by creating two unique keywords and adding them.

 

BTW, thanks for your willingness to help. It is greatly appreciated.

Link to comment
Share on other sites

The alternative is to script the spawn rather than hand place actors and resources, then everything becomes simple.

 

(a) Create copies of say an xmarker myActorXmarker myPlantXmarker and place them in the game. Then run a start game enabled quest which finds the markers by a quest fill of GetIsID or FindAllreferencesOfType, spawns actors and plants at them and then runs the workshop registration scripts. OR;

 

(b) Create copies of say default activator myActorActivator myPlantActivator and attach Event Onload Scripts to them which spawns the actor/plant and then runs the workshop registration scripts and then disables themselves.

 

Trick is to tie therm all together. Can be done in script, but if you want specific actor working a specific plant you will need to create static linkedref associations;

 

ActorMarker --- myActorPlantKeyword ---> PlantMarker

| |

myWorkshopKeyword myWorkshopKeyword

|---------------> Workshop < ------------|

 

Whilst I generally prefer to run central scripts on quests as they are easier to maintain and manage, in this instance (b) looks better as your not having to wait and detect when the markers are loaded as they are self referencing. The ONLY challenge I can envisage is the actor detecting "my plant is ready for me" ... but thats also doable.

Link to comment
Share on other sites

Yes sure spawning/activation can be started from a terminal no problem.

 

Unfortunately the workshop script AssignActorToObject function can only specifiy the first object, for MultiResources it then automatically looks for similar unassigned resources using TryToAssignResourceType

Link to comment
Share on other sites

Update: The 20 vanilla GreenHsPlanter01Mutfruit planters are now identified as 00_GreenHsPlanter01Mutfruit with the unique keyword ObjectGreenHsPlanterMutfruit. The six NPCs now have the unique keyword ActorInstBotanist.

 

==================

As a quick and dirty test, I did the xmarker thing for 1 of the NPC. Used the terminal to spawn them it, coupled with the code you provided earlier for auto assign. I was quite surprised to find out it worked (e.g., the workshop showed 6 food production). I wonder since myActorXMarker and myNPCActor will be incremented by 1 upto 6 if this could be done via arrays and a for I = 1 to 6 setup. It’s late so that might be gibberish.

SIIR_RecruitBSBTGlobal.SetValueInt(1)
Actor Spawned = myActorXMarker01.PlaceActorAtMe(myNPCActor01 ,1)
Spawned.Disable()
Spawned.SetLinkedref(myWorkshop,myWorkshopItemKeyword)
Spawned.Enable()
Spawned.SetValue(pWorkshopGuardPreference, 0.0) ; not guard so farm
(pWorkshopParent as WorkshopParentScript).TryToAutoAssignActor((myWorkshop as WorkshopScript), (Spawned as WorkshopNPCScript))
Edited by pepperman35
Link to comment
Share on other sites

Based on the success from yesterday, I took your advice and pressed forward with the scripted spawn vice hand placing the actors. Thus, I created the xMarkers myActorXMarker01 through myActorXMarker06. As the workshop assign actors script you provided, seemed to work via testing I opted to not spawn in the resources. I still wanted to spawn these NPCs via a terminal (e.g, Recruit botanists to the team) so I adapted what you provided. The following script fragment serves to spawn in the six NPC botanists, link them to the workshop, and allow the workshop to auto-assign them to farming. In addition, additional non-producing bioscientists are enabled for cosmetic purposes. While the code is not elegant it seems to work okay (e.g., tested multiple times today via new game). However, I am aware of my short comings WRT programing and its implications and would welcome your insight regarding implementation. Once again, thank you for your help!

 

 

SIIR_RecruitBSBTGlobal.SetValueInt(1)
;
; Spawn in the 1st NPC (Botantist), link them to the workshop and allow workshop to auto assign to farming
;
Actor Spawned = myActorXMarker01.PlaceActorAtMe(myNPCActor01 ,1)
Spawned.Disable()
Spawned.SetLinkedref(myWorkshop,myWorkshopItemKeyword)
Spawned.Enable()
Spawned.SetValue(pWorkshopGuardPreference, 0.0) ; not guard so farm
(pWorkshopParent as WorkshopParentScript).TryToAutoAssignActor((myWorkshop as WorkshopScript), (Spawned as WorkshopNPCScript))
;
; Repeat the process for the 2nd NPC
;
Actor Spawned2 = myActorXMarker02.PlaceActorAtMe(myNPCActor02 ,1)
Spawned2.Disable()
Spawned2.SetLinkedref(myWorkshop,myWorkshopItemKeyword)
Spawned2.Enable()
Spawned2.SetValue(pWorkshopGuardPreference, 0.0) ; not guard so farm
(pWorkshopParent as WorkshopParentScript).TryToAutoAssignActor((myWorkshop as WorkshopScript), (Spawned2 as WorkshopNPCScript))
;
; Repeat the process for the 3rd NPC
;
Actor Spawned3 = myActorXMarker03.PlaceActorAtMe(myNPCActor03 ,1)
Spawned3.Disable()
Spawned3.SetLinkedref(myWorkshop,myWorkshopItemKeyword)
Spawned3.Enable()
Spawned3.SetValue(pWorkshopGuardPreference, 0.0) ; not guard so farm
(pWorkshopParent as WorkshopParentScript).TryToAutoAssignActor((myWorkshop as WorkshopScript), (Spawned3 as WorkshopNPCScript))
;
; Repeat the process for the 4th NPC
;
Actor Spawned4 = myActorXMarker04.PlaceActorAtMe(myNPCActor04 ,1)
Spawned4.Disable()
Spawned4.SetLinkedref(myWorkshop,myWorkshopItemKeyword)
Spawned4.Enable()
Spawned4.SetValue(pWorkshopGuardPreference, 0.0) ; not guard so farm
(pWorkshopParent as WorkshopParentScript).TryToAutoAssignActor((myWorkshop as WorkshopScript), (Spawned4 as WorkshopNPCScript))
;
; Repeat the process for the 5th NPC
;
Actor Spawned5 = myActorXMarker05.PlaceActorAtMe(myNPCActor05 ,1)
Spawned5.Disable()
Spawned5.SetLinkedref(myWorkshop,myWorkshopItemKeyword)
Spawned5.Enable()
Spawned5.SetValue(pWorkshopGuardPreference, 0.0) ; not guard so farm
(pWorkshopParent as WorkshopParentScript).TryToAutoAssignActor((myWorkshop as WorkshopScript), (Spawned5 as WorkshopNPCScript))
;
; Repeat the process for the 6th NPC
;
Actor Spawned6 = myActorXMarker06.PlaceActorAtMe(myNPCActor06 ,1)
Spawned6.Disable()
Spawned6.SetLinkedref(myWorkshop,myWorkshopItemKeyword)
Spawned6.Enable()
Spawned6.SetValue(pWorkshopGuardPreference, 0.0) ; not guard so farm
(pWorkshopParent as WorkshopParentScript).TryToAutoAssignActor((myWorkshop as WorkshopScript), (Spawned6 as WorkshopNPCScript))
;
; Spawn in additional NPCs for cosmetic purposes
;
SIIR_RecruitBSController.enable()

 

Link to comment
Share on other sites

Here is a working model I cobbeld from existing libraries which has multiple methods to do the plant:actor:workshop thing.

 

Build a SKK_testTerminalSpawn at any workshop (Resources/Misc)

 

If the terminal is associated with a workshop, the terminal menu SPAWN option will either:

 

Detect all SKK_testTerminalPlantMarker xmarkers and place a GreenHsPlanter01Mutfruit at it and register them with the workshop.

Detect all SKK_testTerminalPlantKeyword plants enable and register them with the workshop.

Detect all GreenHsPlanter01Mutfruit if they are unassigned register them with the workshop.

Detect all SKK_testTerminalActorMarker xmarkers and place a SKK_testTerminallWorkshopBotanist at it and register them with the workshop.

Detect all SKK_testTerminalActorKeyword actors enable and register them with the workshop.

If no ActorMarkers or ActorKeywords it will just spawn a pSKK_testTerminallWorkshopBotanist at each activated plant and register them with the workshop.

If There are activated plants and actors, assign them to work and produce.

 

Note: there is no way to FORCE continued actor/work object association or affinity. Any time a ResetWorkshop() is triggered they could be reassigned. That would need a ResetWorkshop detector and reassigner to constantly run which is nasty.

 

As a quick test with no CK placed objects, [ player.placeatme 00100cab ] then build a terminal and run the spawn option.

 

Terminal attached script source, bit longer than necessary with each variable explicity declared and lots of debug output to help follow the assignments:

 

 

Scriptname SKK_testTerminalScript extends ObjectReference Const

Group BaseGame
Quest			Property pWorkshopParent					Auto Const Mandatory	
Flora 			Property pGreenHsPlanter01Mutfruit				Auto Const Mandatory	
Keyword 		Property pWorkshopItemKeyword 					Auto Const Mandatory		
ActorValue		Property pWorkshopRatingPopulation 				Auto Const Mandatory
ActorValue		Property pWorkshopGuardPreference				Auto Const Mandatory
EndGroup 

Group SKK
ActorBase		Property pSKK_testTerminallWorkshopBotanist 	Auto Const Mandatory
Static 			Property pSKK_testTerminalPlantMarker 		Auto Const Mandatory
Static 			Property pSKK_testTerminalActorMarker 		Auto Const Mandatory
Keyword 		Property pSKK_testTerminalPlantKeyword		Auto Const Mandatory
Keyword 		Property pSKK_testTerminalActorKeyword		Auto Const Mandatory
Message			Property pSKK_testTerminalNoWorkshop		Auto Const Mandatory
Message			Property pSKK_testTerminalNoPlants		Auto Const Mandatory
Message			Property pSKK_testAssignmentError		Auto Const Mandatory
GlobalVariable  Property pSKK_testTerminalSpawnState 			Auto Const Mandatory ;Switches terminal display
EndGroup

;**********************************************************************************************************************

Function ActivatePlants() ; called by terminal script fragment using (akTerminalRef as SKK_testTerminalScript).ActivatePlants()

If (pSKK_testTerminalSpawnState.GetValue() == 0) ; has not yet spawned

	ObjectReference ThisWorkshop = Self.GetLinkedRef(pWorkshopItemKeyword)

	If (ThisWorkshop == None) 	

		Debug.Trace("SKK_testTerminalScript.ActivatePlants ERROR NoWorkshop")
		pSKK_testTerminalNoWorkshop.Show() ; I am not linked to a Workshop.

	Else

		ObjectReference[] PlantMarkers   = Self.FindAllReferencesOfType(pSKK_testTerminalPlantMarker, afRadius = 10240)
		ObjectReference[] PlantKeywords  = Self.FindAllReferencesWithKeyword(pSKK_testTerminalPlantKeyword, afRadius = 10240)

		ObjectReference[] ActivatedPlants = New ObjectReference[0]

		If (PlantMarkers.Length == 0) && (PlantKeywords.Length == 0) 
			Debug.Trace("SKK_testTerminalScript.ActivatePlants no markers or keywords looking for plants")
			ObjectReference[] PlantsFound  = Self.FindAllReferencesOfType(pGreenHsPlanter01Mutfruit, afRadius = 10240)
			Int iPlantsFoundIndex = 0 
			While (iPlantsFoundIndex < PlantsFound.Length)
				ObjectReference ThisPlant = PlantsFound[iPlantsFoundIndex]
				If (ThisPlant.IsDeleted() == False) && (ThisPlant is WorkshopObjectScript) && ((ThisPlant as WorkshopObjectScript).IsActorAssigned() == FALSE)
					ActivatedPlants.Add(ThisPlant)
				Endif
				iPlantsFoundIndex +=1
			EndWhile
		Endif

		Debug.Trace("SKK_testTerminalScript.ActivatePlants PlantMarkers    " + PlantMarkers.Length)
		Debug.Trace("SKK_testTerminalScript.ActivatePlants PlantKeywords   " + PlantKeywords.Length)
		Debug.Trace("SKK_testTerminalScript.ActivatePlants ActivatedPlants " + ActivatedPlants.Length)

		If (PlantMarkers.Length == 0) && (PlantKeywords.Length == 0) && (ActivatedPlants.Length == 0)
			Debug.Trace("SKK_testTerminalScript.ActivatePlants ERROR NoPlantMarkers NoPlantkeywords Noplants")
			pSKK_testTerminalNoPlants.Show() 
		Else

			Int iPlantMarkersIndex = 0 
			While (iPlantMarkersIndex < PlantMarkers.Length)
				ObjectReference ThisMarker = PlantMarkers[iPlantMarkersIndex]
				ObjectReference ThisPlant = ThisMarker.PlaceAtMe(pGreenHsPlanter01Mutfruit, 1,abForcePersist = false, abInitiallyDisabled = false, abDeleteWhenAble = false)
				ActivatedPlants.Add(ThisPlant)
				iPlantMarkersIndex +=1
			EndWhile

			Int iPlantKeywordsIndex = 0 
			While (iPlantKeywordsIndex < PlantKeywords.Length)
				ObjectReference ThisPlant = PlantKeywords[iPlantKeywordsIndex]
				ActivatedPlants.Add(ThisPlant)
				iPlantKeywordsIndex +=1
			EndWhile

			If (ActivatedPlants.Length == 0)
				pSKK_testTerminalNoPlants.Show() 
			Else
				ActivateActors(ActivatedPlants, ThisWorkshop)
			EndIf

		EndIf

	EndIf

EndIf

EndFunction

;**********************************************************************************************************************

Function ActivateActors(ObjectReference[] ActivatedPlants, ObjectReference ThisWorkshop)

If (ActivatedPlants == None) || (ActivatedPlants.Length  == 0) ; all functions validate conditions incase thay are called direct 
	pSKK_testTerminalNoPlants.Show()
ElseIf (ThisWorkshop == None)  
	pSKK_testTerminalNoWorkshop.Show() ; I am not linked to a Workshop.	
Else

	ObjectReference[] ActorMarkers   = Self.FindAllReferencesOfType(pSKK_testTerminalActorMarker, afRadius = 10240)
	ObjectReference[] ActorKeywords  = Self.FindAllReferencesWithKeyword(pSKK_testTerminalActorKeyword, afRadius = 10240)
	ObjectReference[] ActivatedActors = New ObjectReference[0]

	Int iWorkshopID = (ThisWorkshop as WorkshopScript).GetWorkshopID() 

	If (ActorMarkers.Length > 0)
		Int iActorMarkersIndex = 0 
		While (iActorMarkersIndex < ActorMarkers.Length)
			ObjectReference ThisActorMarker =  ActorMarkers[iActorMarkersIndex]
			ObjectReference ThisActor = ThisActorMarker.PlaceActorAtMe(pSKK_testTerminallWorkshopBotanist, aiLevelMod = 4, akZone = None)
			ActivatedActors.Add(ThisActor)
			iActorMarkersIndex +=1
		EndWhile
	EndIf

	If (ActorKeywords.Length > 0)
		Int iActorKeywordsIndex = 0 
		While (iActorKeywordsIndex < ActorKeywords.Length)
			ObjectReference ThisActor =  ActorKeywords[iActorKeywordsIndex]
			If (ThisActor as Actor).IsDead() == False && (ThisActor is WorkshopNPCScript) && ((ThisActor as WorkshopNPCScript).bIsWorker == FALSE) ;is not currently assigned to an object 
				ActivatedActors.Add(ThisActor)
			EndIf
			iActorKeywordsIndex +=1
		EndWhile
	EndIf	

	If (ActivatedActors.Length == 0) ; No Markers or keywords so create actors
		Int iActivatedPlantsIndex = 0 
		While (iActivatedPlantsIndex < ActivatedPlants.Length)
			ObjectReference ThisPlant = ActivatedPlants[iActivatedPlantsIndex]
			ObjectReference ThisActor = ThisPlant.PlaceActorAtMe(pSKK_testTerminallWorkshopBotanist, aiLevelMod = 4, akZone = None)
			ThisActor.MoveTo(ThisPlant,  64.0, 64.0, 0.0)
			ActivatedActors.Add(ThisActor)
			iActivatedPlantsIndex +=1
		EndWhile
	EndIf

	Debug.Trace("SKK_testTerminalScript.ActivateActors ActorMarkers    " + ActorMarkers.Length)
	Debug.Trace("SKK_testTerminalScript.ActivateActors ActorKeywords   " + ActorKeywords.Length)
	Debug.Trace("SKK_testTerminalScript.ActivateActors ActivatedActors " + ActivatedActors.Length)
	Debug.Trace("SKK_testTerminalScript.ActivateActors ActivatedPlants " + ActivatedPlants.Length)

	If (ActivatedActors.Length > 0) && (ActivatedActors.Length == ActivatedPlants.Length)  ; have plants, have actors

		Int iActivatedIndex = 0 
		While (iActivatedIndex < ActivatedActors.Length)
			ObjectReference ThisActor = ActivatedActors[iActivatedIndex]
			ObjectReference ThisPlant = ActivatedPlants[iActivatedIndex]
			ThisPlant.Enable()
			If ((ThisPlant as WorkshopObjectScript).WorkshopID != iWorkshopID)
				(pWorkshopParent as WorkshopParentScript).BuildObjectPUBLIC((ThisPlant as ObjectReference),  (ThisWorkshop as WorkshopScript))
				Debug.Trace("SKK_testTerminalScript.ActivateActors ThisPlant.WorkshopID " + ThisPlant  + " " + (ThisPlant as WorkshopObjectScript).WorkshopID )
			EndIf
			ThisActor.Enable()
			ThisActor.SetValue(pWorkshopRatingPopulation, 1)
			ThisActor.SetValue(pWorkshopGuardPreference, 0)
			(ThisActor as WorkshopNPCScript).SetCommandable(TRUE)
			(ThisActor as WorkshopNPCScript).SetAllowCaravan(FALSE)
			(ThisActor as WorkshopNPCScript).SetAllowMove(FALSE)
			If ((ThisActor as WorkshopNPCScript).GetWorkshopID() != iWorkshopID)			
				(pWorkshopParent as WorkshopParentScript).AddActorToWorkshopPUBLIC((ThisActor as WorkshopNPCScript), (ThisWorkshop as WorkshopScript), bResetMode = false)
				Debug.Trace("SKK_testTerminalScript.ActivateActors ThisActor.WorkshopID " + ThisActor  + " " + (ThisActor as WorkshopNPCScript).GetWorkshopID() )
			EndIf
			(pWorkshopParent as WorkshopParentScript).AssignActorToObjectPUBLIC((ThisActor as WorkshopNPCScript), (ThisPlant as WorkshopObjectScript), bResetMode = false) 
			Debug.Trace("SKK_testTerminalScript.ActivateActors " + iActivatedIndex + " Assigned Actor " + ThisActor  + " To Plant " + ThisPlant)		
			iActivatedIndex	+=1
		EndWhile

		If (iActivatedIndex > 0)
			pSKK_testTerminalSpawnState.SetValue(1) ; lock terminal spawn option
		Else
			pSKK_testAssignmentError.Show(ActivatedActors.Length,ActivatedPlants.Length) ; Spawn can not be completed. | Errors assigning %.0f actors to %.0f plants.

		EndIf

	Else
		pSKK_testAssignmentError.Show(ActivatedActors.Length,ActivatedPlants.Length) ; Spawn can not be completed. | Errors assigning %.0f actors to %.0f plants.
	EndIf

EndIf

EndFunction

;********************************************************************************************************************** 

 

 

Link to comment
Share on other sites

  • Recently Browsing   0 members

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