Rarities & affixes
Rarity is the power dial — affix counts, sockets, multipliers, and roll quality. Affixes are the vocabulary of bonuses, picked by weight under strict no-duplicate rules.
What a rarity controls
A RarityDefinition bundles every per-tier knob. The example set ships six: Common, Magic, Rare, Epic, Legendary, Unique.
| Field | Type | Description |
|---|---|---|
| Sort Order | int | Lower = more common. Used for minimum-rarity gating and UI ordering — not a drop probability. |
| Display Color / Border Sprite | Color / Sprite | Card tinting and border art. |
| Min/Max Random Affixes | int | How many random affixes an item of this tier rolls. |
| Min/Max Sockets | int | Socket count range. |
| Stat Value Multiplier | float | Scales every rolled stat value on the item. |
| Minimum Roll Quality | float 0–1 | Floor for the roll lerp — a 0.5 means every stat lands in the top half of its range. |
| Sell Value / Durability Multiplier | float | Economy and durability scaling. |
| Can/Requires Legendary Effect | bool | Whether template legendary effects attach — and for Unique-style tiers, whether one is expected (and the unique name pool is used). |
| Max Name Affix Count | int 0–2 | 0 = bare name, 1 = prefix, 2 = prefix + suffix in the generated name. |
GeneratorSettings.AvailableRarities looks like this:using ItemGeneratorSystem; using UnityEngine; public static class RarityRoller { // Pair each rarity with your drop weight, heaviest first. static readonly (string name, float weight)[] table = { ("Common", 60f), ("Magic", 25f), ("Rare", 10f), ("Epic", 4f), ("Legendary", 1f) }; public static RarityDefinition Roll(GeneratorSettings settings) { float total = 0f; foreach (var e in table) total += e.weight; float pick = Random.value * total; foreach (var e in table) { if ((pick -= e.weight) <= 0f) return System.Array.Find(settings.AvailableRarities, r => r.RarityName == e.name); } return settings.AvailableRarities[0]; } }
Anatomy of an affix
An AffixDefinition grants one or more stat rolls and declares where it may appear:
| Field | Type | Description |
|---|---|---|
| Affix Name / Affix Type | string / Prefix|Suffix | Display metadata for your tooltips (item names come from the separate name-generation pools, not from affix names). |
| Stat Grants | StatPoolEntry[] | The stats + ranges this affix rolls. Every entry rolls. |
| Weight | float | Selection weight — heavier affixes appear more often. |
| Minimum Rarity / Allowed Rarities | gate | Tier gating: an explicit allowed-list wins; otherwise anything at or above the minimum qualifies. |
| Restricted To Types / Sub-Types | gate | Limit an affix to weapons, rings, staves… |
| Exclusion Group | string | At most one affix per group per item — e.g. one “damage conversion” family member. |
The example content's 25 affixes show the patterns: 9 prefixes like Sharp and Vampiric, 7 suffixes like of Power and of the Fortress, four Magic-exclusive enchantments, and four Common-only Minor affixes that keep low-tier loot interesting without power creep.
How rolling works
count = random in [rarity.MinRandomAffixes .. rarity.MaxRandomAffixes]
filter = tier gate ∩ type/sub-type gate ∩ granted stats ⊆ allowed stats
pick = weighted selection, without replacement, skipping:
· any affix whose ExclusionGroup is already used
· any affix granting a stat the item already has
(base stats, implicits, forced affixes, earlier picks)
roll = per stat: quality = minQuality + rand × (1 − minQuality)
value = lerp(min, max, quality) × rarity.StatValueMultiplier
Flat → whole numbers; %/multiplier → 3 decimals; never a dead +0Template forced affixes are rolled first and count against exclusion groups and stat uniqueness, so random picks never duplicate a signature stat. If the eligible pool runs dry before the rarity's minimum is met, the item still generates — with a console warning naming the rarity contract it couldn't meet.
