Moving Items without Resetting Health, Stolen-Status or Ench

Post » Tue Feb 15, 2011 8:23 pm

I could use some help. I will be working on this in the mean time and will post the solution, if and when I find one.

I am seeking a semi-generic user-defined function for moving items from one container to another that won't reset current object health, owner (or stolen-status), or current enchantment charge, that can be called in the OnActivate block and that excepts the following parameters: FromContainer:ref ToContainer:ref ObjectID:ref and MoveCount:long.

I have all the surrounding code in place and I am currently using RemoveItemNS and AddItemNS to move these things. I don't want to have to change the surrounding code. I am hoping to make this as efficient as possible. To facilitate efficiency, an assumption can be made about items passed as ObjectID. These items will be inventory items of the following types:

19: Apparatus
20: Armor
21: Book
22: Clothing
25: Ingredient
26: Light
27: Misc
33: Weapon
34: Ammo
38: SoulGem
40: AlchemyItem
42: SigilStone

With this in mind another parameter could be FormType:long, though this might not be the case in every application. Possibly FormType could be passed as -1 to force checking the objects type.
User avatar
Mimi BC
 
Posts: 3282
Joined: Sat Oct 07, 2006 10:30 pm

Post » Wed Feb 16, 2011 2:26 am

What the...?
scn TestObjectref Containerref ObjectIDlong ItemCount			; let ItemCount := Container.GetItemCount ObjectIDlong FormTypefloat ItemHealth		; (health:float) reference.GetCurrentHealth	- (nothing) reference.SetCurrentHealth nuHealth:floatfloat ItemCharge		; (charge:float) reference.GetCurrentCharge	- (nothing) reference.SetCurrentCharge newCharge:shortref ItemOwner			; (owner:ref) reference.GetOwner		- (nothing) referenced-item.SetOwnership Ownerstring_var RetStringBegin Function {Container, ObjectID, FormType}	let RetString := "%e"	;let RetString := sv_Construct "Found at %n 
" Container If (FormType == 33) ; Weapon - Breakable, Ownable, Charged let ItemHealth := ObjectID.GetCurrentHealth let ItemCharge := ObjectID.GetCurrentCharge let ItemOwner := ObjectID.GetOwner let ItemCount := Container.GetItemCount ObjectID let RetString := RetString + sv_Construct "
(W) %5.0f - %n's %n H %f, C %f" ItemCount ItemOwner ObjectID ItemHealth ItemCharge ElseIf (FormType == 20) ; Armor - Breakable, Ownable let ItemHealth := ObjectID.GetCurrentHealth let ItemOwner := ObjectID.GetOwner let ItemCount := Container.GetItemCount ObjectID let RetString := RetString + sv_Construct "
(A) %5.0f - %n's %n - H %f" ItemCount ItemOwner ObjectID ItemHealth EndIf SetFunctionValue RetStringEnd

