Combat: FIX missile direct damage 6x over-application -- damage once per salvo (task #62)
User live regression: missiles killed a mech in ~2 shots ("takes way more than 2
normally"). Root cause -- DamageZone::TakeDamage (arcade @0041e4e0 == WinTesla
DAMAGE.cpp:379) is `damageLevel += amount*scale` and IGNORES burstCount. So the
arcade's ONE cluster Missile per trigger lands its damageAmount EXACTLY ONCE; the
missileCount/burstCount split is cosmetic for zone damage (only gyro-bounce +
splash-falloff read burstCount). The port re-expresses that one cluster as N
flying rounds and was damaging on EVERY round = ~missileCount x too lethal on the
direct hit (mirrors the splash over-application fixed in 145a69f).
Fix (mislanch.cpp FireWeapon): only the salvo-LEAD round (i==0) carries damage
(damageData.damageAmount) AND the cluster splash; the other N-1 rounds are VISUAL
(damage 0) -- the tracer ripple, no extra damage. AC unaffected (one round/shot,
not a cluster).
Verified (BT_DMG_LOG [dmghit] trace): per-hit missile damage = clean 5.83, burst
1, once. Missiles-ONLY (BT_AF_MISSILE now independent of BT_AUTOFIRE), single
enemy, 45s: 8 damaging hits, top zone reaches only 0.18, NO death (was death in
~3 pulls) -- "way more than 2" restored. Earlier test deaths were BT_AUTOFIRE
firing laser+PPC+missiles combined, not missiles alone.
KB: combat-damage.md documents burstCount-ignored + the N-round cluster trap
(direct + splash both once-per-salvo).
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
145a69f865
commit
fa0b825b60
@@ -3730,10 +3730,12 @@ void
|
||||
LBE4ControlsManager::ButtonJoystickThumbLow, // 0x46
|
||||
LBE4ControlsManager::ButtonJoystickThumbHigh, // 0x47
|
||||
};
|
||||
// DEV: BT_AF_MISSILE=1 also pulses the missile group (ThumbHigh) so a
|
||||
// headless rig can exercise the launcher (splash verification, task #62).
|
||||
// DEV: BT_AF_MISSILE=1 pulses the missile group (ThumbHigh). INDEPENDENT
|
||||
// of BT_AUTOFIRE (which drives the main gun group) so a headless rig can
|
||||
// exercise MISSILES ONLY -- isolates missile damage/splash from laser+PPC
|
||||
// fire (task #62 TTK verification).
|
||||
static const int s_afMissile = getenv("BT_AF_MISSILE") ? 1 : 0;
|
||||
const int autofireMsl = (s_afMissile && gBTDrive.fireForced && targetInArc) ? s_afPhase : 0;
|
||||
const int autofireMsl = (s_afMissile && targetInArc) ? s_afPhase : 0;
|
||||
int want[4];
|
||||
want[0] = ((gBTLaserKey && targetInArc) || autofire) ? 1 : 0;
|
||||
want[1] = (gBTPinkyKey && targetInArc) ? 1 : 0; // key '4' (was unmapped)
|
||||
|
||||
@@ -424,7 +424,14 @@ void
|
||||
}
|
||||
|
||||
// ---- real zone: apply to armour/structure ----
|
||||
Scalar preLvl = damageLevel;
|
||||
DamageZone::TakeDamage(damage); // FUN_0041e4e0
|
||||
if (getenv("BT_DMG_LOG"))
|
||||
DEBUG_STREAM << "[dmghit] mech=" << mech->GetEntityID()
|
||||
<< " zone=" << damageZoneIndex << " vital=" << (int)vitalDamageZone
|
||||
<< " type=" << (int)damage.damageType << " amt=" << damage.damageAmount
|
||||
<< " burst=" << damage.burstCount
|
||||
<< " lvl " << preLvl << "->" << damageLevel << "\n" << std::flush;
|
||||
|
||||
Mech__DamageZone *parent = parentArtifactZone.GetCurrent(); // FUN_00417ab4(this+0x62)
|
||||
if (parent != 0)
|
||||
|
||||
@@ -305,15 +305,19 @@ void MissileLauncher::FireWeapon()
|
||||
// on the authored up-tilt, then the seeker loft + steering arc it onto the target.
|
||||
int nmiss = (missileCount > 0 && missileCount < 40) ? missileCount : 1;
|
||||
for (int i = 0; i < nmiss; ++i)
|
||||
// SPLASH (task #62 fix): the whole salvo re-expresses ONE arcade cluster
|
||||
// missile, which does ONE SplashDamage event with baseBurst = the cluster
|
||||
// count. Tag ONLY the first round as the salvo lead (splash_burst = nmiss);
|
||||
// the rest carry 0 so splash fires once per salvo, not once per visual round
|
||||
// (which floored-at-1 N times = ~missileCount-x over-splash).
|
||||
BTPushProjectile(muzzle, o, target, targetPos, speed, damageData.damageAmount,
|
||||
// DAMAGE + SPLASH ONCE PER SALVO (task #62 fix): the arcade fires ONE
|
||||
// cluster Missile per trigger, and its zone damage is applied EXACTLY ONCE
|
||||
// -- DamageZone::TakeDamage (@0041e4e0) is `damageLevel += amount*scale`
|
||||
// and IGNORES burstCount. The port draws that cluster as N visual rounds;
|
||||
// damaging on EVERY round applied the hit N times = ~missileCount-x too
|
||||
// lethal (the "2-shot kill" regression). Only the LEAD round (i==0)
|
||||
// carries the missile's damageAmount + the cluster splash; the rest are
|
||||
// VISUAL (damage 0) -- the ripple of tracers, no extra damage.
|
||||
BTPushProjectile(muzzle, o, target, targetPos, speed,
|
||||
(i == 0) ? damageData.damageAmount : 0.0f,
|
||||
&launchVelocity, 1,
|
||||
subsystemID /*messmgr explosion bundling at impact (task #7)*/,
|
||||
(i == 0) ? nmiss : 0 /*salvo-lead cluster splash*/);
|
||||
(i == 0) ? nmiss : 0 /*salvo-lead: cluster splash baseBurst*/);
|
||||
|
||||
// Salvo replication (missile-visibility wave): bump the fire counter + stamp
|
||||
// the aim point; the extended update record carries both to peer nodes.
|
||||
|
||||
Reference in New Issue
Block a user