Per the title, I/anyone using my mod will sometimes have a function running on a non-existent (NULL) object. Is this bad? Should I explore other options?
I have provided my code below. It is an adaptation of Amethyst Deceivers Universal Item Display Script.
A quick run-down of how it works: The player can display almost any item by interacting with a given activator which gates access to the container providing nothing is blocking the item's destination coordinates (an item already being displayed for example). The container then "drops" the item and "mounts" it at its own origin and rotation.
Aside from tweaking the functionality to my liking, it always irked me that unless you only added one single item to the scripted container it would correctly reject surplus items but it would never also display the original valid item. For that item to be displayed the player would have to retrieve the item from the container, then add it, and only it, to the container once more. Ease of use, and being "foolproof" is a very big deal to me, so a user-end workaround is not acceptable to me.
To get around this small quirk, I thought it would be a good idea to also queue the MountCurrentItem function whenever any items get removed from the container. The good news is that this seems to work perfectly when surplus items are added to an empty container. The bad news (I think?) is that the MountCurrentItem function will also run whenever the player legitimately removes an item from being displayed, and thus runs on a NULL object. I must assume this will happen very frequently, will this cause any problems?
Scriptname MDHDisplayScriptCONTAINER extends ObjectReference {Script for display containers}Bool Property Blocked = False Auto HiddenMessage Property MessageWarning AutoMessage Property MessageCount AutoKeyword Property ArmorShield AutoKeyword Property WeapTypeDagger AutoKeyword Property WeapTypeSword AutoKeyword Property WeapTypeGreatSword AutoKeyword Property ClothingRing AutoKeyword Property VendorItemPotion AutoKeyword Property VendorItemPoison AutoKeyword Property VendorItemGem AutoKeyword Property ClothingNecklace AutoFormList Property ClawList AutoFormList Property WhitePhial AutoFormList Property PoisonList AutoFormList Property UniqueJarList AutoInt Property PlacedItem = 0 Auto HiddenInt Property DisplayType = 1 Auto{1 = Weapon rack2 = Dagger case3 = Jewel display4 = Shield plaque5 = Potion/Poison6 = Dragon claw7 = COA weapon8 = Unique Jar9 = Necklace}ObjectReference ItemRefForm ItemBaseEvent OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer)Actor PlayerRef = Game.GetPlayer()If (akSourceContainer == PlayerRef) If (AllowedItems(akBaseItem)) If (aiItemCount == 1) && (PlacedItem == 0) PlacedItem += aiItemCount ItemBase = akBaseItem ItemRef = akItemReference RegisterForSingleUpdate(0.1) Else MessageCount.Show() PlacedItem += aiItemCount RemoveItem(akBaseItem, aiItemCount, False, PlayerRef) ;if I register for a single update in the OnItemRemoved Event it should force a recheck of the now singular item EndIf Else MessageWarning.Show() PlacedItem += aiItemCount RemoveItem(akBaseItem, aiItemCount, False, PlayerRef) EndIfElse RemoveItem(akBaseItem, aiItemCount, False, akSourceContainer)EndIfEndEventEvent OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)If (akDestContainer == Game.GetPlayer()) UnregisterForUpdate()EndIfPlacedItem -= aiItemCountRegisterForSingleUpdate(0.1) ;This event only fires when the player attempts to add more than one item to the container, and when the player physically removes a displayed item.EndEvent ;The latter won't have any object to "drop" but the MountCurrentItem function will still fire, is this bad?Event OnUpdate()MountCurrentItem(ItemBase, ItemRef)EndEventFunction MountCurrentItem(Form akBaseItem, ObjectReference akItemReference)ObjectReference MountedItemInt i = 0If (akItemReference) DropObject(akBaseItem) MountedItem = akItemReferenceElse MountedItem = DropObject(akBaseItem)EndIfIf (MountedItem != None) Blocked = True While(!MountedItem.Is3DLoaded()) && (i < 10) Utility.Wait(0.1) i += 1 EndWhile ;If Staff use MoveToNode ;else use original code below MountedItem.SetMotionType(Motion_Keyframed, False) MountedItem.TranslateToRef(Self, 2000.0, 0.0) Utility.Wait(1) Blocked = False ItemRef = NoneEndIfEndFunctionBool Function AllowedItems(Form akBaseItem)If (DisplayType == 1) Return (akBaseItem as Weapon)ElseIf (DisplayType == 2) Return (akBaseItem.HasKeyword(WeapTypeDagger))ElseIf (DisplayType == 3) Return ((akBaseItem.HasKeyword(ClothingRing)) || (akBaseItem.HasKeyword(VendorItemGem)))ElseIf (DisplayType == 4) Return (akBaseItem.HasKeyword(ArmorShield))ElseIf (DisplayType == 5) Return ((akBaseItem.HasKeyword(VendorItemPotion)) || (akBaseItem.HasKeyword(VendorItemPoison)) || (WhitePhial.HasForm(akBaseItem)) || (PoisonList.HasForm(akBaseItem)))ElseIf (DisplayType == 6) Return (ClawList.HasForm(akBaseItem))ElseIf (DisplayType == 7) Return ((akBaseItem.HasKeyword(WeapTypeSword)) || (akBaseItem.HasKeyword(WeapTypeGreatSword)))ElseIf (DisplayType == 8) Return (UniqueJarList .HasForm(akBaseItem))ElseIf (DisplayType == 9) Return (akBaseItem.HasKeyword(ClothingNecklace))EndIfEndFunction
EDIT: From my limited tests in-game I could not detect any adverse effects.