Mechanics

properties

Property → stat composition layer. Maps every mod-code used across uniqueitems / setitems / sets / runes / magicprefix / magicsuffix / cubemain / automagic into one or more itemstatcost stats with a function ID controlling how min / max / param resolve at item-generation time.

properties.txt is the composition layer between item-mod codes (the prop1, mod1code, Code, mod 1 columns scattered across the other item tables) and the engine's stat dictionary in itemstatcost. When a unique item ships prop1 = "ac", the engine looks up ac here, sees it composes the armorclass stat via function 1 (random between min and max), and applies the resulting value to the item. Every modifier on every spawned item — every +1 to Skills, every Faster Cast Rate, every Adds 5–10 Fire Damage — passes through one row in this file.

285 rows × 38 columns. Each row is one property code, and codes are unique (no duplicates). A property can compose up to 7 stats through its func1/stat1/set1/val1func7/stat7/set7/val7 slot blocks, though in practice the deeper slots are rarely used: 285 rows fill slot 1, 15 fill slot 2, 10 slot 3, 6 slot 4, 2 each in slots 5–6, and 1 in slot 7.

How a property resolves

When an item-generation routine looks up a property code, it iterates the row's slot blocks 1 through 7 in order. For each filled slot:

  1. Read funcN — the function ID, a small integer enum (0–25 in shipped data, plus 36) that selects how the slot's values are interpreted.
  2. Read statN — the stat key from itemstatcost that this slot writes to (some functions don't need a stat; locbones marks those slots blank).
  3. Read setN — a boolean controlling whether the slot sets the stat value (replacing any current value) or adds to it. 1 = set, 0/blank = add.
  4. Read valN — an integer parameter consumed by certain functions (most commonly for stat-ID offset arithmetic).

The function ID is the load-bearing piece. Function 1 (the default for "random value between min and max") covers 123 of the 285 properties; everything else uses a more specialized function — chance-to-cast skill encoding, day-night time scaling, per-character-level scaling, charged skills, etc. The full function reference is below.

When a property uses multiple slots, the slots compose: res-all writes to all four resistance stats by chaining four slots (the second–fourth reusing the first's rolled value via function 3). dmg-elem writes seven stats (fire min/max, lightning min/max, cold min/max/duration) by chaining all seven slots. Multi-slot properties are how the engine bundles "one displayed line" into multiple underlying stats.

Columns

Identity

ColumnMeaning
codeUnique property identifier. Referenced by prop1prop12 in uniqueitems and setitems, PCode2a/FCode1 etc. in sets, T1Code1T1Code7 in runes (runeword stats), mod1codemod3code in magicprefix and magicsuffix, mod 1mod 5 in cubemain recipe outputs, and modcode slots in automagic.

Stat-composition slots (slot blocks 1 through 7)

Each slot block is four columns. Slot 1 is required (every property fills it); slots 2–7 are optional and used only when the property needs to write to multiple stats.

Column patternMeaning
funcNFunction ID from the table below. Controls how min/max/param/val are read and what the slot does.
statNStat key from itemstatcost. The slot writes its computed value to this stat. Some functions (5/6/7 for damage, 14 for sockets, 20 for indestructible, 23 for ethereal) don't take a stat and leave this blank.
setN1 = set the stat to the computed value (replacing); 0 or blank = add to the stat's current value.
valNInteger parameter consumed by functions that need it (most commonly function 21 / 22 / 36, where val acts as a stat-ID offset).

UI

ColumnMeaning
uiRangeTypeControls how the property's range is displayed in tooltips. Used by 46 of 285 rows (37 with value 1, others scattered). All 37 uiRangeType = 1 rows are character-level-scaling mods (/lvl suffix in their code) — Defense Per Character Level, Life Per Character Level, etc.

Annotation (asterisk-prefixed — reference only)

ColumnMeaning
*IdNumeric row index. Stable across patches if the row order doesn't change.
*Enabled1 if the property is live; 0 if disabled. (All 285 rows are enabled in the shipped data.)
*TooltipThe localized display string template for the property's mod line (e.g. +# Defense, Adds #-# Fire Damage, +# to [Skill] ([Class] only)). The # and […] placeholders are filled by the engine at display time using the stat values and the statN keys.
*ParameterAuthor note describing what the valN or stat parameter columns mean for this property (e.g. for randclassskill, *Notes reads val1 = # of Skill levels).
*Min, *MaxAuthor notes describing how the stat-block's min / max values are interpreted for this property. Often literally Min # / Max #.
*NotesFree-form author commentary.
*eolEnd-of-row marker, always 0. Common to most .txt tables.

Function ID reference

Every property's slot specifies a function ID. The function controls how the slot's min, max, param, val values are interpreted and written into the stat.

IDNameReadsBehavior
0(null)Unused.
1ItemModsSetValueRegularstat, setThe default. Roll a random value between the stat's min and max. On High Quality (Superior) items, use the stat's max. Used by 123 of 285 properties — every standard "+X to stat" mod.
2ItemModsSetValueBaseToMaxstat, setAlways set the stat to its max value (no roll).
3ItemModsSetValueRegular2stat, setSame as function 1, but consecutive calls reuse the previous slot's rolled value. This is how res-all keeps all four resistances at the same value.
4ItemModsSetValueBaseToMax2stat, setSame as function 2, with the consecutive-reuse behavior.
5ItemModsSetMinDamagesetSet the item's minimum damage value.
6ItemModsSetMaxDamagesetSet the item's maximum damage value (dependent on its minimum).
7ItemModsSetDamagePctsetSet the damage percent (%ED) based on the stat's min/max range.
8ItemModsSetSpeedstat, setRoll a random value between min and max for a speed mod (FCR, FHR, FRW, IAS). Used by 15 properties — all the +X% Faster … lines.
9ItemModsSetSingleSkillstat, setUsed for single-skill +N mods. Stat's parameter carries the skill ID; min/max are the skill-level range.
10ItemModsSetTabSkillsstat, setSkill-tab +N mods (e.g. +1 to Fire Spells). Stat's parameter is the tab ID: 0–2 Amazon, 3–5 Sorceress, 6–8 Necromancer, 9–11 Paladin, 12–14 Barbarian, 15–17 Druid, 18–20 Assassin.
11ItemModsSetSkillOnAttackstat, setChance-to-cast skill on an event (hit-skill, gethit-skill, death-skill). Stat's parameter is the skill ID; min is the percent chance (default 5 if 0); max is the skill level.
12ItemModsSetRandomParamstat, setRandom selection of the stat's parameter value using min/max as a range.
13ItemModsSetMaxDurabilitystat, setRoll min/max for a durability mod; on Superior items set to max; current durability snaps to maximum after calculation.
14ItemModsSetSocketsRoll the number of sockets on an item. min/max define the random socket count; capped by item's grid size and the hard cap of 6.
15ItemModsSetMinstat, setAlways use the stat's min value (no roll). For physical-minimum-damage stats, this becomes the item's min damage.
16ItemModsSetMaxstat, setAlways use the stat's max value (no roll). Symmetric counterpart to function 15 for max damage.
17ItemModsSetParamstat, setRead the stat's parameter value, falling back to a random min/max value, then 0. The standard pattern for per-character-level scaling mods (all 37 /lvl properties use this).
18ItemModsSetByTimestatDay/night-cycle-scaled stat. The stat's parameter value names a time period (0 = Day, 1 = Dusk, 2 = Night, 3 = Dawn). The stat's effective value depends on how close the in-game time is to the named period, scaled between min and max. Used by 36 properties — the entire day-night cycle mod family.
19ItemModsSetChargedSkillstatSkill-charge mods (the +N charges of Skill X family). Stat's parameter is the skill ID; stat's min calculates MaxCharges (using ilvl-scaled arithmetic when negative); max is skill level; spawned charges are randomized within a bounded range. Capped at 255 charges total.
20ItemModsSetIndestructibleAdd the Indestructible stat to the item.
21ItemModsSetValueRegPropValParamstat, set, valLike function 1, but the property's val value offsets the stat ID. Used to write to one of a family of similarly-structured stats based on val.
22ItemModsSetValueRegParamstat, setLike function 1, but the stat's parameter value offsets the stat ID. The aura, skill, oskill properties use this pattern — the skill ID lives in the stat's parameter, the level in min/max.
23ItemModsSetEtherealAdd the Ethereal stat. Only applies to items that have Durability.
24ItemModsSetParamAndValuestat, setRoll the value (min/max) and offset the stat ID by the stat's parameter. Consecutive calls reuse the rolled value.
25(engine-extended)Used by one shipped property (affix-rand, tooltip Add random affix from property). The slot has no stat set; the engine interprets this code as a directive to overlay a random named affix from the property's referenced pool.
26–35(null)Unused.
36ItemModsSetValueRegPropValParamSwappedstat, set, valVariant of function 21 where the roles of the stat's value and the property's val are switched. Used by randclassskill (Hellfire Torch's +1–3 random class skills mod).

Worked example: dmg-elem chains all 7 slots to write 7 stats

The mixed-element damage mod (Adds #-# Fire/Lightning/Cold Damage) is the only shipped property that fills every slot. Reading its row left to right:

SlotfuncNstatNBehavior
115 (SetMin)firemindamUse the property's min as the item's fire min damage.
216 (SetMax)firemaxdamUse the property's max as the item's fire max damage.
315 (SetMin)lightmindamUse min again, this time for lightning min damage.
416 (SetMax)lightmaxdamUse max again for lightning max.
515 (SetMin)coldmindamMin → cold min damage.
616 (SetMax)coldmaxdamMax → cold max damage.
717 (SetParam)coldlengthUse the property's parameter value as the cold-damage duration in frames.

One property roll with one min/max pair writes to seven stats, and the seventh stat reads the parameter value instead of the rolled min/max. That's why dmg-elem items show three element damage ranges that are identical (same min, same max) with a cold-damage duration on top — the underlying mechanic is one rolled pair fanned out.

For a simpler chain pattern, res-all does the same thing for resistances using function 3 (consecutive-reuse) instead of repeated min/max reads:

SlotfuncNstatNBehavior
11 (regular)fireresistRoll between min and max.
23 (regular-reuse)lightresistReuse the slot-1 rolled value.
33 (regular-reuse)coldresistSame.
43 (regular-reuse)poisonresistSame.

One rolled value, applied identically to all four resistance stats — that's why +25 All Resistances literally means +25 Fire / +25 Lightning / +25 Cold / +25 Poison rather than four independent rolls.

Cross-references

  • uniqueitems, setitemsprop1prop12 columns name property codes from this file.
  • setsPCode2aPCode5a and FCode1FCode8 columns name property codes (partial-set and full-set bonuses).
  • runes — runeword stat columns (T1Code1T1Code7) name property codes.
  • magicprefix, magicsuffixmod1code/mod2code/mod3code columns name property codes.
  • cubemainmod 1mod 5 columns on recipe outputs name property codes.
  • automagic — auto-mod codes for class-restricted base items name property codes.
  • itemstatcost — every statN slot in this file resolves to a stat row here.
  • skills — referenced indirectly through stat parameter values that carry skill IDs for the skill-mod functions (9, 11, 19, 22).