Jump to content

RemoveComponents


niston

Recommended Posts

I am going to offer my 2 cents here. This is the best I can come up with. Maybe you can improve this script. Replace player with your container's ObjectReference.

Scriptname TestScript extends Quest

FormList Property CA_JunkItems Auto Const Mandatory ; A Formlist that contains all junk items in FO4. I found this one already made in CK but I am not sure if it has all the junk items.
Component Property c_Steel Auto Const Mandatory

Struct ConsumedItem
	Form baseForm
	int count
EndStruct

ConsumedItem[] items

Event OnInit()
	AddInventoryEventFilter(CA_JunkItems)
	RegisterForRemoteEvent(Game.GetPlayer(), "OnItemRemoved")
EndEvent

Event ObjectReference.OnItemRemoved(ObjectReference akSender, Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)
	Debug.Trace("[TestScript] OnItemRemoved() Removed " + aiItemCount + " of item: " + akBaseItem)
	ConsumedItem cItem = new ConsumedItem
	cItem.baseForm= akBaseItem
	cItem.count = aiItemCount
	items.Add(cItem)
EndEvent

Function removeComps()
	items = None
	items = new ConsumedItem[0]
	Game.GetPlayer().RemoveComponents(c_steel, 20)
	Debug.Trace("[TestScript] removeComps() finished")
EndFunction

; When to call this??
Function onRemoveComponentsDone()
	int i = 0
	While i < items.length
		Debug.Trace("[TestScript] Item: " + items[i].baseForm + ", Count: " + items[i].count)
		i =  i + 1
	EndWhile
EndFunction

The problem is I don't know how to detect when RemoveComponents() has done its work. removeComps() finishes before all the events are even fired. Maybe you could find a workaround for this one using timers or something. I honestly don't know

Edited by NoCashNoExp
Link to comment
Share on other sites

Same problem there though, how'd you know that RemoveComponents() in fact removed 20 steel?

I think it'll have to be combined with GetComponentCount().

 

Do you plan on using ConsumedItem[] items as sort of a queue?

If so, you could add a timer processing the queue in blocks, for as long as there's something in the queue.

Link to comment
Share on other sites

Really depends on what you want to do. E.g. for my working generators I used a mix between get and remove.

 

 

Scriptname FVFireScrWoodandOil extends ObjectReference



Component Property c_Wood Auto
Component Property c_oil Auto
ObjectReference Property FVWarmTrigger Auto
Int Property Into Auto
Int Property Into2 Auto

Event OnLoad()
While Self.isenabled()
Utility.wait(10)

Into = Self.GetComponentCount (c_wood)
Into2 = Self.GetComponentCount (c_oil)

If (Into+Into2 > 2)


If Self.GetComponentCount(c_wood) > 2
Self.RemoveComponents(c_Wood, 3)

FVWarmTrigger.enable()
Utility.wait(180)

Elseif Self.GetComponentCount(c_oil) > 2
Self.RemoveComponents(c_oil, 3)

FVWarmTrigger.enable()
Utility.wait(180)


Elseif (Self.GetComponentCount(c_wood) > 1) && (Self.GetComponentCount(c_oil) > 1)
Self.RemoveComponents(c_Wood, 2)
Self.RemoveComponents(c_oil, 1)
FVWarmTrigger.enable()
Utility.wait(180)

Elseif (Self.GetComponentCount(c_wood) > 0) && (Self.GetComponentCount(c_oil) > 1)
Self.RemoveComponents(c_Wood, 1)
Self.RemoveComponents(c_oil, 2)
FVWarmTrigger.enable()
Utility.wait(180)

Elseif (Self.GetComponentCount(c_wood) > 1) && (Self.GetComponentCount(c_oil) > 0)
Self.RemoveComponents(c_Wood, 2)
Self.RemoveComponents(c_oil, 1)
FVWarmTrigger.enable()
Utility.wait(180)

Else
FVWarmTrigger.disable()
Endif
Endif
Endwhile
EndEvent



 


And yes I should have used a timer instead of utility.wait...

Link to comment
Share on other sites

Yes if you are manually scripting crafting conditions then you need to validate the source has GetComponentCount() before RemoveComponents() or a fail path.

 

Edit: which is where you can log the latency across those transative workshop provisioner supply networks getting component counts from piles of crap in 30 workshops. Yay ! lets add *more* workshops to that then cry when it all falls over /salty.

Link to comment
Share on other sites

Same problem there though, how'd you know that RemoveComponents() in fact removed 20 steel?

I think it'll have to be combined with GetComponentCount().

 

Do you plan on using ConsumedItem[] items as sort of a queue?

If so, you could add a timer processing the queue in blocks, for as long as there's something in the queue.

 

