#include "MW4Headers.hpp" #include "Sensor.hpp" #include "Vehicle.hpp" #include "Building.hpp" #include "MWPlayer.hpp" #include "SubsystemClassData.hpp" #include "mwmission.hpp" #include "vehicleinterface.hpp" #include "narc.hpp" #include "mwapplication.hpp" #include #include #include #ifdef NEW_SENSOR_TIMING __int64 tSensorTime; __int64 tSensorFillTime; __int64 tSensorCheckTime; __int64 tVehicleTime; DWORD tTotalSensorsExecuted; #endif; Stuff::Time Sensor::s_LastSensorCheck = 0; // jcem - begin #define UNLIMITED_RADAR_RANGE 6000.0f extern bool g_bUnlimitedRadarRange; // jcem - end HGOSHEAP g_SensorHeap = NULL; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // SensorData::SensorData( MWObject *entity, Scalar target_distance_squared, int target_alignment, int chasis_type ) : Plug(Plug::DefaultData), object(NULL) { object.Add(entity); distanceSquared = target_distance_squared; alignment = target_alignment; chasisType = chasis_type; } SensorData::SensorData() : Plug (Plug::DefaultData) , object(NULL) , distanceSquared(0.0f) , alignment(-1) , chasisType(-1) { } SensorData::~SensorData() { } //############################################################################# //########################## ExecutionStateEngine ####################### //############################################################################# Sensor::ExecutionStateEngine::ClassData* Sensor::ExecutionStateEngine::DefaultData = NULL; const StateEngine::StateEntry Sensor::ExecutionStateEngine::StateEntries[]= { STATE_ENTRY(Sensor__ExecutionStateEngine, Active), STATE_ENTRY(Sensor__ExecutionStateEngine, Passive), STATE_ENTRY(Sensor__ExecutionStateEngine, Beagle) }; DECLARE_TIMER(static, Sensor_Time); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Sensor::ExecutionStateEngine::InitializeClass() { Check_Object(StateEngine::DefaultData); Verify(!DefaultData); DefaultData = new ClassData( Sensor__ExecutionStateEngineClassID, "Sensor::ExecutionStateEngine", Subsystem::ExecutionStateEngine::DefaultData, ELEMENTS(StateEntries), StateEntries, (Entity::ExecutionStateEngine::Factory)Make, (Entity::ExecutionStateEngine::FactoryRequest::Factory) &FactoryRequest::ConstructFactoryRequest ); Register_Object(DefaultData); #ifdef NEW_SENSOR_TIMING AddStatistic("Sensors", "%", gos_timedata, (void*)&tSensorTime, 0); AddStatistic("Sensor Fill", "%", gos_timedata, (void*)&tSensorFillTime, 0); AddStatistic("Sensor Check", "%", gos_timedata, (void*)&tSensorCheckTime, 0); AddStatistic("Vehicle Time", "%", gos_timedata, (void*)&tVehicleTime, 0); AddStatistic("Total Sensors", "%", gos_DWORD, (void*)&tTotalSensorsExecuted, Stat_AutoReset + Stat_Graph); #endif } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Sensor::ExecutionStateEngine::TerminateClass() { Unregister_Object(DefaultData); delete DefaultData; DefaultData = NULL; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Sensor::ExecutionStateEngine* Sensor::ExecutionStateEngine::Make( Sensor *weapon, FactoryRequest *request ) { Check_Object(weapon); Check_Object(request); gos_PushCurrentHeap(Heap); Sensor::ExecutionStateEngine *sensor = new Sensor::ExecutionStateEngine(DefaultData, weapon, request); gos_PopCurrentHeap(); return sensor; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Sensor::ExecutionStateEngine::TestInstance() const { Verify(IsDerivedFrom(DefaultData)); } //############################################################################# //############################### Sensor ############################## //############################################################################# Sensor::ClassData* Sensor::DefaultData = NULL; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Sensor::InitializeClass() { Verify(!DefaultData); DefaultData = new ClassData( SensorClassID, "MechWarrior4::Sensor", Subsystem::DefaultData, 0, NULL, (Entity::Factory)Make, (Entity::CreateMessage::Factory)CreateMessage::ConstructCreateMessage, ExecutionStateEngine::DefaultData, (Entity::GameModel::Factory)GameModel::ConstructGameModel, NULL, (Entity::GameModel::ReadAndVerifier)GameModel::ReadAndVerify, (Entity::GameModel::ModelWrite)GameModel::WriteToText, (Entity::GameModel::ModelSave)GameModel::SaveGameModel, (Subsystem::StreamCreate)CreateStream ); Register_Object(DefaultData); Initialize_Timer(Sensor_Time, "Sensor Time"); Verify(!g_SensorHeap); g_SensorHeap = gos_CreateMemoryHeap("Sensor"); Check_Pointer(g_SensorHeap); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Sensor::TerminateClass() { Unregister_Object(DefaultData); delete DefaultData; DefaultData = NULL; Check_Pointer(g_SensorHeap); gos_DestroyMemoryHeap(g_SensorHeap); g_SensorHeap = NULL; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Sensor* Sensor::Make( CreateMessage *message, ReplicatorID *base_id ) { Check_Object(message); gos_PushCurrentHeap(Heap); Sensor *new_entity = new Sensor(DefaultData, message, base_id, NULL); gos_PopCurrentHeap(); Check_Object(new_entity); return new_entity; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Sensor::Sensor( ClassData *class_data, CreateMessage *message, ReplicatorID *base_id, ElementRenderer::Element *element ): Subsystem(class_data, message, base_id, element), m_nearestEnemy(NULL), m_nearestFriendly(NULL), m_LastTimeUpdatedBuildingData(0), m_ContainsEntityLastIndex(0), m_ShutdownRange(0), m_PassiveRange(0), m_ECMRange(0), m_NormalRange(0), m_LastUpdateTime(0), m_NeedsSensorRefresh(false) { Check_Object(message); numberOfContacts = 0; numberOfBuildingContacts = 0; m_UpdateTime = 2.0f; gos_PushCurrentHeap(g_SensorHeap); for(int i=0;i<32;i++) { sensorData[i] = new SensorData(); Register_Object(sensorData[i]); } for(i=0;i<32;i++) { buildingData[i] = new SensorData(); Register_Object(buildingData[i]); } gos_PopCurrentHeap(); executionTimer = Stuff::Random::GetFraction()*2.0f; m_maxRange = 1000.0f; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Sensor::~Sensor() { for(int i=0;i<32;i++) { Unregister_Object(sensorData[i]); delete sensorData[i]; } for(i=0;i<32;i++) { Unregister_Object(buildingData[i]); delete buildingData[i]; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Sensor::CheckBuilding(Entity *entity, Entity *original_caller) { Check_Object(entity); Check_Object(original_caller); Sensor *sensor = Cast_Object(Sensor*, original_caller); MWObject *mw_object = sensor->GetParentVehicle(); int execution_state = sensor->executionState->GetState(); Scalar target_distance_squared = mw_object->GetDistanceSquaredFrom(entity, true); if((!entity->IsDestroyed()) && (entity->GetAlignment() != mw_object->GetAlignment()) && (entity->GetAlignment() != Entity::DefaultAlignment)) { switch(execution_state) { case ExecutionStateEngine::ActiveState: if(target_distance_squared <= 1000000) { Verify(entity->IsDerivedFrom(Building::DefaultData)); MWObject *building = Cast_Object(MWObject *, entity); AddBuildingContact(building, target_distance_squared); } break; case ExecutionStateEngine::BeagleState: if(target_distance_squared <= 1440000) { Verify(entity->IsDerivedFrom(Building::DefaultData)); MWObject *building = Cast_Object(MWObject *, entity); AddBuildingContact(building, target_distance_squared); } break; case ExecutionStateEngine::PassiveState: if(target_distance_squared <= 625000) { Verify(entity->IsDerivedFrom(Building::DefaultData)); MWObject *building = Cast_Object(MWObject *, entity); AddBuildingContact(building, target_distance_squared); } break; } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Sensor::PreCollisionExecute(Time till) { Check_Object(this); PRECOLLISION_LOGIC("Subsystem::Sensor"); // //-------------------------------------------- //Need to check for vehicles within our radius //-------------------------------------------- // Start_Timer(Sensor_Time); if (m_NeedsSensorRefresh == true) { if (s_LastSensorCheck != gos_GetElapsedTime()) { Refresh(); s_LastSensorCheck = gos_GetElapsedTime(); Stop_Timer(Sensor_Time); } return; } else { if (GetParentVehicle()->IsPlayerVehicle() == false) { return; } } if (executionTimer < m_UpdateTime) { Stuff::Scalar time_slice = GetTimeSlice(till); executionTimer += time_slice; Stop_Timer(Sensor_Time); return; } Refresh(); lastExecuted = till; Stop_Timer(Sensor_Time); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Sensor::Refresh() { executionTimer = 0.0f; m_NeedsSensorRefresh = false; #ifdef NEW_SENSOR_TIMING ++tTotalSensorsExecuted; #endif m_nearestEnemy.Remove(); m_nearestEnemyRange = 0.0f; m_nearestFriendly.Remove(); m_nearestFriendlyRange = 0.0f; numberOfContacts = 0; CheckForContacts_VehiclesAndTurrets(); CheckForNarc(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // const Sensor::sensorDataArray& Sensor::RefreshAndGetSensorData() { Start_Timer(Sensor_Time); if (m_LastUpdateTime + 2.0f < (Stuff::Scalar)gos_GetElapsedTime()) { MWMission *mission = Cast_Object (MWMission *,MWMission::GetInstance ()); Check_Object (mission); if (mission->m_VehicleAndTurretCellMap.ChecksumMatches(GetParentVehicle()->GetLocalToWorld(), GetMaxRange(), m_ChecksumList) == false) { if (s_LastSensorCheck == gos_GetElapsedTime()) { m_NeedsSensorRefresh = true; Stop_Timer(Sensor_Time); return (GetSensorData()); } Refresh(); s_LastSensorCheck = gos_GetElapsedTime(); } m_LastUpdateTime = (Stuff::Scalar)gos_GetElapsedTime(); } Stop_Timer(Sensor_Time); return (GetSensorData()); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Sensor::CheckForNarc (void) { if (!GetParentVehicle ()->vehicleInterface) return; MWMission *mission = Cast_Object (MWMission *,MWMission::GetInstance ()); Check_Object (mission); Narc *narc; narc = mission->GetNarc(GetParentVehicle()->GetAlignment()); if (!narc) { GetParentVehicle ()->vehicleInterface->ReactToEvent (VehicleInterface::NARC_SIGNAL_STOP); return; } Scalar target_distance_squared = GetParentVehicle ()->GetDistanceSquaredFrom(narc, true); // MSL - Changed to reflect Max range of LRM missiles // Also changed to give tone if Inside that range... // if (target_distance_squared > (GetMaxRange()*GetMaxRange())) // jcem use func instead of variable directly... // MSL - if there is a function that checks for Max Range of a Weapon then change 2400.0f to that function // checking max range of LRM if (target_distance_squared < (1800.0f*1800.0f)) // jcem use func instead of variable directly... { { GetParentVehicle ()->vehicleInterface->ReactToEvent (VehicleInterface::NARC_SIGNAL_START); } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Sensor::CheckForContacts_Buildings() { #ifdef NEW_SENSOR_TIMING __int64 start_time = GetCycles(); #endif MWMission *mission = Cast_Object (MWMission *,MWMission::GetInstance ()); Check_Object (mission); m_ParentVehiclePos = GetParentVehicle()->GetLocalToWorld(); DetermineRanges(); SensorCellMap::list_type object_list; #ifdef NEW_SENSOR_TIMING __int64 fill_start = GetCycles(); #endif mission->m_BuildingCellMap.Fill(GetParentVehicle()->GetLocalToWorld(), GetMaxRange(), object_list, m_BuildingChecksumList); #ifdef NEW_SENSOR_TIMING tSensorFillTime += GetCycles() - fill_start; __int64 check_start = GetCycles(); #endif {for (SensorCellMap::list_type::const_iterator i = object_list.begin(); i != object_list.end(); ++i) { CheckBuilding(*i,this); }} #ifdef NEW_SENSOR_TIMING tSensorCheckTime += GetCycles() - check_start; tSensorTime += GetCycles() - start_time; #endif } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Sensor::CheckForContacts_VehiclesAndTurrets() { Check_Object(this); Check_Object(NameTable::GetInstance()); #ifdef NEW_SENSOR_TIMING __int64 start_time = GetCycles(); #endif MWMission *mission = Cast_Object (MWMission *,MWMission::GetInstance ()); Check_Object (mission); m_ParentVehiclePos = GetParentVehicle()->GetLocalToWorld(); DetermineRanges(); SensorCellMap::list_type object_list; #ifdef NEW_SENSOR_TIMING __int64 fill_start = GetCycles(); #endif mission->m_VehicleAndTurretCellMap.Fill(GetParentVehicle()->GetLocalToWorld(), GetMaxRange(), object_list, m_ChecksumList); #ifdef NEW_SENSOR_TIMING tSensorFillTime += GetCycles() - fill_start; __int64 check_start = GetCycles(); #endif {for (SensorCellMap::list_type::const_iterator i = object_list.begin(); i != object_list.end(); ++i) { CheckEntity(**i); }} #ifdef NEW_SENSOR_TIMING tSensorCheckTime += GetCycles() - check_start; tSensorTime += GetCycles() - start_time; #endif } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Sensor::UpdateBuildingData() { Check_Object(this); numberOfBuildingContacts = 0; CheckForContacts_Buildings(); m_LastTimeUpdatedBuildingData = (Scalar)gos_GetElapsedTime(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Sensor::DestroySubsystem() { Check_Object(this); // numberOfContacts = 0; // Subsystem::DestroySubsystem(); // EnterNeverExecuteState(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Sensor::AddBuildingContact(MWObject *vehicle, Scalar target_distance_squared) { Check_Object(this); Check_Object(vehicle); if(numberOfBuildingContacts < 32) { buildingData[numberOfBuildingContacts]->object.Remove(); buildingData[numberOfBuildingContacts]->object.Add(vehicle); buildingData[numberOfBuildingContacts]->distanceSquared = target_distance_squared; buildingData[numberOfBuildingContacts]->alignment = vehicle->GetAlignment(); ++numberOfBuildingContacts; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Sensor::SetSensorMode(int mode, bool has_beagle) { Check_Object(this); Check_Object(executionState); sensorMode = mode; switch(mode) { case ActiveMode: if(has_beagle) { executionState->RequestState(ExecutionStateEngine::BeagleState); m_maxRange = 1200.0f; } else { executionState->RequestState(ExecutionStateEngine::ActiveState); m_maxRange = 1000.0f; } break; case PassiveMode: executionState->RequestState(ExecutionStateEngine::PassiveState); m_maxRange = 250.0f; break; } } bool Sensor::SensorDataOK(SensorData& data, int alignment) { MWObject *veh; veh = GetParentVehicle(); int rel_align; if ((data.object.GetCurrent() == 0) || (data.object.GetCurrent()->IsDestroyed())) return false; rel_align = veh->GetRelativeAlignment (data.alignment); return (rel_align == alignment); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Entity* Sensor::GetNextEnemy(Entity *current_enemy, bool previous) { Check_Object(this); if (MWApplication::GetInstance()->networkingFlag) { NetMissionParameters::MWNetMissionParameters *params = MWApplication::GetInstance()->GetLocalNetParams(); if ((params->m_radarMode != 0) && (params->m_radarMode != 3)) { return NULL; } } if(current_enemy) { for(int i=0; i< numberOfContacts; i++) { if(sensorData[i]->object.GetCurrent() == current_enemy) { if (previous == false) { for(int q=(i+1); q< numberOfContacts; q++) { if (SensorDataOK(*sensorData[q],Entity::Enemy) == true) return sensorData[q]->object.GetCurrent(); } for(int y=0; y<=i; y++) { if (SensorDataOK(*sensorData[y],Entity::Enemy) == true) return sensorData[y]->object.GetCurrent(); } } else { for(int q=(i-1); q >= 0; --q) { if (SensorDataOK(*sensorData[q],Entity::Enemy) == true) return sensorData[q]->object.GetCurrent(); } for(int y=(numberOfContacts - 1); y > i; --y) { if (SensorDataOK(*sensorData[y],Entity::Enemy) == true) return sensorData[y]->object.GetCurrent(); } } } } } for(int i=0; i< numberOfContacts; i++) { if (SensorDataOK(*sensorData[i],Entity::Enemy) == true) return sensorData[i]->object.GetCurrent(); } return NULL; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Entity* Sensor::GetNearestEnemy() { Check_Object(this); Entity * entity = m_nearestEnemy.GetCurrent(); if (MWApplication::GetInstance()->networkingFlag) { NetMissionParameters::MWNetMissionParameters *params = MWApplication::GetInstance()->GetLocalNetParams(); if ((params->m_radarMode != 0) && (params->m_radarMode != 3)) { return NULL; } } if (entity) { if (entity->IsDestroyed()) { m_NeedsSensorRefresh = true; return NULL; } } return entity; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Entity* Sensor::GetNextFriendly(Entity *current_friendly, bool previous) { Check_Object(this); if (MWApplication::GetInstance()->networkingFlag) { NetMissionParameters::MWNetMissionParameters *params = MWApplication::GetInstance()->GetLocalNetParams(); if (params->m_radarMode == 2) { return NULL; } } if(current_friendly) { for(int i=0; i< numberOfContacts; i++) { if(sensorData[i]->object.GetCurrent() == current_friendly) { if (previous == false) { for(int q=(i + 1); q< numberOfContacts; q++) { if (SensorDataOK(*sensorData[q],Entity::Player) == true) return sensorData[q]->object.GetCurrent(); } for(int y=0; y<=i; y++) { if (SensorDataOK(*sensorData[y],Entity::Player) == true) return sensorData[y]->object.GetCurrent(); } } else { for(int q=(i-1); q >= 0; --q) { if (SensorDataOK(*sensorData[q],Entity::Player) == true) return sensorData[q]->object.GetCurrent(); } for(int y=(numberOfContacts - 1); y > i; --y) { if (SensorDataOK(*sensorData[y],Entity::Player) == true) return sensorData[y]->object.GetCurrent(); } } } } } for(int i=0; i< numberOfContacts; i++) { if (SensorDataOK(*sensorData[i],Entity::Player) == true) return sensorData[i]->object.GetCurrent(); } return NULL; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Entity* Sensor::GetNearestFriendly() { Check_Object(this); if (MWApplication::GetInstance()->networkingFlag) { NetMissionParameters::MWNetMissionParameters *params = MWApplication::GetInstance()->GetLocalNetParams(); if (params->m_radarMode == 2) { return NULL; } } return m_nearestFriendly.GetCurrent(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Scalar Sensor::GetMaxRange() { Check_Object(this); Check_Object(executionState); // jcem - begin if (g_bUnlimitedRadarRange) return UNLIMITED_RADAR_RANGE; // jcem - end return m_maxRange; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Sensor::TestInstance() const { Verify(IsDerivedFrom(DefaultData)); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Scalar Sensor::GetLastTimeUpdatedBuildingData() const { return (m_LastTimeUpdatedBuildingData); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool Sensor::ContainsEntity(Adept::Entity* entity) { if ((m_ContainsEntityLastIndex < numberOfContacts) && (sensorData[m_ContainsEntityLastIndex]->object.GetCurrent() == entity)) { return (true); } {for (int i = 0; i < numberOfContacts; ++i) { if (sensorData[i]->object.GetCurrent() == entity) { m_ContainsEntityLastIndex = i; return (true); } }} if ((entity != 0) && (entity->IsDerivedFrom(Building::DefaultData) == true)) { {for (int i = 0; i < numberOfBuildingContacts; ++i) { if (buildingData[i]->object.GetCurrent() == entity) { m_ContainsEntityLastIndex = numberOfContacts; return (true); } }} } return (false); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool Sensor::CanSeeEntity(MWObject& mwobject) { if ((mwobject.IsDestroyed() == true) || (&mwobject == GetParentVehicle()) || (mwobject.GetVisibleOnSensors() == false)) { return (false); } if (mwobject.IsPlayerVehicle() == true) { if (mwobject.executionState->GetState() == Entity::ExecutionStateEngine::NeverExecuteState) { return (false); } } else { if (mwobject.HasAI() == 0) { if ((MWApplication::GetInstance()->networkingFlag == false) || (mwobject.IsDerivedFrom(Mech::DefaultData) == false)) { return (false); } } } return (true); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Stuff::Scalar Sensor::SquaredRangeToEntity(MWObject& mwobject) { Scalar x_delta = mwobject.GetLocalToWorld()(W_Axis, X_Axis) - m_ParentVehiclePos.x; x_delta *= x_delta; Scalar z_delta = mwobject.GetLocalToWorld()(W_Axis, Z_Axis) - m_ParentVehiclePos.z; z_delta *= z_delta; return(x_delta + z_delta); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Stuff::Scalar Sensor::CurrentMaxDetectionRangeTo(MWObject& mwobject) { if (mwobject.vehicleShutDown == true) { return (m_ShutdownRange); } if (mwobject.GetSensorMode() == PassiveMode) { return (m_PassiveRange); } if (mwobject.DoesHaveECM() == true) { return (m_ECMRange); } return (m_NormalRange); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Sensor::CheckEntity(MWObject& mwobject) { Check_Object(executionState); if (CanSeeEntity(mwobject) == false) { return; } Stuff::Scalar detection_range_squared = CurrentMaxDetectionRangeTo(mwobject); if (detection_range_squared == 0) { return; } Stuff::Scalar target_distance_squared = SquaredRangeToEntity(mwobject); if (target_distance_squared > detection_range_squared) { return; } if (GetParentVehicle()->vehicleInterface) { if ((mwobject.vehicleJustPoweredUp) && (GetParentVehicle()->GetRelativeAlignment(mwobject.GetAlignment()) == Adept::Entity::Enemy)) { mwobject.vehicleJustPoweredUp = false; GetParentVehicle()->vehicleInterface->ReactToEvent(VehicleInterface::NEW_VEHICLE_RADAR_POWER_UP); } } int mwobject_alignment(mwobject.GetAlignment()); int my_alignment(GetParentVehicle()->GetAlignment()); if (mwobject_alignment != my_alignment) { if (mwobject_alignment != Entity::DefaultAlignment) { if ((!m_nearestEnemy.GetCurrent()) || (m_nearestEnemyRange > target_distance_squared)) { m_nearestEnemy.Remove(); m_nearestEnemy.Add((Entity *)&mwobject); m_nearestEnemyRange = target_distance_squared; } } } else { if ((!m_nearestFriendly.GetCurrent()) || (m_nearestFriendlyRange > target_distance_squared)) { m_nearestFriendly.Remove(); m_nearestFriendly.Add((Entity *)&mwobject); m_nearestFriendlyRange = target_distance_squared; } } if (numberOfContacts < 32) { SensorData* sensor_data = sensorData[numberOfContacts]; sensor_data->object.Remove(); sensor_data->object.Add(&mwobject); sensor_data->distanceSquared = target_distance_squared; sensor_data->alignment = mwobject_alignment; ++numberOfContacts; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Sensor::DetermineRanges() { MWMission *mission = Cast_Object (MWMission *,MWMission::GetInstance ()); Check_Object (mission); // jcem - begin if (g_bUnlimitedRadarRange) { m_PassiveRange = m_ECMRange = m_NormalRange = m_ShutdownRange = UNLIMITED_RADAR_RANGE * UNLIMITED_RADAR_RANGE; return; } // jcem - end switch (executionState->GetState()) { case ExecutionStateEngine::ActiveState: { m_PassiveRange = 500.0f * 500.0f; m_ECMRange = 500.0f * 500.0f; m_NormalRange = 1000.0f * 1000.0f; // MSL 5.04 Modified Shutdown Range // m_ShutdownRange = 50.0f * 50.0f; // MSL 5.05 Modified Shutdown Range m_ShutdownRange = 500.0f * 500.0f; break; } case ExecutionStateEngine::BeagleState: { m_PassiveRange = 600.0f * 600.0f; // MSL 5.04 Modified Beagle Range m_ECMRange = 700.0f * 700.0f; m_NormalRange = 1200.0f * 1200.0f; // m_ShutdownRange = 100.0f * 100.0f; // MSL 5.05 Modified Shutdown Range m_ShutdownRange = 600.0f * 600.0f; break; } case ExecutionStateEngine::PassiveState: { m_ECMRange = 100.0f * 100.0f; m_NormalRange = 250.0f * 250.0f; m_ShutdownRange = 0; m_PassiveRange = 0; break; } default: { m_ShutdownRange = 0; m_PassiveRange = 0; m_ECMRange = 0; m_NormalRange = 0; break; } } }