//*************************************************************************** // // mech.h - This file contains the BattleMech Class header // // MechCommander 2 // //---------------------------------------------------------------------------// // Copyright (C) Microsoft Corporation. All rights reserved. // //===========================================================================// #ifndef MECH_H #define MECH_H #ifndef MCLIB_H #include "mclib.h" #endif #ifndef MOVER_H #include "mover.h" #endif #ifndef DMECH_H #include "dmech.h" #endif #ifndef GAMEOBJ_H #include "gameobj.h" #endif #ifndef OBJTYPE_H #include "objtype.h" #endif #ifndef DOBJNUM_H #include "dobjnum.h" #endif #ifndef CMPONENT_H #include "cmponent.h" #endif #ifndef WARRIOR_H #include "warrior.h" #endif #ifdef USE_JETS #ifndef DJET_H #include "djet.h" #endif #endif #ifndef MECHCLASS_H #include "mechclass.h" #endif extern float metersPerWorldUnit; //*************************************************************************** #define PILOTCHECK_SITUATION_NONE 0 #define PILOTCHECK_SITUATION_JUMPING 1 #define PILOTCHECK_SITUATION_COLLISION 2 #define MECH_SPRITESPEED_FLAG_NONE 0 #define MECH_SPRITESPEED_FLAG_GO_SLOW 1 #define NUM_MECH_HIT_ARCS 4 #define MECH_HIT_ARC_FRONT 0 #define MECH_HIT_ARC_REAR 1 #define MECH_HIT_ARC_LEFT 2 #define MECH_HIT_ARC_RIGHT 3 #define NUM_MECH_HIT_SECTIONS 3 #define MECH_HIT_SECTION_TOP 0 #define MECH_HIT_SECTION_MIDDLE 1 #define MECH_HIT_SECTION_BOTTOM 2 #define HIT_TYPE_WEAK 0 #define HIT_TYPE_MODERATE 1 #define HIT_TYPE_HEAVY 2 #define NUM_CRITICAL_SPACES_HEAD 6 #define NUM_CRITICAL_SPACES_CTORSO 12 #define NUM_CRITICAL_SPACES_LTORSO 12 #define NUM_CRITICAL_SPACES_RTORSO 12 #define NUM_CRITICAL_SPACES_LARM 12 #define NUM_CRITICAL_SPACES_RARM 12 #define NUM_CRITICAL_SPACES_LLEG 6 #define NUM_CRITICAL_SPACES_RLEG 6 #define NUM_ACTUATORS 4 #define ACTUATOR_LSHOULDER 0 #define ACTUATOR_RSHOULDER 1 #define ACTUATOR_LHIP 2 #define ACTUATOR_RHIP 3 #define NUM_MECH_GESTURES 25 #define MECH_GESTURE_PARK 0 #define MECH_GESTURE_STAND_TO_PARK 1 #define MECH_GESTURE_STAND 2 #define MECH_GESTURE_STAND_TO_WALK 3 #define MECH_GESTURE_WALK 4 #define MECH_GESTURE_WALK_TO_STAND 5 #define MECH_GESTURE_WALK_TO_RUN 6 #define MECH_GESTURE_RUN 7 #define MECH_GESTURE_RUN_TO_WALK 8 #define MECH_GESTURE_REVERSE 9 #define MECH_GESTURE_STAND_TO_REVERSE 10 #define MECH_GESTURE_LIMPING 11 //Limp #define MECH_GESTURE_WALK_HIT_B 12 //WalkToHitBehindToWalk #define MECH_GESTURE_WALK_HIT_F 13 //WalkToHitFrontToWalk #define MECH_GESTURE_WALK_FALL_B 14 //WalkToFallBackward #define MECH_GESTURE_WALK_FALL_F 15 //WalkToFallForward #define MECH_GESTURE_RUN_FALL_B 16 //RunToFallBackward #define MECH_GESTURE_RUN_FALL_F 17 //RunToFallForward #define MECH_GESTURE_STAND_FALL_B 18 //StandToFallBackward #define MECH_GESTURE_STAND_FALL_F 19 //StandToFallForward #define MECH_GESTURE_JUMP 20 //Jump #define MECH_GESTURE_ROLLOVER 21 //Rollover from FallBack to FallForward #define MECH_GESTURE_GETUP 22 //Get up from FallForward #define MECH_GESTURE_FALLEN_F 23 //Fallen Forward (Single Frame, mech on ground) #define MECH_GESTURE_FALLEN_B 24 //Fallen Backward (Single Frame, mech on ground) #define NO_APPEARANCE_FOR_MECH 0xFFFA0001 #define NO_RAM_FOR_DYNAMICS_TYPE 0xFFFA0002 #define INVALID_DYNAMICS_TYPE 0xFFFA0003 #define NO_RAM_FOR_CONTROL 0xFFFA0004 #define INVALID_CONTROL_TYPE 0xFFFA0005 #define NO_RAM_FOR_CONTROL_DATA 0xFFFA0006 #define INVALID_CONTROL_DATA_TYPE 0xFFFA0007 #define NO_RAM_FOR_DYNAMICS 0xFFFA0008 #define NO_APPEARANCE_TYPE_FOR_MECH 0xFFFA0009 #define APPEARANCE_NOT_SPRITE_TREE 0xFFFA000A #define NO_RAM_FOR_FOOT_HS 0xFFFA000B #define NO_RAM_FOR_WEAPON_HS 0xFFFA000C #define FOOT_HS_WRONG_SIZE 0xFFFA000D #define BAD_HS_PACKET 0xFFFA000E #define NO_RAM_FOR_XLAT_HS 0xFFFA000F #define MAGIC_ROTATE_FORCE_NUMBER (360.0 / (17.0)) #define MAX_MECH_SMOKES 4 //------------------------------------------------------------------------------------------ // Enums //------------------------------------------------------------------------------------------ typedef enum { MECH_BODY_LOCATION_ANY = -1, MECH_BODY_LOCATION_HEAD, MECH_BODY_LOCATION_CTORSO, MECH_BODY_LOCATION_LTORSO, MECH_BODY_LOCATION_RTORSO, MECH_BODY_LOCATION_LARM, MECH_BODY_LOCATION_RARM, MECH_BODY_LOCATION_LLEG, MECH_BODY_LOCATION_RLEG, NUM_MECH_BODY_LOCATIONS } MechBodyLocationType; typedef enum { MECH_ARMOR_LOCATION_ANY = -1, MECH_ARMOR_LOCATION_HEAD, MECH_ARMOR_LOCATION_CTORSO, MECH_ARMOR_LOCATION_LTORSO, MECH_ARMOR_LOCATION_RTORSO, MECH_ARMOR_LOCATION_LARM, MECH_ARMOR_LOCATION_RARM, MECH_ARMOR_LOCATION_LLEG, MECH_ARMOR_LOCATION_RLEG, MECH_ARMOR_LOCATION_RCTORSO, MECH_ARMOR_LOCATION_RLTORSO, MECH_ARMOR_LOCATION_RRTORSO, NUM_MECH_ARMOR_LOCATIONS } MechArmorLocationType; typedef enum { LEG_STATUS_NORMAL, LEG_STATUS_HURTING, LEG_STATUS_IMPAIRED_LEFT, LEG_STATUS_IMPAIRED_RIGHT, LEG_STATUS_DESTROYED, NUM_LEG_STATUSES } LegStatusType; typedef enum { TORSO_STATUS_NORMAL, TORSO_STATUS_IMPAIRED, NUM_TORSO_STATUSES } TorsoStatusType; typedef enum { MECH_PILOT_CHECK_CONDITION_NO_LEG, MECH_PILOT_CHECK_CONDITION_NO_HIP, NUM_MECH_PILOT_CHECK_CONDITIONS } MechPilotCheckCondition; typedef enum { MECH_STATUSCHUNK_BODYSTATE_NORMAL, MECH_STATUSCHUNK_BODYSTATE_STANDING, MECH_STATUSCHUNK_BODYSTATE_PARKED, MECH_STATUSCHUNK_BODYSTATE_FALLEN_BACKWARD, MECH_STATUSCHUNK_BODYSTATE_FALLEN_FORWARD, MECH_STATUSCHUNK_BODYSTATE_DESTROYED } MechStatusChunkBodyState; //--------------------------------------------------------------------------- // classes and structs //--------------------------------------------------------------------------- class BattleMechType : public ObjectType { //------------- // Data Members public: bool isEndoSteel; // has endosteel frame? unsigned char maxInternalStructure[NUM_BODY_LOCATIONS]; char* anim; unsigned char moveAnimSpeed[3]; //unsigned long controlType; // Who controls us, Player, AI or NET? //unsigned long controlDataType; // which data set do we use. MoverDynamics dynamics; // what dynamics do we use. //---------------------------------------------------------------------------------------- // NO MORE HOTSPOT DATA HERE. ALL RESIDES IN APPEARANCE NOW! Including footprint type! unsigned long rightArmDebrisId; //Id of the shot off right arm. unsigned long leftArmDebrisId; //Id of the shot off left arm. unsigned long destroyedDebrisId; //Id of the destroyed mech piece. long moveType; long crashAvoidSelf; long crashAvoidPath; long crashBlockSelf; long crashBlockPath; float crashYieldTime; float explDmg; float explRad; float LOSFactor; float destructDamage; //---------------- //Member Functions public: void init (void); BattleMechType (void) { ObjectType::init(); init(); } virtual long init (FilePtr objFile, unsigned long fileSize); virtual GameObjectPtr createInstance (void); virtual void destroy (void); ~BattleMechType (void) { destroy(); } virtual bool handleCollision (GameObjectPtr collidee, GameObjectPtr collider); virtual bool handleDestruction (GameObjectPtr collidee, GameObjectPtr collider); }; //--------------------------------------------------------------------------- typedef struct _MechData : public MoverData { char chassisClass; long chassisBR; long variantID; char variantName[64]; char legStatus; char torsoStatus; unsigned char actuator[NUM_ACTUATORS]; unsigned char gyro; bool sensorOK; unsigned char numJumpJets; float lastJumpTime; bool inJump; Stuff::Vector3D jumpGoal; float centerTorsoBlowTime; bool hitFromBehindThisFrame; bool hitFromFrontThisFrame; bool leftArmBlownThisFrame; bool rightArmBlownThisFrame; float torsoRotation; float rightArmRotation; float leftArmRotation; bool fallen; bool mechRemoved; float pivotTurnRate; bool playedJumpSFX; bool playedCriticalHit; float maxWeaponDamage; char longName[MAXLEN_MECH_LONGNAME]; long pilotNum; bool captureable; bool notMineYet; long descID; float damageThisFrame; bool sentCrippledMsg; float rotateValues[6]; long ItemLocationToInvLocation[MAX_MOVER_INVENTORY_ITEMS]; float damageAfterDisabled; long numArmorComponents; long cBills; MechAppearanceData apData; } MechData; class BattleMech : public Mover { //------------ //Data Members public: char chassisClass; // none, light, medium, heavy, assault long chassisBR; // chassis Battle Rating long variantID; // need to store this for logistics char variantName[64]; // user defined //------------------ // Additional status char legStatus; // normal, hurting, impaired, disabled char torsoStatus; // normal, impaired //-------------------------------------- // Additional Critical Component Indices unsigned char actuator[NUM_ACTUATORS]; // actuator inventory index unsigned char gyro; // gyro inventory index //------------------ // Additional Engine unsigned char numJumpJets; float lastJumpTime; bool inJump; Stuff::Vector3D jumpGoal; float centerTorsoBlowTime; bool hitFromBehindThisFrame; bool hitFromFrontThisFrame; //----------------------- // Additional Update Info bool leftArmBlownThisFrame; bool rightArmBlownThisFrame; float torsoRotation; // Current Rotation of Torso in Degrees float rightArmRotation; // Current Rotation of Right Arm in Degrees float leftArmRotation; // Current Rotation of Left Arm in Degrees bool fallen; bool mechRemoved; // Have we removed ourselves from the interface. float pivotTurnRate; bool playedJumpSFX; //Have I played the Jump SOund EFfect for this jump? bool playedCriticalHit; //Have I played a critical hit explosion this frame? float maxWeaponDamage; // max total damage possible char longName[MAXLEN_MECH_LONGNAME]; //Used by logistics (and the interface) to get long name. long pilotNum; //Used by logistics to restore pilot on return. bool captureable; bool notMineYet; //Used by logsitics to drop this mech if mission lost. long descID; //Used by Logistics to Desc. // long variant; // Now we have three longs storing a bytes worth of data well done SJ float damageThisFrame; // How much damage have we taken this frame. bool sentCrippledMsg; // Have I already announced that I'm gimped? bool playedHeloDestruct; float rotateValues[6]; long ItemLocationToInvLocation[MAX_MOVER_INVENTORY_ITEMS]; float damageAfterDisabled; // Stores damaged inflicted after disabled. // Once we reach the threshold, BLOW the mech for real!! long numArmorComponents; long cBills; //---------------- //Member Functions public: void operator = (BattleMech copy); virtual void init (bool create); BattleMech (void) { init(true); } virtual void init (bool create, ObjectTypePtr _type); virtual long init (FitIniFile* mechFile); virtual long init (DWORD variantNum); virtual long init (FilePtr mechFile); virtual void destroy (void); virtual void clear (void); virtual long write (FilePtr mechFile); virtual float getStatusRating (void); virtual void setControl (ControlType ctrlType); virtual bool crashAvoidanceSystem (void); virtual void updateAIControl (void); virtual void updatePlayerControl (void); virtual void updateNetworkControl (void); virtual void updateDynamics (void); virtual long update (void); virtual void render (void); virtual void renderShadows (void); virtual bool isCrippled (void) { return((legStatus == LEG_STATUS_IMPAIRED_RIGHT) ||(legStatus == LEG_STATUS_IMPAIRED_LEFT) || (legStatus == LEG_STATUS_DESTROYED)); } virtual long calcHitLocation (GameObjectPtr attacker, long weaponIndex, long attackSource, long attackType); virtual long handleWeaponHit (WeaponShotInfoPtr shotInfo, bool addMultiplayChunk = false); virtual float weaponLocked (long weaponIndex, Stuff::Vector3D targetPosition); virtual float getWeaponHeat (long weaponIndex) { return(MasterComponent::masterList[inventory[weaponIndex].masterID].getWeaponHeat()); } virtual void pilotingCheck (unsigned long situation = 0, float modifier = 0.0); virtual void mineCheck (void); bool updateJump (void); bool pivotTo (void); void updateMoveStateGoal (void); bool updateMovePath (float& newRotate, char& newThrottleSetting, long& newGestureStateGoal, long& newMoveState, long& minThrottle, long& maxThrottle, float& facingRotate); bool netUpdateMovePath (float& newRotate, char& newThrottleSetting, long& newGestureStateGoal, long& newMoveState, long& minThrottle, long& maxThrottle); void setNextMovePath (char& newThrottleSetting, long& newGestureStateGoal); void setControlSettings (float& newRotate, char& newThrottleSetting, long& newGestureStateGoal, long& minThrottle, long& maxThrottle, float& facingRotate); void updateTorso (float newRotate); virtual long getCBills (void) { return(cBills); } virtual void updateMovement (void); virtual void netUpdateMovement (void); virtual long calcCV (bool calcMax = false); long getResourcePointValue (void); virtual bool isWeaponReady (long weaponIndex); virtual float calcAttackChance (GameObjectPtr target, long aimLocation, float targetTime, long weaponIndex, float modifiers, long* range, Stuff::Vector3D* targetPoint = NULL); virtual float getTotalEffectiveness(void); virtual bool hitInventoryItem (long itemIndex, bool setupOnly = false); virtual void destroyBodyLocation (long location); virtual void handleCriticalHit (long bodyLocation, long criticalSpace); virtual long updateCriticalHitChunks (long which); virtual long buildStatusChunk (void); virtual long handleStatusChunk (long updateAge, unsigned long chunk); virtual long buildMoveChunk (void); virtual long handleMoveChunk (unsigned long chunk); virtual void calcCriticalHit (long hitLocation); virtual bool injureBodyLocation (long bodyLocation, float damage); virtual long handleWeaponFire (long weaponIndex, GameObjectPtr target, Stuff::Vector3D* targetPoint, bool hit, float entryAngle, long numMissiles, long hitLocation); virtual long fireWeapon (GameObjectPtr target, float targetTime, long weaponIndex, long attackType, long aimLocation, Stuff::Vector3D* targetPoint, float &damageDone); virtual float relFacingTo (Stuff::Vector3D goal, long bodyLocation = -1); virtual float relViewFacingTo (Stuff::Vector3D goal) { return(relFacingTo(goal, MECH_BODY_LOCATION_CTORSO)); } virtual bool canPowerUp (void); virtual Stuff::Vector3D getPositionFromHS (long weaponType); virtual long getBodyState (void); virtual float getDestructLevel (void) { return 5000.0f; //ALWAYS just keep shooting at a mech. This would be nearly impossible to calculate. } //----------------------------------- // Additional Mech-specific functions void createJumpFX (void); void endJumpFX (void); Stuff::Vector3D getJumpPosition (void); long getActuatorMax (long actuatorId) { return(MasterComponent::masterList[inventory[actuator[actuatorId]].masterID].getHealth()); } long getActuatorHealth (long actuatorId) { return(inventory[actuator[actuatorId]].health); } long calcLegStatus (void); long calcTorsoStatus (void); bool isTorso (long bodyLocation) { return((bodyLocation >= MECH_BODY_LOCATION_CTORSO) && (bodyLocation <= MECH_BODY_LOCATION_RTORSO)); } long transferHitLocation (long hitLocation); bool inTransitionGestureState (void) { return(appearance->getInTransition()); } long setGestureStateGoal (long state) { return(appearance->setGestureGoal(state)); } long getGestureFramesLeft (void) { return(appearance->getNumFramesInGesture(appearance->getCurrentGestureGoal()) - appearance->getFrameNumber()); } bool isStanding (void) { return(appearance->getOldGestureGoal() == MECH_STATE_STANDING); } bool isWalking (long* throttle = NULL) { if (throttle) *throttle = control.settings.mech.throttle; return(appearance->getOldGestureGoal() == MECH_STATE_WALKING); } bool isRunning (void) { return(appearance->getOldGestureGoal() == MECH_STATE_RUNNING); } virtual bool isJumping (Stuff::Vector3D* jumpGoal = NULL); bool isReversing (void) { return(appearance->getOldGestureGoal() == MECH_STATE_REVERSE); } bool isFallen (void) { return((appearance->getOldGestureGoal() == MECH_STATE_FALLEN_BACKWARD) || (appearance->getOldGestureGoal() == MECH_STATE_FALLEN_FORWARD)); } bool canRotateTorso (void) { return(body[MECH_BODY_LOCATION_CTORSO].damageState == IS_DAMAGE_NONE); } bool canRun (void) { return(legStatus == LEG_STATUS_NORMAL); } bool canWalk (void) { return(legStatus < LEG_STATUS_IMPAIRED_LEFT); } bool canLimp (void) { return((legStatus == LEG_STATUS_IMPAIRED_LEFT) || (legStatus == LEG_STATUS_IMPAIRED_RIGHT)); } bool canMove (void) { return(legStatus != LEG_STATUS_DESTROYED); } virtual long getSpeedState (void); virtual bool canJump (void) { return(numJumpJets > 0); } virtual float getJumpRange (long* numOffsets = NULL, long* jumpCost = NULL); virtual bool handleFall (bool forward); virtual bool handleEjection (void); float calcMaxSpeed (void); float calcSlowSpeed (void); float calcModerateSpeed (void); long calcSpriteSpeed (float speed, unsigned long flags, long& state, long& throttle); void forceTorsoAlign (void) { torsoRotation = rightArmRotation = leftArmRotation = 0.0; } ~BattleMech (void) { destroy(); } virtual bool isCaptureable(long capturingTeamID); virtual void handleStaticCollision (void); virtual float calcMaxTargetDamage(void); bool isWeaponWorking (long weaponIndex); void damageLoadedComponents (void); virtual char* getIfaceName(void) { return(longName); } static long loadGameSystem (FitIniFilePtr mechFile); virtual bool isMech (void) { return true; } virtual bool isVehicle (void) { return false; } virtual bool isGuardTower (void) { return false; } void resetComponents (long totalComponents, long* componentList); virtual float getLOSFactor (void) { return (((BattleMechType *)getObjectType())->LOSFactor); } virtual void startShutDown (void); virtual void Save (PacketFilePtr file, long packetNum); void CopyTo (MechData *data); void Load (MechData *data); static void initOptimalCells (long numIncrements); virtual void repairAll (void); }; #endif //******************************************************************************************