JustChill Posted February 23, 2021 Share Posted February 23, 2021 I used to take over a script that actually uses if Ref.GetInventoryObject 0 else ;===> There is something in the inventory of the ref endif for checking if an enemy corpse has something in the inventory for the "Disintegrate corpse" spell of Nehrim Expanded (now implemented in the Nehrim Magic Overhaul). Yet, the problem with that was, that it also runs the ELSE-block, when there are non-playable items in the inventory.Which triggers the same behavior (warning messagebox) as if there were items in the inventory.So I saw no other solution than running through the inventory, checking for non-playable items: Begin ScriptEffectFinish Set ZielRef to GetSelf If ZielRef.IsActor && ZielRef.GetDead Let ZielInventarCount := ZielRef.GetNumItems ;=> CPU-heavy, so rather safe it into if ZielInventarCount > 0 ;=> a variable! While ZielInventarCounter < ZielInventarCount ;=> GetInventoryObject starts with inventory index 0 Let ZielInventarRef := (ZielRef.GetInventoryObject ZielInventarCounter) ;=>so no <= again in the loop condition. ;) if IsPlayable2 ZielInventarRef else Let ZielNotPlayableCounter += 1 endif Let ZielInventarCounter += 1 Loop endif if ZielNotPlayableCounter == ZielInventarCount ;=> When only non-playable items are available, Let ZielInventarRef := 0 ;=> we set the reference to 0, as if there would be no item in the inventory endif Let ZielNotPlayableCounter := 0 Let ZielInventarCounter := 0 if ZielInventarRef ;=> There are items in the inventory else ;=> There are NO, or only non-playable items in the inventory endif endif EndYet, I have never used "GetNumItems" before, as the wiki says it's a bad command. Does someone has experience using it? Could this script really harm the game, just because of using that function? Cheers Link to comment Share on other sites More sharing options...
Pellape Posted February 24, 2021 Share Posted February 24, 2021 I do not know really. I use it a lot, specially in my dynamic sorter and I bet even Wrye uses it in the alchemy sorter if I recall right. If we don not use it, the code will take longer time really, specially if you handle a big stack. Lets say you have 1k arrows. While ( arrows ) chest.additem arrow 1 player.removeitem arrow 1 loop and that is what we used to do in Morrowind when it is more optimal to Let Arrowvar := player.getnumitems arrowammount chest.additem Arrowvar arrowammount player.removeitem Arrowvar arrowammount Link to comment Share on other sites More sharing options...
JustChill Posted February 24, 2021 Author Share Posted February 24, 2021 Redited original response: Hmmm... I just checked your use of that again. Let Arrowvar := player.getnumitems arrowammountI think you are mistaking GetNumItemshttps://cs.elderscrolls.com/index.php?title=GetNumItemswith GetItemCount :wink:https://cs.elderscrolls.com/index.php?title=GetItemCount GetNumItems DOES NOT require any item ID, but just the container / actor ref.Player.GetNumItemsWill return how many different items the player has in its inventory. It is normally used to walk through the whole inventory of a container / actor, as it can be used as maximum index value,when using "Player.GetInventoryObject <index>". But here are some notes on the Wiki page, that are concerning: Using this function every frame will significantly drop FPS. The more items that have to be scanned, the worse it is (i.e., 1 item a frame will drop it by 3, 15 by 25). Use this function only when necessary, and try to avoid using it in GameMode.There are several ways to use GetInventoryObject instead of GetNumItems (keep in mind that it is also CPU-heavy, but not as much)v0013 significantly improves the efficiency of this functionEven though it's stated that the effiiciency got improved, I would still like to hear about experiences using this function. As I avoid stuff like this or "PlaceAtMe" like the plague. ^^ Link to comment Share on other sites More sharing options...
KatsAwful Posted February 24, 2021 Share Posted February 24, 2021 (edited) Why not use inventory references? It doesn't have the same performance hit from my experience and it seems like that's all you need for your original post. The latest releases of xOBSE and OBSE does have a ghost bug, but that will be fixed with the next xOBSE release Example: ForEach item <- container ; do stuff with item, a temporary reference of the current item in a container ; this item will be gone on the next loop ; and if RemoveItemIR is used Loop Edited February 24, 2021 by KatsAwful Link to comment Share on other sites More sharing options...
Pellape Posted February 25, 2021 Share Posted February 25, 2021 Sorry JustChill, you are right of course but you did got it anyway. I do use both in my sorting script, checking how many different objects there is in a container and the stack sizes. Link to comment Share on other sites More sharing options...
JustChill Posted February 25, 2021 Author Share Posted February 25, 2021 @KatsAwfulWell, I barely use ForEach as I still struggle with its functionality.I doubt that "item" and "container" are set up in OBSE to work like that?These are just variables in your example I guess? Where "container" is an array and "item" is a reference variable? Furthermore I am not using xOBSE, as Nehrim doesn't have it and I am not making mods where users have to update their OBSE. Arthmoor also didn't really appreciate me using SkyBSA as requirement for the Unofficial Nehrim Fixes, as I simply wanted to pack all fixed Unofficial Oblivion Patch resources into a BSA. ^^It's just that I love BSAs, but without SkyBSA, they are not really getting loaded properly in Oblivion. But I understand that it is a struggle adding new requirements for mods. I know that OBSE has issues, but currently it's the only solution for Nehrim.If people want to fix that, they have to update to xOBSE themselves, but currently Nehrim just uses the OBSE version from Silverlock in its default installation. @PellapeThanks, I'll stick with it then.I don't think that any of these dead NPCs has a an enormous amount of items in its inventory, so it shouldn't be that bad. :smile: Link to comment Share on other sites More sharing options...
Pellape Posted February 25, 2021 Share Posted February 25, 2021 Well does it matter if you use it or not? You can still recommend others to use it as well, why stay in the passed with old stuff? Link to comment Share on other sites More sharing options...
JustChill Posted February 25, 2021 Author Share Posted February 25, 2021 As it is not that common unfortunately.I agree with Arthmoor there and I would have removed the dependency of SkyBSA on my mod, if I wouldn't be that mad about using BSAs. ^^ Link to comment Share on other sites More sharing options...
KatsAwful Posted February 25, 2021 Share Posted February 25, 2021 @KatsAwfulWell, I barely use ForEach as I still struggle with its functionality.I doubt that "item" and "container" are set up in OBSE to work like that?These are just variables in your example I guess? Where "container" is an array and "item" is a reference variable? In an inventory reference foreach loop, the 'item' is the specific and current inventory reference found in any container named 'container'. So if you want to walk through the player's inventory you can do something like this: ref item ref container ... let container := PlayerREF ForEach item <- container let itemCount += 1 ; if you need item count at all ; do stuff Loop OBSE will process over every unique item stored in the player's inventory, allowing you to perform reference specific functions to them (like see if an item is stolen). However it works over unique references, so if you have 10 iron arrows that aren't stolen then OBSE will process them as one group of items. This is quite efficient and doesn't require you to know the entire inventory of some container since it happens sequentially. It's the simplest of the ForEach loops, and the OBSE bug is able to be worked around (the bug being an extra item that counts towards item count) However, as xOBSE diverges the importance of using it will begin to become apparent. The inventory reference bug is only a small part of what llde has planned, and once the next release comes out with the merged changes to the let statement, the speedup benefits will begin to be important Link to comment Share on other sites More sharing options...
JustChill Posted February 25, 2021 Author Share Posted February 25, 2021 Hey, thanks for the details. The only thing where I know it's used in my mods is where I simply took over the script from Nehrim Expanded. ^^ ForEach NMOactiveSpellEffectsPlayer <- (Player.GetActiveEffectCodes) let NMOeffectIndex := NMOactiveSpellEffectsPlayer["value"] if (MagicEffectUsesCreatureC NMOeffectIndex) let NMOeffectKey := NMOactiveSpellEffectsPlayer["key"] let NMOsingleBaseNpcREF := Player.GetNthActiveEffectSummonRef NMOeffectKey if NMOSummonedRef1 == 0 && NMOsingleBaseNpcREF if NMOSummonedRef2 == 0 && NMOSummonedRef3 Let NMOSummonedRef1 := NMOsingleBaseNpcREF elseif NMOSummonedRef2 != NMOsingleBaseNpcREF && NMOSummonedRef3 != NMOsingleBaseNpcREF Let NMOSummonedRef1 := NMOsingleBaseNpcREF endif endif if NMOSummonedRef2 == 0 && NMOsingleBaseNpcREF if NMOSummonedRef1 == 0 && NMOSummonedRef3 == 0 Let NMOSummonedRef2 := NMOsingleBaseNpcREF elseif NMOSummonedRef1 != NMOsingleBaseNpcREF && NMOSummonedRef3 != NMOsingleBaseNpcREF Let NMOSummonedRef2 := NMOsingleBaseNpcREF endif endif if NMOSummonedRef3 == 0 && NMOsingleBaseNpcREF if NMOSummonedRef1 == 0 && NMOSummonedRef2 == 0 Let NMOSummonedRef3 := NMOsingleBaseNpcREF elseif NMOSummonedRef1 != NMOsingleBaseNpcREF && NMOSummonedRef2 != NMOsingleBaseNpcREF Let NMOSummonedRef3 := NMOsingleBaseNpcREF endif endif Set NMOsingleBaseNpcREF to 0 endif Loop This will generate 3 references for the summoned creatures of the player, but I barely knew why or how it works. It just works. ^^ So I guess "<-" means that like in your example every item from the container gets translated into the item reference.Pretty interesting. :) Link to comment Share on other sites More sharing options...
Recommended Posts