Lazauya Posted January 25, 2017 Author Share Posted January 25, 2017 (edited) I'm very confident that it is possible. Essentially, i have everythibg written--just under the assumption that i can get a function for the container. Edited January 25, 2017 by Lazauya Link to comment Share on other sites More sharing options...
irswat Posted January 25, 2017 Share Posted January 25, 2017 (edited) I think what I suggested is worth a try. I can think of circumstances where it might fail, but even then I think it should work. One instance that comes to mind is looting piles of dead npcs. Honestly, because it is the sort of script that is firing only on opening container menu events I don't think it will be as slow as you would think. I had to use some unconventional methods in creating my parser engine for SVCE and there are some methods that I was certain were going to be unbearably slow that ended up being much much faster than I expected after testing and minor optimizations.I'd be more concerned about accuracy, but if you include code, for example sorting in ascending order, the closest container should yield the correct container most of the time. However I must say Ive never used the scancellobjects function, but I know the other PpayrusUtil functions are very well optimized. I assume its a ref walking script at its core. I helped work on the playable fallout mech for FO:NV which used a ref walking script much more intensive than this, and it was acceptably quick. Again I don't think speed will be the problem, but there may be accuracy limitations which you may or may not be able to circumvent with some creativity. Edited January 25, 2017 by irswat Link to comment Share on other sites More sharing options...
cdcooley Posted January 26, 2017 Share Posted January 26, 2017 If you are willing to let the durability values for items that start in containers be undefined until the player actually takes them (which to me seems the logical choice) the event filter scheme is the best option. You can detect every item that enters and leaves the player's inventory very easily. The only problem is that Papyrus gets temporarily overloaded if you do a Take All on a container with huge numbers of items. But you'll have to deal with that eventually anyway and it will eventually recover (even if some players freak out because they have the Papyrus log turned on). When the player takes an item you'll know which container it came from (or if it was picked up from the world instead of a container). When the player drops an item or places it in a container you'll also know where it went. If you make the player actually pick up an item before being able to check the durability, then there's absolutely no downside to that scheme. You can assign any new items a random durability when the player picks it up. The implementation is also very simple. Just put the player in an alias and use a script on the alias with the OnItemAdded and OnItemRemoved events. I think you'll find the bigger problem being that once an item is in a container (including the player's inventory) the game aggressively tries to stack it with others with the same formId value. And providing a UI for this will be an interesting challenge. But that's not the question at hand. Link to comment Share on other sites More sharing options...
lofgren Posted January 26, 2017 Share Posted January 26, 2017 You can literally stand on top of a container while activating another, so I don't see testing for the nearest container being very accurate. It would also give inaccurate results in the case of vendors and scripted containers. I only mentioned speed because the OP thought that the OnItemAdded/Removed method would be too slow, when it would definitely be faster than the polling method. I don't see any advantage that the polling method would have over the perk method, which would return the actual container that the player activated without any ambiguity. Link to comment Share on other sites More sharing options...
Lazauya Posted January 26, 2017 Author Share Posted January 26, 2017 (edited) If you are willing to let the durability values for items that start in containers be undefined until the player actually takes them (which to me seems the logical choice) the event filter scheme is the best option. You can detect every item that enters and leaves the player's inventory very easily. The only problem is that Papyrus gets temporarily overloaded if you do a Take All on a container with huge numbers of items. But you'll have to deal with that eventually anyway and it will eventually recover (even if some players freak out because they have the Papyrus log turned on). When the player takes an item you'll know which container it came from (or if it was picked up from the world instead of a container). When the player drops an item or places it in a container you'll also know where it went.ÃÂ If you make the player actually pick up an item before being able to check the durability, then there's absolutely no downside to that scheme. You can assign any new items a random durability when the player picks it up. ÃÂ The implementation is also very simple. Just put the player in an alias and use a script on the alias with the OnItemAdded and OnItemRemoved events.ÃÂ I think you'll find the bigger problem being that once an item is in a container (including the player's inventory) the game aggressively tries to stack it with others with the same formId value. And providing a UI for this will be an interesting challenge. But that's not the question at hand.Hm, I think that idea is okay. I can have items say "this item needs to be inspected further" or something before the player has put it in thier own inventory. It's kind of cheeky, and from a usability aspect there is a downside: a player can't know the durability before they pickup the item, even if it has a durability a durabilty. Of course, the slightly less cumbersome (but still really cheeky) method would be to say "this container needs to be inspected further" and give durabilities to all items when the player interacts with the container. But as of now the onitemremoved/added methods are the only ones really practical, and as @lofgren mentioned the polling one may not work so great. So I will, for now, (begrudgingly) use onitemremoved/added. The stacking isn't really a problem. The game doesn't "agressively" stack items like you say, instead it only tries to stack items added to the inventory, and only does so on the first entry matching the proper criteria. After an onitemaddeItemCount event, i can just call my "unstack" function. There are still problems that arise from this, but it's better than nothing. Alternatively, I thought of doing the unstacking in Scaleform, and as I'm writing this I might have just come up with another hassle free solution. I can use the ItemCount property on the scaleform entrties and add extra entries on updatelist. Ooooh, this is so much less intrusive then unstacking it in the backend! Aaaaaaah! Edited January 26, 2017 by Lazauya Link to comment Share on other sites More sharing options...
irswat Posted January 26, 2017 Share Posted January 26, 2017 You can literally stand on top of a container while activating another, so I don't see testing for the nearest container being very accurate. It would also give inaccurate results in the case of vendors and scripted containers. I only mentioned speed because the OP thought that the OnItemAdded/Removed method would be too slow, when it would definitely be faster than the polling method. I don't see any advantage that the polling method would have over the perk method, which would return the actual container that the player activated without any ambiguity.it's slow because of how OnItemAdded()/OnItemRemoved() work. I'd suggest reading the wiki entry on these events. Link to comment Share on other sites More sharing options...
lofgren Posted January 26, 2017 Share Posted January 26, 2017 (edited) Just did and I didn't see any reason it would be slower than running multiple operations. In all honesty I was puzzled by the concern over the speed of these functions as they have always seemed instantaneous to me. Edited January 26, 2017 by lofgren Link to comment Share on other sites More sharing options...
irswat Posted January 26, 2017 Share Posted January 26, 2017 I don't want to assume because Im fairly new to skyrim modding as well, but I think perhaps he was talking about when you take all. You read the wiki entry and didn't see this? If the player takes a large number of items out of a container (e.g. by using the Take All feature while in their home), an OnItemAdded event handler that doesn't use an inventory filter will be queued to run for each type (base form) of item that the player removes. If a container has a considerably large variety of items inside, too many OnItemAdded calls will accrue, causing Skyrim to just throw away those queued function calls as well as calls from other mods and DLCs (this is called "dumping stacks"). By contrast, an OnItemAdded handler with an event filter won't even be queued to run unless the item being added matches that filter; that handler won't cause stack dumping unless the player adds a huge number of the specific item that the handler is looking for, and even that would only happen if the player added all of those items one-by-one.Problems can also occur if the player picks up a large number of items in rapid succession (e.g. because they're thoroughly looting an interior, or because they like picking flowers as they walk). If your OnItemAdded handler is slow (perhaps it accesses a shared resource, such as the player), and if you're not using an inventory event filter, then queued OnItemAdded calls can pile up. Chances are good that the player will eventually stop picking up items and give your script calls enough time to finish, but if the player doesn't stop for a long enough while, then your script may eventually cause Skyrim to dump stacks.If you need to temporarily stop OnItemAdded and OnItemRemoved calls from being queued, you can use AddInventoryEventFilter with an empty FormList as an argument. To resume listening for item additions and removals, you can call RemoveAllInventoryEventFilters.This trick stops OnItemAdded calls from being queued. It doesn't prevent the execution of function calls that have already been queued. To wit, using this trick from inside of OnItemAdded won't stop Skyrim from dumping stacks when you Take All from a QASmoke container, because the first OnItemAdded call only executes after the other hundred or so have been queued. Rather, you'd want to stop listening to inventory events from elsewhere (e.g. an OnMenuOpen event checking for inventory menus, if you don't mind relying on SKSE). Link to comment Share on other sites More sharing options...
cdcooley Posted January 27, 2017 Share Posted January 27, 2017 That warning is actually wrong. Stack dumps are just a debugging scheme the game uses to signal the Papyrus system is falling behind. No information is actually lost. It's true that a Take All operation can temporarily overwhelm the system, but it's not nearly as big of a problem as people originally thought. No queued calls are lost. You do want to make sure the event code runs as quickly as possible. If you're only wanting to give durability to armor and weapons then make sure your code starts with something like this to quickly skip over other types of items. (And yes, casting a base formid to a type is the fastest way to do that check.) Code in those event handlers are one of the rare cases where every last bit of optimization is justified and function calls (like GetType) should be avoided unless absolutely needed. if !(akBaseItem as Weapon || akBaseItem as Armor) return endif Link to comment Share on other sites More sharing options...
lofgren Posted January 27, 2017 Share Posted January 27, 2017 I saw it but it's not really relevant, nor does it indicate that the function is slow, so for those two reasons I don't think that's what he was referring to. Link to comment Share on other sites More sharing options...
Recommended Posts