ZeroCore Posted June 2, 2013 Share Posted June 2, 2013 I'm trying to essentially make a replicator mod. The idea is this: you put an item in a chest, flip a lever, and the chest gives itself a copy of the item inside it. I'm not sure if it's possible though, as I don't know of any way to get the item ID's of anything stored inside a container. I'm still very inexperienced with the Papyrus scripting language, and the Wiki for the creation kit doesn't seem to help much (it doesn't give enough practical examples, and the descriptions given there are rather hard to figure out at times. The tutorials don't have anything similar to what I'm out to find, and the descriptions they give in these tutorials of what to do, how, and why are woefully limited as well). Any help on this would be much appreciated. Link to comment Share on other sites More sharing options...
IsharaMeradin Posted June 2, 2013 Share Posted June 2, 2013 I think this should be fairly easy. You want to use the OnItemAdded event on the script attached to the container. I highly recommend having an empty formlist and adding to it with AddForm so that you can account for multiple items. Plus your lever script can use the formlist to add the duplicate items to the chest. After duplication you can Revert the formlist so that it is empty again for future use. Link to comment Share on other sites More sharing options...
ZeroCore Posted June 2, 2013 Author Share Posted June 2, 2013 (edited) I think this should be fairly easy. You want to use the OnItemAdded event on the script attached to the container. I highly recommend having an empty formlist and adding to it with AddForm so that you can account for multiple items. Plus your lever script can use the formlist to add the duplicate items to the chest. After duplication you can Revert the formlist so that it is empty again for future use.Probably a good idea. Unfortunately I have no idea how to use forms, form lists, or anything related to them, and I couldn't find any good tutorials on how to use them to accomplish what I'm trying to do. I also ran into a problem with the work-around that I thought up. The work-around was essentially to have two containers. The one container is a recepticle where you place the item. It uses the "OnItemAdded" event to run a script which is supposed to send the ID of the item that was put into it to an "AddItem" command, which would then add the item to the replicator chest. I keep running into the following error when I try to compile the script: "cannot call the member function additem alone or on a type, must call it on a variable" the script I've come up with looks like this: Scriptname Replicator extends ObjectReference Event OnItemAdd (Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer)Replicator.additem (akBaseItem, 2, true)endEvent I have no idea what I'm doing wrong. Edited June 2, 2013 by ZeroCore Link to comment Share on other sites More sharing options...
IsharaMeradin Posted June 2, 2013 Share Posted June 2, 2013 Since I've done similar stuff, I'll quickly adapt and show basic scripts that *should* do what you want. Here are the basics of the container script Scriptname YourContainerScript extends ObjectReference Actor Property PlayerRef Auto FormList Property ItemList Auto ;an empty formlist Event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer) If akSourceContainer == PlayerRef If !(ItemList.HasForm(akBaseItem)) ItemList.AddForm(akBaseItem) EndIf EndIf EndEvent Your lever script would need to be something akin to the following. Scriptname YourLeverScript extends ObjectReference Actor Property PlayerRef Auto ObjectReference ContainerRef Auto ;container with items to be duplicated FormList Property ItemList Auto ;these three have the same index count -- or should Event OnActivate(ObjectReference akActionRef) If akActionRef == PlayerRef Int ILsize = ItemList.GetSize() Int index = 0 While index < ILsize Form entry = ItemList.GetAt(index) Int qty = ContainerRef.GetItemCount(entry[index]) If qty > 0 ContainerRef.AddItem(entry,qty,true) EndIf index += 1 EndWhile ItemList.Revert() EndIf EndEvent A little more complicated than necessary, maybe. Not sure. I felt better about going into the form list and checking for specific entries rather than just adding 1 of everything on the form list. You'll need to test the compilation and the execution of the scripts. Don't forget to fill your properties. And you need to create an empty form list in the Creation Kit too. Form lists are located in the Misc. category in the Object Window. Once there, just right click and select new. Give it a name and OK to save it. Link to comment Share on other sites More sharing options...
IsharaMeradin Posted June 2, 2013 Share Posted June 2, 2013 The work-around was essentially to have two containers. The one container is a recepticle where you place the item. It uses the "OnItemAdded" event to run a script which is supposed to send the ID of the item that was put into it to an "AddItem" command, which would then add the item to the replicator chest. I keep running into the following error when I try to compile the script: "cannot call the member function additem alone or on a type, must call it on a variable" the script I've come up with looks like this: Scriptname Replicator extends ObjectReference Event OnItemAdd (Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer)Replicator.additem (akBaseItem, 2, true)endEvent I have no idea what I'm doing wrong. Regarding your attemptYou named your script Replicator and then used an undefined variable called Replicator to run the AddItem function. You would need to add an ObjectReference property for your container and give it a variable name that is not the same as a script. FYI -- before you get going too far into your mod. Strongly suggest you use a script prefix so that you'll have an easier time of recognizing which scripts belong to your mods. Link to comment Share on other sites More sharing options...
ZeroCore Posted June 2, 2013 Author Share Posted June 2, 2013 (edited) The work-around was essentially to have two containers. The one container is a recepticle where you place the item. It uses the "OnItemAdded" event to run a script which is supposed to send the ID of the item that was put into it to an "AddItem" command, which would then add the item to the replicator chest. I keep running into the following error when I try to compile the script: "cannot call the member function additem alone or on a type, must call it on a variable" the script I've come up with looks like this: Scriptname Replicator extends ObjectReference Event OnItemAdd (Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer)Replicator.additem (akBaseItem, 2, true)endEvent I have no idea what I'm doing wrong. Regarding your attemptYou named your script Replicator and then used an undefined variable called Replicator to run the AddItem function. You would need to add an ObjectReference property for your container and give it a variable name that is not the same as a script. FYI -- before you get going too far into your mod. Strongly suggest you use a script prefix so that you'll have an easier time of recognizing which scripts belong to your mods. Well, actually I'd already named the container that the new items would be deposited in "Replicator".... but it does conflict with the script name. I'll change the name of the script and see if that works, but I don't know what will happen. Nevermind. Tried changing the name, and got the same error. Also, I'm curious as to how the script you wrote above works. I can understand some of it (I know other coding languages, but not this one). I'd like to know, step by step, what everything means and how it does what it does. Also, how does this thing know what form list to use, and what form list is referenced, if the name of the form list never appears? I have a lot of questions about this scripting language, I admit, but there seems to be no good tutorials anywhere to learn from. The wiki is two inches away from being useless since it doesn't tell me exactly what means what and how things fit together, and there aren't a lot of user-made in-depth tutorials out there on the web. I really don't know where to start, and there seems to be little to no resources available to learn from. Edited June 2, 2013 by ZeroCore Link to comment Share on other sites More sharing options...
IsharaMeradin Posted June 3, 2013 Share Posted June 3, 2013 Also, I'm curious as to how the script you wrote above works. I can understand some of it (I know other coding languages, but not this one). I'd like to know, step by step, what everything means and how it does what it does. Also, how does this thing know what form list to use, and what form list is referenced, if the name of the form list never appears? Ok. I'll walk thru the first one. Perhaps that will give an idea on how it works.Descriptions are in the comments. i.e after the semi-colons Scriptname YourContainerScript extends ObjectReference ;Defines the script name & which script it is an extension of ;i.e. which script that functions and events can be used without inline referencing ;do note that if the extended script extends another script then the ;functions and events of that higher level script can also be used without inline ;referencing ;Property section ;Properties follow this pattern all on a single line ;Type of form ;The word Property so that the CK knows to offer you an interface for this variable ;The variable name to use ;The type of variable. Auto is typical. Tho there are other options. Actor Property PlayerRef Auto ;the property assignment for the player character ;it will auto-fill when the auto-fill button is pressed on the properties window ;properties window is accessed by pressing the property button after highlighting ;the assigned script in the script section of the given record FormList Property ItemList Auto ;an empty formlist ;form lists are located under the Miscellaneous section of the Object Window ;in the Creation Kit. An empty form list consists of creating a new list ;but not assigning any other data. ;Finally, you assign the empty form list to this property. If you use the same name for the form list ;and the property variable name then you can auto-fill on the properties window. ;Otherwise you will need to manually assign the form list property via the drop down that appears after ;you highlight the property and press the Edit Value button. Event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer) ;The OnItemAdded event is used on any object which can hold items. ;i.e. containers and actor inventories ;akBaseItem is the form ID of the item added ;aiItemCount is the amount of said item added ;akItemReference has never been used by me... you will have to read the wiki ;akSourceContainer is the container that the item was in prior If akSourceContainer == PlayerRef ;A simple check to determine if the source container was the player ;Note how it compares the variable from the event to the actor variable from the properties If !(ItemList.HasForm(akBaseItem)) ;A simple check to determine if the added item is not on the form list ;ItemList is the property variable name ;HasForm is the function -- found on ObjectReference script ;akBaseItem is the added item variable name from the event ItemList.AddForm(akBaseItem) ;Finally add the item to the form list ;ItemList is the property variable name ;AddForm is the function -- found on ObjectReference script ;akBaseItem is the added item variable name from the event EndIf EndIf EndEvent ;The if statements and the event have to be closed off, thus EndIf & EndEvent are used Link to comment Share on other sites More sharing options...
ZeroCore Posted June 12, 2013 Author Share Posted June 12, 2013 (edited) Also, I'm curious as to how the script you wrote above works. I can understand some of it (I know other coding languages, but not this one). I'd like to know, step by step, what everything means and how it does what it does. Also, how does this thing know what form list to use, and what form list is referenced, if the name of the form list never appears? Ok. I'll walk thru the first one. Perhaps that will give an idea on how it works.Descriptions are in the comments. i.e after the semi-colons Scriptname YourContainerScript extends ObjectReference ;Defines the script name & which script it is an extension of ;i.e. which script that functions and events can be used without inline referencing ;do note that if the extended script extends another script then the ;functions and events of that higher level script can also be used without inline ;referencing ;Property section ;Properties follow this pattern all on a single line ;Type of form ;The word Property so that the CK knows to offer you an interface for this variable ;The variable name to use ;The type of variable. Auto is typical. Tho there are other options. Actor Property PlayerRef Auto ;the property assignment for the player character ;it will auto-fill when the auto-fill button is pressed on the properties window ;properties window is accessed by pressing the property button after highlighting ;the assigned script in the script section of the given record FormList Property ItemList Auto ;an empty formlist ;form lists are located under the Miscellaneous section of the Object Window ;in the Creation Kit. An empty form list consists of creating a new list ;but not assigning any other data. ;Finally, you assign the empty form list to this property. If you use the same name for the form list ;and the property variable name then you can auto-fill on the properties window. ;Otherwise you will need to manually assign the form list property via the drop down that appears after ;you highlight the property and press the Edit Value button. Event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer) ;The OnItemAdded event is used on any object which can hold items. ;i.e. containers and actor inventories ;akBaseItem is the form ID of the item added ;aiItemCount is the amount of said item added ;akItemReference has never been used by me... you will have to read the wiki ;akSourceContainer is the container that the item was in prior If akSourceContainer == PlayerRef ;A simple check to determine if the source container was the player ;Note how it compares the variable from the event to the actor variable from the properties If !(ItemList.HasForm(akBaseItem)) ;A simple check to determine if the added item is not on the form list ;ItemList is the property variable name ;HasForm is the function -- found on ObjectReference script ;akBaseItem is the added item variable name from the event ItemList.AddForm(akBaseItem) ;Finally add the item to the form list ;ItemList is the property variable name ;AddForm is the function -- found on ObjectReference script ;akBaseItem is the added item variable name from the event EndIf EndIf EndEvent ;The if statements and the event have to be closed off, thus EndIf & EndEvent are used This didn't quite work. The container script worked just fine, but when I tried to compile the lever script, it gave me errors: c:\program files (x86)\steam\steamapps\common\skyrim\Data\Scripts\Source\temp\YourLeverScript.psc(4,27): required (...)+ loop did not match anything at input 'Auto'c:\program files (x86)\steam\steamapps\common\skyrim\Data\Scripts\Source\temp\YourLeverScript.psc(4,31): mismatched input '\\r\\n' expecting STATENo output generated for YourLeverScript, compilation failed. Also, I have no idea how to set up a reference now. In the past (in other words before the chaotic mess that is papyrus came around), setting up an object reference was as easy as placing a name in the thing's reference ID section at the top of its object window. Now, I have no idea how to set up an item as a reference, none at all, and there doesn't seem to be a single tutorial on the whole of the internet on how to do it that I can understand. Edited June 12, 2013 by ZeroCore Link to comment Share on other sites More sharing options...
IsharaMeradin Posted June 12, 2013 Share Posted June 12, 2013 Regarding the compiler errors, I'd have to see the script in order to match up the code with the reported errors. As far as references. I can't really explain that. I just know that in your scripts you can reference via properties either the base object (what you can edit from the object window) or a specific instance (a copy that has been placed in a cell). Referencing the base allows you to interact with all instances of said object. Referencing a specific instance only allows interaction with that one copy. Link to comment Share on other sites More sharing options...
ZeroCore Posted June 12, 2013 Author Share Posted June 12, 2013 Regarding the compiler errors, I'd have to see the script in order to match up the code with the reported errors. As far as references. I can't really explain that. I just know that in your scripts you can reference via properties either the base object (what you can edit from the object window) or a specific instance (a copy that has been placed in a cell). Referencing the base allows you to interact with all instances of said object. Referencing a specific instance only allows interaction with that one copy.The script is the same one you wrote above. I tried using it just to see how things would work, but it didn't work at all, at least the lever script didn't. As goes how to reference something by base and by instance, how do you do that? I don't know how to do that. Papyrus is really badly made, IMO. Link to comment Share on other sites More sharing options...
Recommended Posts