irswat Posted January 25, 2017 Share Posted January 25, 2017 read again. Link to comment Share on other sites More sharing options...
irswat Posted January 25, 2017 Share Posted January 25, 2017 If you are gonna use it on more then one container, as in more then a few just put the script on the Base and create a new name for it.I myself don't even know how to do the "alias" version could you show us an example ... Using OnItemAdded and OnItemRemoved with the script on the container is how this is done ... Sure IF you want to edit every container in the game that you want to deal with. And again, it won't trigger if the player doesn't add or remove an object.Using a player alias script is more compatible when dealing with containers that are not of your creation. I prefer to go the route of compatibility. If you are gonna use it on more then one container, as in more then a few just put the script on the Base and create a new name for it.I myself don't even know how to do the "alias" version could you show us an example ... that's good to know, is there a way to dynamically attach a script to a base object for compatibility purposes? Link to comment Share on other sites More sharing options...
IsharaMeradin Posted January 25, 2017 Share Posted January 25, 2017 @ NexusComa There are plenty of tutorials on how to create a quest and create an alias that points to the player. I won't go into that. This is a 'barebones' script that will print a text string on screen for testing purposes. Scriptname SomeScript Extends ReferenceAlias ;GetName() is an SKSE function. It will fail without visible in-game notice or harm if SKSE is not present. Event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer) ;Optional SKSE code ;If UI.IsMenuOpen("ContainerMenu") || UI.IsMenuOpen("GiftMenu") || UI.IsMenuOpen("BarterMenu") ; the above are all menus that access a container of some sort ; they could be used to limit processing to only those items that come from a container ; thus the portion after the Else would never run and not need to be included. ; Depends on mod needs as to whether all menus or just one are used If akSourceContainer ;is a valid object Debug.Notification(akBaseItem.GetName()+" ["+akBaseItem+"] came from "+akSourceContainer.GetBaseObject().GetName()+" ["+akSourceContainer+"]") Else Debug.Notification(akBaseItem.GetName()+" ["+akBaseItem+"] was picked up or added from nothingness") EndIf ;Closing tag for optional SKSE code ;EndIf EndEvent Event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer) ;Optional SKSE code ;If UI.IsMenuOpen("ContainerMenu") || UI.IsMenuOpen("GiftMenu") || UI.IsMenuOpen("BarterMenu") ; the above are all menus that access a container of some sort ; they could be used to limit processing to only those items that go to a container ; thus the portion after the Else would never run and not need to be included. ; Depends on mod needs as to whether all menus or just one are used If akDestContainer ;is a valid object Debug.Notification(akBaseItem.GetName()+" ["+akBaseItem+"] was placed in "+akDestContainer.GetBaseObject().GetName()+" ["+akDestContainer+"]") Else Debug.Notification(akBaseItem.GetName()+" ["+akBaseItem+"] was dropped or removed into nothingness") EndIf ;Closing tag for optional SKSE code ;EndIf EndEvent ;Yields ;When Item added to player with source (with SKSE) ; ItemName [XX123456] came from ContainerName [XX78ABCD] ;When Item added to player with source (without SKSE) ; [XX123456] came from [XX78ABCD] ;When Item added to player without source (with SKSE) ; ItemName [XX123456] was picked up or added from nothingness ;When Item added to player without source (without SKSE) ; [XX123456] was picked up or added from nothingness ;When Item removed from player with destination (with SKSE) ; ItemName [XX123456] was placed in ContainerName [XX78ABCD] ;When Item removed from player with destination (without SKSE) ; [XX123456] was placed in [XX78ABCD] ;When Item removed from player without destination (with SKSE) ; ItemName [XX123456] was dropped or removed from nothingness ;When Item removed from player without destination (without SKSE) ; [XX123456] was picked up or added from nothingness I will admit that with it being on the player it would trigger for EVERY item added or removed. So careful use of conditioning and/or states may be in order so that papyrus doesn't get flooded. And yes, if the idea is only for a few containers... the scripting is better served on the container(s). The original poster did not specify one way or the other. Link to comment Share on other sites More sharing options...
Lazauya Posted January 25, 2017 Author Share Posted January 25, 2017 Could use you use  RegisterForMenu(ContainerMenu) and OnMenuOpen(ContainerMen) in conjunction with a container ref walking script? Then you could use GetType for 28 (kContainer), starting with the closest? Im looking for something like IsActive(), or IsOpen(), but finding none. MiscUtil from PapyrusUtil has ObjectReference[] function ScanCellObjects(int formType, ObjectReference CenterOn, float radius = 5000.0, Keyword HasKeyword = none) global native. I think its possible to be creative to get this accomplished but Im fairly new to skyrim scripting. for example: run a while loop inside OnMenuOpen(ContainerMenu) event. Something like: event OnMenuOpen(ContainerMenu)form[] ObjectsNearPlayer=new form[128]bool containerFound=falsefloat searchRadius=.01while searchRadius<=10 && containerFound==falseObjectsNearPlayer=MiscUtil.ScanCellObjects(28, playerRef, searchRadius)nObjectsInRadius=ObjectsNearPlayer.lengthint x=0while x<nObjectsInRadiusformType=ObjectsNearPlayer[x]if formType==28;this is probably the container that has been opened.containerFound=trueelsex+=1endifsearchRadius+=.01endWhileendEvent If you are in a container, that container should be detected in a very small search radius. It couldn't hurt to test. If it works, you now have a function GetOpenContainer(). if you are looking for a specific container you could just attach a script to it, but there is a keyword parameter to that ScanCellObjects() function. Another note is that this script wouldn't in principle work for remote containers, like DeepStorage spell, but you might be able to use keyword to detect remote containers too because there are not many of them.Hm. This method seems feasible. But still a little slow. I'll try some if these out and see what the result is. Link to comment Share on other sites More sharing options...
Lazauya Posted January 25, 2017 Author Share Posted January 25, 2017 Could use you use ÃÂ RegisterForMenu(ContainerMenu) and OnMenuOpen(ContainerMen) in conjunction with a container ref walking script? Then you could use GetType for 28 (kContainer), starting with the closest? Im looking for something like IsActive(), or IsOpen(), but finding none. MiscUtil from PapyrusUtil hasÃÂ ObjectReference[] function ScanCellObjects(int formType, ObjectReference CenterOn, float radius = 5000.0, Keyword HasKeyword = none) global native. I think its possible to be creative to get this accomplished but Im fairly new to skyrim scripting. for example: run a while loop inside OnMenuOpen(ContainerMenu) event. Something like: event OnMenuOpen(ContainerMenu)form[] ObjectsNearPlayer=new form[128]bool containerFound=falsefloat searchRadius=.01while searchRadius<=10 && containerFound==falseObjectsNearPlayer=MiscUtil.ScanCellObjects(28, playerRef, searchRadius)nObjectsInRadius=ObjectsNearPlayer.lengthint x=0while x<nObjectsInRadiusformType=ObjectsNearPlayer[x]if formType==28;this is probably the container that has been opened.containerFound=trueelsex+=1endifsearchRadius+=.01endWhileendEvent If you are in a container, that container should be detected in a very small search radius. It couldn't hurt to test. If it works, you now have a function GetOpenContainer(). if you are looking for a specific container you could just attach a script to it, but there is a keyword parameter to that ScanCellObjects() function. Another note is that this script wouldn't in principle work for remote containers, like DeepStorage spell, but you might be able to use keyword to detect remote containers too because there are not many of them.Hm. This method seems feasible. But still a little slow. I'll try some if these out and see what the result is.Oh, and adding a keyword/script to "special" base objects is a pretty good idea. I overlooked that one. I don't kniw how many I would have to update, but it's definitely worth a go. (Though, if anyone thinks of something else I'm still open to suggestions) Link to comment Share on other sites More sharing options...
lofgren Posted January 25, 2017 Share Posted January 25, 2017 (edited) Why don't you tell us what you are trying to do, and then we will see if we can help. The method you quoted above would be EXTREMELY slow. If you are only concerned with detecting containers that the player has actually activated with the crosshair, you can use a perk entry point. Check run immediately and condition the script to run only when a container is activated. Boom, done. This will not catch vendors, containers activated by script, or NPCs the player gives/receives gifts from. If you want to catch any container that the player interacts with, the only way to do so is after the player has added or removed an item, at which point you can use OnItemAdded/Removed to detect the container. This would also be triggered if items were removed from a container and added to the player (or vice versa) via script, which may be undesirable but could probably be worked around. If you want to detect any container that the player interacts with, regardless of whether they clicked on it directly or activated it via script, before any items have been added or removed, then Papyrus simply can't do it. Edited January 25, 2017 by lofgren Link to comment Share on other sites More sharing options...
cdcooley Posted January 25, 2017 Share Posted January 25, 2017 I'll second lofgren's comments. If you're wanting the container reference before any items are transferred it can't be done in a generic way. I've tried this in the past using every technique described in this thread so far (and a few others) and none of them work well. The only real solution would be an SKSE plugin. With a perk you can capture normal containers but not anything that's scripted which includes many containers, interactions with NPCs, activators that are designed to access remote containers, etc. Using the crosshair doesn't work any better. The container in the crosshair may not be the actual container accessed if the one in the crosshair is scripted to open something else. Searching for the nearest container when the container menu opens is a false and dangerous trail. It will find the wrong container far more often than you would expect. If it's OK to wait until after some item has been transferred then you can get the reference and the only problem is that if the player has a habit of storing massive numbers of things in containers then grabbing them all with "Take All" you'll run into some performance issues (that can be minimized by careful use of states but not eliminated). As far as I know no one has yet created an SKSE plugin that can access the current container's ID. I do know that the information isn't passed through to the user interface files when you open the menu. The display name of the container, whether it's a container or NPC and the list of contents are sent, but nothing about the container itself. So in short, post what you're really trying to accomplish and I can probably tell you if there's a reasonable workaround in Papyrus to get the job done or if you're going to have to write (or get someone else to write) an SKSE plugin. So far I have always found an acceptable workaround for my needs except for the one case where I simply decided it was too much trouble to implement my original idea. Link to comment Share on other sites More sharing options...
NexusComa Posted January 25, 2017 Share Posted January 25, 2017 (edited) Hard to understand how everything said here (by me at least) seems to be taken as some type of insult ... I have made many "container scripts". When I have one I want to use many times I simply create a custom base container by clicking base on the container I want then renaming it ( so I have my own custom version of that base ). Then add the script to that new base I just created. After that I can put down as many containers with that new base as I wish and all use the script with no problems ... Edited January 25, 2017 by NexusComa Link to comment Share on other sites More sharing options...
Lazauya Posted January 25, 2017 Author Share Posted January 25, 2017 What I'm trying to do...Okay, I'll try to explain as well as I can. I'm creating a nondiscrete value based durability system in skyrim, like the ones in morrowind and oblivion. Every weapon/armor will have an associated maximum durability, and every instance of that form will be able to have a unique current durability; this includes objects in the inventory and objects on the ground. Objects on the ground are remarkably easy: no ui data needs to be thrown around, and the durability can be stored in a map where the key is a {coordinates, objectref, cell} object and the value is a {maxdurabilty, durability} pair. Inventories, however are tricky. Firstly, the player should be able to see the durability (im thinking similar to how charge of an enchantment is displayed, but thats nonimportant). Secondly, a player should be able to store more than a single item of the same form in an inventory with unique durabilities. Thirdly, a player should be able to move items with durability between inventories. These mean, however, a few important things:1. Items in the list must be unstacked. I know how to do this.2. A system must be in place to keep track of all the nonempty containers that the player has interacted with. This isn't much different then keeping track of ground objects, but i'll get to that.3. The system keeping track needs to be able to reference specific containers, including the player. In number 2, i mentioned a system. A basic implementation would be a map where the key is an object {objectref, coirdinates, cell} and the value is a vector of objects {ptr to entrydata, durability, maxdurability}. You might think this is a big structure, but the anount if containers included won't actually be that big for most people. It should be easy enough to implement a check that also gets rid of containers that have no items with durability.Number 3 is where i'm hung up on. With a way to get the accessed container, it would be possible to track objects properly and extend the ui with durability information easily. If you would like a further explanation on something, ask.I know how to write skse plugins, but i cant find anything related to the container thing i need. Anyway, woo, writing that on a smartphone was hard. Link to comment Share on other sites More sharing options...
IsharaMeradin Posted January 25, 2017 Share Posted January 25, 2017 @ LazauyaNot sure if you can achieve what you want. I'd wait for cdcooley's response, however. Link to comment Share on other sites More sharing options...
Recommended Posts