SPID: The Complete Reference (by sasnikol)
as of SPID 3.0.0
Everything you need to know to start creating SPID mods.
Table of Contents
- 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 Fallout 4 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:
- Keywords
- Factions
- Spells
- Perks
- 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:
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]*
- Package [PACK, FLST*]
- Keyword* [KYWD]
- Outfit [OTFT]
- SleepOutfit [OTFT]
- Faction [FACT]
- Skin [ARMO]
* 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:
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.
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. LaserMusket or BaseballBat).
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:
Form = 0x12345|A,B|0x12,0x34
can be read as "give a form 0x12345 when NPC has (A OR B) AND (0x12 OR 0x34)".
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. Piper).
- NPC's EditorID (e.g. CompanionPiper).
- 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).
Example:
Form = 0x12345|MinuteMan
Give a form to NPC with ActorTypeNPC OR ActorTypeGhoul
Form = 0x12345|ActorTypeNPC,ActorTypeGhoul
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.
Form = 0x12345|-Piper
- Partial match modifier (*). Placed in front of a term. This will make the expression allow partial matches of the term. (e.g. "Raider" in "Raider Boss")
Form = 0x12345|*Raider
- 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.
Form = 0x12345|ActorTypeNPC+Raider+ActorTypeGhoul
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 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:
Form = 0x12345||FeralGhoulRace
Give a form to NPCs that are located in Diamond City (DiamondCityLocation "Diamond City" [LCTN:00002CEF]) OR report crimes in Diamond City (CrimeDiamondCIty ""Diamond City" [FACT:00002CB4]).
Form = 0x12345||DiamondCityLocation,CrimeDiamondCity
Additionally, here you can specify only name of the plugin where NPC is defined. This will match only NPCs from given plugin.
Example:
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.
Form = 0x12345||-FeralGhoulRace
- Combining modifier (+). Placed between multiple forms you want to combine. This will make the expression only match NPCs who have ALL of the forms.
Form = 0x12345||FeralGhoulRace+CrimeDiamondCity
Level Filters
A list of comma-separated expressions with numeric ranges that allows you to filter eligible NPCs by their leveled properties, such as NPC level or actor values.
Form = 0x12345|||LevelExpression,ActorValueExpression1,ActorValueExpression2,...
Supported Values
Level Filters allow you to match NPCs by the following criteria:
Value Expression
- Level min/max
- Actor Value ActorValueInfoID*(min/max)
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.
Form = 0x12345|||5
Give a form to NPCs who has 50 in Destruction skill level
Form = 0x12345|||FrostResist(50/50)
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 actor values 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)
Example:
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.
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.
Form = 0x12345||||-U/M/-C
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 templates.
Additionally, String Filters and Form Filters allow you to target specific NPCs using EditorID or FormID, including IDs of templates that they derive from.
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:
Form = PulseGrenade
Give 3 pulse grenades
Form = PulseGrenade|||||3
Give somewhere between 10 and 20 pulse grenades
Item = PulseGrenade|||||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:
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:
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:
Form = 0x12345||||||60
Give a form with a 0.01% chance
Form = 0x12345||||||0.01
0 comments