Updating
Which tCAD files are yours to carry forward, which are replaced outright, and how to reword any string in the CAD without losing the change on the next release.
tCAD is an escrowed resource. Four files are yours to edit: they ship readable rather than encrypted, so you can write in them. They are also shipped — a release contains a copy of each — so the release archive carries a current version of every one of them, and it is yours to merge your changes forward into.
Knowing which is which is the whole of updating safely, so it is one table.
What is yours, and what is replaced
escrow_ignore means "ships readable". It does not mean "left alone by an update" — the archive contains these files too.
| File | Yours to edit? | What to do on an update |
|---|---|---|
config.lua | Yes | Keep yours; merge in any new keys the release note names |
config/sv_functions.lua | Yes | Keep yours; merge in any new hook you want |
config/cl_functions.lua | Yes | Keep yours; merge in any new hook you want |
locales.json | Yes | Keep yours — only the keys you reworded need to be in it |
shared/locales.default.json | ⛔ No | Take the new one. locales.json layers over it, so a string you did not reword updates itself |
| Everything else | No | Take the new one |
data.json / data.json.bak | Yours, by not being shipped at all | Not in the archive — but see the warning below |
Release notes call out any config change, which is the signal to re-read this table rather than something tCAD reports at runtime.
Updating
- Back up
data.jsonanddata.json.bakif you are on the JSON backend, or take a database dump if you are not. - Put your four files somewhere safe, extract the new release over the resource folder, then merge your copies back in. Keep the folder named
tCAD— the name appears in escrow paths. - Restart the resource.
- Run
tcad_configandtcad_hooksin the server console.
Step 4 is the one worth not skipping. The copies you merged forward are as old as the day you wrote them, and the product code that reads them is not — so tcad_hooks carries an expected version and a signature table and names a hook that has fallen out of step, rather than letting it fail as a nil call mid-shift.
A hook gains a field, never an argument, precisely so that this does not happen. But a release note telling you a hook gained a field is worth reading.
Rewording anything in the CAD
Every string in the panel and in the server's messages comes from a table of 467 strings across 22 sections. You override the ones you want in locales.json, and the rest keep arriving from the shipped file.
{
"header": {
"title": "LSPD DISPATCH"
},
"duty": {
"go_on": "Sign on"
}
}Put only the keys you are changing there, in the same section.key shape as shared/locales.default.json. Keys beginning with an underscore are never looked up, so the _README key in the shipped template can stay.
⛔ Do not edit shared/locales.default.json
Key by key and not section by section, specifically so that a two-year-old detail section in your file — missing most of the keys the current one has — still works: your keys win, and every key you have not overridden comes from the shipped table.
A missing key shows as section.key
That is deliberate. A literal detail.timeline on screen is an unmissable "this key is not in the table"; blanking it would ship an empty label nobody ever reports. If you see one, you have a typo in your locales.json or you are overriding a key that no longer exists.
To check what loaded:
tcad_config
reports the string count and the section names.
⛔ What must never go in a string
Placeholders
A string may carry {placeholders}, filled at runtime:
{ "notices": { "call_cancelled": "Call {callNumber} cancelled by {actor}" } }Keep the placeholder names exactly as the shipped string has them — they are what the code fills. Rewording the sentence around them is the point; renaming one leaves it unfilled.
A CAD address is free text, so substitution is done with a function rather than a replacement string. That means a % or a %1 in a real address cannot corrupt the line — but it also means you should not try to use capture syntax in your own strings, because there is nothing interpreting it.
Version checking
tCAD reports its own version against the published release channel at startup, in the server console. The version it reports is read from the manifest, so it is always the number you see in your resource list.
It reports no counts of anything — not calls, not civilians, not warrants. A record count is the kind of number that ends up in a screenshot pasted into a support channel, and there is nothing worth the line.
Was this page helpful?
TIMMYG Studios