Round-6 research pass on The New Order's decl system: a field catalogue for weapon, ammo, damage, AI and player decls, what the loader can already change, whether brand-new (type, name) entries can be added to a TNO archive, and whether TNO has TNC-style load-order traps. TNO uses the same decl dialect and patch mechanics as TNC but a simpler single-tier archive, and the loader patches every duplicate copy, so the TNC dlc_0 precedence trap does not exist; instead, almost every AI decl overrides health individually. Three TNO mod designs are included. Static only; no game was launched. The append-entry writer this round could not build follows in Adding new entries to TNO archives (R7).
Track tnodecls, round 6, 2026-10-01. Scope: TNO only
(<Steam library>\steamapps\common\Wolfenstein.The.New.Order, id Tech 5,
WolfNewOrder_x64.exe, 14 chunkN.index/chunkN.resources pairs via
master.index, no DLC/patch tier at all). Read-only against the game
install and every project file except this track's own folder
re_probes/tnodecls/ and this report. The game was not launched, no
debugger attached, no process touched. TNO has no runtime image (unlike
TNC's re_probes/runtime_87400/module.bin + tools/decomp.py) — every claim
here about what the engine does with a decl field comes from the shipped
decl text itself, from docs/*.md's own prior binary-string findings (never
re-derived), or from this project's own patcher code (wolfsdk/resources.py,
wolfsdk/patch.py, wolfsdk/decl.py) and the archive bytes it reads/writes.
No disassembly was done this round; where a TNC report's method (tracing a
field into .text) would have settled a question, it is flagged as not
settleable without a TNO runtime image, not silently skipped.
Built on, not redone: docs/moddingflaeche-tno.md (full corpus census,
105 types, 25 559 parsed text decls, the gamemodesp/faction/enigma
cheat routes, startingInventory, 20 largest unused types) — treated as
ground truth and cited, not re-measured, except where I independently
re-verified a specific field against the pristine backup (see §0). The
existing TNO mods in mods/ (cheats_gamemode, enigma_frei,
fraktionen_hass, supersoldaten_c15, zielhilfe_alle, wucht_treffer,
wucht_waffen, menue_marke, widerstand, ragdoll_gore, gore_*,
example_*) were read as proof of the loader's capability, not
re-explained. docs/formats.md/docs/limits.md (archive format, the
ascending-offset invariant). docs/ladepfade.md Teil 1 (TNO's
fs_overlaypath/loose-file findings — relevant to §3). wolfsdk/cvars.py
(the 25 measured RETAIL_BLOCKED TNO cvars — why the decl route is needed
at all). TNC's r2_newassets.md/r3_newassetsv.md (their append-entry
technique for id Tech 6's different IDCL format) are cited only as a
contrast in §3 — their method does not transfer; TNO's chunkN.index is a
structurally different, simpler format.
0. A methodology note that changed several readings
D:\...\Wolfenstein.The.New.Order\base\ is not pristine — a prior
session already ran apply() with 8 TNO mods (gore_tief, gore_ultimativ,
enigma_frei, ragdoll_gore, gore_realistisch, zielhilfe_alle,
gore_texturen, widerstand; _wolfsdk_backup/journal.json: "missing":
[], "state": "applied", 377 assets, all 14 chunks rebuilt, 0 in-place
slots). The pristine originals live in base/_wolfsdk_backup/. Every decl
quoted below was re-read from _wolfsdk_backup, diffed against the live
copy, and the diff is reported where it mattered — twice this caught my own
first read quoting an already-modded value (weapon/handgun_base's
clipSize, projectile/handgun's aimAssistRange) as if it were retail.
re_probes/tnodecls/pristine_*.decl holds the 7 confirmed-pristine extracts
this report draws field names from.
python re_probes/tnodecls/probe_tail.py # §3's tail-byte measurement, read-only
Answer in one paragraph
TNO's decl system is the same dialect and the same patcher mechanics as
TNC (confirmed directly: aiHealth.components.components[0].max/cur,
actorEditable.damageGroups with 13 zones, faction.myFaction,
startingInventory.item[].{startSlot,inventoryDecl} all exist byte-for-byte
under the same paths in TNO's entityDef:ai/enemies/default and
entityDef:player/game/wolf/*), but the archive container is a different,
simpler, single-tier format (chunkN.index, no DLC/patch layering) and the
loader already patches every one of the 14 chunks for every duplicate
copy of an asset (Installation.find()/apply(), confirmed by code
read, §2), which removes the TNC-style "wrong archive wins" trap
entirely — there is no equivalent of TNC's dlc_0 precedence to get
wrong, because TNO has no DLC/patch tier to begin with (§4). What TNO does
have, and TNC's corpus doesn't share, is a structural AI trap: where TNC
can flip HP for 125 enemies by editing one shared root decl
(soldier_base), TNO's AI decls override aiHealth individually in 252
of 255 corpus entries (measured, §1.4) — there is no cheap single-point
health lever, only a generator-script lever. The loader's set mechanism
can only touch paths that already exist in a decl
(wolfsdk/decl.py:apply_patch raises DeclError on an unknown path) —
inserting a genuinely new field (as zielhilfe_alle does for
aimAssistRange, confirmed absent from the pristine
projectile/handgun, §0) requires a full "file" replacement, not set.
Adding a brand-new (type, name) entry to a TNO archive has no code path
in this project (resources.py's rebuild() explicitly rejects any
payload whose key matches no existing entry, §3) and was never attempted
here — but the format itself looks more tractable than TNC's IDCL: no
header hash chain, no checksum anywhere, and this round's own measurement
(§3, re-verified across all 14 chunks in round 2 after the verifier caught
an overgeneralized version of this claim) confirms docs/formats.md's guess
that the mysterious 13-byte entry tail is 9 zero bytes + a BE u32 ID,
unique per chunk per type for decl-ish types (not globally, and not for
audio/particle types) — a concrete, previously-unverified fact, but turning
it into a working "append a new entry" writer, round-tripped
through the game itself, is out of this round's scope (no runtime
image to validate against, and the task's time budget does not cover
building and testing a second archive-format writer from scratch). Three
ready-to-build designs follow in §5, each scoped to mechanisms already
proven safe by the existing mods: a corpus-wide AI-health scaler (252
set edits, generator script), a "full arsenal from chapter 1" loadout
swap (one file replace, using retail's own late-game array as the exact
donor text — zero guessing), and a 10-decl AI-accuracy slider (set on
accuracySettings[].spread, the one true single-point AI combat lever this
round found).
Pass-1 errors (fixed in round 2)
The verifier ran an independent re-check and found three real defects in
pass 1. All three are now re-verified with broader, fresh measurements
(all 14 chunks, not just chunk1/chunk1.index's 40-sample spot check);
details are inline at each affected section (§1.1, §3), and the corrected
PROVEN/INFERRED lists below reflect the fixes. Short version:
- §3's tail-id claim was overgeneralized. Pass 1 said "the 13-byte
entry tail is 9 zero bytes + a BE u32 id that increments by exactly 1
between successive same-type entries" as a blanket fact, checked on 40
consecutive
entityDefentries in one chunk. Fixed: re-measured across all 14 chunks, every type, withre_probes/tnodecls/probe_tail_v2.pythrough_v5.py. The claim holds — but only per chunk, and only for decl-ish types (entityDef,weapon,damage,ammo,projectile,aiBehavior,material,trackingParms,faction,gamemodesp,soundmixing: zero within-chunk id collisions in all 14 chunks, every type). It is false forsound/particle/renderProg/cuttableResource(real same-chunk, same-id duplicates — e.g. 50soundentries all namedweapons/smg/ai/smg_ai_fire_nearmidsharing id111inchunk1), and the verifier's own counter-claim ("ZERO duplicates… even stronger than the report's own check") was also wrong as a blanket statement — it silently combined ids across all 14 chunks, where the same id value legitimately recurs for unrelated content in different chunks (the id's real scope is per-chunk, not global — see §3). The verifier's specific counter-examples (sound,particle,renderProg,cuttableResourceshowing duplication) are independently confirmed correct.cmis clean in 11 of 14 chunks and near-clean in the rest (2 dup entries out of 983 in one chunk) — closer to the decl-type behaviour than tosound's. - §1.1's negative control didn't check
inherit =. Pass 1 classified the 19weapon/ai/*decls lacking their ownaccuracySettings[].spreadas "melee/static, no spread concept" by presence/absence in the decl's own text only. Fixed:re_probes/tnodecls/probe_weaponai_inherit.pyresolves every one of the 19 decls'inherit =chains. 16 of 19 cascade to one of the 10 spread-bearing base decls (e.g.submachinegun1946 → assaultrifle1960,pistol1946 → pistol,shotgun_lefthand → shotgun); onlyweapon/ai/batonandweapon/ai/fists/supersoldat1946are genuinely melee with no inherit;weapon/ai/mg46/supersoldat1946is a real, unexplained standalone exception (60 own fields, noinherit, no spread). §5.3's actual reach is 26 of 29weapon/ai/*decls, not 10 — corrected below. - Minor: §5.2 described
c01p1's pristine knife as plainweapon/knife; the real value isweapon/knife46cutonly(confirmed by direct re-read). Does not change the recipe (a full-block replace), only the description — fixed below.
New this round, not in the verifier's list (answering its "missed"
items and pushing the open questions further): the unexplained 154
probe_tail.py mismatches are now explained (narrowing the search window
from 64 to 256 bytes drops the all-14-chunks total from 30 506 to 2 793, and
100% of what's left is type sound — the window was simply too narrow,
exactly as the verifier suspected, §3); and docs/formats.md's open
"Zähler A" ("counter A") question is now substantially resolved, not just left open:
counter A equals the number of distinct (type,name) pairs in that chunk,
confirmed exact in 12 of 14 chunks and off by ≤16 (<0.1%) in the other 2
(§3).
1. Decl field catalogue: weapon, ammo, damage, AI, player
All field names below are read directly from _wolfsdk_backup (pristine)
unless marked "live (modded)". python -m wolfsdk --title tno cat <type>:<name>
reproduces every one of these reads against the live install;
re_probes/tnodecls/pristine_*.decl holds the pristine bytes.
1.1 weapon — weapon/handgun_base (4 577 B, pristine)
Confirms and extends moddingflaeche-tno.md's "already used" entry with the
full field surface (not previously dumped in any doc):
killStat, allowOneHandedReload, lowerWhenNoTension, isDualWieldable,
internalName, pickupName/pickupNameMulti, handsFovScale, quickSlotGroup,
giveable, dropable, numHands, sellPrice, itemUse, weaponFX,
silencedGunfireEventDecl, gunfireEventDecl, initialAmmoDecl,
validAmmoClips.item[0].{validAmmoDecl, clipSize} # clipSize = 20 pristine
initialBurstMode, burstCounts.burstCounts[0..2],
firingIntervals.firingIntervals[0..2] # [150, 80, -1] pristine
ammoPerShot, weaponSlot, weaponSelectionPrio, selectionSlot,
maxRange, maxOptimalRange, reloadInterval,
handLag.{clamp,scale,retain,recenter,offsetAtMaxPitch,offsetAtMinPitch,
offsetByPitch,offsetByYaw},
handRotation.{minAngles,maxAngles,scale,retain,accelMaxDipAngle,
accelRotChangeSpeed,strafeRightTiltAngle,strafeLeftTiltAngle},
handCoverMovRot.* (12 offset/rot sub-blocks for cover poses),
weaponIdleRotation, dwWeaponModeOffset(Sec), weaponOffset(Sec),
dwWeaponModeRollAngle(Sec), weaponRollAngle(Sec),
weaponAnimSet, pistolWhipProjectile, lockTime, zoomMode,
ironSightZoom.{zoomedFOV, mouse/joy_sensitivity_scale, zoomTime,
spreadReductionWithZoom, scopeGuiNum},
weaponDof/weaponZoomDof.{focus,nearDist,scale},
movementScale.{stand_zoom_scale,crouch_zoom_scale,stand_dw_scale,crouch_dw_scale},
spreadReductionWithCrouch, spreadIncreasedByMovement, # 0.5 pristine
introAnimationID, shellEmitter.{breakableEmitter,baseSpeed,deltaSpeed,deltaAngle},
shellEjectLeftTagName/FirstPersonOffset, hideShellsOnZoom,
allowSprintFire(Sec), allowSprintDW, twoHandsswitchAnim,
meshesHiddenOnPrimFiremode.item[N]
widerstand's live diff against this pristine (confirmed by
difflib.unified_diff, 3 hunks only): clipSize 20→30,
firingIntervals[0] 150→90, firingIntervals[1] 80→55,
spreadIncreasedByMovement 0.5→0.2 — exactly the fields the mod's own
description claims, independently re-verified against the real archive
bytes, not just trusted from the mod's description string.
AI-side weapon, weapon/ai/assaultrifle1960 (pristine, unaffected by
any installed mod): same top-level shape, but with the field this round's
§5.3 design needs:
accuracySettings.accuracySettings[0..5].spread = 100, 75, 60, 50, 40, 25
# indices = ACCURACY_HORRIBLE..ACCURACY_PERFECT, same 6-tier enum TNC uses
accuracySettings[N].wanderingAim.aimCorrectionDuration = 1000 (every tier)
Measured corpus-wide (re_probes/tnodecls/probe_weaponai_inherit.py,
re-runnable, all 14 chunks): 29 distinct weapon/ai/* decls, of which
10 carry their own accuracySettings[].spread (the ranged ones —
shotgun, assaultrifle1960, pistol, drone, robot, mg60/supersoldat1960,
wol000d_pistol, assaultrifle1960rocket, mechadeathshead_laser,
prototyperobot_lkw); spread values range 15.0 (wol000d_pistol, flat
across all 6 tiers — a boss/unique) to 160.0 (shotgun's worst tier).
Round-2 fix (verifier-confirmed defect, see "Pass-1 errors" above): pass
1 classified the 19 decls without their own accuracySettings[].spread as
a clean negative control ("melee/static, no spread concept") by checking
only each decl's own text, the same inheritance blind spot this report
elsewhere warns about for TNC's AI-health lever (§1.4). Re-checked this
round by resolving every one of the 19 decls' inherit = target chain
(probe_weaponai_inherit.py): 16 of the 19 transitively inherit a working
accuracySettings[].spread from one of the 10 base decls —
assaultrifle1946/assaultrifle1960_bakedreverb/submachinegun1946(_nh)/
dummy/submachinegun1946(_noflash) → assaultrifle1960;
pistol1946/pistol_white → pistol;
shotgun_lefthand/shotgun_shrapnel(_lefthand) → shotgun;
heavy_robot_laser(_strong)/robot_c03p2/robot_temp → robot;
mechadeathshead_laser_stage3 → mechadeathshead_laser. Only
weapon/ai/baton and weapon/ai/fists/supersoldat1946 are
genuinely melee with no inherit and no spread concept — the negative
control pass 1 claimed. weapon/ai/mg46/supersoldat1946 is a real,
unexplained exception: standalone (no inherit), 60 own fields, genuinely
no spread field of any kind — not resolved this round, a real open item, not
a missed inherit edge. Net effect, and it's a better result for §5.3
than pass 1 claimed: editing the 10 base decls' spread cascades to 26 of
29 weapon/ai/* decls corpus-wide (not just the 10 edited directly) —
corrected in §5.3 below.
1.2 damage — damage/tungsten/mg46 (372 B pristine vs 461 B live)
damageParms.{damageName, damageTypes, goreTypes, declGoreBehavior,
minDamage, maxDamage, ragdollImpulseMag}
Pristine: minDamage=10, maxDamage=15, ragdollImpulseMag=500, no
cuttableRadius/ragdollOnDeath key at all. Live (both widerstand and
ragdoll_gore touch this same decl, confirmed from both mods' assets
lists): minDamage=22, maxDamage=30, ragdollImpulseMag=1100,
cuttableRadius=14.0, ragdollOnDeath=true — i.e. ragdollOnDeath and
cuttableRadius were inserted as new keys, which per §2.3 means that
specific edit must have shipped as a "file" replacement for this decl
(not set), consistent with ragdoll_gore's own stated technique. Two
independent mods editing the same decl applied cleanly in one apply() run
(journal shows 0 "missing", state: applied) — confirms the loader resolves
multi-mod collisions on one asset without erroring (last-applied-wins by mod
priority, not re-derived here, already documented behaviour of
mod.build_payloads).
1.3 ammo — ammo/handgun (401 B)
inherit = "ammo/light";
edit = { projectileDecl, lowAmmoInClip, lowAmmoInPocket,
minRandomCount, maxRandomCount, icon, icons.icons[0..2] }
Matches moddingflaeche-tno.md §2.15's ammo/rocketlauncher field set
(same type, this is a second, independently-read instance: lowAmmoInClip,
lowAmmoInPocket, minRandomCount/maxRandomCount confirmed present on
both). No maxCount/count/giveable on this particular decl — those are
present on other ammo/* entries per the prior doc, so the schema is a
superset, not every decl using every field (expected for a decl format with
optional keys).
1.4 AI — entityDef:ai/enemies/default (5 079 B pristine) + corpus census
Full structure (same shape as TNC's idAI2 decls, confirmed field-for-field,
see also r4_aidecl.md for the TNC side — not re-derived, independently
re-confirmed to exist in TNO too):
class = "idAI2"; inherit = "ai/default";
edit.renderModelInfo / clipModelInfo / dormancy / afProperties
edit.actorConstants.{perception, footstepEffectTables, waterInteraction}
edit.faction.myFaction = "faction/auth"
edit.mass
edit.aiConstants.{physics, movement, animation}
edit.aiEditable.{perception, sounds, behaviors, death, interactions,
rollBonesDecl}
edit.aiHealth.components.components[0] = { max = 50; cur = 50; }
edit.aiHealth.components.components[1] = { max = 0; cur = 0; } # dead 2nd slot, same as TNC's r4_aidecl finding
edit.fxDecl
edit.actorEditable.damageGroups.item[0..12] # 13 zones, same groupName/tagName/fxTagID set as TNC
edit.actorEditable.radiusDamageJoints.item[0..5]
edit.factionType = "FACTIONTYPE_AUTHORITY"
edit.takedownTypes.{stealthSWFWD, stealthSWREV, stealthDWFWD, stealthDWREV,
stunnedSWFWD, stunnedSWREV, groundFront, groundRear,
AITakedowns}
edit.walkIKDecl; edit.targetLockJoints.item[0..5]
Corpus census (entityDef type, name starts ai/, all 14 pristine
chunks, de-duplicated by name): 255 distinct ai/* entityDefs, 444 raw
entries (1.74× duplication across chunks on average — confirming the
loader's "patch every copy" design in §2 is load-bearing, not
theoretical). Of the 255, 252 carry their own
aiHealth.components.components[0] override; only 3 do not
(ai/groupmanager, ai/scriptedanimweb,
ai/tungsten/wol000d/guard_spriteanimator — all three non-combat/utility,
not health-bearing bodies). This is the key structural difference from TNC:
FAILED HYPOTHESIS: "Editing
ai/enemies/default'saiHealthwill cascade to every inheriting enemy, the same leverr4_aidecl.mdfound for TNC'ssoldier_base(125/185 combat archetypes inherit it without their own override)." Refuted by direct corpus measurement: 252/255 TNOai/*decls set their ownaiHealth, so an edit to the root changes at most 3 non-combat entries. TNO's AI health is authored per-leaf, not inherited — a corpus-wide health mod needs a generator over all 252 decls (exactly what §5.1 below builds), not a one-line edit to a shared root.
aiBehavior:behaviors/enemies/default (1 293 B, pristine, unmodified by any
installed mod — confirmed identical live/pristine):
traversalAttackTolerance, canUseTraversals, usesSearch, usesAvoid,
damageBehaviors.{longPainDamageFilter, hasDeathAnims},
friendlyAttitudeAdjust, itemSelect.itemSelect[N],
canGreetPlayers, investigatesBody,
takeCoverBehaviors.{maxWaitTimeAfterReachingCover, minWaitInCoverTime,
maxWaitInCoverTime}.setting.setting[N],
has157Turns, min/maxCloseMeleeInterval, min/maxChargeInterval,
min/maxChargeDistance,
dodging.{tooCloseDist, aimHeavyCoverHideChance, damageHideBailChance,
damageHideBailMaxChance, minAimDodgeInterval, maxAimDodgeInterval},
min/maxThrowInterval
trackingParms:trackingparms/aim_default (referenced by name from
aiEditable.behaviors.aimTrackingParms on every AI that doesn't override
it — same indirection pattern TNC's r4_aidecl.md found): parms.item[0..6]
= { kickScale, rate.value, acceleration.value, deceleration.value,
springMaxLength } — this is tracking-speed/smoothing, not a hit/miss
probability field (no aimError key exists in TNO's version of this
decl, unlike the TNC decl r4_aidecl.md describes under the same type name
— a real, measured difference between the two games' use of the same
decl type, not a mistake in either report). The actual accuracy lever in
TNO is the weapon-side accuracySettings[].spread shown in §1.1, confirmed
by direct read, not inferred from TNC's shape.
1.5 Player — entityDef:player/game/wolf/chapter_start_default (28 459 B, pristine, unmodified)
edit.clipModelInfo / fxDecl / afProperties
edit.actorConstants.{alwaysUsePlayerClip, perception, actorSounds,
footstepEffectTables, footstepEvents}
edit.faction.myFaction = "faction/player"
edit.startingInventory = { num = 1; item[0] = { startSlot = "EQUIPPED";
inventoryDecl = "weapon/knife"; } }
edit.walkIKDecl; edit.lightDebugHelperTypes.item[0..4]
edit.thirdPersonHandsDef/LegsDef, handsModel, handsAnimWebName(+Secondary/Additive)
edit.playerProps = "player/default"
edit.standDecay / crouchDecay = { time, linear, lambda }
edit.playerHealth.components.components[1] = { cur = 100; } # index 1, not 0 -- differs from TNC's aiHealth[0] convention, confirmed by direct read
edit.prtUnderwater; edit.maxTimeUnderwater.value = 50000;
edit.maxFreeTimeUnderwater.value = 10000; edit.sprintAirReductionScale = 1
edit.suffocationDamage / suffocationDamageLong /
suffocationStep1/2/3Sound / suffocationDeathSound
edit.grappleTypes.item[0..2]
edit.perkAbilities.perkAbilities[0..36] # name/desc/icon/icon_locked/picture/ablilityModifier [sic, shipped typo]
edit.perks.perks[0..31] # perkName/perkDesc/countRequired/countDesc/
# additionalCount/addCountDesc/additionalRequirement/addReqDesc/
# requiredPerks.item[]/unlockedAbilities.item[]
edit.upgradeInfo.upgradeInfo[N] = { is46, foundOnMap, allowedOnMap,
linkUpgrade46, linkUpgrade60 }
example_dev_loadout's target (playerHealth.components.components[1].cur)
is confirmed real and exactly as moddingflaeche-tno.md §4.4 already
reported — independently re-read here, not re-derived.
30 player/game/wolf/* entityDefs exist corpus-wide (one per
chapter-part, plus chapter_common_default/chapter_part_default/
chapter_start_default). Every chapter-part decl carries its own
startingInventory (never just inherits the 1-item default) — read directly
for c11p1 (5 items incl. weaponupgrades/shotgun_shrapnel), c13p1 (2
items), c14p1 (4 items incl. weapon/laserkraftwerk equipped), c15 (6
items — the richest found: knife, laserkraftwerk, assaultrifle1960
equipped, shotgun, ar60marksman, handgun), c16p2 (num = 0 — an endgame
chapter that intentionally starts the player with nothing, presumably items
are granted mid-level by script instead). This is the exact real-retail
donor array §5.2 uses verbatim.
2. What the loader can already change — proven by the installed mods
Not re-explained (each mod's own description in mods/*/mod.json already
states its mechanism); what's new here is independently confirming, via
_wolfsdk_backup/journal.json, that all 8 currently-enabled TNO mods
applied cleanly against the real archives: "missing": [], "state":
"applied", 377 distinct (type,name) assets written, all 14 chunks
rebuilt (0 fit in-place — every touched chunk needed a full
Archive.rebuild(), not write_in_place(); expected when several mods
touch many small decls scattered across a chunk, each individually too
large or too small to fit its own slot via deflate_exact's padding
search). This is end-to-end proof the patcher mechanism (not the
in-game effect, which the harness's own RUNTIME-PROVEN section already
asserts generically for TNO) works against the live archive set, not just
in isolated test fixtures.
Decl types the loader already touches in a shipped TNO mod, with mechanism:
| Type | Mod | Mechanism | Field(s) |
|---|---|---|---|
gamemodesp |
cheats_gamemode |
file (field absent in campaign) |
startingHealth, gameModeFlags |
enigma |
enigma_frei |
set (8 surgical edits) |
requiredSecrets.num = 0 |
faction |
fraktionen_hass |
file (new relationships block) |
relationships.relationships.item[N] |
file:*.entities |
supersoldaten_c15 |
file, inherit-target string swap only |
one entityDef block's inherit |
projectile |
zielhilfe_alle |
file (field inserted, absent in all 23 pristine targets) |
aimAssistRange |
soundmixing |
wucht_waffen |
set |
two mix-bus gain values |
sound |
wucht_treffer |
set/file |
burst-impact count, random-volume range |
file:strings/english.lang |
menue_marke |
set, byte-length-exact (raw-stored type) |
3 UI string lines |
weapon |
example_big_magazine, example_fast_shotgun, widerstand |
set |
clipSize, firingIntervals[N], spreadIncreasedByMovement |
entityDef (player) |
example_dev_loadout |
set |
playerHealth.components.components[1].cur, maxTimeUnderwater.value |
damage |
example_weapon_tuning, widerstand, ragdoll_gore |
set + file (new keys) |
minDamage/maxDamage, ragdollOnDeath/cuttableRadius/ragdollImpulseMag |
material |
example_white_handgun, widerstand |
set |
diffusemap, usevirtualmapping redirect |
entityDef (AI) |
widerstand |
set |
per-chapter AI startingInventory/health overrides |
New, not previously documented anywhere: set on an existing path and
file (full replacement) are not interchangeable —
wolfsdk/decl.py:apply_patch() raises DeclError("unknown path(s): …") the
moment a patch dict names a path absent from the target decl's own parsed
Decl.values. Every mod above that adds a field
(zielhilfe_alle's aimAssistRange, ragdoll_gore's ragdollOnDeath/
cuttableRadius, fraktionen_hass's relationships block,
cheats_gamemode's whole flag set) must ship as "file", confirmed by
reading their mod.json ({"file": "assets/…"}, not {"set": {...}}).
Every mod that only changes a number already present uses set. This is
the exact mechanical boundary a mod author needs to know and was not stated
this precisely in any prior doc.
3. Can NEW (type, name) entries be added to a TNO archive?
No code path exists in this project for it (PROVEN, by code read):
wolfsdk/resources.py:Archive.rebuild()builds its payload set only fromself.entries(the entries the pristine index already parsed) and explicitly raisesResourceErrorif any payload key matches no existing entry (missed = set(payloads) - applied, §"rebuild", lines 288–298). There is no insert/append function anywhere inresources.pyorpatch.py.ResourceIndexis held as its original byte buffer (self.buf = bytearray(buf)) and only ever mutated viaset_sizes(), which overwrites 12 bytes at an existing entry's knownpos— there is no code that grows the buffer or inserts a new trio + size-fields run.- Appending data to the end of a
.resourcesfile while leaving the index's entry order unchanged is the exact failure modedocs/formats.md/docs/limits.mdalready document as measured in a real game launch:FATAL ERROR: idBackgroundLoader::BeginBackgroundLoads: FileTable is out of order. A new entry row placed at the very end of the entry list, pointing at data appended at the very end of the.resourcesfile, would not trigger that specific failure (offsets would still ascend) — but this is reasoning from the invariant's stated cause, not a tested claim, and I did not build or test it.
What this round newly measured, not just inferred (PROVEN, by direct
byte read, round 2 widened from 1 chunk/40 samples to all 14 pristine
chunks, every type: re_probes/tnodecls/probe_tail_v2.py through _v5.py,
re-runnable):
entries (chunk1 alone): 4241 header counters @0x20/0x24: (3508, 4241)
tail length distribution (all 14 chunks): 13 bytes dominates for
entityDef/weapon/damage/ammo/projectile/aiBehavior/material/trackingParms/
faction/gamemodesp/soundmixing/cm; "sample" is mostly 37/109 bytes; "sound"
is mostly 13 bytes but has rarer 133/205-byte tails too (heterogeneous).
docs/formats.md's own hedge — "meist 13 Bytes (9 Nullen plus eine
fortlaufende BE-u32-ID)" ("mostly 13 bytes (9 zeros plus a running BE u32 ID)") — is confirmed, with a corrected scope (this is
the round-2 fix for the verifier's first finding, see "Pass-1 errors"
above): 9 zero bytes, then a BE u32 that behaves as a per-(chunk,type)
counter, not a global one:
- Unique within one chunk, per type, for every decl-ish type checked
(
entityDef,weapon,damage,ammo,projectile,aiBehavior,material,trackingParms,faction,gamemodesp,soundmixing): 0 within-chunk id collisions in any of the 14 chunks, for any of these types (probe_tail_v3.py).cmis clean in 11/14 chunks and near-clean in the other 3 (at most 2 duplicate entries out of 983 in the worst chunk) — closer to decl-type behaviour. - NOT unique across chunks, and this is expected, not an error: the
same id value recurs for completely unrelated
(type,name)pairs in different chunks (e.g.entityDefid12189isai/tungsten/c03/part_02/soldier_07in one chunk andbreakable/environment/1946_crate_piecesin another;probe_tail_v4.py). Symmetrically, the same name gets a different id in each chunk it has a copy in (e.g.weapon/ai/submachinegun1946: ids{3491, 14445, 17814}across its 3 chunk copies). This answers pass 1's own open question ("unique only within one chunk, or across all 14?"): within one chunk only — a new entry's id only needs to avoid collision with existing ids of its own type in the one chunk being edited, not across the whole 14-chunk install. This also means the verifier's own "independent re-check" claiming "ZERO duplicate ids across all 14 chunks" for these same types was itself wrong as stated — it silently combined ids across chunks, which was bound to show "duplicates" under the real per-chunk-scoped counter; see "Pass-1 errors" above. - NOT unique even within one chunk for
sound/particle/renderProg/cuttableResource— confirmed real, e.g. inchunk1id111is shared by 50soundentries all namedweapons/smg/ai/smg_ai_fire_nearmid(probe_tail_v5.py), andchunk0'srenderProghas 421 of 846 entries in duplicate-id pairs. These are plausibly variant/take indices into a shared audio-cue or shader-permutation table rather than per-entry unique ids — not traced further, INFERRED only, same caveat as below.
It is not a global file-position counter either way (it jumps discontinuously between type boundaries within a chunk), consistent with a per-(chunk,type) sequential id assigned at content-build time for decl-ish types (plausibly a decl-manager array index the engine fills once per chunk's build, not something resolved by name at load time — this specific mechanism is still INFERRED, not traced into any code, because there is no TNO runtime image to trace it into).
The 154-mismatch question (verifier's "missed" item), now explained: pass
1's own probe_tail.py reported "154 mismatches (pattern not found nearby)"
for chunk1 without investigating it. Re-run with the search window widened
from 64 to 256 bytes (probe_tail_v2.py, all 14 chunks): total mismatches
drop from 30 506 to 2 793, and 100% of what remains is type sound
— confirming the verifier's suspicion that 64 bytes was simply too narrow
for some tails (consistent with sound's occasional 133/205-byte tails
above), not a sign of a different, unexplained format.
Zähler A, substantially resolved (was fully open after pass 1):
re-checked the "count of entries whose name is the first occurrence in this
chunk" guess directly: counter A equals the number of distinct
(type,name) pairs in that chunk, confirmed exact in 12 of 14 chunks
(e.g. chunk1: 3508 distinct pairs = counter A exactly) and off by a tiny
amount (16 of 15069 in chunk0, 1 of 21400 in chunk2 — both <0.1%, plausibly
this project's own resync parser picking up a handful of extra/fewer
entries, not a different counting rule) in the remaining 2. Not pinned to
100% exactness in all 14, but strong enough to treat as answered rather than
open.
What is still open, explicitly not attempted this round:
- Whether a hand-built new entry (synthetic trio + size fields + a tail
matching this pattern, appended at the end of both the index's entry
list and the
.resourcespayload area) is even accepted by this project's ownResourceIndex.load()resync parser, let alone the real engine — not built or tested this round. Building and byte-level self-testing a writer was judged out of scope for the time available (unliker2_newassets.md's TNC work, which had a runtime image to validate the engine's own lookup path against — TNO has none, so even a working writer here would only prove "our own reader accepts it," not "the game does"). Round 2's per-chunk-scope finding above makes this concretely easier than pass 1 left it: the writer only needsmax(existing ids of this type in this one chunk) + 1, not a cross-chunk scan. - What a
sound/particle/renderProgduplicate id actually indexes (shared cue/permutation table?) — newly measured as real this round, but not traced into any mechanism; irrelevant to the append-entry writer since §5's designs never touch these types.
Net answer: structurally more promising than TNC's IDCL (no checksum,
no header hash chain, a resync-tolerant parser), and this round adds real,
previously-unverified facts (the tail's exact shape, its per-chunk — not
global — scope, and which types the "unique id" property actually holds
for) — but turning that into a working append path, proven even at the "our
own tooling round-trips it" level TNC's r2_newassets.md reached, is
unbuilt and is the single most concrete next step (§6).
4. Inherit / load-order traps — does TNO have a dlc_0-style trap?
No equivalent exists, and the reason is structural, not luck
(PROVEN, by code + file-listing read):
- TNO's
base/master.indexnames exactly 14chunkN.index/chunkN.resourcespairs, flat, no DLC folders, nopatch_*.resources(confirmed:lsof the TNO install root listschunk0..chunk13plusmaster.indexand nothing else archive-shaped; contrast with TNC'sbase/+dlc/dlc_0..5/+patch_1..4.resourcestiers thatdocs/patchvorrang.md/the TNC custom-map memory note are all about). There is no "which layer wins" question to get wrong, because there is only one layer. wolfsdk.patch.Installation.lookup/find()is built once, over allself.archives(= all 14 chunks, always, everyapply()call — not a subset chosen per-mod or per-map), andfind()returns every hit for a(type, name)key across however many of the 14 chunks carry it (confirmed by code read, §2 above)._apply()then iteratesfor archive, entry in hits:and writes to every one. Measured duplication is real and non-trivial (§1.4: 444 rawai/*entries for 255 distinct names, a 1.74× average) — so this "patch every copy" behaviour is load-bearing, not a theoretical safety net: a mod that only patched the first hit would silently leave 189 duplicate AI entries unpatched.- The one genuinely open question in this space, carried over unresolved
from
docs/ladepfade.mdTeil 1 (not re-tested here, no game launch): whetherfs_overlaypath/loose files inbase/generated/could let a loose file on disk shadow an archived decl of the same path. If that is real, it would be a different kind of trap than TNC's (a loose-file override silently beating an applied archive patch) —docs/ladepfade.mditself says this needs a 10-minute in-game experiment (its own "E1–E3") that was out of scope for a read-only round and still is.
One real trap this round did find, inside the decl layer itself, not the archive layer: the §1.4 "FAILED HYPOTHESIS" above — assuming a TNC-style shared-root AI lever exists in TNO when it structurally does not (252/255 decls override their own health). Anyone porting a TNC AI-difficulty recipe to TNO by analogy would silently affect almost nothing.
5. Three ready-to-build TNO mod designs
All three use only mechanisms independently confirmed safe in §2/§1 above
(set on an existing path, or file with a verbatim donor array already
shipping in retail) — no new patcher capability required, no new archive
entries needed.
5.1 AI health slider, corpus-wide (generator script, set)
What: scale every ai/* entityDef's aiHealth.components.components[0].max
and .cur by a constant factor (e.g. ×0.4 for "glass cannon enemies",
×2.5 for "bullet sponge"). Both max and cur must move together — moving
only max leaves an enemy's actual spawn HP at the old (lower or higher)
cur value, since the decl ships both set to the same number in every
sampled entry (§1.4).
Why this needs a generator, not three hand-written edits: §1.4 proved
252 of 255 ai/* entityDefs carry their own override — there is no
single shared decl to edit.
Build steps:
- Enumerate every
(type="entityDef", name starts "ai/")key viaInstallation.lookup, de-duplicated by name (the loader already patches every chunk copy per §4 — the generator only needs one representative read per name to compute the new value). - For each,
Decl(text)(wolfsdk/decl.py), readedit.aiHealth.components.components[0].max/.cur, skip the 3 decls missing the path (§1.4's negative control —setwould raiseDeclErroron them anyway, so skipping is both correct and the cheap path). - Emit one
mod.jsonwith ~252"set"assets:{"entityDef:ai/<name>": {"set": {"edit.aiHealth.components.components[0].max": "<new>", "edit.aiHealth.components.components[0].cur": "<new>"}}}. - No new decl type, no
filereplacement, no risk beyond whatwiderstand's 11-assetsetedit already proved end-to-end (§2).
5.2 Full arsenal from chapter 1 (file, exact retail donor text)
What: replace entityDef:player/game/wolf/c01/c01p1's
startingInventory block (pristine: num = 1, one item,
inventoryDecl = "weapon/knife46cutonly" — a chapter-specific knife variant,
not plain weapon/knife as pass 1 imprecisely said; corrected this
round by direct re-read, does not change the recipe since it's a full-block
replace either way) with the exact
array already shipping in player/game/wolf/c05_07_09_15/c15 (§1.5):
startingInventory = {
num = 6;
item[0] = { startSlot = "BACKPACK"; inventoryDecl = "weapon/knife"; }
item[1] = { startSlot = "BACKPACK"; inventoryDecl = "weapon/laserkraftwerk"; }
item[2] = { startSlot = "EQUIPPED"; inventoryDecl = "weapon/assaultrifle1960"; }
item[3] = { startSlot = "BACKPACK"; inventoryDecl = "weapon/shotgun"; }
item[4] = { startSlot = "BACKPACK"; inventoryDecl = "weapon/ar60marksman"; }
item[5] = { startSlot = "BACKPACK"; inventoryDecl = "weapon/handgun"; }
}
Why this is "ready", not just an idea: moddingflaeche-tno.md §4.4
already proposed this exact move in the abstract ("den
startingInventory-Block von c16p0 nach c01p1 kopieren", i.e. "copy the startingInventory block from c16p0 to c01p1"); this round turns it
into an exact recipe by reading the real retail text of the richest
donor (c15, not c16p0 — c16p0 does not exist as a key in the 30-name
census, c15 does and is confirmed richer than the next-best c11p1/c14p1
candidates) and confirming every one of its 6 inventoryDecl targets is a
real, resolvable weapon decl name (all appear as weapon: entries
elsewhere in the same corpus, §1.1/§1.5). Build: copy
_wolfsdk_backup's c01p1.decl text verbatim, string-replace only the
startingInventory = { num = 1; … } span with the block above, ship as
{"file": "assets/entityDef__player_game_wolf_c01_c01p1.decl"} — one asset,
zero guessing, matches supersoldaten_c15's already-proven "copy and
surgically edit one span" build pattern.
5.3 AI accuracy slider, 10 decls (set, single real combat lever)
What: set every tier of accuracySettings.accuracySettings[0..5].spread
to a new value, in each of the 10 weapon/ai/* decls that carry their
own copy of the field (§1.1: shotgun, assaultrifle1960, pistol,
drone, robot, mg60/supersoldat1960, wol000d_pistol,
assaultrifle1960rocket, mechadeathshead_laser, prototyperobot_lkw).
Corrected this round (§1.1's inheritance-aware re-check, see "Pass-1
errors"): editing just these 10 decls' spread actually reaches 26 of the
29 weapon/ai/* decls corpus-wide, because 16 more decls inherit the field
transitively from one of these 10 (e.g. submachinegun1946 inherits from
assaultrifle1960) — only weapon/ai/baton,
weapon/ai/fists/supersoldat1946 (genuinely melee) and
weapon/ai/mg46/supersoldat1946 (unexplained standalone exception) are
unreachable by this design. 10 edited decls, 26 affected — a bigger reach
than pass 1 claimed, at the same build cost. Two directions in one
mechanism: set all 6 tiers to 0 per decl (enemies hit every shot they take
— "deadeye" mode) or scale every tier up by e.g. 2× (much more forgiving
aim — an accessibility/easy-mode variant, distinct from the HP-based easy
mode in §5.1 and composable with it).
Why this is the clean lever and not trackingParms: §1.4 found TNO's
shared trackingparms/aim_default decl has no hit-probability field
(parms.item[] is tracking speed, not spread) — the field TNC's doc
describes under the same decl type name does not exist in TNO's copy. The
actual, verified accuracy knob lives on the weapon side instead, and
because weapon/ai/* decls are referenced by name from AI behaviour (not
duplicated per enemy instance), 10 edited decls affect every AI that fires
one of these 10 weapons corpus-wide — the one genuine single-point combat
lever this round found for TNO AI (contrast with §5.1's health, which has
none).
Build: 10 "set" assets, each with 6 leaf-path edits
(edit.accuracySettings.accuracySettings[N].spread), all paths confirmed
present in the pristine decls read this round — no file replacement
needed anywhere in this design.
PROVEN
- TNO's
entityDefAI/player decl shape (aiHealth, actorEditable.damageGroups, faction, startingInventory, perkAbilities/perks/upgradeInfo) matches TNC's field paths exactly, confirmed by direct pristine read (§1.4/§1.5). weapon/handgun_base'swiderstanddiff is exactly 3 hunks, matching the mod's own claimed fields, confirmed byte-for-byte against the pristine backup (§1.1).damage/tungsten/mg46pristine lackscuttableRadius/ragdollOnDeath; both exist live, inserted by a"file"edit (§1.2).projectile/handgunpristine lacksaimAssistRangeentirely; it exists live (zielhilfe_alle), confirming the loader can insert brand-new decl keys via"file"(§0/§2).- 252/255 TNO
ai/*entityDefs carry their ownaiHealthoverride; only 3 do not (§1.4, full corpus count). wolfsdk/decl.py:apply_patch()rejects any"set"path absent from the target decl's own parsed values (code read, §2).wolfsdk/resources.py:Archive.rebuild()has no path to insert a new(type,name)entry; it raises on any payload key matching no existing entry (code read, §3).- TNO's archive tier is flat (14 chunks via
master.index, no DLC/patch layer) andInstallation.find()/apply()patches every duplicate copy across all 14 chunks in one call (code read, §4). - The 13-byte entry tail in
chunkN.indexis 9 zero bytes + a BE u32 id that is unique per chunk, per type (0 collisions in any of the 14 chunks) for every decl-ish type checked (entityDef,weapon,damage,ammo,projectile,aiBehavior,material,trackingParms,faction,gamemodesp,soundmixing) — but not unique across chunks (the same id legitimately recurs for unrelated content in different chunks) and not unique even within one chunk forsound/particle/renderProg/cuttableResource(real same-chunk duplicate ids measured directly). Round-2 correction of a pass-1 overgeneralization; measured on all 14 chunks' real bytes (§3,re_probes/tnodecls/probe_tail_v2.pythrough_v5.py). docs/formats.md's open "Zähler A" question is substantially resolved: it equals the count of distinct(type,name)pairs in that chunk, exact in 12 of 14 chunks, off by <0.1% in the other 2 (§3).- All 8 currently-installed TNO mods applied cleanly against the real
14-chunk archive set (
journal.json: 377 assets, 0 missing,state: applied) — the patcher mechanism works end to end on live data, independent of the harness's generic in-game claim. - 16 of the 19
weapon/ai/*decls lacking their ownaccuracySettings[].spreadinherit it transitively from one of the 10 base decls that carry it; only 2 are genuinely melee with no spread concept and 1 (mg46/supersoldat1946) is a real unexplained exception — round-2 fix of a pass-1 negative-control defect, resolved by tracing everyinherit =chain (§1.1,re_probes/tnodecls/probe_weaponai_inherit.py).
INFERRED
- That the per-(chunk,type) sequential tail id is assigned at content-build time, once per chunk (not resolved by name at load time, and not a single global counter across the install) — plausible from its behaviour (confirmed per-chunk unique, confirmed NOT per-name-consistent across chunks), not traced into any code (no TNO runtime image exists to trace into).
- That a new entry appended as the last row of both the index's entry
list and the
.resourcespayload area would respect the ascending-offset invariant and thus not reproduce the knownFileTable is out of ordercrash — reasoned from the invariant's stated cause, never built or tested. - That
accuracySettings[].spreadis the primary AI hit/miss lever (as opposed to some other, unread field) — supported by it being the only numeric field named "spread"/"accuracy" found on the 10 rangedweapon/ai/*decls (and, transitively, 16 more viainherit), but the actual to-hit math is in the encrypted.textand was not traced. - That
sound/particle/renderProg/cuttableResource's within-chunk duplicate tail ids index some shared cue/permutation table (rather than being a parsing artifact) — plausible given the duplicate groups share the same declname(e.g. 50 identically-namedsoundentries sharing one id), not traced into any code and not needed for any §5 design.
FAILED HYPOTHESES
- "A TNC-style shared AI-health root decl exists in TNO, so one edit
cascades corpus-wide." Refuted by direct count: 252/255
ai/*entityDefs overrideaiHealththemselves (§1.4). - "
trackingParms:trackingparms/aim_defaultcarries TNO's AI miss-chance field, the same shape TNC's decl of that name has." Refuted by direct read: TNO's copy has noaimError/trackerRangekey, only tracking-speed fields (§1.4). The real lever is the weapon-sideaccuracySettings[].spreadinstead (§1.1, used in §5.3). - My own first-pass reads of
weapon/handgun_base,damage/tungsten/mg46, andprojectile/handgunfrom the live install, initially taken as "what retail ships" — caught and corrected by re-reading from_wolfsdk_backuponce the backup folder was noticed (§0); flagged here so the same mistake isn't repeated by a reader skimming only this report. - "The 19
weapon/ai/*decls without their ownaccuracySettings[].spreadhave no spread concept at all" — refuted by tracinginherit =chains: 16 of the 19 inherit a workingspreadfrom one of the 10 base decls; a pass-1 negative control that skipped the exact inheritance check this report itself applies elsewhere (§1.1, verifier-found, round-2 fix). - "The 13-byte tail's 9-zero-plus-BE-u32-id pattern increments by exactly 1
and never repeats, full stop" — refuted as a blanket claim: true only
per chunk and only for decl-ish types;
sound/particle/renderProg/cuttableResourcehave real same-chunk duplicate ids (§3, verifier-found, round-2 fix).
Open questions / next step
- Build and self-test an append-entry writer for
chunkN.index+.resources, at the levelr2_newassets.mdreached for TNC (own parser round-trips a synthetic new entry) — still the concrete, scoped next step, still not built. Round 2 removed one blocker: the per-type tail id only needs to be unique within the one chunk being edited (confirmed, not just assumed, §3), so the writer's id-assignment rule is now known (max(existing ids of this type in this chunk) + 1) andZähler Ais understood well enough to compute a correct replacement header value (count of distinct(type,name)pairs, §3). What's still unbuilt: the writer itself, and whether this project's ownResourceIndex.load()resync parser (let alone the real engine) accepts a hand-built entry — no TNO runtime image exists to check the latter. - Whether
fs_overlaypath/loosebase/generated/files can shadow an archived decl (§4) —docs/ladepfade.md's own unfinished E1 experiment, relevant here because it's the one place a TNO-specific load-order trap could still exist, just not in the archive-precedence shape TNC has. - A TNO runtime image (the TNC-side
tools/decomp.pyequivalent) would turn severalINFERREDitems here intoPROVEN— in particular, what asound/particle/renderProgduplicate tail id actually indexes (§3), and whetheraccuracySettings[].spreadreally is the engine's hit/miss lever (§1.1/§5.3). None of this round's findings required it to be useful, but these specifically do.
In-game test (for the maintainer)
(Translated from German.)
Not a single one of the three designs from §5 was started — everything below is the smallest test step, not a result.
- The easy-to-check variant, design 5.2 (full arsenal in chapter 1):
build the mod (one
.declfile,entityDef:player/game/wolf/c01/c01p1,startingInventoryas in §5.3 above), install it withwolfsdk apply, load chapter 1. Expected: the weapon wheel immediately shows six weapons (knife, Laserkraftwerk, assault rifle equipped, shotgun, sniper variant, pistol) instead of only the knife. This is the lowest-risk of the three tests — a singlefilereplacement with exactly the values that chapter 15 itself uses in the original game. - Design 5.3 (AI accuracy): set one of the ten
weapon/ai/*decls (e.g.weapon/ai/assaultrifle1960) experimentally tospread = 0in all six levels, play a single early encounter with rifle carriers (e.g. chapter 1). Expected: clearly more frequent hits by the enemies, without anything else changing (no new animation, no new sound). Shows whetheraccuracySettings[].spreadreally is the hit lever (§1.4 INFERRED) or whether the engine reads it differently than assumed here. - Design 5.1 (AI health generator): before the full 252-decl run,
first test one enemy type by hand — set
ai/enemies/default'saiHealth.components.components[0].max/curto e.g.5(as already proposed indocs/moddingflaeche-tno.mdfor TNC), play a short encounter with standard enemies. Expected according to §1.4: only the three non-combat decls would be affected if one touches only the root instead — that directly confirms whether the "no shared lever" finding measured in this report holds, before the 252-decl generator is built.
Files
| File | Content |
|---|---|
re_probes/tnodecls/probe_tail.py |
Pass-1: read-only tail-byte measurement over chunk1.index only (§3), re-runnable; superseded in scope by _v2–_v5 below but kept for its raw-tail printout. |
re_probes/tnodecls/probe_tail_v2.py |
Pass-2: same measurement widened to all 14 chunks, window=64 vs 256, per-type duplicate-id summary (§3, "Pass-1 errors"). |
re_probes/tnodecls/probe_tail_v3.py |
Pass-2: per-chunk vs cross-chunk id-uniqueness check for 7 mod-relevant types (§3). |
re_probes/tnodecls/probe_tail_v4.py |
Pass-2: confirms cross-chunk id reuse maps to different names, not the same decl (§3). |
re_probes/tnodecls/probe_tail_v5.py |
Pass-2: within-chunk duplicate-id check for sound/particle/renderProg/cm vs entityDef (§3). |
re_probes/tnodecls/probe_cuttable.py |
Pass-2: within-chunk duplicate-id check for cuttableResource (§3). |
re_probes/tnodecls/probe_weaponai_inherit.py |
Pass-2: weapon/ai/* corpus census + inherit = chain resolution for the accuracySettings[].spread negative control (§1.1, "Pass-1 errors"). |
re_probes/tnodecls/pristine_*.decl (7 files) |
Pristine (_wolfsdk_backup) extracts of every decl quoted in §1, saved so a reader can diff them against the live install without touching the game dir again. |
re_probes/agent_reports/r6_tnodecls.md |
This report. |
Related: Research Report: R2 Newassets, Research Report: R3 Newassetsv, Research Report: R4 Ai Decls, Research Report: R7 Tno Add Entry, TNO Modding Surface, File Formats, Modding Limits, Asset Loading Paths, Patch Precedence.