Can I access item references for items in the inventory?

Post » Sun Nov 18, 2012 5:15 am

I want my mod to operate on items in a player's inventory, and I think I need the actual items by reference, not just type. The reason is that I want to operate on Soul Gems, which are special in that individual instances have a soul amount which varies greatly. Empty soul gems and soul gems filled by monsters all have the same item base, for example "SoulGemCommon", but I want to treat them differently based on their soul amount.

I can count how many soul gems there are with GetItemCount but I can't figure out how to access individual gems, and figure out how much soul is in them.

Can anyone help?
User avatar
Franko AlVarado
 
Posts: 3473
Joined: Sun Nov 18, 2007 7:49 pm

Post » Sun Nov 18, 2012 3:33 pm

Yes, provided the ObjectReference is persistent and/or is filling an alias.

Ghostblade, for instance, will retain its FormID throughout the game even when its in your inventory since its REFR is persistent. If you want to ensure a particular ObjectReference, ExcaliburREF, is given to the player, you can place it somewhere, then point a property at it which will set it as persistent. From there, either...
ObjectReference Property ExcaliburREF AutoEvent OnActivate(ObjectReference akActionRef)	If (akActionRef As Actor).HasntGotSh1tAllOverHim() ; He is a king!		akActionRef.AddItem(ExcaliburREF)	EndIfEndEvent
...or...
Actor Property KingArthurREF AutoReferenceAlias Property ExcaliburAlias Auto ; Filled w/ ExcaliburREFEvent OnActivate(ObjectReference akActionRef)	If akActionRef == KingArthurREF		akActionRef.AddItem(ExcaliburAlias.GetReference())	EndIfEndEvent
...will give THE Excalibur blade.

Some aspects of non-persistent REFRs are also retained, it seems, like scale. If you place a non-persistent wooden spoon REFR that's ginormous and "Take" it, it'll still be huge when you drop it from your inventory. I'm not sure, however, how long the game retains such info for such non-persistent ObjectReferences.
User avatar
Hilm Music
 
Posts: 3357
Joined: Wed Jun 06, 2007 9:36 pm

Post » Sun Nov 18, 2012 4:29 am

