Jump to content

How harmful is "GetNumItems"?


Recommended Posts

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
End

Yet, 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

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

Redited original response:

 

 

Hmmm... I just checked your use of that again.

Let Arrowvar := player.getnumitems arrowammount

I think you are mistaking GetNumItems

https://cs.elderscrolls.com/index.php?title=GetNumItems

with GetItemCount :wink:

https://cs.elderscrolls.com/index.php?title=GetItemCount

 

 

GetNumItems DOES NOT require any item ID, but just the container / actor ref.

Player.GetNumItems

Will 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 function

Even 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

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 by KatsAwful
Link to comment
Share on other sites

@KatsAwful

Well, 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.

 

 

 

 

@Pellape

Thanks, 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

@KatsAwful

Well, 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

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

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...