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:
co-authored by
Claude Fable 5
parent
bf87360c42
commit
9b5004c39d
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user