This research decodes how weapon decls are structured in TNC end to end — the entity/class system, fire modes, hitscan vs. travelling-projectile logic, viewmodel/animation/sound wiring, upgrades, dual wield, and the three ways the player actually receives a weapon — and works out exactly what a brand-new, separately-named weapon clone would need. The key finding is a clean, corpus-measured refutation of an earlier diagnosis that the default weapon class could only fire hitscan: the pistol and the hatchet share the identical absence of a specialized weapon class, and the hatchet already fires a genuine travelling projectile in unmodified retail, proving the restriction never existed. All of this is static decl-corpus analysis (no game launch); one incidental finding is that the explosive-pistol mod currently installed on the test machine is still the older, pre-fix version.
The weapon class system
Every player and AI weapon in the game — all 34 weapons/entity/* entity definitions — is rendered and fired through the same single C++ entity class, idWeaponEntity. One level down, an optional inventoryClass decl field can name one of exactly 12 compiled logic subclasses (idShotgun, idBattleRifle, idKampfpistol, etc.) — corpus-measured 12/12 match against the engine's own class list, 0 extra, 0 unused. The handgun sets no inventoryClass at all (runs on the engine's bare default), and so does the hatchet — whose axe_throw projectile already fires as a real, non-hitscan travelling entity in unmodified retail. Since both weapons share the identical missing field, there is no hitscan-only restriction baked into the default class; whether a weapon fires hitscan or a travelling projectile is decided purely by the fired projectile decl (hitscan=false plus a populated notHitscanInfo.entityDef) — 27 of the 44 retail player projectiles already take that path, including an ordinary full-auto rifle, not just melee/throwables.
Other weapon decl anatomy
- Viewmodel/worldmodel: two independent fields —
handsModelMD6on the weapon decl (first person) andrenderModelInfo.modelon itsattachEntityDef(world/third-person) — sometimes the same.md6file, sometimes a dedicated one. - Animations: a decl-driven state machine (
animSysDecl) reacts to fire/reload/equip/unequip events and names clip aliases resolved through anmd6Defto.md6animfiles. Since.md6anim's per-frame compression still isn't decoded (see the animation-decode report), a new weapon can reuse an existing animation set for free but can't get bespoke new animations yet. - Sounds: three separate channels — an
fxdecl for particle/sound trigger events, a Wwise switch-container key on the weapon decl, and afireSoundEventon the projectile decl — plus a fourth,gunfireEventDecl, which governs how loud AI perceives each shot. - Upgrades:
upgradedecls (195 corpus-wide) are referenced by an ordered unlock-slot list on the weapon decl, with up to three typed modifier arrays each (weapon/ammo/data modifiers). - Dual wield: purely decl-side —
dualwieldable=trueplusmaxCount=2on the same weapon decl, no second decl needed.
How the player actually gets weapons — and how they don't
Three corpus-proven, independent routes: devInvLoadout decls (per-map dev/test starting kits, 21-item default list, gated per story-timeline), propItem pickups placed in a map's entity data, and the mission-script node idKisculeNodeActionGiveItems (45 uses across 29 retail scripts). There is no console "give" command — the full list of 234 registered console commands was checked exhaustively and contains none.
The weapon wheel ceiling
The weapon-wheel/HUD is an unwritable, closed Flash-derived binary format with no existing or buildable writer. A weapon decl only controls the data the wheel reads — icon, display name, and two small closed enums (weaponSlotFlash, 8 values; weaponSelectionGroup, 7 values), both shared by several weapons each. A new weapon can occupy an existing slot but can never invent its own.
What a brand-new, separately-named weapon needs end to end
Every single piece — decl chain, viewmodel, animations, sounds, upgrades, pickup — is individually buildable with existing tooling by reusing retail assets, except making it a genuinely new name rather than a retune of an existing one, which needs appending new entries to the archive (structurally proven possible, not yet a production tool — see the related new-assets report). Until that tool exists, the proven, shippable version of "a new weapon" is retuning an existing weapon's own decl in place, exactly as the project's current explosive-pistol mod does.
In-game test
- Re-apply the explosive-pistol mod's current (fixed) version — the archive on the test machine was found to still carry the older, pre-fix build — then fire at a wall beyond 10 m on the custom map. An explosion (where there wasn't one before) confirms both the earlier load-order diagnosis and that redirecting via the ammo decl's own field (rather than the projectile's inherit chain) is the correct approach.
- No action needed to confirm travelling projectiles work with a specialized weapon class too — just observe during normal play that the Dieselgewehr rifle (which already uses a specialized
inventoryClassand a travelling projectile) behaves normally.