R3V0LUTI0N4 Posted September 21, 2018 Share Posted September 21, 2018 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 ObjectReferencechest.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 More sharing options...
markyrocks Posted September 21, 2018 Share Posted September 21, 2018 Can you show an example of how index is assigned a value Link to comment Share on other sites More sharing options...
R3V0LUTI0N4 Posted September 21, 2018 Author Share Posted September 21, 2018 (edited) 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 September 21, 2018 by R3V0LUTI0N4 Link to comment Share on other sites More sharing options...
Reneer Posted September 21, 2018 Share Posted September 21, 2018 (edited) 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 September 21, 2018 by Reneer Link to comment Share on other sites More sharing options...
markyrocks Posted September 21, 2018 Share Posted September 21, 2018 (edited) 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 September 21, 2018 by markyrocks Link to comment Share on other sites More sharing options...
R3V0LUTI0N4 Posted September 21, 2018 Author Share Posted September 21, 2018 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 More sharing options...
SKKmods Posted September 21, 2018 Share Posted September 21, 2018 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 More sharing options...
markyrocks Posted September 21, 2018 Share Posted September 21, 2018 PVIS_VendorContainers_REF.GetAt(akVictim.getactorbase().getname()).removeallitems(akVictim) I'm not familiar with the PVIS_VendorContainers_Ref so idk if theres a different way to search it. I'm really just spitballing. Link to comment Share on other sites More sharing options...
Carreau Posted September 21, 2018 Share Posted September 21, 2018 (edited) 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 September 21, 2018 by Carreau Link to comment Share on other sites More sharing options...
SKKmods Posted September 21, 2018 Share Posted September 21, 2018 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 More sharing options...
Recommended Posts