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.
|
||||
|
||||
@@ -38,8 +38,20 @@ New unaccounted functionality no prior list knew (addresses verified absent from
|
||||
Settle via vtable lookup (plausibly a config/roster scroller).
|
||||
- **FUN_00454a70** (193 ln) — the PNAME1-8/PLACE1-8.bgf MP name-billboard loader (the known
|
||||
"MP target identification" gap's exact function).
|
||||
- **Explosion::SplashDamage @0042fad0** — substantial, unreferenced, directly in the combat
|
||||
path; one-time diff vs engine EXPLODE.cpp would rule out 1995-vs-WinTesla falloff drift.
|
||||
- ✅ **Explosion::SplashDamage @0042fad0 — RECONSTRUCTED (task #62, 2026-07-13) [T1/T2].** ONE call
|
||||
site, **Missile::Perform (FUN_004bef78, part_013.c:10097)**, in the collision branch (fires on ANY
|
||||
missile impact — mover OR world), gated on `missile+0x360`, radius = `missile+0x364`. **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 → missile ctor SearchList @10184) — NOT the
|
||||
launcher's `ExplosionModelFile`. The MissileThruster parser `FUN_004bf8ec` writes `"SplashRadius"` to
|
||||
+0x50 (size-0x54 record). Burst falloff `baseBurst / dist^exp` floored at 1 (arcade 1.25 / WinTesla
|
||||
`EXPLODE.cpp:209` 1.2f). Only missiles splash (AC tracer is not a Missile). The engine `EXPLODE.cpp`
|
||||
diff is DONE — the T0 source confirmed the model; the only 1995-vs-WinTesla drift is the exponent.
|
||||
Port: `BTResolveSplashRadius`/`BTApplySplashDamage` (mech4.cpp), see [[combat-damage]]. **Remaining
|
||||
T3:** the per-player enable sub-gate `missile+0x360 = BTPlayer+0x264` (its writers read as a per-frame
|
||||
toggle, not a config flag; the `showDamageInflicted@0x264` label is a guess) — port treats authored
|
||||
`SplashRadius>0` as the enable. The mech's `DeathSplashDamage`/`DeathSplashRadius` (mech+0x520/0x524)
|
||||
stay **VESTIGIAL** (written, never read; no mech-death splash mechanic — death is visual only).
|
||||
- **The binary's own VelociRender BGF/BMF/BSL/VTX loader (~4,550 ln, dead code)** — a free
|
||||
ground-truth cross-check for [[bgf-format]]/[[asset-formats]] claims.
|
||||
Full ranked audit: the workflow output (2026-07-13); top-10 ranking cross-checked against this
|
||||
|
||||
Reference in New Issue
Block a user