Any way to remove all unequipped items?

Post » Thu Jun 21, 2012 6:57 pm

I have a function that revolves around removeallitems, and what I'd dearly love is to make it such that it removes all items that aren't equipped. Possible?
User avatar
Georgine Lee
 
Posts: 3353
Joined: Wed Oct 04, 2006 11:50 am

Post » Thu Jun 21, 2012 4:55 pm

I'm up against this very same problem for Bag of Holding and have resolved to drop everything equipped by equipping a dummy item that takes all the applicable slots after setting my player alias in a "Catch" state with an OnObjectUnequipped event where each unequipped item is dropped, disabled, and added to an ObjectReference array. From there, all the remaining, unequipped items can be removed and, afterward, I walk through the array, enable the dropped stuff, have Player activate them to take 'em back, then re-equip each item. By excluding the equipped items, the move happens a lot faster, but momentarily strips the player.

There are other ways, but they're painfully slooooooow. Here's one I abandoned:

Spoiler
			aiListIndex = (BagOfHoldingSortApparelAllFLST.GetSize() - 1) ; This is a FormList of FormLists			While (aiListIndex > -1)				akCurrentList = BagOfHoldingSortWeaponsAllFLST.GetAt(aiListIndex) As FormList				If PlayerREF.GetItemCount(akCurrentList)					If PlayerREF.IsEquipped(akCurrentList)						aiListIndex = (akCurrentList.GetSize() - 1)						While (aiListIndex > -1)							akCurrentForm = akCurrentList.GetAt(aiListIndex) As Armor							If PlayerREF.IsEquipped(akCurrentForm)								PlayerREF.RemoveItem(akCurrentForm, PlayerREF.GetItemCount(akCurrentForm) - 1, True, Self)							Else								PlayerREF.RemoveItem(akCurrentForm, PlayerREF.GetItemCount(akCurrentForm), True, Self)							EndIf							If PlayerREF.GetItemCount(akCurrentList)								aiListIndex -= 1							Else								aiListIndex = -1							EndIf						EndWhile						aiListIndex -= 1					Else						PlayerREF.RemoveItem(akCurrentList, PlayerREF.GetItemCount(akCurrentList), True, Self)						aiListIndex -= 1					EndIf				Else					aiListIndex -= 1				EndIf			EndWhile
User avatar
Siobhan Wallis-McRobert
 
Posts: 3449
Joined: Fri Dec 08, 2006 4:09 pm

Post » Thu Jun 21, 2012 2:53 pm

Here's the problem, I'm not sure dead actors can equip things. It's not in the wiki, but I'm having trouble getting it to work.
User avatar
Rachel Eloise Getoutofmyface
 
Posts: 3445
Joined: Mon Oct 09, 2006 5:20 pm

Post » Fri Jun 22, 2012 1:50 am

So what's the context? Are you trying to auto remove all but equipped items from a corpse with a hotkey or something? Are you opposed to requiring SKSE?
User avatar
roxxii lenaghan
 
Posts: 3388
Joined: Wed Jul 05, 2006 11:53 am

Post » Thu Jun 21, 2012 9:56 pm

My mod already required SKSE. For context, I'd just look at the other thread I have up, the one with Pilfer in the title.

Then I'd go and download Pilfer, because it will make your life better.
User avatar
Rhysa Hughes
 
Posts: 3438
Joined: Thu Nov 23, 2006 3:00 pm

Post » Thu Jun 21, 2012 11:02 pm

Doesn't SKSE have inventory traversal functions? GetNumItems/GetNthForm. So rather than the intermediary of the chest, can you just cycle through the dead actor's inventory, and only transfer the items over the threshold ratio--either ignoring all items that are equipped, or only unequipping and transferring the valuable ones?
User avatar
Andrew Lang
 
Posts: 3489
Joined: Thu Oct 11, 2007 8:50 pm

Post » Thu Jun 21, 2012 3:19 pm

