Mod:Battlespire Save Game Offset List
An editor has requested for this article to be peer reviewed to receive a broader perspective on how it may be improved. Please make any edits as you see fit to help improve the quality of this article. |
Saved games in Battlespire are made up of 4 files: IMAGE.RAW SAVENAME.DAT SAVETREE.DAT SAVEVARS.DAT
Contents
- 1 IMAGE.RAW
- 2 SAVENAME.DAT
- 3 SAVETREE.DAT
- 4 SAVEVARS.DAT
- 5 Enumerations
- 5.1 Arrays
- 5.2 Lists
- 5.2.1 ArmorList
- 5.2.2 ElementEnchantmentList
- 5.2.3 ElementSpellList
- 5.2.4 EnemyList
- 5.2.5 ItemList
- 5.2.6 MaterialList
- 5.2.7 RaceList
- 5.2.8 SkillList
- 5.2.9 SpellDeliveryList
- 5.2.10 SpellDetonationList
- 5.2.11 SpellList
- 5.2.12 SpellSchoolList
- 5.2.13 SpellTargetList
- 5.2.14 VariableList
- 5.2.15 WeaponList
IMAGE.RAW[edit]
This is the mini screenshot that is shown while selecting the game to load. The image file is a headerless 80x50 15 bit raw image.
SAVENAME.DAT[edit]
This file is a 32 byte file that just contains the name given to the saved game (not the player).
SAVETREE.DAT[edit]
The SAVETREE.DAT file is the primary save game data file for Battlespire. The file begins with a 4 byte value that may be a file version and then is primarily composed of unordered records with no record index mapping, each record begins following the previous. Trailing that is an additional variable length section that I suspect may be control object related but have not verified yet.
RecordType[edit]
There are 9 known record types. All records of the same type are the same length and begin with a header, followed by the record's actual data.
TypeID | RecordLength | Name | Description |
---|---|---|---|
2 | 820 | Item | All objects that are items (can be picked up, equpped, etc), not the level's 3D objects (table, rug, etc) |
3 | 856 | Player | The player's personal details (attributes, skills, etc)
The player's inventory, known spells, etc are separate records of their specific type and linked to the player in the record header |
6 | 176 | Object | 3D objects such as rugs on floor, doors, levers/switchs, moveable platforms, etc.
Note: NPCs (like Chimere) are considered an object |
7 | 66 | Projectile | Short lived objects that exist for as long as the projectile is in motion/exists |
9 | 184 | Spell | These records are for spells known by the player, enchantments on items, and cast spell effects in some cases |
18 | 856 | Monster | Same length and mostly identical to the player record, with only a few different usages of some values
This will be documented together with the player record type with any known differences noted |
23 | 70 | Options | Believe this is a legacy data type left over from Daggerfall as only one game option appears to be saved here |
51 | 1270 | Automap | Large flag field that indicates what areas on the map have been discovered and should be displayed in the automap |
66 | 514 | Effect | Contains details on active spell effects for most spell's that have an effect with a duration
Confusion/Shield do not use this and store values on the player or monster record instead |
Header[edit]
All record types begin with a 65 byte header. The values are largely the same for all types with a few exceptions.
Offset | DataType | Name | Description |
---|---|---|---|
0 | u32 | RecordLength | Length of record - excludes self (i.e. length 100 would have a total length of 104 including this)
Size is always the same for each record type (possible Automap is variable in interiors, need to doublecheck in L5+) |
4 | u8 | Type | What the record is for, player/NPC share the same structure despite being different types
Enumeration value for |
5 | u16 | ViewPitch | ↕ - Also used for the hoizontal grid size on the automap record (51) |
7 | u16 | ViewYaw | ↔ - Also used for the vertical grid size on the automap record (51) |
9 | u16 | ViewRoll | ↻ - Generally only relevant for 3D objects |
11 | float | PositionX | East/West |
15 | float | PositionY | Up/Down - not North/South |
19 | float | PositionZ | North/South |
23 | u16 | Unknown_017 | Looks to be a flag field though it's usage and value meanings seems to depend on the record type |
25 | u32 | FileID | This is the ID number for the 3D file for objects defined in level BS6
T2/6 - Only set when standard record - content (116) and random are 0 Appears unused for T3/9 - Unknown purpose for T18 |
29 | u32 | Unknown_01D | Unknown |
33 | u32 | RecordID | Unique ID for each record, player is always 50C30000 (50000) |
37 | u32 | Unknown_025 | Timestamp for when used gem reappears |
41 | s16 | LinkID | Looks like it generates a number starting at 0 for each record that has a link - unsure how this actually ties to linked record |
43 | s16 | Unknown_02B | Similar to LinkID, it counts up from 0 but not sure purpose
It is primarily set on records that have links but does not match up with LinkID and counts far higher |
45 | u32 | Unknown_02D | Think this is when you started breathing underwater |
49 | u32 | Unknown_031 | These 3 are definitely related |
53 | u32 | Unknown_035 | but are somewhat odd where they appear to link to every other record |
57 | u32 | Unknown_039 | in an ownership chain (i.e. Creature > Item1 > Sack1 > Sack1Item1 > Sack1Item2) |
61 | u32 | ParentID | RecordID of parent (i.e. things the player is holding and known spells will have 50C30000 here, things in a chest will have the chest's ID)
Objects directly on the map (not carried or in chest/sack/etc) will have 1 (or occasionally 0?) |
Note: Offset is from beginning of the record, not the file.
Item[edit]
Item type objects. Of note, this type is fairly large as it has its own data as well as contains an Object
and a partial Player
record type embedded in it as well. Descriptions for the embedded types will be largely skipped and can be found in the relevant record type section except where usage is unique for items.
Offset | DataType | Name | Description |
---|---|---|---|
0 | struct[65] | Header | Common record header structure
|
65 | char[32] | ItemName | Base item name, the added enchantment name is set separately
Note: For armor/clothes, the name is set from a value in the BSI file for that item (i.e. Sandals instead of the item name Boots) |
97 | u16 | ItemID | Enumeration field using ItemList
|
99 | char[9] | FileName | Only set for armor, clothes, and weapons - pretty sure this is 8 with a NULL terminator
First character is dynamic for male/female - armor numbering and clothes type/number appears to be randomly generated when not hardcoded item |
108 | u32 | Condition | |
112 | u32 | Condition_Max | |
116 | u16 | ModifierID | Multi use field
|
118 | u32 | Weight | Divide by 2 |
122 | s8 | SpellID | Enumeration value using SpellList - Used by potions
Note: Enchantment spells are set towards the end |
123 | u32 | Unknown_07B | |
127 | u32 | Quantity | Stackable items (arrows/etc) |
131 | u16 | IsContainer | Boolean value set on sacks/chests/etc - odd it's 2 bytes so maybe 2x u8s but no usage of 2nd byte seen |
133 | u32 | BaseItemTypeID | Start of embedded Object record type
|
137 | u32 | Unknown_089 | Usually only set when carried |
141 | u32 | Unknown_08D | Usually only set when carried |
145 | u32 | Unknown_091 | Usually only set when carried |
149 | u32 | Unknown_095 | Usually only set when carried |
153 | u32 | Unknown_099 | Usually only set when carried |
157 | float | UNK_X | |
161 | float | UNK_Y | |
165 | float | UNK_Z | |
169 | float | ItemX | |
173 | float | ItemY | |
177 | float | ItemZ | |
181 | u32 | RotatePitch | |
185 | u32 | RotateYaw | |
189 | u32 | RotateRoll | |
193 | u16 | Unknown_0C1 | May be 2 u8s - second byte is 06 if equipped by player |
195 | u32 | Unknown_0C3 | |
199 | u32 | Unknown_0C7 | |
203 | u32 | Unknown_0CB | |
207 | u32 | Unknown_0CF | |
211 | u32 | Unknown_0D3 | |
215 | u32 | Unknown_0D7 | |
219 | u32 | Unknown_0DB | |
223 | u32 | Unknown_0DF | |
227 | u32 | Unknown_0E3 | |
231 | u32 | Unknown_0E7 | |
235 | u32 | Unknown_0EB | |
239 | u32 | Unknown_0EF | |
243 | u8 | Unknown_0F3 | End of embedded Object record type
|
244 | char[33] | EnchantmentName | Partial name that is tacked onto the enchanted item's name (i.e. "of Stupendous Ridiculousness")
Pretty sure this is 32 with a NULL terminator |
277 | u32 | EnchantmentItem | Matches to Item value in enchantment definition text files
As best I can tell:
|
281 | unknown[67] | Unknown_119 | No idea - since this is a partial character record it may be name padding (32) leaving 35 bytes before it or maybe a dummy header with two bytes padding somewhere? |
348 | u32 | Strength | Start of partial Player object record type data for enchanted items
|
352 | u32 | Intelligence | Base values are used when enchanted items alter attributes/skills |
356 | u32 | Willpower | |
360 | u32 | Agility | |
364 | u32 | Endurance | |
368 | u32 | Personality | |
372 | u32 | Speed | |
376 | u32 | Luck | |
380 | u32 | Strength_Base | |
384 | u32 | Intelligence_Base | |
388 | u32 | Willpower_Base | |
392 | u32 | Agility_Base | |
396 | u32 | Endurance_Base | |
400 | u32 | Personality_Base | |
404 | u32 | Speed_Base | |
408 | u32 | Luck_Base | |
412 | u16 | SpellPoints | |
414 | u16 | SpellPoints_Max | |
416 | u16 | SpellPoints_Base | |
418 | u32 | Wounds | |
422 | u32 | Wounds_Max | |
426 | u32 | Wounds_Base | |
430 | u32 | Medical | |
434 | u32 | Medical_Count | |
438 | u32 | Medical_Base | |
442 | u32 | Jumping | |
446 | u32 | Jumping_Count | |
450 | u32 | Jumping_Base | |
454 | u32 | Lockpicking | |
458 | u32 | Lockpicking_Count | |
462 | u32 | Lockpicking_Base | |
466 | u32 | Stealth | |
470 | u32 | Stealth_Count | |
474 | u32 | Stealth_Base | |
478 | u32 | Swimming | |
482 | u32 | Swimming_Count | |
486 | u32 | Swimming_Base | |
490 | u32 | Backstabbing | |
494 | u32 | Backstabbing_Count | |
498 | u32 | Backstabbing_Base | |
502 | u32 | Dodging | |
506 | u32 | Dodging_Count | |
510 | u32 | Dodging_Base | |
514 | u32 | Running | |
518 | u32 | Running_Count | |
522 | u32 | Running_Base | |
526 | u32 | Destruction | |
530 | u32 | Destruction_Count | |
534 | u32 | Destruction_Base | |
538 | u32 | Restoration | |
542 | u32 | Restoration_Count | |
546 | u32 | Restoration_Base | |
550 | u32 | Illusion | |
554 | u32 | Illusion_Count | |
558 | u32 | Illusion_Base | |
562 | u32 | Alteration | |
566 | u32 | Alteration_Count | |
570 | u32 | Alteration_Base | |
574 | u32 | Thaumaturgy | |
578 | u32 | Thaumaturgy_Count | |
582 | u32 | Thaumaturgy_Base | |
586 | u32 | Mysticism | |
590 | u32 | Mysticism_Count | |
594 | u32 | Mysticism_Base | |
598 | u32 | ShortBlade | |
602 | u32 | ShortBlade_Count | |
606 | u32 | ShortBlade_Base | |
610 | u32 | LongBlade | |
614 | u32 | LongBlade_Count | |
618 | u32 | LongBlade_Base | |
622 | u32 | HandToHand | |
626 | u32 | HandToHand_Count | |
630 | u32 | HandToHand_Base | |
634 | u32 | Axe | |
638 | u32 | Axe_Count | |
642 | u32 | Axe_Base | |
646 | u32 | BluntWeapon | |
650 | u32 | BluntWeapon_Count | |
654 | u32 | BluntWeapon_Base | |
658 | u32 | Missile | |
662 | u32 | Missile_Count | |
666 | u32 | Missile_Base | |
670 | u32 | CriticalStrike | |
674 | u32 | CriticalStrike_Count | |
678 | u32 | CriticalStrike_Base | |
682 | char[24] | ClassName | Not set but assuming that's what it is based on location/size |
706 | u8 | Resistance | These do not appear to used when applying an enchantment advantage/disadvantage - base values are used instead |
707 | u8 | Immunity | |
708 | u8 | AcuteHearing | |
709 | u8 | SpellAbsorption | |
710 | u8 | RapidHealing | |
711 | u8 | RegenerateHealth | |
712 | u8 | RegenerateSPs | |
713 | u8 | Athleticism | |
714 | u32 | IncreaseMagery | |
718 | u8 | AdrenalineRush | |
719 | u8 | LowTolerance | |
720 | u8 | CriticalWeakness | |
721 | u8 | NoRegenOfSpellPoints | |
722 | u8 | ForbiddenWeapons | |
723 | u8 | ForbiddenArmor | |
724 | u8 | ForbiddenShield | |
725 | u8 | ForbiddenMaterial | |
726 | char[24] | ClassName_Base | Not set but assuming that's what it is based on location/size |
750 | u8 | Resistance_Base | |
751 | u8 | Immunity_Base | |
752 | u8 | AcuteHearing_Base | |
753 | u8 | SpellAbsorption_Base | |
754 | u8 | RapidHealing_Base | |
755 | u8 | RegenerateHealth_Base | |
756 | u8 | RegenerateSPs_Base | |
757 | u8 | Athleticism_Base | |
758 | u32 | IncreaseMagery_Base | Doesn't appear this will lower the value (i.e. player has 3x and item is 1.5x, player will still have 3x value) |
762 | u8 | AdrenalineRush_Base | |
763 | u8 | LowTolerance_Base | |
764 | u8 | CriticalWeakness_Base | |
765 | u8 | NoRegenOfSpellPoints_Base | |
766 | u8 | ForbiddenWeapons_Base | |
767 | u8 | ForbiddenArmor_Base | |
768 | u8 | ForbiddenShield_Base | |
769 | u8 | ForbiddenMaterial_Base | End of embedded Player record type
|
770 | u8 | ArmorValue1 | This and next byte are only set on armor/clothes but not if the item is enchanted? |
771 | u8 | ArmorValue2 | Appears to be the last digit of file name for armor - may make sense based on squirrelly way armor is handled |
772 | u16 | Unknown_304 | Not really sure if 16, assuming from gap till enchantment stuff - FF00 for all except sigils which are 0000 |
774 | u32 | Unknown_306 | |
778 | u32 | Unknown_30A | |
782 | s8 | CastOnEquip | Enumeration field using SpellList
|
783 | s8 | CastOnUse | Enumeration field using SpellList
|
784 | s8 | CastOnStrike | Enumeration field using SpellList
|
785 | s8 | Magnitude | Referred to as that in guide but assuming it's actually the level passed to the spell formula |
786 | s8 | Element | Enumeration field using ElementEnchantmentList
Guessing it's just to control the casting animation when set on inapplicable spells |
787 | u32 | EnchantmentCharges | |
791 | u32 | EnchantmentCharges_Max | |
795 | u32 | Unknown_31B | |
799 | u32 | Unknown_31F | |
803 | u32 | EnchantmentID | Refers to ID value in MG0_GEN & MG2_SPC text files |
807 | u32 | Unknown_327 | |
811 | u32 | Unknown_32B | |
815 | u32 | Unknown_32F | |
819 | u8 | Unknown_333 | A few semi-randomly have 96 (150) set, mostly containers but also set on a scroll? |
Player/Monster[edit]
Player and Monster type objects. These are largely the same but instances where they differ are noted.
Offset | DataType | Name | Description |
---|---|---|---|
0 | struct[65] | Header | Common record header structure
|
65 | char[32] | Name | |
97 | u32 | Strength | These are current values with temporary effects (spells, enchanted equipment, etc) applied |
101 | u32 | Intelligence | |
105 | u32 | Willpower | |
109 | u32 | Agility | |
113 | u32 | Endurance | |
117 | u32 | Personality | |
121 | u32 | Speed | |
125 | u32 | Luck | |
129 | u32 | Strength_Base | Base values are the original character values with no temporary effects |
133 | u32 | Intelligence_Base | |
137 | u32 | Willpower_Base | |
141 | u32 | Agility_Base | |
145 | u32 | Endurance_Base | |
149 | u32 | Personality_Base | |
153 | u32 | Speed_Base | |
157 | u32 | Luck_Base | |
161 | u16 | SpellPoints | |
163 | u16 | SpellPoints_Max | Max values should be self explanatory if you have any hope of parsing this mess |
165 | u16 | SpellPoints_Base | |
167 | s32 | Wounds | |
171 | s32 | Wounds_Max | |
175 | s32 | Wounds_Base | |
179 | u32 | Medical | |
183 | u32 | Medical_Count | Count values are just basic counters of how many times the skill has been used to determine when to level it up |
187 | u32 | Medical_Base | |
191 | u32 | Jumping | |
195 | u32 | Jumping_Count | |
199 | u32 | Jumping_Base | |
203 | u32 | Lockpicking | |
207 | u32 | Lockpicking_Count | |
211 | u32 | Lockpicking_Base | |
215 | u32 | Stealth | |
219 | u32 | Stealth_Count | |
223 | u32 | Stealth_Base | |
227 | u32 | Swimming | |
231 | u32 | Swimming_Count | |
235 | u32 | Swimming_Base | |
239 | u32 | Backstabbing | |
243 | u32 | Backstabbing_Count | |
247 | u32 | Backstabbing_Base | |
251 | u32 | Dodging | |
255 | u32 | Dodging_Count | |
259 | u32 | Dodging_Base | |
263 | u32 | Running | |
267 | u32 | Running_Count | |
271 | u32 | Running_Base | |
275 | u32 | Destruction | |
279 | u32 | Destruction_Count | |
283 | u32 | Destruction_Base | |
287 | u32 | Restoration | |
291 | u32 | Restoration_Count | |
295 | u32 | Restoration_Base | |
299 | u32 | Illusion | |
303 | u32 | Illusion_Count | |
307 | u32 | Illusion_Base | |
311 | u32 | Alteration | |
315 | u32 | Alteration_Count | |
319 | u32 | Alteration_Base | |
323 | u32 | Thaumaturgy | |
327 | u32 | Thaumaturgy_Count | |
331 | u32 | Thaumaturgy_Base | |
335 | u32 | Mysticism | |
339 | u32 | Mysticism_Count | |
343 | u32 | Mysticism_Base | |
347 | u32 | ShortBlade | |
351 | u32 | ShortBlade_Count | |
355 | u32 | ShortBlade_Base | |
359 | u32 | LongBlade | |
363 | u32 | LongBlade_Count | |
367 | u32 | LongBlade_Base | |
371 | u32 | HandToHand | |
375 | u32 | HandToHand_Count | |
379 | u32 | HandToHand_Base | |
383 | u32 | Axe | |
387 | u32 | Axe_Count | |
391 | u32 | Axe_Base | |
395 | u32 | BluntWeapon | |
399 | u32 | BluntWeapon_Count | |
403 | u32 | BluntWeapon_Base | |
407 | u32 | Missile | |
411 | u32 | Missile_Count | |
415 | u32 | Missile_Base | |
419 | u32 | CriticalStrike | |
423 | u32 | CriticalStrike_Count | |
427 | u32 | CriticalStrike_Base | |
431 | u32 | ShieldEffect | Shield spell magnitude |
435 | u32 | ActiveSpells | Bit array enumeration field using SpellArray
Not really applicable to player but allows for permanent spells effects on NPCs (they do work on player if hex edited in though) |
439 | u32 | Level_Enemy | |
443 | char[24] | ClassName | |
467 | u8 | Resistance | Bit array enumeration field using ElementArray
|
468 | u8 | Immunity | Bit array enumeration field using ElementArray
|
469 | bool | AcuteHearing | |
470 | bool | SpellAbsorption | |
471 | bool | RapidHealing | |
472 | bool | RegenerateHealth | |
473 | bool | RegenerateSPs | |
474 | bool | Athleticism | |
475 | u32 | IncreaseMagery | Calculated as Val / 256
Note: this is the only adv/dis that must have a value set - default 00010000 (1x) |
479 | bool | AdrenalineRush | |
480 | u8 | LowTolerance | Bit array enumeration field using ElementArray
|
481 | u8 | CriticalWeakness | Bit array enumeration field using ElementArray
|
482 | bool | NoRegenOfSpellpoints | |
483 | u8 | ForbiddenWeapons | Bit array enumeration field using WeaponArray
I'll note that forbidden use of long blades does not prevent you from using the Spear of Bitter Mercy/Broadsword of the Moon Reiver |
484 | u8 | ForbiddenArmor | Enumeration field using ArmorList
Somewhat misleading but leaving name to match adv/dis screen, this is actually the max level of armor you can use So a value of 3 (heavy) means you can use all armor types, a value of 2 (medium) means you can use light & medium I'll note that setting to "No armor allowed" does not prevent you from wearing the Savior's Hide armor |
485 | bool | ForbiddenShield | Unused (no shields in BS) but can be added by clicking empty space directly below the No regen. of Spellpoints checkbox - it actually costs you 300 points to add for some reason |
486 | u8 | ForbiddenMaterial | Enumeration field using MaterialList
Also misleading but leaving name to match adv/dis screen, this is actually the max level you can use So a value of 7 (ebony) means you can use everything up to and including ebony - orcish and daedric are what is actually forbidden |
487 | u8 | PrimarySkill1 | Enumeration fields using SkillList
|
488 | u8 | PrimarySkill2 | |
489 | u8 | PrimarySkill3 | |
490 | u8 | MajorSkill1 | |
491 | u8 | MajorSkill2 | |
492 | u8 | MajorSkill3 | |
493 | u8 | MinorSkill1 | |
494 | u8 | MinorSkill2 | |
495 | u8 | MinorSkill3 | |
496 | u8 | MinorSkill4 | |
497 | u8 | MinorSkill5 | |
498 | u8 | MinorSkill6 | |
499 | char[24] | ClassName_Base | Really not sure why they keep this specific base value |
523 | u8 | Resistance_Base | Bit array enumeration field using ElementArray
|
524 | u8 | Immunity_Base | Bit array enumeration field using ElementArray
|
525 | bool | AcuteHearing_Base | |
526 | bool | SpellAbsorption_Base | |
527 | bool | RapidHealing_Base | |
528 | bool | RegenerateHealth_Base | |
529 | bool | RegenerateSPs_Base | |
530 | bool | Athleticism_Base | |
531 | u32 | IncreaseMagery_Base | |
535 | bool | AdrenalineRush_Base | |
536 | u8 | LowTolerance_Base | Bit array enumeration field using ElementArray
|
537 | u8 | CriticalWeakness_Base | Bit array enumeration field using ElementArray
|
538 | bool | NoRegenOfSpellpoints_Base | |
539 | u8 | ForbiddenWeapons_Base | Bit array enumeration field using WeaponArray
I'll note that forbidden use of long blades does not prevent you from using the Spear of Bitter Mercy/Broadsword of the Moon Reiver |
540 | u8 | ForbiddenArmor_Base | Enumeration field using ArmorList
Somewhat misleading but leaving name to match adv/dis screen, this is actually the max level of armor you can use So a value of 3 (heavy) means you can use all armor types, a value of 2 (medium) means you can use light & medium I'll note that setting to "No armor allowed" does not prevent you from wearing the Savior's Hide armor |
541 | bool | ForbiddenShield_Base | Unused (no shields in BS) but can be added by clicking empty space directly below the No regen. of Spellpoints checkbox - it actually costs you 300 points to add for some reason |
542 | u8 | ForbiddenMaterial_Base | Enumeration field using MaterialList
Also misleading but leaving name to match adv/dis screen, this is actually the max level you can use So a value of 7 (ebony) means you can use everything up to and including ebony - orcish and daedric are what is actually forbidden |
543 | u8 | PrimarySkill1_Base | Enumeration fields using SkillList
|
544 | u8 | PrimarySkill2_Base | |
545 | u8 | PrimarySkill3_Base | |
546 | u8 | MajorSkill1_Base | |
547 | u8 | MajorSkill2_Base | |
548 | u8 | MajorSkill3_Base | |
549 | u8 | MinorSkill1_Base | |
550 | u8 | MinorSkill2_Base | |
551 | u8 | MinorSkill3_Base | |
552 | u8 | MinorSkill4_Base | |
553 | u8 | MinorSkill5_Base | |
554 | u8 | MinorSkill6_Base | |
555 | u32 | Unknown_22B | 00 until enter combat - unknown purpose |
559 | u32 | Unknown_22F | Initially set to FEFFFFFF (-2) for player, all 00s for NPCs - NPCs update while attacking - small values, only -2, 0, & 1 seen |
563 | u32 | CombatTimestamp | Pretty sure this a timestamp for when they started attacking/pursuing you |
567 | u32 | Unknown_237 | Not sure, seems like maybe a countdown or something - interest/chase timer? |
571 | u32 | Unknown_23B | |
575 | u8 | HotkeyF1 | Enumeration fields using SpellList if mapped to spell, when mapped to item it uses a pointer value starting at 64 through 71 to point to the item's RecordID starting at offset 808
|
576 | u8 | HotkeyF2 | |
577 | u8 | HotkeyF3 | |
578 | u8 | HotkeyF4 | |
579 | u8 | HotkeyF5 | |
580 | u8 | HotkeyF6 | |
581 | u8 | HotkeyF7 | |
582 | u8 | HotkeyF8 | |
583 | u32 | Unknown_247 | For player, appears to have something to do with jumping/falling/flying set to CCF9FFFF while jumping - destination/trajectory or speed?
For monsters, is populated on death - unknown what value maps to |
587 | u32 | AvailableSkillPoints | More like leftover, not available until next level up/transition |
591 | float | PlayerLastSeenX | Looks to be the location (from header) where an NPC last saw the character |
595 | float | PlayerLastSeenY | If you sneak away the value will remain until you're spotted again |
599 | float | PlayerLastSeenZ | |
603 | float | UnknownPosX1 | Unsure, only seen set on enemies and is generally close but not the player position, maybe a goto position |
607 | float | UnknownPosY | |
611 | float | UnknownPosX2 | No idea - where I've seen these 3 set, this has been the same value as X1 and not in an area where the coordinates would plausibly allow a coincidental match with the Z and X values |
615 | u32 | Flags | Enumeration field using CharacterFlagArray
Note: Not sure if this is full u32 or a u16 with another u16 or 2xu8s following - not seen the last 2 bytes with a value set |
619 | u32 | Target | Looks like a target enemy type - value of 08 - targets player - set to 00 when on PCTeam |
623 | u32 | Team | Normally 00, set to 01 or 02 when on PCTeam - Maybe other values exist for Red/Blue team in multiplayer or L4 with ice/fire daedra infighting? |
627 | u32 | Goal | Current goal or activity - 02/03/06/08/09/0D seen
Enumeration list (or possibly bitarray?) not created yet for these as I'm guessing on these values and behavior does not always seem to track but looks like:
|
631 | u32 | ConfigVolumeMusic | Music volume on player
Only seen set to 1 when Goal is 02 (goto (I think)) on monsters |
635 | u32 | Unknown_27B | Number values seen could be directional (direction of goal?) or maybe countdown to reevaluate goal like x237 (assuming that's what that is or BS even does that) |
639 | u8 | Hair | These 3 are player only - value maps to the number on the image file |
640 | u8 | Eyes | Number is 0 padded to 3 digits |
641 | u8 | Mouth | And combined with the file like: 'FBRMT' + RIGHT('000' + <Val>, 3) |
642 | u8 | Unknown_282 | |
643 | u32 | Unknown_283 | |
647 | u32 | Unknown_287 | |
651 | u32 | ConfigVolumeSound | Sound effect volume on player record |
655 | u32 | EnemyType | Enumeration field using EnemyList
|
659 | u32 | LastAttackTimestamp1 | Last attack timestamp |
663 | u32 | LastAttackTimestamp2 | Not sure exactly, usually the same timestamp as previous but sometimes a few milliseconds different (both +-) |
667 | u16 | EquippedWeaponItemID | Enumeration field using WeaponList
|
669 | u8 | Unknown_29D | |
670 | u8 | Race | Enumeration field using RaceList - Player only
|
671 | u8 | Unknown_29F | |
672 | u8 | Unknown_2A0 | Guessing last attack roll |
673 | u32 | EquippedWeaponRecordID | This is the RecordID from the item's header record |
677 | u32 | Unknown_2A5 | |
681 | u32 | AC_Helmet | For player this is the defense value of the equipped armor of that type |
685 | u32 | AC_Pauldron | For monsters, their defense value is applied to all types |
689 | u32 | AC_Cuirass | Meaning a Scamp will have 2 applied to Helmet/Pauldron/Cuirass/etc |
693 | u32 | AC_Greave | |
697 | u32 | AC_Gauntlet | |
701 | u32 | AC_Boot | |
705 | u32 | AC_Shield | Unused for player - this is set for monsters (no idea if it actually gets applied/considered in combat calculations) |
709 | u32 | Unknown_2C5 | |
713 | u32 | LastHitYaw | Looks to be the yaw angle they were hit from |
717 | u32 | Unknown_2CD | Since these 4 look to be last hit info, maybe the last hit's defense roll? |
721 | u32 | LastHitTimestamp1 | Timestamp of when last hit |
725 | u32 | LastHitTimestamp2 | Not sure exactly, usually the same timestamp as previous but sometimes a tiny bit later (usually 150milli though other small values seen) |
729 | u32 | Unknown_2D9 | |
733 | s16 | View_Pitch | Appears to be a signed version of the pitch angle in the header |
735 | u8 | Unknown_2DF | |
736 | u32 | Level_Player | Not sure layout, this could be u8 and with a trailing 32 but going with u32 since enemy level is |
740 | u8 | Unknown_2E1 | Don't know for certain if previous is 32 and this is 8 or vise versa or some combo of 16s and 8s |
741 | u32 | Unknown_2E5 | Seem to always be set to 96 (150) on monsters |
745 | u32 | Unknown_2E9 | Seem to always be set to 96 (150) on monsters |
749 | u32 | Unknown_2ED | Seem to always be set to 96 (150) on monsters |
753 | float | AnchorX | Teleport anchor position |
757 | float | AnchorY | All 00s if no anchor set |
761 | float | AnchorZ | Player only obviously |
765 | u32 | Unknown_2FD | |
769 | u32 | WaterBreathingExpireAt | Timestamp for when player runs out of breath
Water Breathing spell sets value at some point in future, otherwise set when going underwater based on swimming skill |
773 | s16 | Unknown_305 | Appears to be 11 s16s though is near always all FF (-1) for monsters or 00 for player |
775 | s16 | Unknown_307 | |
777 | s16 | Unknown_309 | |
779 | s16 | Unknown_30B | |
781 | s16 | Unknown_30D | |
783 | s16 | Unknown_30F | |
785 | s16 | Unknown_311 | |
787 | s16 | Unknown_313 | |
789 | s16 | Unknown_315 | |
791 | s16 | Unknown_317 | |
793 | s16 | Unknown_319 | |
795 | u32 | Unknown_31B | |
799 | u8 | Unknown_31F | Set to 1 when dead (Monsters) |
800 | u8 | Unknown_320 | Set to FF on player when first enters combat |
801 | u8 | ConfigTurnRate | Turn speed set in controls |
802 | u8 | Unknown_322 | |
803 | u32 | SAVEVARID | Record ordinal in SAVEVARS StaticEnemy block
Not sure on datatype, target block only allows 128 records so could be as small as a s8 |
807 | u8 | Unknown_327 | |
808 | u32 | HotkeyF1RecordID | 64 - RecordID of item when mapped to hotkey |
812 | u32 | HotkeyF2RecordID | 65 - RecordID of item when mapped to hotkey |
816 | u32 | HotkeyF3RecordID | 66 - RecordID of item when mapped to hotkey |
820 | u32 | HotkeyF4RecordID | 67 - RecordID of item when mapped to hotkey |
824 | u32 | HotkeyF5RecordID | 68 - RecordID of item when mapped to hotkey |
828 | u32 | HotkeyF6RecordID | 69 - RecordID of item when mapped to hotkey |
832 | u32 | HotkeyF7RecordID | 70 - RecordID of item when mapped to hotkey |
836 | u32 | HotkeyF8RecordID | 71 - RecordID of item when mapped to hotkey |
840 | u32 | Unknown_34B | |
844 | u32 | ConfusionExpireAt | Timestamp for the confusion effect to expire |
848 | u32 | Unknown_353 | |
852 | u32 | Unknown_357 |
Object[edit]
Non-item 3D objects. This type is not very well understood.
Offset | DataType | Name | Description |
---|---|---|---|
0 | struct[65] | Header | Common record header structure
|
65 | u32 | BaseTypeID | Unique identifier for each item/object type (i.e. all daggers will have the same value, regardless of anything else, material, enchantments, etc) |
69 | u32 | Unknown_49 | These are near always all 00 |
73 | u32 | Unknown_4D | When embedded in Item record, these values are populated once picked up
|
77 | u32 | Unknown_51 | So assuming some sort of record link |
81 | u32 | Unknown_55 | |
85 | u32 | Unknown_59 | |
89 | float | UNK_X | I'm not clear what these 3 are used for |
93 | float | UNK_Y | They are definitely position related and sometimes close to object's position |
97 | float | UNK_Z | Though often completely different |
101 | float | ObjectX | Matches with header |
105 | float | ObjectY | Unclear why it is duplicated |
109 | float | ObjectZ | Maybe base/start position? |
113 | u32 | RotatePitch | Matches with header |
117 | u32 | RotateYaw | Unclear why it is duplicated and 32 bit value instead of 16 |
121 | u32 | RotateRoll | Maybe base/start angle? |
125 | u16 | Unknown_81 | |
127 | u32 | Unknown_83 | I'm really not clear what these values are and just using u32s as a default as they definitely are in blocks of 4 or a bunch of blocks with pairs of 16s |
131 | u32 | Unknown_87 | Suspect they may be scaling values |
135 | u32 | Unknown_8B | But could be anything really |
139 | u32 | Unknown_8F | What I know about 3D models could fill a thimble halfway |
143 | u32 | Unknown_93 | Making this section mostly guesses to begin with |
147 | u32 | Unknown_97 | Probably just need to stand in front of one and then start messing with the values and see what happens |
151 | u32 | Unknown_9B | |
155 | u32 | Unknown_9F | |
159 | u32 | Unknown_A3 | |
163 | u32 | Unknown_A7 | |
167 | u32 | Unknown_AB | |
171 | u32 | Unknown_AF | |
175 | u8 | Unknown_B3 |
Projectile[edit]
Short lived objects that exist for as long as the projectile is in motion/exists.
This type is only 1 byte long and every instance seen is always 0x96 (150). It is always linked to the cast spell in the header so my assumption is that this is a shell record with the real data being the positioning data in the header.
Spell[edit]
Primarily spells known by the player but a few spells, like Delayed Damage, will create a record where cast to function as the anchor/mine that is removed once triggered.
Offset | DataType | Name | Description |
---|---|---|---|
0 | struct[65] | Header | Common record header structure
|
65 | char[32] | Name | |
97 | u8 | SpellID | Enumeration field using SpellList
|
98 | u8 | TargetType | Enumeration field using SpellTargetList
|
99 | u8 | Icon | Number of the SYMB spell icon to use - Unused spells are out of range - Valid values are 00-1A |
100 | u32 | DurationBase | 1 = 5000 milliseconds |
104 | u32 | DurationBonus | |
108 | u32 | DurationBonusLevel | Caster's level is divided by this value then multiplied by the bonus value
Always either 1 (bonus applied every level) or 2 (bonus applies every other level) |
112 | u32 | MagnitudeBaseMin | |
116 | u32 | MagnitudeBaseMax | |
120 | u32 | MagnitudeBonusMin | |
124 | u32 | MagnitudeBonusMax | |
128 | u32 | MagnitudeBonusLevel | Caster's level is divided by this value then multiplied by the bonus value; however, all applicable spells have a value of 1 so not really used |
132 | u32 | LastCastDuration | Not sure why it bothers storing these two, duration is reusable I guess |
136 | u32 | LastCastMagnitude | |
140 | u16 | Icon_Base | Default/original icon for the spell (from EXE table) - functions same as Icon above - u16 for some reason? |
142 | u8 | Element | Enumeration field using ElementSpellList
|
143 | u8 | Delivery | Enumeration field using SpellDeliveryList
|
144 | u32 | LastCastTarget | RecordID of the last target - Self targetted spells will be 50C3 (player RecordID)
Appears to be 1000F0F8 if never cast or cast at range (maybe just if you missed in that case) Projectile records reference the caster |
148 | float | HeadingX | Projectile spell record heading in radians |
152 | float | HeadingY | Projectile spell record heading in radians |
156 | float | HeadingZ | Projectile spell record heading in radians |
160 | u32 | SPCost_Base | |
164 | u32 | SPCost_Current | Calculated cost based on relevant skill and selected delivery type |
168 | u32 | School | Enumeration field using SpellSchoolList
|
172 | u32 | DetonationType | Enumeration field using SpellDetonationList
Note: Manual is incorrect, this does not affect the casting cost |
176 | u32 | Unknown_0B0 | |
180 | u32 | ProjectileSpeed | Guessing here but likely the speed the projectile is traveling on its heading from origin |
Options[edit]
Likely a legacy data type left over from Daggerfall as only the fullscreen option is set here.
Offset | DataType | Name | Description |
---|---|---|---|
0 | struct[65] | Header | Common record header structure
|
65 | bool | IsFullscreen | This is the toggle for showing the bottom UI elements with character portrait or just the compass and health/spell point bars |
66 | u8 | Unknown_042 | Not sure how much this is really used as the only value I can see changed |
67 | u8 | Unknown_043 | When messing with all the config values available |
68 | u8 | Unknown_044 | Is the first byte when toggling between fullscreen and standard |
69 | u8 | Unknown_045 | May be legacy type leftover from Daggerfall |
Automap[edit]
Large flag field that indicates what areas on the map have been discovered and should be displayed in the automap. Of note, the grid size is defined in the header using the ViewPitch and ViewYaw values.
Offset | DataType | Name | Description |
---|---|---|---|
0 | struct[65] | Header | Common record header structure
|
65 | bool | Tile_00x00 | Each byte is 16x16 square on automap starting at top left and going across in rows until the bottom right that is flagged true once visited
Updated while walking - immediately opening map on new game will be empty |
… | bool | Tile_XXxYY | Not going to bother listing all of these |
1264 | bool | Tile_39x29 | Note: 16x16 grid size is only size seen but not all maps checked
So possible some of the small interior maps (mostly in L5) use different values |
1265 | u32 | Unknown_4F1 | Always seen empty (00000000) |
1269 | u8 | Unknown_4F5 | Always 96 (150) or 0 - unknown purpose |
Effect[edit]
Most spell effects that have a duration, excluding Monster Summoning and Water Breathing, will have an effect record that details the effect, start/end time, etc.
Offset | DataType | Name | Description |
---|---|---|---|
0 | struct[65] | Header | Common record header structure
|
65 | char[32] | Name | This is the spell's name |
97 | u16 | Unknown_061 | |
99 | s16 | StrengthModifier | Assume Strength spell will set this |
101 | padding[10] | All attributes/skills are broken into 12 byte blocks with 8 or 10 bytes of padding depending on the datatype (s16/s32) with the exception of Wounds which is a 10 byte block | |
111 | s16 | IntelligenceModifier | Probably trying to mimic the current/count/base layout used for skills in player records so assumed never used |
113 | padding[10] | Only Speed seen modified with the assumption Strength would be updated in multiplayer mode with Strength spell | |
123 | s16 | WillpowerModifier | |
125 | padding[10] | ||
135 | s16 | AgilityModifier | |
137 | padding[10] | ||
147 | s16 | EnduranceModifier | |
149 | padding[10] | ||
159 | s16 | PersonalityModifier | |
161 | padding[10] | ||
171 | s16 | SpeedModifier | Set by Haste/Slow |
173 | padding[10] | ||
183 | s16 | LuckModifier | |
185 | padding[10] | ||
195 | s16 | SpellPointModifiier | |
197 | padding[10] | ||
207 | s16 | WoundsModifier | |
209 | padding[8] | ||
217 | s32 | MedicalModifier | |
221 | padding[8] | ||
229 | s32 | JumpingModifier | |
233 | padding[8] | ||
241 | s32 | LockpickingModifier | |
245 | padding[8] | ||
253 | s32 | StealthModifier | |
257 | padding[8] | ||
265 | s32 | SwimmingModifier | |
269 | padding[8] | ||
277 | s32 | BackstabbingModifier | |
281 | padding[8] | ||
289 | s32 | DodgingModifier | |
293 | padding[8] | ||
301 | s32 | RunningModifier | |
305 | padding[8] | ||
313 | s32 | DestructionModifier | |
317 | padding[8] | ||
325 | s32 | RestorationModifier | |
329 | padding[8] | ||
337 | s32 | IllusionModifier | |
341 | padding[8] | ||
349 | s32 | AlterationModifier | |
353 | padding[8] | ||
361 | s32 | ThaumaturgyModifier | |
365 | padding[8] | ||
373 | s32 | MysticismModifier | |
377 | padding[8] | ||
385 | s32 | ShortBladeModifier | |
389 | padding[8] | ||
397 | s32 | LongBladeModifier | |
401 | padding[8] | ||
409 | s32 | HandToHandModifier | |
413 | padding[8] | ||
421 | s32 | AxeModifier | |
425 | padding[8] | ||
433 | s32 | BluntWeaponModifier | |
437 | padding[8] | ||
445 | s32 | MissileModifier | |
449 | padding[8] | ||
457 | s32 | CriticalStrikeModifier | |
461 | padding[8] | ||
469 | u32 | Unknown_1D5 | Appears to only be set on damage type spells/effects (Poison/ContinuousDamage) but only seen it set to FFFFFFFF (-1) |
473 | u32 | StartTime | Timestamp value for when the spell was cast
Appears to only be set on damage type spells/effects (Poison/ContinuousDamage) |
477 | u32 | ApplyInterval | Guessing - always seen as E803 (1000 or 1 second) for Poison/ContinousDamage |
481 | u32 | SpellIcon | +1 - Probably done so can be 0 if it shouldn't show icon (effect applied to enemy, etc) |
485 | u32 | ExpireAt | Timestamp value for when the effect ends |
489 | u32 | ActiveSpell | Bit array enumeration field using SpellArray
|
493 | u32 | Unknown_1ED | |
497 | u32 | Unknown_1F1 | |
501 | u32 | SpellResistanceEffect | Magnitude x10 |
505 | u32 | SpellAbsorptionEffect | Magnitude x10 |
509 | u32 | SpellReflectEffect | Magnitude x10 |
513 | u8 | Unknown_201 | Always seen set to 96 (150) on all effects except Etherealness, Haste, Jumping, & SlowFall which are 00 |
Spells with effects:
- Continuous Damage
- Detect Enemy
- Detect Invisibility
- Etherealness
- Fire Shield
- Haste
- Invisibility
- Jumping
- Poison
- Resistance
- Slow
- Slow Fall
- Spell Absorption
- Spell Reflection
- Spell Resistance
Note: Confusion & Shield do not use an effect record and have specific values on the character record
SAVEVARS.DAT[edit]
The SAVEVARS.DAT file primarily contains variable values and additional monster/NPC data. It is a 34,805 byte file made up of 11 (possibly 12) fixed length blocks of data. At the end of most blocks there is a value that matches the record count on L1 but is unreliable as it's been seen to not always update correctly and is recommended to just read until an empty record is found for most block types.
VARS Block Types[edit]
Name | StartOffset | EndOffset | BlockSize | MaxRecords | RecordLength | Description |
---|---|---|---|---|---|---|
Player | 0 | 1050 | 1052 | 1 | 787 | Copy of 03 SAVETREE player record without the header - unknown usage
As it is identical, not included, can reference |
Miscellaneous |
1051 | 1074 | 24 | 6 | 4 | Contains some miscellaneous values |
LogText |
1075 | 2354 | 1280 | Variable | NULL terminated | Contains a history of on-screen messages |
LogTimestamp |
2355 | 4491 | 2137 | 534 | 4 | Timestamps for the logged messaged in the previous block |
ConversationMap |
4492 | 4659 | 1024 | 128 | 8 | Maps SAVETREE RecordIDs of NPCs to the conversation file specified in the BS6 |
StaticEnemy |
5520 | 8655 | 7168 | 128 | 56 | Contains all defined NPC/Enemy 106 records defined in the level's BS6 |
HP/SPModify |
12692 | 12754 | 1052 | 128 | 9 | Contains the modify values for HP/SP to apply on use/touch for objects like gems |
Block5 | 13848 | 14359 | 512 | ? | ? | No idea if this is really a block or not as I haven't seen it populated (all 00s)
But it's fairly large and easily divided into 64x8 byte records, 128x4 byte, etc, so listed here but (obviously) not documented |
Sigil |
14364 | 14399 | 768 | 64 | 12 | Contains all sigils of warding in the level |
GlobalVariable |
15237 | 25988 | 10752 | 1344 | 8 | All currently set global variable values |
LocalVariable |
25989 | 34692 | 8704 | 128 | 68 | Contains a record for NPC local variables that are created on first conversation |
MonsterTypeCount |
34693 | 34708 | 16 | 16 | 1 | This a separate single byte counter for each enemy type (index = MonsterID) that has a local variable record defined. |
Miscellaneous[edit]
This is broken into 6x 4 byte records.
Ordinal | DataType | Name | Description |
---|---|---|---|
0 | u32 | CurrentLevel | The current map level, not character level |
1 | u32 | CurrentTimestamp | Timestamp value |
2 | u32 | Unknown_08 | Never seen populated |
3 | u32 | Unknown_0C | Never seen populated |
4 | u32 | Unknown_10 | Small single digit values seen when populated - Unknown purpose |
5 | u32 | Unknown_14 | Small single digit values seen when populated - Unknown purpose |
LogText/LogTimestamp[edit]
The LogText block contains the text from (most?) on screen messages (the text boxs that displays at top of screen). These are variable length records that are NULL (00) terminated that, oddly, are missing the first character of the message string. The LogTimestamp records are 4 byte timestamp values that are paired with the LogText record by index (i.e. the timestamp for the 2nd LogText record will be the value of the 2nd LogTimestamp record).
Note: Gaps will occur in the LogText block with a cooresponding gap in the LogTimestamp block. Since LogText is variable length, a blank space of 3x records (i.e. <EndOfPreviousRecord>00000000<StartOfNewRecord> will have a 12 byte chunk of 00s in the LogTimestamp block to go with each empty record.
ConversationMap[edit]
This is a simple mapping of a specific NPC or monster to a conversation script file. All NPCs in the level will have a record and any monster type with a unique script will also be listed (i.e. Methats in L1). Any monster without a mapping specified here (which is taken from the 108 record in the level's BS6 file) will use the default value found in the hardcoded table in the executable.
Offset | DataType | Name | Description |
---|---|---|---|
0 | u32 | RecordID | RecordID in SAVTREE |
4 | char[4] | ConvFile | First 3 characters of the assigned conversation file base name
Meaning it excludes the B/M/F/T type character at the end (and extension) |
StaticEnemy[edit]
This block contains a copy of the non-random monsters defined in the level's BS6 file. The values in here override the standard values defined in the monster table from the EXE.
Offset | DataType | Name | Description |
---|---|---|---|
0 | u32 | RecordID | RecordID in SAVTREE |
4 | s32 | EnemyID | Need to subtract 1 to match to EnemyList
This is due to the EnemyList value in the BS6 file using 0 to indicate a random enemy Note: Random enemies do not have a record here |
8 | s32 | Speed | |
12 | s32 | Strength | |
16 | s32 | SP | |
20 | s32 | HP | |
24 | s32 | Skill | |
28 | s32 | NPC attitude/goal | When set this is near always set to 0D (13)
Think this sets them to stand still and maybe to initiate conversation once you're range |
32 | u32 | Active/Innate spell array | Bit array enumeration field using SpellArray
|
36 | s32 | SpellID1 | Enumeration field using SpellList
|
40 | s32 | SpellID2 | Assum this replaces standard spell list from EXE table though only used for one monster that already has spells |
44 | s32 | SpellID3 | |
48 | s32 | SpellID4 | These two are never populated but assume that is the purpose |
52 | s32 | SpellID5 |
HP/SPModify[edit]
This block holds the HP or SP modify values to apply when damaging or healing objects are touched or used.
Offset | DataType | Name | Description |
---|---|---|---|
0 | u32 | RecordID | RecordID in SAVTREE |
4 | s32 | ModifyValue | Amount to add/subtract from HP/SP |
8 | u32 | IsSP | Boolean flag (despite using 4 bytes) to indicate if value applied to SP |
Sigil[edit]
This block contains a record for each sigil barrier in the current level.
Offset | DataType | Name | Description |
---|---|---|---|
0 | u32 | RecordID | RecordID in SAVTREE |
4 | s32 | YPos | The sigils Y (vertical, not north/south) position
Unclear why this is a s32 instead of a float |
8 | u32 | Unknown_08 | All 00s in test files |
GlobalVariable[edit]
This block contains all currently set global variable values. All variables from the EXE inventory table are initialized/set by default as well as PCFemale/PCMale (appropriate one is set true) & SkelServ (false). Additional variables are added to table when set, assumed treated as false when checked if not specified.
Occasionally a conversation branch identifier (i.e. DN1A01) will have a record set here as a variable, unclear why this happens or why in this block instead of the LocalVariable
record for the monster/NPC.
Offset | DataType | Name | Description |
---|---|---|---|
0 | u32 | VarHash | This a 4-byte hash of the variable name using some baffling method I cannot believe I figured out.
Since this (and every other block) in this file is fixed length (excluding logs), assumed this was done to allow small, fixed length records here without requiring a large amount of padding to accommodate variable length names that range from 3-14 characters long. Known variable hashes are enumerated in |
4 | u32 | VarValue | The variable's value - likely just a boolean as 0/1 are only observed values but is 4 bytes long so possible other numeric values accepted/used |
LocalVariable[edit]
This block contains conversation variables for a specific monster/NPC. These are initialized in the B/F/M conversation files, set in the T file, then checked at the start of subsequent conversations to control the conversation starting point/options.
This block differs in that fills in records from the bottom up so to read this section you begin at the beginning of the MonsterTypeCount
section and skip back 68 bytes (this sections record length). Unfortunately, you cannot reliably tell how many records actually are in use without checking all 128 records as NPCs are not included in MonsterTypeCount
and dead monster records are left but all values (including RecordID) are set to 00 meaning an empty record may just indicate a monster that has been spoken to then killed.
Offset | DataType | Name | Description |
---|---|---|---|
0 | u32 | RecordID | RecordID in SAVTREE
Note: NPC's do not have a record in SAVETREE, this maps to their ID from the level's BS6 file |
4 | u32 | VarHash0 | Same baffling 4-byte hash that is used in global variables and enumerated in VariableList
|
8 | u32 | VarValue0 | All values are the same as the global variables and is likely just a boolean value |
12 | u32 | VarHash1 | Variables are filled in from the beginning of the record with unused variables left blank |
16 | u32 | VarValue1 | |
20 | u32 | VarHash2 | |
24 | u32 | VarValue2 | |
28 | u32 | VarHash3 | |
32 | u32 | VarValue3 | |
36 | u32 | VarHash4 | |
40 | u32 | VarValue4 | |
44 | u32 | VarHash5 | |
48 | u32 | VarValue5 | |
52 | u32 | VarHash6 | |
56 | u32 | VarValue6 | |
60 | u32 | VarHash7 | No conversations have 8 variables, so this is always unused |
64 | u32 | VarValue7 |
MonsterTypeCount[edit]
This is a 16 byte array with each byte being a count of the number of monsters of that type that have a LocalVariable
record. The records are mapped to the EnemyList (TBA) enumeration type by their position in the array (i.e. byte 0 (1st) is for 0/Scamp, byte 2 (3rd) to 2/Dremora, etc).
This, unfortunately, cannot be used to tell the number of LocalVariable
records as NPC records do not have a count value here.
Ordinal | DataType | Name | Description |
---|---|---|---|
0 | u8 | SK_Count | Simple count of the number of LocalVariable records for this enemy type |
1 | u8 | VM_Count | |
2 | u8 | DR_Count | |
3 | u8 | SD_Count | |
4 | u8 | SN_Count | |
5 | u8 | GH_Count | |
6 | u8 | WR_Count | |
7 | u8 | MD_Count | |
8 | u8 | FR_Count | |
9 | u8 | FT_Count | |
10 | u8 | MA_Count | |
11 | u8 | CF_Count | |
12 | u8 | SR_Count | |
13 | u8 | DS_Count | |
14 | u8 | ML_Count | |
15 | u8 | DL_Count |
Enumerations[edit]
Lookup/mapping lists used by many of the records values. This is split into it's own section instead of embedded into records as they are all typically used in multiple places.
Arrays[edit]
These are bit array fields allowing for multiple properties/flags/values/etc to be assigned in a single byte. This works by assigning a value/meaning to each bit in the byte and then, essentially, treating each bit as a boolean on/off flag (more complicated uses do exist but not here).
Note: When working with bytes/bits, they are 0 based, meaning that the first bit is bit 0 and the last bit in a byte is 7. Do not confuse a value of 00 in a record as meaning the first bit value is set (i.e. ForbiddenWeapon set to 00 in Player record means nothing is set, not that Short Blade is forbidden).
CharacterFlagArray[edit]
Various player/monster state flags. Most not seen used and it's unclear if this is actually 32-bits or only 16.
Bit | Name | Comments |
---|---|---|
0 | Unknown_00 | |
1 | Unknown_01 | |
2 | Detected | This seems kinda dodgy |
3 | IsFemale1 | |
4 | Unknown_04 | |
5 | Unknown_05 | |
6 | Sneaking | |
7 | CursorMode | Toggle between View/Cursor Movement mode from Controls |
8 | Unknown_08 | |
9 | Unknown_09 | |
10 | LanternOn | |
11 | IsFemale2 | Unsure why this is flagged twice? |
12 | Unknown_12 | |
13 | Unknown_13 | |
14 | Unknown_14 | |
15 | Unknown_15 | |
16 | Unknown_16 | |
17 | Unknown_17 | |
18 | Unknown_18 | |
19 | Unknown_19 | |
20 | Unknown_20 | |
21 | Unknown_21 | |
22 | Unknown_22 | |
23 | Unknown_23 | |
24 | Unknown_24 | |
25 | Unknown_25 | |
26 | Unknown_26 | |
27 | Unknown_27 | |
28 | Unknown_28 | |
29 | Unknown_29 | |
30 | Unknown_30 | |
31 | Unknown_31 |
ElementArray[edit]
Used to flag the elements set in advantages/disadvantages.
Bit | Name | Comments |
---|---|---|
0 | Magic | Magicka in SpellMaker |
1 | Fire | |
2 | Cold | Ice in SpellMaker |
3 | Shock | Electricity in SpellMaker |
4 | Poison |
SpellArray[edit]
Used to flag spell effects. When set on monster records, these are permanent always on/innate abilities/effects (i.e. Spell Resistance on Seducers).
Note: While all spells have a bit value assigned, this does nothing for most and is only relevant to spells that have an Effect
record.
Bit | Name | Comments |
---|---|---|
0 | Unused | |
1 | Monster Summoning | |
2 | Detect Spell | |
3 | Detect Enemy | |
4 | Detect Invisibility | |
5 | Invisibility | |
6 | Shadow | Removed |
7 | Chameleon | Removed - effect is set on Vermai though |
8 | Slow Fall | |
9 | Continuous Damage | |
10 | Poison | |
11 | Confusion | |
12 | Vampiric Drain | |
13 | Delayed Damage | |
14 | Dispel Magic | |
15 | Spell Reflection | |
16 | Spell Resistance | |
17 | Spell Absorption | |
18 | Cause Damage | |
19 | Fire Shield | |
20 | Cure Poison | |
21 | Cure Health | |
22 | Jumping | |
23 | Running | Removed |
24 | Etherealness | |
25 | Teleport | |
26 | Shield | |
27 | Resistance | |
28 | Slow | |
29 | Haste | |
30 | Strength | Multiplayer only (I think?) |
31 | Dispel Sigil | Multiplayer only |
WeaponArray[edit]
Used to flag forbidden weapons set in advantages/disadvantages.
Bit | Name | Comments |
---|---|---|
0 | Short Blade | |
1 | Long Blade | This does not prevent equipping/using the Spear of Bitter Mercy or Broadsword of the Moon Reiver |
2 | Blunt Weapon | |
3 | Axe | |
4 | Missile |
Lists[edit]
These are standard single value lookup lists. A signed value of FF (-1) is typically used to indicate the value is not set as 0 is always used for these (excluding VariableList).
ArmorList[edit]
Maps to the Forbidden Armor values.
Note: Somewhat confusingly named field as the value is the max you can use, not what you're actually forbidden from using (i.e. Forbidden Armor: Medium Armor means you can't use armor greater than medium (heavy)).
ID | Name | Comments |
---|---|---|
0 | No armor allowed | This does not prevent you from equipping the Savior's Hide armor |
1 | Light | |
2 | Medium | |
3 | Heavy |
ElementEnchantmentList[edit]
Name really not visible for these but, since spell related, matching them to SpellMaker naming convention instead of the advantage/disadvantage array names.
ID | Name | Comments |
---|---|---|
0 | None | |
1 | Fire | |
2 | Ice | Cold in advantages/disadvantages |
3 | Poison | |
4 | Electricity | Shock in advantages/disadvantages |
5 | Magicka | Magic in advantages/disadvantages |
ElementSpellList[edit]
ID | Name | Comments
This ultimately doesn't necessarily affect a lot of the spells though it does change the casting animation. |
---|---|---|
0 | Fire | |
1 | Ice | Cold in advantages/disadvantages |
2 | Poison | |
3 | Electricity | Shock in advantages/disadvantages |
4 | Magicka | Magic in advantages/disadvantages |
EnemyList[edit]
When referencing from BS6, need to subtract 1 as 0 in that file means random enemy.
Abbreviation used in a number of locations, including BSI and conversation file names included in comments.
ID | Name | Comments |
---|---|---|
0 | Scamp | SK |
1 | Vermai | VM |
2 | Dremora | DR |
3 | Spider Daedra | SD |
4 | Skeleton | SN |
5 | Ghost | GH |
6 | Wraith | WR |
7 | Morphoid Daedra | MD |
8 | Fire Daedra | FR |
9 | Frost Daedra | FT |
10 | Herne | MA |
11 | Clannfear | CF |
12 | Seducer | SR |
13 | Dark Seducer | DS |
14 | Daedra Count | ML |
15 | Daedra Lord | DL |
ItemList[edit]
All base items in the game.
ID | Name | Comments |
---|---|---|
0 | Dagger | |
1 | Short Sword | |
2 | Long Sword | |
3 | Broad Sword | |
4 | Claymore | |
5 | Battle Axe | |
6 | War Axe | |
7 | Mace | |
8 | Short Bow | |
9 | Long Bow | |
10 | Crossbow | |
11 | Javelin | |
12 | Sling | Unused - this spot will have a random weapon in the CharacterMaker |
13 | Staff | |
14 | Spear | |
15 | Potion | |
16 | Sack | |
17 | Large Chest | |
18 | Small Chest | |
19 | Clothes | |
20 | Gem | |
21 | Scroll | |
22 | Arrow | |
23 | Lantern | |
24 | Helmet | |
25 | Cuirass | |
26 | Pauldrons | |
27 | Greaves | |
28 | Boots | |
29 | Gauntlets | |
30 | Voidguide | |
31 | Sigil Amulet | |
32 | Book | |
33 | Gold Pieces | Unused - I suspect one of the unknown values on Player/Monster is a carried gold value because of this
|
34 | Key | Unused |
35 | Gatekey | Used in L6 |
36 | Cog | |
37 | Rod | |
38 | Gatekey | Used in L5 |
39 | Parchment | |
40 | Spear Case | |
41 | Gatekey | Unused |
42 | Coffer of Restoration |
MaterialList[edit]
Armor/Weapon material types. When used for Forbidden Material values this functions the same as Forbidden Armor where the "forbidden" value is actually the max material type allowed.
ID | Name | Comments |
---|---|---|
0 | Iron | |
1 | Steel | |
2 | Silver | |
3 | Elven | |
4 | Dwarven | |
5 | Mithril | |
6 | Adamantium | |
7 | Ebony | |
8 | Orcish | Still don't get why Orc stuff is supposed to be so good, I'd always heard it's not easy being green… |
9 | Daedric |
RaceList[edit]
Species the player's race in the Player
record.
ID | Name | Comments |
---|---|---|
0 | Redguard | |
1 | Breton | |
2 | Nord | |
3 | High Elf | |
4 | Dark Elf | |
5 | Wood Elf |
SkillList[edit]
Player/Monster skills with attribute from EXE table included in comments.
ID | Name | Comments |
---|---|---|
0 | Medical | Strength (Removed) |
1 | Jumping | Speed |
2 | Lockpicking | Agility (Removed) |
3 | Stealth | Agility |
4 | Swimming | Endurance |
5 | Backstabbing | Agility |
6 | Dodging | Speed |
7 | Running | Speed (Removed) |
8 | Destruction | Willpower |
9 | Restoration | Personality |
10 | Illusion | Personality |
11 | Alteration | Willpower |
12 | Thaumaturgy | Willpower |
13 | Mysticism | Personality |
14 | Short Blade | Agility |
15 | Long Blade | Strength |
16 | Hand to Hand | Strength |
17 | Axe | Strength |
18 | Blunt Weapon | Strength |
19 | Missile | Agility |
20 | Critical Strike | Intelligence |
SpellDeliveryList[edit]
Spell delivery options from the SpellMaker
ID | Name | Comments |
---|---|---|
0 | Caster only | |
1 | Touch delivery | |
2 | Single creature at range | |
3 | Area around caster | |
4 | Area at range |
SpellDetonationList[edit]
Spell detonation type from the SpellMaker
Note: This does not affect the casting cost of the spell
ID | Name | Comments |
---|---|---|
0 | Any | |
1 | Organic | |
2 | Organic Drop |
SpellList[edit]
All basic spells in the game.
Note: Restore Spell Points & Water Breathing are technically not spells but this is value used by potions/enchanted items for setting those effects.
ID | Name | Comments |
---|---|---|
0 | Monster Summoning | |
1 | Detect Spell | |
2 | Detect Enemy | |
3 | Detect Invisibility | |
4 | Invisibility | |
5 | Shadow | Removed |
6 | Chameleon | Removed |
7 | Slow Fall | |
8 | Continuous Damage | |
9 | Poison | |
10 | Confusion | |
11 | Vampiric Drain | |
12 | Delayed Damage | |
13 | Dispel Magic | |
14 | Spell Reflection | |
15 | Spell Resistance | |
16 | Spell Absorption | |
17 | Cause Damage | |
18 | Fire Shield | |
19 | Cure Poison | |
20 | Cure Health | |
21 | Jumping | |
22 | Running | Removed |
23 | Etherealness | |
24 | Teleport | |
25 | Shield | |
26 | Resistance | |
27 | Slow | No potions |
28 | Haste | No potions |
29 | Strength | No potions - Multiplayer only (I think?) |
30 | Dispel Sigil | No potions - Multiplayer only |
31-37 | Unused | |
38 | Water Breathing | Enchanted item/potion only |
39 | Restore Spell Points | Enchanted item/potion only |
SpellSchoolList[edit]
Separate lookup list used only by spells to map to their skill.
ID | Name | Comments |
---|---|---|
0 | Alteration | |
1 | Restoration | |
2 | Destruction | |
3 | Mysticism | |
4 | Thaumaturgy | |
5 | Illusion |
SpellTargetList[edit]
Controls available delivery types
allowed for spells.
ID | Name | Comments |
---|---|---|
0 | Self | Caster only - cannot change delivery type |
1 | Other | All types except Caster only available |
2 | Either | All types allowed |
VariableList[edit]
Not really an enumeration type but listing all known local/global variables with their hash value due to it being impossible to reverse the hash to identify which variable it is for. Variables are not case sensitive as they are converted to uppercase when hashed.
Note: Some conversations will set a conversation branch identifier as a global variable for unknown reasons. These are not listed as it is not known what all would be set and just listing all of them would cause this list to be over ~2.5k records long with a lot of collisions (duplicates) as the hashing method used is not very smart.
Hash | Name | Comments |
---|---|---|
18276 | Cat | |
18389 | Bye | |
18743 | Dog | |
20177 | Iya | Set to false by default from EXE inventory table |
292469 | Case | Set to false by default from EXE inventory table |
293507 | Cess | Set to false by default from EXE inventory table |
313967 | Hero | |
327059 | Kids | |
4616770 | Armor | Set to false by default from EXE inventory table |
4654613 | Blame | |
4667012 | Boast | |
4692121 | Buddy | |
5533085 | Payem | Set to false by default from EXE inventory table |
5785954 | Spear | |
5788734 | Spoon | |
5795229 | Tayem | Set to false by default from EXE inventory table |
75873186 | Dagger | Set to false by default from EXE inventory table |
78045524 | FayMad | |
78149207 | FDBrag | |
79066711 | FrBrag | |
79307092 | GemMad | |
83759266 | Killer | |
88610309 | PCMale | Set by default based on character's gender |
90827426 | Reiver | Set to false by default from EXE inventory table |
92707077 | Tattle | |
95839941 | WarAxe | Set to false by default from EXE inventory table |
97431892 | XivMad | |
294957597 | CallToView | |
365125991 | ImagoAlly | |
369456781 | Malacath | |
430335651 | SumeerAlly | |
430386079 | SumeerName | |
430393896 | SumeerOpen | |
511167899 | Mischief | Set true on read of BK2_007 (Lives of the Heroes) |
610655631 | DremoraDone | |
610694879 | DremoraNice | |
611635545 | MorphMad | |
634955582 | ZenaideMad | |
634957737 | ZenaideTwo | |
709091800 | Neonymic | |
727212442 | AngadaMad | |
727213978 | AngadaSad | |
778744043 | DeyaniraName | |
881226311 | NotArmor | Set to true by default from EXE inventory table |
949645999 | Nocturnal | |
1032625632 | Voidguide | |
1127534183 | DagonNoTalk | |
1181540349 | DremoraSpeak | |
1184929603 | Pauldron | Set to false by default from EXE inventory table |
1202329098 | PCFemale | Set by default based on character's gender |
1211909557 | CogPage | Set true on read of BK1_996 (Clarentavious' Letter) |
1214710100 | DarkMad | |
1214945907 | PCReturn | |
1231678197 | NotReiver | Set to true by default from EXE inventory table |
1236651630 | Egahirn | |
1248696901 | FayDupe | |
1251373396 | FearMad | |
1256628564 | FireMad | |
1256629340 | FirePal | |
1268880421 | GemDone | |
1295308882 | MorphNoTalk | |
1300918700 | SpiderMad | |
1330279004 | Journal | |
1363579220 | LordMad | |
1468311221 | Scourge | Set to false by default from EXE inventory table |
1473909154 | JacielMad | |
1531392340 | VornMad | |
1558864153 | XivAlly | |
1558869517 | XivCalm | |
1569359031 | ZenaideName | |
1651011965 | GatanasName | |
1651013853 | GatanasNice | |
1714054682 | WearAmuletD | Set to false by default from EXE inventory table |
1714054686 | WearAmuletH | Set to false by default from EXE inventory table |
1714054691 | WearAmuletM | Set to false by default from EXE inventory table |
1714054693 | WearAmuletO | Set to false by default from EXE inventory table |
1714054696 | WearAmuletR | Set to false by default from EXE inventory table |
1714054699 | WearAmuletU | Set to false by default from EXE inventory table |
1714054701 | WearAmuletW | Set to false by default from EXE inventory table |
1714054704 | WearAmuletZ | Set to false by default from EXE inventory table |
1721931941 | ClarenDone | |
1727670897 | DarkEnemy | |
1728630387 | DarkThink | |
1767404608 | ReadBook | Set true on read of BK3_021 (Book of Life and Service) |
1787327552 | RestBook | Set true on read of BK3_022 (Book of Rest and Endings) |
1853655393 | RishDeal | |
1853656720 | NoRishDeal | |
1901998879 | VermaiNice | |
1982148044 | ScampNice | |
1982150367 | ScampOath | |
2002932057 | ScampMad | |
2050621348 | SeduceNoTalk | |
2056806840 | ServeDagon | |
2086714775 | WonshalaMad | |
2090957236 | TalchelmMad | |
2090957238 | TanchelmMad | |
2107685754 | JacielFree | |
2107714298 | JacielName | |
2150925840 | SKNoTalk | |
2179497472 | Dismissed2 | |
2225312088 | CountMad | |
2250671626 | GatanasMad | |
2301940191 | GhostNoTalk | |
2335475216 | SVNoTalk | |
2363664058 | RathineMad | |
2490508909 | StormName | |
2510188251 | ReadyRite | |
2591555654 | SumeerServe | |
2693120294 | SoulDagger | |
2704575370 | SkelNoTalk | |
2711253420 | SumeerMad | |
2721351254 | GemNoTalk | |
2722521035 | DremoraFoe | |
2722522602 | DremoraMad | |
2745032328 | CountYield | |
2747749378 | ChimereJournal | Set true on read of BK5_032 (Chimere's Journal) |
2799315501 | FayEnemy | |
2800454890 | FayVsXiv | |
2803229102 | VermaiMad | |
2804526801 | HerneFite | |
2828569565 | QuestStart | |
2842078857 | FearFite | |
3027445274 | VornName | |
3074986328 | FrostMad | |
3074987104 | FrostPal | |
3123090845 | GemReady | |
3311500540 | RishaalName | |
3322669644 | WonshalaName | |
3322694322 | WonshalaTask | |
3331880893 | MethatsName | |
3331882781 | MethatsNice | |
3390511660 | TalchelmDone | |
3390511692 | TanchelmDone | |
3396510040 | HerneMad | |
3458890877 | RathineName | |
3458892765 | RathineNice | |
3467258414 | XivEnemy | |
3630343479 | DohtAmulet | |
3642233908 | InvVoidguide1 | Set to false by default from EXE inventory table |
3647351483 | FaydraName | |
3657892940 | JacielAwake | |
3658994868 | JacielScram | |
3764290303 | XivilaiName | |
3780919640 | ImagoMad | |
3894314972 | Dismissed | |
4195854332 | SkelServe | Set to false by default |
WeaponList[edit]
This is essentially a truncated version of ItemList
for weapons.
Hash | Name | Comments |
---|---|---|
0 | Dagger | |
1 | Short Sword | |
2 | Long Sword | |
3 | Broad Sword | |
4 | Claymore | |
5 | Battle Axe | |
6 | War Axe | |
7 | Mace | |
8 | Short Bow | |
9 | Long Bow | |
10 | Crossbow | |
11 | Javelin | |
12 | Sling | Unused |
13 | Staff | |
14 | Spear | |
15 | Hand to Hand | Only real difference from ItemList |