How about soul gems? I imagine they must be persistent somehow: every soul gem that was initially empty is distinct in your inventory (it doesn't stack, and sells for the same price as empty). Can I get access to them somehow?
User avatar
clelia vega
 
Posts: 3433
Joined: Wed Mar 21, 2007 6:04 pm

Post » Sun Nov 18, 2012 7:00 pm

Cant say I ever noticed they sell for the same prices empty/filled in game, never tried to sell them either, just use them myself.

But could be an easy fix for the price of empty/filled SoulGems?

In the creation kit under items/soul gems you'll notice 2 of each type, one empty/one filled.
The filled ones all have a higher price.

But you'll also notice that if you load the empty Grand or Black types they are linked with the filled counterparts and the rest are not.
I'd guess that due to the fact that the empty petty/lesser/common/greater are not linked to the filled counterparts is the reason they stay the same price?
Yet there would still be no way to tell if that black soul gem is filled with a wolf's soul or a humans.
That info just isnt available in the editor and whats not in the editor normally cant be gotton with a script.

Quick and easy way to check the price staying the same.
Open CK and link the empty gems to the filled gems the way grand/black soulgems are, save & test it out.
Post back if it works or not.
User avatar
Trevor Bostwick
 
Posts: 3393
Joined: Tue Sep 25, 2007 10:51 am

Post » Sun Nov 18, 2012 12:02 pm

Well, the point isn't to fix the price issue. The point is to figure out what size soul is stored in each gem in the player's inventory, but that just seems impossible.
User avatar
Blackdrak
 
Posts: 3451
Joined: Thu May 17, 2007 11:40 pm

Post » Sun Nov 18, 2012 10:42 am

Here ya go, needs SKSE

SKSE Member Functions
int Function http://www.creationkit.com/index.php?title=GetSoulSize_-_SoulGem&action=edit&redlink=1()
  • Returns the default soul size held in the base form of the soul gem.
int Function http://www.creationkit.com/index.php?title=GetGemSize_-_SoulGem&action=edit&redlink=1()
  • Returns the size of the soul gem.
User avatar
Rozlyn Robinson
 
Posts: 3528
Joined: Wed Jun 21, 2006 1:25 am

Post » Sun Nov 18, 2012 3:37 am

Right, you can get the soul size with SKSE, but you can't actually get access to the item references you would need to make that work. Maybe I can just do something wonky, like move items silently, one-by-one to a hidden chest with a OnItemAdded trigger on it.
User avatar
Breautiful
 
Posts: 3539
Joined: Tue Jan 16, 2007 6:51 am

Post » Sun Nov 18, 2012 7:37 am

Sorry, not gonna test this out for ya right now, got other projects going on ATM.

Try an OnItemAdded event with a Debug.MessageBox("BaseID is " + akBaseItem) as the events only function.

Without the empty Gems being linked to their filled counterparts,
I'd seriously doubt it would return the BaseID of the filled gem no matter how large/small the soul inside is.

The exceptions to this would be the Grand and Black gems.
I'd guess these would work just fine, Because they are in fact linked,
So even a petty soul in a black gem should return 002E504 because it is in fact full.

Likewise if you found/bought a greater soulgem thats filled, drop it on the ground (removes the traqed soul)
akBaseItem would more than likely return 0002E4FB rather than 0002E4F4 (as it should) even though its now empty.

BaseID's for each type empty/filled,
BaseID's will never change & akBaseItem from the OnItemAdded event returns just that, the BaseID!
Petty empty 0002E4E2 filled 0002E4E3
Lesser empty 0002E4E4 filled 0002E4E5
Common empty 0002E4E6 filled 0002E4F3
Greater empty 0002E4F4 filled 0002E4FB
Grand empty 0002E4FC filled 0002E4FF
Black empty 0002E500 filled 0002E504

Gonna try this out myself when I get a chance,
Realize it or not, you may have stumbled accross an oversight when they made the game?

And as for the SKSE function, GetSoulSize.
Thats looking at only the size of the soul inside the gem thats passed to it.
In otherwords, it should still get ya what you are looking to do.
User avatar
Kayla Oatney
 
Posts: 3472
Joined: Sat Jan 20, 2007 9:02 pm

Post » Sun Nov 18, 2012 6:12 pm

I wouldn't call it an oversight, exactly. Just a hardcoded hack.

For example, a Common gem you get that is initially filled (from a vendor or a chest, for example) will have SoulGemCommonFilled (0002E4F3) as its base type. This item is not persistent, so it stacks, and is worth 150. A Common gem that is *not* initially filled has base type SoulGemCommon (0002E4E6) and it is worth 50. When it is empty (you just picked it up) it is non-persistent and stacks, but when a soul is trapped, it is given a persistent object reference for as long as it is in your inventory, which means it no longer stacks, but it is still a SoulGemCommon and is still worth 50. This is the source of some weird behavior (try dropping a non-stacking gem and picking it up again, it resets to empty). Anyways, this persistent item reference is stored somewhere in memory. For example, if you have a handle on it you can call GetSoulSize from SKSE. When the game wants to use the gem, for example to enchant an item, it does some hardcoded jiggerypokery to examine the persistent item reference for a given gem, or to just use the non-persistent SoulGemXXXFilled variety. This is hard-coded, you won't find any script defining how this works. Similarly, trapping a soul is hard-coded magic too: scripts can't actually find empty soul gems in the player's inventory, they can only call the native TrapSoul function which examines some internal rules to find a suitable empty gem and fill it (which amounts to giving it a persistent reference with a soul size, and notably does *not* remove or add any items, or give the player a SoulGemXXXFilled item).

Basically, if you want to override this behavior, as I do, you have to resort to total hacks. My current plan is to do the following: silently move all gems of all types to a dummy hidden chest somewhere, just before the Trap Soul effect finishes. Then I repeatedly give the player increasingly powerful soul gems (petty -> lesser -> common -> greater -> black) until victim.TrapSoul() succeeds, at which point I play the TrapSoul animation and give them a SoulGemXXXFilled item. Finally I return all their old gems, except for one empty variety of the kind that succeeded. Since I can't tell how much soul that particular gem has, I might be replacing a "trapped" soul of sufficient size with a SoulGemXXXFilled item which basically means the soul trap accomplishes nothing, but this can only happen once per trapped soul, and if a player just plays with my mod all the time it will never come up.

This is super hacky, and I hate that I might overwrite trapped souls, but it accomplishes what I want to (make sure not to waste big gems on small creatures).
User avatar
Carlos Rojas
 
Posts: 3391
Joined: Thu Aug 16, 2007 11:19 am


Return to V - Skyrim