I Looped over Player.GetItems 33 and Player.GetItems 20 in an OnActivate Block (surely the block doesn't matter here) and got all null values for GetCurrentHealth, GetCurrentCharge, GetOwner

I got errors for "Attempting to call a function on a NULL reference or base object."

With the existance of GetBaseItems, I assumed that GetItems returned references. Was I wrong? If so, is there a way to get the references?

Now let's review http://obse.silverlock.org/obse_command_doc.html on these functions.

Health
GetCurrentHealth - returns the current health of the calling reference
(health:float) reference.GetCurrentHealth
SetCurrentHealth - sets the current health of the calling reference
(nothing) reference.SetCurrentHealth nuHealth:float

GetEquippedCurrentHealth - gets the current health of the object in the specified equipment slot
(health:float) reference.GetEquippedCurrentHealth slot:short
SetEquippedCurrentHealth - sets the current health of the object in the specified equipment slot
(nothing) reference.SetEquippedCurrentHealth nuHealth:long slot:short

Charge
GetCurrentCharge - returns the current charge of the calling reference
(charge:float) reference.GetCurrentCharge
SetCurrentCharge - sets the current charge of the calling reference if it is less than or equal to the maximum charge
(nothing) reference.SetCurrentCharge newCharge:short

GetEquippedCurrentCharge - returns the current charge of the object in the specified slot
(charge:float) reference.GetEquippedCurrentCharge slot:short
SetEquippedCurrentCharge - sets the current charge of the object in the specified slot
(nothing) reference.SetEquippedCurrentCharge nuCharge:long slot:short

According to ShadeMe on http://www.gamesas.com/index.php?/topic/1005280-obse-syntax-base-objects-vs-refs/page__view__findpost__p__14545792:
-SNIP- ... getObjectHealth must be called on an inventory object, and on either a reference or a base record. Same for getCurrentHealth but it can't be called on a base object for obvious reasons. Also, active attributes of inventory objects ( like health and charge ) can only be accessed ( when in a container/inventory ) if it happens to be equipped. -SNIP-


If what ShadeMe says is true, why do the functions GetCurrentHealth, SetCurrentHealth, GetCurrentCharge and SetCurrentCharge exist? What are they for? How do I use them? My need's won't allow for equipping each item and using GetEquippedCurrentHealth, SetEquippedCurrentHealth, GetEquippedCurrentCharge and SetEquippedCurrentCharge.
User avatar
x a million...
 
Posts: 3464
Joined: Tue Jun 13, 2006 2:59 pm

Post » Wed Feb 16, 2011 1:34 am

I Looped over Player.GetItems 33 and Player.GetItems 20 in an OnActivate Block (surely the block doesn't matter here) and got all null values for GetCurrentHealth, GetCurrentCharge, GetOwner

I got errors for "Attempting to call a function on a NULL reference or base object."

With the existance of GetBaseItems, I assumed that GetItems returned references. Was I wrong? If so, is there a way to get the references?
There aren't any references inside a container - Just a base item and an ExtraData list. GetItems returns an array populated with the calling reference's current inventory items. GetBaseItems returns an array populated with the calling reference's base record's inventory items (the list you can look up in the CS).

OBSE 19 will add commands to directly modify item extradata in containers.


According to ShadeMe on http://www.gamesas.com/index.php?/topic/1005280-obse-syntax-base-objects-vs-refs/page__view__findpost__p__14545792:

If what ShadeMe says is true, why do the functions GetCurrentHealth, SetCurrentHealth, GetCurrentCharge and SetCurrentCharge exist? What are they for? How do I use them? My need's won't allow for equipping each item and using GetEquippedCurrentHealth, SetEquippedCurrentHealth, GetEquippedCurrentCharge and SetEquippedCurrentCharge.
Ignore that misleading post of mine - I was probably high when I typed it.
User avatar
Alex [AK]
 
Posts: 3436
Joined: Fri Jun 15, 2007 10:01 pm

Post » Tue Feb 15, 2011 5:25 pm

OBSE 19 will add commands to directly modify item extradata in containers.

Extradata... Sounds good... I think. Hmm. Could you explain more about extradata?
User avatar
Dark Mogul
 
Posts: 3438
Joined: Tue Feb 20, 2007 11:51 am

Post » Wed Feb 16, 2011 2:21 am

An item's ExtraData is what makes it different from other items of the same type. For example, you have one Iron Longsword with 100 durability, one with 125 durability, and another with 75. They're all the same item, but they're also different. Other things that can differ from items of the same type are charge, ownership, scale, script variables, etc.

The fact that items in a container don't normally have references is just a technicality of how Oblivion works. All you need to realize is that you cannot refer to a specific item within a container in a script.

That said, there is currently a way to move items between containers without losing their ExtraData, but it has limitations and is rather clunky. It relies on exploiting how RemoveAllItems works with quest items and how it treats the player in a different manner than it treats other containers.

Limitations:
1) It can move all or none of an item. If you have 10 Iron Longswords, you can't move all but one.
2) The player has to be used as an intermediary container if you're moving items from two arbitrary containers.
3) The player's equipment has to be unequipped before the move, and re-equipped when the move is complete.

The entire process works, but is error prone. I'd highly suggest just waiting for OBSE v19 to be released. Otherwise, you can look at Wolfhound's Speedy Depositing to see how you can move items from the player into a container, and at my Speedy Looting mod for an idea of how to move items from a container to the player. Be forewarned, the scripting in Speedy Looting is not for the faint of heart.
User avatar
Heather Stewart
 
Posts: 3525
Joined: Thu Aug 10, 2006 11:04 pm

Post » Tue Feb 15, 2011 6:36 pm

That said, there is currently a way to move items between containers without losing their ExtraData, but it has limitations and is rather clunky. -Snip-
The entire process works, but is error prone.


Aye. I know.

I'd highly suggest just waiting for OBSE v19 to be released. -Snip-


Aye. Will do.

Like I said I have the surrounding code in place. Actually, I am moving items at this point, which gives this mod a cheat factor.

Thanks for the explanation on ExtraData. That seems logical. I can't wait to see the documentation on the functions involving ExtraData. Would be nice to know what I am in for, so I can let the concepts mull around in my head in the mean time.

Edit: Grammer/Spelling
User avatar
Hot
 
Posts: 3433
Joined: Sat Dec 01, 2007 6:22 pm


Return to IV - Oblivion