ESO Mod:Skill Data Format

The UESPWiki – Your source for The Elder Scrolls since 1995
Jump to: navigation, search

This describes the format of the file containing skill data for ESO.

Location[edit]

The file in question is contained within the depot/Eso0000.dat file. Use the Online:EsoExtractData utility with the following options to extract:

        EsoExtractData.exe /path/to/eso.mnf /path/output/ --extractsubfile combined --archive 0

This should export a bunch of files looking like:

      000\807315.EsoFileData
      000\807315_Uncompressed.EsoFileData
      000\807316.EsoIdData
      000\807317.EsoFileData
      000\807317_Uncompressed.EsoFileData
      000\807318.EsoIdData
      ....

Note that the exact numbers output will likely change after each patch. The skill data file is 'usually' the first such file (smallest ID) but can also be found by searching for the textTool - Spherical Range like:

      grep 'Tool - Spherical Range' *.EsoFileData

Usually the skill data is the only such file containing that string.


Overall Format[edit]

The overall file format for the skill data is:

      Header (16 bytes)
      SkillRecords[] (variable number, variable sized)

Note that all data is in Big Endian byte order unless specified.


Header Format[edit]

The header is 16 bytes in length at the very start of the file and has the format:

      dword MagicBytes      // FA FA EB EB
      dword Unknown1        // 0x13?
      dword NumRecords      // Number of skill records that follow
      dword Unknown2        // 0x1C8?


Skill Record Format[edit]

The skill records immediately follow the header and fill the remaining file. The following format description is accurate as of update 29 (the format does change in some patches). Note that most field names given below are arbitrary.

      struct AbilityDef_Client {
      dword MagicBytes           // #### (23 23 23 23)
      dword Index                // Consecutive number starting at 1
      dword RecordLength1        // Add 32 (0x20) to get the total length of the skill record from the start of the magic bytes
      dword RecordLength2        // RecordLength1, RecordLength2, and RecordLength3 are always the same
       ----------- end of esoExtractData additions
       ----------- start of "AbilityDef(_Client)"
      dword Unknown // these are internal "Definitions ids" that you will find as linked element to other definitions
      dword Unknown // this is consequence of the game data files being a static export from actual Relational Database for development builds of the game.
      dword AbilityId1           // AbilityID (same as in-game), same as abilityId2
      dword RecordLength3
      
      dword AbilityId2


      struct ZoStringBase{
         dword NameLength   // this is not always a dword, it is packed as serialization goes. Usually it will be size in form of Big Endian Short , then string, then null terminator (not counted in size)
                            // a union with word would be pertinent there for future, or even better a variant, as this is extensively used in client code.
         std::vector<uint8_t> Name[NameLength]     // Does not include the terminated nul character (unless you include the following zero field)
      };
      ZoStringBase * AbilityName;
      //byte  Zero                 // Always 0 the null terminator said before. It is not really good to make object from data like that, as these are binary serialization and are quite far from that ingame.
                                   // ingame object deserialized will usually not have (unless nested struct) anything coming from serialization before this+0x10 and the usual vtable mess;
                                   // when it comes to reversing this game, taking in account the very high extent of polymorphism the game uses is crucial so you can properly design long term mimetism object s and behavior.
                                   // and when you intend to specifically describe binary data format like that, using proper tool like Katai struct is always preferable, more true and gives best outcomes.
      word  Zero                 // Always 0
      dword Zero                 // Always 0
      word  Unknown
      word  Unknown
      dword Zero                 // Always 0
      
      dword Unknown2[22]         // Contains lots of interested data (see below)
      byte  Flags[188]           // Values always 00 or 01
      
      dwordlist_t List1          // See Dword List format below (dword size + array of dwords)
      dwordlist_t List2
      dword Unknown6[6] 
      dwordlist_t List6a
      dword Unknown6a[7]
      dwordlist_t List6aa
      dwordlist_t List6ab
      dwordlist_t List3
      dwordlist_t List4
      dword Unknown7[9]
      dwordlist_t List6
      dwordlist_t List6b
      dword Unknown8[25]
      dwordlist_t List7
      dword Unknown9[4]
      dwordlist_t List8
      dword Unknown8a
      dword Unknown8b
      dwordlist_t List9
      dwordlist_t List10
      dword Unknown10[9]
      dwordlist_t List11
      dwordlist_t List12
      dword Unknown11[16]
      dwordlist2_t List13      // Note the double list size
      dword Unknown12[22]
      dwordlist2_t List14      // Note the double list size
      dword Unknown13[2]

};

