Jump to content

Special container scripting


Recommended Posts

What I need:

A container that only accepts a single item, whatever happens, not one stack, just one item. And access from another script to the form of that item to pass it as a parameter for FindClosestReferenceOfTypeFromRef. The container will be accessible by the player "equipping" a misc item but haven't got that far yet...

Ideally the weight of the misc item would increase with the content of the container, but that would require skse, right? It's not a main feature anyway and cosnidering you can only place a single item, the amount of weight you can cheat is low.

 

What I have:

Some of my concerns as comments within the code. Looks good and reliable? any errors you can spot? Improvements?

Scriptname CONTAINERTEST extends ObjectReference
{Accepts only a single item and stores its form}

Bool IsFull
Form Property MyItem Auto ; to be accessed and used by another script as a form parameter
; wiki says you cant "make" a form property as in fill it in ck i guess, but can you store stuff in it?

Event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer)
If !IsFull
  IsFull = True
  MyItem = akBaseItem
  If aiItemCount > 1
    Self.RemoveItem(akBaseItem, aiItemCount - 1, true, akSourceContainer) ;keep 1 item send the rest back, should take care of stacks
  Endif
Else
  Self.RemoveItem(akBaseItem, aiItemCount, true, akSourceContainer) ;if full send everything back
Endif
EndEvent

Event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)
  IsFull = False ; if it only accepts one item, whenever anything is removed it should be empty? reliable?
endEvent
Edited by FrankFamily
Link to comment
Share on other sites

I'm not sure about using a property with Form. In theory it should work if all you are doing is storing a form to use on another script. However, if the compiler complains about it...

 

Your OnItemAdded block seems fine as a means of preventing additional items to be added (i.e. remove the excess).

Your OnItemRemoved block will be a problem. Each of the removals of excess items will trigger this event. So, you'll be inadvertently resetting the bool when you do not want it to be reset.

 

You may therefore wish to use SKSE's GetNumItems function as a means of limiting the storage of excess rather than using a bool. (EDIT: Code block not tested.)

Event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer)
	If Self.GetNumItems() == 0
		MyItem = akBaseItem		;container was empty - store this item.
		If aiItemCount > 1
			Self.RemoveItem(akBaseItem, aiItemCount - 1, true, akSourceContainer) ;keep 1 item send the rest back, should take care of stacks
		Endif 
	ElseIf Self.GetNumItems() > 1
		Self.RemoveItem(akBaseItem, aiItemCount, true, akSourceContainer) ;return entire ammount as container is maxed already
	EndIf
EndEvent

I have code in my Inventory Management System mod which adds content weight to container weight. It requires SKSE and it is not persistent across saves which means there is required maintenance code to run. So there is code to add weight when items are added and subtract weight when items are removed, and code on a player alias to reset the weight when the game is loaded. You are welcome to break it down and use what you need.

Edited by IsharaMeradin
Link to comment
Share on other sites

The Form property will be fine. The CK can't fill it but your script can and other scripts can use the value without any problems.

There's just one problem I see. When you return the extras OnItemRemoved will trigger and mark the container empty. You need three states to handle the situation not a single boolean. With states the code would be:

ScriptName CONTAINERTEST extends ObjectReference
{Accepts only a single item and stores its form}

Form Property MyItem Auto ; to be accessed and used by another script as a form parameter


Event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer)
{Default is to reject any new items.}
  Self.RemoveItem(akBaseItem, aiItemCount, true, akSourceContainer) ;if full send everything back
EndEvent


Auto State IsEmpty  ; container starts empty

Event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer)
{When empty, container can accept one and only one.}
  GoToState("")  ; reject new items but do not reset if extras need to be removed
  If aiItemCount > 1
    Self.RemoveItem(akBaseItem, aiItemCount - 1, true, akSourceContainer) ;keep 1 item send the rest back, should take care of stacks
  Endif
  MyItem = akBaseItem
  GoToState("IsFull") ; now there is just one
EndEvent

EndState


State IsFull

Event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)
  GoToState("IsEmpty")
  MyItem = None ; should you be clearing MyItem here?
EndEvent

EndState

If you aren't planning to reset the MyItem variable to None like the code I added to OnItemRemoved in my version you can actually get by with something much simpler by returning all items every time. In that case the container would be used to remember the chosen item but the item would go back into the player's inventory and you wouldn't have to worry about weight. Your other script could always check to see if the player still has that item before it does whatever else it is supposed to do. And if the player adds another item it would replace the previous choice. In that situation the simplified code would be:

ScriptName CONTAINERTEST2 extends ObjectReference
{Remembers the form of the last item placed in the container}

Form Property MyItem Auto ; to be accessed and used by another script as a form parameter

Event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer)
  MyItem = akBaseItem ; remember this new item
  Self.RemoveItem(akBaseItem, aiItemCount, true, akSourceContainer) ; send everything back
EndEvent
Link to comment
Share on other sites

Thanks both for the help:)

 

I wished removeitem wouldn't trigger onitemremoved but yeah it makes more sense that it does.

And i'd like to clear the property if no item is inside, forgot that in my script, so i'll go with the states for now.

Link to comment
Share on other sites

  • Recently Browsing   0 members

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