Jump to content

Do I have to hardcode this for every vendor?


R3V0LUTI0N4

Recommended Posts

Not on mobile anymore. Wouldn't it make more sense to put all in-game chests into a RefCollectionAlias and add a script like this to it (note, I'm not on my main computer so I can't check to see if this compiles perfectly):

 

Scriptname RCAContainerCheckDeathScript extends RefCollectionAlias

Actor myowner
ObjectReference myself
Bool ownerdied = false

Event OnCellAttach(ObjectReference container)

	myself = container

	if (container != none && ownerdied == false && myowner == none)
		myowner = container.GetActorRefOwner()
		if (myowner != none)
			Self.RegisterForRemoteEvent(myowner, "OnDeath")
		endif
	endif
	
endEvent

Event Actor.OnDeath(Actor akSender, Actor akKiller)

	if (akSender != none && myself != none)
		myself.RemoveAllItems(akSender)
		ownerdied = true
	endif

endEvent
Edited by Reneer
Link to comment
Share on other sites

Getting vendors or their containers into the Refcollectionalias in the first place is the painful bit that stopped me. There are no common conditions to identify vendors or their containers to let the story manager do it for you, so you have to addref them from form lists anyway.

 

"Whilst the generic wasteland and workshop traders are all in the DialogueMechantsFaction, there is no common vendor faction / keyword / linkref to test that includes uniques, so they need to be driven by a fixed lookup list. "

 

If your making a formlist of container refs, its zero additional overhead to drag the actor ref in to another formlist, and now you can register for OnDeath directly and index the container. Plus OnLoad or OnCellAttach will only kick the next time you visit a dead vendor.

Link to comment
Share on other sites

Getting vendors or their containers into the Refcollectionalias in the first place is the painful bit that stopped me. There are no common conditions to identify vendors or their containers to let the story manager do it for you, so you have to addref them from form lists anyway.

Can't you simply drag and drop all the containers into the RefCollectionAlias? Or set up a FormList system and add them to the RefCollectionAlias that way.

 

If your making a formlist of container refs, its zero additional overhead to drag the actor ref in to another formlist, and now you can register for OnDeath directly and index the container. Plus OnLoad or OnCellAttach will only kick the next time you visit a dead vendor.

Yes, but then you need to make sure that the container refs match up to the actor references, which would be a royal pain in the butt if it didn't already match up. It's twice the number of clicks / dragging.

 

And I was thinking OnLoad / OnCellAttach should work fine because you need to at least see said vendor before they get killed (unless they were already killed in the savegame). It could easily be switched to something else, like OnAliasInit().

Edited by Reneer
Link to comment
Share on other sites

Getting vendors or their containers into the Refcollectionalias in the first place is the painful bit that stopped me. There are no common conditions to identify vendors or their containers to let the story manager do it for you, so you have to addref them from form lists anyway.

 

"Whilst the generic wasteland and workshop traders are all in the DialogueMechantsFaction, there is no common vendor faction / keyword / linkref to test that includes uniques, so they need to be driven by a fixed lookup list. "

 

If your making a formlist of container refs, its zero additional overhead to drag the actor ref in to another formlist, and now you can register for OnDeath directly and index the container. Plus OnLoad or OnCellAttach will only kick the next time you visit a dead vendor.

 

That's one of the reasons I was suggesting going with a struct array. It's essentially the same as using a ref collection for this purpose and you can ensure that the indexing always matches up since the vendor and the container ref would be input into the same index of the array. If it were me, I'd rather juggle one annoying list than two.

Link to comment
Share on other sites

 

 

I could not find a way to dynamically query the linked vendor chest for base game placed vendors as there is no script/API call to access the "Merchant Container" or any faction form vendor data tab info.

 

Inspiration: you may get lucky if that function is using the same keywords that the Workshop scripts use to assign containers to workshop vendors, try polling them to see:

 

FormList property pVendorContainerKeywords Auto Const Mandatory
Int iIndex = 0 
While iIndex < pVendorContainerKeywords.GetSize()
   Keyword ThisKeyword = pVendorContainerKeywords.GetAt(iIndex)
   ObjectReference ThisVendorREF ; fill this in from your refcollection or array
   Debug.Trace ("VendorContainerKeywords vendor " + ThisVendorREF + " keyword " + ThisKeyword + " return " + ThisVendorREF.GetLinkedREF(ThisKeyword))
   iIndex +=1
EndWhile
But, it may return the additional legendary/aspirational item spawn container, rather than the faction form general container so check the result values before getting over excited at the awesome suggestion.

 

 

So, looking at the use of the VendorContainerKeyword, it's linked to a bunch of vendors, but not all vendors. It looks to be only vendors that can exist in a settlement, so you won't have vendors such as Takahashi or CLEO. Plus, you'd still be left with how do you get a link between the actor ref and the container ref.

 

The link between actor and container is buried inside the faction, but F4SE hasn't cracked that set of scripts open, so it hasn't been exposed yet. Polling a couple of ref lists isn't going to work either because you'd still need to go and find each in world reference and add it to the ref collection, and then still handle the dynamic settler containers as well.

 