Dword List Formats[edit]

Within the skill record data there are multiple lists of dwords with the following format:

      struct dwordlist_t {
             dword Size
             dword Data[Size]
       }

Note that an empty list is a just a dword with value 00 00 00 00. There are also lists that have elements with two dword instead of one:

      struct dwordlist2_t {
             dword Size
             dword Data[Size*2]
       }

The exact nature of the dword values depends from list to list. Sometimes they are skill abilityIds.

AbilityTypes[edit]

  • undocumented but extensively used both server and client side
enum class ABILITY_TYPE : unsigned int
{
NONE=0x0,
DAMAGE=0x1,
HEAL=0x2,
RESURRECT=0x3,
BLINK=0x4,
BONUS=0x5,
REGISTERTRIGGER=0x6,
SETTARGET=0x7,
THREAT=0x8,
STUN=0x9,
SNARE=0xa,
SILENCE=0xb,
REMOVETYPE=0xc,
SETCOOLDOWN=0xd,
COMBATRESOURCE=0xe,
DAMAGESHIELD=0xf,
MOVEPOSITION=0x10,
KNOCKBACK=0x11,
CHARGE=0x12,
IMMUNITY=0x13,
INTERCEPT=0x14,
REFLECTION=0x15,
AREAEFFECT=0x16,
DEPRECATED2=0x17,
CREATEINVENTORYITEM=0x18,
DAMAGELIMIT=0x19,
AREATELEPORT=0x1a,
FEAR=0x1b,
TRAUMA=0x1c,
STEALTH=0x1d,
SEESTEALTH=0x1e,
FLIGHT=0x1f,
DISORIENT=0x20,
STAGGER=0x21,
SLOWFALL=0x22,
JUMP=0x23,
SIEGECLUSTERAREAEFFECT=0x24,
SUMMON=0x25,
MOUNT=0x26,
INTERACTREFUSALOVERRIDE=0x27,
BLADETURN=0x28,
NONEXISTENT=0x29,
NOKILL=0x2a,
NOAGGRO=0x2b,
DISPEL=0x2c,
VAMPIRE=0x2d,
CREATEINTERACTABLE=0x2e,
MODIFYCOOLDOWN=0x2f,
LEVITATE=0x30,
PACIFY=0x31,
ACTIONLIST=0x32,
INTERRUPT=0x33,
BLOCK=0x34,
OFFBALANCE=0x35,
EXHAUSTED=0x36,
MODIFYDURATION=0x37,
DODGE=0x38,
SHOWNON=0x39,
MISDIRECT=0x3a,
FREECAST=0x3b,
SIEGECREATE=0x3c,
SIEGEAREAEFFECT=0x3d,
DEFEND=0x3e,
FREEINTERACT=0x3f,
CHANGEAPPEARANCE=0x40,
ATTACKERREFLECT=0x41,
ATTACKERINTERCEPT=0x42,
DISARM=0x43,
PARRY=0x44,
PATHLINE=0x45,
DOUBLEFIRE=0x46,
FIREPROC=0x47,
LEAP=0x48,
REVEAL=0x49,
SIEGEPACKUP=0x4a,
RECALL=0x4b,
GRANTABILITY=0x4c,
HIDE=0x4d,
SETHOTBAR=0x4e,
NOLOCKPICK=0x4f,
FILLSOULGEM=0x50,
SOULGEMRESURRECT=0x51,
DESPAWNOVERRIDE=0x52,
UPDATEDEATHDIALOG=0x53,
DEPRECATED4=0x54,
CLIENTFX=0x55,
AVOIDDEATH=0x56,
NONCOMBATBONUS=0x57,
NOSEETARGET=0x58,
DEPRECATED=0x59,
SETPERSONALITY=0x5a,
BASIC=0x5b,
REWINDTIME=0x5c,
LIGHTHEAVYATTACKOVERRIDE=0x5d,
DERIVEDSTATCACHE=0x5e,
AVAREACH=0x5f,
RANDOMBRANCH=0x60,
MOUNTBLOCK=0x61,
DEPRECATED3=0x62,
HARDDISMOUNT=0x63,
LINKTARGET=0x64,
CUSTOMTARGETAREA=0x65,
DAMAGETRANSFER=0x66,
DISABLEITEMSETS=0x67,
FOLLOWWAYPOINTPATH=0x68,
SETAIMATTARGET=0x69,
FACETARGET=0x6a,
LOSMOVEPOSITION=0x6b,
DISABLECLIENTTURNING=0x6c,
DAMAGEIMMUNE=0x6d,
STOPMOVING=0x6e,
RESOURCETAP=0x6f
};

 unsigned int AbilityDef_Client::GetAbilitypeNumber()
 {
                return *(unsigned int*)(this+0x4C);
 }

