SPL file format

Applies to:
BG1, BG1: TotS, BG2, BG2: ToB, PST, IWD, IWD:HoW, IWD:TotL, BGEE

General Description
This file format describes a "spell". Spells include mage spells, priest spells, innate abilities, special abilities and effects used for game advancement (e.g. animation effects, custom spells). SPL files have a similar structure to ITM files.

Header:Size=114 Bytes Ext. Header: Size= 40 Bytes Feature Block: Size=48 Bytes

Detailed Description
SPL files consist of a main header, zero or more extended headers (each containing zero or more feature blocks) and zero or more casting feature blocks. All the feature blocks are stored as a continuous data segment, with each extended header containing an offset into this data, and the main header containing an offset into this data for the casting feature blocks.

Overall structure:


Offset Size (datatype) Description
0 4 (char array)

Signature (‘SPL  ’)

4 4 (char array)

Version (‘V1 ‘)

8 4 (dword)

Spell Name - Unidentified (strref)

12 4 (dword)

Spell Name - Identified (strref) (usually -1) (unused)

16 8 (resref)

Completion Sound

24 4 (dword)

Flags

28 2 (word)

Spell type:

Info:
30 4 (dword)

Exclusion Flags

34 2 (word)

Casting Graphics

36 1 (char)

Min Level (unused)

37 1 (byte)

Primary Type (School) (IWD: school.2da, BG2:mschool.2da)

Info: For subspells, Primary Type should always match parent spell, both for interaction with opcodes #220/#229, and with the specialists save bonus/penalty (and opcode #346).
38 1 (byte)

Min Strength (unused)

39 1 (char)

Secondary Type (BG2:msectype.2da)

Info: For subspells, Secondary Type should always match parent spell, for interaction with opcodes #221/#230.
40 1 (byte)

Min Strength Bonus (unused)

41 1 (byte)

Usability 1 (unused)

42 1 (byte)

Min Int (unused)

43 1 (byte)

Usability 2 (unused)

44 1 (byte)

Min Dex (unused)

45 1 (byte)

Usability 3 (unused)

46 1 (byte)

Min Wis (unused)

47 1 (byte)

Usability 4 (unused)

48 2 (word)

Min Con (unused)

50 2 (word)

Min Cha (unused)

52 4 (dword)

Spell Level

56 2 (word)

Stack amount (unused)

58 8 (resref)

Spellbook icon (BAM). The engine replaces the last character of this filename with a C.

66 2 (word)

Lore to ID (unused)

68 8 (resref)

Ground icon (unused)

76 4 (dword)

Weight (unused)

80 4 (dword)

Spell Description - Unidentified (strref)

84 4 (dword)

Spell Description - Identified (strref) (usually -1) (unused)

88 8 (resref)

Description icon (unused)

96 4 (dword)

Enchantment (unused)

100 4 (dword)

Extended Header offset

104 2 (word)

Extended Header count

106 4 (dword)

Feature Block Table offset

110 2 (word)

Casting Feature Block offset (these feature blocks may not use target type 2)

112 2 (word)

Casting Feature Block count



Extended headers represent the effects of a spell on the target. Multiple extended headers can be set in a spell, to allow the spell to use effects based on the level of the caster. Extended headers should be in the file in order of increasing level

Offset Size (datatype) Description
0 1 (char)

Spell form

  • 1 - Standard
  • 2 - Projectile
Note: This field matters only for ITM, SPL files shouldn’t function any different based on their type (even 0).
1 1 (char)
  • bit 2: ‘Friendly’ ability
2 2 (word)

Location

  • 0 ⟶ None
    • Ability will not be selectable through the UI (but still available to scripts and spell-casting opcodes).
  • 1 ⟶ Weapon
  • 2 ⟶ Spell
    • Ability can be selected from “Cast Spell (F7)” button, and from Quick-spell buttons.
  • 3 ⟶ Item
  • 4 ⟶ Innate
    • Ability can be selected from “Special Abilities (F12)” button.
  • 5+ ⟶ As 0.
Note: Subspells don’t require an Ability Location.
4 8 (resref)

Memorised icon (BAM). The engine replaces the last character of this filename with a B.

12 1 (char)

Target

Note:
  • This field doesn’t matter when the ability is activated/cast by script or when cast by another opcode.
  • Subspells don’t require an Ability Target.
13 1 (char)

Target count

  • Only usable with Ability Targets 1, 3, or 4.
  • Targeting reticle will display amount remaining while selecting targets.
  • Double-clicking a target/location will target it for the remaining amount.
  • Regardless of the number of targets, only a single “Memorization” will be expended.
  • This feature cannot be utilized by scripts.
    • Scripts will treat this field as if it’s always 1.
14 2 (word)

Range

Info: As far as subspells are concerned, their Range is only checked if cast through opcode #148, opcode #232, opcode #258, or opcode #260.
16 2 (word)

Level Required

Info: Standard spellcasting only utilizes the first byte (0 – 255), but opcodes that specify Casting Level (146*p2=2/326*EFF/333) have access to the entire range (0 – 65535).
18 2 (word)

Casting Time

Info:
  • This value represents the number of tenths of rounds that it takes to cast the spell.
  • Combat scripting in the IE gets very dumb when Casting Times start matching or exceeding 10 (one full round). The engine assumes any spell is cast within a round, and can sometimes just go to the next round’s action (f.i. the mage sits there casting for six seconds, then throws the spell away to use a sling).
    • As a result, you might want to use maximum Casting Times of 9 (i.e. 910ths of a round) even for spells which are supposed to have a Casting Time of a full round.
  • As far as subspells are concerned, their speed is only used if cast through opcode #146/opcode #148 with the Cast normally option.
