Rear-fire + look views (task #68): the pod's rear arsenal reconstructed

The user's tip ("some mechs actually do fire backward") checks out end to
end.  Binary ground truth [T1]:
- weapon+0x334 (attr 0x1B "RearFiring"): the ctor tests the MOUNT SEGMENT's
  page name for the marker 'b' (@0x511aa2, part_013.c:6913-6930) -- the back
  gun ports sitelbgunport/siterbgunport.  The old reading ("EXT in the
  weapon model name") was a double misread (wrong string, wrong name).
- mech+0x410 (attr id 50 "RearFiring"; the old `stateFlags` label): the ctor
  ORs every weapon's flag (part_012.c:10220) -- "carries a rear arsenal".
- The mapper's five-state LOOK machine (part_013.c:396-459): on a state
  change it re-aims the eyepoint (mech+0x360 = EyepointRotation -- consumed
  by DPLEyeRenderable, already live in the port) and re-arms each weapon's
  viewFireEnable(+0x3E0): FORWARD view = the non-rear weapons, LOOK-BACK
  (yaw pi + lookBackAngle pitch) = the REAR-mounted ones, side/down = none.
  +0x3E0 is the same flag the emitter's Loaded->Firing gate reads (the old
  `useConfiguredPip` label) -- pips and fire permission both follow the view.

Port: rearFiring derived from the mount segment name (BTWeaponMountIsRear);
mech rearFiring ORed in the roster pass (the old SubProxy::IsDerivedFrom
stub returned 0 -- that loop never ran; now bridged through
BTWeaponIsRearFiring, which also fixes the weaponRoster fill); the look
commit is LIVE (BTCommitLookState: eyepoint EulerAngles from the authored
per-mech look angles -- now real members, were Wword scratch parks -- +
per-weapon view enables); MissileLauncher/ProjectileWeapon FireWeapon gate
on viewFireEnable like the emitter; RearFiring attrs (mech + weapon) bind
real members.  Keyboard: HOLD 'V' = the pod's rear-view button.

Live-verified on the default blackhawk: ERMLaser_2 -> siterbgunport rear=1,
ERMLaser_3 -> sitelbgunport rear=1, PPCs/SRMs/torso mounts forward -- the
blackhawk authors TWO REAR LASERS (owens also has back ports).  [rearfire]
trace under BT_PROJ_LOG.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
arcattack
2026-07-16 17:10:40 -05:00
co-authored by Claude Opus 4.8
parent ab6ea83e3b
commit 38febae36b
10 changed files with 195 additions and 32 deletions
+33 -5
View File
@@ -141,7 +141,7 @@ const MechWeapon::IndexEntry
ATTRIBUTE_ENTRY(MechWeapon, PipColor, pipColor), // 0x18 @0x33C
ATTRIBUTE_ENTRY(MechWeapon, PipExtendedRange, pipExtendedRange), // 0x19 @0x348
ATTRIBUTE_ENTRY(MechWeapon, EstimatedReadyTime, estimatedReadyTime),// 0x1A @0x330
ATTRIBUTE_ENTRY(MechWeapon, RearFiring, usesExternalModel), // 0x1B @0x334
ATTRIBUTE_ENTRY(MechWeapon, RearFiring, rearFiring), // 0x1B @0x334 (task #68: real semantics)
ATTRIBUTE_ENTRY(MechWeapon, WeaponState, weaponAlarm), // 0x1C @0x350
ATTRIBUTE_ENTRY(MechWeapon, OutputVoltage, rechargeLevel) // 0x1D (port alias)
};
@@ -315,9 +315,18 @@ MechWeapon::MechWeapon(
// removed. The muzzle segment index is the inherited base slot this+0xdc (used by
// GetMuzzlePoint); the pip mount is gated by useConfiguredPip in DrawWeaponPip.
// usesExternalModel: True if the model name contains the marker substring
// (DAT_00511aa2); selects whether the configured pip is drawn.
usesExternalModel = (strstr(GetName(), "EXT") != 0) ? True : False;
// (task #68) REAR-FIRING: the binary ctor (@004b99a8 tail, part_013.c:6913-
// 6930) resolves the weapon's MOUNT SEGMENT page name and tests it for the
// marker 'b' (DAT_00511aa2) -- the back gun ports (sitelbgunport /
// siterbgunport). Rear-mounted weapons fire only into the LOOK-BACK view.
{
extern int BTWeaponMountIsRear(void *ownerMech, int segIndex);
rearFiring = BTWeaponMountIsRear(owner, GetSegmentIndex()) ? True : False;
if (getenv("BT_PROJ_LOG")) { static int s_rf=0; if (s_rf++<40)
DEBUG_STREAM << "[rearfire] weapon '" << GetName()
<< "' seg=" << GetSegmentIndex()
<< " rear=" << (int)rearFiring << "\n" << std::flush; }
}
fireImpulse = 0.0f; // 0x31C
// task #6: the binary MechWeapon ctor defaults its controls-destination
@@ -329,7 +338,7 @@ MechWeapon::MechWeapon(
rechargeLevel = 1.0f; // 0x320 (fully charged)
previousFireImpulse = 0.0f; // 0x3A4
recoil = 0.0f; // 0x3E8
useConfiguredPip = (usesExternalModel == 0); // 0x3E0
viewFireEnable = (rearFiring == 0); // 0x3E0 (spawn in the forward view)
estimatedReadyTime = 0; // 0x330 (binary attr "EstimatedReadyTime")
Check_Fpu();
@@ -887,3 +896,22 @@ int
return True;
}
//#############################################################################
// Rear-fire bridges (task #68) -- complete-MechWeapon-type helpers for the
// Mech ctor's rear-arsenal OR and the mapper's look-state commit (both TUs
// hold only Subsystem*; the old SubProxy::IsDerivedFrom stub returned 0, so
// the roster loop's capabilityFlags read never ran).
//#############################################################################
int BTWeaponIsRearFiring(Subsystem *sub) // -1 = not a MechWeapon
{
if (sub == 0 || !sub->IsDerivedFrom(MechWeapon::ClassDerivations))
return -1;
return (((MechWeapon *)sub)->GetRearFiring() != 0) ? 1 : 0;
}
void BTWeaponSetViewFireEnable(Subsystem *sub, int enable)
{
if (sub != 0 && sub->IsDerivedFrom(MechWeapon::ClassDerivations))
((MechWeapon *)sub)->SetViewFireEnable(enable);
}