Traversing with GetNumItems and GetNthForm will work but it is very slow compared to the way Il Ducey is currently doing things. For the corpse looting purpose it should be fine though since that doesn't have to happen spontaneously. And most NPCs don't have more than a dozen or so items in their inventory so it shouldn't take more than two or three seconds. Just be aware that every time you remove an item from the NPC the index position of other items can and usually will shift. Since you'll be removing all but a small set of items it will be more efficient to work from the beginning of the list, so the code would have to be something like this:
   int n = 0   item = theNPC.GetNthForm(n)   while item      count = theNPC.GetItemCount(item)      if count > 0 and !theNPC.isEquipped(item)         theNPC.RemoveItem(item, count, true, thePlayer)      else         n += 1      endif      item = theNPC.GetNthForm(n)   endwhile
The GetNthForm function returns None when you get to the end of the list, so you don't actually need to call GetNumItems in this case.

(If you were only removing a smaller set of items it would be more efficient to start that the end of the list and work your way down to zero.)
User avatar
DeeD
 
Posts: 3439
Joined: Sat Jul 14, 2007 6:50 pm

Post » Thu Jun 21, 2012 12:53 pm

Ah, I didn't realize the container traversal functions were that slow! I haven't played with them yet myself. Good to know, thanks.
User avatar
jasminε
 
Posts: 3511
Joined: Mon Jan 29, 2007 4:12 am

Post » Thu Jun 21, 2012 5:11 pm

Ideally it would pick up things that are equipped if they are worth the money, but leave everything else on. TO that end I wrote this:
User avatar
Connor Wing
 
Posts: 3465
Joined: Wed Jun 20, 2007 1:22 am

Post » Thu Jun 21, 2012 7:16 pm

Scriptname PilferingScript extends activemagiceffect  GlobalVariable Property PilferGlobal autoObjectReference Property Imaginary autoActor Property PlayerREF autoevent OnEffectStart(Actor Target, Actor Caster)   int n = 0  Form item = Target.GetNthForm(n)   while itemitem = Target.GetNthForm(n)float Weight = item.GetWeight()if Weight==0.0Weight = 0.0001endIfint count = Target.GetItemCount(item)      if ((item.GetGoldValue() / Weight) >= (PilferGlobal.GetValue() as float))         Target.RemoveItem(item, count, true, PlayerREF)      endif n += 1item = Target.GetNthForm(n)   endwhileTarget.SetActorValue("Infamy", 47)endEvent

But its very inconsistent. It picks up everything worth the money that isn't equipped fine, and sometimes it picks up stuff that is if its worth the money. But only sometimes. Boggling my mind why.
NVM. It works, it just is slow sometimes.
User avatar
Mackenzie
 
Posts: 3404
Joined: Tue Jan 23, 2007 9:18 pm

Post » Thu Jun 21, 2012 2:34 pm

Well, now you have two calls to GetNthForm inside your loop. You only need one. The one at the bottom since the very first call is made before the loop starts. Just removing that first call inside the loop should almost double the speed of the script.
User avatar
Nina Mccormick
 
Posts: 3507
Joined: Mon Sep 18, 2006 5:38 pm

Post » Thu Jun 21, 2012 9:04 pm

ScriptName PilferingScript extends ActiveMagicEffect  Float fWeightInt iIndexForm kItemActor Property PlayerREF AutoGlobalVariable Property PilferGlobal AutoObjectReference Property Imaginary AutoEvent OnEffectStart(Actor akTarget, Actor akCaster)	If akTarget.GetActorValue("Infamy") != 47		akTarget.SetActorValue("Infamy", 47)		iIndex = akTarget.GetNumItems()		While iIndex > 0			iIndex -= 1			kItem = akTarget.GetNthForm(iIndex)			fWeight = kItem.GetWeight()			If !fWeight				fWeight = 0.0001			EndIf			If (kItem.GetGoldValue() / fWeight) >= PilferGlobal.GetValue() As Float				akTarget.RemoveItem(kItem, akTarget.GetItemCount(kItem), True, PlayerREF)			EndIf		EndWhile	EndIfEndEvent
User avatar
Robyn Lena
 
Posts: 3338
Joined: Mon Jan 01, 2007 6:17 am

Post » Fri Jun 22, 2012 1:49 am

Yeah, thats basically how it works now, except I don't even have the infamy set, as it will only take off the correct items in the first place. I didn't get rid of the second call however, and it sped things up quite a bit.
User avatar
Nauty
 
Posts: 3410
Joined: Wed Jan 24, 2007 6:58 pm


Return to V - Skyrim