Finding items and vendor stock

Finding items and vendor stock

Every sword you've ever looted has a paper trail. We dumped all of them — 75,809 edges linking items to whatever can grant them — and read the code that rolls the drops.

The provenance census

SourceEdgesWhat it means
Units26,995carried/dropped by creatures
Dungeon & area loot tables25,556containers and placeables
Shared vendor tables9,878shop stock
Trash-loot settings3,403auto-filled junk
Etudes / dialog cues / answers3,582story grants
Buffs, abilities, crafting2,592everything else

Story grants are bigger than they feel: 3,582 items arrive through dialog and story state — quest rewards live in conversations, not in the loot system at all.

How a container rolls its contents

GenerateItems() runs every loot component in order, and there are exactly three kinds (loot-vendor-math.json):

  • Fixed pack — adds exactly m_Count of an item or table. No roll.
  • Variable pack — count is a uniform integer in [CountFrom, CountTo], inclusive. Your two-arrows-vs-eleven-arrows roll.
  • Weighted pick — one roll of uniform[0, sumWeights), walked down cumulative weights; adds exactly 1 of the winner.

The fourth kind isn't a component but a recursion: a loot entry can point at another loot table, once per count — tables compose into trees, which is why a simple crate can be secretly rolling against a dungeon-level table that rolls again.

Trash loot is priced, not listed: FillLootComponent keeps adding uniform-random trash items until the pile reaches its target approximate price. That's why every bandit's pouch is worth about the same.

Vendor math

sellPrice = round0.5(cost × SellModifier × discount × vendor.SellPriceModifier)
buyPrice  = round0.5(cost × discount × vendor.PriceModifier)

Three things the UI never says:

  • Selling outside the trade window pays less — the junk-sale path skips the vendor's own modifier entirely.
  • Discounts are injectable: kingdom buffs and etudes can attach per-vendor, per-item-type discounts through a generic action wrapper.
  • Shop stock generates once and persists. A shared vendor table's GenerateItems() result is saved with your game; restocking only ever adds newly unlocked fixed items (GetLootDifference). Sold out of the unique cloak? It stays sold out.

Trace any specific item's sources from its page in our Items section.