Jump to content

Limited containers capacity weight


baronesbc

Recommended Posts

So, there's no way to get a list of items in the container? WHat about a combination of GetNumItems() and GetNthForm(). Do those functions work well or have neither of you dealt with them before? If they work well, we could get the number of items, and then cycle through them without ever removing anything.

Event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)
	If ( akDestContainer )
		Int NumItems = akDestContainer.GetNumItems() - 1 ;-1 because GetNthForm starts at 0
		Int i = 0
		Float TotalWeight = 0
		While ( i < NumItems )
			TotalWeight = akDestContainer.GetNthForm(i).GetWeight()
			i += 1
		EndWhile
		If ( TotalWeight > Max )
			akDestContainer.RemoveItem( akItemReference, aiItemCount, true, Game.GetPlayer() )
			Debug.Notification("This item won't fit in this container")
		EndIf
	EndIf
EndEvent
Edited by Xander9009
Link to comment
Share on other sites

 

So, there's no way to get a list of items in the container? WHat about a combination of GetNumItems() and GetNthForm(). Do those functions work well or have neither of you dealt with them before? If they work well, we could get the number of items, and then cycle through them without ever removing anything.

Event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)
	If ( akDestContainer )
		Int NumItems = akDestContainer.GetNumItems() - 1 ;-1 because GetNthForm starts at 0
		Int i = 0
		Float TotalWeight = 0
		While ( i < NumItems )
			TotalWeight = akDestContainer.GetNthForm(i).GetWeight()
			i += 1
		EndWhile
		If ( TotalWeight > Max )
			akDestContainer.RemoveItem( akItemReference, aiItemCount, true, Game.GetPlayer() )
			Debug.Notification("This item won't fit in this container")
		EndIf
	EndIf
EndEvent

 

GetNumItems and GetNthForm work perfectly fine as far as I know only used them for a quest which involved forcing the player to drop certain items though. However I think it only shows the stacks of items not how many are in the stack so you would have to also account for that with something like GetItemCount

 

So using your example maybe:

Event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)
	If ( akDestContainer )
		Int NumItems = akDestContainer.GetNumItems() - 1 ;-1 because GetNthForm starts at 0
		Int i = 0
		Int stackCount = 0
		Float TotalWeight = 0
		While ( i < NumItems )
			stackCount = akDestContainer.GetItemCount(akDestContainer.GetNthForm(i))
			While (stackCount)
				TotalWeight +=  akDestContainer.GetNthForm(i).GetWeight()
				stackCount -= 1
			EndWhile
			i += 1
		EndWhile
		If ( TotalWeight > Max )
			akDestContainer.RemoveItem( akItemReference, aiItemCount, true, Game.GetPlayer() )
			Debug.Notification("This item won't fit in this container")
		EndIf
	EndIf
EndEvent

Something like that?

Edited by CraftySentinel
Link to comment
Share on other sites

I actually read that specific note on that function and intended to account for that and then completely forgot about it. Thank you. Of course, you could also just multiply them.

Event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)
	If ( akDestContainer )
		Int NumItems = akDestContainer.GetNumItems() - 1 ;-1 because GetNthForm starts at 0
		Int i = 0
		Float TotalWeight = 0
		While ( i < NumItems )
			TotalWeight = TotalWeight + ( akDestContainer.GetNthForm(i).GetWeight() * akDestContainer.GetItemCount(akDestContainer.GetNthForm(i)) )
			i += 1
		EndWhile
		If ( TotalWeight > Max )
			akDestContainer.RemoveItem( akItemReference, aiItemCount, true, Game.GetPlayer() )
			Debug.Notification("This item won't fit in this container")
		EndIf
	EndIf
EndEvent

I'm not sure which would be more efficient.

 

EDIT: Removed the leftover Int Stackcount.

Edited by Xander9009
Link to comment
Share on other sites

I actually read that specific note on that function and intended to account for that and then completely forgot about it. Thank you. Of course, you could also just multiply them.

Event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)
	If ( akDestContainer )
		Int NumItems = akDestContainer.GetNumItems() - 1 ;-1 because GetNthForm starts at 0
		Int i = 0
		Int stackCount = 0
		Float TotalWeight = 0
		While ( i < NumItems )
			TotalWeight = TotalWeight + ( akDestContainer.GetNthForm(i).GetWeight() * akDestContainer.GetItemCount(akDestContainer.GetNthForm(i)) )
			i += 1
		EndWhile
		If ( TotalWeight > Max )
			akDestContainer.RemoveItem( akItemReference, aiItemCount, true, Game.GetPlayer() )
			Debug.Notification("This item won't fit in this container")
		EndIf
	EndIf
EndEvent

I'm not sure which would be more efficient.

 

