Combat: MISSILE SPLASH DAMAGE -- Explosion::SplashDamage reconstructed (task #62)
Area-of-effect blast on missile detonation, from the T0 source EXPLODE.cpp:50-254 (@0042fad0) + the arcade decomp. Fires on ANY missile impact (world or mech) -- the +0x360 gate sits in the Missile::Perform collision branch (part_013.c:10097). Only missiles splash; the AC's tracer is not a Missile. Radius source CORRECTED: it is the ROUND's own GameModel (type-0xf) +0x50, seeded from the launcher's linked AmmoBin ammoModelFile @0x1e8 (part_013.c:8778) -- NOT the launcher's ExplosionModelFile (which resolved to 0). Live-resolved radius = 30 for both MP missile launchers; 0 for AC/Emitters. Burst falloff = baseBurst / dist^exp floored at 1 (arcade 1.25 = decomp 0x3ff40000; WinTesla EXPLODE.cpp:209 drifted to 1.2f). damageType/amount pass through unchanged; only burstCount, radial damageForce, and impactPoint are set. Excludes shooter + direct victim; dist>radius gated; delivered via msgmgr (cross-pod) or Dispatch. New: BTResolveSplashRadius / BTApplySplashDamage (mech4.cpp), hooked at both the world-impact and contact detonation paths; BTAmmoRoundModelResource bridge (ammobin). Env: BT_SPLASH_LOG, BT_SPLASH_TEST (synthetic near-miss), BT_AF_MISSILE (missile autofire). Verified: near-miss dist=15 -> 1 burst to a bystander; live missiles detonate + exclude the direct victim; AC does not splash; no crash. Deferred (T3): per-player enable sub-gate missile+0x360 = BTPlayer+0x264 (writers read as a per-frame toggle, not a config flag) -- port treats SplashRadius>0 as the enable. KB: combat-damage.md + open-questions.md updated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
4c54f7ef0c
commit
12fbc023a8
@@ -439,6 +439,44 @@ the un-exported master-perf writer (0x4a9770-0x4ab188 [T4]); the exact authentic
|
||||
writer emitted (msg+0x24) is likewise unrecovered, so the killing-blow magnitude is the faithful
|
||||
stand-in until it is. [T1 mechanism / T4 exact authentic value]
|
||||
|
||||
## Missile splash damage — `Explosion::SplashDamage` (task #62, 2026-07-13) [T1/T2]
|
||||
Area-of-effect blast on **missile** detonation — NOT the vestigial whole-mech `DeathSplashDamage`
|
||||
above (mech+0x520, never read). The T0 source is `engine/MUNGA/EXPLODE.cpp:50-254` (`@0042fad0`),
|
||||
called ONLY from the Missile's per-frame `Perform` (`@004bef78`, part_013.c:10097) inside the
|
||||
collision branch — so it fires on **any** missile impact (mover OR world geometry), gated on
|
||||
`Missile+0x360`. The AC's tracer is not a Missile and never splashes.
|
||||
|
||||
**The model [T0, `EXPLODE.cpp`]:** build a Y-axis cylinder of `SplashRadius` at the blast, collect
|
||||
every `Mover` in it (+ static world), then for each target that has `damageZones` and is not the
|
||||
direct victim (`entityHit`), the detonator (`this`), or `excluded`:
|
||||
- `burstCount = baseBurst / pow(dist, 1.2f)`, `Min_Clamp(…, 1)` — dist = `|target.localOrigin −
|
||||
blastCenter|` (center-to-center). The **arcade** exponent is **1.25** (decomp `0x3ff40000` at
|
||||
part_004.c:865; the decompiler hid the x87 FDIV + the `FUN_004dcd94`=ROUND that WinTesla writes as
|
||||
truncation). Point-blank AMPLIFIES (dist<1 → >baseBurst); no distance floor (real victims are never
|
||||
at dist~0 — the one AT the center is the excluded direct victim).
|
||||
- `damageType`/`damageAmount` pass through UNCHANGED; only `burstCount`, `damageForce` (radial), and
|
||||
`impactPoint` (= blastCenter+offset) are set. Delivered via `TakeDamageMessage(inflicting, zone=-1)`.
|
||||
|
||||
**The SplashRadius source [T1]:** it is the ROUND's GameModel resource `+0x50`, NOT the launcher's
|
||||
`ExplosionModelFile`. The launcher seeds each spawned Missile's model from its linked **AmmoBin**
|
||||
`ammoModelFile @0x1e8` (part_013.c:8778); the Missile ctor `SearchList(that_id, GameModelResourceType)`
|
||||
→ `+0x50` → `Missile+0x364` (part_013.c:10184). The MissileThruster GameModel parser
|
||||
`FUN_004bf8ec` writes `"SplashRadius"` to `+0x50` of the type-`0xf`/size-`0x54` record. Live-resolved
|
||||
radius for both MP missile launchers = **30** (`BT_ROSTER` dump).
|
||||
|
||||
**Port impl (`mech4.cpp`):** `BTResolveSplashRadius` gates on `MissileLauncher::ClassDerivations`,
|
||||
resolves launcher → `BTWeaponAmmoBin` → `BTAmmoRoundModelResource` (+0x1e8) → GameModel +0x50.
|
||||
`BTApplySplashDamage` walks `BTGetTargetCandidates` (excludes shooter), skips the direct victim +
|
||||
destroyed/zoneless mechs, applies the `dist>radius` gate + the burst falloff, delivers through the
|
||||
shooter's msgmgr (cross-pod) or `Dispatch`. Hooked at BOTH detonation paths (world-impact + contact).
|
||||
**Verified:** radius resolves to 30 for missiles / 0 for AC+Emitters; near-miss dist=15 → 1 burst
|
||||
delivered to a bystander; live missiles detonate + exclude the direct victim; AC does not splash; no
|
||||
crash. Env `BT_SPLASH_LOG`, `BT_SPLASH_TEST` (synthetic near-miss), `BT_AF_MISSILE` (missile autofire).
|
||||
**Deferred [T3]:** the per-player enable sub-gate `Missile+0x360 = BTPlayer+0x264` (part_013.c:8757) —
|
||||
its decomp writers (4668/10512) read as a per-frame state toggle, not a clean config flag, and the
|
||||
port's `showDamageInflicted` label is itself a guess; port treats authored `SplashRadius>0` as the
|
||||
enable. See [[open-questions]].
|
||||
|
||||
## Key Relationships
|
||||
- Weapons/roster: [[subsystems]]. Aim source: [[locomotion]] (drive/facing). Effects: [[rendering]].
|
||||
- P5 forensics: `docs/HARD_PROBLEMS.md`. Data: [[decomp-reference]] §4-5.
|
||||
|
||||
Reference in New Issue
Block a user