#84: missiles ACCELERATE like the binary -- the pool flew at constant

rack-eject speed; the authored MissileThruster was never applied

The binary Missile hosts a MissileThruster subsystem: authored
acceleration for BurnTime seconds after the MuzzleVelocity eject.
Authored values decoded from BTL4.RES (type-15 missile model records,
reached from the AmmoBin's ammoModelFile via the type-1 MODELLIST
indirection): SRM 2.5s @ 600 u/s^2, LRM 10s @ 300 (climb 50), Streak
3s @ 300 (turn 360deg/s), NARC 10s @ 300; splash 30 all (port constant
was already right); authored drag ~0.001 = negligible.

The port pool flew every round at CONSTANT |MuzzleVelocity| -- SRMs 100
u/s, LRMs 30 u/s (10x slower than authored) -- the entirety of the
night-7 "missiles are very slow" report, and the driver of the
"explosion before the missiles arrive" perception (the salvo-lead
detonates while the slow spread rounds straggle in).

Fix: BTMissileThrustOf (mech4.cpp) lazily parses + caches the RES
thruster table (ModelList ids aliased to their type-15 member's
burn/accel); both launch paths (master FireWeapon + the replicant salvo
mirror -- peers see the same speed) resolve through the launcher's bin
and pass burn/accel into the pool; the advance integrates speed +=
accel*dt while burn remains, heading preserved.  Ballistic rounds
(autocannon/gauss) pass 0/0 -- unchanged.  Impact log now prints
v=/burnLeft= evidence.

Verified live (solo, BT_SPAWN_ENEMY + BT_AF_MISSILE): thrust table 8
entries cached; Black Hawk Streak resolve burn=3 accel=300; impacts at
v=277 u/s (was a constant 100).  Fun authenticity note: the Black
Hawk's "SRM6" fires strk (STREAK) ammo per its authored bin.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019Zh7PTkFy4KwTzVighLR9J
This commit is contained in:
Joe DiPrima
2026-07-31 10:41:39 -05:00
co-authored by Claude Fable 5
parent ac7c46b87a
commit 4704ab3d41
6 changed files with 196 additions and 5 deletions
+31 -3
View File
@@ -74,7 +74,14 @@ extern void BTPushProjectile(const Point3D &muzzle, void *shooter, void *target,
const Point3D &targetPos, Scalar speed, Scalar damage,
const Vector3D *launch_velocity = 0, int guided = 1,
int weapon_subsys = -1, int splash_burst = 0, int muzzle_seg = -1,
int damage_type = 2 /*ExplosiveDamageType default*/);
int damage_type = 2 /*ExplosiveDamageType default*/,
Scalar thrust_accel = 0.0f, Scalar thrust_burn = 0.0f /*#84 thruster*/);
// #84: resolve this launcher's authored thruster (burn s, accel u/s^2) through
// its connected bin's round-model resource. 0/0 when unresolvable (flies at
// the old constant eject speed -- never worse than before).
extern void *BTWeaponAmmoBin(void *weapon); // projweap.cpp
extern int BTAmmoBinModelFile(void *bin); // ammobin.cpp
extern int BTMissileThrustOf(int model_id, float *out_burn, float *out_accel); // mech4.cpp
//###########################################################################
// Port-side salvo replication state (missile-visibility wave).
@@ -305,6 +312,18 @@ void MissileLauncher::FireWeapon()
// MuzzleVelocity VECTOR rides along (missile-arc wave): the round leaves the rack
// on the authored up-tilt, then the seeker loft + steering arc it onto the target.
int nmiss = (missileCount > 0 && missileCount < 40) ? missileCount : 1;
float tBurn = 0.0f, tAccel = 0.0f; // #84 authored thruster
{
void *bin = BTWeaponAmmoBin(this);
int mid = (bin != 0) ? BTAmmoBinModelFile(bin) : -1;
int hit = 0;
if (mid >= 0)
hit = BTMissileThrustOf(mid, &tBurn, &tAccel);
if (getenv("BT_PROJ_LOG"))
DEBUG_STREAM << "[projectile] thrust resolve: bin=" << bin
<< " modelID=" << mid << " hit=" << hit
<< " burn=" << tBurn << " accel=" << tAccel << "\n" << std::flush;
}
for (int i = 0; i < nmiss; ++i)
// DAMAGE + SPLASH ONCE PER SALVO (task #62 fix): the arcade fires ONE
// cluster Missile per trigger, and its zone damage is applied EXACTLY ONCE
@@ -320,7 +339,8 @@ void MissileLauncher::FireWeapon()
subsystemID /*messmgr explosion bundling at impact (task #7)*/,
(i == 0) ? nmiss : 0 /*salvo-lead: cluster splash baseBurst*/,
GetSegmentIndex() /*task #67: launch through the MOUNT frame (torso twist)*/,
(int)damageData.damageType /*missile = Explosive (authentic)*/);
(int)damageData.damageType /*missile = Explosive (authentic)*/,
tAccel, tBurn /*#84: the round ACCELERATES like the binary Missile*/);
// Salvo replication (missile-visibility wave): bump the fire counter + stamp
// the aim point; the extended update record carries both to peer nodes.
@@ -386,11 +406,19 @@ void
int n = rec->salvoRounds;
if (n < 1 || n > 40)
n = (missileCount > 0 && missileCount < 40) ? missileCount : 1;
float tBurn = 0.0f, tAccel = 0.0f; // #84: mirror the master's
{ // thruster so peer missiles
void *bin = BTWeaponAmmoBin(this); // fly at the same speed
int mid = (bin != 0) ? BTAmmoBinModelFile(bin) : -1;
if (mid >= 0)
BTMissileThrustOf(mid, &tBurn, &tAccel);
}
for (int i = 0; i < n; ++i)
BTPushProjectile(mz, owner, 0 /*no entity: aim point only*/,
rec->salvoTarget, spd, 0.0f /*VISUAL*/, &launchVelocity, 1,
subsystemID /*per-round detonation resolve on this node*/,
0, GetSegmentIndex() /*task #67 mount frame*/);
0, GetSegmentIndex() /*task #67 mount frame*/,
2 /*Explosive*/, tAccel, tBurn);
if (getenv("BT_PROJ_LOG"))
DEBUG_STREAM << "[projectile] REPLICANT salvo x" << n
<< " at(" << rec->salvoTarget.x << "," << rec->salvoTarget.y