From 5038d643821ad66f7f991faabe589a5b45898fcd Mon Sep 17 00:00:00 2001 From: arcattack Date: Thu, 9 Jul 2026 08:11:03 -0500 Subject: [PATCH] Damage range gate: the authentic per-weapon effectiveRange (was a 100u stand-in) User report: lock at spawn range (~120) but no damage until closing in. The bring-up damage gate used kWeaponRange=100 -- a placeholder from before the weapon reconstruction -- while the authored BLH weapon range is 500 m. The binary's rule (FireWeapon @004bace8:7758 [T1]): damage applies when dist <= the weapon's EFFECTIVE range = (1 - host-zone damage) x authored WeaponRange -- the per-weapon targetWithinRange flag UpdateTargeting computes each frame. The gate (and the [target] log's IN WEAPON RANGE annotation) now reads that flag across the weapon roster; kWeaponRange removed. Verified: stationary at spawn range 120 -> IN WEAPON RANGE + 34 aimed zone hits (was 0 until closing under 100). Co-Authored-By: Claude Fable 5 --- game/reconstructed/mech4.cpp | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/game/reconstructed/mech4.cpp b/game/reconstructed/mech4.cpp index 4779428..2734e82 100644 --- a/game/reconstructed/mech4.cpp +++ b/game/reconstructed/mech4.cpp @@ -537,9 +537,8 @@ extern BTDriveInput gBTDrive; // real gait wiring). Units are world units/sec and radians/sec. static const Scalar kDriveMaxSpeed = 30.0f; // full-throttle forward speed static const Scalar kDriveTurnRate = 1.2f; // full-deflection yaw rate -static const Scalar kWeaponRange = 100.0f; // bring-up "in range" threshold for the - // targeting log (real value = Emitter - // effectiveRange @0x328, per-weapon) +// (kWeaponRange removed: the damage gate now reads the AUTHENTIC per-weapon +// targetWithinRange -- effectiveRange @0x328 = (1-damage) x authored 500 m.) // Single local-player drive state (bring-up). static Scalar gDriveHeading = 0.0f; // yaw about world up (Y) @@ -2527,6 +2526,27 @@ void float ddz = enemyPos.z - localOrigin.linearPosition.z; float range = (float)Sqrt((double)(ddx*ddx + ddy*ddy + ddz*ddz)); + // THE AUTHENTIC RANGE GATE (FireWeapon @004bace8 :7758 [T1]): damage + // applies when dist <= the weapon's EFFECTIVE range = (1 - host-zone + // damage) x its AUTHORED WeaponRange (BLH lasers/PPCs: 500 m) -- the + // per-weapon targetWithinRange flag UpdateTargeting computes each + // frame. Any live weapon within reach lands the aggregate shot. + // (Replaces the old kWeaponRange=100 bring-up constant, which + // silently blanked damage between 100 and the real 500 -- lock at + // spawn range 120 dealt nothing until you closed in; user-reported.) + int anyWeaponInRange = 0; + for (int wi = 0; wi < GetSubsystemCount(); ++wi) + { + Subsystem *ws = GetSubsystem(wi); + if (ws == 0 || !ws->IsDerivedFrom(MechWeapon::ClassDerivations)) + continue; + if (*(Logical *)((MechWeapon *)ws)->WithinRangePtr()) + { + anyWeaponInRange = 1; + break; + } + } + gTargetLogAccum += dt; if (gTargetLogAccum >= 1.0f) { @@ -2536,7 +2556,7 @@ void : (pickTarget != 0 ? " terrain downrange (beam at scenery)" : " sky (no target, no discharge)")) << " range=" << range - << (range <= kWeaponRange ? " IN RANGE" : "") + << (anyWeaponInRange ? " IN WEAPON RANGE" : "") << " [enemyPicks=" << gAimHits << " groundPicks=" << gAimGround << " noRay=" << gAimNoRay << "]" << "\n" << std::flush; @@ -2592,7 +2612,7 @@ void } if (fireWanted && designated && targetInArc && gFireCooldown <= 0.0f - && range <= kWeaponRange && gExplodeReady == 1) + && anyWeaponInRange && gExplodeReady == 1) // authentic gate (computed above) { gFireCooldown = kFireCooldown; ++gShotCount;