Item Sorters Revisited

Post » Tue Aug 24, 2010 2:05 am

Hey,

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
User avatar
An Lor
 
Posts: 3439
Joined: Sun Feb 18, 2007 8:46 pm

Return to Fallout: New Vegas