Missiles: authentic dsrm smoke trail + torso aim (placeholder tracer removed)

The "white lines toward the feet" report: the LAUNCHES are authentic (the
mech's real MissileLauncher/ProjectileWeapon roster subsystems firing on
their own recharge cadence -- that's the every-Nth-shot rhythm), but the
visual was the bring-up 3-segment beam tracer, and the aim point was the
victim's ORIGIN (ground level between the feet).

- Trail: per-frame puffs of the AUTHENTIC dsrm effect (psfx 0, "the lrm
  smoke trail") along the flight path, frame-oriented so the smoke streams
  behind the round (its .PFX velocities are +Z = backward); the round itself
  is a short hot streak.  New BTPfxTrailPuff spawns slot particles directly
  at a moving point (no emitter instance).
- Aim: the resolved target point lifts to torso height (the beams already
  converged there) -- impacts now cyl-resolve to body zones instead of
  diving at the feet/legs.

Follow-up noted: the round MESHES (BULLET/LRMS.BGF ship) for a true
model-per-projectile look.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
arcattack
2026-07-08 16:15:03 -05:00
co-authored by Claude Fable 5
parent bf87360c42
commit 9b5004c39d
2 changed files with 46 additions and 7 deletions
+30
View File
@@ -546,6 +546,36 @@ void BTStartPfx(int effect_number, float x, float y, float z)
BTStartPfxFrame(effect_number, x, y, z, 0, 0, 0);
}
// Spawn a few particles of a slot's effect DIRECTLY at a moving point (no
// emitter instance) -- the per-frame projectile SMOKE TRAIL (psfx 0 = dsrm,
// "the lrm smoke trail": its velocities stream +Z = BEHIND the round, so the
// frame is built with local +Z = the flight's backward direction).
static void BTPfxSpawn(const BTPfxEmitter &e); // defined below
void BTPfxTrailPuff(int effect_number, float x, float y, float z,
float backx, float backy, float backz, int count)
{
if (effect_number < 0 || effect_number >= BT_PFX_SLOTS)
return;
const BTPfxDef &d = gBTPfxDefs[effect_number];
if (!d.valid)
return;
BTPfxEmitter e; // transient -- used only as the spawn context
e.def = &d;
e.pos = D3DXVECTOR3(x, y, z);
D3DXVECTOR3 az(backx, backy, backz);
if (D3DXVec3LengthSq(&az) < 1e-6f)
az = D3DXVECTOR3(0, 0, 1);
D3DXVec3Normalize(&az, &az);
D3DXVECTOR3 up(0, 1, 0);
if (fabsf(az.y) > 0.99f) up = D3DXVECTOR3(1, 0, 0);
D3DXVECTOR3 ax; D3DXVec3Cross(&ax, &up, &az); D3DXVec3Normalize(&ax, &ax);
D3DXVECTOR3 ay; D3DXVec3Cross(&ay, &az, &ax);
e.ax = ax; e.ay = ay; e.az = az;
e.emitAccum = 0.0f; e.issued = 0; e.active = 0;
for (int i = 0; i < count; ++i)
BTPfxSpawn(e);
}
static void BTPfxSpawn(const BTPfxEmitter &e)
{
const BTPfxDef &d = *e.def;