It would almost be easier to set up a struct with data members of actor and objectreference, and either shove that in an array. Then you could populate the known vendors in the script properties tab with the actor and the in world ORef, and for dynamic settlers, populate new ones as they crop up. During the OnDeath() event, scroll the array, find the matching actor, and move all items.

Scriptname MoveThatIsh extends AliasReference
;Attach this to an alias on the player

Struct ContainerLink
     Actor Vendor
     ObjectReference VendorChest
EndStruct

ContainerLink[] ContainerArray    ;This would get populated in the CK

Event OnKill(Actor akVictim)
     int i = 0
     While(i<ContainerArray.length)
          If(akVictim == ContainerArray[i].Vendor)
               ContainerArray[i].VendorChest.RemoveAllItems(Vendor)
          EndIf
          i += 1
     EndWhile
EndEvent

;add some method to figure out when to add more vendors to the array at run time.

Edit: Added some code to show what I'm suggesting. It's mostly front work when adding all the stuff to the array. But, create a ref alias for the player, stick a script on it, and let it roll.

 

Ok, I will try this. What does "CK" mean when you say that the array will get populated in the CK?

Link to comment
Share on other sites

 

 

 

I could not find a way to dynamically query the linked vendor chest for base game placed vendors as there is no script/API call to access the "Merchant Container" or any faction form vendor data tab info.

 

Inspiration: you may get lucky if that function is using the same keywords that the Workshop scripts use to assign containers to workshop vendors, try polling them to see:

 

FormList property pVendorContainerKeywords Auto Const Mandatory
Int iIndex = 0 
While iIndex < pVendorContainerKeywords.GetSize()
   Keyword ThisKeyword = pVendorContainerKeywords.GetAt(iIndex)
   ObjectReference ThisVendorREF ; fill this in from your refcollection or array
   Debug.Trace ("VendorContainerKeywords vendor " + ThisVendorREF + " keyword " + ThisKeyword + " return " + ThisVendorREF.GetLinkedREF(ThisKeyword))
   iIndex +=1
EndWhile
But, it may return the additional legendary/aspirational item spawn container, rather than the faction form general container so check the result values before getting over excited at the awesome suggestion.

 

 

So, looking at the use of the VendorContainerKeyword, it's linked to a bunch of vendors, but not all vendors. It looks to be only vendors that can exist in a settlement, so you won't have vendors such as Takahashi or CLEO. Plus, you'd still be left with how do you get a link between the actor ref and the container ref.

 

The link between actor and container is buried inside the faction, but F4SE hasn't cracked that set of scripts open, so it hasn't been exposed yet. Polling a couple of ref lists isn't going to work either because you'd still need to go and find each in world reference and add it to the ref collection, and then still handle the dynamic settler containers as well.

 

It would almost be easier to set up a struct with data members of actor and objectreference, and either shove that in an array. Then you could populate the known vendors in the script properties tab with the actor and the in world ORef, and for dynamic settlers, populate new ones as they crop up. During the OnDeath() event, scroll the array, find the matching actor, and move all items.

Scriptname MoveThatIsh extends AliasReference
;Attach this to an alias on the player

Struct ContainerLink
     Actor Vendor
     ObjectReference VendorChest
EndStruct

ContainerLink[] ContainerArray    ;This would get populated in the CK

Event OnKill(Actor akVictim)
     int i = 0
     While(i<ContainerArray.length)
          If(akVictim == ContainerArray[i].Vendor)
               ContainerArray[i].VendorChest.RemoveAllItems(Vendor)
          EndIf
          i += 1
     EndWhile
EndEvent

;add some method to figure out when to add more vendors to the array at run time.

Edit: Added some code to show what I'm suggesting. It's mostly front work when adding all the stuff to the array. But, create a ref alias for the player, stick a script on it, and let it roll.

 

Ok, I will try this. What does "CK" mean when you say that the array will get populated in the CK?

 

Never mind. I see what you mean about adding the array as a property in the creation kit. Is there a way to somehow "import" my two form lists into each value of the struct array?

Link to comment
Share on other sites

A formlist is essentially a struct on a file... ummm an array is similar but completely different. If you're not sure what those things are you need to read up on them in the papyrus scripting reference.

 

I'm asking if Creation Kit allows you to populate values in an array of structs with a formlist. I have a formlist of Actors and a formlist of ObjectReferences. I have an array of structs that each hold an Actor and an ObjectReference. I have it working, but I have to add each Actor and ObjectReference manually. This is more a question on the capabilities of the Creation Kit.

Link to comment
Share on other sites

Something like

Object reference[] array = new array[formlist.getsize()]

Int index=0

While index != Formlist.getsize()

array[index] = Formlist.getat(index)

;

index+=1

Endwhile

(Untested)

As far as having a struct in your script theres no way to access the elements via a number. You can However do what I did and use autoit to generate code similarly using text files and copying the information to arrays and making it spit out what I wanted.

Edited by markyrocks
Link to comment
Share on other sites

  • Recently Browsing   0 members

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