The reconstruction modeled the binary's 0x54 AlarmIndicator (FUN_0041b9ec) with undersized
stand-ins (AlarmIndicator==ReconAlarm==4B; HeatAlarm==8B) across the entire subsystem tree, so
every field above an alarm sat at the wrong compiled offset. Retype every such stand-in to
GaugeAlarm54(0x54) and de-phantom each class against its ctor, so the whole PoweredSubsystem
subtree becomes byte-exact. An 8-agent read-only decomp-mapping workflow decoded every ctor
first; then hands-on implementation. static_assert-locked chain (verified vs the raw ctors):
HeatSink 0x1D0
-> PoweredSubsystem 0x31C retype electricalStateAlarm@0x264 + modeAlarm@0x2B8 @004b0f74
-> MechWeapon 0x3F0 retype weaponAlarm@0x350; delete 5 phantom tail fields @004b99a8
-> Emitter 0x478 delete outputVoltage/beamLengthRatio/firingArmed aliases
+ beamHit*/beamColor/beamHitData/energyRampTime phantoms;
retype beamOrientation EulerAngles->Quaternion(16B) @004bb120
-> PPC 0x478 (no own fields) @004bb888
PoweredSubsystem -> Sensor 0x328 (no alarm; 3 own fields) @004b1d18
PoweredSubsystem -> Myomers 0x358 (no alarm) @004b8fec
New systemic bug-class instances fixed (added to the CLAUDE.md checklist):
* alias field - Emitter outputVoltage==inherited rechargeLevel@0x320; beamLengthRatio==
beamScale.z@0x434; firingArmed==inherited useConfiguredPip@0x3E0
* phantom field - MechWeapon segmentReference/pipSegment/hasTarget/targetPoint/muzzlePoint
(past 0x3F0); Emitter beamHitPoint/beamImpact/beamImpactScalar/beamColor/
beamHitData/energyRampTime (binary writes inherited damageData/voltageScale
or the value is a method local)
Non-layout fixes required in the same wave:
* outputVoltage->rechargeLevel also in the compiled GAUSS.CPP:74/93 (external readers of the
removed Emitter field -- must grep EVERY TU, not just the class's own .cpp)
* MechWeapon::GetMuzzlePoint reimplemented faithfully (removed muzzlePoint collided with
Emitter's own fields at 0x3F0) via a BTResolveWeaponMuzzle void* bridge in mech4.cpp,
resolving the weapon's mount segment (inherited this+0xdc) through the owner segment table
* DetachFromVoltageSource fixed to set electricalStateAlarm not modeAlarm (raw @004b0e30
writes the 0x264 alarm)
The vehicleSubSystems aux-screen gauge raw reads (btl4gau2.cpp:868/952 at subsystem+0x2b8/+0x278)
and the Sensor RadarPercent path now read the CORRECT byte offsets (garbage under the short layout).
Verified: combat DESTROYED-in-8, 28 shots, 0 crashes, heat heatEnergy=1.34e7, every static_assert
lock passes, heapcheck-clean through construction (the phase the isolated PoweredSubsystem retype
had overflowed). LESSON: a factory-bridge runtime Check(sizeof<=alloc) does NOT fail the build --
only a static_assert sizeof lock catches alloc overflow at compile time.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
154 lines
3.7 KiB
C++
154 lines
3.7 KiB
C++
//===========================================================================//
|
|
// File: gauss.cc //
|
|
// Project: BT Brick: Entity Manager //
|
|
// Contents: Basic weapons system pieces //
|
|
//---------------------------------------------------------------------------//
|
|
// Date Who Modification //
|
|
// -------- --- ---------------------------------------------------------- //
|
|
// 04/13/95 JM Initial coding. //
|
|
// 07/19/95 GDU Complied with new munga and added electrical behavior
|
|
//---------------------------------------------------------------------------//
|
|
// Copyright (C) 1995, Virtual World Entertainment, Inc. All Rights reserved //
|
|
//
|
|
// PROPRIETARY AND CONFIDENTIAL //
|
|
//===========================================================================//
|
|
|
|
#include <bt.hpp>
|
|
#pragma hdrstop
|
|
|
|
#if !defined(GAUSS_HPP)
|
|
# include <gauss.hpp>
|
|
#endif
|
|
|
|
//#############################################################################
|
|
// Shared Data Support
|
|
//
|
|
GaussRifle::SharedData
|
|
GaussRifle::DefaultData(
|
|
&GaussRifle::ClassDerivations,
|
|
GaussRifle::MessageHandlers,
|
|
GaussRifle::AttributeIndex,
|
|
GaussRifle::StateCount
|
|
);
|
|
|
|
Derivation
|
|
GaussRifle::ClassDerivations(
|
|
&Emitter::ClassDerivations,
|
|
"GaussRifle"
|
|
);
|
|
|
|
|
|
//#############################################################################
|
|
// Messaging Support
|
|
//
|
|
|
|
#if 0
|
|
//#############################################################################
|
|
// Attribute Support
|
|
//
|
|
|
|
const GaussRifle::IndexEntry
|
|
GaussRifle::AttributePointers[]=
|
|
{
|
|
ATTRIBUTE_ENTRY(GaussRifle, DischargeVoltage, dischargeVoltage)
|
|
};
|
|
|
|
GaussRifle::AttributeIndexSet
|
|
GaussRifle::AttributeIndex(
|
|
ELEMENTS(GaussRifle::AttributePointers),
|
|
GaussRifle::AttributePointers,
|
|
Emitter::AttributeIndex
|
|
);
|
|
#endif
|
|
|
|
//#############################################################################
|
|
// Model Support
|
|
//
|
|
|
|
void
|
|
GaussRifle::FireWeapon()
|
|
{
|
|
//
|
|
// Fire the weapon
|
|
//
|
|
rechargeLevel = 0.0f; // was outputVoltage: the Emitter dup was removed (== inherited rechargeLevel@0x320)
|
|
|
|
Check_Fpu();
|
|
}
|
|
|
|
//#############################################################################
|
|
// Constructer/Destructor Support
|
|
//
|
|
|
|
GaussRifle::GaussRifle(
|
|
Mech *owner,
|
|
int subsystem_ID,
|
|
SubsystemResource *subsystem_resource,
|
|
SharedData &shared_data
|
|
):
|
|
Emitter(owner, subsystem_ID, subsystem_resource, shared_data)
|
|
{
|
|
Check(owner);
|
|
Check_Pointer(subsystem_resource);
|
|
rechargeLevel = 0.0f; // was outputVoltage: the Emitter dup was removed (== inherited rechargeLevel@0x320)
|
|
Check_Fpu();
|
|
}
|
|
|
|
GaussRifle::~GaussRifle()
|
|
{
|
|
Check(this);
|
|
Check_Fpu();
|
|
}
|
|
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// CreateStreamedSubsystem
|
|
//
|
|
Logical
|
|
GaussRifle::CreateStreamedSubsystem(
|
|
ResourceFile *resource_file,
|
|
NotationFile *model_file,
|
|
const char *model_name,
|
|
const char *subsystem_name,
|
|
SubsystemResource *subsystem_resource,
|
|
NotationFile *subsystem_file,
|
|
const ResourceDirectories *directories,
|
|
int passes
|
|
)
|
|
{
|
|
|
|
if (
|
|
!Emitter::CreateStreamedSubsystem(
|
|
resource_file,
|
|
model_file,
|
|
model_name,
|
|
subsystem_name,
|
|
subsystem_resource,
|
|
subsystem_file,
|
|
directories,
|
|
passes
|
|
)
|
|
)
|
|
{
|
|
Check_Fpu();
|
|
return False;
|
|
}
|
|
|
|
|
|
|
|
|
|
subsystem_resource->subsystemModelSize = sizeof(*subsystem_resource);
|
|
subsystem_resource->classID = RegisteredClass::GaussRifleClassID;
|
|
|
|
|
|
Check_Fpu();
|
|
return True;
|
|
}
|
|
|
|
Logical
|
|
GaussRifle::TestInstance() const
|
|
{
|
|
return IsDerivedFrom(ClassDerivations);
|
|
}
|
|
|