DayZ db/types.xml
The per-item central economy table: one <type> entry per classname, ~1,970
of them per map. Vanilla source: BohemiaInteractive/DayZ-Central-Economy.
Unlike globals.xml, this file is different on every map. Chernarus,
Livonia and Sakhal ship different entries, different value tiers and different
nominals. Diff against the matching map or you will generate false positives
on every line.
These servers are Xbox on Nitrado. No mods; init.c is inert. See the
dayz-cfggameplay skill for what that rules out.
Never answer from memory
Every element name, unit, default and tier list must come from
references/keys.md. An agent asked ten routine questions about this file
answered fluently and was wrong in ways that would have shipped:
- Asked which
value tiers Livonia has, it said "Tier1 through Tier4…
possibly Tier5." Livonia ships Tier1–Tier3 only. A Tier4 copied from
a Chernarus entry is silently ignored and the item never spawns.
- It invented a
vehiclesparts category. The real one is lootdispatch.
- It described
cost as spawn priority and omitted that the engine uses the
same number for cleanup priority.
- It called
<category> and <usage> effectively mandatory. 358 vanilla
Livonia types have no <category> at all.
The fluency is the problem. Nothing above reads as a guess.
The rule that matters most
Total nominal across the file is a server performance budget, not a loot
dial. Every point of nominal is an object the server may have to track.
This is the operator's stated reason for how Clan Wars is tuned, and it is the
frame to bring to any "can we add more X" request. Clan Wars holds 26% fewer
objects than vanilla Livonia while carrying 26% more weapons:
|
vanilla Livonia |
Clan Wars |
|
| Total nominal |
13,468 |
9,976 |
−26% |
| Active types (nominal > 0) |
1,021 |
604 |
−41% |
| weapons |
2,730 |
3,435 |
+26% |
| clothes |
3,979 |
1,997 |
−50% |
| food |
562 |
119 |
−79% |
| tools |
4,156 |
3,078 |
−26% |
"The goal is for the server to feel like it has boosted loot, while actually
having less total items than vanilla. This is strictly a server performance
call." — operator
The move is concentration, not addition: fewer distinct types, higher
nominal each. Raising a weapon's nominal is paid for by cutting clothing
variants nobody looks at. scripts/validate.py --budget prints this table for
any mission; run it before and after any nominal change.
Things that are not what they look like
count_in_cargo="1" will make an item stop spawning. Hoarded copies
count toward nominal, so once players stockpile it the CE sees the target
met and places no more in the world. This is the real cause of "the item
vanished from loot after a few weeks." Operator-confirmed on these
servers — not folklore. Same applies to count_in_hoarder and
count_in_player. See references/keys.md.
crafted="1" stops an item spawning entirely. It marks the type
craft-only and the CE will not place it, whatever nominal says.
Operator-confirmed. Vanilla agrees: every Chernarus type carrying the
flag sits at nominal 0. Livonia has one that does not — Firewood,
crafted="1" with a non-zero nominal, so it never spawns. Counts in
references/keys.md.
quantmin/quantmax are percentages, not counts. 100 means a full
magazine, not 100 rounds. [source] CEItemProfile::GetQuantityMin()
returns a float 0.0–1.0. -1 on both means "no quantity roll."
restock is not a respawn timer, it is the opposite of lifetime —
the idle period before the type is allowed to respawn once needed.
[source] centraleconomy.c:762.
cost is priority for cleanup as well as respawn. [source]
centraleconomy.c:764. Vanilla leaves it at 100 on nearly everything and
the operator has never moved it. Treat it as leave-alone.
- A type name absent from vanilla
types.xml is not invalid. Many real
classnames ship with no vanilla entry and work once added. Do not "correct"
or delete an unfamiliar name. See references/classnames.md.
cfgspawnabletypes.xml is not required for an item to spawn. It only
controls attachments and cargo. Operator-confirmed. An item with no
entry there still spawns, bare.
- A type in
cfgignorelist.xml is despawned, not merely untracked. Its
types.xml entry is dead weight whatever the values say. Clan Wars ignores
all four PartyTent* deliberately — they are a known source of server
lag and are not allowed to exist — while types.xml still carries entries
for them. That overlap is intentional; leave it.
lifetime is clamped to [3, 316224000] (3 seconds to 10 years).
[source] centraleconomy.c:314. lifetime 0 appears only on static map
objects — Land_*_DE and StaticObj_*_DE wrecks, containers and
roadblocks. Per-map counts in references/keys.md.
lootdispatch is a category, not a mechanism you configure here. 174
vanilla Livonia types use it, all vehicle doors and panels. It is how parts
reach <dispatch> proxies on wrecks — see
dayz-globals/references/cross-file.md.
- Vanilla violates its own invariants.
Crossbow_Black ships
quantmin 80 / quantmax 0 on Livonia and Sakhal; BatteryCharger ships
min 18 > nominal 13 on Sakhal. These are Bohemia's bugs, present
upstream. Never treat a shipped vanilla file as a schema reference.
Routing
| Task |
Read |
| What an element means, its unit, its default |
references/keys.md |
| Which files a change here also touches |
references/cross-file.md |
| Adding an item vanilla does not list |
references/classnames.md |
| Checking a file before shipping |
scripts/validate.py |
scripts/validate.py <mission>/db/types.xml # errors, warnings, notes
scripts/validate.py --budget <mission>/db/types.xml # total nominal by category
scripts/validate.py --verbose <mission>/db/types.xml # + normal-in-vanilla notes
It checks, in this order: XML parse and root element; the seven required
scalars, <flags> attributes and duplicate names; crafted vs nominal,
min vs nominal, the quantity pair, the lifetime clamp; every
usage/value/tag/category name against cfglimitsdefinition.xml; and
then cfgignorelist.xml, cfgspawnabletypes.xml and db/events.xml. It does
not check anything in mapgroupproto.xml, so it cannot tell you a
declared usage matches no real loot point — and it cannot check a classname.
It stays silent on a coherent config: vanilla Chernarus reports OK and
nothing else. It does not flag a type name vanilla omits, because unknown
is not invalid, and it downgrades Bohemia's three shipped defects to a tagged
warning so an untouched mission still exits 0.
Paths are relative to this skill's directory; run it from there or use an
absolute path.
Diagnosing "the item does not spawn"
In the order these actually bite, not the order they seem likely:
- Wrong tier for the map.
Tier4 on Livonia is the single most common
silent kill. Livonia is Tier1–3; Chernarus and Sakhal are Tier1–4.
nominal is 0. The standard way to disable an item — check it was not
already disabled on purpose.
- A
usage, value, tag or category name not in
cfglimitsdefinition.xml for that map. Silently dropped.
crafted="1". Craft-only; the CE will not place it at all.
- The type is in
cfgignorelist.xml. It will be despawned on sight.
- No
<usage> at all, on an item you expect in building loot. It can
then only arrive as cargo, via an event, or from cfgspawnabletypes.xml.
count_in_* satisfaction — see the trap above. Suspect this when the
item used to spawn.
- Classname is genuinely wrong. Real, but rarer than it feels, and you
cannot confirm it from any file in the tree — see
references/classnames.md.
scripts/validate.py catches 1–6 mechanically.
Deploying and verifying a change
Deploying the file and waiting for the next restart is enough.
[operator] No manual restart, no storage wipe. Servers restart every 2
hours, so that is the worst-case wait before a change is live. (On Clan Wars
the deploy trigger is publishing a GitHub Release — a tag alone ships
nothing.)
How fast it becomes visible depends on which way you moved the number.
[operator]
- Raising
nominal shows up quickly. The CE has a deficit to fill and
spawns into it.
- Lowering
nominal shows up slowly. It stops new placement; the surplus
has to age out through each copy's lifetime first, and anything in
persistent storage never ages out at all. Same mechanism as nominal 0.
So do not judge a reduction after one restart. An agent that checks too
early will conclude the edit failed and start "fixing" a config that is
working. If a cut must take effect now, the lever is cfgignorelist.xml,
not a smaller nominal.
Diagnosing "the item will not go away"
Setting nominal 0 stops new placement. It does not remove what already
exists — those copies run out their lifetime first, and persistent storage
does not expire on a restart. To remove an item now, add it to
cfgignorelist.xml; that despawns it.
House conventions
Splice, never parse-and-reserialize. These files have meaningful key
order and indentation, and Clan Wars' was hand-edited item by item through
Claude Code — there is no generator to re-run and the file is the source
of truth. A round trip makes the diff unreviewable and destroys the only
record of intent.
For one or a few types, edit the <type> block in place with a targeted
string replacement. For a bulk change across many types — the realistic
case, e.g. the 22 base-part lifetimes — scope the edit to the types you
mean by name, rather than pattern-matching a value across the file:
import re, pathlib
BASE = ["Barrel_Blue", "CarTent", "Fence", "LargeTent", "Watchtower"] # etc.
p = pathlib.Path("db/types.xml"); s = p.read_text()
for name in BASE:
block = re.search(rf'(<type name="{re.escape(name)}">.*?</type>)', s, re.S)
assert block, name # fail loudly on a typo'd name
new = re.sub(r"<lifetime>\d+</lifetime>",
"<lifetime>604800</lifetime>", block.group(1))
s = s.replace(block.group(1), new)
p.write_text(s)
A blind sed s/3888000/604800/g would also hit any unrelated type that
happens to share the value. Then read the values back and diff — a key
at the wrong nesting depth still parses, and git diff --stat should show
exactly the line count you intended.
Keep the element order vanilla uses: nominal, lifetime, restock,
min, quantmin, quantmax, cost, flags, then category, usage,
value, tag.
One Life tracks upstream master but is deliberately frozen at the
vanilla reset. Upstream has since moved (mossy ghillies enabled, Tier4
added to PoliceVest, deloot flag changes). Flag the gap so it is
visible; never auto-apply it. Adopting an upstream value is an operator
decision each time.
State the before and after in the commit body, per value. These are
economy numbers someone will diff later.
Known live-server state
Recorded so it is not "fixed" by accident. See also the root CLAUDE.md.
- One Life base part lifetimes are vanilla
3888000 (45 days) on all
three maps, while globals.xml sets FlagRefreshMaxDuration to 7 days.
The flag only postpones these lifetimes, so the shortened refresh is close
to inert. The fix lives in this file. Offer it; do not apply it unasked.
Clan Wars already did exactly this — 35 types at 604800.
- Clan Wars' broad
7200 lifetime is not tied to the 2-hour restart
cadence. It looks like it is and it is not — the operator confirmed there
is no such rationale. Do not repeat that story.
- Clan Wars sets
quantmin/quantmax to 100/100 on all 1,979 types,
including items with no quantity at all, where vanilla uses -1. This is a
deliberate blanket pass and has caused no problems. Do not "clean it up."
1---2name: dayz-types3description: Use when working with a DayZ server's db/types.xml or per-item central economy tuning — how much of an item exists, how long it survives, where and in which tier it spawns, disabling or adding an item, base and storage decay, loot budget and server performance — or when an item does not spawn, will not stop spawning, or vanished from loot over time.4---56# DayZ db/types.xml78The per-item central economy table: one `<type>` entry per classname, ~1,9709of them per map. Vanilla source: `BohemiaInteractive/DayZ-Central-Economy`.1011**Unlike `globals.xml`, this file is different on every map.** Chernarus,12Livonia and Sakhal ship different entries, different value tiers and different13nominals. Diff against the matching map or you will generate false positives14on every line.1516**These servers are Xbox on Nitrado.** No mods; `init.c` is inert. See the17`dayz-cfggameplay` skill for what that rules out.1819## Never answer from memory2021Every element name, unit, default and tier list **must** come from22`references/keys.md`. An agent asked ten routine questions about this file23answered fluently and was wrong in ways that would have shipped:2425- Asked which `value` tiers Livonia has, it said **"Tier1 through Tier4…26 possibly Tier5."** Livonia ships **Tier1–Tier3 only**. A `Tier4` copied from27 a Chernarus entry is silently ignored and the item never spawns.28- It invented a `vehiclesparts` category. The real one is `lootdispatch`.29- It described `cost` as spawn priority and omitted that the engine uses the30 same number for **cleanup** priority.31- It called `<category>` and `<usage>` effectively mandatory. **358 vanilla32 Livonia types have no `<category>` at all.**3334The fluency is the problem. Nothing above reads as a guess.3536## The rule that matters most3738**Total `nominal` across the file is a server performance budget, not a loot39dial.** Every point of nominal is an object the server may have to track.4041This is the operator's stated reason for how Clan Wars is tuned, and it is the42frame to bring to any "can we add more X" request. Clan Wars holds **26% fewer43objects than vanilla Livonia while carrying 26% more weapons**:4445| | vanilla Livonia | Clan Wars | |46|---|---|---|---|47| **Total nominal** | 13,468 | **9,976** | **−26%** |48| Active types (nominal > 0) | 1,021 | 604 | −41% |49| weapons | 2,730 | **3,435** | **+26%** |50| clothes | 3,979 | 1,997 | −50% |51| food | 562 | 119 | −79% |52| tools | 4,156 | 3,078 | −26% |5354> "The goal is for the server to feel like it has boosted loot, while actually55> having less total items than vanilla. This is strictly a server performance56> call." — operator5758The move is **concentration, not addition**: fewer distinct types, higher59nominal each. Raising a weapon's nominal is paid for by cutting clothing60variants nobody looks at. `scripts/validate.py --budget` prints this table for61any mission; run it before and after any nominal change.6263## Things that are not what they look like6465- **`count_in_cargo="1"` will make an item stop spawning.** Hoarded copies66 count toward `nominal`, so once players stockpile it the CE sees the target67 met and places no more in the world. This is the real cause of "the item68 vanished from loot after a few weeks." **Operator-confirmed on these69 servers** — not folklore. Same applies to `count_in_hoarder` and70 `count_in_player`. See `references/keys.md`.71- **`crafted="1"` stops an item spawning entirely.** It marks the type72 craft-only and the CE will not place it, whatever `nominal` says.73 **Operator-confirmed.** Vanilla agrees: every Chernarus type carrying the74 flag sits at `nominal 0`. Livonia has one that does not — `Firewood`,75 `crafted="1"` with a non-zero nominal, so it never spawns. Counts in76 `references/keys.md`.77- **`quantmin`/`quantmax` are percentages, not counts.** `100` means a full78 magazine, not 100 rounds. **[source]** `CEItemProfile::GetQuantityMin()`79 returns a float `0.0`–`1.0`. `-1` on both means "no quantity roll."80- **`restock` is not a respawn timer, it is the opposite of `lifetime`** —81 the idle period before the type is *allowed* to respawn once needed.82 **[source]** `centraleconomy.c:762`.83- **`cost` is priority for cleanup as well as respawn.** **[source]**84 `centraleconomy.c:764`. Vanilla leaves it at `100` on nearly everything and85 the operator has never moved it. Treat it as leave-alone.86- **A type name absent from vanilla `types.xml` is not invalid.** Many real87 classnames ship with no vanilla entry and work once added. Do not "correct"88 or delete an unfamiliar name. See `references/classnames.md`.89- **`cfgspawnabletypes.xml` is not required for an item to spawn.** It only90 controls attachments and cargo. **Operator-confirmed.** An item with no91 entry there still spawns, bare.92- **A type in `cfgignorelist.xml` is despawned, not merely untracked.** Its93 `types.xml` entry is dead weight whatever the values say. Clan Wars ignores94 all four `PartyTent*` deliberately — **they are a known source of server95 lag and are not allowed to exist** — while `types.xml` still carries entries96 for them. That overlap is intentional; leave it.97- **`lifetime` is clamped to `[3, 316224000]`** (3 seconds to 10 years).98 **[source]** `centraleconomy.c:314`. `lifetime 0` appears only on static map99 objects — `Land_*_DE` and `StaticObj_*_DE` wrecks, containers and100 roadblocks. Per-map counts in `references/keys.md`.101- **`lootdispatch` is a category, not a mechanism you configure here.** 174102 vanilla Livonia types use it, all vehicle doors and panels. It is how parts103 reach `<dispatch>` proxies on wrecks — see104 `dayz-globals/references/cross-file.md`.105- **Vanilla violates its own invariants.** `Crossbow_Black` ships106 `quantmin 80` / `quantmax 0` on Livonia and Sakhal; `BatteryCharger` ships107 `min 18` > `nominal 13` on Sakhal. These are Bohemia's bugs, present108 upstream. Never treat a shipped vanilla file as a schema reference.109110## Routing111112| Task | Read |113|---|---|114| What an element means, its unit, its default | `references/keys.md` |115| Which files a change here also touches | `references/cross-file.md` |116| Adding an item vanilla does not list | `references/classnames.md` |117| Checking a file before shipping | `scripts/validate.py` |118119```sh120scripts/validate.py <mission>/db/types.xml # errors, warnings, notes121scripts/validate.py --budget <mission>/db/types.xml # total nominal by category122scripts/validate.py --verbose <mission>/db/types.xml # + normal-in-vanilla notes123```124125It checks, in this order: XML parse and root element; the seven required126scalars, `<flags>` attributes and duplicate names; `crafted` vs `nominal`,127`min` vs `nominal`, the quantity pair, the lifetime clamp; every128`usage`/`value`/`tag`/`category` name against `cfglimitsdefinition.xml`; and129then `cfgignorelist.xml`, `cfgspawnabletypes.xml` and `db/events.xml`. It does130**not** check anything in `mapgroupproto.xml`, so it cannot tell you a131declared usage matches no real loot point — and it cannot check a classname.132133It stays silent on a coherent config: vanilla Chernarus reports `OK` and134nothing else. It **does not** flag a type name vanilla omits, because unknown135is not invalid, and it downgrades Bohemia's three shipped defects to a tagged136warning so an untouched mission still exits 0.137138Paths are relative to this skill's directory; run it from there or use an139absolute path.140141## Diagnosing "the item does not spawn"142143In the order these actually bite, not the order they seem likely:1441451. **Wrong tier for the map.** `Tier4` on Livonia is the single most common146 silent kill. Livonia is Tier1–3; Chernarus and Sakhal are Tier1–4.1472. **`nominal` is 0.** The standard way to disable an item — check it was not148 already disabled on purpose.1493. **A `usage`, `value`, `tag` or `category` name not in150 `cfglimitsdefinition.xml`** for that map. Silently dropped.1514. **`crafted="1"`.** Craft-only; the CE will not place it at all.1525. **The type is in `cfgignorelist.xml`.** It will be despawned on sight.1536. **No `<usage>` at all**, on an item you expect in building loot. It can154 then only arrive as cargo, via an event, or from `cfgspawnabletypes.xml`.1557. **`count_in_*` satisfaction** — see the trap above. Suspect this when the156 item *used to* spawn.1578. **Classname is genuinely wrong.** Real, but rarer than it feels, and you158 cannot confirm it from any file in the tree — see159 `references/classnames.md`.160161`scripts/validate.py` catches 1–6 mechanically.162163## Deploying and verifying a change164165**Deploying the file and waiting for the next restart is enough.**166**[operator]** No manual restart, no storage wipe. Servers restart every 2167hours, so that is the worst-case wait before a change is live. (On Clan Wars168the deploy trigger is *publishing a GitHub Release* — a tag alone ships169nothing.)170171**How fast it becomes visible depends on which way you moved the number.**172**[operator]**173174- **Raising `nominal` shows up quickly.** The CE has a deficit to fill and175 spawns into it.176- **Lowering `nominal` shows up slowly.** It stops new placement; the surplus177 has to age out through each copy's `lifetime` first, and anything in178 persistent storage never ages out at all. Same mechanism as `nominal 0`.179180**So do not judge a reduction after one restart.** An agent that checks too181early will conclude the edit failed and start "fixing" a config that is182working. If a cut must take effect now, the lever is `cfgignorelist.xml`,183not a smaller nominal.184185## Diagnosing "the item will not go away"186187Setting `nominal 0` stops *new* placement. It does not remove what already188exists — those copies run out their `lifetime` first, and persistent storage189does not expire on a restart. To remove an item now, add it to190`cfgignorelist.xml`; that despawns it.191192## House conventions193194- **Splice, never parse-and-reserialize.** These files have meaningful key195 order and indentation, and Clan Wars' was hand-edited item by item through196 Claude Code — **there is no generator to re-run and the file is the source197 of truth**. A round trip makes the diff unreviewable and destroys the only198 record of intent.199200 For one or a few types, edit the `<type>` block in place with a targeted201 string replacement. For a bulk change across many types — the realistic202 case, e.g. the 22 base-part lifetimes — scope the edit to the types you203 mean by name, rather than pattern-matching a value across the file:204205 ```python206 import re, pathlib207 BASE = ["Barrel_Blue", "CarTent", "Fence", "LargeTent", "Watchtower"] # etc.208 p = pathlib.Path("db/types.xml"); s = p.read_text()209 for name in BASE:210 block = re.search(rf'(<type name="{re.escape(name)}">.*?</type>)', s, re.S)211 assert block, name # fail loudly on a typo'd name212 new = re.sub(r"<lifetime>\d+</lifetime>",213 "<lifetime>604800</lifetime>", block.group(1))214 s = s.replace(block.group(1), new)215 p.write_text(s)216 ```217218 A blind `sed s/3888000/604800/g` would also hit any unrelated type that219 happens to share the value. **Then read the values back** and diff — a key220 at the wrong nesting depth still parses, and `git diff --stat` should show221 exactly the line count you intended.222- **Keep the element order** vanilla uses: `nominal`, `lifetime`, `restock`,223 `min`, `quantmin`, `quantmax`, `cost`, `flags`, then `category`, `usage`,224 `value`, `tag`.225- **One Life tracks upstream `master` but is deliberately frozen** at the226 vanilla reset. Upstream has since moved (mossy ghillies enabled, `Tier4`227 added to `PoliceVest`, `deloot` flag changes). **Flag the gap so it is228 visible; never auto-apply it.** Adopting an upstream value is an operator229 decision each time.230- **State the before and after in the commit body**, per value. These are231 economy numbers someone will diff later.232233## Known live-server state234235Recorded so it is not "fixed" by accident. See also the root `CLAUDE.md`.236237- **One Life base part lifetimes are vanilla `3888000` (45 days)** on all238 three maps, while `globals.xml` sets `FlagRefreshMaxDuration` to 7 days.239 The flag only postpones these lifetimes, so the shortened refresh is close240 to inert. **The fix lives in this file.** Offer it; do not apply it unasked.241 Clan Wars already did exactly this — 35 types at `604800`.242- **Clan Wars' broad `7200` lifetime is not tied to the 2-hour restart243 cadence.** It looks like it is and it is not — the operator confirmed there244 is no such rationale. Do not repeat that story.245- **Clan Wars sets `quantmin`/`quantmax` to `100`/`100` on all 1,979 types**,246 including items with no quantity at all, where vanilla uses `-1`. This is a247 deliberate blanket pass and has caused no problems. Do not "clean it up."