Completes the weapon-side half of the look commit: - MECHWEAP: real rearFiring/viewFireEnable members (binary @0x334/@0x3E0) + accessors. Ctor resolves REAR-FIRING authentically (@004b99a8 tail): the mount SEGMENT site name is tested for the 'b' (back) marker -- only the back gun ports (sitelbgunport/siterbgunport) carry it. Spawn = forward-armed. - MECH CommitLookState: re-arms every roster weapon per view (forward = non-rear, LOOK-BACK = rear-mounted, side/down = none) and flips the HUD reticle pip group with the authentic Reticle::Front/RearFiringWeaponsOn flags (BT411's raw "bits 1/2" resolved to their 1995 names). - MECHWEAP: defined MechWeapon::MessageHandlers (0-entry set inheriting the Subsystem chain) -- it was declared-but-undefined, and the surviving CODE PPC.CPP binds the inherited name into PPC::DefaultData; the zero-filled common block was a latent NULL deref (same trap as Emitter::AttributeIndex). Discovery: the TEST.EGG mech genuinely mounts TWO REAR LASERS (ERMLaser_2/3 on the b-ports). Verified on a full-clean baseline (engine 181 + bt 42, 0 fail): look-behind arms exactly the rear lasers, disarms the other five, pipMask=0xfffffffe; neutral run holds forward-armed; zero Fail. build410.sh HARDENED against the stale-obj layout-skew trap this wave exposed: cc() skipped recompiles on obj-vs-.cpp timestamps only, so the MECHWEAP.HPP member additions left emitter.obj on the OLD MechWeapon layout -- its chargeLevel=0.0f write landed exactly on the new rearFiring (a silent cross-TU struct skew, heisenbug-grade). cc() now honors header stamps: a source410 engine-header edit invalidates every bucket, a BT/BT_L4 header edit additionally invalidates the game buckets. CODE/ is immutable, no stamp needed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
182 lines
5.2 KiB
C++
182 lines
5.2 KiB
C++
//===========================================================================//
|
|
// File: mechweap.cpp //
|
|
// Project: BattleTech Brick: Mech weapons //
|
|
// Contents: MechWeapon -- the base weapon subsystem //
|
|
//---------------------------------------------------------------------------//
|
|
// Copyright (C) 1995, Virtual World Entertainment, Inc. //
|
|
// All Rights reserved worldwide //
|
|
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
|
|
//===========================================================================//
|
|
|
|
#include <bt.hpp>
|
|
#pragma hdrstop
|
|
|
|
#if !defined(MECHWEAP_HPP)
|
|
# include <mechweap.hpp>
|
|
#endif
|
|
|
|
#if !defined(MECH_HPP)
|
|
# include <mech.hpp>
|
|
#endif
|
|
|
|
#if !defined(SEGMENT_HPP)
|
|
# include <segment.hpp>
|
|
#endif
|
|
|
|
#include <string.h>
|
|
|
|
Derivation
|
|
MechWeapon::ClassDerivations(
|
|
PoweredSubsystem::ClassDerivations,
|
|
"MechWeapon"
|
|
);
|
|
|
|
//
|
|
//#############################################################################
|
|
// Message handlers. MechWeapon publishes no handlers of its own yet (the
|
|
// weapon fire/damage handler wave), but the set MUST be a real defined object:
|
|
// the surviving CODE PPC.CPP binds the inherited name (`PPC::MessageHandlers`)
|
|
// into PPC::DefaultData, and a declared-but-undefined static links as a
|
|
// zero-filled common block -- the same silent-NULL trap as the
|
|
// Emitter::AttributeIndex crash (see MECHWEAP.NOTES.md).
|
|
//#############################################################################
|
|
//
|
|
MechWeapon::MessageHandlerSet
|
|
MechWeapon::MessageHandlers(
|
|
0,
|
|
NULL,
|
|
Subsystem::MessageHandlers
|
|
);
|
|
|
|
MechWeapon::SharedData
|
|
MechWeapon::DefaultData(
|
|
MechWeapon::ClassDerivations,
|
|
MechWeapon::MessageHandlers,
|
|
Subsystem::AttributeIndex,
|
|
Subsystem::StateCount
|
|
);
|
|
|
|
MechWeapon::MechWeapon(
|
|
Mech *owner,
|
|
int subsystem_ID,
|
|
SubsystemResource *subsystem_resource,
|
|
SharedData &shared_data
|
|
):
|
|
PoweredSubsystem(owner, subsystem_ID, subsystem_resource, shared_data)
|
|
{
|
|
Check(owner);
|
|
Check_Pointer(subsystem_resource);
|
|
|
|
rechargeRate = subsystem_resource->rechargeRate;
|
|
weaponRange = subsystem_resource->weaponRange;
|
|
damageAmount = subsystem_resource->damageAmount;
|
|
damageType = subsystem_resource->damageType;
|
|
heatCostToFire = subsystem_resource->heatCostToFire;
|
|
targetWithinRange = False;
|
|
|
|
damageData.damageType = damageType;
|
|
damageData.damageAmount = damageAmount;
|
|
|
|
//
|
|
// REAR-FIRING resolve (the binary ctor tail @004b99a8): a weapon is
|
|
// rear-mounted when its MOUNT SEGMENT's site name carries the 'b' (back)
|
|
// marker -- the back gun ports (sitelbgunport / siterbgunport) are the only
|
|
// port names containing it. Rear-mounted weapons fire only into the
|
|
// LOOK-BACK view; everything else fires forward. The look-state commit
|
|
// (Mech::CommitLookState) re-arms viewFireEnable on every view change; a
|
|
// weapon spawns armed for the forward view.
|
|
//
|
|
rearFiring = False;
|
|
{
|
|
EntitySegment *mount = owner->GetSegment(GetSegmentIndex());
|
|
if (mount != NULL)
|
|
{
|
|
const char *mount_name = mount->GetName();
|
|
if (mount_name != NULL && strstr(mount_name, "b") != NULL)
|
|
{
|
|
rearFiring = True;
|
|
}
|
|
}
|
|
}
|
|
viewFireEnable = (rearFiring == False);
|
|
|
|
if (getenv("BT_MECH_LOG"))
|
|
{
|
|
EntitySegment *mount = owner->GetSegment(GetSegmentIndex());
|
|
DEBUG_STREAM << "[weap] '" << GetName()
|
|
<< "' seg=" << GetSegmentIndex() << " mount=";
|
|
if (mount != NULL)
|
|
{
|
|
DEBUG_STREAM << mount->GetName();
|
|
}
|
|
else
|
|
{
|
|
DEBUG_STREAM << "<none>";
|
|
}
|
|
DEBUG_STREAM << " rear=" << (int)rearFiring << endl << flush;
|
|
}
|
|
|
|
Check_Fpu();
|
|
}
|
|
|
|
MechWeapon::~MechWeapon()
|
|
{
|
|
}
|
|
|
|
Logical
|
|
MechWeapon::TestClass(Mech &)
|
|
{
|
|
return True;
|
|
}
|
|
|
|
Logical
|
|
MechWeapon::TestInstance() const
|
|
{
|
|
return IsDerivedFrom(ClassDerivations);
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
// FireWeapon Abstract -- each concrete weapon (Emitter/PPC, ProjectileWeapon/
|
|
// Gauss/MissileLauncher) overrides this. Reaching the base is a bug.
|
|
//#############################################################################
|
|
//
|
|
void
|
|
MechWeapon::FireWeapon()
|
|
{
|
|
Fail("MechWeapon::FireWeapon -- should not be here (abstract)");
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
// SendDamage Deliver this weapon's damage to a struck entity. The damage/
|
|
// networking path is not yet reconstructed.
|
|
//#############################################################################
|
|
//
|
|
void
|
|
MechWeapon::SendDamage(Entity *, Damage &)
|
|
{
|
|
Fail("MechWeapon::SendDamage -- mechweap.cpp not yet reconstructed");
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
// CreateStreamedSubsystem Model-load-time construction. Not yet reconstructed.
|
|
//#############################################################################
|
|
//
|
|
int
|
|
MechWeapon::CreateStreamedSubsystem(
|
|
ResourceFile *,
|
|
NotationFile *,
|
|
const char *,
|
|
const char *,
|
|
SubsystemResource *,
|
|
NotationFile *,
|
|
const ResourceDirectories *,
|
|
int
|
|
)
|
|
{
|
|
Fail("MechWeapon::CreateStreamedSubsystem -- mechweap.cpp not yet reconstructed");
|
|
return 0;
|
|
}
|