//===========================================================================// // File: mechweap.hpp // // Project: BattleTech // // Contents: Implementation details for mech weapons // //---------------------------------------------------------------------------// // Date Who Modification // // -------- --- ---------------------------------------------------------- // // // //---------------------------------------------------------------------------// // Copyright (C) 1995, Virtual World Entertainment, Inc. // // All Rights reserved worldwide // // This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // //===========================================================================// #if !defined(MECHWEAP_HPP) # define MECHWEAP_HPP # if !defined(POWERSUB_HPP) # include # endif # if !defined(DAMAGE_HPP) # include # endif # if !defined(ALARM_HPP) # include # endif //##################### Forward Class Declarations ####################### class Mech; //########################################################################### //###################### MechWeapon Model Resource ###################### //########################################################################### // // WIRE-VERIFIED layout (raw-stream dump vs the BT411 verified overlay): // eleven fields; the pip tail is pipPosition(int) + pipColor(3 floats) + // pipExtendedRange(int). bhk1 PPC reads: recharge 5.0s, range 900, // damage 12, type 4, heatCost 11, pipColor (0,0,1). // struct MechWeapon__SubsystemResource: public PoweredSubsystem::SubsystemResource { Scalar rechargeRate; Scalar weaponRange; ResourceDescription::ResourceID explosionModelFile; Scalar damageAmount; int damageType; Scalar heatCostToFire; int pipPosition; Scalar pipColor[3]; int pipExtendedRange; }; //########################################################################### //############################ MechWeapon ############################### //########################################################################### class MechWeapon: public PoweredSubsystem { //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Shared Data Support // public: static Derivation ClassDerivations; static SharedData DefaultData; static MessageHandlerSet MessageHandlers; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Attribute Support. The real IDs are PINNED to the 1995 binary numbering // (table @0x511890, ids 0x12..0x1C): the streamed per-mech control mappings // reference them by NUMBER -- TriggerState (0x13) is the fire-button binding. // Our parent chain publishes nothing past Subsystem::NextAttributeID (2) // yet, so pads bridge the gap 2..0x11 (they shrink to the authentic // 0x0F..0x11 once the mechsub/heat/powersub attribute waves publish -- // SENSOR.HPP pins PoweredSubsystem::NextAttributeID at 0x0F). The pads are // LOAD-BEARING: AttributeIndexSet::Build leaves unlisted gap slots as // uninitialized garbage, so every ID up to the max must be covered. // public: enum { MechWeaponPadFirstAttributeID = Subsystem::NextAttributeID, // 2 PercentDoneAttributeID = 0x12, TriggerStateAttributeID, // 0x13 -- the streamed fire-button binding DistanceToTargetAttributeID, // 0x14 TargetWithinRangeAttributeID, // 0x15 WeaponRangeAttributeID, // 0x16 PipPositionAttributeID, // 0x17 PipColorAttributeID, // 0x18 PipExtendedRangeAttributeID, // 0x19 EstimatedReadyTimeAttributeID, // 0x1A RearFiringAttributeID, // 0x1B WeaponStateAttributeID, // 0x1C (binary table end) NextAttributeID // 0x1D (the Emitter family starts here) }; static const IndexEntry AttributePointers[]; static AttributeIndexSet AttributeIndex; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Test Class Support // public: static Logical TestClass(Mech &); Logical TestInstance() const; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Construction and Destruction // public: typedef MechWeapon__SubsystemResource SubsystemResource; MechWeapon( Mech *owner, int subsystem_ID, SubsystemResource *subsystem_resource, SharedData &shared_data = DefaultData ); ~MechWeapon(); static int 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 = 1 ); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Weapon interface // public: virtual void FireWeapon(); void SendDamage( Entity *target, Damage &damage ); // // View-fire gating (the look-state commit re-arms these): a weapon // mounted on a back gun port (rearFiring) fires only into the LOOK-BACK // view; the rest fire only in the forward view. // Logical IsRearFiring() const { Check(this); return rearFiring; } Logical GetViewFireEnable() const { Check(this); return viewFireEnable; } void SetViewFireEnable(Logical enable){ Check(this); viewFireEnable = enable; } // // Fire state machine. The weapon state is carried in the weapon alarm // level: 0 = Firing, 2 = Loaded (ready), 3 = Loading, 4 = the // trigger-during-load blip. CheckFireEdge is the rising-edge detector // on fireImpulse (binary @004b9608): TriggerState carries the raw // ControlsButton INT bit-copied by the streamed direct mapping, so the // compare works on the BIT PATTERNS as signed ints (sign-correct for // the button ints AND genuine floats), reproducing the binary's x87 // semantics. ComputeOutputVoltage (@004b9c9c) is the recharge-dial // writer. // enum { FiringState = 0, DryTriggerState = 1, LoadedState = 2, LoadingState = 3, TriggerDuringLoadState = 4, JammedState = 5, TriggerDuringJamState = 6, NoAmmoState = 7, WeaponStateCount = 8 }; unsigned GetWeaponState() { Check(this); return weaponAlarm.GetLevel(); } Logical CheckFireEdge(); virtual void ComputeOutputVoltage(); // vtable slot 17; the Emitter overrides // with its charge-voltage form // // Targeting: the owner mech's target slot gates the Loaded->Firing // transition (no target = the denial blip, no shot); UpdateTargeting // (binary @004b9bdc) refreshes rangeToTarget / targetWithinRange from // the target's position each frame. // Logical HasActiveTarget(); Logical UpdateTargeting(); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Local Data // protected: Scalar rechargeRate; Scalar weaponRange; Scalar damageAmount; int damageType; Scalar heatCostToFire; ResourceDescription::ResourceID explosionResourceID; // binary @0x3e4 -- the projectile / // explosion GameModel this weapon spawns int targetWithinRange; Damage damageData; Logical rearFiring; Logical viewFireEnable; // // Fire-machine state (binary @0x31C/0x320/0x324/0x328/0x330/0x350/ // 0x3A4/0x3E8): the trigger sample pair, the recharge dial, targeting // ranges, and the weapon-state alarm. // Scalar fireImpulse; Scalar previousFireImpulse; Scalar rechargeLevel; Scalar rangeToTarget; Scalar effectiveRange; int estimatedReadyTime; Scalar recoil; AlarmIndicator weaponAlarm; }; #endif