//===========================================================================// // File: Vehicle.hpp //---------------------------------------------------------------------------// // Date Who Modification // // -------- --- ---------------------------------------------------------- // // 09/09/98 JSE Inital base class based off of Shadowrun/Adept //---------------------------------------------------------------------------// // Copyright (C) 1998, Fasa Interactive // // All Rights reserved worldwide // // This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // //===========================================================================// #pragma once #include "MW4.hpp" #pragma warning (push) #include #include #include #pragma warning (pop) #include "MWMover.hpp" #include "AnimationState.hpp" #include "AnimationTrigger.hpp" #include "Group.hpp" #include "AI_FindObjectCache.hpp" namespace Adept { class DamageObject; class Effect; class Site; } namespace MechWarrior4 { class Weapon; class MoverAI; class CombatAI; class HeatManager; class MWObject; class Weapon; class Torso; class MWInternalDamageObject; class Sensor; class Beagle; class AMS; class SearchLight; class Subsystem; class ECM; class VehicleInterface; // MSL 5.02 SubSystems class IFF_Jammer; // class EnhancedOptics; class AdvancedGyro; class IdleEffectObject : public Stuff::Plug { public: IdleEffectObject(); Adept::ResourceID effectResourceID; Stuff::SlotOf idleEffect; Stuff::SlotOf siteSlot; }; //########################################################################## //##################### MWObject::ClassData ########################## //########################################################################## class MWObject__ClassData: public MWMover__ClassData { //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // public: typedef MWMover__ClassData BaseClass; MWObject__ClassData( Stuff::RegisteredClass::ClassID class_id, const char* class_name, Adept::Replicator::ClassData *parent_class, int message_count, const Adept::Receiver::MessageEntry *message_handlers, Adept::Entity::Factory entity_factory, Adept::Entity::CreateMessage::Factory message_factory, Adept::Entity::ExecutionStateEngine::ClassData *execution_state, Adept::Entity::GameModel::Factory model_factory, Adept::Entity::GameModel::Factory obb_factory, Adept::Entity::GameModel::ReadAndVerifier verifier, Adept::Entity::GameModel::ModelWrite model_write_to_text, Adept::Entity::GameModel::ModelSave model_save_to_text, AnimationStateEngine::Factory animation_state_factory ): MWMover__ClassData( class_id, class_name, parent_class, message_count, message_handlers, entity_factory, message_factory, execution_state, model_factory, obb_factory, verifier, model_write_to_text, model_save_to_text ) { //This line is commented out due to Internal Compile Error in //and Armor Build #if 0 Check_Pointer(animation_state_factory); #endif animationStateFactory = animation_state_factory; } AnimationStateEngine::Factory animationStateFactory; }; //########################################################################## //##################### MWObject::ModelResource ####################### //########################################################################## class MWObject__GameModel: public MWMover__GameModel { public: typedef MWMover__GameModel BaseClass; enum { LEG_MOVETYPE, LEGJUMP_MOVETYPE, TRACK_MOVETYPE, WHEEL_MOVETYPE, FLYER_MOVETYPE, HOVER_MOVETYPE, HELI_MOVETYPE, NONE_MOVETYPE, DROPSHIP_MOVETYPE, WATER_MOVETYPE, LAST_MOVETYPE }; int moveTypeFlag; #if NSWIZZLE Adept::ResourceID deathEntityResource; Adept::ResourceID destroyedEffectResource; // these can be used for special derived classes // mech uses it for alternate deaths and a two // part explosion Adept::ResourceID secondaryDeathEntityResource; Adept::ResourceID secondaryDestroyedEffectResource; Adept::ResourceID idleEffectResourceID; Adept::ResourceID partDestructionEffectResource; #else // these can be used for special derived classes // mech uses it for alternate deaths and a two // part explosion Adept::ResourceID secondaryDeathEntityResource; Adept::ResourceID secondaryDestroyedEffectResource; Adept::ResourceID idleEffectResourceID; Adept::ResourceID partDestructionEffectResource; Adept::ResourceID deathEntityResource; Adept::ResourceID destroyedEffectResource; #endif Stuff::Scalar vehicleTonnage; Stuff::Scalar maxVehicleTonnage; int vehicleBattleValue; Stuff::Scalar splashDamageRadius; Stuff::Scalar splashDamageAmount; Stuff::Scalar splashHeatAmount; char animScriptName[256]; char eyeSiteName [MaxStringLength]; Adept::ResourceID coolantEffectResource; Adept::ResourceID overHeatEffectResource; Adept::ResourceID ejectEffectResource; Adept::ResourceID hierarchicalOBBStreamResourceID; int m_nameIndex; enum { DeathEntityResourceAttributeID = MWMover__GameModel::NextAttributeID, DestroyedEffectResourceAttributeID, SecondaryDeathEntityResourceAttributeID, SecondaryDestroyedEffectResourceAttributeID, VehicleTonnageAttributeID, MaxVehicleTonnageAttributeID, EyeSiteNameAttributeID, PartDestructionEffectResourceAttributeID, SplashDamageRadiusAttributeID, SplashDamageAmountAttributeID, VehicleBattleValueAttributeID, CoolantEffectResourceAttributeID, SplashHeatAmountAttributeID, EjectEffectResourceAttributeID, NameIndexAttributeID, OverHeatEffectResourceAttributeID, NextAttributeID }; static bool ReadAndVerify( MWObject__GameModel *model, Adept::ModelAttributeEntry *attribute_entry, const char *data, char **error, int error_buffer = 128 ); static int ConvertStringToMoveType (const char *str); static void ConstructGameModel(Script *script); static void ConstructOBBStream(Script *script); static Adept::ResourceID CreateEffectTableResource(Stuff::NotationFile *effect_file, BYTE length); }; //########################################################################## //################## MWObject::CreateMessage ######################### //########################################################################## class MWObject__CreateMessage: public MWMover__CreateMessage { public: typedef MWMover__CreateMessage BaseClass; #if NSWIZZLE Adept::ResourceID subsystemStreamResourceID; Adept::ResourceID damageStreamResourceID; #else Adept::ResourceID damageStreamResourceID; Adept::ResourceID subsystemStreamResourceID; #endif char skinPrefix; int teamDecal; int pilotDecal; int nameIndex; bool doesHaveInstanceName; MWObject__CreateMessage( size_t length, int priority, int message_flags, Stuff::RegisteredClass::ClassID class_id, int replicator_flags, const Adept::ResourceID& instance_id, const Stuff::LinearMatrix4D &creation_matrix, Stuff::Scalar age, int execution_state, int name_id, int entity_alignment, const Stuff::Motion3D &initial_velocity, const Stuff::Motion3D &initial_acceleration, const char *entity_name, const Adept::ResourceID& armature_id, const Adept::ResourceID& site_id, const Adept::ResourceID& subsystem_id, const Adept::ResourceID& damage_id, char skin_prefix, int team_decal, int pilot_decal, int name_index, bool has_instance_name ): MWMover__CreateMessage( length, priority, message_flags, class_id, replicator_flags, instance_id, creation_matrix, age, execution_state, name_id, entity_alignment, initial_velocity, initial_acceleration, entity_name, armature_id, site_id ), subsystemStreamResourceID(subsystem_id), damageStreamResourceID(damage_id), skinPrefix(skin_prefix), teamDecal(team_decal), pilotDecal(pilot_decal), nameIndex(name_index), doesHaveInstanceName(has_instance_name) {} static void ConstructCreateMessage(Script *script); }; //########################################################################## //############################ MWObject ############################## //########################################################################## //------------------------------------------------------------------------- // The following helper classes must always be typedef'd or overriden by an // inheritor // typedef MWMover__Message MWObject__Message; typedef MWMover__UpdateMessage MWObject__UpdateMessage; typedef MWMover__ExecutionStateEngine MWObject__ExecutionStateEngine; //----------------------- End of inheritance stuff ------------------------ class MWObject: public MWMover { friend class MovementClass; public: static void InitializeClass(); static void TerminateClass(); bool invulnerable; typedef MWMover BaseClass; //########################################################################## // Inheritance support // public: typedef MWObject__ClassData ClassData; typedef MWObject__GameModel GameModel; typedef MWObject__Message Message; typedef MWObject__ExecutionStateEngine ExecutionStateEngine; typedef MWObject__CreateMessage CreateMessage; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Run-time Construction and Destruction Support // public: static MWObject* Make( CreateMessage *message, Adept::ReplicatorID *base_id ); Adept::Replicator::CreateMessage* SaveMakeMessage(Stuff::MemoryStream *stream, Adept::ResourceFile *res_file); void Respawn(Adept::Entity::CreateMessage *message); void CommonCreation(CreateMessage *message); void SaveInstanceText(Stuff::Page *page); void LoadSubsystemsFromResource( const Adept::ResourceID &subsystem_stream_id, Adept::ReplicatorID *base_id ); void LoadIdleEffectsFromResource(const Adept::ResourceID &effects_stream_id); Adept::Effect* CreateIdleEffect(IdleEffectObject *effect_object); static void CreateArmatureStream(Stuff::MemoryStream *stream, Stuff::NotationFile *notation_file); static void CreateDamageStream(Stuff::MemoryStream *stream, Stuff::NotationFile *notation_file); static void CreateSubsystemStream(Stuff::MemoryStream *stream, Stuff::NotationFile *notation_file); protected: MWObject( ClassData *class_data, CreateMessage *message, Adept::ReplicatorID *base_id, ElementRenderer::Element *element ); void LoadDamageObjectsFromResource( const Adept::ResourceID &damage_stream_id ); ~MWObject(); void SentenceToDeathRow(); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Message support // public: void TakeDamageMessageHandler(const TakeDamageMessage *message); protected: static const MessageEntry MessageEntries[]; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class Data support // public: static ClassData *DefaultData; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Child Support // public: void AddChild(Adept::Entity *entity); void RemoveChild(Adept::Entity *entity); protected: void ChildPreCollisionChanged(Adept::Entity *entity); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Game Model Support // public: const GameModel* GetGameModel() { Check_Object(this); return Cast_Pointer(const GameModel*,gameModelResource.GetPointer()); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Animation Support // public: Stuff::Vector3D animationVelocity; Stuff::Vector3D instantaniousAngularVelocity; int animationArrayCount; MWMover **animationArray; int *lastTriggerArray; MW4AI::FindObjectCache* m_FindObjectCache; MW4AI::FindObjectList* m_FindObjectList; AnimationTriggerManager animationTriggerManager; static void ApplyChannel ( MW4Animation::ChannelApplication &channel_data, int joint_index, void *user_data ); void MakeAnimationArray(); AnimationStateEngine *animStateEngine; virtual void LoadAnimationScripts(); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Simulation Animation Requests // public: virtual void GetUpRequestRequest(void){}; virtual bool ShutDownRequest(bool shutdown){return false;} virtual void CrouchRequest(void){}; virtual bool JumpRequest(void){return false;}; virtual void StopJumpRequest(void){}; virtual bool IsCrouched() {return false;} bool vehicleShutDown; bool vehicleJustPoweredUp; // used in sensors to send vehicleinterface messages //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Execution Support // public: AI *m_AI; void AttachAI (AI *ai); AI* GetAI() { return m_AI; } bool m_bHasAI; void HasAI(bool hasAI) { m_bHasAI = hasAI; } bool HasAI() { return m_bHasAI; } // MSL 5.06 Armor Mode int m_ArmorMode; virtual void TurnOn (void) {} virtual void TurnOff (void) {} Stuff::Scalar m_HitPoints,m_MaxHitPoints; // for hud tracking Stuff::Scalar armorArray[12]; virtual void InitializeArmorArray(); void PreCollisionExecute(Stuff::Time till); void SyncMatrices(bool update_matrix); void PostCollisionExecute(Stuff::Time till); void ReactToDestruction(int damage_mode, int damage_type); void ReactToHit(const Adept::Entity::TakeDamageMessage *message,Adept::DamageObject *part_hit); virtual void EngineDead (void); bool CollisionHandler( Stuff::LinearMatrix4D *new_position, Stuff::DynamicArrayOf *collisions ); void DestroyDamageObjects(); void DestroyRunningLight(); bool m_hasExecuted; MWMover *jointRunningLight; #if 0 void CreateDestructionEffect(); void CreateSecondaryDeathEntity(); void CreateSecondaryDestructionEffect(); void CreateDeathEntity(); #endif Adept::Effect* CreateEffect(const Adept::ResourceID& effect_id, MWMover *parent_part, bool follow_joint = false); Adept::Effect* CreateLoopingEffect(const Adept::ResourceID& effect_id, MWMover *parent_part, bool follow_joint = false); Adept::Effect* CreateEffect(const Adept::ResourceID& effect_id, const Stuff::Point3D &location); // MSL 5.03 Glass Adept::Effect* CreateEffect(const Adept::ResourceID& effect_id, const Stuff::Point3D &location, const Stuff::Vector3D &normal); Adept::Effect* CreateLoopingEffect(const Adept::ResourceID& effect_id, const Stuff::Point3D &location); //Effect support to accept sites Adept::Effect* CreateEffect(const Adept::ResourceID& effect_id, Adept::Site *parent_part, bool follow_joint = false); Adept::Effect* CreateLoopingEffect(const Adept::ResourceID& effect_id, Adept::Site *parent_part, bool follow_joint = false); Adept::Entity* CreateStaticHermitEntity(Adept::ResourceID entity_id); Adept::Entity::CollisionMask originalCollisionMask; unsigned originalCullMode; virtual void RemoveFromExecution(); static int FindChildMoverIndexUserData( const char *joint_name, void *user_data ); int FindChildMoverIndex( const char *joint_name ); MWMover* FindChildMover( const char *joint_name ); Adept::Site* FindSite(const char *site_name) #ifdef _DEBUG ; #else // !_DEBUG {Check_Object(this); Check_Pointer(site_name); return m_sites.Find(site_name);} #endif // _DEBUG void ConnectDamageObjects(); void ReuseDamageObjects(); void MakeArmatureChain(); void ConnectMWMover(MWMover *mover); void ToggleSearchLight(); void TurnOnSearchLight(); void TurnOffSearchLight(); bool IsSearchLightOn(); //Entity__CollisionQuery // *targetQuery; Stuff::ChainOf subsystemsInVehicle; Stuff::ChainOf executingSubsystems; Stuff::ChainOf entitiesToSync; //Damage virtual void DealSplashDamage(); void TakeSplashDamage(Adept::Entity::TakeDamageMessage *message); static void SplashCallBack(Adept::Entity *entity, Adept::Entity *original_enitiy, const Stuff::Sphere &sphere); static void SubSplashCallBack(Adept::CollisionVolume *solid, Adept::Entity *original_enitiy, const Stuff::Sphere &sphere); Stuff::ChainOf splashedEntities; int splashSize; Stuff::SortedChainOf damageObjects; Stuff::SortedChainOf internalDamageObjects; Stuff::ChainOf armatureChain; Stuff::ChainOf idleEffects; Adept::ResourceID damageStreamResourceID; Adept::ResourceID subsystemStreamResourceID; typedef std::vector GroupList; const GroupList& GetGroups() const; GroupList& GetGroups(); void BecomeInteresting(bool render_me); void CheckVideoStates(bool render_me); // MSL 5.05 Torso virtual void DestroyLeftArmSpecialZones() {}; virtual void DestroyRightArmSpecialZones() {}; virtual void DestroyLeftTorsoSpecialZones() {}; virtual void DestroyRightTorsoSpecialZones() {}; virtual void DestroyLeftLegSpecialZones() {}; virtual void DestroyRightLegSpecialZones() {}; virtual void DestroyLeftArm() {}; virtual void DestroyRightArm() {}; virtual void SetLeftGimp() {}; virtual void SetRightGimp() {}; // MSL 5.02 headshot virtual void HeadShotInternal() {}; // MSL 5.03 Gyro Hit virtual void GyroHitInternal() {}; Stuff::Scalar GetTonage() { Check_Object(this); return tonage; } void AddTonage(Stuff::Scalar add_tonage) { Check_Object(this); tonage += add_tonage; } void SubtractTonage(Stuff::Scalar subtract_tonage) { Check_Object(this); tonage -= subtract_tonage; } void SetTonnage(Stuff::Scalar new_tonnage) { Check_Object(this); tonage = new_tonnage; } bool DoesHaveAvailableTonage(Stuff::Scalar tons); int GetBattleValue() { Check_Object(this); return battleValue; } void AddBattleValue(int add_value) { Check_Object(this); battleValue += add_value; } void SubtractBattleValue(int subtract_value) { Check_Object(this); battleValue -= subtract_value; } VehicleInterface *vehicleInterface; // int // m_RadarMode; int GetSensorMode(); Sensor* GetSensor() {return sensor;} AMS* GetAMS() {Check_Object(this); return ams;} Beagle *GetBeagle() {Check_Object(this); return beagle;} bool DoesHaveBeagle(); void DestroyBeagle() {Check_Object(this); beagle = NULL;} ECM *GetECM() {Check_Object(this); return ecm;} bool DoesHaveECM() {return ecm != NULL;} void DestroyECM() {Check_Object(this); ecm = NULL;} // MSL 5.02 SubSystems // EnhancedOptics // *GetEnhancedOptics() // {Check_Object(this); return enhancedOptics;} // bool // DoesHaveEnhancedOptics() // {return enhancedOptics != NULL;} // void // DestroyEnhancedOptics() // {Check_Object(this); enhancedOptics = NULL;} IFF_Jammer *GetIFF_Jammer() {Check_Object(this); return iff_jammer;} bool DoesHaveIFF_Jammer() {return iff_jammer != NULL;} void DestroyIFF_Jammer() {Check_Object(this); iff_jammer = NULL;} AdvancedGyro *GetAdvancedGyro() {Check_Object(this); return advancedGyro;} bool DoesHaveAdvancedGyro() {return advancedGyro != NULL;} void DestroyAdvancedGyro() {Check_Object(this); advancedGyro = NULL;} virtual void AddStatsToString(std::string& s); void AddDamageInfoToString(std::string& s); void SetTargetDesirability(Stuff::Scalar desirability); Stuff::Scalar GetTargetDesirability() const; virtual void NotifyFired(const Adept::Entity::CollisionQuery& query); void NotifyInTargetingReticule(MWObject& mwobject); virtual void GetLineOfSight(Stuff::LinearMatrix4D& line_of_sight); Stuff::Point3D GetLineOfSight(); virtual Stuff::Scalar FriendlyFireDamageMultiplier() const; enum { desirability_invalid = -2, desirability_never = -1 }; void NotifyProjectileApproaching(const Stuff::Point3D& origin); Adept::ResourceID ReactToMissileApproach(Stuff::Scalar distance, const Stuff::Point3D& current_position); void NotifyOfMissileLock(); virtual Stuff::Point3D& EstimateFuturePosition( Stuff::Point3D *new_position, Stuff::Scalar seconds, bool consider_terrain = true ); void Reuse( const CreateMessage *message, Adept::ReplicatorID *base_id ); bool m_markedForSalvage; private: Stuff::Scalar tonage; int battleValue; std::vector m_groups; Stuff::Scalar m_TargetDesirability; protected: Sensor *sensor; Beagle *beagle; AMS *ams; ECM *ecm; // MSL 5.02 SubSystems // EnhancedOptics // *enhancedOptics; IFF_Jammer *iff_jammer; AdvancedGyro *advancedGyro; bool m_VisibleOnSensors; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Localization Support // public: char* GetObjectName(); char* GetModelName(); bool m_doesHaveInstanceName; int m_localizeIndex; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Test Support // public: void TestInstance() const; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // public: virtual void HookUpSubsystems(void); void ReuseSubsystems(Stuff::MemoryStream *stream); virtual void AddSubsystem(Subsystem *subsystem); virtual void RemoveSubsystem(Subsystem *subsystem); Torso* GetTorso(int index = 0) { Check_Object(this); if ((index < 0) || (index >= m_Torsos.size())) { return (0); } return m_Torsos[index]; } int NumTorsos() const { return (m_Torsos.size()); } bool GetVisibleOnSensors() const; void SetVisibleOnSensors(bool visible); SearchLight* GetSearchLight() {Check_Object(this); return searchLight;} Stuff::ChainOf weaponChain; Stuff::SlotOf eyeSitePointer; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Heat support // public: virtual void ReactToOverHeat() {} virtual void SetCooling(int new_int) {} HeatManager *m_heatManager; const std::vector& GetTorsos() { return (m_Torsos); } // virtual void // SetSearchLightMode(bool fOn) // {} //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Subsystem vars protected: std::vector m_Torsos; SearchLight *searchLight; // bool // m_previousSearchLightState; public: void SetDmgModifier (int nIdx, int nDmgFactor); // jcem void RepairDamage (Stuff::Scalar fRepair); // jcem }; }