Skyrim Special Edition

Scriptname PKYDynamicArmorRackScript extends ObjectReference
{Controlling script for dynamic armor racks resource. Only works with correctly keyworded armors with vanilla mesh alignment.}

Keyword[] Property ArmorKeywords Auto
{Array of keywords, ensure markers are setup with same keywords and linked from this object.}

ObjectReference[] Property oArmorDisplayItem Auto
{Array of displayed items, must be same length as ArmorKeywords}

Auto State Ready

Event OnCellAttach()
;Do a bit of housekeeping on cell loading.
Upkeep()
EndEvent

Event OnItemAdded(Form akBaseItem, Int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer)
if oArmorDisplayItem.Find(NONE) == -1
;if all slots on this display are full
debug.notification("This armor stand is full.")
GoToState("Blocked")
if akItemReference
RemoveItem(akItemReference, akOtherContainer = akSourceContainer)
else
RemoveItem(akBaseItem, akOtherContainer = akSourceContainer)
endif
GoToState("Ready")
Return
endif

Keyword aArmorKWD

if akItemReference
;if unique reference
aArmorKWD = GetItemType(akItemReference)
if aArmorKWD == NONE
;if not a compatible item, exit function
GoToState("Blocked")
RemoveItem(akBaseItem, akOtherContainer = akSourceContainer)
debug.notification("That item cannot be displayed.")
GoToState("Ready")
Return
endif
int pos = ArmorKeywords.Find(aArmorKWD)
if !oArmorDisplayItem[pos]
;if no display for this slot, add a display
oArmorDisplayItem[pos] = GetLinkedRef(aArmorKWD).PlaceAtMe(akItemReference.GetBaseObject())
while !oArmorDisplayItem[pos].Is3DLoaded()
endwhile
oArmorDisplayItem[pos].SetMotionType(4)
oArmorDisplayItem[pos].BlockActivation()
else
;else if an armor piece of this type exists, exit function.
GoToState("Blocked")
RemoveItem(akItemReference, akOtherContainer = akSourceContainer)
debug.notification("An item of that type is already displayed.")
GoToState("Ready")
endif
elseif akBaseItem
;if generic or created item.
aArmorKWD = GetItemType(akBaseItem)
if aArmorKWD == NONE
;if not a compatible item, exit function.
RemoveItem(akBaseItem, akOtherContainer = akSourceContainer)
GoToState("Blocked")
debug.notification("That item cannot be displayed.")
GoToState("Ready")
Return
endif
int pos = ArmorKeywords.Find(aArmorKWD)
if !oArmorDisplayItem[pos]
;if no display for this slot, add a display
oArmorDisplayItem[pos] = GetLinkedRef(aArmorKWD).PlaceAtMe(akBaseItem)
while !oArmorDisplayItem[pos].Is3DLoaded()
endwhile
oArmorDisplayItem[pos].SetMotionType(4)
oArmorDisplayItem[pos].BlockActivation()
else
;else if an armor piece of this type exists, exit function.
GoToState("Blocked")
RemoveItem(akBaseItem, akOtherContainer = akSourceContainer)
debug.notification("An item of that type is already displayed.")
GoToState("Ready")
endif
else
;Error
Return
endif
EndEvent

Event OnItemRemoved(Form akBaseItem, Int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)
if GetState() != "Blocked"
int POS = -1
int index = ArmorKeywords.Length
while index && POS == -1
index -= 1
if akBaseItem && akBaseItem.HasKeyword(ArmorKeywords[index]) && oArmorDisplayItem[index]
;if generic item with correct keyword and disable enabled.
POS = index
elseif akItemReference && akItemReference.HasKeyword(ArmorKeywords[index]) && oArmorDisplayItem[index]
;if unique item with correct keyword and disable enabled.
POS = index
endif
endwhile

if POS != -1
;if the above function passed; disable, delete and clear the display.
oArmorDisplayItem[POS].Disable()
oArmorDisplayItem[POS].Delete()
oArmorDisplayItem[POS] = None
endif
endif
EndEvent
EndState

State Blocked

EndState

Keyword Function GetItemType(Form akItem)
;Search the keyword array against akItem, return result if found.
int kw = ArmorKeywords.Length
Keyword found
while kw && !found
kw -= 1
if akItem.HasKeyword(ArmorKeywords[kw])
found = ArmorKeywords[kw]
endif
endwhile
;debug.notification("GetItemType found keyword " + (found) + " on item " + (akItem))
Return found
EndFunction

Function Upkeep()
if ArmorKeywords.Length > oArmorDisplayItem.Length
;If the arrays are setup incorrectly, shut down the display.
GoToState("Blocked")
Debug.trace("Armor Rack Error 1 - Mismatched array sizes at " + Self + ".")
return
endif

int kw = ArmorKeywords.Length
;if a Keyword defined in the array doesn't match the linkedrefs, remove the keyword.
while kw
kw -= 1
if !GetLinkedRef(ArmorKeywords[kw])
ArmorKeywords[kw] = None
endif
endwhile

int chk = oArmorDisplayItem.Length
while chk
chk -= 1
if oArmorDisplayItem[chk]
;if an object is already defined on this display
if !GetItemCount(oArmorDisplayItem[chk].GetBaseObject())
;if there are no versions of this item in the chest, delete the static display and clear.
oArmorDisplayItem[chk].Disable()
oArmorDisplayItem[chk].Delete()
oArmorDisplayItem[chk] = None
else
;Once the objects have loaded, reset their position, motion and activation status
while !oArmorDisplayItem[chk].Is3DLoaded()
endwhile
oArmorDisplayItem[chk].MoveTo(GetLinkedRef(ArmorKeywords[chk]))
oArmorDisplayItem[chk].SetMotionType(4)
oArmorDisplayItem[chk].BlockActivation()
endif
else
if GetLinkedRef(ArmorKeywords[chk]).GetLinkedRef()
;if the dummy marker is linked to another object
if GetItemType(GetLinkedRef(ArmorKeywords[chk]).GetLinkedRef()) == ArmorKeywords[chk]
;if the linked object has the same keyword as the linked ref, add it to the container and process a normal ItemAdded event.
GoToState("Ready")
AddItem(GetLinkedRef(ArmorKeywords[chk]).GetLinkedRef())
GoToState("Blocked")
endif
endif
endif
endwhile
GoToState("Ready")
Debug.Trace(Self + "- Upkeep done.")
EndFunction

Article information

Added on

Edited on

Written by

Pickysaurus

1 comment

  1. Katarsi
    Katarsi
    • premium
    • 116 kudos
    akOtherCjavascript-event-stripped akSourceContainer

    This is a bug in Nexus' display of certain wording.
    When you write (I'll use spaces between letters so it appears properly)    o n t a i n e r =    you'll then get displayed javascript-event-stripped instead.

    Useful to put this here in case someone wants to copy/paste parts of this script. Don't copy the line above, it needs to be corrected.