I saw a post by Cipscis a while back (think on the nexus, can't find it again) which talked about a different way of sorting items and maintaining the weapons/armors current health. In a nutshell, you set items you don't want removed from the player to "temporary quest items" and then do a "Player.RemoveAllItems rDestinationContainer" and then set the "fake quest items" back to non-quest items.
The benefits being:
No timers
No item form lists
Works with all items (including custom items)
Change which items get sorted in-game
So I kind of picked up that ball and ran with it. The idea being, you place an item you want sorted into a container that the sorter "sees" (form list of containers). When the sort is run, it will "see" there is item X in container Y. It will then check if the player has more of item X. If they do, all item X will be put into container Y - retaining health if any.
What I ended up with works well with one exception. Items that originate in the containers will find their way back into them. IE: If container Y has item X in it from the start (GECK was used to add the items to the container), when I run the sort - item X will find its way back to container Y even though container Y no longer has that item.
In other words, you enter the cell for the first time. Container Y has 2 Whiskeys in it. Take the Whiskeys from the container (now in player inventory) and now container Y is empty. I run the sorter and the Whiskeys that were in container Y somehow find their way back into it (no longer in player inventory).
One way around it is to ensure that any containers that have the potential to be added to the sorter are empty from the get-go, but I think I may just be doing something wrong. I just don't see how it's possible those items could wind back up in their original container if a container isn't even set in the script.
Note:
When the sorter has something to do, the players items get unequipped. So I had to store previously equipped items to a temp list and then re-equip them afterwards - which was causing a crash because of the PipBoy. Thanks to another post I can't seem to re-find, it was pointed out to me that the PipBoy had to be re-equipped in MenuMode. So there's a little high-jinxery going on - but it works - except for the fore-mention container/item problem.
All of the form lists used start off empty and all of the globals are non-constant bools that start off 0.
The message "zzEzMSItemSorterCONTMESG" has:
0) Open
1) Add to List [shown if zzEzMSItemSorterIsInListGLOB == 0]
2) Remove from List [shown if zzEzMSItemSorterIsInListGLOB == 1]
3) Close
The message "zzEzMSItemSorterACTIMESG" has:
0) Sort Items
1) Enable Config Mode [shown if zzEzMSItemSorterConfigGLOB== 0]
2) Disable Config Mode [shown if zzEzMSItemSorterConfigGLOB== 1]
3) Exit
----
This is the script the containers that have the potential to be part of the sorter run (just adds or removes itself from a list via menu):
Spoiler
scn zzEzMSItemSorterCONTSCPT; Requires NVSEint bInitint bInListint bMsgBoxint iButtonfloat fTimerref rContainerBegin OnActivate if (IsActionRef Player) if (zzEzMSItemSorterConfigGLOB) if (bInit == 0) set rContainer to GetSelf set bInit to 1 endif if (bInList) set zzEzMSItemSorterIsInListGLOB to 1 else set zzEzMSItemSorterIsInListGLOB to 0 endif set bMsgBox to 1 ShowMessage zzEzMSItemSorterCONTMESG else Activate endif endifEndBegin MenuMode if (bMsgBox) set iButton to GetButtonPressed if (iButton > -1) if (iButton == 0) ; open the container Activate elseif (iButton == 1) ListAddReference zzEzMSItemSorterContainersFLST ; add myself to the sorter list set bInList to 1 elseif (iButton == 2) ListRemoveForm zzEzMSItemSorterContainersFLST rContainer ; remove myself from the sorter list set bInList to 0 endif SMS fxSearchAndMark SMS fxSpotterShader set fTimer to 0 set bMsgBox to 0 endif endifEndBegin GameMode if (zzEzMSItemSorterConfigGLOB) if (fTimer > 0) set fTimer to (fTimer - GetSecondsPassed) else if (bInList) PMS fxSpotterShader else PMS fxSearchAndMark endif set fTimer to 3 endif else if (fTimer) SMS fxSearchAndMark SMS fxSpotterShader set fTimer to 0 endif endifEnd
This is the script the sorter activator runs (the one having the issue):
Spoiler
scn zzEzMSItemSorterACTISCPT; Requires NVSEint bActiveint bInitint iButtonint iIndexContint iIndexItemint iMsgBoxint iStageref rContainerref rDestContref rItemref rPipBoyBegin OnActivate if (IsActionRef Player) if (iMsgBox || bActive) ; busy else set iMsgBox to 1 ShowMessage zzEzMSItemSorterACTIMESG endif endifEndBegin MenuMode if (iMsgBox) set iButton to GetButtonPressed if (iButton > -1) if (iMsgBox == 1) if (iButton == 0) ; sort set bActive to 1 elseif (iButton == 1) ; config enable set zzEzMSItemSorterConfigGLOB to 1 elseif (iButton == 2) ; config disable set zzEzMSItemSorterConfigGLOB to 0 endif elseif (iMsgBox == 2) ; complete if (rPipBoy) Player.EquipItem rPipBoy 0 1 set rPipBoy to 0 endif ResetPipboyManager endif set iMsgBox to 0 endif endifEndBegin GameMode if (bActive) ; get currently equipped items if (iStage == 0) set iIndexCont to ListGetCount zzEzMSItemSorterContainersFLST if (iIndexCont) set iIndexCont to (iIndexCont - 1) else ; quit if there are no containers ShowMessage zzEzMSItemSorterNoneMESG set bActive to 0 Return endif DisablePlayerControls 1 1 1 1 0 1 1 set rPipBoy to 0 set iIndexItem to 19 ; slots Label 10 if (iIndexItem > -1) set rItem to Player.GetEquippedObject iIndexItem if (iIndexItem == 6) ; skip the pipboy set rPipBoy to rItem elseif (rItem) ListAddForm zzEzMSItemSorterEquippedFLST rItem endif set iIndexItem to (iIndexItem - 1) Goto 10 endif set iStage to 1 ; start the sort elseif (iStage == 1) set iIndexItem to (Player.GetNumItems - 1) set rContainer to ListGetNthForm zzEzMSItemSorterContainersFLST iIndexCont set rDestCont to 0 Label 20 ; check containers one at a time if (iIndexItem > -1) set rItem to Player.GetInventoryObject iIndexItem if (IsQuestItem rItem) ; skip real quest items else if (rContainer.GetItemCount rItem) if (rDestCont == 0) set rDestCont to rContainer ; the only way a destination container gets set is if it passes these checks endif else ListAddForm zzEzMSItemSorterQuestItemsFLST rItem SetQuestItem 1 rItem endif endif if (iIndexItem) set iIndexItem to (iIndexItem - 1) Goto 20 endif endif ; if GetItemCount fails, this should be empty if (rDestCont) Player.RemoveAllItems rDestCont 1 endif ; set fake quest items back to non-quest items Label 30 if (ListGetCount zzEzMSItemSorterQuestItemsFLST) set rItem to ListGetNthForm zzEzMSItemSorterQuestItemsFLST 0 SetQuestItem 0 rItem ListRemoveNthForm zzEzMSItemSorterQuestItemsFLST 0 Goto 30 endif set iIndexCont to (iIndexCont - 1) if (iIndexCont > -1) Return ; next container else if (ListGetCount zzEzMSItemSorterEquippedFLST) set iStage to 2 ; re-equip else set iStage to 3 ; done endif endif ; re-equip previously equipped items elseif (iStage == 2) set iIndexItem to 19 ; slots Label 40 if (iIndexItem > -1) set rItem to ListGetNthForm zzEzMSItemSorterEquippedFLST iIndexItem if (rItem) Player.EquipItem rItem 0 1 ; equipping pipboy here will crash endif ListRemoveNthForm zzEzMSItemSorterEquippedFLST iIndexItem set iIndexItem to (iIndexItem - 1) Goto 40 endif set iStage to 3 ; complete elseif (iStage == 3) EnablePlayerControls set bActive to 0 set iIndexCont to 0 set iIndexItem to 0 set iStage to 0 set rContainer to 0 set rDestCont to 0 set rItem to 0 set iMsgBox to 2 ShowMessage zzEzMSItemSorterDoneMESG ; sort complete endif endifEnd
On a side note, if I use "ListAddReference zzEzItemSorterContainersFLST" - how can I check if a reference is in the list? I can seem to get "IsInList" or "ListGetFormIndex" to detect added references
Edit:
I think I've narrowed it down to "GetItemCount" not working right, or NVSE not working right with GetItemCount (replicate):
set iIndexItem to (Player.GetNumItems - 1)set rContainer to zzRefrigeratorCONTREFLabel 10 if (iIndexItem > -1) set rItem to Player.GetInventoryObject iIndexItem set iCount to 0 ; this is returning "1" even though there are "0" of them for items that spawned in this container set iCount to rContainer.GetItemCount rItem printc "Container: %n Item: %n Qty: %x", rContainer rItem iCount set iCount to 0 set iIndexItem to (iIndexItem - 1) Goto 10 endif
"rContainer.GetItemCount rItem" will return 1 even though there may have been more than 1 of those items at spawn. If 3 Whiskeys spawned in the container and then were removed, it will return "1" if it's checking for "Whiskey". Even if the 3 Whiskeys that spawned were taken by player and then dropped on the floor, if I add a Whiskey to the player using the console - it will return "1".
Thanks