-
Notifications
You must be signed in to change notification settings - Fork 2
Preset Creation Guide
- Create a folder for your mod:
Data/SKSE/Plugins/DAF/animData/MyMod/ - Put a JSON file inside (example: MyFile.json)
- Minimal example:
{
"priority": 10,
"events": [5],
"animations": ["MyPickupIdle"],
"forms": ["IronSword"]
}Meaning:
- events: [5] → ItemPickup
- forms: ["IronSword"] → the item (ID) you’re targeting
- animations: ["MyPickupIdle"] → animation event name to send (see Important note below)
- priority: lower numbers override higher numbers
Launch the game → log should show the folder and file were found.
⚠️ ⚠️ ⚠️ Important⚠️ ⚠️ ⚠️
Idles (TESIdleForm/IDLE) are currently disabled. Please use animation event names.
| Rule | Meaning |
|---|---|
| Base path | Data/SKSE/Plugins/DAF/animData/ |
| Must be inside a subfolder | animData/MyMod/MyFile.json |
| No nested folders | animData/MyMod/Sub/… (ignored) |
| No JSON directly in animData root | Ignored |
| Folder naming | Keep it simple (letters, numbers, underscores) |
| Special characters are skipped | Folders with any of these characters are skipped and warned: ! @ # $ % ^ & * ( ) [ ] { } ; : ' " \ | , . < > / ?
|
Use one folder per mod/author.
Each JSON file describes exactly one animation setup.
No arrays of multiple definitions. Just plain key/value pairs.
| Key | Required? | Type | Negation | Form Groups | What It Does |
|---|---|---|---|---|---|
priority |
No; default 0
|
integer |
No | No | Lower numbers win when multiple presets match |
events |
Yes |
integer[] or string
|
No | No | Uses built-in event numbers 1–28 or one custom event name |
animations |
Yes | string[] |
No | No | Animation events played in order |
durations |
No | integer[] |
No | No | Sets each animation's duration in milliseconds by matching array position |
forms |
No | string[] |
Yes | Yes | Uses IDs to filter the Form supplied by the event |
form_types |
No |
integer[] or string[]
|
Names only | No | Filters by numeric or named Form types; do not mix both types |
keywords |
No | string[] |
Yes | Yes | Uses IDs to filter keywords on the supplied Form |
actors |
No |
integer[] or string[]
|
String IDs only | Yes | Uses IDs to filter the Actor; do not mix both types |
locations |
No | string[] |
Yes | Yes | Uses IDs to filter the Actor's current Location |
actor_keywords |
No | string[] |
Yes | Yes | Uses IDs to filter keywords on the Actor's base NPC |
conditions |
No | string[] |
Yes | Yes | Uses Perk IDs whose conditions are evaluated with the Actor and event Form |
attach_node |
No | string |
No | No | The node in the Animation Object's NIF where the event Form's 3D model is attached |
delay |
No |
boolean or integer
|
No | No |
true uses total durations; a positive integer sets milliseconds; otherwise no delay |
DAF can delay Activate, ItemAdd, ItemRemove, ItemDrop, ItemPickup, Buy, Sell, and menu-open actions. Other built-in events do not delay their underlying action. Custom events return the configured delay to the plugin that sent the event.
IDs written as strings can use any of these formats:
-
Plugin-local FormID (load-order safe):
0x01ABCDEF~MyPlugin.esp -
Full FormID:
00012EB7 -
Editor ID:
IronSword
These values are strings and must be written in quotes in JSON. You may mix these three formats within the same string array.
actors also accepts non-negative FormIDs as an integer array. Do not mix integers and strings within the same actors array.
Fields marked Yes in the Form Groups column also accept a Form Group name.
Every Form in the group must have the record type required by that field. For example, an actors group must contain only Actor references.
Form Groups are stored in:
Data/SKSE/Plugins/DAF/formGroups
Implementation detail:
The event table shows the Actor and Form supplied by each event:
- Actor: the Actor reference that plays the animation.
-
Form: the object related to the event and checked by
forms,form_types, andkeywords.
If the Form is a placed or runtime reference, those filters check its base record instead. For example, picking up a placed Iron Sword checks the IronSword weapon record.
You can declare:
- A list of built‑in event numbers, OR
- Use a custom event name when a mod registers/sends its own event via the API with that name.
| Number | Event | Actor | Form |
|---|---|---|---|
| 1 | Activate | Activating actor | Activated reference |
| 2 | ItemAdd | Actor receiving the item | Added item |
| 3 | ItemRemove | Actor losing the item | Removed item |
| 4 | ItemDrop | Actor dropping the item | Dropped item |
| 5 | ItemPickup | Actor picking up the item | Picked-up reference |
| 6 | Equip | Actor equipping the item | Equipped item |
| 7 | Unequip | Actor unequipping the item | Unequipped item |
| 8 | Buy | Buying actor | Bought item |
| 9 | Sell | Selling actor | Sold item |
| 10 | MenuOpenInventory | Player | — |
| 11 | MenuCloseInventory | Player | — |
| 12 | MenuHoverInventory | Item owner | Hovered item |
| 13 | MenuOpenContainer | Player | — |
| 14 | MenuCloseContainer | Player | — |
| 15 | MenuHoverContainer | Item owner | Hovered item |
| 16 | MenuOpenMagic | Player | — |
| 17 | MenuCloseMagic | Player | — |
| 18 | MenuOpenBarter | Player | — |
| 19 | MenuCloseBarter | Player | — |
| 20 | MenuHoverBarter | Item owner | Hovered item |
| 21 | MenuOpenFavorites | Player | — |
| 22 | MenuCloseFavorites | Player | — |
| 23 | MenuOpenMap | Player | — |
| 24 | MenuCloseMap | Player | — |
| 25 | MenuOpenJournal | Player | — |
| 26 | MenuCloseJournal | Player | — |
| 27 | MagicEffectCast | Effect caster | Magic Effect (MGEF) |
| 28 | MagicEffectTarget | Effect target | Magic Effect (MGEF) |
For custom events, the sending plugin supplies the Actor and Form through the DAF API.
Examples
Built-in events
"events": [5,6]Custom event:
"events": "MyMod_CustomOpen"Example:
"animations": ["MyIdleStart","MyModAnimSwing","MyIdleLoop"],
"durations": [0, 1000, 2500]Rules:
- Each duration corresponds to the animation at the same array position.
- If an animation has no matching duration, its duration is
0. -
durationsis optional and contains milliseconds. - Extra durations do not correspond to an animation, but are still included when
"delay": truecalculates the total delay. - Leave durations out entirely if you don't care about timing.
- IDLE Form support is currently disabled.
- Each animation entry is treated as an animation event name (idles disabled).
Simple:
"animations": ["MyPickupIdle"]If you omit all filters, the preset can match whenever one of its events occurs.
| Filter | Checked Against |
|---|---|
forms |
The Form supplied by the event, or its base record when it is a reference |
form_types |
The type of that Form or base record |
keywords |
Keywords on that Form or base record |
actors |
The Actor reference that plays the animation |
actor_keywords |
The Actor's base NPC record |
locations |
The Actor's current Location |
conditions |
Perk conditions evaluated with the Actor as Subject and the original Form reference as Target, when available |
Matching rules:
- Entries without
!are includes. Entries beginning with!are exclusions. - Entries within one include filter use OR: any one may match.
- Different filter categories use AND: every configured category must match.
- Any matching exclusion prevents the preset from matching the current event.
- An empty filter array behaves like an omitted filter.
- For
conditions, at least one included Perk must evaluate true. Any excluded Perk that evaluates true prevents the preset from matching the current event. - The Actor does not need to have the Perk used by
conditions.
In the event table, — means the event provides no Form. Therefore, a preset using an include filter for forms, form_types, or keywords cannot match that event.
Actor-based filters can still match these events.
actors must use Actor reference IDs (ACHR), not NPC base-record IDs (NPC_).
Keywords created at runtime by KID or SPID can be used by Editor ID in keywords and actor_keywords.
⚠️ If an included or excluded ID cannot be resolved, a referenced Form Group is empty, or a form type or event number is invalid, DAF skips the entire preset file. The log identifies the problem and file.
DAF sorts matches by ascending priority and picks the first.
Lower = overrides higher.
Avoid using the same priority for definitions that might clash.
Minimal:
{
"priority": 10,
"events": [5],
"animations": ["MyPickupIdle"],
"forms": ["IronSword"]
}Multiple events:
{
"priority": 25,
"events": [6,7],
"animations": ["MyMod_Draw","MyMod_Settle"],
"durations": [20,40],
"keywords": ["WeapTypeSword"]
}Custom event:
{
"priority": 5,
"events": "MyMod_Inspect",
"animations": ["MyMod_InspectPose"]
}Negation:
{
"priority": 12,
"events": [5],
"animations": ["MyPickupEvent"],
"keywords": ["WeapTypeSword", "!WeapTypeDagger"],
"forms": ["!Gold001"],
"form_types": ["Weapon", "!Armor"],
"actors": ["!PlayerRef"],
"locations": ["!SovngardeLocation"]
}Conditions:
{
"priority": 8,
"events": [6],
"animations": ["MyMod_Draw"],
"conditions": ["Armsman00", "!Stealth00"]
}Layered naming strategy:
animData/MyMod/
05_ItemSpecific.json
20_WeaponType.json
60_GenericFallback.json
| Thing | Tip | Example |
|---|---|---|
| Folder | Use mod or author name | MyMod |
| File | <priority>_<topic>.json |
05_IronSword.json |
| Custom event | Prefix with mod name | MyMod_Inspect |
| Animation names | Consistent prefix | MyMod_Draw |
| Problem | Why | Fix |
|---|---|---|
| File ignored | Wrong folder level | Place in animData/MyMod/ |
| Folder skipped | Special characters in folder name | Use letters, numbers, underscores only |
| Not listed in log | Wrong extension | Must be .json |
| Animation not playing | Filters too strict / wrong event | Temporarily remove filters & test |
| ID not found | Typo or format issue | Re-check IDs |
| Wrong definition chosen | Priority misunderstanding | Lower number wins |
| delay true returns 0 | All durations are 0 | Use a number or add durations |
| Custom event unused | Not triggered | Other mod must send it |
| Nothing happens on pickup/activate | Target ref disabled/deleted | Ensure the reference is valid/alive |
- File is in animData/MyMod/ (one folder deep)
- Folder name contains only letters/numbers/underscores (no special chars)
- events set (numbers or one custom name)
- animations list not empty
- durations (if present) are in milliseconds and correspond to animations by array position
- IDs valid where used
- priority chosen (lower = stronger)
- delay correct (or omitted)
- Only ONE custom event string if using custom event
Standard:
{
"priority": 20,
"events": [EVENT_NUMBER],
"animations": ["YourAnimEventName"],
"forms": ["IronSword"]
}Custom event:
{
"priority": 10,
"events": "MyMod_CustomEvent",
"animations": ["MyMod_CustomAnim"]
}Happy animating!