20 2 (word)

Times per day

22 2 (word)

Dice Sides (unused)

24 2 (word)

Dice Thrown (unused)

26 2 (word)

Enchanted (unused)

28 2 (word)

Damage Type (unused)

30 2 (word)

Count of feature blocks

32 2 (word)

Offset to feature blocks

34 2 (word)

Charges (unused)

36 2 (word)

Charge depletion behaviour (unused)

38 2 (word)

Projectile (BG2: projectl.ids. Note: in BG2, this value is off-by-one from projectl.ids value. I.e. binary value of 2 corresponds to 0x1 - ARROW)



Any action carried out by a spell is done by feature blocks, each of which holds an effect number as well as targetting and timing information. The engine appears to roll a probability for each valid target type, rather than one probability per attack.

Offset Size (datatype) Description
0 2 (word)

Opcode Number

2 1 (char)

Target type

Info: See here for further details.
3 1 (char)

Power

4 4 (dword)

Parameter 1

8 4 (dword)

Parameter 2

12 1 (char)

Timing mode

Info: See here for further details.
13 1 (char)

Dispel / Resistance

The default behaviour is that effects cannot be dispelled and ignore magic resistance.

  • bit 0 ⟶ Can be dispelled, affected by magic resistance
  • bit 1 ⟶ Ignores magic resistance (when used in combination with bit 0)

This can also be presented in the more traditional way:

  • 0 ⟶ Natural/Nonmagical
  • 1 ⟶ Can be dispelled/Affected by resistance
  • 2 ⟶ Cannot be dispelled/Ignores resistance
  • 3 ⟶ Can be dispelled/Ignores resistance

The only difference between 0 and 2 is that 0 will automatically convert to 2 when targeting yourself.

14 4 (dword)

Duration

18 1 (char)

Probability 1

19 1 (char)

Probability 2

Info: See here for further details.
20 8 (resref)

Resource

28 4 (dword)

Dice Thrown / Maximum Level

Info: See here for further details.
32 4 (dword)

Dice Sides / Minimum Level

Info: See here for further details.
36 4 (dword)

Saving throw type

Info: See here for further details.
40 4 (dword)

Saving Throw Bonus

44 4 (dword)

TobEx: Stacking ID. Checked when bit 25 of the Saving Throw Type is set.

If two effects of the same opcode are applied, both have Limit Effect Stacking bit set, and both have the same stacking ID, then the latter applied effect is suspended in application until the former effect expires. Regardless of whether it is applied, the latter effect will expire at the same time that it would expire if it was applied. In other words, the total duration of some non-stacking effect opcode is not extended because more than one copy of the effect was applied.

Stacking IDs are unique to the opcode being applied. To maintain uniqueness of stacking IDs between different mods, one recommendation is to use the higher word of Special as the modder’s Infinity Engine Community Prefix, then use the lower word as an identifying ID. For example, 0x41360001 (‘A6’ 0x0001).





Bit Byte 1 Byte 2 Byte 3 Byte 4
0 Unknown Unknown Not in combat Can target invisible (BGEE, TobEx)
1 Unknown Breaks Sanctuary (BGEE) Unknown Castable when silenced (BGEE, TobEx)
2 Unknown Hostile / Breaks Invisibility Unknown Unknown
3 Unknown No LOS required Unknown Unknown
4 Unknown Allow spotting Unknown Unknown
5 Unknown Outdoors only Unknown Unknown
6 Unknown Ignore dead-magic and wild surge effect Unknown Unknown
7 Unknown Ignore wild surge effect (i.e. trigger/contingency) Unknown Unknown


bit 0: Exclude Chaotic priests. (BG2 & HoW)
bit 1: Exclude Evil priests. (BG2 & HoW)
bit 2: Exclude Good priests. (BG2 & HoW)
bit 3: Exclude GENeutral priests. (BG2 & HoW)
bit 4: Exclude Lawful priests. (BG2 & HoW)
bit 5: Exclude LCNeutral priests. (BG2 & HoW)
bit 6: Exclude Abjurers
bit 7: Exclude Conjurers
bit 8: Exclude Diviners
bit 9: Exclude Enchanters
bit 10: Exclude Illusionists
bit 11: Exclude Invokers
bit 12: Exclude Necromancers
bit 13: Exclude Transmuters
bit 14: Wild Magic (exclude Generalists) (BG2)
bit 15 - 29: Unused
bit 30: Exclude Cleric/Paladin
bit 31: Exclude Druid/Ranger

NB.Alignment and School exclusion bits cannot be combined.


BG1,BG2,IWD
00
    ...No animation
08
09 Necromancy
10 Alteration
11 Enchantment
12 Abjuration
13 Illusion
14 Conjuration
15 Invocation
16 Divination
17 White sparks
18 Black sparks
19 White sparks
20 White sparks
21 White sparks
22 White -> red sparks
23 White -> purple/red sparks
24 White -> red sparks
26 White sparks
32 White sparks
34 White sparks
56461 No animation
65535 No animation

NB. The 'spark' entries are related to sprklclr.2da (and probably opcode #41)

PST
35: Abjuration
36: Alteration
37: Conjuration
38: Enchantment
39: Divination
40: Illusion
41: Invocation
42: Necromancy
44: Special (Innate) Skill