//===========================================================================// // File: torso.hpp // // Project: BattleTech Brick: Mech subsystems // // Contents: Torso -- the torso twist / weapon-elevation subsystem // //---------------------------------------------------------------------------// // Copyright (C) 1995, Virtual World Entertainment, Inc. // // All Rights reserved worldwide // // This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // //===========================================================================// #if !defined(TORSO_HPP) # define TORSO_HPP # if !defined(POWERSUB_HPP) # include # endif //##################### Forward Class Declarations ####################### class Mech; class Joint; //########################################################################### //##################### Torso Model Resource ########################### //########################################################################### struct Torso__SubsystemResource: public PowerWatcher::SubsystemResource { Scalar horizontalRotationPerSecond; Scalar verticalRotationPerSecond; Scalar horizontalLimitRight; Scalar horizontalLimitLeft; Scalar verticalLimitTop; Scalar verticalLimitBottom; char torsoHorizontalJoint[32]; char torsoHorizontalShadowJoint[32]; Logical torsoHorizontalEnabled; Scalar buttonAccelerationPerSecond; Scalar buttonAccelerationStartValue; }; //########################################################################### //############################### Torso ################################ //########################################################################### // // Drives torso twist (horizontal) and weapon elevation (vertical). The // tuning rates/limits come from the resource; the live twist/elevation state // and the resolved skeleton joints are advanced by the per-frame // TorsoSimulation (staged) once the Mech skeleton link is live. // class Torso: public PowerWatcher { public: static Derivation ClassDerivations; static SharedData DefaultData; typedef void (Torso::*Performance)(Scalar time_slice); void SetPerformance(Performance performance) { Check(this); activePerformance = (Simulation::Performance)performance; } static Logical TestClass(Mech &); Logical TestInstance() const; Scalar CurrentTwist() const { Check(this); return currentTwist; } Scalar CurrentElevation() const { Check(this); return currentElevation; } Logical GetHorizontalEnabled() const{ Check(this); return horizontalEnabled; } // // Analog aim inputs (written by MechControlsMapper::InterpretControls; // consumed by TorsoSimulation to slew the twist/elevation each frame). // void SetAnalogElevationAxis(Scalar axis) { Check(this); analogElevationAxis = axis; } void SetAnalogTwistAxis(Scalar axis) { Check(this); analogTwistAxis = axis; } void TorsoSimulation(Scalar time_slice); void TorsoCopySimulation(Scalar time_slice); public: typedef Torso__SubsystemResource SubsystemResource; Torso( Mech *owner, int subsystem_ID, SubsystemResource *subsystem_resource, SharedData &shared_data = DefaultData ); ~Torso(); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Attribute publication. The shipped string pool lists this class's // attribute names contiguously after the class name "Torso": // // RotationOfTorsoVertical RotationOfTorsoHorizontal // HorizontalLimitRight HorizontalLimitLeft // SpeedOfTorsoVertical SpeedOfTorsoHorizontal // // The FULL authentic table, ids 3..15, confirmed twice over: the BT411 // donor's decompiled enum carries these names WITH binary member offsets // (torso.hpp 111-124, @0x1E4..@0x20C), and BTL4.RES's own streamed // control mappings bind ids 12/13 as DIRECT button destinations on // subsystem 17 = Torso (the [map] audit). // // An earlier revision declared "TorsoUp/Down/Left/Right/Center are // MESSAGES, not attributes" and stopped at 7 entries with MotionState at // id 9. That was WRONG in a specifically nasty way: the ids are the // binding key for the streamed mappings, so Thrustmaster's buttons // (12/13) resolved NULL -- the boot write-fault at // ControlsInstanceDirectOf::Update+0xE -- and the RIO's ANALOG // StickPosition (9) resolved to our motionState StateIndicator, letting // every analog update from a live RIO smash a watcher-socketed object // with raw floats. // // The chain -- PowerWatcher -> HeatWatcher -> MechSubsystem -- publishes // nothing of its own, so these start at MechSubsystem::NextAttributeID. // public: enum { RotationOfTorsoVerticalAttributeID = MechSubsystem::NextAttributeID, RotationOfTorsoHorizontalAttributeID, HorizontalLimitRightAttributeID, HorizontalLimitLeftAttributeID, SpeedOfTorsoVerticalAttributeID, SpeedOfTorsoHorizontalAttributeID, StickPositionAttributeID, TorsoUpAttributeID, TorsoDownAttributeID, TorsoLeftAttributeID, TorsoRightAttributeID, TorsoCenterAttributeID, MotionStateAttributeID, NextAttributeID }; static const IndexEntry AttributePointers[]; static AttributeIndexSet AttributeIndex; protected: int isDamagedCopy; int statusFlags; Logical horizontalEnabled; Scalar baseTwistRate; Scalar baseElevationRate; Scalar horizontalLimitRight; Scalar horizontalLimitLeft; Scalar verticalLimitTop; Scalar verticalLimitBottom; Scalar twistCenterHigh; Scalar twistCenterLow; Scalar elevationCenter; Scalar elevationHalfBottom; Scalar buttonAccelerationPerSecond; Scalar buttonAccelerationStart; int buttonRampActive; Scalar buttonRamp; Joint *horizontalJointNode; Joint *horizontalShadowJointNode; Scalar currentTwist; Scalar currentElevation; Scalar analogElevationAxis; Scalar analogTwistAxis; // // MUST BE A StateIndicator. The authored watcher for a *State // name is an AudioStateWatcher, which is AudioWatcherOf // and whose ctor immediately runs // Cast_Object(StateIndicator*, attributePointer)->AddAudioWatcher(this) // (AUDWTHR.CPP:891). Point it at a plain int and that call goes // through garbage -- the pod dies on the extender. // StateIndicator motionState; // authored watcher // // The five BUTTON COMMAND destinations (donor torso.hpp @0x1F8-0x208). // The streamed control mappings bind these BY ID as DIRECT WRITE // targets -- LBE4ControlsManager::CreateStreamedMappings registers // GetAttributePointer(attributeID) as the destination a device poll // writes through (L4CTRL.CPP:1936). Carved from the front of the // dynamicsState reserve so the class size is unchanged. // int elevateUpCommand; int elevateDownCommand; int twistLeftCommand; int twistRightCommand; int centerCommand; // // Recenter latch (donor @0x268-adjacent family): armed by the centre // button, cleared by a twist button or on arrival at centre. // int recenterActive; // // Twist/elevation dynamics accumulators advanced by TorsoSimulation. // Reserved until the per-frame sim is reconstructed (phase 5). // Scalar dynamicsState[16]; }; #endif