Data Format Notes[edit]

Most of the format has not been deciphered yet but there are a number of discoveries to note:

  • Skills per class can be found in the next file (807317 in update 29pts).
  • There are some float values in some places. All of them are in Little Endian byte order.
  • In the language file skill names are found in section 198758357 and skill descriptions in 132143172.
  • Unknown2[]
  • Unknown2[0] is a time/date in time_t format.
  • Unknown2[1] is cast time*1000.
  • Unknown2[3] + Unknown2[4] are something related to tooltip values.
  • Unknown2[5] is maxRange.
  • Unknown2[6] is the ability type (ABILITY_TYPE_...). In-game this is only available in combat effect callbacks.
  • Unknown2[7] target type?
  • Values following this may depend on the ability type or something else. The skill cost is sometimes in element 14 and sometimes in element 15.
  • Unknown2[11] duration or channel time *1000
  • Unknown2[13] angleDistance *50
  • Unknown2[14] or Unknown2[15] is ability cost. Is not always the exact value (see list9 below).
  • Unknown2[16] radius *100
  • Unknown2[18] always float 100
  • Unknown2[19] usually 7000?
  • Flags
  • Always a 00 or 01 value.
  • Flags[187] is always 0
  • Unknown6a[4] is the mechanic (-2 is health)
  • List1 / List2
  • Related to linked abilities (synergy, minor/major buffs/debuffs used in skill, etc...)
  • List1 is linked type?
  • List2 is abilityId
  • List3 / List4
  • Related to tooltip values from the skill description. Should have the same number of elements as the placeholder <<#>> values in the description (numbers start at 1).
  • List3 is some sort of type (18 = damage?, 17 = damage?)
  • List4 is abilityId (this can point back the same skill)
  • List9
  • List9[1] and List9[2] is something related to skill cost (types?)
  • List9[1] is skillCost/72 when the skill cost in Unknown2[] is not the skill cost. (not completely verified)
  • List12[4] is a float
  • Unknown8
  • Unknown8[10], Unknown2[12], Unknown2[14], Unknown2[16] are stat types (4 = magicka, 25 = spell damage, 35 = stamina, 29 = weapon damage). Possible values are:
      0: STAT_NONE
      1: STAT_BONUS_OPTION_DONT_APPLY_BONUS
      2: STAT_WEAPON_AND_SPELL_DAMAGE
      4: STAT_MAGICKA_MAX
      7: STAT_HEALTH_MAX
      8: STAT_HEALTH_REGEN_COMBAT
      22: STAT_PHYSICAL_RESIST
      25: STAT_SPELL_POWER (Spell Damage)
      29: STAT_STAMINA_MAX 
      35: STAT_POWER (Weapon Damage)
      36: STAT_DAMAGE_RESIST_START
  • Updated Exhaustive list as of 6.3.6 is as follow:
      0x0:STAT_NONE
      0x1:STAT_ATTACK_POWER
      0x2:STAT_WEAPON_AND_SPELL_DAMAGE
      0x3:STAT_ARMOR_RATING
      0x4:STAT_MAGICKA_MAX
      0x5:STAT_MAGICKA_REGEN_COMBAT
      0x6:STAT_MAGICKA_REGEN_IDLE
      0x7:STAT_HEALTH_MAX
      0x8:STAT_HEALTH_REGEN_COMBAT
      0x9:STAT_HEALTH_REGEN_IDLE
      0xa:STAT_HEALING_TAKEN
      0xb:STAT_DODGE
      0xc:STAT_HEALING_DONE
      0xd:STAT_SPELL_RESIST
      0xe:STAT_BLOCK
      0x10:STAT_CRITICAL_STRIKE
      0x14:STAT_MITIGATION
      0x16:STAT_PHYSICAL_RESIST
      0x17:STAT_SPELL_CRITICAL
      0x18:STAT_CRITICAL_RESISTANCE
      0x19:STAT_SPELL_POWER
      0x1a:STAT_SPELL_MITIGATION
      0x1b:STAT_OFFENSIVE_PENETRATION
      0x1c:STAT_CRITICAL_CHANCE
      0x1d:STAT_STAMINA_MAX
      0x1e:STAT_STAMINA_REGEN_COMBAT
      0x1f:STAT_STAMINA_REGEN_IDLE
      0x20:STAT_MISS
      0x21:STAT_PHYSICAL_PENETRATION
      0x22:STAT_SPELL_PENETRATION
      0x23:STAT_POWER
      0x24:STAT_DAMAGE_RESIST_START
      0x25:STAT_DAMAGE_RESIST_GENERIC
      0x26:STAT_DAMAGE_RESIST_PHYSICAL
      0x27:STAT_DAMAGE_RESIST_FIRE
      0x28:STAT_DAMAGE_RESIST_SHOCK
      0x29:STAT_DAMAGE_RESIST_OBLIVION
      0x2a:STAT_DAMAGE_RESIST_COLD
      0x2b:STAT_DAMAGE_RESIST_EARTH
      0x2c:STAT_DAMAGE_RESIST_MAGIC
      0x2d:STAT_DAMAGE_RESIST_DROWN
      0x2e:STAT_DAMAGE_RESIST_DISEASE
      0x2f:STAT_DAMAGE_RESIST_POISON
      0x30:STAT_MOUNT_STAMINA_MAX
      0x31:STAT_MOUNT_STAMINA_REGEN_COMBAT
      0x32:STAT_MOUNT_STAMINA_REGEN_MOVING
      0x0:STAT_MIN_VALUE
      0x32:STAT_MAX_VALUE
      0x0:STAT_ITERATION_BEGIN
      0x32:STAT_ITERATION_END
      0x0:STAT_BONUS_OPTION_APPLY_BONUS
      0x1:STAT_BONUS_OPTION_DONT_APPLY_BONUS
      0x0:STAT_BONUS_OPTION_MIN_VALUE
      0x1:STAT_BONUS_OPTION_MAX_VALUE
      0x0:STAT_BONUS_OPTION_ITERATION_BEGIN
      0x1:STAT_BONUS_OPTION_ITERATION_END
  • Unknown8[11], Unknown2[13], Unknown2[15], Unknown2[17] are float values representing the coefficient for the previous stat type.
  • Regular skills have 14/15/16/17 as 0. Ultimates have full sections. Unknown if more than 10-16 can have coefficient values.
  • For example:
       10 = 25
       11 = 0.05
       12 = 4
       13 = 0.1
       14 = 35
       15 = 0.05
       16 = 29
       17 = 0.1
  • Only one rank of active skills is stored in the data (this was changed in one update).
  • Ranks have the same description text and most of the same data.
  • Ranks 1-3 have 3/2/1% smaller coefficients (not confirmed).
  • Some skills ranks 1-3 have increased skill cost 270/180/90 (not confirmed, unsure what controls this).

More Info[edit]