Jump to content

Do I have to hardcode this for every vendor?


R3V0LUTI0N4

Recommended Posts

I'm working on a mod that basically transfers the items from a vendor's chest to their body on death. I have the OnDeath event working with the formlist of vendor npcs, but since the only tie between a vendor and their chest (as far as I've found) is usually either a faction or they are owner of the chest, I have had to manually point each vendor to the chest I want transferred to them on death. Is there an easier way to do this?

 

I basically have a bunch of if statements that set the variable "index" to a specific value depending on the name of the death victim. Here is a snippet of what happens after the index is assigned:

 

ObjectReference chest = PVIS_VendorContainers_REF.GetAt(index) As ObjectReference

chest.RemoveAllItems(akTransferTo = akVictimRef)

 

Like I said, the mod works, it's just a matter of implementing it for all vendors in the base game. I have been slowly hardcoding each chest to each vendor, but it is a tedious process.

 

Additional question, I've been picking the index based on the actual name of the NPC, but since that is not unique, I have had some issues. Is there a function to get the ID instead of the name?

 

 

Any help is much appreciated.

Link to comment
Share on other sites

Can you show an example of how index is assigned a value

 

 

Sure, here is an example if I wanted to do it with Takahashi.

 

I have a quest with a reference collection which is a formlist of all the vendors. The formlist of all vendor chests is added as a property to the script. Then I pick the index in the list that matches the chest of the items I want to the corresponding NPC name. Since the VendorDCPowerNoodles chest in my formlist is at index 0, I assign 0 to the index when takahashi dies.

 

Event OnDeath(ObjectReference akVictimRef, Actor akKiller)

;Self.RemoveRef(akVictimRef)

 

String name = akVictimRef.GetBaseObject().GetName()

int index

 

 

if name == "Takahashi"

index = 0

endIf

 

ObjectReference chest = PVIS_VendorContainers_REF.GetAt(index) As ObjectReference

 

chest.RemoveAllItems(akTransferTo = akVictimRef)

 

I did it this way because I was thinking I'll have to hardcode it and add if statements for every vendor.

Edited by R3V0LUTI0N4
Link to comment
Share on other sites

There are definitely better ways to accomplish what you are trying to do. I'm on mobile right now, but one idea would be to create a quest and find nearby objects with a vendor keyword, then once you have found a chest, add it to a RefCollectionAlias, and on that alias script check GetActorOwner() and then use RegisterForRemoteEvent to detect when the actor dies, then transfer all the items to the dead actor using RemoveAllItems. Edited by Reneer
Link to comment
Share on other sites

your exactly right every vendor in the game is going to be in one of 6 factions... so to handle all death events ( i used the inverse) this is probably my best crack at it. you only need one if statement if you do it like this

;declare the 6 vendor factions...

;event registered up here ect


Event OnKill(Actor akVictim)

if akVictim.IsInFaction(Faction akFaction) || akVictim.IsInFaction(Faction akFaction1) || akVictim.IsInFaction(Faction akFaction2) ;ect



   ;move items ect 



  Endif

endEvent
Edited by markyrocks
Link to comment
Share on other sites

 

your exactly right every vendor in the game is going to be in one of 6 factions... so to handle all death events ( i used the inverse) this is probably my best crack at it. you only need one if statement if you do it like this

;declare the 6 vendor factions...

;event registered up here ect


Event OnKill(Actor akVictim)

if akVictim.IsInFaction(Faction akFaction) || akVictim.IsInFaction(Faction akFaction1) || akVictim.IsInFaction(Faction akFaction2) ;ect



   ;move items ect 



  Endif

endEvent

 

That makes sense. The only thing is how can I specify the chest that corresponds to the person I just killed since many chests belong to the faction itself and not a singular owner?

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.
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.

Edited by Carreau
Link to comment
Share on other sites

Look at the quest AspirationalItems for some ideas, vendors are linked to their aspirationitemcontainer via VendorContainerKeywords.

 

Having been round this loop several times, I just dragged all base game vendorREFs into a formlist and their containerREFs into another formlist keeping the same indexes so when I need vendor list index N I can lookup chest index N. As used in Fallout 4-76.

Link to comment
Share on other sites

  • Recently Browsing   0 members

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