//===========================================================================// // File: Building.cpp //---------------------------------------------------------------------------// // Date Who Modification // // -------- --- ---------------------------------------------------------- // // 05/06/99 DPB Inital base class //---------------------------------------------------------------------------// // Copyright (C) 1998, Fasa Interactive // // All Rights reserved worldwide // // This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // //===========================================================================// #include "MW4Headers.hpp" #include "Building.hpp" #include "CombatAI.hpp" #include "obstacle.hpp" #include "Weapon.hpp" #include #include "MWMission.hpp" #include "MWDamageObject.hpp" //############################################################################# //############################### Building ############################## //############################################################################# extern int g_nMR; Building::ClassData* Building::DefaultData = NULL; DWORD MechWarrior4::Executed_Building_Count = 0; bool MechWarrior4::Building::m_BuildingsAddedToCellMap = false; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Building::InitializeClass() { Verify(!DefaultData); DefaultData = new ClassData( BuildingClassID, "MechWarrior4::Building", MWObject::DefaultData, 0, NULL, (Entity::Factory)Make, (Entity::CreateMessage::Factory)CreateMessage::ConstructCreateMessage, ExecutionStateEngine::DefaultData, (Entity::GameModel::Factory)GameModel::ConstructGameModel, (Entity::GameModel::Factory)GameModel::ConstructOBBStream, (Entity::GameModel::ReadAndVerifier)GameModel::ReadAndVerify, (Entity::GameModel::ModelWrite)GameModel::WriteToText, (Entity::GameModel::ModelSave)GameModel::SaveGameModel, AnimationStateEngine::Make ); Register_Object(DefaultData); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Building::TerminateClass() { Unregister_Object(DefaultData); delete DefaultData; DefaultData = NULL; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Building* Building::Make( CreateMessage *message, ReplicatorID *base_id ) { gos_PushCurrentHeap(Heap); Building *new_entity = new Building(DefaultData, message, base_id, NULL); gos_PopCurrentHeap(); Check_Object(new_entity); return new_entity; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Building::Building( ClassData *class_data, CreateMessage *message, ReplicatorID *base_id, ElementRenderer::Element *element ): MWObject(class_data, message, base_id, element) , //the abl call markBuildingAsScorable is made in siege assault //strong hold type maps. //If set, when the building is destroyed points are awarded. //Turrets will always be scored. m_scoreThisBuilding (false) { Check_Pointer(this); Check_Object(message); CommonCreation(message); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Building::CommonCreation(CreateMessage *message) { Check_Object(this); Check_Object(message); m_AddedToSensorCellMap = false; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Building::LoadAnimationScripts() { MWObject::LoadAnimationScripts(); if (!m_AI) { const GameModel *model = GetGameModel(); if(model->animScriptName[0] != NULL) { executionState->RequestState(ExecutionStateEngine::AlwaysExecuteState); animStateEngine->RequestState(AnimationStateEngine::Test1State); } // if(!executingSubsystems.IsEmpty()) // executionState->RequestState(ExecutionStateEngine::AlwaysExecuteState); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Building::Respawn(Entity::CreateMessage *message) { Check_Object(this); Check_Object(message); MWObject::Respawn(message); CreateMessage *building_message = Cast_Pointer(CreateMessage *, message); CommonCreation(building_message); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Building::~Building() { DESTRUCTOR("Building"); } void Building::TurnOn (void) { lastParameterization = gos_GetElapsedTime (); const GameModel *model = GetGameModel(); if(model->animScriptName[0] != NULL) { executionState->RequestState(ExecutionStateEngine::AlwaysExecuteState); animStateEngine->RequestState(AnimationStateEngine::Test1State); } if(!executingSubsystems.IsEmpty()) executionState->RequestState(ExecutionStateEngine::AlwaysExecuteState); } void Building::TurnOff (void) { executionState->RequestState(ExecutionStateEngine::NeverExecuteState); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Building::Reuse( const CreateMessage *message, ReplicatorID *base_id ) { Check_Object(this); STOP(("Not implemented")); MWObject::Reuse(message, base_id); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int Building::GetExecutionSlot() { Check_Object(this); return BuildingExecutionSlot; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Building::PreCollisionExecute(Stuff::Time till) { Check_Object(this); Check_Object(animStateEngine); PRECOLLISION_LOGIC("Building"); Scalar time_slice = GetTimeSlice(till); Verify(time_slice > 0.0f); Verify(executionState->GetState() != ExecutionStateEngine::NeverExecuteState); Check_Object(animStateEngine); if(animStateEngine->GetState() != AnimationStateEngine::UninitializedState) { animStateEngine->RunStates(time_slice); } Set_Statistic(Executed_Building_Count, Executed_Building_Count+1); MWObject::PreCollisionExecute(till); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #if defined(LAB_ONLY) void Building::SyncMatrices(bool update_matrix) { SYNC_LOGIC("Building"); BaseClass::SyncMatrices(update_matrix); } #endif //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Building::ReactToDestruction(int damage_mode, int damage_type) { Check_Object(this); if(!IsDestroyed()) { //added for scroing objective building in strong holds and siege assault if (m_scoreThisBuilding) { Check_Object (Mission::GetInstance()); Mission::GetInstance()->ScoringReactToBuildingDeath (m_whoShotMeLast, GetReplicatorID()); } if(m_AI) { Check_Object(m_AI); m_AI->Die(); } SetDestroyedFlag(damage_mode); if (damage_type != SplashDamageType) DealSplashDamage(); MW4AI::g_Rect4DHash->RemovePermRect (this); const GameModel *model = GetGameModel(); Check_Object(model); // CreateEffect(model->destroyedEffectResource, (Point3D)GetLocalToWorld()); CreateEffect(model->destroyedEffectResource, this); Entity *death_entity = CreateStaticHermitEntity(model->deathEntityResource); if((death_entity) && (!m_deathEntity.GetCurrent())) { m_deathEntity.Remove(); m_deathEntity.Add(death_entity); } RemoveFromExecution(); } Entity::ReactToDestruction(damage_mode, damage_type); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Building::TestInstance() const { Verify(IsDerivedFrom(DefaultData)); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Building::ReactToHit(const Entity__TakeDamageMessage *message,Adept::DamageObject *part_hit) { Check_Object(this); Check_Object(message); MWObject::ReactToHit(message,part_hit); if (g_nMR == 2) return; // TODO: this should be more general and should take near // misses into account as well as direct hits -- PAULT if (GetAI() != 0) { NotifyAIShot(*(GetAI()),message->inflictingEntityID); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Stuff::Scalar Building::FriendlyFireDamageMultiplier() const { if (MW4AI::UserConstants::Instance() != 0) { return (MW4AI::UserConstants::Instance()->Get(MW4AI::UserConstants::building_ff_multiplier)); } return (1); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Building::GetLineOfSight(Stuff::LinearMatrix4D& line_of_sight) { Stuff::ChainIteratorOf i(&weaponChain); MechWarrior4::Weapon* weapon = i.ReadAndNext(); if ((weapon != 0) && (weapon->sitePointer != 0) && (weapon->sitePointer->GetParent() != 0)) { line_of_sight = weapon->sitePointer->GetParent()->GetLocalToWorld(); return; } MWObject::GetLineOfSight(line_of_sight); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void AddOrRemoveFromMap(SensorCellMap& sensor_cell_map, int name_table_array, bool add) { NameTable *table = NameTable::GetInstance(); int size(table->nameTableArray[name_table_array].GetLength()); {for (int i = 0; i < size; ++i) { NameTableEntry *data = &table->nameTableArray [name_table_array][i]; Adept::Entity* entity = data->dataPointer->GetCurrent (); if ((entity != 0) && (entity->IsDerivedFrom(Building::DefaultData) == true)) { Building* building = Cast_Object(Building*,entity); if (building->m_AddedToSensorCellMap != add) { if (add == true) { sensor_cell_map.Add(building,building->GetLocalToWorld()); } else { sensor_cell_map.Remove(building,building->GetLocalToWorld()); } } building->m_AddedToSensorCellMap = add; } }} } void Building::AddAllBuildingsToSensorCellMap() { if ((NameTable::GetInstance() == 0) || (m_BuildingsAddedToCellMap == true) || (MWMission::GetInstance() == 0)) { return; } MWMission* mwmission = Cast_Object(MWMission*,MWMission::GetInstance()); AddOrRemoveFromMap(mwmission->m_BuildingCellMap,NameTable::BuildingArray,true); AddOrRemoveFromMap(mwmission->m_VehicleAndTurretCellMap,NameTable::TurretArray,true); m_BuildingsAddedToCellMap = true; } void Building::RemoveAllBuildingsFromSensorCellMap() { if ((NameTable::GetInstance() == 0) || (m_BuildingsAddedToCellMap == false) || (MWMission::GetInstance() == 0)) { return; } MWMission* mwmission = Cast_Object(MWMission*,MWMission::GetInstance()); AddOrRemoveFromMap(mwmission->m_BuildingCellMap,NameTable::BuildingArray,false); AddOrRemoveFromMap(mwmission->m_VehicleAndTurretCellMap,NameTable::TurretArray,false); m_BuildingsAddedToCellMap = false; }