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:
co-authored by
Claude Opus 4.8
parent
ab6ea83e3b
commit
38febae36b
@@ -390,7 +390,7 @@ void
|
||||
case 2: // Loaded -- ready; fire on the trigger's rising edge
|
||||
if (fireEdge)
|
||||
{
|
||||
if (useConfiguredPip && HasActiveTarget()) // this+0x3E0 (Loaded->Firing gate) && entity+0x388
|
||||
if (viewFireEnable && HasActiveTarget()) // this+0x3E0 (Loaded->Firing gate: enabled in the CURRENT look view) && entity+0x388
|
||||
{
|
||||
weaponAlarm.SetLevel(0); // -> Firing
|
||||
FireWeapon(); // (*vtable+0x48)()
|
||||
@@ -833,8 +833,8 @@ Emitter::Emitter(
|
||||
}
|
||||
|
||||
// (E4 removed) the former `firingArmed = 1` wrote this+0x3e8 == MechWeapon::recoil,
|
||||
// NOT the Loaded->Firing gate: the binary gate reads useConfiguredPip@0x3E0 (set by
|
||||
// the MechWeapon ctor from usesExternalModel), so no separate arming is needed.
|
||||
// NOT the Loaded->Firing gate: the binary gate reads viewFireEnable@0x3E0 (set by
|
||||
// the MechWeapon ctor / the look-state commit), so no separate arming is needed.
|
||||
weaponAlarm.SetLevel(3); // Loading
|
||||
beamEndpoint = Point3D(0.0f, 0.0f, 0.0f); // 0x460 <- (0,0,0)
|
||||
beamFlag = 0; // 0x46c
|
||||
|
||||
@@ -308,7 +308,7 @@ class NotationFile;
|
||||
// * beamHitPoint/beamImpact/beamImpactScalar -> binary writes into the inherited
|
||||
// Damage damageData (0x3C8/0x3B0/0x3AC); the recon assignments were dead -> deleted
|
||||
// * beamColor -> never read (WriteUpdateRecord builds colour from targetEntity)
|
||||
// * firingArmed -> the Loaded->Firing gate reads inherited useConfiguredPip@0x3E0
|
||||
// * firingArmed -> the Loaded->Firing gate reads inherited viewFireEnable@0x3E0
|
||||
// * energyRampTime -> binary writes the base slot voltageScale@0x310; recon computes a local
|
||||
// * beamLengthRatio -> is beamScale.z@0x434
|
||||
int seekVoltageIndex; // @0x3F0 (param_1[0xfc]) current charge-curve index
|
||||
|
||||
+18
-11
@@ -731,7 +731,7 @@ const Mech::IndexEntry
|
||||
ATTRIBUTE_ENTRY(Mech, RadarRange, radarRange), // 0x2f (radar scale)
|
||||
ATTRIBUTE_ENTRY(Mech, RadarLinearPosition, radarLinearPosition), // 0x30 (Point3D* -> localOrigin)
|
||||
ATTRIBUTE_ENTRY(Mech, RadarAngularPosition, radarAngularPosition),// 0x31 (Quaternion* -> localOrigin)
|
||||
ATTRIBUTE_ENTRY(Mech, RearFiring, attrPad), // 0x32
|
||||
ATTRIBUTE_ENTRY(Mech, RearFiring, rearFiring), // 0x32 (task #68: binary id 50 @0x410)
|
||||
ATTRIBUTE_ENTRY(Mech, RequestDuckAnimation, attrPad), // 0x33
|
||||
ATTRIBUTE_ENTRY(Mech, UnstablePercentage, unstablePercentage), // 0x34 (task #66: the instability alarm; binary id 52 @0x3F0)
|
||||
ATTRIBUTE_ENTRY(Mech, SuperStop, attrPad), // 0x35
|
||||
@@ -853,7 +853,7 @@ Mech::Mech(
|
||||
|
||||
mechNameFilter.Initialize(); // FUN_00435a7c(this+0xdb)
|
||||
masterAlarm = AlarmIndicator(0x21); // FUN_0041b9ec(this+0xe7,0x21)
|
||||
stateFlags = 0; // Wword(0xff)
|
||||
rearFiring = 0; // (task #68) ORed from the weapons below
|
||||
// (F7 correction) the binary's 0x400 = FLT_MAX init is DistanceToMissile's
|
||||
// "no missile" far default (attr id 56), NOT a maxSpeed -- the old member
|
||||
// is retired; distanceToMissile (init below) owns the slot's meaning.
|
||||
@@ -1329,11 +1329,17 @@ Mech::Mech(
|
||||
}
|
||||
for (int id = 2; id < subsystemCount; ++id) // weapon roster (0x511830 = MechWeapon)
|
||||
{
|
||||
SubProxy *s = (SubProxy *)subsystemArray[id];
|
||||
if (s != 0 && s->IsDerivedFrom(0x511830))
|
||||
// (task #68) REAL derivation test via the mechweap bridge -- the old
|
||||
// SubProxy::IsDerivedFrom stub returned 0, so this loop never ran
|
||||
// (empty weaponRoster, no capability OR).
|
||||
extern int BTWeaponIsRearFiring(Subsystem *sub); // -1 = not a weapon
|
||||
int rf = BTWeaponIsRearFiring(subsystemArray[id]);
|
||||
if (rf >= 0)
|
||||
{
|
||||
weaponRoster.Add((Subsystem *)s);
|
||||
stateFlags |= s->capabilityFlags; // |= *(s+0x334) -> Wword(0x104)
|
||||
weaponRoster.Add(subsystemArray[id]);
|
||||
// mech.RearFiring |= weapon.rearFiring (binary ctor
|
||||
// @part_012.c:10220: mech[0x104] |= *(weapon+0x334))
|
||||
rearFiring |= rf;
|
||||
}
|
||||
}
|
||||
for (int id = 2; id < subsystemCount; ++id) // damageable roster
|
||||
@@ -1403,11 +1409,12 @@ Mech::Mech(
|
||||
unstableHighVelocityEffect = model->unstableHighVelocityEffect;
|
||||
unstableStopedTurnEffect = model->unstableStopedTurnEffect;
|
||||
|
||||
// Angle fields converted from degrees to radians.
|
||||
Wword(0x159) = (int)(model->lookLeftAngle * DegreesToRadians); // +0x50
|
||||
Wword(0x15a) = (int)(model->lookRightAngle * DegreesToRadians); // +0x54
|
||||
Wword(0x15b) = (int)(model->lookFrontAngle * DegreesToRadians); // +0x58
|
||||
Wword(0x15c) = (int)(model->lookBackAngle * DegreesToRadians); // +0x5c
|
||||
// Angle fields converted from degrees to radians. (task #68: REAL members
|
||||
// now -- the look-state commit consumes them; were Wword scratch parks.)
|
||||
lookLeftAngle = model->lookLeftAngle * DegreesToRadians; // +0x50 -> @0x564
|
||||
lookRightAngle = model->lookRightAngle * DegreesToRadians; // +0x54 -> @0x568
|
||||
lookFrontAngle = model->lookFrontAngle * DegreesToRadians; // +0x58 -> @0x56C
|
||||
lookBackAngle = model->lookBackAngle * DegreesToRadians; // +0x5c -> @0x570
|
||||
// The update-record deadbands (task #3; the struct is now the verified
|
||||
// 200-byte overlay, so the named fields ARE the raw offsets).
|
||||
updateTurnAngleDeadband = model->updateTurnDegreeDiffrence * DegreesToRadians; // @0x770
|
||||
|
||||
@@ -299,6 +299,7 @@ struct ShotDescriptor
|
||||
{
|
||||
friend class Mech__DamageZone; // per-zone damage code reads the roster / segment table
|
||||
friend struct MechBaseLayoutCheck; // base-region layout locks (mech4.cpp; P3 STEP-6 audit)
|
||||
friend void BTCommitLookState(void *, int); // task #68: the look-state commit (mech4.cpp)
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Shared Data Support
|
||||
//
|
||||
@@ -726,7 +727,19 @@ protected:
|
||||
// (F7) `Scalar maxSpeed @0x400` was a MISREAD -- the binary attribute
|
||||
// table names 0x400 DistanceToMissile (id 56; FLT_MAX = far default);
|
||||
// the member is retired in favor of distanceToMissile below.
|
||||
int stateFlags; // @0x410 this[0x104] (binary attr table: RearFiring, id 50)
|
||||
// (task #68) REAR-FIRING (binary attr id 50 @0x410; the old name was
|
||||
// `stateFlags`): OR of every mounted weapon's rearFiring flag -- "this
|
||||
// mech carries a rear arsenal". The look-back view arms those weapons.
|
||||
int rearFiring; // @0x410 this[0x104]
|
||||
// (task #68) the authored look-view angles (model record +0x50..0x5c,
|
||||
// ctor converts degrees->radians; binary @0x564..0x570 -- previously
|
||||
// parked in the Wword scratch bank). Consumed by the look-state
|
||||
// commit: side views yaw by these, look-back = yaw pi + lookBackAngle
|
||||
// pitch, look-down pitches by lookFrontAngle.
|
||||
Scalar lookLeftAngle; // @0x564
|
||||
Scalar lookRightAngle; // @0x568
|
||||
Scalar lookFrontAngle; // @0x56C
|
||||
Scalar lookBackAngle; // @0x570
|
||||
int throttleState; // @0x4a4 this[0x129] = 2 (initial)
|
||||
int heatLevel; // @0x518 this[0x146]
|
||||
int heatCapacity; // @0x51c this[0x147] = 0.6 * heatLevel
|
||||
|
||||
@@ -651,6 +651,7 @@ static int gBTPPCKey = 0;
|
||||
static int gBTMissileKey = 0;
|
||||
static int gBTPinkyKey = 0; // key '4' = the pod's 4th fire button (Pinky 0x45)
|
||||
int gBTModeCycle = 0; // 'M' edge: cycle the control mode (mapper consumes)
|
||||
int gBTLookBehind = 0; // 'V' held: the pod's rear-view button (task #68)
|
||||
float gBTTwistAxis = 0.0f; // Q/E torso-twist deflection (assisted-mode stick X)
|
||||
int gBTTorsoRecenter = 0; // 'X' edge: pulse the authentic torso recenter (mapper consumes)
|
||||
static int gBTConfigKey = 0; // task #6: HOLD 'G' = the weapon-configure button
|
||||
@@ -2606,6 +2607,10 @@ void
|
||||
const int mNow = focused && (pAsync('M') & dn) ? 1 : 0;
|
||||
if (mNow && !sPrevM) gBTModeCycle = 1; // edge -> one cycle
|
||||
sPrevM = mNow;
|
||||
// (task #68) 'V' HELD = look behind (the pod's rear-view
|
||||
// button; releases back to the forward view). Rear-mounted
|
||||
// weapons (blackhawk/owens back racks) fire only in it.
|
||||
gBTLookBehind = focused && (pAsync('V') & dn) ? 1 : 0;
|
||||
const int tw = (focused && (pAsync('E') & dn) ? 1 : 0)
|
||||
- (focused && (pAsync('Q') & dn) ? 1 : 0);
|
||||
static float sTwist = 0.0f;
|
||||
@@ -6148,3 +6153,80 @@ void BTReportIncomingMissile(Entity *target, Scalar range)
|
||||
((Mech *)target)->ReportIncomingMissile(range);
|
||||
}
|
||||
}
|
||||
|
||||
//###########################################################################
|
||||
// Rear-fire / look-view bridges (task #68)
|
||||
//
|
||||
// The binary's controls mapper (part_013.c:396-459) runs a five-state LOOK
|
||||
// machine off the pod's look buttons: on a state change it re-aims the
|
||||
// eyepoint (mech+0x360 = EyepointRotation, consumed by DPLEyeRenderable)
|
||||
// and re-arms each weapon's view-fire enable (+0x3E0): FORWARD view enables
|
||||
// the non-rear weapons, LOOK-BACK enables the REAR-mounted ones (+0x334,
|
||||
// set from the mount segment's 'b' marker -- sitelbgunport/siterbgunport),
|
||||
// side/down views disable all fire. Complete-Mech/Weapon TU bridges; the
|
||||
// mapper calls BTCommitLookState on each state change.
|
||||
//###########################################################################
|
||||
int BTWeaponMountIsRear(void *ownerMech, int segIndex)
|
||||
{
|
||||
Mech *m = (Mech *)ownerMech;
|
||||
if (m == 0)
|
||||
return 0;
|
||||
EntitySegment *seg = m->GetSegment(segIndex);
|
||||
if (seg == 0)
|
||||
return 0;
|
||||
const char *segname = seg->GetName(); // CString -> const char*
|
||||
if (segname == 0)
|
||||
return 0;
|
||||
// the binary marker @0x511aa2 is the single character "b" (the back
|
||||
// gun-port site names are the only port names containing it)
|
||||
int rear = (strstr(segname, "b") != 0) ? 1 : 0;
|
||||
if (getenv("BT_PROJ_LOG")) { static int s_rn=0; if (s_rn++<40)
|
||||
DEBUG_STREAM << "[rearfire] segIndex=" << segIndex << " name='"
|
||||
<< segname << "' rear=" << rear << "\n" << std::flush; }
|
||||
return rear;
|
||||
}
|
||||
|
||||
void BTCommitLookState(void *mech_v, int look_state)
|
||||
{
|
||||
Mech *m = (Mech *)mech_v;
|
||||
if (m == 0)
|
||||
return;
|
||||
|
||||
// eyepoint per state (binary case switch: yaw = the authored side angles,
|
||||
// look-back = yaw pi (0x40490fdb) + lookBackAngle pitch, look-down =
|
||||
// lookFrontAngle pitch)
|
||||
Scalar pitch = 0.0f, yaw = 0.0f;
|
||||
switch (look_state)
|
||||
{
|
||||
case 1: /*LookLeft*/ yaw = m->lookLeftAngle; break;
|
||||
case 2: /*LookRight*/ yaw = m->lookRightAngle; break;
|
||||
case 3: /*LookBehind*/ yaw = PI; // binary 0x40490fdb
|
||||
pitch = m->lookBackAngle; break;
|
||||
case 4: /*LookDown*/ pitch = m->lookFrontAngle; break;
|
||||
default: break; // LookNone: identity
|
||||
}
|
||||
m->eyepointRotation = EulerAngles(
|
||||
Radian(Radian::Normalize(pitch)),
|
||||
Radian(Radian::Normalize(yaw)),
|
||||
Radian(0.0f));
|
||||
|
||||
// weapon view-fire enables (binary: fwd = !rear, back = rear, else 0)
|
||||
{
|
||||
extern int BTWeaponIsRearFiring(Subsystem *sub); // -1 = not a weapon
|
||||
extern void BTWeaponSetViewFireEnable(Subsystem *sub, int enable);
|
||||
for (int id = 2; id < m->GetSubsystemCount(); ++id)
|
||||
{
|
||||
Subsystem *sub = m->GetSubsystem(id);
|
||||
int rf = BTWeaponIsRearFiring(sub);
|
||||
if (rf < 0)
|
||||
continue;
|
||||
BTWeaponSetViewFireEnable(sub,
|
||||
(look_state == 0) ? (rf == 0) :
|
||||
(look_state == 3) ? rf : 0);
|
||||
}
|
||||
}
|
||||
if (getenv("BT_KEY_LOG"))
|
||||
DEBUG_STREAM << "[look] state=" << look_state
|
||||
<< " rearFiring=" << m->rearFiring
|
||||
<< " yaw=" << yaw << " pitch=" << pitch << "\n" << std::flush;
|
||||
}
|
||||
|
||||
@@ -697,6 +697,12 @@ void
|
||||
}
|
||||
throttlePosition = (key_throttle >= 0.0f) ? key_throttle : -key_throttle;
|
||||
reverseThrust = (key_throttle < 0.0f) ? 1 : 0;
|
||||
// (task #68) look-behind: hold 'V' = the pod's rear-view button.
|
||||
// (The other look buttons stay unbound on the keyboard rig.)
|
||||
{
|
||||
extern int gBTLookBehind;
|
||||
lookBehind = gBTLookBehind;
|
||||
}
|
||||
// CONTROL-MODE AXIS ROUTING (2026-07-13, the pod mapping): in
|
||||
// BASIC the stick steers the legs (turn) and the torso auto-
|
||||
// centers; in STANDARD/VETERAN the stick is the TORSO (free aim /
|
||||
@@ -893,14 +899,16 @@ void
|
||||
|
||||
if (lookState != previousLookState)
|
||||
{
|
||||
// TODO(look-eyepoint): the commit block below writes the eyepoint pose at
|
||||
// binary offsets whose Mech-member mapping is CONFLICTED (mech+0x360 is
|
||||
// claimed by mechName, +0x410 by stateFlags, +0x7bc by weaponRoster --
|
||||
// and the old draft even routed them through the TORSO pointer). Arbitrate
|
||||
// those labels against the raw before enabling; the port has no eyepoint
|
||||
// consumer yet. Look-state SELECTION above stays live (this-only).
|
||||
DEBUG_STREAM << "[mppr] look state -> " << lookState
|
||||
<< " (eyepoint commit deferred)\n" << std::flush;
|
||||
// (task #68) the look commit is LIVE: the conflicted labels are
|
||||
// arbitrated (mech+0x360 = EyepointRotation -- the eye renderable
|
||||
// consumes it; +0x410 = RearFiring; the +0x7bc children = the WEAPON
|
||||
// roster, not cameras). BTCommitLookState (mech4.cpp complete-type
|
||||
// TU) re-aims the eyepoint and re-arms each weapon's viewFireEnable:
|
||||
// forward view = the non-rear weapons, LOOK-BACK = the rear-mounted
|
||||
// ones, side/down = none.
|
||||
extern void BTCommitLookState(void *mech, int look_state);
|
||||
BTCommitLookState((void *)mech, (int)lookState);
|
||||
DEBUG_STREAM << "[mppr] look state -> " << lookState << "\n" << std::flush;
|
||||
}
|
||||
else if (0) // DEFERRED body (kept for the reconstruction record)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -398,7 +398,17 @@ class CockpitHud;
|
||||
Scalar weaponRange; // @0x32C resource WeaponRange (configured max)
|
||||
int estimatedReadyTime; // @0x330 reset 0 (binary attr 0x1A "EstimatedReadyTime"
|
||||
// names this slot -- resolves the old pipState TODO)
|
||||
Logical usesExternalModel; // @0x334 the "EXT" model-name marker; the binary attr
|
||||
public:
|
||||
// (task #68) rear-fire accessors for the complete-type bridges
|
||||
int GetRearFiring() const { return (int)rearFiring; }
|
||||
void SetViewFireEnable(int enable) { viewFireEnable = enable ? True : False; }
|
||||
protected:
|
||||
Logical rearFiring; // @0x334 REAR-MOUNTED weapon (task #68): the binary ctor
|
||||
// sets it iff the MOUNT SEGMENT's page name contains 'b'
|
||||
// (marker @0x511aa2; the back ports sitelbgunport/
|
||||
// siterbgunport -- blackhawk + owens author them). The
|
||||
// old "EXT in the weapon name" was a double misread.
|
||||
// The binary attr
|
||||
// 0x1B names this slot "RearFiring" (an EXT/rear-mount
|
||||
// weapon fires backward)
|
||||
int pipPosition; // @0x338 resource PipPosition
|
||||
@@ -415,7 +425,11 @@ class CockpitHud;
|
||||
|
||||
Scalar heatCostToFire; // @0x3D8 resource HeatCostToFire
|
||||
Scalar rechargeRate; // @0x3DC resource RechargeRate
|
||||
Logical useConfiguredPip; // @0x3E0 = (usesExternalModel == 0) (best-effort)
|
||||
Logical viewFireEnable; // @0x3E0 "enabled in the CURRENT look view" (task #68):
|
||||
// forward view = !rearFiring, rear view = rearFiring,
|
||||
// side/down views = 0 (the mapper look-state commit
|
||||
// toggles it). Gates BOTH firing (the emitter
|
||||
// Loaded->Firing gate reads it) and the HUD pip.
|
||||
ResourceDescription::ResourceID
|
||||
explosionResourceID; // @0x3E4 resource ExplosionModelFile
|
||||
public:
|
||||
@@ -433,7 +447,7 @@ class CockpitHud;
|
||||
// collided with the Emitter subclass's own fields at 0x3F0+; removed:
|
||||
// * segmentReference -> the muzzle segment is the inherited base slot this+0xdc
|
||||
// (GetMuzzlePoint resolves it live via the mech4 BTResolveWeaponMuzzle bridge)
|
||||
// * pipSegment -> DrawWeaponPip gates on useConfiguredPip
|
||||
// * pipSegment -> DrawWeaponPip gates on viewFireEnable
|
||||
// * hasTarget -> dead (HasActiveTarget reads owner+0x388)
|
||||
// * targetPoint -> GetTargetPosition reads owner+0x37c
|
||||
// * muzzlePoint -> resolved live by GetMuzzlePoint
|
||||
|
||||
@@ -267,6 +267,12 @@ void MissileLauncher::FireWeapon()
|
||||
{
|
||||
Check(this);
|
||||
|
||||
// (task #68) the view gate: a weapon disabled in the CURRENT look view
|
||||
// (rear rack in the forward view, anything in a side view) does not fire
|
||||
// -- the same +0x3E0 gate the emitter's Loaded->Firing transition reads.
|
||||
if (!viewFireEnable)
|
||||
return;
|
||||
|
||||
// THE FIRING HEAT (task #9): heatCostToFire RAW into the launcher's own
|
||||
// pendingHeat (pre-scaled 1e7-unit resources: SRM6 = 5e7, LRM15 = 6.5e7)
|
||||
// -- the binary's add @part_013.c:8744-8747, gated on the heatable check.
|
||||
|
||||
@@ -703,6 +703,11 @@ void
|
||||
{
|
||||
Check(this);
|
||||
|
||||
// (task #68) the view gate: a weapon disabled in the CURRENT look view
|
||||
// does not fire (see mislanch.cpp / the emitter's Loaded->Firing gate).
|
||||
if (!viewFireEnable)
|
||||
return;
|
||||
|
||||
// THE FIRING HEAT (task #9; was "a separate pre-existing gap"): the
|
||||
// binary adds heatCostToFire RAW to the weapon's own pendingHeat --
|
||||
// projectile resources author PRE-scaled 1e7-unit heat (AFC100 = 6.5e7)
|
||||
|
||||
Reference in New Issue
Block a user