//===========================================================================// // File: HeatManager.cpp //---------------------------------------------------------------------------// // Date Who Modification // // -------- --- ---------------------------------------------------------- // // 12/26/01 MSL Added code to Restart Mech only if < 90% Heat // // 12/26/01 MSL Disabled LOW_HEAT betty // // 12/26/01 MSL Disabled MED_HEAT betty // // 01/09/02 MSL Adjusted Coolant loss and Heat dissapated by Coolant // //---------------------------------------------------------------------------// //===========================================================================// #include "MW4Headers.hpp" #include "HeatManager.hpp" #include "Mech.hpp" #include "AI.hpp" #include "VehicleInterface.hpp" #include "MWApplication.hpp" // MSL 5.03 Lava #include "DamageDispatch.hpp" #include #include //############################################################################# //########################### HeatManager ############################### //############################################################################# HeatManager::ClassData* HeatManager::DefaultData = NULL; bool HeatManager::g_OverrideHeatOption = false; void MechWarrior4::HeatSecurityCheckStart() { _asm { nop } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void HeatManager::InitializeClass() { Verify(!DefaultData); DefaultData = new ClassData( HeatManagerClassID, "MechWarrior4::HeatManager", Receiver::DefaultData, 0, NULL ); Check_Object(DefaultData); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void HeatManager::TerminateClass() { Check_Object(DefaultData); delete DefaultData; DefaultData = NULL; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool HeatOn(NetMissionParameters::MWNetMissionParameters& net_params) { if (InputTrainer::GetInstance()->GetFlags() != InputTrainer::ALL) { return (InputTrainer::GetInstance()->GetEnabled(InputTrainer::HEAT)); } return (Network::GetInstance()->AmIServer() && net_params.m_heatOn); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // HeatManager::HeatManager( Stuff::Scalar max_heat, Stuff::Scalar current_heat, Stuff::Scalar max_coolant, Stuff::Scalar current_coolant, Mech *parent, Adept::ResourceID stream_id ) : Adept::Receiver(DefaultData), heatObjects(NULL), coolantEffect(NULL), overHeatEffect(NULL) { maxHeat = max_heat; heatValue = current_heat; Clamp(heatValue, 0.0f, maxHeat); maxCoolant = max_coolant; coolantValue = current_coolant; lastTime = gos_GetElapsedTime(); isCooling = 0; lastCoolTime = gos_GetElapsedTime(); SetCoolantPercentage(); SetHeatPercentage(); isHeatDirty = 1; isCoolantDirty = 1; m_parentMech = parent; shutdown = false; m_shuttingDown = false; m_startingUp = false; m_shutDownTimer = gos_GetElapsedTime(); m_startUpTimer = gos_GetElapsedTime(); m_overHeatCheckTime = gos_GetElapsedTime(); m_overHeatTimer = gos_GetElapsedTime(); over90 = false; // MSL 5.03 Lava m_maxHeatTimer = gos_GetElapsedTime(); atMaxHeat = false; Resource stream(stream_id); Verify(stream.DoesResourceExist()); stream >> m_movementHeat; stream >> m_doubleMovementHeat; stream >> m_heatEffectsSpeed; stream >> m_shutDownTime; m_movementHeatObject = NULL; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // HeatManager::~HeatManager() { heatObjects.DeletePlugs(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void HeatManager::Reuse() { Check_Object(this); heatValue = 0.0f; lastTime = gos_GetElapsedTime(); coolantValue = maxCoolant; lastTime = gos_GetElapsedTime(); isCooling = 0; lastCoolTime = gos_GetElapsedTime(); SetCoolantPercentage(); SetHeatPercentage(); shutdown = false; m_shuttingDown = false; m_shutDownTimer = gos_GetElapsedTime(); m_startUpTimer = gos_GetElapsedTime(); m_overHeatCheckTime = gos_GetElapsedTime(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void HeatManager::AddHeat(Stuff::Scalar added_heat) { Check_Object(this); NetMissionParameters::MWNetMissionParameters *params = MWApplication::GetInstance()->GetLocalNetParams(); if (HeatOn(*params) == true) { if(added_heat < 0.0f) { Check_Object(Mission::GetInstance()); const Mission::GameModel *mission_model = Mission::GetInstance()->GetGameModel(); Check_Object(mission_model); added_heat *= mission_model->m_heatSinkEfficiency; added_heat *= m_parentMech->m_heatMaterialMultiplier; } heatValue += added_heat; Clamp(heatValue, 0.0f, maxHeat); } isHeatDirty = 1; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void HeatManager::SetCooling(int new_int) { Check_Object(this); if (new_int) { if (coolantValue > 0.0f) { if(m_parentMech->vehicleInterface) m_parentMech->vehicleInterface->ReactToEvent (VehicleInterface::COOLANT_FLUSH_START); isCooling = new_int; } } else { isCooling = new_int; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void HeatManager::ApplyMovementHeat(Scalar current_rate, Scalar max_rate) { Check_Object(this); NetMissionParameters::MWNetMissionParameters *params = MWApplication::GetInstance()->GetLocalNetParams(); if (HeatOn(*params) == true) { current_rate = Abs(current_rate); Scalar ratio = current_rate / max_rate; if(m_movementHeatObject == NULL) { m_movementHeatObject = AddHeatObject(1.0, true); } Check_Object(m_movementHeatObject); if(ratio == 0) { m_movementHeatObject->heatApplied = 0.0f; } else if(ratio < m_doubleMovementHeat) { m_movementHeatObject->heatApplied = m_movementHeat; } else { m_movementHeatObject->heatApplied = m_movementHeat * 2; } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // HeatObject* HeatManager::AddHeatObject(Stuff::Scalar times_applied, Scalar heat_applied, bool is_permanent) { Check_Object(this); NetMissionParameters::MWNetMissionParameters *params = MWApplication::GetInstance()->GetLocalNetParams(); if ((HeatOn(*params) == true) || (HeatManager::g_OverrideHeatOption == true)) { HeatObject *heat_object = new HeatObject(times_applied, heat_applied, is_permanent); Check_Object(heat_object); heatObjects.Add(heat_object); return heat_object; } return NULL; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // HeatObject* HeatManager::AddHeatObject(Scalar heat_applied, bool is_permanent) { Check_Object(this); NetMissionParameters::MWNetMissionParameters *params = MWApplication::GetInstance()->GetLocalNetParams(); if ((HeatOn(*params) == true) || (HeatManager::g_OverrideHeatOption == true)) { HeatObject *heat_object = new HeatObject(heat_applied, is_permanent); Check_Object(heat_object); heatObjects.Add(heat_object); return heat_object; } return NULL; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Stuff::Scalar HeatManager::EstimateMaxCurrentHeat() { Stuff::Scalar heat = heatValue; ChainIteratorOf iterator(&heatObjects); HeatObject *heat_object; while ((heat_object = iterator.ReadAndNext()) !=NULL) { heat += heat_object->heatApplied; } Clamp(heat,0.0f,maxHeat); if (heatValue > heat) { return (heatValue); } return (heat); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool HeatManager::Execute() { Check_Object(this); bool return_value = false; //mark not overheating to default; NetMissionParameters::MWNetMissionParameters *params = MWApplication::GetInstance()->GetLocalNetParams(); if ((Network::GetInstance()->AmIServer() && params->m_heatOn) || (HeatManager::g_OverrideHeatOption == true)) { if(isCooling) { // MSL 5.06 //#define HEAT_AND_COOLANT 10.0f // jcem Gold Version Value : -8.0f..., below 3 lines should use same value.... #define HEAT_AND_COOLANT 5.0f // Changed from 10.0f to 5.0f if((coolantValue - HEAT_AND_COOLANT) >= 0.0f) { if(gos_GetElapsedTime() - lastCoolTime >= 0.3f) { lastCoolTime = gos_GetElapsedTime(); // Changed AddHeat(-3.6f); // MSL 5.00 AddHeat(-HEAT_AND_COOLANT); // Changed AddCoolant(-10.0f); // MSL 5.00 AddCoolant(-HEAT_AND_COOLANT); } } else { if(m_parentMech->vehicleInterface) m_parentMech->vehicleInterface->ReactToEvent (VehicleInterface::COOLANT_FLUSH_STOP); coolantValue = 0.0f; isCooling = false; } #undef HEAT_AND_COOLANT } if(!heatObjects.IsEmpty()) { if(gos_GetElapsedTime() - lastTime >= 0.5f) { lastTime = gos_GetElapsedTime(); ChainIteratorOf iterator(&heatObjects); HeatObject *heat_object; while((heat_object = iterator.GetCurrent()) !=NULL) { Check_Object(heat_object); AddHeat(heat_object->heatApplied); heat_object->currentCount++; if(!heat_object->isPermanent) { if(heat_object->currentCount >= heat_object->timesApplied) { iterator.Remove(); delete heat_object; } else { iterator.ReadAndNext(); } } else { iterator.ReadAndNext(); } } } } //Ok here you want to do your time check. If you are over 90 for so long then send a die //to the player //Jerry because this means we are the server do we have to some how post this command or can //we process it directly. Not checking in until I have your ok. if(m_parentMech->vehicleShutDown) { over90 = false; } if((GetHeatPercentage() >= 0.85f) && (!shutdown)) { if(!over90) { m_overHeatTimer = gos_GetElapsedTime(); over90 = true; } else { if(gos_GetElapsedTime() - m_overHeatTimer > 10.0f) { // MSL 5.03 Lava // m_parentMech->SelfDestruct(); if (!DamageDispatch::GetGlobalInvulnerability() || (MWApplication::GetInstance()->networkingFlag)) { m_parentMech->SelfDestruct(); goto skipShutdownHeatCheck; } } } } else { over90 = false; } // MSL 5.03 Lava if ((GetHeatPercentage () >= 0.85f) && (m_parentMech->vehicleShutDown) && ((m_parentMech->materialHit ==OpenLavaMaterial ) || (m_parentMech->materialHit == CrackedLavaMaterial) )) { if (!atMaxHeat) { m_maxHeatTimer = gos_GetElapsedTime(); atMaxHeat = true; } else { if(gos_GetElapsedTime() - m_maxHeatTimer > 15.0f) { m_parentMech->SelfDestruct(); } } } else { atMaxHeat = false; } skipShutdownHeatCheck: ; } else { ChainIteratorOf iterator(&heatObjects); HeatObject *heat_object; while((heat_object = iterator.GetCurrent()) !=NULL) { iterator.Remove(); delete heat_object; } } SetCoolantPercentage(); SetHeatPercentage(); if (m_parentMech->GetReplicatorMode() == Replicator::ClientMasterMode || m_parentMech->GetReplicatorMode() == Replicator::MasterMode) { Scalar percent = GetHeatPercentage (); if(m_parentMech->vehicleInterface) { MWGUIManager *gui = MWGUIManager::GetInstance (); Verify (gui); gui->HeatLevel (percent); } // Changing range from 0.7 to 0.8 to prevent constant "heat" betty // MSL 5.00 if (percent < 0.8f) { if((m_parentMech->vehicleInterface) && (!shutdown)) m_parentMech->vehicleInterface->ReactToEvent (VehicleInterface::NO_HEAT); } if (percent >= 0.8f) { if((m_parentMech->vehicleInterface) && (!shutdown)) m_parentMech->vehicleInterface->ReactToEvent (VehicleInterface::HIGH_HEAT); } // MSL 5.00 // if ((percent >= 0.7f) && (percent < 0.8f)) // { // if((m_parentMech->vehicleInterface) && (!shutdown)) // m_parentMech->vehicleInterface->ReactToEvent (VehicleInterface::LOW_HEAT); // } // else if ((percent >= 0.8f) && (percent < 0.9f)) // { // if((m_parentMech->vehicleInterface) && (!shutdown)) // m_parentMech->vehicleInterface->ReactToEvent (VehicleInterface::MED_HEAT); // } if(GetHeatPercentage() > 0.90f) { return_value = true; // MSL 5.00 // if((m_parentMech->vehicleInterface) && (!shutdown)) // m_parentMech->vehicleInterface->ReactToEvent (VehicleInterface::HIGH_HEAT); if(!m_shuttingDown) { if(m_overHeatCheckTime <= gos_GetElapsedTime()) { m_overHeatCheckTime = gos_GetElapsedTime() + 0.5f; // Scalar random_roll = Stuff::Random::GetFraction(); // if((GetHeatPercentage() - 0.2f >= random_roll) && (!shutdown)) { m_shutDownTimer = gos_GetElapsedTime() + m_shutDownTime; m_shuttingDown = true; } } } else { if(gos_GetElapsedTime() >= m_shutDownTimer) { m_shuttingDown = false; if ((m_parentMech->GetAI() != 0) && (!m_parentMech->IsPlayerVehicle())) { m_parentMech->GetAI()->NotifyHeatShutdownImminent(); if (m_parentMech->ShutDownRequest(true)) { over90 = false; if((m_parentMech->vehicleInterface) && (!shutdown)) m_parentMech->vehicleInterface->ReactToEvent (VehicleInterface::SHUTDOWN); shutdown = true; } } else { if (m_parentMech->ShutDownRequest(true)) { over90 = false; if((m_parentMech->vehicleInterface) && (!shutdown)) m_parentMech->vehicleInterface->ReactToEvent (VehicleInterface::SHUTDOWN); shutdown = true; } } } } } else { // Added Recover from Shutdown only if Heat below 66% // MSL 5.00 if(GetHeatPercentage() < 0.66f) { if(overHeatEffect.GetCurrent()) overHeatEffect.GetCurrent()->executionState->RequestState(Effect::ExecutionStateEngine::StoppingState); if(m_shuttingDown) m_shuttingDown = false; if(shutdown) { if(!m_startingUp) { // Reduced startup timer to elapsed time // Original Code - m_startUpTimer = gos_GetElapsedTime() + 5.0f; // MSL 5.00 m_startUpTimer = gos_GetElapsedTime(); m_startingUp = true; } if(m_startUpTimer <= gos_GetElapsedTime()) { m_shuttingDown = false; shutdown = false; m_startingUp = false; if(m_parentMech->vehicleShutDown) { m_parentMech->ShutDownRequest(false); if(m_parentMech->vehicleShutDown) { m_startingUp = true; shutdown = true; } else { if(m_parentMech->vehicleInterface) m_parentMech->vehicleInterface->ReactToEvent (VehicleInterface::POWER_UP); } } } } } } } return return_value; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Scalar HeatManager::GetSpeedMultiplier() { Check_Object(this); Scalar value = 1.0f; Scalar heat_percentage = GetHeatPercentage(); if(heat_percentage > m_heatEffectsSpeed) { value = 1.0f - (heat_percentage - m_heatEffectsSpeed); } Clamp(value, 0.5f, 1.0f); return value; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Scalar HeatManager::GetTorsoTwistMultiplier() { Check_Object(this); Scalar value = 1.0f; Scalar heat_percentage = GetHeatPercentage(); if(heat_percentage > m_heatEffectsSpeed) { value = 1.0f - (heat_percentage - m_heatEffectsSpeed); } Clamp(value, 0.5f, 1.0f); return value; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void HeatManager::SetCoolantPercentage() { Check_Object(this); if(maxCoolant > 0.0f) coolantPercentage = (int)((coolantValue / maxCoolant) * 100); else coolantPercentage = 0; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void HeatManager::SetHeatPercentage() { Check_Object(this); if(maxHeat > 0.0f) heatPercentage = (int)((heatValue / maxHeat) * 100); else heatPercentage = 0; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void HeatManager::SetCoolantPercentage(Scalar percentage) { Check_Object(this); Scalar old_coolant = coolantValue; coolantValue = maxCoolant * percentage; if (old_coolant != heatValue) isCoolantDirty = 1; if(maxCoolant > 0.0f) coolantPercentage = (int)((coolantValue / maxCoolant) * 100); else coolantPercentage = 0; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void HeatManager::SetHeatPercentage(Scalar percentage) { Check_Object(this); Scalar old_heat = heatValue; heatValue = maxHeat * percentage; if (old_heat != heatValue) isHeatDirty = 1; if(maxHeat > 0.0f) heatPercentage = (int)((heatValue / maxHeat) * 100); else heatPercentage = 0; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool HeatManager::OverrideShutDown() { Check_Object(this); if(m_shuttingDown) { if((m_parentMech->vehicleInterface) && (!shutdown)) m_parentMech->vehicleInterface->ReactToEvent (VehicleInterface::AUTO_SHUTDOWN_OVERRIDE); m_shutDownTimer += 3.0f; return true; } return false; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MechWarrior4::HeatSecurityCheckStop() { _asm { nop } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void HeatManager::TestInstance() { Verify(IsDerivedFrom(DefaultData)); }