Description: by Nefarius, Restyled by HarvestWombs
Categories: File Guides (1.1x)
Stat: An Id pointer used in other *.txt files (Properties.txt, Skills.txt, States.txt and also within ItemStatCost.txt) to refer to this stat, this field must be unique, otherwise you're looking into a world of glitches and bugs.
Id: This field isn't compiled into the bin files, and thus only serves as reference for the internal numeric Id. The internal idea is identical to the # of the record in the array (that is, the first stat would be 0, the second 1 and so on).
Send Other: A boolean that controls whenever the value of this stat is sent to other players, this is only semi functional because most of this is hardcoded to specific stats only, leave it set only for the stats that are being sent in vanilla (Strength, Dexterity etc) because the game needs to keep clients up to date on these values to function properly (otherwise you'll just glitch up the game).
Signed: A boolean that controls whenever the stat is signed (can be both positive and negative) or unsigned (can only be positive), this doesn't really seam to make any difference because whenever a stat is really signed or unsigned depends on how the code is designed to use it, and not on this column, for example Life, Mana, Stamina (etc) can all become negative when they exceed 8388607 * 256 no matter what you set this too, I suspect this simply has to do with the way the game reads stat packets because these packets generally only transmit stats in WORD size and it would need to know if they are signed or unsigned for a semi-proper conversion (...)
Send Bits: How many bits of data the game will attempt to fit into a stat update packet for the value of the stat if the stat is sent to clients, again this is not really utilized too a very great extent because most of this is hardcoded, in general for signed stats, it is best to set this to 1 more then Save Bits (so say, if save bits is 31 then set this to 32), for unsigned stats it shouldn't matter. Stats with Save Bits of 32 are never treated as signed, always unsigned, and you can't really set Send Bits to above 32 bits anyway (for very obvious reasons).
Send Param: How many bits of data the game will attempt to fit into a stat update packet for the parameter of the stat if the stat is sent to clients, it is best to set this to 1 more then Save Param Bits unless it is set to 32 bits (in which case it is unsigned), otherwise the param is always signed. This is used to transmit things like the skill granted by oskills (etc), however the same applies here as applied to the previous column, this is almost entirely hardcoded.
UpdateAnimRate: This boolean tells the game to call the speed handler and properly adjust the speed of a unit when a stat with this boolean set to true is altered on the unit (via a skill for example), this is for example the case when an aura is applied, so that the speed of the unit changes immediately and not after the current cycle (either attack, walk to a cell etc) ends... As usual, this is rather hardcoded so you'd need to expand the code if you add custom speed stats like these!
Saved: This boolean controls whenever the value of the stat is saved on characters inside the *.d2s file after you leave the game, be aware that statNo 511 is used to signify the 'End-Of-Stat-Section' and cannot be used, there are reports that only stats 0 to 255 are saveable and other reports that all 510 stats are saveable, I haven't tested this myself so I cannot validate either claim ATM... Looking at the *.d2s reading and writing code I however could not find any artificially imposed limitation (other then the aforementioned fact stat 511 cannot be used for anything).
CSvSigned: If the previous column is set to true, this boolean controls whenever the stat is saved in signed or unsigned format, this makes no real difference, other then the fact the way it is written and read from the *.d2s is different (this has more relevance when you have the source code at hand and don't want to get tons of warning messages about signed / unsigned mismatch I guess)...
CSvBits: How many bits of data are allocated to the value of this stat within the *.d2s file stat section when the stat is saved (only used if the Saved boolean is true), for unsigned stats you can go all the way to 32 bits (allowing for a range of 0 to 4294967295), for signed stats you can go only to 31 bits (allowing for a range of -2147483648 to 2147483647), it makes no real difference as stated for the previous column, keep it like in vanilla for the existing stats though, it works so no need to fix it. Setting this field to 32 bits for a signed stat has the same effect as setting CSvSigned to false.
CSvParam: How many bits of data are allocated to the parameter of this stat within the *.d2s file stat section when the stat is saved (only used if the Saved boolean is true), the parameter is always signed, unless you set this to 32 bits, in which case it becomes unsigned. The same applies here as for the previous column...
fCallback: This boolean controls whenever the stat-assignment callback function is called by the game if the value of this stat changes, this is used to assign / remove item events, skills, auras, states and more to the character / monster... For new special effects you have to expand the callback function... It will work fine for new stats that trigger item events however!
fMin: This boolean controls whenever the game will attempt to keep the stat in range calling a special function (and at times doing this inline, such as when the stats are altered by an aura), this prevents stats like strength, dexterity, energy, vitality (etc) from dropping below zero...
MinAccr: This field (a DWORD btw) controls the minimum value that the stat is capped to, this seams (I haven't verified this) to work hand-in-hand with fMin, however the times I've seen the code access that flag inline I haven't seen it utilize this column, but rather use hardcoded minimum values!
Encode: This field tells the game whenever to encode the stat (and in this case in what way to encode it) when it is saved to conserve space, this is used for complex stats with more then just a parameter and a value such as 'chance to cast on event', which have to store the chance, sLvl and the skill to cast, the arithmetics of this are rather complex and aren't within the scope of this fileguide, you can read about them in several old forum posts however... For new stats, follow the theme vanilla is using and use this only if you try to duplicate a stat that is encoded in vanilla!
Add and Multiply: These two fields control the additional price added to an item's cost (be aware that certain stats like armorclass on armors (etc) are treated more then once as there are hardcoded cases for them!)
the bonus equals: cost * (1 + value * multiply / 1024)) + add (...)
Divide: This field is not used by the code anymore, the game uses a inline function for all this price judgling, and it never accesses divide, rather it uses a hardcoded division by 1024!
ValShift: This field tells the game how the stat is going to be read from and written to items, it does not control whenever the stat is generally used in higher precision, this is entirely hardcoded! Basically this field is only there to save space in the *.d2s file, so that instead of having to save +256 life it will simply save +1 life when this stat is present on an item!
1.09-Save Bits and 1.09-Save Add: These fields are used only for items imported from v1.07 - v1.09, they replace Save Bits and Save Add so that you can convert the items to the old stat format to the new one, character stats didn't use ItemStatCost.txt prior to v1.10 so this doesn't apply to those stats... If you want to prevent people from cheating by creating a v1.09 character and then entering your mod with hacked items (that will get automatically converted by the game), simply blank out all these columns and they'll get a nice 'bad stats' or 'bad inventory' error in their face
Save Bits and Save Add: These fields control how many bits of data are allocated to the value of this stat within the *.d2s file item stat section ONLY, they have almost no realtime application at all, stats granted by skills and monster stats (etc) are not in any way or form bound to this! The only realtime application this has is when an item is getting compressed / decompressed (which happens every time you pick it up or do anything with it) any way, with this misconception taken off the shelf, lets look at how they work. Save Bits controls how many bits of data are allocated to the stat value (see discussion under CSvBits for more info about unsigned / signed implications on what values you can use in this field), the actual maximum value of the stat is therefore equal to 2^SaveBits-1, now Save Add comes into play, this controls how large the negative range of the stat can be, for example a Save Add equal to 100 would allow you to use -100 for this stat on an item, this also means the maximum value possible for the stat decreases by 100, thus the final range possible for a stat is -SaveAdd to 2^SaveBits-(SaveAdd+1).
Save Param Bits: This field controls how many bits of data are allocated to the parameter of this stat when it is saved on items, the same applies here as to the previous column and to CSvParam so refer to the description of these columns, Save Add does not effect the maximum or minimum value of the stat's parameter however... It is best to set this to 17 for all stats that use any form of Id for their parameter (either a skill or a monster etc), because most Id ranges are capped to 65,535, and these parameters always being signed unless they are set to store 32 bits means this will allow you to use all Ids without any fear of glitches or bugs!
KeepZero: This boolean supposedly controls whenever to prevent the stat from going negative, probably working hand-in-hand with some of the fMin implementations, at best the effect is however only client-side, as we all know stats like mana and stamina can roll over when they exceed 8388607 * 256!
Op, Op Param, Op Base and Op Stat1 to Op Stat3: These fields control special forms of stat assignment used for example for stats that add a bonus depending on cLvl (etc), I'll explain each of the op methods in detail below (there are in total 13 op formula, but not all are used by the game)... Leaving this field blank or setting it to 0 will use the default op, that just adds the stat to the unit directly... In the below formula, opstat refers to the stats set in the three Op Stat columns, statvalue refers to the value of the stat itself (the stat that has the op stuff assigned to it), basevalue refers to the stat set in the Op Base column and param refers to the value set in the Op Param column!
CODE: Select all
1 - adds [color=#80FFBF]opstat.base * statvalue / 100[/color] to the [b][color=#FFBF00]opstat[/color][/b]. 2 - adds [color=#80FFBF](statvalue * basevalue) / (2 ^ param)[/color] to the [b][color=#FFBF00]opstat[/color][/b], this does not work properly with any stat other then level because of the way this is updated, it is only refreshed when you re-equip the item, your character is saved or you level up, similar to passive skills, just because it looks like it works in the item description does not mean it does, the game just recalculates the information in the description every frame, while the values remain unchanged serverside. 3 - this is a percentage based version of op #2, look at op #2 for information about the formula behind it, just remember the stat is increased by a percentage rather then by adding an integer. 4 - this works the same way op #2 works, however the stat bonus is added to the item and not to the player (so that +defense per level properly adds the defense to the armor and not to the character directly!) 5 - this works like op #4 but is percentage based, it is used for percentage based increase of stats that are found on the item itself, and not stats that are found on the character. 6 - like for op #7, however this adds a plain bonus to the stat, and just like #7 it also doesn't work so I won't bother to explain the arithmetic behind it either. 7 - this is used to increase a stat based on the current daytime of the game world by a percentage, there is no need to explain the arithmetics behind it because frankly enough it just doesn't work serverside, it only updates clientside so this op is essentially useless. 8 - hardcoded to work only with maxmana, this will apply the proper amount of mana to your character based on CharStats.txt for the amount of energy the stat added (doesn't work for non characters) 9 - hardcoded to work only with maxhp and maxstamina, this will apply the proper amount of maxhp and maxstamina to your character based on CharStats.txt for the amount of vitality the stat added (doesn't work for non characters) 10 - doesn't do anything, this has no switch case in the op function. 11 - adds [color=#80FFBF]opstat.base * statvalue / 100[/color] similar to 1 and 13, the code just does a few more checks 12 - doesn't do anything, this has no switch case in the op function. 13 - adds [color=#80FFBF]opstat.base * statvalue / 100[/color] to the value of [b][color=#FFBF00]opstat[/color][/b], this is useable only on items it will not apply the bonus to other unit types (this is why it is used for +% durability, +% level requirement, +% damage, +% defense [etc]).
Direct: this boolean controls whenever this stat has a maximum stat associated with it, which among others means that unless you screw up something badly, this stat can never exceed the value of the maximum stat and that any change to this stat is permanent (a skill that alters mana, hitpoints or stamina is permanent, while a skill that alters maxmana, maxhp and maxstamina is temporary). You do not need to specify a maximum stat for the effect to be permanent, this can be used to get kill counters to work (look for SVR's old post).
MaxStat: the maximum stat associated with this stat, this field only ever has an effect if Direct is set to true, see the discussion under that field. Percentage based increases to the max stat will usually alter this stat too, however this has some hardcoded aspects to it and is not entirely softcoded.
ItemSpecific: this boolean controls whenever this stat is specific to a single item, that is, if you socket a jewel that adds +durability or +quantity into something else, the quantity or durability of both items will not stack when a general call to GetStat is returned, however whenever this works properly is unknown, I at least haven't tested it and nobody else has either. It should also prevent the stat from being added to the item owners accumulated total of that stat.
DamageRelated: this boolean controls whenever the stat will be restricted to a single weapon and not stack with the item owners accumulated total of that stat when he equips the weapon (this is used to prevent barbarians who dual wield from for example having 50% lifesteal if one weapon has 1% and the other 49% no matter what weapon they swing). To explain this more indepth, when you swing your weapon the game copies all these stats (from the weapon involved) to a temporary statlist that is then flushed after the attack is completed (this is not 100% what happens, but it should give you an idea).
ItemEvent1: and ItemEvent2: the event (from Events.txt) that will trigger the associated event function be aware that not every event will work with every event function, and some event functions will not work when set as an item event!
ItemEventFunc1: and ItemEventFunc2: the event function associated with the corresponding event set in the previous columns. Below is a list of events and what they do.
CODE: Select all
1 - shoots a missile at the owner of a missile that has just hit you (Chilling Armor uses this) 2 - freezes the attacker for a set duration the attacker (Frozen Armor uses this) 3 - does cold damage to and chills the attacker (Shiver Armor uses this) 4 - % of damage taken is done to the attacker (Iron Maiden, thorns uses a hardcoded stat) 5 - % of damage done added to life, bypassing the targets resistance (used by Life Tap) 6 - attacker takes physical damage of # 7 - knocks the target back 8 - induces fear in the target making it run away 9 - applies Dim Vision to the target (it casts the actual curse on the monster) 10 - attacker takes lightning damage of # 11 - attacker takes fire damage of # 12 - attacker takes cold damage of # 13 - % damage taken is added to mana 14 - freezes the target 15 - causes the target to bleed and lose life (negative life regen) 16 - crushing blow against the target 17 - mana after killing a monster 18 - life after killing a demon 19 - slows the target 20 - casts a skill against the defender 21 - casts a skill against the attacker 22 - absorbs physical damage taken (used by Bone Armor) 23 - transfers damage done from the summon to the owner (used by Blood Golem) 24 - used by Energy Shield to absorb damage and shift it from life to mana 25 - absorbs elemental damage taken (used by Cyclone Armor) 26 - transfers damage taken from the summon to the owner (used by Blood Golem) 27 - used to slow the attacker if he hits a unit that has the slow target stat (used by Clay Golem) 28 - life after killing a monster 29 - destroys the corpse of a killed monster (rest in peace effect) 30 - cast a skill when the event occurs, without a target 31 - reanimate the target as the specified monster
DescFunc: the function used for generating the description for this stat, this works like the descfuncs in SkillDesc.txt pretty much. See below for an explanation of individual functions, these are listed the way they would show up if DescVal is set to 1. This follows the syntax Char used in the old fileguide, but includes the functions he didn't cover.
CODE: Select all
1 - +[value] [string1] 2 - [value]% [string1] 3 - [value] [string1] 4 - +[value]% [string1] 5 - [value*100/128]% [string1] 6 - +[value] [string1] [string2] 7 - [value]% [string1] [string2] 8 - +[value]% [string1] [string2] 9 - [value] [string1] [string2] 10 - [value*100/128]% [string1] [string2] 11 - Repairs 1 Durability In [100 / value] Seconds 12 - +[value] [string1] 13 - +[value] to [class] Skill Levels 14 - +[value] to [skilltab] Skill Levels ([class] Only) 15 - [chance]% to case [slvl] [skill] on [event] 16 - Level [sLvl] [skill] Aura When Equipped 17 - [value] [string1] (Increases near [time]) 18 - [value]% [string1] (Increases near [time]) 19 - this is used by stats that use Blizzard's sprintf implementation (if you don't know what that is, it won't be of interest to you eitherway I guess), look at how prismatic is setup, the string is the format that gets passed to their sprintf spinoff. 20 - [value * -1]% [string1] 21 - [value * -1] [string1] 22 - [value]% [string1] [montype] (warning: this is bugged in vanilla and doesn't work properly, see CE forum) 23 - [value]% [string1] [monster] 24 - used for charges, we all know how that desc looks 25 - not used by vanilla, present in the code but I didn't test it yet 26 - not used by vanilla, present in the code but I didn't test it yet 27 - +[value] to [skill] ([class] Only) 28 - +[value] to [skill]
DescStrPos: The string used for the description when the stat value is positive.
DescStrNeg: The string used for the description when the stat value is negative.
DescStr2: An additional string used by some DescFuncs, usually used as a suffix or for aditional info (such as per character level etc).
dGrp: When all stats in this group are present on the same item and they all have the same value, replace their description with the associated group description.
dGrpFunc: The same as DescFunc, just for the group description
dGrpVal: The same as DescVal, just for the group description
dGrpStrPos: The same as DescStrPos, just for the group description
dGrpStrNeg: The same as DescStrNeg, just for the group description
dGrpStr2: The same as DescStr2, just for the group description
Stuff: Stay far away from this column unless you really know what you're doing and / or work for Blizzard, this column is used during bin-file creation to generate a cache regulating the op-stat stuff and other things, changing it can be futile, it works like the constants column in MonUMod.txt and has no other relation to ItemStatCost.txt, the first stat in the file simply must have this set or else you may break the entire op stuff.
Link to this article: Select all
[url=https://www.d2mods.info/forum/kb/viewarticle?a=448&sid=bc4479c5684aaa2b1ff9108236c4a032]Knowledge Base - ItemStatCost.txt[/url]