Status as of 2026-09-25, read from Retail installation (read-only only). All data resides in gameresources.resources (Container MAIN, always mounted); deviations are noted below. Verifiable via: python tools/verify_weapon_mod.py.
Status: structurally valid, unconfirmed in-game.
Chain of the Player Pistol
weapon/player/sp/handgun inherit handgun_nomesh; Model pistole61.md6, magazineEnt, casing
weapon/player/sp/handgun_nomesh inherit base_nomesh (no inventoryClass = Standard class)
initialAmmoDecl = ammo/player/sp/handgun
BURSTMODE_SINGLE, burstInterval 85, dualwieldable, maxCount 2
upgrades: magazine_size, silencer, elephantrounds, elephantrounds_silencer
ammo/player/sp/handgun inherit base_ammo (clipSize 30 as default)
clipSize 10, maxCount 80, lowAmmoInClip 3, 20 ammoCountMeshes
projectileDecl = projectile/player/pistol
projectile/player/pistol inherit projectile/player/default -> Hitscan (no hitscan=false)
damageDecl bullet_pistol, impactEffectTable handgun, tracers 2
damage/firearm/bullet_pistol inherit bullet_standard; 20/20, DAMAGETYPE_HANDGUN,
declGoreBehavior standard/pistol
Upgrades (applyTo = weapon/player/sp/handgun) swap the projectile via modifiersData.item[].data.valueDecl:
silencer -> pistol_silenced, elephantrounds -> pistol_elephant (Damage bullet_pistol_elephant 30, Gore standard/magnum; newer version in patch_2), elephantrounds_silencer -> pistol_elephantrounds_silenced.
All three inherit (directly or via pistol_elephant) from projectile/player/pistol.
magazine_size: AMT_AMMO_CLIP_SIZE, valueInt = 20, priority 4, without opType; located in gameresources and patch_3 (there additionally DMT_UPGRADE_ANIM). All four Retail magazine upgrades set exactly double the base magazine (10/20, 30/60, 20/40, 45/90) - whether "set" or "add" is intended, the data does not specify.
Decl entries in IDCL carry 0 dependencies; references are resolved at runtime by name. generated/buildgame/common.mapresources (highest copy in patch_4) loads the entire chain with the Always bit.
What Explodes
Every Retail projectile with splashDamageDecl is an Entity projectile (hitscan = false + notHitscanInfo.entityDef); a hitscan with area damage does not exist. Candidates: Grenades, dieselgun, ubergun, dkw_*, Combat Pistol.
Combat Pistol (ammo/player/sp/kampfpistol, 6 shots):
projectile/player/kampf_pistol- Grenade, parabolic trajectory, bounces off surfaces, ignites after 2.5s or upon contact with enemies (explodeOnActorsAfterTime 200).- Launcher upgrade
weapons/kampf/launcher->projectile/player/kampf_pistol_rocket:gravityFactor 0, speed 70, Entityprojectile_ent/kampf_grenade_rocket(idProjectile_Grenade,explodeOnImpactAfterTime 75ms, fuse 3s),splashDamageDecl damage/player/kampf_grenade: 250 damage, Radius 2 (inner 1),selfDamageScale 0.25, Gorestandard/grenade+ radial. Direct hitdamage/player/kampf_grenade/minorimpact.
The Mod (mods/tnc_waffe_explosivpistole)
| Asset | Change | Location |
|---|---|---|
projectile:projectile/player/pistol |
inherit default -> kampf_pistol_rocket |
408/448 B |
ammo:ammo/player/sp/handgun |
edit.clipSize 10 -> 30 |
465/512 B |
upgrade:weapons/handgun/magazine_size |
patch_3-Retail without indentation, valueInt 20 -> 30 |
439/448 B (gameresources), 439/512 B (patch_3) |
Why use inherit instead of projectileDecl for the ammunition: The upgrades replace the projectile, but all replacement projectiles inherit from projectile/player/pistol. This causes basic, silencer, and elephant ammunition to explode, while the pistol retains its bullet sound, spread, and its hit damage (bullet_pistol instead of minorimpact); additionally, it gains the area damage of the combat pistol rocket.
Why the upgrade is a file: Installation.read reads the first copy (gameresources) and apply writes the result to every copy. A set would have taken DMT_UPGRADE_ANIM from the patch_3 copy. The indented patch_3 version packs to 467 bytes; the space in gameresources is 448 bytes—thus a rebuild of 702 MB. Without indentation (token-identical, as confirmed by the reviewer): 439 bytes.
Retail examples: The hatchet (weapon/player/sp/hatchet, also standard class) fires an entity projectile (axe_throw, hitscan = false). A magazine larger than ammoCountMeshes.num is common (smg 45/1, battlerifle 30/3).
Open (only to be clarified in-game)
- Whether the standard weapon class starts the rocket entity exactly like
idKampfpistol(the hatchet example supports this). - Whether the spawned entity takes damage from
projectile/player/pistolor from its ownprojectileDecl(kampf_pistol_rocket) — it should explode in both cases. - Setting or adding
AMT_AMMO_CLIP_SIZE: with magazine upgrade 30 or 60. - The rocket does not ignite on impact under ~5 m (75 ms at speed 70), but bounces off and ignites later — self-damage 25 %.
aiEventDecl base/misc/grenade: Enemies react to every shot as if it were a grenade; the silencer no longer makes the pistol silent.