Ahh true you could (Why didn't I think of that :laugh: ), I would say multiplying them would be the much more efficient way since your only calling it once per stack.

Link to comment
Share on other sites

I think if you subtract one (as you are doing) from the result of GetNumItems, then you need to adjust your While loop logic.

 

As I understand it, GetNumItems returns the number of forms irregardless or the quantity of the object. Much like a form list holds the object but not the quantity of that object. GetNthForm starts at 0. So 0 from GetNthForm returns the first form counted in GetNumItems (or # 1). This is why you want to subtract 1 so that you can use 0 and 0. But you don't need to.

 

Your index (i) starts at 0. This is the value you pass to GetNthForm. You only need the value of GetNumItems to keep the loop going.

 

Consider there are 10 total objects in a container. GetNthForm refers to them as 0 - 9 rather than 1 - 10 as GetNumItems would.

 

If you subtract one from GetNumItems, the highest value now equals the highest with GetNthForm.

 

While (i < NumItems) -- as in your script above will fail to obtain the highest form.

While (i <= NumItems) -- put into your script above will obtain the highest form.

 

However, if you avoid subtracting from GetNumItems then

While (i < NumItems) -- will indeed work as it should.

 

At any rate, it is always safe to put in a sanity check.

If akDestContainer.GetNthForm(i)

placed before the total weight calculation it will ensure that there is a valid object before trying to get the weight from it.

Link to comment
Share on other sites

Indeed. I didn't think about the fact that if the player is fast enough or another script is involved an item might be removed while the loop is running, thus short-circuiting it. It honestly wasn't meant to be the final, used result, anyway. It was just a proof of concept, so I didn't think about it hard enough to realize the -1 problem. But since neither of you have suggested it wouldn't work, should I assume you think it might? If so I'll go ahead and test it.

Event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)
	If ( akDestContainer )
		Int NumItems = akDestContainer.GetNumItems()
		Int i = 0
		Float TotalWeight = 0
		While ( i < NumItems )
			If ( akDestContainer.GetNthForm(i) )
					TotalWeight = TotalWeight + ( akDestContainer.GetNthForm(i).GetWeight() * akDestContainer.GetItemCount(akDestContainer.GetNthForm(i)) )
					i += 1
			EndIf
		EndWhile
		If ( TotalWeight > Max )
			akDestContainer.RemoveItem( akItemReference, aiItemCount, true, Game.GetPlayer() )
			Debug.Notification("This item won't fit in this container")
		EndIf
	EndIf
EndEvent
Link to comment
Share on other sites

Alright, so I made a manager quest for Limited Container Capacity, made the player ref, and added this script:

Scriptname LCC_ManagerScript extends ReferenceAlias

Float Property Max = 500.00 Auto

;Event OnInit()
;	Debug.Notification("LCC running")
;EndEvent

Event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)
;	Debug.Notification("Item removed from player")
	If ( akDestContainer )
;		Debug.Notification("akDestContainer is valid")
		Int NumItems = akDestContainer.GetNumItems()
;		Debug.Notification("NumItems: "+NumItems)
		Int i = 0
		Float TotalWeight = 0
		While ( i < NumItems )
			If ( akDestContainer.GetNthForm(i) )
					TotalWeight = TotalWeight + ( akDestContainer.GetNthForm(i).GetWeight() * akDestContainer.GetItemCount(akDestContainer.GetNthForm(i)) )
					i += 1
			EndIf
		EndWhile
		Debug.Notification("Container Weight: "+TotalWeight)
		If ( TotalWeight > Max )
			akDestContainer.RemoveItem( akBaseItem, aiItemCount, true, Game.GetPlayer() )
			Debug.Notification("This item won't fit in this container")
;		Else
;			Debug.Notification("The item fits")
		EndIf
	EndIf
EndEvent

It originally didn't work because I was dumb and had it extending ObjectReference. But after I changed that, I noticed everything was working fine except that the item wasn't being returned to the player. It wasn't being removed, either. It was just staying there even though it knew it didn't fit. So I changed it to akBaseItem and it worked perfectly. I even clicked 3 in rapid succession that wouldn't fit and even though all three made it in before the script got through the first, it managed to return all three in turn. So, that's promising.

 

But I'm worried that returning the base item is going to strip any player enchanted/upgraded items of their enhancements. Thoughts?

 

Actually, I realized I had an upgraded piece of armor. So I filled the container and then put in the armor, and it was returned in its upgraded state. However, I don't have anything I've enchanted, so I can't test that easily. Here's the file if one of you would be awesome enough to test it if you can easily.

 

EDIT: In the file, I forgot to compile the script. The only thing I'd changed is commenting out the unnecessary notifications.

 

EDIT2: I reread this and realized it was practically unintelligible because I made so many typing mistakes. They're fixed now. I should really proof-read my posts...

Edited by Xander9009
Link to comment
Share on other sites

So long as you keep the actual item available, enchantments will stay. I've had no issues with using akBaseItem with the OnItemAdded and OnItemRemoved events.

 

Question:

Your method uses the player reference to hold the script. This means that every container is given the same limited capacity? Not that "realistic" to have an alchemy satchel limited to 500 lbs. :P

 

If you don't want to apply the script to the container... perhaps you can group the base containers into similar sizes on form lists. Then compare the destination container's base to those on the form lists. Depending upon which list it is on, determines which max value to use.

 

Any new mod base containers would be SOL unless you provided a means by menu perhaps or thru some MCM magic to let them assign mod containers to a specific max weight or to leave unlimited. Then add that base container to the appropriate form list for later usage.

Link to comment
Share on other sites

Ok, good. I wasn't sure about the enchantment bit.

 

As for the rest: yeah, I thought it'd be a bit odd that everything had the same limit. I didn't want to get any more complex unless it actually worked to begin with, though. Since it does, I'll see about adding the other types. I've got satchels, sacks, barrels, chests, dressers, cupboards, strongboxes, bookcases, coffins, urns, large urns, end tables, safes, dwemer boxes (the smaller squarish ones), round dwemer containers, dwemer dressers, and large chests (that's a heck of a lot more than I expected...). They're fairly easy to select in bulk by sorting by their model. But deciding the numbers might take a bit longer.

 

I'll TRY to make an MCM, but I've never managed it before. I tried once, but it wouldn't work. But it turned out that my skse had somehow corrupted every script it altered and I couldn't compile anything, so I gave up (since I didn't know what was wrong). I'll look into it tomorrow. For tonight, I plan to play for an hour, take a shower, and sleep for as long as I possibly can :)

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...