Well, the items array currently has base form junk items that the game decided to use up. This means we can copy those in another separate container and count them to make sure. This is untested and I am not sure if it will return correct numbers. It's more conceptual really. The problem is again how would you know that the game is done with RemoveComponents().

Scriptname TestScript extends Quest

FormList Property CA_JunkItems Auto Const Mandatory ; A Formlist that contains all junk items in FO4. I found this one already made in CK but I am not sure if it has all the junk items.
Component Property c_Steel Auto Const Mandatory
Container Property TempContainer Auto Const Mandatory ; Temp Container Property

Struct ConsumedItem
	Form baseForm
	int count
EndStruct

ConsumedItem[] items

Event OnInit()
	AddInventoryEventFilter(CA_JunkItems)
	RegisterForRemoteEvent(Game.GetPlayer(), "OnItemRemoved")
EndEvent

Event ObjectReference.OnItemRemoved(ObjectReference akSender, Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)
	Debug.Trace("[TestScript] OnItemRemoved() Removed " + aiItemCount + " of item: " + akBaseItem)
	ConsumedItem cItem = new ConsumedItem
	cItem.baseForm= akBaseItem
	cItem.count = aiItemCount
	items.Add(cItem)
EndEvent

Function removeComps()
	items = None
	items = new ConsumedItem[0]
	Game.GetPlayer().RemoveComponents(c_steel, 20)
	Debug.Trace("[TestScript] removeComps() finished")
EndFunction

; When to call this??
Function onRemoveComponentsDone()
​	ObjectReference cont = Game.GetPlayer().PlaceAtMe(TempContainer)
	int i = 0
	While i < items.length
		cont.AddItem(items[i].baseForm, items[i].count, true)
		i =  i + 1
	EndWhile
	Debug.Trace("The game consumed (" + cont.GetComponentCount(c_steel) +") steel components from player")
	cont.DisableNoWait()
	cont.Delete()
EndFunction

Edit: I've just realised, this is such a roundabout way for this problem. Why not just call GetComponentCount() before even calling RemoveComponents() to make sure whether the container has 20 steel or not.

Edited by NoCashNoExp
Link to comment
Share on other sites

 


Edit: I've just realised, this is such a roundabout way for this problem. Why not just call GetComponentCount() before even calling RemoveComponents() to make sure whether the container has 20 steel or not.

 

That's what I'm thinking, yes.

Since RemoveComponents() doesn't tell you anything, you'll have to check for the required components to be present beforehand.

Link to comment
Share on other sites

I've got this. Didn't get around to test it yet, but I expect it just works.

Scriptname F4MS:F4MS_ComponentScrapAgent extends ObjectReference

; F4MS component scrapping agent
; custom scripting by niston

Int Function ScrapItems(Int componentCountRequested, Component componentToScrapFor, ObjectReference sourceContainer, ObjectReference targetContainer)
	; get available component count for source container
	Int numberOfComponentsScrapped = sourceContainer.GetComponentCount(componentToScrapFor)
		
	; container has requested component in it?
	If (numberOfComponentsScrapped > 0)			
	
		; component count supplied?
		If (componentCountRequested > 0)
			; limit scrapped count to requested amount
			If (numberOfComponentsScrapped > componentCountRequested)
				numberOfComponentsScrapped = componentCountRequested
			EndIf
		EndIf		
		
		; perform scrapping on source container
		sourceContainer.RemoveComponents(componentToScrapFor, numberOfComponentsScrapped, abSilent = true)
		
		; add scrapped components to target container
		targetContainer.AddItem(componentToScrapFor, numberOfComponentsScrapped, abSilent = true)		
		
	Else
		; nothing to scrap for in this container
                numberOfComponentsScrapped = 0

	EndIf
	
	; return amount of scrapped components moved to target container
	Return numberOfComponentsScrapped
EndFunction

If ScrapItems() is called with a componentCountRequested of < 1, it'll scrap for the entire lot of the requested component that it can find in sourceContainer. Once can obviously not call it with a Formlist, for no one ever could know which components from the list RemoveComponents() actually scrapped for. But if you want FormList processing, you'll simply call ScrapItems() for each entry in your Formlist.

 

@NoCashNoExp: Regarding the problem of knowing when RemoveComponents() is done, I think you can't. I don't personally face that problem in my application, but perhaps you could call GetComponentCount() again and it would block until RemoveComponents is done? Pure speculation on my part, but it might just work as well.

 

 

BTW: It appears that ObjectReference already has a function Scrap() on it. But I can't find any documentation about it. Is it added by F4SE, perhaps?

Link to comment
Share on other sites

  • Recently Browsing   0 members

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