Mech phase 4: the Mech constructor + segment walk WORKS -- roster instantiates live
The Mech ctor now finds the model's subsystem-model-stream resource (SearchList by SubsystemModelStreamResourceType), wraps it in a MemoryStream, and walks the segments -- switching on seg->classID to into the base Entity's subsystemArray, caching sensor/gyro/sinkSource/hud and counting weapons. KEY FINDING: the source410 VDATA ClassID values MATCH the 4.10 binary for the core subsystems (0xBBD=Condenser, 0xBC3=Sensor, 0xBC5=Torso, 0xBD6=HUD, ...) -- BT411's 'mislabels' were its OWN wrong enum names. So the walk switches on the real VDATA names cleanly. Unrecognised classIDs leave a NULL slot (roster stays aligned) rather than aborting. LIVE: boot now runs the full Mech ctor -- segment walk instantiates the roster, no crash -- and advances PAST it to BTL4Application::MakeViewpointEntity, which halts at 'Mech has no controls mapping!' (the slot-0 control mapper / SetMappingSubsystem is the next brick). The largest function in the game executes. BT: 42 ok; tree links clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -19,6 +19,37 @@
|
||||
# include <mech.hpp>
|
||||
#endif
|
||||
|
||||
#if !defined(APP_HPP)
|
||||
# include <app.hpp>
|
||||
#endif
|
||||
#if !defined(MEMSTRM_HPP)
|
||||
# include <memstrm.hpp>
|
||||
#endif
|
||||
#if !defined(RESOURCE_HPP)
|
||||
# include <resource.hpp>
|
||||
#endif
|
||||
|
||||
// The subsystem roster the segment walk instantiates.
|
||||
#include <heat.hpp> // HeatableSubsystem, HeatSink, HeatWatcher, Condenser
|
||||
#include <powersub.hpp> // PoweredSubsystem, PowerWatcher, Generator
|
||||
#include <reservr.hpp> // Reservoir
|
||||
#include <sensor.hpp> // Sensor
|
||||
#include <gyro.hpp> // Gyroscope
|
||||
#include <torso.hpp> // Torso
|
||||
#include <myomers.hpp> // Myomers
|
||||
#include <hud.hpp> // HUD
|
||||
#include <searchlt.hpp> // Searchlight
|
||||
#include <thermsgt.hpp> // ThermalSight
|
||||
#include <mechtech.hpp> // MechTech
|
||||
#include <messmgr.hpp> // SubsystemMessageManager
|
||||
#include <mechweap.hpp> // MechWeapon
|
||||
#include <emitter.hpp> // Emitter
|
||||
#include <ppc.hpp> // PPC
|
||||
#include <gauss.hpp> // GaussRifle
|
||||
#include <projweap.hpp> // ProjectileWeapon
|
||||
#include <mislanch.hpp> // MissileLauncher
|
||||
#include <ammobin.hpp> // AmmoBin
|
||||
|
||||
//
|
||||
//#############################################################################
|
||||
//#############################################################################
|
||||
@@ -118,10 +149,151 @@ Mech::Mech(
|
||||
}
|
||||
|
||||
//
|
||||
// The segment-table walk (subsystem instantiation + capability-chain
|
||||
// wiring) is not yet reconstructed. See MECHSUB.NOTES.md for the blueprint.
|
||||
//-----------------------------------------------------------------------
|
||||
// Segment-table walk: instantiate one Subsystem per streamed segment,
|
||||
// dispatching on its classID. The subsystem roster (subsystemArray /
|
||||
// subsystemCount) lives in the base Entity.
|
||||
//-----------------------------------------------------------------------
|
||||
//
|
||||
Fail("Mech::Mech -- segment walk not yet reconstructed");
|
||||
ResourceDescription::ResourceID modelResourceID = creation_message->resourceID;
|
||||
|
||||
ResourceDescription *subsystemDesc =
|
||||
application->GetResourceFile()->SearchList(
|
||||
modelResourceID,
|
||||
ResourceDescription::SubsystemModelStreamResourceType
|
||||
);
|
||||
Check(subsystemDesc);
|
||||
subsystemDesc->Lock();
|
||||
|
||||
//
|
||||
// Copy the raw stream into a padded buffer: reading a SubsystemResource
|
||||
// struct off the tail segment can over-read the raw resource, so pad it.
|
||||
//
|
||||
size_t rawSize = (size_t)subsystemDesc->resourceSize;
|
||||
size_t padSize = rawSize + 0x400;
|
||||
void *padBuffer = (void *)new char[padSize];
|
||||
memcpy(padBuffer, subsystemDesc->resourceAddress, rawSize);
|
||||
|
||||
MemoryStream subsystemStream(padBuffer, padSize);
|
||||
|
||||
int streamedSubsystemCount = *(int *)subsystemStream.GetPointer();
|
||||
subsystemStream.AdvancePointer(sizeof(int));
|
||||
|
||||
//
|
||||
// Slot 0 = the (later-installed) control mapper, slot 1 = the voltage bus
|
||||
// sentinel; the streamed subsystems fill from slot 2.
|
||||
//
|
||||
subsystemCount = streamedSubsystemCount + 2;
|
||||
subsystemArray = new Subsystem *[subsystemCount];
|
||||
{
|
||||
for (int z = 0; z < subsystemCount; ++z)
|
||||
{
|
||||
subsystemArray[z] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
for (int id = 2; id < subsystemCount; ++id)
|
||||
{
|
||||
Subsystem::SubsystemResource *seg =
|
||||
(Subsystem::SubsystemResource *)subsystemStream.GetPointer();
|
||||
|
||||
Subsystem *made = NULL;
|
||||
|
||||
switch (seg->classID)
|
||||
{
|
||||
case CondenserClassID:
|
||||
made = new Condenser(this, id, (Condenser::SubsystemResource *)seg);
|
||||
break;
|
||||
case HeatSinkClassID:
|
||||
made = new HeatSink(this, id, (HeatSink::SubsystemResource *)seg);
|
||||
break;
|
||||
case HeatWatcherClassID:
|
||||
made = new HeatWatcher(this, id, (HeatWatcher::SubsystemResource *)seg);
|
||||
break;
|
||||
case ReservoirClassID:
|
||||
made = new Reservoir(this, id, (Reservoir::SubsystemResource *)seg);
|
||||
break;
|
||||
case GeneratorClassID:
|
||||
made = new Generator(this, id, (Generator::SubsystemResource *)seg);
|
||||
break;
|
||||
case PoweredSubsystemClassID:
|
||||
made = new PoweredSubsystem(this, id, (PoweredSubsystem::SubsystemResource *)seg);
|
||||
break;
|
||||
case SensorClassID:
|
||||
made = new Sensor(this, id, (Sensor::SubsystemResource *)seg);
|
||||
sensorSubsystem = made;
|
||||
break;
|
||||
case GyroscopeClassID:
|
||||
made = new Gyroscope(this, id, (Gyroscope::SubsystemResource *)seg);
|
||||
gyroSubsystem = made;
|
||||
break;
|
||||
case TorsoClassID:
|
||||
made = new Torso(this, id, (Torso::SubsystemResource *)seg);
|
||||
sinkSourceSubsystem = made;
|
||||
break;
|
||||
case MyomersClassID:
|
||||
made = new Myomers(this, id, (Myomers::SubsystemResource *)seg);
|
||||
break;
|
||||
case EmitterClassID:
|
||||
made = new Emitter(this, id, (Emitter::SubsystemResource *)seg);
|
||||
++weaponCount;
|
||||
break;
|
||||
case PPCClassID:
|
||||
made = new PPC(this, id, (PPC::SubsystemResource *)seg, PPC::DefaultData);
|
||||
++weaponCount;
|
||||
break;
|
||||
case AmmoBinClassID:
|
||||
made = new AmmoBin(this, id, (AmmoBin::SubsystemResource *)seg);
|
||||
break;
|
||||
case ProjectileWeaponClassID:
|
||||
made = new ProjectileWeapon(this, id, (ProjectileWeapon::SubsystemResource *)seg);
|
||||
++weaponCount;
|
||||
break;
|
||||
case GaussRifleClassID:
|
||||
made = new GaussRifle(this, id, (GaussRifle::SubsystemResource *)seg);
|
||||
++weaponCount;
|
||||
break;
|
||||
case MissileLauncherClassID:
|
||||
made = new MissileLauncher(this, id, (MissileLauncher::SubsystemResource *)seg);
|
||||
++weaponCount;
|
||||
break;
|
||||
case SubsystemMessageManagerClassID:
|
||||
made = new SubsystemMessageManager(this, id, (SubsystemMessageManager::SubsystemResource *)seg);
|
||||
messageManager = (SubsystemMessageManager *)made;
|
||||
break;
|
||||
case HUDClassID:
|
||||
made = new HUD(this, id, (HUD::SubsystemResource *)seg);
|
||||
hudSubsystem = made;
|
||||
break;
|
||||
case SearchlightClassID:
|
||||
made = new Searchlight(this, id, (Searchlight::SubsystemResource *)seg);
|
||||
break;
|
||||
case ThermalSightClassID:
|
||||
made = new ThermalSight(this, id, (ThermalSight::SubsystemResource *)seg);
|
||||
break;
|
||||
case MechTechClassID:
|
||||
made = new MechTech(this, id, (MechTech::SubsystemResource *)seg);
|
||||
break;
|
||||
default:
|
||||
//
|
||||
// Unrecognised / not-yet-reconstructed subsystem class (e.g.
|
||||
// Laser, ParticleCannon, Capacitor, AmmoFeeder, Radar, Turret):
|
||||
// leave the slot NULL so the roster stays aligned rather than
|
||||
// aborting the whole mech.
|
||||
//
|
||||
made = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
subsystemArray[id] = made;
|
||||
|
||||
subsystemStream.AdvancePointer(seg->subsystemModelSize);
|
||||
}
|
||||
|
||||
subsystemDesc->Unlock();
|
||||
delete [] (char *)padBuffer;
|
||||
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
Mech::~Mech()
|
||||
|
||||
Reference in New Issue
Block a user