Babachele's Mod Talk Series: Dynamic Script-Based Modding The idea is to dynamically* identify Forms via their References and add them to Formlists, then apply changes via scripting to the Forms based on the FormList they belong to. This allows you to make your mod capable of integrating/responding to Forms introduced by other mods without conflicts. WARNING: This technique requires basic scripting knowledge, links to tutorials provided however. Also, keep in mind that this is not a step-by-step line-by-line scripting tutorial, but rather the explanation of a concept and various methods that can be used to apply it. Detailed step-by-step instructions and sample script fragments will be provided at a later date. (When I feel less lazy) If you use this technique in your mod and you learned it from here, please link to this tut in the credits section of your Mod. Also, I am currently working on a Mod that provides a Framework for other mods using this technique to easily integrate with one another and vanilla Skyrim. This should be complete in about a week and help promote compatibility-focused modding while also providing A LOT of custom functions to make the process very easy (cut-paste-fill in the blank easy) for the not-so-scripting inclined. I remember seeing at some point another forum post talking about using a single empty FormList in Skyrim to facilitate communication between mods and that inspired me to make this Framework, I just don't remember where the forum post was from or I would link to provide proper credit. (Not that my Framework will use just one FormList) Problem: Many mods on Nexus render themselves incompatible with one another due to conflicting edits of vanilla (original) Skyrim files. This can be especially frustrating if you end up having to choose between one or more good mods because of unfortunate mod conflicts. Or it's just mildly annoying, requiring the use of Wyre Bash or another utility to make patches. The inability to add new food items to Imp's More Complex Needs without a mod-specific patch comes to mind, and inspired me to think of this method. (Not that I came up with it, I'm pretty sure some mods utilize variations of this to include support for items added by other mods) The Solution: Scripting (Oh Noes!) - Before you peace out on this thread, I'd like to say that this requires MINIMAL scripting knowledge and ability. Depending on how you use it, it will also NOT give you a toxic savegame. As long as you can grasp the basics, you'll be good to implement this in your own mod. That being said, I don't really have the patience to write a tutorial on the basics, so provided here is a list of the resources I utilized to teach myself: 1. http://www.cipscis.com/skyrim/tutorials/beginners.aspx -Papyrus for Beginners 2. http://www.creationkit.com/Bethesda_Tutorial_Papyrus_Hello_World - Bethesda Papyrus Tutorials (I recommend going through all of them. While some information is repeated, it helps to see the same things explained in different ways, especially with this scripting s***. ) 3. http://www.creationkit.com/Category:Papyrus - Just a link to the Creation Kit page for Papyrus. The Wiki is perfect for looking up Functions and how they work. So assuming you have basic understanding of scripting, we'll move on. Skyrim utilizes what are called "Formlists" to keep track of a variety of things, from vendor buy/sell lists to the classification of weapons. A FormList is, as the name suggests, nothing more than a list of Forms. What is a "Form"? A Form is the "Base-Object" of an "Object Reference". An Object Reference (or just "Reference") is basically any specific item, actor, weapon, entity, etc. rendered in the game. For example, there are hundreds of Red Apples in Skyrim each with their own Reference IDs. You could (with great difficulty) edit a Red Apple individually by only applying changes to a specific reference ID, or you could edit the base object (Form) Red Apple and have the desired changes apply to ALL Red Apple references. Basic s*** you already knew, right? Well, to reiterate some more basic s***, while editing base objects using CK will assuredly apply your changes throughout the world of Skyrim, they will also most assuredly cause conflicts with any other mods that rely on the vanilla properties/modify the vanilla properties of those objects. This problem can be avoided with FormLists. The idea is to dynamically* identify Forms via their References and add them to Formlists, then apply changes via scripting to the Forms based on the FormList they belong to. This allows you to make your mod capable of integrating/responding to Forms introduced by other mods. When I say "dynamically" I basically mean "while the game is running" i.e. not through preloaded changes in an esp/esm or post-facto edits using the Creation Kit. This is made possibly by the fact that all Forms fall into different broad category (like "Potion" or "Armor") and often have Keywords attached. Don't worry, we'll get into Keywords later. Thus the changes are applied AFTER all the mods are loaded and none of them are permanently saved as modifications to your Skyrim\Data files. Instead, the changes are saved are unique to your savegame. (No, this shouldn't cause excessive savegame bloating, or excessive load times, but we'll get to that later). Scripts from differing mods which modify the same Forms will not cause a CTD or other game-breaking errors. If the scripts are poorly coded and do not account for possible changes from other mods, the worst that would happen is that References would have inconsistent values, changing depending on whichever script happens to be active/updating at that very moment. This is annoying and can possibly render some of your mod-added scripts nonfunctional, but can easily be fixed once identified. Dynamically Identify Forms 1. Depending on the contents of your mod, you will need to utilize a method of filtering out Forms/Object References that do not concern your mod. For example, if your mod only deals with Armor, there is no point in you have an identification script run on all Potions as well. The easiest way is using the AddInventoryEventFilter function. This function will only allow object references of the specified Form or FormList to trigger an Event/Function scripted on a line after the AddInventoryEventFilter function and before a RemoveInventoryEventFilter of the same kind or a RemoveAllInventoryEventFilters function (Use of filter removal function is ALWAYS recommended when adding filters to avoid bugs and mod conflicts). I recommend using the AddInventoryEventFilter because it allows you to screen Object References before an Event/Function triggers, instead of having an Event/Function trigger for all applicable Object References and screening out objects using the functions nested within it. The former method produces a more efficiently running script. However, you can also use conditionals (If-Else) "if akbaseObject as Form...." within an Event/Function to detect whether the given Base-Object (Form) matches the Form or category of Forms you are trying to detect. Remember, a Form can be both individual Base-Object (Ex. Iron Sword) or a category of base object as classified by the Construction Kit (Ex. Potion, Armor, Weapon, etc.) Alternatively, given a situation where SKSE is available one can use the GetType function to return an integer value corresponding to a specific category of Forms. Create a conditional to check the returned value against your desired value ("If returnedvalue == expectedvalue...") and nest it within an appropriate Event (Step 2). Another conditional method that can be nested in an Event is checking whether the given Form has the appropriate "Keyword" using the HasKeyWord function. Keywords are just words (they can be any word) that are on the Keyword list of an object reference. You can add Keywords to items using the CK. You can also check whether the given Form is a member of the specified Formlist with the HasForm function (which also has many variations depending on what kind of object reference you are working with, see Wiki). 2. Select an appropriate Event to trigger your script's method of dynamically identifying new Forms. I would recommend OnObjectEquipped or OnItemAdded, but the appropriate Event largely depends on what exactly your mod is doing/modifying. OnUpdate is also a popular choice, but it can easily be abused and I don't feel like explaining a proper OnUpdate setup right now. Anyways, whenever this Event is detected you should have your method of filtering kick in to ensure that your upcoming Functions will only apply to the desired Forms. Technically if you used the AddInventoryEventFilter/RemoveInventoryEventFilter combo then that's already happened, and you can move on. If not, then you need to nest filtering conditionals within your Event to make sure you aren't applying your Functions all willy-nilly to every single Object Reference that happens to trigger your Event. Dynamically Add Forms to FormLists 1. This section and the following sections will be necessarily general and vague (at least, moreso than the previous sections) due to the fact that these sections depend almost entirely on what you want to do with your mod. But anyways, once you've got all that filtering out of the way you've got a hold of the base-object (Form) you want to modify. At this point you are going to want to script a menu with inputs so that a Player could select the different modifications/qualities they would like to ascribe to the Form. Unless of course you don't want to give the Player a choice, in which case you can proceed to insert any functions you want to run based on all items that pass your filter. Going back to the scripted menu though, each input should be tied to a Function that will add your Form to the appropriate FormList(s) that corresponds with the input choice. For example, let's say your Form is a Red Apple and you would like to add 10, 20, or 30 pounds to its weight. You should have three separate FormLists for each of those desired actions. Alternatively, you could go ahead and use the appropriate Functions (SetBaseDamage, SetAV, etc.) tied to specific inputs in order to go ahead and apply the changes you want. However, FormLists are recommended over this and I'll explain why in a bit. 2. Once that's done, don't forget to place a RemoveInventoryEventFilter function if you used one earlier, and don't forget to close off your Event with an "EndEvent". Dynamically Apply Changes to Forms based on FormList Membership 1. You can do this in an incredible number of ways, and again it depends on what your mod is aiming to do. The basic idea is to have a set of custom Functions that use either nested HasForm functions and conditionals or GetAt functions to identify members of specific FormLists and run sets of nested native/Global/SKSE functions in response. The former option focuses on the individual Reference, i.e. it will check if a Red Apple is a member of the RedAppleFormList then apply Functions. Using the latter function would help facilitate the opposite, starting with the entire FormList and working down to the individual Reference. The end result is the same between both methods, so its a matter of preference/mod needs. Either way, the nested functions should contain the changes you intend to make. You will need some method to call these functions to action, or keep them in action if they need to be constantly active. Ensure Compatibility with Other Mods 1. DO NOT HAVE YOUR DYNAMIC DETECTION SCRIPT SET TO ALWAYS RUN IN THE BACKGROUND be it via Quest Script or by attaching the script to an Actor. This may be easy, but it's a pretty shitty thing to do. Imagine if everyone tried to have their mods running their various dynamic identification scripts in the background all at once, some with overlaps, some without, etc. It would create a hassle when multiple scripts use the same Events to trigger, degrading into a situation where the first script that happened to be loaded (it would be random) would trigger, while perhaps the next time the same Event was called another script triggered. This would break the technique for everyone. Instead, introduce an item or spell or MCM menu that set your scripts to a State containing your Event and its dynamic identification/filtering method. This allows Players to control when they want your mod to discover and incorporate new items. 2. Do Not Modify Vanilla FormLists directly using the CK. If you want to add something to a Vanilla FormList, add it via script. Make Your Mod Uninstall Cleanly 1. Script everything you can into custom functions. Even when you don't really need to, use a custom function in lieu of just the native/global/skse function and just define your desired function within that custom function. Then set your scripts up to have States. For every script you added, include one State at the very end that defines all the custom functions you defined earlier, except in this state leave the definition empty. [ex. CustomFunction() EndFunction]. Now, either include a menu option or some sort of activator that when enabled will set ALL of your scripts to this Stage. This will effectively disable your Mod, allowing it to be safely uninstalled/updated without leaving lingering functions running to bloat your savegame. 2. I REPEAT - Do Not Modify Vanilla FormLists directly using the CK. If you want to add something to a Vanilla FormList, add it via script. 3. You can use the Revert function to remove all script-added forms from a FormList. Useful to get rid of any additions you made to Vanilla FormLists, though it will also remove script-added Forms from other Mods. I have a workaround for this, but I'm too lazy to explain it right now. I'll get to it eventually.