//============================================================================// // File: seeker.hpp // // Project: BattleTech // // Contents: A subsystem which guides, seeks out and finds a target // //----------------------------------------------------------------------------// // Date Who Modification // // -------- --- ------------------------------------------------------------// // 04/13/95 JM Initial coding. // // 07/12/95 GDU Complied with new libraries, added seeker logic // //----------------------------------------------------------------------------// // Copyright (C) 1995, Virtual World Entertainment, Inc. All Rights reserved // // PROPRIETARY AND CONFIDENTIAL // //============================================================================// // // RECONSTRUCTED from the shipped binary (Ghidra pseudo-C, module cluster // @004bec34-@004bee70 in part_013.c) cross-referenced HEAVILY against the // SURVIVING SEEKER.HPP and the MUNGA SUBSYSTM.HPP base interface. The class // declaration below is the surviving header; the only additions are the byte // offsets observed in the decompiled object (see seeker.cpp for per-method // @ADDR evidence). // // Inheritance chain established from the decomp: // Simulation -> Subsystem (FUN_0041c52c base ctor) -> Seeker // The Seeker ctor (@004bec34) installs vtable PTR_LAB_00512ce8 and chains to // the Subsystem base ctor @0041c52c with the shared resource &DAT_00512bec. // Every vtable slot other than the destructor inherits the Subsystem base // (vtable @00512ce8 holds only 0x41xxxx engine slots), so the Seeker's real // behaviour lives in the non-virtual Performance method LeadTarget(). // // Field offsets in comments are byte offsets into the shipped object; the // Subsystem base occupies everything below +0xE4. Member names are taken // verbatim from the surviving SEEKER.HPP. // #if !defined (SEEKER_HPP) #define SEEKER_HPP #if !defined(SUBSYSTM_HPP) #include #endif #if !defined(POINT3D_HPP) #include #endif //######################### Forward Class Declarations ######################## class Missile; class Entity; //######################### Seeker Subsystem Resource ########################## // // The Seeker carries no resource fields of its own -- the shared default // record &DAT_00512bec (resolved at @004bec34) is the bare Subsystem record. // struct Seeker__SubsystemResource: public Subsystem::SubsystemResource { }; //########################################################################### //######################### CLASS -- Seeker ########################## //########################################################################### // // (vtable @00512ce8, ctor @004bec34, dtor @004bee44.) // class Seeker : public Subsystem { //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Messaging Support // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Shared Data Support // public: static Derivation ClassDerivations; static Receiver::MessageHandlerSet MessageHandlers; static SharedData DefaultData; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Attribute Support // // Attribute IDs verified against the IndexEntry table @00512d50: // TargetPositionAttributeID == 0x341 (string @0051012e "...") // RangeToTargetAttributeID == 0x345 // RangeFromCreationAttributeID == 0x34d // public: enum { TargetPositionAttributeID = Subsystem::NextAttributeID, RangeToTargetAttributeID, RangeFromCreationAttributeID, NextAttributeID }; private: static const IndexEntry AttributePointers[]; protected: static AttributeIndexSet AttributeIndex; // // public attribute declarations go here // public: Point3D targetPosition; // @0xE4 for thruster (lead/aim point) Point3D creationPoint; // @0xF0 where the missile was fired from Entity *targetEntity; // @0xFC homing target (0 == dumb-fire) Point3D targetOffset; // @0x100 aim offset within the target Scalar rangeToTarget, // @0x10C distance to targetPosition rangeFromCreation, // @0x110 distance travelled from creationPoint startingRangeToTarget; // @0x114 rangeToTarget sampled at spawn //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Model Support // public: enum { Empty = Subsystem::StateCount, StateCount}; typedef void (Seeker::*Performance)(Scalar time_slice); // @004beae4 -- recompute targetPosition by leading the moving // targetEntity along its velocity (clamped lead window 200..300 m). void LeadTarget(); // FindTarget(time_slice) is the per-frame Performance entry point. In // the shipped binary its body is folded into the Missile guidance pass // (Missile::MoveAndCollide @004bef78, which samples this->targetPosition // at +0x1c4); the standalone update is LeadTarget(). Declared to match // the surviving header and MISSILE.TCP's seeker->FindTarget(time_slice). void FindTarget(Scalar time_slice); void SetPerformance(Performance performance) { Check(this); activePerformance = (Simulation::Performance)performance; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // TestClass Support // public: static Logical TestClass(Missile &); void ResetToInitialState(); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Construction and Destruction // public: typedef Seeker__SubsystemResource SubsystemResource; Seeker ( // @004bec34 Missile *owner, int subsystem_ID, SubsystemResource *subsystem_resource, Entity *target, const Point3D offset ); ~Seeker(); // @004bee44 Logical TestInstance() const; }; #endif