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;
|
||||
|
||||
@@ -768,6 +768,12 @@ void
|
||||
target = gEnemyMech;
|
||||
tpos = ((Mech *)gEnemyMech)->localOrigin.linearPosition;
|
||||
}
|
||||
// AIM at the torso, not the feet: every target-position source here is the
|
||||
// victim's ORIGIN (ground level between the feet) -- the beams already
|
||||
// converge at chest height; missiles must too, or they visibly dive at the
|
||||
// target's feet and the cylinder resolves leg zones for every hit.
|
||||
if (target != 0)
|
||||
tpos.y += kMuzzleHeight;
|
||||
Vector3D d;
|
||||
d.x = tpos.x - mz.x; d.y = tpos.y - mz.y; d.z = tpos.z - mz.z;
|
||||
Scalar len = (Scalar)sqrtf(d.x*d.x + d.y*d.y + d.z*d.z);
|
||||
@@ -804,14 +810,17 @@ static void
|
||||
Scalar step = p.speed * dt;
|
||||
p.pos.x += p.dir.x*step; p.pos.y += p.dir.y*step; p.pos.z += p.dir.z*step;
|
||||
p.traveled += step;
|
||||
// Missile look: a short smoky exhaust trail (behind) + a bright warm body + a
|
||||
// hot flame tip, so it reads as a projectile rather than a thin laser line.
|
||||
// AUTHENTIC missile look: the round is a short hot streak, and the trail
|
||||
// is the real dsrm smoke-trail effect (psfx 0, "the lrm smoke trail")
|
||||
// puffed along the flight path each frame with local +Z = backward (the
|
||||
// .PFX's velocities stream the smoke behind the round). This replaces
|
||||
// the old 3-segment white tracer lines (a bring-up placeholder).
|
||||
Vector3D bd = p.dir;
|
||||
Point3D tail; tail.x = prev.x - bd.x*8.0f; tail.y = prev.y - bd.y*8.0f; tail.z = prev.z - bd.z*8.0f;
|
||||
Point3D tip; tip.x = p.pos.x + bd.x*2.0f; tip.y = p.pos.y + bd.y*2.0f; tip.z = p.pos.z + bd.z*2.0f;
|
||||
BTPushBeam(tail.x, tail.y, tail.z, prev.x, prev.y, prev.z, 0x00804020u, 0.20f, 3.2f); // dim smoke trail
|
||||
BTPushBeam(prev.x, prev.y, prev.z, p.pos.x, p.pos.y, p.pos.z, 0x00FF6010u, 0.15f, 2.6f); // orange body
|
||||
BTPushBeam(p.pos.x, p.pos.y, p.pos.z, tip.x, tip.y, tip.z, 0x00FFF0C0u, 0.15f, 1.4f); // hot flame tip
|
||||
BTPushBeam(prev.x, prev.y, prev.z, p.pos.x, p.pos.y, p.pos.z, 0x00FFB040u, 0.10f, 0.9f); // the round (hot streak)
|
||||
{
|
||||
extern void BTPfxTrailPuff(int, float, float, float, float, float, float, int);
|
||||
BTPfxTrailPuff(0, prev.x, prev.y, prev.z, -bd.x, -bd.y, -bd.z, 2);
|
||||
}
|
||||
|
||||
Scalar dx = p.targetPos.x - p.pos.x, dy = p.targetPos.y - p.pos.y, dz = p.targetPos.z - p.pos.z;
|
||||
if (dx*dx + dy*dy + dz*dz < (10.0f*10.0f) || p.traveled >= p.range)
|
||||
|
||||
Reference in New Issue
Block a user