SPID: The Complete Reference
as of SPID 7.0.0

Everything you need to know to start creating SPID mods.


Changelog

Spoiler:  
Show

  • 17.04.24 
  • Removed section about special Outfits ordering. The reverse ordering was removed in SPID 6.5.0


Table of Contents
Spoiler:  
Show

  • General Distribution Info
  • How does SPID load configs?
  • When distribution happens?
  • In what order forms are distributed?
  • Syntax
  • Form Type
  • Type Inferring
  • Distributable Form
  • Filtering
  • String Filters
  • Supported Strings
  • String Expression Modifiers
  • Form Filters
  • Supported Filterable Forms
  • Form Expression Modifiers
  • Level Filters
  • Supported Values
  • Ranges Syntax
  • Leveled Distribution
  • Traits Filters
  • Supported Traits
  • Trait Expression Modifier
  • Note on Templated NPCs
  • Count or Package Index
  • Item Count
  • Package Index
  • Package List Type
  • Chance


General Distribution Info

SPID distributes all configured forms at runtime, it doesn't have effect on either loaded plugins nor on save. SPID distributes everything from scratch each time you launch the game. You can think of SPID distribution as a "virtual plugin" that applies changes last in your load order. This makes any SPID-based mods safe to install/uninstall at any time, as they don't leave a trace.

  • How does SPID load configs? (Order)

  • At startup SPID looks into Skyrim's Data/ folder and finds all ini files that have a _DISTR suffix in their name.
  • Then it orders them alphabetically from A to Z and loads in that order.
  • Each file is read from top to bottom, preserving relative order of each type of forms (this order is used later during distribution. (each type of forms is guaranteed to be distributed in the same order as they appear in the file as well as the global order of files).

  • When Distribution happens?

Distribution of forms is split into two steps:

  • Persistent static (not scaling with Player's level) NPCs are distributed to on Main Menu load.
  • Dynamic leveled NPCs are distributed to as they are loaded in the world (typically, on cell load).

  • In what order forms are distributed?

SPID distribution processes forms of each type separately.
The exact order at which form types are processed is:
Spoiler:  
Show

  • Keywords
  • Factions
  • Spells
  • Perks
  • Shouts
  • Packages
  • Outfits
  • Items
  • Skins

Within each type forms are distributed in the same order that they were loaded with a few exceptions:

  • Keywords are additionally sorted to make sure that keywords that depend on other keywords will be distributed later than their dependencies. This allows you to freely use keywords as requirements for other keywords without manually ordering them.


Syntax

General syntax for a distributable form looks like this:

FormType = FormOrEditorID|StringFilters|FormFilters|LevelFilters|TraitFilters|CountOrPackageIndex|Chance
      required                           required                             optional                              optional                      optional                      optional                                           optional                               optional
                    Default: Index=0; Count=1            Default: 100

Optional sections can be either left blank or marked as NONE.

Example:
Spoiler:  
Show
So both
Item = MyItem|||||5
and 
Item = MyItem|NONE|NONE|NONE|NONE|5
are valid.


Form Type
Type of a distributable form that you want to configure.

Here is a list of all supported Distributable Forms that you can specify in FormType:

    Form type       Signature
  • Spell               [SPEL, LVSP]
  • Perk                [PERK]
  • Item                 [ALCH, AMMO, ARMO, BOOK, INGR, KEYM, LVLI, MISC, SCRL, SLGM, WEAP]*
  • Shout             [SHOU]
  • Package        [PACK, FLST*]
  • Keyword*      [KYWD]
  • Outfit             [OTFT]
  • SleepOutfit   [OTFT]
  • Faction          [FACT]
  • Skin               [ARMO]
Basically, any carriable items. Let me know if I missed some.
* When distributing FormList it must contain only Packages, otherwise game most likely will crash.
SPID can also create Keywords dynamically, so you can distribute custom keywords.
Example:
Spoiler:  
Show
This will create a new keyword and distribute it to NPCs
Keyword = MyVerySpecialKeyword


Type Inferring

You can also specify Form as a generic Form Type and let SPID work out proper Form Type based on provided Distributable Form.
IMPORTANT
Keep in mind that SleepOutfit and Skin can't be inferred,
because they use the same forms as Outfit and Item respectively, so the latter will always be detected first.
Example:
Spoiler:  
Show
Form = SteelSword
Form = DefaultOutfit
is the same as
Item = SteelSword
Outfit = DefaultOutfit


Distributable Form
A unique identifier of the Form to be distributed.

Form must be one of the supported types listed in Form Type section.

A form can be identified by using one of the following IDs:

  • FormID - a hexadecimal number (0x12345) with a plugin name as a suffix (e.g 0x12345~MyPlugin.esp). Read FormIDs and You for more details on how this ID is formed.
  • EditorID - a text identifier of the Form as seen in Creation Kit or xEdit. (e.g. ElvenMace or ImperialBow).

Generally, EditorID is considered to be a more stable way of referencing a Form since, unlike FormID, it will remain the same when the mod is merged, converted to esl or compacted.

Filtering

Distributable Form can be restricted to a group of NPCs that match specific criteria. These criteria are configured by a handful of filtering sections, that we'll talk about in a moment.

All Filters sections are multiplicative (combined using logical AND operation), while expressions within the same section are additive (combined using logical OR operation).

Example:
Spoiler:  
Show
So the entry
Form = 0x12345|A,B|0x12,0x34
can be read as "give a form 0x12345 when NPC has (A OR B) AND (0x12 OR 0x34)".


TIP
Use multiple entries for the same distributable forms to target different groups of NPCs.
Example:
Spoiler:  
Show

Keyword = FemaleBandits||BanditFaction||F
will give the keyword only to NPCs that are both Female AND part of Bandit Faction. But
Keyword = FemaleOrBandits||BanditFaction
Keyword = FemaleOrBandits||||F
will give the keyword to all members of Bandit Faction as well as all Females in the game.

String Filters

A list of comma-separated textual expressions that allows you to filter eligible NPCs by their textual properties, such as a name.

Form = 0x12345|StringExpression1,StringExpression2,...

Supported Strings
String Filters allow you to match NPCs by the following criteria:

  • NPC's Name (e.g. Balgruuf).
  • NPC's EditorID (e.g. BalgruufTheGreater).
  • NPC Templates* EditorID. This allows you to target all descendants of a template.
  • NPC's Keywords (e.g. ActorTypeNPC). This also includes Keywords distributed by SPID.
  • NPC Race's Keywords (e.g. ActorTypeAnimal).
This allows you to target all descendants of the same template. See Note on Templated NPCs below.

Example:
Spoiler:  
Show
Give a form to all Whiterun Guards
Form = 0x12345|Whiterun Guard

Give a form to NPC with ActorTypeNPC OR ActorTypeDragon

Form = 0x12345|ActorTypeNPC,ActorTypeDragon

String Expression Modifiers
By default, String Expression looks for the exact match of the specified term, but this behavior can be changed with several modifiers.

  • Exclusion modifier (-). Placed in front of a term. This will invert the expression and make it only match NPCs who does NOT have the exact term. 
Example:
Spoiler:  
Show
Give a form to every NPC except specifically "Balgruuf" (so "Balgruuf Junior" would still be allowed)
Form = 0x12345|-Balgruuf

  • Partial match modifier (*). Placed in front of a term. This will make the expression allow partial matches of the term. (e.g. "Guard" in "Whiterun Guard")
Example:
Spoiler:  
Show
Give form to every guard, this will match all "Whiterun Guard", "Falkreath Guard", "Markarth Guard", etc. Note that this will also match NPCs like "Guardian" or "Bodyguard".
Form = 0x12345|*Guard

  • Combining modifier (+). Placed between multiple terms you want to combine. This will make the expression only match NPCs who have ALL of the exact terms.
Example:
Spoiler:  
Show
Give a form to NPCs who are simultaneously ActorTypeNPC, Bandit and ActorTypeGhost
Form = 0x12345|ActorTypeNPC+Bandit+ActorTypeGhost

IMPORTANT
Only one modifier can be used in a single expression.
Example:
Spoiler:  
Show
None of these are valid:
Form = 0x12345|-*Guard
Form = 0x12345|-Guard+ActorTypeNPC
Form = 0x12345|ActorTypeNPC-Guard
Form = 0x12345|*Guard+ActoryTypeNPC


Form Filters
A list of comma-separated expressions containing FormOrEditorIDs that allows you to filter eligible NPCs by their form properties, such as Race, Class, etc.

Form = 0x12345||FormExpression1,FormExpression2,...

Supported Filterable Forms

Form Filters allow you to match NPCs by the following criteria:

        Form type            Signature       NPC's Record in xEdit
  • Combat Style[CSTY]          ZNAM - Combat Style    
  • Class              [CLAS]          CNAM - Class
  • Faction          [FACT]           Factions
  • Race               [RACE]          RNAM - Race
  • Outfit             [OTFT]           DOFT - Default outfit
  • Specific NPC [NPC_]          FormID, EDID - Editor ID
  • NPC's Template*  [NPC_]  FormID, EDID - Editor ID
  • Voice Type            [VTYP]           VTCK - Voice
  • Known Spell          [SPEL]           Actor Effects
  • Skin                       [ARMO]          WNAM - Worn Armor
  • Editor Location*   [LCTN]           XLCN - Persistent Location (of ActorRef)
  • FormList*              [FLST]           Recursively looks for any form from the list.
This allows you to target all descendants of the same template. See Note on Templated NPCs below.
* This is the location where NPC is placed in the Editor, NOT the location where NPC is right now.
* List can contain any of the forms from this table, including another nested FormList.

Example:
Spoiler:  
Show
Give a form to all Nords (NordRace "Nord" [RACE:00013746])
Form = 0x12345||NordRace

Give a form to NPCs that are located in Whiterun (WhiterunLocation "Whiterun" [LCTN:00018A56]) OR report crimes in Whiterun Hold (CrimeFactionWhiterun "Whiterun" [FACT:000267EA]).
Form = 0x12345||WhiterunLocation,CrimeFactionWhiterun

Additionally, here you can specify only name of the plugin where NPC is defined. This will match only NPCs from given plugin.
Example:
Spoiler:  
Show
Give a form only to NPCs from CoolNPCs.esp plugin
Form = 0x12345||CoolNPCs.esp


Form Expression Modifiers
By default, Form Expression checks whether an NPC has the specified form, but this behavior can be changed with several modifiers.

  • Exclusion modifier (-). Placed in front of a form. This will invert the expression and make it only match NPCs who does NOT have the form. 
Example:
Spoiler:  
Show
Give a form to every NPC except Nords (NordRace "Nord" [RACE:00013746])
Form = 0x12345||-NordRace

  • Combining modifier (+). Placed between multiple forms you want to combine. This will make the expression only match NPCs who have ALL of the forms.
Example:
Spoiler:  
Show
Give a form to NPCs who are simultaneously Nords (NordRace "Nord" [RACE:00013746]), Report Crime in Whiterun (CrimeFactionWhiterun "Whiterun" [FACT:000267EA]) and know Stoneflesh spell (StonefleshLeftHand "Stoneflesh" [SPEL:00072316])
Form = 0x12345||NordRace+CrimeFactionWhiterun+StonefleshLeftHand

IMPORTANT
Only one modifier can be used in a single expression.
Example:
Spoiler:  
Show
None of these are valid:
Form = 0x12345|-NordRace+WhiterunLocation
Form = 0x12345|CrimeFactionWhiterun-NordRace

Level Filters
A list of comma-separated expressions with numeric ranges that allows you to filter eligible NPCs by their leveled properties, such as level or skill.

Form = 0x12345|||LevelExpression,SkillExpression1,SkillExpression2,...

IMPORTANT
Only one Level Expression can be specified.
Providing multiple Level Expression will cause SPID to only recognize the last one.
Example:
Spoiler:  
Show
In the entry
Form = 0x12345|||5/10,7/12
only 7/12 levels will be stored. 5/10 will be discarded.


Supported Values
Level Filters allow you to match NPCs by the following criteria:

        Value                 Expression
  • Level                 min/max
  • Skill Level        skillIndex*(min/max)
  • Skill Weight     Same as Skill but prefixed with letter w.
* skillIndex is a number corresponding to one of the 17 skills:
Spoiler:  
Show
  #  Skill
  0. One-Handed
  1. Two-Handed
  2. Archery
  3. Block
  4. Smithing
  5. Heavy Armor
  6. Light Armor
  7. Pickpocket
  8. Lockpicking
  9. Sneak
10. Alchemy
11. Speech
12. Alteration
13. Conjuration
14. Destruction
15. Illusion
16. Restoration
17. Enchanting


Ranges Syntax

  • Closed range (min/max). Match values between min and max, including min and max.
  • Half-open range (min or min/). Matches values starting from min and to infinity :)
  • Exact value (value/value). Matches exact value.
Example:
Spoiler:  
Show
Give a form to NPCs who are at least level 5
Form = 0x12345|||5

Give a form to NPCs who has 50 in Destruction skill level
Form = 0x12345|||14(50/50)

Give a form to NPCs who level up their Two-Handed skill slightly more actively than other skills. (controlled by Skill Weight)
Form = 0x12345|||w2(2/3)


Leveled Distribution

Whenever a Distributable Form defines a Level Filter it becomes a part of the Leveled Distribution. Unlike regular distribution, Leveled Distribution checks levels and/or skills of all loaded auto-leveled NPCs and checks whether they've met requirements of the Level Filter. This happens unless either other filters discard the NPC or a random chance check would fail.


Trait Filters
A single expression that allows you to filter eligible NPCs by traits, such as gender or teammate.

Form = 0x12345||||TraitExpression

Supported Traits

  • Female
  • Male
  • Unique
  • Summonable
  • Child
  • Leveled (Is PC Level Mult)
  • Player's Teammate

Example:
Spoiler:  
Show
Give a form to females
Form = 0x12345||||F


Trait Expression Modifier
By default, Trait Expression checks whether an NPC has given Trait, but this behavior can be changed with several modifiers.

  • Exclusion modifier (-). Placed in front of a trait. This will invert the trait and make it only match NPCs who does NOT have that trait. 
Example:
Spoiler:  
Show
Give a form only to not unique NPC
Form = 0x12345||||-U

  • Combining modifier (/). Placed between multiple traits you want to combine. This will make the expression only match NPCs who have ALL of the traits.
Example:
Spoiler:  
Show
Give a form to all non unique male NPCs who are also adults
Form = 0x12345||||-U/M/-C



TIP
Note that, unlike other filters, Traits actually support mixing of expression modifiers.
Example:
Spoiler:  
Show
So you can do this
Form = 0x12345||||F/-U/L/-S


Note on Templated NPCs

Templated NPCs are those that inherit their attributes from another NPC, that is referred to as a base template. Filters always check the final NPC that is created after merging attributes from NPC and its base template.

Additionally, String Filters and Form Filters allow you to target specific NPCs using EditorID or FormID, including IDs of templates that they derive from. However, when template hierarchy includes multiple templated NPC, SPID can only reach specific templates. In such cases the following templates can be specified:

For not leveled NPCs:

  • Final NPC. This is the resolved NPC that will inherit attributes from its template.
  • Base template. This is the immediate parent Template of the final NPC. 
Example:
Spoiler:  
Show

DLC2SV01DragonPriestBoss [NPC_:0401CAD5] => EncDragonPriestFire [NPC_:0002025A] => EncDragonPriest [NPC_:00023A93]
Final NPC                                                                             Base template                                                                          Further template in hierarchy
                         Reachable                                                                                                        Reachable                                                                                      Unreachable



For leveled NPCs:

  • Original NPC. This is the top-level NPC that was used to create the final NPC.
  • Base leveled NPC. This is the Leveled NPC that is the closest to Original NPC in the hierarchy of templates that was used to pick a random NPC.
  • Base template. This is a random NPC that was picked from Leveled NPC and will be used as a template for Original NPC.
Example:
Spoiler:  
Show

[NPC_:FF000D45] => LvlDraugrAmbushMelee2HMale [NPC_:0004A04E] => LCharDraugrMelee2HMale [LVLN:0001E772] => 
 Dynamic Final NPC                                            Original NPC                                                                                              Base leveled NPC
      Unreachable                                                    Reachable                                                                                                               Reachable

SubCharDraugr02Melee2HM [LVLN:00023BFF] => EncDraugr02Melee2HHeadM05 [NPC_:0001FF2C] => EncDraugr02Template2H [NPC_:0005B753]
     Nested leveled NPC                                                                                       Base template                                                                                               Further template in hierarchy
          Unreachable                                                                                                             
Reachable                                                                                                               Unreachable



Count or Package Index
A numeric value that is interpreted based on associated Distributable Form.

Item Count

When Distributable Form is an Item, this section is interpreted as a number of items that should be added.
If this section is empty or absent Default count is 1.

You can also specify a numeric range as a Count and let SPID pick a Random Item Count to distribute from this range.

Example:
Spoiler:  
Show
Give a single bow (default count 1)
Form = ImperialBow

Give 3 swords
Form = IronSword|||||3

Give somewhere between 10 and 20 arrows
Item = SteelArrow|||||10-20


Package Index

When Distributable Form is a Package, this section is interpreted as an index where given Package should be inserted.
If this section is empty or absent Default index is 0.

Note that Package Index is zero-based, so the first Package has index 0.

Example:
Spoiler:  
Show
Set Patrol package (Patrol [PACK:00017723]) as the second package
Package = Patrol|||||1

Set Travel package (Travel [PACK:00016FAA]) as the first package (default index 0)
Package = Travel


Package List Type

When Distributable Form is a FormList, this section is interpreted as a type of the Package List that should be overwritten.
If this section is empty or absent Default type is 0.

Type can be one of the following:
#              Type                                       NPC's Record in xEdit
0. Default Package List                  DPLT - Default Package List
1. Spectator Override                     SPOR - Spectator override package list
2. Observe Corpse Override          OCOR - Observe dead body override package list
3. Guard Warn Override                 GWOR - Guard warn override package list
4. Enter Combat Override              ECOR - Combat override package list
Example:
Spoiler:  
Show
Set default package list
Package = DefaultPackageListLinkedPatrol|||||0

or, since default type is 0, we can simply write
Package = DefaultPackageListLinkedPatrol


Chance
A percentage value that sets a chance of given Distributable Form to be distributed.

Chance is a decimal value from 0 to 100. There is no limit on how small you want the chance to be (good luck hitting those 0.0001% chances though :D)
If this section is absent Default chance is 100 (e.g. guaranteed).

Example:
Spoiler:  
Show
Give a form with a 60% chance
Form = 0x12345||||||60

Give a form with a 0.01% chance
Form = 0x12345||||||0.01

Article information

Added on

Edited on

Written by

sasnikol

443 comments

  1. sasnikol
    sasnikol
    • premium
    • 475 kudos
    Locked
    Sticky
    Please comment here only if you have specific questions about developing DISTR files
    all general questions about SPID and/or issues with it, should be asked on the Posts section of the mod page itself.
    This will make it easier for people who are looking for a particular type of help to search for answers in the comments.
    Thanks!
  2. gokieks
    gokieks
    • premium
    • 2 kudos
    I was looking in the SPID logfile and noticed that when using my usual format for distributing RSV keywords to NPCs (via the plugin name), certain plugin name formats will cause an error.  A bit of investigation and it seems like it's when the plugin name contains " - " (a space followed by a dash followed by another space), and I was able to confirm it by adding a test line that resulted in the error:

    Failed to parse entry [Keyword = RSVignore||Test - Something.esp]

    Is there a way to escape the plugin name to make it be parsed correctly?  I looked through this article but didn't see anything, but if there is and I just missed it then apologies in advance.
    1. sasnikol
      sasnikol
      • premium
      • 475 kudos
      Hey, I think you got it right. That might be a bug in how SPID parses the filters. For now you can only avoid such names
    2. gokieks
      gokieks
      • premium
      • 2 kudos
      OK, I can work around it by just making modified versions of the problematic mods with changed plugin names, which is slightly annoying but not end of the world.  Using an override ESP with the keywords would be a better/easier choice, but RSVIgnoreteeth still doesn't work via that method as far as I knkow.

      Should I open a SPID bug report for this as well?
    3. sasnikol
      sasnikol
      • premium
      • 475 kudos
      You could open a bug, but that's not necessary, since I was planning to rework the whole parsing at some point, so that bug will be dealt with there. But, I don't know when this will happen.
    4. gokieks
      gokieks
      • premium
      • 2 kudos
      Ah, OK.  I'll just wait for a future update then.  Thanks!
  3. CourierSixOG
    CourierSixOG
    • member
    • 22 kudos
    Is there a way to ensure that once a NPC gets an item (weapon) for a DISTR file that the same NPC will not get multiple items from that same DISTR file? If it is stated somewhere I missed it I did read the reference and didn't see anything like this mentioned.
    1. sasnikol
      sasnikol
      • premium
      • 475 kudos
      Sounds like something that Exclusive Groups can help you with Though, there is no way to limit it to a single file, but most likely you won't need such limitation.
    2. CourierSixOG
      CourierSixOG
      • member
      • 22 kudos
      Thank you so much, I was so focused on the reference I missed this article. By chance do you know of any mods that use this I can look at as an example, I am not really understanding it too well. Would this work as instructed?

      For example I want to make sure NPCs only get 1 of the following 3 possible items:

      Item = 18DwemerEnergyGreatswordYellow4|Thalmor Soldier, Thalmor Justiciar|NONE|35|NONE|1|3
      Item = 18DwemerEnergyGreatswordWhite4|Thalmor Soldier, Thalmor Justiciar|NONE|35|NONE|1|3
      Item = 18DwemerEnergyGreatswordTeal4|Thalmor Soldier, Thalmor Justiciar|NONE|35|NONE|1|3


      ExclusiveGroup = GroupName|FormsList

      EnergyGreatsword = EnergyGreatswordGroup|18DwemerEnergyGreatswordYellow4, 18DwemerEnergyGreatswordWhite4, 18DwemerEnergyGreatswordTeal4
    3. sasnikol
      sasnikol
      • premium
      • 475 kudos
      Hey, can't remember any, but there certainly were some.

      You got it almost right "ExclusiveGroup" is the same kind of special keyword like "Item" you don't change it, it must be always there to let SPID know what kind of entry you're writing, so the correct way is:
      ExclusiveGroup = EnergyGreatswordGroup|18DwemerEnergyGreatswordYellow4,18DwemerEnergyGreatswordWhite4,18DwemerEnergyGreatswordTeal4
    4. CourierSixOG
      CourierSixOG
      • member
      • 22 kudos
      Thank you very much, I know it is simple but when new to something it can be confusing! Highest respects to you!
    5. sasnikol
      sasnikol
      • premium
      • 475 kudos
      No worries happy modding!
  4. hgjhjhjkl
    hgjhjhjkl
    • member
    • 3 kudos
    Website translation, sorry, but also posted on the main page, If I have add 9 outfit for vampires, what's the best chance number to get these armors instead of vanilla?

    SPID 6.8.2, Skyrim 1.5.97

    The garments to be distributed have the same appearance but different colors
    (Outfit Each set contains accessories for clothes, shoes, gloves, and more)
    Ex : 0x7AA7 > Newm fancyA copperblack gloves
                           Newm fancyA copperblack shoes
                           Newm fancyA copperblack stocking
                           Newm fancyA copperblack wing
                           Newm fancyA copperblack mask

    ; 0x7AA7 - Newm fancyA copperblack
    ; 0x7AA8 - Newm fancyA coppergrn
    ; 0x7AA9 - Newm fancyA copperwht
    ; 0x7AAA - Newm fancyA goldblue
    ; 0x7AAB - Newm fancyA goldpurp
    ; 0x7AAC - Newm fancyA goldred
    ; 0x7AAD - Newm fancyA ironred
    ; 0x7AAE - Newm fancyA steelblack
    ; 0x7AAF - Newm fancyA steelbrown

    This is my current setup.
    Outfit = 0x7AA7~NewmFancyCuiras.esp|ActorTypeNPC+Vampire,-Serana|VampireFaction|NONE|F|NONE|50
    Outfit = 0x7AA8~NewmFancyCuiras.esp|ActorTypeNPC+Vampire,-Serana|VampireFaction|NONE|F|NONE|50
    Outfit = 0x7AA9~NewmFancyCuiras.esp|ActorTypeNPC+Vampire,-Serana|VampireFaction|NONE|F|NONE|50
    Outfit = 0x7AAA~NewmFancyCuiras.esp|ActorTypeNPC+Vampire,-Serana|VampireFaction|NONE|F|NONE|50
    Outfit = 0x7AAB~NewmFancyCuiras.esp|ActorTypeNPC+Vampire,-Serana|VampireFaction|NONE|F|NONE|50
    Outfit = 0x7AAC~NewmFancyCuiras.esp|ActorTypeNPC+Vampire,-Serana|VampireFaction|NONE|F|NONE|50
    Outfit = 0x7AAD~NewmFancyCuiras.esp|ActorTypeNPC+Vampire,-Serana|VampireFaction|NONE|F|NONE|50
    Outfit = 0x7AAE~NewmFancyCuiras.esp|ActorTypeNPC+Vampire,-Serana|VampireFaction|NONE|F|NONE|50
    Outfit = 0x7AAF~NewmFancyCuiras.esp|ActorTypeNPC+Vampire,-Serana|VampireFaction|NONE|F|NONE|50

    If I apply this formula, will it no longer be possible to see NPCs that have not been given costumes? And have the opportunity to see the 9 outfit distributed?

    The formula is Oi = 100/(N-i) where:

    • Oi is the chance of i-th outfit,
    • N is total number of Outfits you want to distribute,
    •  i is index of the current outfit starting from 0 (e.g. Outfit 1 has I=0)

    Here are the chances of applying the formula.
    Outfit = 0x7AA7~NewmFancyCuiras.esp|ActorTypeNPC+Vampire,-Serana|VampireFaction|NONE|F|NONE|11.1
    Outfit = 0x7AA8~NewmFancyCuiras.esp|ActorTypeNPC+Vampire,-Serana|VampireFaction|NONE|F|NONE|12.5
    Outfit = 0x7AA9~NewmFancyCuiras.esp|ActorTypeNPC+Vampire,-Serana|VampireFaction|NONE|F|NONE|14.2
    Outfit = 0x7AAA~NewmFancyCuiras.esp|ActorTypeNPC+Vampire,-Serana|VampireFaction|NONE|F|NONE|16.6
    Outfit = 0x7AAB~NewmFancyCuiras.esp|ActorTypeNPC+Vampire,-Serana|VampireFaction|NONE|F|NONE|20
    Outfit = 0x7AAC~NewmFancyCuiras.esp|ActorTypeNPC+Vampire,-Serana|VampireFaction|NONE|F|NONE|25
    Outfit = 0x7AAD~NewmFancyCuiras.esp|ActorTypeNPC+Vampire,-Serana|VampireFaction|NONE|F|NONE|33.3
    Outfit = 0x7AAE~NewmFancyCuiras.esp|ActorTypeNPC+Vampire,-Serana|VampireFaction|NONE|F|NONE|50
    Outfit = 0x7AAF~NewmFancyCuiras.esp|ActorTypeNPC+Vampire,-Serana|VampireFaction|NONE|F|NONE|100
    1. sasnikol
      sasnikol
      • premium
      • 475 kudos
      The formula works for a guaranteed even distribution of a number of outfits. If you want to have the same chance to have vanilla outfit as one of your modded ones you can just increase N by 1 and assume that Vanilla outfit is the last one, so in your case you'll have 9 modded + 1 Vanilla - N = 10

      and chances will be
      Outfit = 0x7AA7~NewmFancyCuiras.esp|ActorTypeNPC+Vampire,-Serana|VampireFaction|NONE|F|NONE|10
      Outfit = 0x7AA8~NewmFancyCuiras.esp|ActorTypeNPC+Vampire,-Serana|VampireFaction|NONE|F|NONE|11.1
      Outfit = 0x7AA9~NewmFancyCuiras.esp|ActorTypeNPC+Vampire,-Serana|VampireFaction|NONE|F|NONE|12.5
      Outfit = 0x7AAA~NewmFancyCuiras.esp|ActorTypeNPC+Vampire,-Serana|VampireFaction|NONE|F|NONE|14.2
      Outfit = 0x7AAB~NewmFancyCuiras.esp|ActorTypeNPC+Vampire,-Serana|VampireFaction|NONE|F|NONE|16.6
      Outfit = 0x7AAC~NewmFancyCuiras.esp|ActorTypeNPC+Vampire,-Serana|VampireFaction|NONE|F|NONE|20
      Outfit = 0x7AAD~NewmFancyCuiras.esp|ActorTypeNPC+Vampire,-Serana|VampireFaction|NONE|F|NONE|25
      Outfit = 0x7AAE~NewmFancyCuiras.esp|ActorTypeNPC+Vampire,-Serana|VampireFaction|NONE|F|NONE|33.3
      Outfit = 0x7AAF~NewmFancyCuiras.esp|ActorTypeNPC+Vampire,-Serana|VampireFaction|NONE|F|NONE|50

      Each outfit will have an equal 10% chance to be distributed and there will be a 10% chance that all of them will fail (meaning a vanilla outfit will be used).
    2. hgjhjhjkl
      hgjhjhjkl
      • member
      • 3 kudos
      Thanks for the explanation.
  5. rentedrival04
    rentedrival04
    • member
    • 0 kudos
    This might sound extraordinarily dumb, but can anyone please explain what this bit is?

     7] 0x7FF85BDF8951 po3_SpellPerkItemDistributor.dll+0048951mov rcx, [rbp+0x50] |  D:\a\Spell-Perk-Item-Distributor\Spell-Perk-Item-Distributor\SPID\src\DistributePCLevelMult.cpp:154 Distribute::PlayerLeveledActor::LoadGame::thunk (mangled: ?thunk@LoadGame@PlayerLeveledActor@Distribute@@SAXPEAVCharacter@RE@@PEAVBGSLoadFormBuffer@5@@Z)

    This is a part of my crashlog call stack but I have no idea what it means?
    This is appearing in almost all my crashlogs. Any help would be appreciated.
    1. sasnikol
      sasnikol
      • premium
      • 475 kudos
      This is not the right place to ask about crash, since this article is for development of SPID mods.

      Anyways, that crashlog line (if it's at the top of the stack, which I think it isn't) only means that the crash happened somewhere in the game's code that is responsible for loading data from savegame file. Most likely, not in the SPID. In SKSE mods `thunk` is typically a function that calls the original game code.
    2. rentedrival04
      rentedrival04
      • member
      • 0 kudos
      You are right, that was not at the top of the stack. It was an issue caused by the mod Exquisite NPCS 2. Thanks for your reply though. It gave me info about something new. Much appreciated.
    3. sasnikol
      sasnikol
      • premium
      • 475 kudos
      Yay! gonna remove this comment now to keep it clean here.
  6. Dragonify03
    Dragonify03
    • premium
    • 32 kudos
    This feels like such a simple question but I keep confusing myself. If let's say I have a NEW Leather Armor that I want to distribute to 50% npc that are wearing vanilla Leather Armor, how do I go about doing it and making sure they have it equipped? There's many outfit that has Leather Armor so I thought I'd replace them all line by line, and then leveled list got involved and my brain imploded.
    1. sasnikol
      sasnikol
      • premium
      • 475 kudos
      Hmm, if you want to address all outfits that contains a piece of vanilla Leather Armor, I think your best shot is to use SkyPatcher to patch Outfits that contain vanilla parts and replace it with yours. Then any mods that distributed outfits (either original or modded) with Leather Armor will occasionally have your new leather armor in them. Probably you'd want to create a leveled list that could pick randomly either modded or vanilla leather armor and patch it in instead of directly patching your armor into outfits - this would give more variety.
  7. LummoxJR
    LummoxJR
    • premium
    • 48 kudos
    SPID 7.2.0.0 RC3 and RC11: I'm having an issue with distribution and could use another set of eyes. I'm trying to make my mod Little Library work with The Great Book Hunt, which involves distributing books to an NPC. The NPC starts in the aaaMarkers marker storage cell, which might be the problem. I was trying lines like this:

    Item = LLibBookHerbaneSpriggans||GreatBookHunt_Actor
    Item = LLibBookHerbaneChaurus||GreatBookHunt_Actor
    ...

    But whether on a new game or not, the books don't get distributed. I also tried moving the EditorID for the actor to the second section:

    Item = LLibBookHerbaneSpriggans|GreatBookHunt_Actor
    Item = LLibBookHerbaneChaurus|GreatBookHunt_Actor
    ...

    Nope! And I tried by FormID.

    Item = LLibBookHerbaneSpriggans||0x1~The Great Book Hunt.esp
    Item = LLibBookHerbaneChaurus||0x1~The Great Book Hunt.esp
    ...

    There are no errors related to this file in the log. The log does show that this file was processed. I also have other item distribution lines in this file, for other NPCs, that have been confirmed to work.

    I'm wondering if perhaps this NPC isn't marked as active because it doesn't have a persistent location set, and if maybe that's causing SPID to skip it? Weirdly, the author of The Great Book Hunt has reported success with this NPC using SPID, although I'm not sure which version yet, or if they're following a different set of steps than I did and maybe the test is happening on an existing save where the mod's quest and the actor reference have already been activated.

    Am I running up against an idiosyncrasy or bug in how SPID tracks NPCs? Am I missing something incredibly obvious?
    1. sasnikol
      sasnikol
      • premium
      • 475 kudos
      Hmm, I don't think the location where NPC starts is important. SPID 7.2 uses lazy distribution which typically happens when NPC is loaded into the cell where the player is.

      I don't see the immediate problem with these lines. What I usually do and suggest to do in cases when something is not distributed is to drop all filters and see if the NPC is reachable at all without any filters. That can confirm whether it is something with filters or the NPC/SPID.
    2. LummoxJR
      LummoxJR
      • premium
      • 48 kudos
      Waiting for the NPC to load into the player's cell may be the exact problem. The NPC in this case is a hidden one and never leaves the aaaMarkers cell. The Great Book Hunt basically gives you an item that, when equipped, opens the gift menu for this hidden NPC. I wonder if the author is using an older version of SPID that doesn't do the lazy distribution, and that's why it's working for them.
    3. sasnikol
      sasnikol
      • premium
      • 475 kudos
      Hmm, interesting case. Is that NPC marked as persistent and/or unique? current official version of SPID does both distribution on main menu AND "lazy" distribution. So if that NPC was made persistent or otherwise is required to be loaded by the game at launch time that it would've worked for them then.

      Anyways, I'll add a note for this case. As I'm drafting new syntax for SPID, this is something I'd want to support too
    4. LummoxJR
      LummoxJR
      • premium
      • 48 kudos
      The NPC is unique. It's in the persistent children of the aaaMarkers cell according to xEdit, but it doesn't have a persistent location (XLCN) set.
    5. sasnikol
      sasnikol
      • premium
      • 475 kudos
      Ah, yes. Then it is likely the issue with lazy loading. For now I can only suggest you to use SPID 7.1.3 or for this particular case maybe Container Item Distributor might be better, since NPC's is technically a container and the mod in question uses it as such
    6. LummoxJR
      LummoxJR
      • premium
      • 48 kudos
      Ah, CID is a great idea! Thanks. I could do SkyPatcher also. I use CDF in Little Library already but I think CID or SkyPatcher is probably better suited for this purpose.
  8. xybolt
    xybolt
    • premium
    • 7 kudos
    I am wondering about something that is not clear to me. If you have a NPC that has a outfit that is based on a LeveledList Item, does using SPID to distribute an outfit to this overrule the given leveled list? I am looking for an approach to add to an existing leveled list, but based on gender.

    Example: dawnguard.esm has several generic vampire NPC's, either "EncVampire...F" for female and "EncVampire...M" for male. Now, I can assign outfits based on several vampire armor mods (like Volkihar knight or vampire clothing expansion) to these but I want to keep vanilla leveled list as well.

    So the end goal is that spawned NPC vampires may wear either an outfit from vanilla leveled list and from some armor mods. Since I have some female specific armors (like twilight princess), I can add these to the female vampires exclusively.

    When testing, I never got vanilla armor as I probably overruled that through SPID.
    I guess I have to create an outfit that is a LvlItem. And that LvlItem is then a collection of several outfits?
    I'm really not sure if this approach is a good one. If not, please comment as I may waste my time if there is a better approach :o
    1. sasnikol
      sasnikol
      • premium
      • 475 kudos
      Hey, it sounds like you want to merge vanilla outfit and SPID-distributed. This is not possible. Outfit is a fixed set of wearable items. Those items can be standalone items or picked from LeveledItem, but that only allows variation within the same Outfit.

      You could make a new outfit with LeveledItems that would pick pick either Vanilla or modded items, but this will not give you the desired result, as each LeveledItem is calculated independently, so NPC's would end up with mixed items from vanilla and mod.

      You might take a look into RMB SPIDified mod. RowanMaBoot came up with a solution that uses both SPID and SkyPatcher to create a cool controllable variety of outfits, from what I saw it seems like you could find an inspiration there

  9. cdubsurf
    cdubsurf
    • premium
    • 0 kudos
    I'm trying to add an item based on whether another item is in the NPC's Inventory (versus using an outfit):

    Item = 0x1307~SOS - SPG Schlong Protective Gear.esp|ActorTypeNPC|ArmorElvenCuirass,ArmorElvenGildedCuirass|NONE|M|1|100

    I'm not sure if this is the correct way to go about it, if this is making SPID try to add the item to the armor, or if it's simply failing to find those armors as Keywords.

    SPID log doesn't show any errors but does not add the items either. 
    1. sasnikol
      sasnikol
      • premium
      • 475 kudos
      SPID doesn't support filtering by items. Here is what it supports:

      Supported Filterable Forms
      Form Filters allow you to match NPCs by the following criteria:

              Form type            Signature       NPC's Record in xEdit

      • Combat Style[CSTY]          ZNAM - Combat Style    
      • Class              [CLAS]          CNAM - Class
      • Faction          [FACT]           Factions
      • Race               [RACE]          RNAM - Race
      • Outfit             [OTFT]           DOFT - Default outfit
      • Specific NPC [NPC_]          FormID, EDID - Editor ID
      • NPC's Template*  [NPC_]  FormID, EDID - Editor ID
      • Voice Type            [VTYP]           VTCK - Voice
      • Known Spell          [SPEL]           Actor Effects
      • Skin                       [ARMO]          WNAM - Worn Armor
      • Editor Location*   [LCTN]           XLCN - Persistent Location (of ActorRef)
      • FormList*              [FLST]           Recursively looks for any form from the list.
    2. cdubsurf
      cdubsurf
      • premium
      • 0 kudos
      I thought that would have fallen under "Skin [ARMO] WNAM - Worn Armor" but now that I am doing a little more research on it, I realize where my mistake lies. 

      Thank you for the reply, and consider this a request to add "item" as a filterable field
    3. sasnikol
      sasnikol
      • premium
      • 475 kudos
      Yeah it's been on the list for a while now. It would require some groundwork to be able to do that
  10. Woolwrath
    Woolwrath
    • member
    • 0 kudos
    I have a problem where SPID distributed weapon will disappear after game reload.
    1. sasnikol
      sasnikol
      • premium
      • 475 kudos
      Please share the line you are trying to use. Also, to clarify by game reload you mean restarting the whole game or reloading a save?
    2. Woolwrath
      Woolwrath
      • member
      • 0 kudos
      After the NPC kills me and I am reloaded through a save.

      Item = WeaponEditorId|NPCEditorID|NONE|NONE|NONE|1|100

      I also have an armor SPID file adding an outfit to the same NPC. Not sure if that matters.

      Outfit = OutfitEditorID|NPCEditorID|NONE|NONE|NONE|NONE|100
    3. sasnikol
      sasnikol
      • premium
      • 475 kudos
      Ah, it might be that you reload prior to the point where distribution happened 🤔 thus it reverts changes to inventory but the npc is not unloaded, thus not getting new distribution. I’ll think of a way to handle this
  11. crmcdonaljr
    crmcdonaljr
    • premium
    • 1 kudos
    I would like to thank you before I ask, I appreciate the mod and support.

    I'm trying to distribute the EroticArmor Keyword to vanilla armors for a female skimpy vanilla armor/clothes replacer [Remodeled Armor].  This is loaded in MO2 after the Bodyslide for remodeled armor and the bashed patch. It's broken and I need help.

    I got the idea after fixing "Kreiste's Skimpy Outfits for HIMBO-SOS-Revealing Keywords INI Fixed" for the TNG body, I don't have SOS.  It ran with three skips; not bad.

    So, I took the Krieste SPID script to use it for the female replacer version with appropriate changes.  Since both are vanilla armor and clothes replacers, the Form IDs [SSEEDIT] and DLC names should be the same for male and female clothes and armor.

    Reference to the keyword is installed by OSL Aroused through
    SexLabAroused.esm 
    SSEEdit      form ID 0108C7F6        EditorID EroticArmor

    I added |NONE|F to the end of each keyword assignment to limit the change to females in the SPID INI:
    Spoiler:  
    Show

    ;Add EroticArmor to Armors; Hide, Fur, Studded, Elven, Chitin light, Scaled, Elven Gilded, Glass, Stalhrim light, Dragonscale, Iron, Iron Gilded, Bonemold light, Dwarven, Improved Bonemold, Steel Plate, Chitin Heavy, Orcish, Ebony, Ebony Mail, Nordic carved, Dragonplate, Stalhrim Heavy, Daedric, Falmer, Falmer Heavy, Ivory, General Tullius, Imperial, Nightingale, Blades, Darkbrotherhood, Ancient Nord, Stormcloak Officer, Stormcloak, Theives Guild, Wolf, Dawnguard, General Carius, 
    Keyword = 0x8C7F6~SexLabAroused.esm|Armor|ArmorCuirass,0x13911,0x6f393,0x10594b,0x10594d,0x10594f,0x1b3a2,0x896a3,0x1cd87~Dragonborn.esm,0x1b3a4,0x1392a,0x13939,0x1cda2~Dragonborn.esm,0x1393e,0x12e49,0x13948,0x13952,0xf6f22,0x37564~Dragonborn.esm,0x37563~Dragonborn.esm,0x1394d,0x3ab26~Dragonborn.esm,0x1395c,0x1cd8a~Dragonborn.esm,0x13957,0x13961,0x52794,0x1cd97~Dragonborn.esm,0x13966,0x1cd9f~Dragonborn.esm,0x1396b,0xb83cb,0xb83cb~Dawnguard.esm,0xc816~Dawnguard.esm,0x5CBFE,0x13ed9,0x5DB86,0xFCC0E,0xFCC0F,0x4b28b,0x4b28b~Unofficial Skyrim Special Edition Patch.esp,0x10eb5b,0x105966,0x18388,0x8697E,0xa6d7b,0xad5a0,0x1092b5,0x36584,0xe35db,0xcae15,0xf3fb~Dawnguard.esm,0xf402~Dawnguard.esm,0xf404~Dawnguard.esm,0x376F1~Dragonborn.esm,0x2151e,0x21520,0x21508,0x21525,0x21507,0xc7f5b,0x2150d,0x21522,0xa6d7b|NONE|F
    ;Add EroticArmor to Clothing; Black Robes, Blue Robes, College Robes, Emperor's Robes, Green Robes, Hooded Black Robes, Hooded Blue Robes, Hooded Monk Robes, Mage Robes, Monk Robes, Monk RobesDG, Ragged Robes, Red Robes, Vaermina Robes, Belted Tunic, Blacksmith's Apron, Chef's Tunic, Clothes, Mage Student Robes, Archmage Robes, Vampire, Cultist, Miraak, Telvanni,Temple,
    Keyword = 0x8C7F6~SexLabAroused.esm|Armor|ClothingBody,0x106661,0x376da~Dragonborn.esm,0xA199B,0xD3DEA,0x10D6A5,0x15516,0x10CFF0,0x107108,0x10710A,0x107106,0x6B46B,0xBACF3,0x1570c~Dawnguard.esm,0x13105,0x10CFF2,0xE739B,0x1BE1A,0x5B69F,0x6FF37,0x1BC82,0x209A6,0x3452E,0x17695,0x261C0,0x6C1D8,0x6C1D9,0x6C1DA,0xF1229,0x5B6A1,0x6FF38,0x4223C,0x6FF45,0xCEE80,0x376df~Dragonborn.esm,0x86991,0xF8713,0xF8715,0x8698C,0x6FF43,0x80697,0x5DB7B,0xE84C6,0xE40DF,0xE9EB5,0x8F19A,0xE9EB~Dawnguard.esm,0xE0DD0,0x3C9FE,0xD191F,0x10D67D,0x10CEE4,0x10D667,0x10D2B4,0x10D677,0x10D67B,0x10D680,0x10D664,0x10F570,0x19ADF~Dawnguard.esm,0x191f3~Dawnguard.esm,0x142c7~Dawnguard.esm,0x191f2~Dawnguard.esm,0x11a84~Dawnguard.esm,0xb5db~Dawnguard.esm,0x194c5~Dawnguard.esm,0x11a85~Dawnguard.esm,0x47D7~Dawnguard.esm,0x37B8A~Dragonborn.esm,0x1CDAA~Dragonborn.esm,0x3706B~Dragonborn.esm,0x37065~Dragonborn.esm,0x3706C~Dragonborn.esm,0x37066~Dragonborn.esm,0x39E1E~Dragonborn.esm,0x39D20~Dragonborn.esm,0x39D22~Dragonborn.esm,0x376ED~Dragonborn.esm,0x1CDAB~Dragonborn.esm,0x3910E~Dragonborn.esm|NONE|F


    I created an empty mod and named it "Remodeled_Armor_3BA_EroticArmor_Keywords_KID"
    I named the INI Remodeled_Armor_3BA_EroticArmor_Keywords_KID.ini

    Errors from po3_keyworditemdistributor.log, both keyword assignments failed
    [18:09:26:968] INI : Data\Remodeled_Armor_3BA_EroticArmor_Keywords_KID.ini
    [18:09:26:968] Failed to parse entry [Keyword = 0x8C7F6~SexLabAroused.esm|Armor|ArmorCuirass,0x13911,0x6f393,0x10594b,,,,, 

    I did correct 2 things, removed 1 "|" pipe so female selection would work and a spelling fix for SexLabAroused.  I just don't see my syntax error now.

    Could you help?
    1. sasnikol
      sasnikol
      • premium
      • 475 kudos
      Hey, I think you're in the wrong place this is SPID page, the one that distributes stuff to NPCs. While you're dealing with KID which is distributing keyword to items, magic effects and whatnot. While they have similarities in their syntax, they are not the same and I'm not too familiar with KID specifics.
    2. crmcdonaljr
      crmcdonaljr
      • premium
      • 1 kudos
      It would have been helpful to have pointed me in the right direction.

      But it doesn't matter now because I just got it working. 😊