1. it provides an easy way to adapt the scripts to be used as general display systems for just about anything.
2. it is designed with modding player homes and dungeons in mind. the Vanilla weapon racks are not well suited for multiple use within a single cell (they work well if you only plan on using no more than a handful in the same cell, but start to consume way more resource than necessary when you start using a bunch of them in the same room), plus it allows for more freedom for creating totally new display designs
3. It gives a better consistency in user-interface, as this system uses the familiar inventory screen to place your items, rather than having to equip the weapon in hand before mounting it to the display.
The idea is for this display system to be "large mod friendly" and as simplified as possible, but even still it has its limits and the user should be aware of the risks of over-using too many scripted objects for their interior cells.
To begin, i will cover the basic structure of how this system is set up:
reference image - example weapon display setup: http://i45.tinypic.com/2eehmpy.jpg
1. The "Trigger" - this is a plain trigger box that is used to count the number of items that are currently being displayed. if the count is zero, it will allow a new item to be placed. If the number is one or more, it will not allow any more items to be placed.
2. The "Container" - The container simultaneously replaces the need for a "dummy marker" (the object that lets the placed weapon know exactly where to go) as well as provide the visual interface for placing the object (the built in show inventory screen)
3. The "Activator" - This object is what the player uses to interact with the display system and it sends a script to open the container, which in turn triggers the rest of the placement script. The activator can be anything, from a simple player-activated trigger box, or a physical mesh. in the case of the example above I am using a stone pedestal mesh as the activator for the weapon display (physical 3d meshes IMO work better than invisible trigger boxes).
How it works:
The player mouses their crosshair over the activator and it will prompt a message like "Activate Weapon Display". when they confirm, it will open up the Show Inventory dialogue window, and the player can place whatever script-defined valid items into the container. once the item is placed into the container, the scripts runs and automatically "drops" the object outside the container and re-aligns the item to the same placement and orientation of the container itself. The player can now pull the item directly off the display system without having to open the inventory screen again, if they want to retrieve their displayed item.
Assembling the parts:
1. create a container: In the object window create a new container (right click, new) and give it an editor ID. You may also want to give it a visible name such as "Weapon Display". this name is what the player will see in the upper left corner of the inventory menu screen.
2. select a model for your container. in the example above i am using a dummy sword for the container of the weapon rack. There are many of these dummy type markers which will appear invisible and unselectable in-game. This is ideal, you do not want to use a physical 3d mesh for the container, as it would not be good if the player can access or see the container itself in game. In my example above i used Meshes\Clutter\DummyItems\DummySword01.nif. The folder DummyItems contains a bunch of differntly shaped marker objects which are perfect for this type of display system containers.
3. leave everything else as default and hit ok (dont worry about scripts we will get to that later)
---
4. create an activator - go to your object window under activators and create a new activator object (right click, new) and give it an editor ID. you definitely want to give this a visible name as well (preferably the same name you gave your container). this name is what the player will see when they mouse over it in the game - "Activate Weapon Display" etc.
5. select a model for your activator. unlike the container it is preferable to use a physical 3d mesh for the activator to avoid quirky issues with mousing over in game. if in the case you absolutely cant use a 3d mesh for your activator, you can use a trigger box set to player activation (under primitive tab), but you must rotate the z angle to something with a decimal value, such as 4.15 degrees (like i said it's quirky and even still may not always work properly).
6. Leave everything else as is, unless you want to put something in the activate override text box. this entry is what determines the name of the action when the player mouses over. by default it is "Activate" whatever object, but you can specify it to say something else like "Interact with" or "Open" etc.
---
7. Place your activator in the world by dragging it into the render window.
8. drag your container and align/orient it to how you want the item to display. NOTE - this display system uses PIVOT POINTS instead of node information. so when the script runs the code that aligns the placed item to your dummy marker/container, it will do so by matching pivot to pivot. The pivot point is indicated in the CK as a + crosshair on the object when it is selected in the render window. keep this in mind in case you are making a weapon rack that allows any kind of weapon to be displayed. A staff's pivot is very different from a greatsword pivot, so make sure you are allowing enough space in your display system to accomodate them all. typically the pivot is near where the hand is supposed to grab the weapon.
tip - one way to "preview" the proper look of the weapon display is to drag an actual weapon into the render window and position it how you wnt it to display. then hit Ctrl + F, and substitute it for your container object.
9. when you have placed your items how you want them, draw a trigger box around the container by using the Multibound menu (its the button of a cube with a T inside it)
10, choose DefaultBlankTrigger as your base object for your trigger. use the arrows to scale the trigger, but do not make it too big. it does not have to be bigger than the wepon or item to be displayed, it just has to be big enough to let the script know when an item is being occupied inside it. double click on it in the render window and go to Primitive tab. Under collision layer, change this to L_TRIGGER
---
11. Scripts.
There are a two separate scripts which this system uses in tandem. One script is for the activator and acts as a control for the whole system. the other is for the container and it handles the placement of the object being displayed.
Double click your Container object in the render window, and select Edit Base. in the script panel click Add and Create New. give your new script a name (give it a specific name and not a generic one, nothing like WeaponRackScript because then it will just get lost in with the rest of the vanilla scripts)
12. copy the following code and paste it into your new container script, directly under the first line which is your scripts name "extends object reference":
(you have full permission to use my script in your mods, or even edit it however you like, but please do give credit somewhere in description)
Bool Property Blocked = False AutoMessage 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 AutoFormList Property GemList AutoFormList Property ClawList AutoFormList Property WhitePhial AutoForm Property ItemSlot = None Auto HiddenInt Property PlacedItem = 0 Auto HiddenInt Property DisplayType Auto; 1 = Weapon rack, 2 = Dagger case, 3 = Jewel display, 4 = Shield plaque, 5 = Potion/poison, 6 = Dragon claw, 7 = COA weaponEvent 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 ItemSlot = akBaseItem RegisterForSingleUpdate(0.1) Else MessageCount.Show() PlacedItem += aiItemCount Self.RemoveItem(akBaseItem, aiItemCount, False, PlayerRef) EndIf Else MessageWarning.Show() PlacedItem += aiItemCount Self.RemoveItem(akBaseItem, aiItemCount, False, PlayerRef) EndIfElse Self.RemoveItem(akBaseItem, aiItemCount, False, akSourceContainer)EndIfEndEventEvent OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)If (akDestContainer == Game.GetPlayer()) UnregisterForUpdate()EndIfPlacedItem -= aiItemCountEndEventEvent OnUpdate()MountCurrentItem(ItemSlot)EndEventFunction MountCurrentItem(Form akBaseItem)Int i = 0ObjectReference MountedItem = DropObject(akBaseItem)If (MountedItem != None) Blocked = True While(!MountedItem.Is3DLoaded()) && (i < 10) Utility.Wait(0.1) i += 1 EndWhile MountedItem.SetMotionType(Motion_Keyframed, False) MountedItem.TranslateToRef(Self, 2000.0, 0.0) Utility.Wait(1) Blocked = FalseEndIfEndFunctionBool 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)) || (GemList.HasForm(akBaseItem)))ElseIf (DisplayType == 4) Return (akBaseItem.HasKeyword(ArmorShield))ElseIf (DisplayType == 5) Return ((akBaseItem.HasKeyword(VendorItemPotion)) || (akBaseItem.HasKeyword(VendorItemPoison)) || (WhitePhial.HasForm(akBaseItem)))ElseIf (DisplayType == 6) Return (ClawList.HasForm(akBaseItem))ElseIf (DisplayType == 7) Return ((akBaseItem.HasKeyword(WeapTypeSword)) || (akBaseItem.HasKeyword(WeapTypeGreatSword)))EndIfEndFunction
13. go to File and save. and it should compile with no errors. if it does give you an error it might be because this forum adds html debris - particularly the "&" instead of "&". if you do get a compile error, post the error in the comments and i will help you sort it out
14. hit ok to save and close. Go to Messages in the object window and create new. create a new message object, give it an editor ID and click the Message Box check box. Then in the text field type a Warning message such as "you can only put weapons on the weapon display". hit ok to save. duplicate this item and give it a new editor ID. leave everything the same, but change the text to a Count message such as "You can only put one weapon on the weapon display". hit ok to save. you should have a total of 2 new message objects (one Warning and one Count).
15. go back to your container and edit base again. click on Properties in the script window. Depending on the type of rack you are making, you will ONLY fill the properties which you need for that rack. you will never fill all the properties for any one display system.
for our example weapon rack, you will only need to fill the following:
DisplayType - fill with a value of "1"
MessageCount - fill with the Count message item you created.
MessageWarning - fill with the Warning message item you created.
for other display types such as dagger case, shield rack, potion rack etc, leave a comment and i will detail which properties you need to fill, or if you can decipher the code in the AllowedItems function, it should tell you which properties will be used for that type. but in any case, DisplayType, and both Message properties must be filled for all types.
---
16. double click your Activator in the render window and Edit Base. go to the script section and add a new script, and give it a name
17. copy and paste the following code into your new activator script:
ObjectReference Property ItemChest AutoObjectReference Property ItemTrigger AutoEvent OnActivate(ObjectReference akActionRef)If (akActionRef == Game.GetPlayer()) If ((ItemTrigger.GetTriggerObjectCount() == 0) && ((ItemChest as YourContainerScript).Blocked == False)) ItemChest.Activate(akActionRef) EndIfEndIfEndEvent
NOTE - the line of code that says "YourContainerScript" - replace with the full name of the container script you created above.
18. save the script, close and hit ok to close the Edit Base window. but keep the edit reference window open.
19. in the reference edit window of your activator object scroll all the way to the Scripts tab and click Properties
20. Fill the ItemChest and ItemTrigger properties by pointing them to the Container and Trigger in the render window.
21. click ok to save, and save your mod.
If you made it this far without falling asleep you are in good shape. your display system should now be functional and you can test it out in game. i know its a lengthy tutorial but that is because we are building a new system from scratch.
If you have any questions, or if you are curious as to how the script actually works, i can break down the code for you in the comments below.
when your test is complete you can copy and paste more of these by selecting all the parts and pasting them around your interior cell (the properties should also update with each copy).