//===========================================================================// // File: EntityUpdateManager.cpp //---------------------------------------------------------------------------// // Date Who Modification // // -------- --- ---------------------------------------------------------- // // 07/26/1999 JSE Inital coding //---------------------------------------------------------------------------// // Copyright (C) 1998, Microsoft Corp. // // All Rights reserved worldwide // // This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // //===========================================================================// #include "MW4Headers.hpp" #include "MWEntityManager.hpp" #include "MWApplication.hpp" #include "ObservationVehicle.hpp" #include "Mech.hpp" #include "Torso.hpp" #include "VehicleInterface.hpp" #include "MWPlayer.hpp" #include "Weapon.hpp" #include "MissileWeapon.hpp" // MSL 5.03 RTX //#include "rtxweaponsub.hpp" #include "GameInfo.hpp" #include "SubsystemClassData.hpp" #include "NetAutoPacketSpliter.hpp" #include "MissionReview.hpp" #include "Flag.hpp" #include #include #include #include #include #include #include "MechLabHeaders.h" #include "mwmission.hpp" #include #pragma warning(push) #include #pragma warning(pop) // ngLog addition // JKK #if !defined(NO_LOG) #include "nglog_mw4.hpp" #endif // !defined(NO_LOG) #include "BeamWeapon.hpp" #include // jcem - start #include "windows.h" #include "ctcls.h" #include "ctcl.h" #include "recscore.h" // jcem - mission replay #define DIRECTINPUT_VERSION 0x700 #include #include #include #include #include #include #pragma warning( disable: 4201 ) // nameless struct/union (again - something reenables this!) #include #include #include #include #include #ifndef __IDDrawExclModeVideo_FWD_DEFINED__ #error DirectX Media 6.0 SDK is required #endif #include "gameos\Net_header.hpp" #include "gameos\mreplay.h" #include "mreplay2.h" extern bool g_bCOOP; // jcem - mission replay // jcem - end BYTE *MWEntityManager::Packet_Buffer = NULL; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // //############################################################################# //########################### MWEntityManager ############################# //############################################################################# MWEntityManager::ClassData* MWEntityManager::DefaultData = NULL; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // __int64 tServerRewind; __int64 tServerEncode; __int64 tClientDecode; __int64 tClientEncode; extern DWORD g_clientControlPackets; extern DWORD g_clientPacketsWaitingConfirmation; extern DWORD g_clientSkippedPackets; extern DWORD g_clientForgotenPackets; extern DWORD g_clientTimedOutPackets; extern DWORD g_clientLatePackets; extern DWORD g_clientFullConfirms; extern DWORD g_clientSmallConfirms; extern DWORD g_serverControlsApplied; extern DWORD g_serverFullRetransmits; extern DWORD g_serverSmallRetransmits; extern DWORD g_serverPacketsOutOfRange; extern DWORD g_serverFullConfirms; extern DWORD g_serverSmallConfirms; extern DWORD g_serverTimeOuts; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWEntityManager::InitializeClass() { g_clientControlPackets = 0; g_clientPacketsWaitingConfirmation = 0; g_clientSkippedPackets = 0; g_clientForgotenPackets = 0; g_clientTimedOutPackets = 0; g_clientLatePackets = 0; g_clientFullConfirms = 0; g_clientSmallConfirms = 0; g_serverControlsApplied = 0; g_serverFullConfirms = 0; g_serverSmallConfirms = 0; g_serverFullRetransmits = 0; g_serverSmallRetransmits = 0; g_serverPacketsOutOfRange = 0; g_serverTimeOuts = 0; #if !(defined(NO_TIMERS) && defined(NO_STATS)) StatisticFormat(""); StatisticFormat("MW4 Networking Entity Manager"); StatisticFormat("============="); #endif #if !defined(NO_TIMERS) AddStatistic( "Server Rewind", "%", gos_timedata, &tServerRewind, 0); AddStatistic( "Server Encode", "%", gos_timedata, &tServerEncode, 0); AddStatistic( "Client Encode", "%", gos_timedata, &tClientEncode, 0); AddStatistic( "Client Decode", "%", gos_timedata, &tClientDecode, 0); #endif #if !defined(NO_STATS) AddStatistic( "C: ControlPacket","m", gos_DWORD, &g_clientControlPackets, 0); AddStatistic( "C: Qued", "m", gos_DWORD, &g_clientPacketsWaitingConfirmation, 0); AddStatistic( "C: Skipped", "m", gos_DWORD, &g_clientSkippedPackets, 0); AddStatistic( "C: Forgotten", "m", gos_DWORD, &g_clientForgotenPackets, 0); AddStatistic( "C: TimedOut", "m", gos_DWORD, &g_clientTimedOutPackets, 0); AddStatistic( "C: Late", "m", gos_DWORD, &g_clientLatePackets, 0); AddStatistic( "C: FConfirm", "m", gos_DWORD, &g_clientFullConfirms, 0); AddStatistic( "C: SConfirm", "m", gos_DWORD, &g_clientSmallConfirms, 0); AddStatistic( "S: ControlsApplied","m", gos_DWORD, &g_serverControlsApplied, 0); AddStatistic( "S: OutOfRange", "m", gos_DWORD, &g_serverPacketsOutOfRange, 0); AddStatistic( "S: FConfirm", "m", gos_DWORD, &g_serverFullConfirms, 0); AddStatistic( "S: SConfirm", "m", gos_DWORD, &g_serverSmallConfirms, 0); AddStatistic( "S: FRetransmits", "m", gos_DWORD, &g_serverFullRetransmits, 0); AddStatistic( "S: SRetransmits", "m", gos_DWORD, &g_serverSmallRetransmits, 0); AddStatistic( "S: TimeOuts", "m", gos_DWORD, &g_serverTimeOuts, 0); #endif Verify(!DefaultData); DefaultData = new ClassData( MWEntityManagerClassID, "MechWarrior4::MWEntityManager", Adept::EntityManager::DefaultData ); Check_Object(DefaultData); WeaponUpdate::InitializeClass(); Packet_Buffer = new BYTE[DefaultPacketBufferSize]; Network::HashMessageTypeFlags[FirstPersonControlMessageID] = Network::GameSpecificHash; //Network::HashMessageTypeFlags[FirstPersonObserverControlMessageID] = Network::GameSpecificHash; Network::HashMessageTypeFlags[FirstPersonSmallConfirmationMessageID] = Network::GameSpecificHash; Network::HashMessageTypeFlags[FirstPersonFullConfirmationMessageID] = Network::GameSpecificHash; Network::HashMessageTypeFlags[FirstPersonWeaponToMechCommandMessageID] = Network::GameSpecificHash; Network::HashMessageTypeFlags[FirstPersonWeaponToGroundCommandMessageID] = Network::GameSpecificHash; Network::HashMessageTypeFlags[FirstPersonWeaponToServerObjectCommandMessageID] = Network::GameSpecificHash; Network::HashMessageTypeFlags[FirstPersonWeaponNoTargetCommandMessageID] = Network::GameSpecificHash; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWEntityManager::TerminateClass() { Check_Object(DefaultData); delete DefaultData; DefaultData = NULL; delete[] Packet_Buffer; WeaponUpdate::TerminateClass(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool MWEntityManager::IsNumberAhead(int value, int position, int number_ahead, int wrap_around_number) { Verify(number_ahead < wrap_around_number); int result = value - position; if (result >= 0 && result <= number_ahead) return true; result = value + wrap_around_number - position; if (result >= 0 && result <= number_ahead) return true; return false; }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool MWEntityManager::IsNumberBehind(int value, int position, int number_behind, int wrap_around_number) { Verify(number_behind < wrap_around_number); int result = position - value; if (result > 0 && result <= number_behind) return true; result = position + wrap_around_number - value; if (result > 0 && result <= number_behind) return true; return false; }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool MWEntityManager::IsNumberWithin(int value, int positoin, int number_within, int wrap_around_number) { if (IsNumberAhead(value, positoin, number_within, wrap_around_number)||IsNumberBehind(value, positoin, number_within, wrap_around_number)) { return true; } return false; }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWEntityManager::SetPlayerReady(Entity *entity) { EntityManager::SetPlayerReady(entity); Check_Object(entity); Vehicle *vehicle = Cast_Object(Vehicle *, entity); vehicle->TurnOn(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWEntityManager::StartUpdates() { tServerRewind = 0; tServerEncode = 0; tClientDecode = 0; tClientEncode = 0; //SPEW(("jerryeds","SIM EXECUTE")); // clear out any frame by frame stuff here. } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWEntityManager::EndUpdates() { if (m_uPostDeathFlags) { if (m_uPostDeathFlags & 1) { VehicleInterface* pVI = VehicleInterface::GetInstance(); if (pVI) { pVI->ReactToEvent(VehicleInterface::CRITICAL_HIT_GIMP); } } m_uPostDeathFlags = 0; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWEntityManager::StartClient() { Verify(clientController == NULL); clientController = new ClientController; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWEntityManager::StopClient() { if (clientController != NULL) { delete clientController; clientController = NULL; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWEntityManager::StartServer() { Verify(serverController == NULL); serverController = new ServerController; if (g_nMR == 2) { StartClient(); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWEntityManager::StopServer() { if (g_nMR == 2) { StopClient(); } if (serverController != NULL) { delete serverController; serverController = NULL; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWEntityManager::Reset() { maximumNearBuildings = 124; maximumMidBuildings = 256; maximumFarBuildings = 256; if (clientController != NULL) { clientController->Reset(); } if (serverController != NULL) { serverController->Reset(); } lastExecuted = 0.0f; for (int i = 0; i < Maximum_Players; ++i) { playerVehicle[i] = NULL; if (dictionaryManager[i] != NULL) { delete dictionaryManager[i]; dictionaryManager[i] = NULL; } } Stuff::ChainIteratorOf iterator(&weaponUpdates); WeaponUpdate *update; while ((update = iterator.GetCurrent()) != NULL) { iterator.Remove(); delete update; } Stuff::ChainIteratorOf iterator1(&networkWeaponsQue); while ((update = iterator1.GetCurrent()) != NULL) { iterator1.Remove(); delete update; } ChainIteratorOf command_iterator(&quedCommands); VehicleCommand *command; while ((command = command_iterator.GetCurrent()) != NULL) { command_iterator.Remove(); delete command; } commandCount = 0; m_uPostDeathFlags = 0; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWEntityManager::PreCollisionNetworkEvents() { Stuff::ChainIteratorOf iterator1(&networkWeaponsQue); WeaponUpdate *update; while ((update = iterator1.GetCurrent()) != NULL) { CreateWeaponEffect(*update); iterator1.Remove(); delete update; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // MWEntityManager::MWEntityManager(): EntityManager(DefaultData), servedMechs(NULL, false), servedRespawnLances(NULL), // jcem - for delayed lancemate respawn servedAirplanes(NULL), servedBoats(NULL), servedDropships(NULL), servedHelicopters(NULL), servedHovercraft(NULL), servedTanks(NULL), servedTrucks(NULL), servedTurrets(NULL), weaponUpdates(NULL), networkWeaponsQue(NULL), quedCommands(NULL) { Check_Pointer(this); dictionaryDirtyFlag = false; lastExecuted = 0.0f; lastScore = 0.0; lastWeapon = 0.0; lastActiveReset = 0.0f; maximumNearBuildings = 124; maximumMidBuildings = 256; maximumFarBuildings = 256; for (int i = 0; i < Maximum_Players; ++i) { playerVehicle[i] = NULL; dictionaryManager[i] = NULL; } serverController = NULL; clientController = NULL; commandCount = 0; m_uPostDeathFlags = 0; //open the bitdepth file bitManager = new BitDepthManager; bitManager->InitilizeBitDepths(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // MWEntityManager::~MWEntityManager() { Check_Pointer(this); bitManager->TerminateBitDepths(); delete bitManager; Verify(serverController == NULL); Verify(clientController == NULL); for (int i = 0; i < Maximum_Players; ++i) { if (dictionaryManager[i] != NULL) { delete dictionaryManager[i]; dictionaryManager[i] = NULL; } } Stuff::ChainIteratorOf iterator(&weaponUpdates); WeaponUpdate *update; while ((update = iterator.GetCurrent()) != NULL) { iterator.Remove(); delete update; } Stuff::ChainIteratorOf iterator1(&networkWeaponsQue); while ((update = iterator1.GetCurrent()) != NULL) { iterator1.Remove(); delete update; } ChainIteratorOf command_iterator(&quedCommands); VehicleCommand *command; while ((command = command_iterator.GetCurrent()) != NULL) { command_iterator.Remove(); delete command; } commandCount = 0; m_uPostDeathFlags = 0; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void MWEntityManager::ServeLocalEntities(Time till) { Scalar time_slice = GetTimeSlice(till); if (!Application::GetInstance()->networkingFlag) { lastExecuted = till; return; } if (Mission::GetInstance() && ((till - lastScore) > 5.0)) { lastScore = till; Mission::GetInstance()->scoreDirty = true; } MWApplication *app = MWApplication::GetInstance(); if (!app->serverFlag) { // client control updates __int64 temp=GetCycles(); { #ifdef GROUP_ADEPT_NETWORK LOG_BLOCK("Game Logic::Network::Send Weapon Packets To Server"); #endif clientController->SendWeaponCommands(); } { #ifdef GROUP_ADEPT_NETWORK LOG_BLOCK("Game Logic::Network::Send Control Packets To Server"); #endif clientController->SendControlPacketToServer(time_slice); } tClientEncode+=GetCycles() - temp; lastExecuted = till; return; } else { //we are server #ifdef GROUP_ADEPT_NETWORK LOG_BLOCK("Game Logic::Network::Encode Dictionary"); #endif if ((till - lastWeapon) > 0.25) { lastWeapon = till; while(serverController->SendWeaponCommands()) { } } if ((dictionaryDirtyFlag == true) || ((g_nMR == 1) && !dictionaryManager[1])) { // make and send a new dictionary UpdateDictionaries(); app->SendScore(); Mission::GetInstance()->scoreDirty = false; } else if (Mission::GetInstance()->scoreDirty) { app->SendScore(); Mission::GetInstance()->scoreDirty = false; } // run through the updates... // right now we just count em down... if ((g_nMR == 1) && dictionaryManager[1]) { Dictionary *dictionary = dictionaryManager[1]->GetCurrentDictionary(); if (dictionary) { int nWritten = 0; DynamicMemoryStream movement_packet(MWEntityManager::Packet_Buffer, DefaultPacketBufferSize); movement_packet.WriteBits(&dictionary->versionNumber,8); Stuff::SortedChainIteratorOf iterator(&servedMechs); Mech* mech; while ((mech = iterator.ReadAndNext()) != NULL) { Check_Object(mech); ReplicatorID id = mech->GetReplicatorID(); movement_packet.WriteBits(&id.connectionID, 8); movement_packet.WriteBits(&id.localID, 16); MechPositionUpdate::Encode(mech, &movement_packet, id.connectionID, dictionary->debugDictionaryLevel, dictionary->dictionaryBandwidth); ExternalJumpJetUpdate::Encode(mech, &movement_packet, id.connectionID, dictionary->debugDictionaryLevel, dictionary->dictionaryBandwidth); MechInternalDamageUpdate::Encode(mech, &movement_packet, id.connectionID, dictionary->debugDictionaryLevel, dictionary->dictionaryBandwidth); movement_packet.WriteByteAlign(); nWritten++; } if (nWritten > 0) { movement_packet.Rewind(); } g_MRF.SendMessage(nWritten, &movement_packet, MRP_FULLCONFIRM); } } __int64 temp=GetCycles(); if (g_nMR != 2) { for (int i = 0; i < Maximum_Players; ++i) { if (app->servedConnectionData[i].clientLoaded && dictionaryManager[i]) { if (i == Connection::Server->GetID()) { if ((g_nMR != 1) || (g_MRF.m_nCount < 0)) continue; } Check_Object(dictionaryManager[i]); dictionaryManager[i]->Encode(till); } } } if (((till - lastActiveReset) > 2.0)) { lastActiveReset = till; ResetActivityFlags(); } tServerEncode+=GetCycles()-temp; } lastExecuted = till; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void MWEntityManager::ResetActivityFlags() { Stuff::SortedChainIteratorOf iterator(&servedMechs); Mech *mech; Scalar current_time = (Scalar)gos_GetElapsedTime(); while ((mech = iterator.ReadAndNext()) != NULL) { if (mech->takenDamageThisFrame) { if (current_time - mech->lastDamageTaken > 2.0f) { mech->takenDamageThisFrame = false; mech->lastDamageTaken = 0.0f; } } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void MWEntityManager::UpdateEntities() { // NO MORE CLIENT UPDATES return; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int Exit_Count = 0; void MWEntityManager::UpdateClientEntites(int connection, int message_type, Stuff::MemoryStream *message) { MWApplication *app = MWApplication::GetInstance(); switch (app->GetApplicationState()) { case ApplicationStateEngine::RunningGameState: break; default: return; }; // decode and update the entites... if (message_type == DictionaryIndexMessageID) { #if defined(_DEBUG) && 0 // jcem - for MR test { char Buffer[128]; sprintf(Buffer, "EntityMgr:: DictionaryIndexMessageID\n"); OutputDebugString(Buffer); } #endif // _DEBUG && ... //SPEW(("jerryeds", "%d : RECIEVE INDEX", Connection::Local->GetID())); Network::GetInstance()->netStatCollector[Network::IncomingSystemMessageBitSizeStat].AddToStatistic(connection,message->GetBufferBytesUsed()*8); Verify(!Network::GetInstance()->AmIServer()); // make the index __int64 temp=GetCycles(); // we might as well use our own id! if (dictionaryManager[Connection::Local->GetID()] == NULL) { dictionaryManager[Connection::Local->GetID()] = new DictionaryManager(Connection::Local->GetID()); } int version = 0; int debug_level = 0; int bandwidth = 0; message->ReadBits(&version, 8); message->ReadBits(&debug_level, 2); message->ReadBits(&bandwidth, 2); int player_count = 0; // jcem: critical error - should clear before ReadBits(...)... message->ReadBits(&player_count, 8); int vehicle_id[Maximum_Players]; for (int j = 0; j < Maximum_Players; ++j) { vehicle_id[j] = -1; } for(j = 0; j < player_count; ++j) { BYTE player; int id; message->ReadBits(&player,8); message->ReadBits(&id, 32); vehicle_id[player] = id; } bool error = false; for ( j = 0; j < Maximum_Players; ++j) { if (vehicle_id[j] == -1) { if (app->servedConnectionData[j].clientConnected && app->servedConnectionData[j].clientPlayer) { //STOP(("GAME STATE DOESNT MATCH ---- %d : LOADED BUT SHOULDNT BE", j)); // FAIL #ifdef LAB_ONLY PAUSE(("GAME STATE DOESNT MATCH ---- %d : LOADED BUT SHOULDNT BE", j)); #endif error = true; } } else { if (app->servedConnectionData[j].clientConnected && app->servedConnectionData[j].clientPlayer) { ResourceID id = app->servedConnectionData[j].clientPlayer->vehicle->GetGameModelResourceID(); if (id.GetRecordID() != vehicle_id[j]) { //STOP(("GAME STATE DOESNT MATCH ---- %d : Not in correct vehicle", j)); #ifdef LAB_ONLY PAUSE(("GAME STATE DOESNT MATCH ---- %d : Not in correct vehicle", j)); #endif error = true; } } else { //STOP(("GAME STATE DOESNT MATCH ---- %d : Not loaded", j)); #ifdef LAB_ONLY PAUSE(("GAME STATE DOESNT MATCH ---- %d : Not in correct vehicle", j)); #endif error = true; } } } if (error) { ++Exit_Count; } else { Exit_Count = 0; } if (Exit_Count) { if(Exit_Count < 10) MWApplication::GetInstance()->SendRequestNewDictionaryMessage(); else MWApplication::GetInstance()->QueStopGame(); return; } Dictionary *dictionary = dictionaryManager[Connection::Local->GetID()]->MakeNewDictionary(version, debug_level, bandwidth); MakeDictionaryPages(dictionary); #if defined(LAB_ONLY) MWGameInfo::g_networkDebugLevel[Connection::Local->GetID()] = dictionary->debugDictionaryLevel; MWGameInfo::g_connectRate[Connection::Local->GetID()] = dictionary->dictionaryBandwidth; #endif tClientDecode+=GetCycles()-temp; return; } // we will take dictionaries but nothing else unless we are running... // we will be loaded by the time that message arrives... if ( app->GetApplicationState() != ApplicationStateEngine::RunningGameState ) { return; } if(message_type == FirstPersonControlMessageID && playerVehicle[connection] != NULL) { Verify(Network::GetInstance()->AmIServer()); #if defined(_DEBUG) && 0 // jcem - for MR test { char Buffer[128]; sprintf(Buffer, "EntityMgr:: FirstPersonControlMessageID\n"); OutputDebugString(Buffer); } #endif // _DEBUG && ... serverController->ReceivePlayerControl(connection,message); } else if (message_type == FirstPersonObserverControlMessageID) { Verify(Network::GetInstance()->AmIServer()); #if defined(_DEBUG) && 0 // jcem - for MR test { char Buffer[128]; sprintf(Buffer, "EntityMgr:: FirstPersonObserverControlMessageID\n"); OutputDebugString(Buffer); } #endif // _DEBUG && ... serverController->ReceivePlayerObserverControl(connection,message); } else if (message_type == FirstPersonControlMessageID && playerVehicle[connection] == NULL) { SPEW(("jerryeds", "received control message from %d but do not have mech in list!!!!", connection)); } else if (message_type == FirstPersonFullConfirmationMessageID) { Verify(!Network::GetInstance()->AmIServer()); #if defined(_DEBUG) && 0 // jcem - for MR test { char Buffer[128]; sprintf(Buffer, "EntityMgr:: FirstPersonFullConfirmationMessageID\n"); OutputDebugString(Buffer); } #endif // _DEBUG && ... clientController->ReceiveFullConfirmation(message); } else if (message_type == FirstPersonSmallConfirmationMessageID) { Network::GetInstance()->netStatCollector[Network::MovementConfirmationBitSizeStat].AddToStatistic(connection,message->GetBufferBytesUsed()*8); Verify(!Network::GetInstance()->AmIServer()); #if defined(_DEBUG) && 0 // jcem - for MR test { char Buffer[128]; sprintf(Buffer, "EntityMgr:: FirstPersonSmallConfirmationMessageID\n"); OutputDebugString(Buffer); } #endif // _DEBUG && ... clientController->ReceiveSmallConfirmation(message); } else if (message_type >= MWEntityManager::StartThirdPersonWeaponMessageID && message_type <= MWEntityManager::EndThirdPersonWeaponMessageID) { Network::GetInstance()->netStatCollector[Network::IncomingWeaponMessageBitSizeStat].AddToStatistic(connection,message->GetBufferBytesUsed()*8); clientController->ReceiveWeaponCommand(connection, message_type, message); } else if (message_type >= MWEntityManager::StartFirstPersonWeaponMessageID && message_type <= MWEntityManager::EndFirstPersonWeaponMessageID) { Network::GetInstance()->netStatCollector[Network::IncomingWeaponMessageBitSizeStat].AddToStatistic(connection,message->GetBufferBytesUsed()*8); serverController->ReceiveWeaponCommand(connection, message_type, message); } else if (message_type >= MWEntityManager::StartAIWeaponMessageID && message_type <= MWEntityManager::EndAIWeaponMessageID) { Network::GetInstance()->netStatCollector[Network::IncomingWeaponMessageBitSizeStat].AddToStatistic(connection,message->GetBufferBytesUsed()*8); clientController->ReceiveWeaponCommand(connection, message_type, message); } else if (message_type == MWEntityManager::WeaponBundleMessageID) { Network::GetInstance()->netStatCollector[Network::IncomingWeaponMessageBitSizeStat].AddToStatistic(connection,message->GetBufferBytesUsed()*8); #if defined(_DEBUG) && 0 // jcem - for MR test { char Buffer[128]; sprintf(Buffer, "EntityMgr:: MWEntityManager::WeaponBundleMessageID\n"); OutputDebugString(Buffer); } #endif // _DEBUG && ... clientController->ReceiveWeaponBundle(connection, message_type, message); } else if (message_type >= MWEntityManager::DictionaryPage0MessageID && message_type <= MWEntityManager::DictionaryPageMaxMessageID) { if (dictionaryManager[Connection::Local->GetID()] == NULL) return; #if defined(_DEBUG) && 0 // jcem - for MR test { char Buffer[128]; sprintf(Buffer, "EntityMgr:: MWEntityManager::DictionaryPage###\n"); OutputDebugString(Buffer); } #endif // _DEBUG && ... if (g_nMR != 2) NetVerify(!Network::GetInstance()->AmIServer()); NetVerify(message != NULL); NetVerify(message->GetBytesRemaining() > 0); dictionaryManager[Connection::Local->GetID()]->Decode(message_type, message); } else { STOP(("MWEntityManager::UNHANDLED PACKET!!!!!")); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void MWEntityManager::CreateWeaponEffect(WeaponUpdate &weapon_packet) { if (weapon_packet.obsolete) return; if (weapon_packet.originator.GetCurrent() == NULL) return; //make the collision query... Stuff::Point3D local_point; Stuff::Point3D origin_point; LinearMatrix4D our_matrix; MWObject *vehicle = Cast_Object(MWObject *, weapon_packet.originator.GetCurrent()); // the packet originiated locally. if (g_nMR != 2) { if (vehicle->GetReplicatorID().connectionID == Connection::Local->GetID()) { return; } } LinearMatrix4D eye_mat; origin_point = vehicle->GetLocalToWorld(); eye_mat = vehicle->GetLocalToWorld(); if(vehicle->eyeSitePointer.GetCurrent()) { origin_point = vehicle->eyeSitePointer.GetCurrent()->GetLocalToWorld(); eye_mat = vehicle->eyeSitePointer.GetCurrent()->GetLocalToWorld(); } else { Stuff::ChainIteratorOf iterator(&vehicle->weaponChain); Weapon *weapon; if ((weapon = iterator.ReadAndNext()) != NULL) { if (weapon->sitePointer) { origin_point = weapon->sitePointer->GetLocalToWorld(); eye_mat = weapon->sitePointer->GetLocalToWorld(); } } } Vector3D line_direction; Point3D target_point = Point3D::Identity; if (weapon_packet.target.GetCurrent() != NULL) { if (weapon_packet.target.GetCurrent() != Map::GetInstance()) { // SPEWALWAYS(("jackyc", "CreateWeaponEffect - packet target is not a map")); //target_point = weapon_packet.target->GetLocalToWorld(); //target_point += weapon_packet.targetOffset; target_point.Multiply(weapon_packet.targetOffset, weapon_packet.target.GetCurrent()->GetLocalToWorld()); } else { // SPEWALWAYS(("jackyc", "CreateWeaponEffect - packet target is a map")); target_point = weapon_packet.targetOffset; } line_direction.Subtract(target_point, origin_point); } else { // SPEWALWAYS(("jackyc", "CreateWeaponEffect - packet target is NULL")); //UnitVector3D temp_vector; //eye_mat.GetLocalForwardInWorld(&temp_vector); //line_direction = temp_vector; Point3D target_point; target_point = weapon_packet.targetOffset; line_direction.Subtract(target_point, origin_point); } Stuff::Normal3D normal(0.0f, 1.0f, 0.0f); Stuff::Line3D target_line; target_line.SetOrigin(origin_point); target_line.SetDirection(line_direction); target_line.m_length = 1500.0f; // SPEWALWAYS(("jackyc", "CreateWeaponEffect - target_line origin, %f, %f, %f", origin_point.x, origin_point.y, origin_point.z)); // SPEWALWAYS(("jackyc", "CreateWeaponEffect - target_line direction, %f, %f, %f", line_direction.x, line_direction.y, line_direction.z)); // SPEWALWAYS(("jackyc", "CreateWeaponEffect - target_line length, %f", 1500)); Adept::Entity::CollisionQuery query(&target_line, &normal, Adept::Entity::CanBeShotFlag, weapon_packet.originator.GetCurrent()); Adept::Entity *entity_hit = NULL; Check_Object(CollisionGrid::Instance); entity_hit = CollisionGrid::Instance->ProjectLine(&query); // SPEWALWAYS(("jackyc", "CreateWeaponEffect - query line origin, %f, %f, %f", query.m_line->m_origin.x, query.m_line->m_origin.y, query.m_line->m_origin.z)); // SPEWALWAYS(("jackyc", "CreateWeaponEffect - query line direction, %f, %f, %f", query.m_line->m_direction.x, query.m_line->m_direction.y, query.m_line->m_direction.z)); // SPEWALWAYS(("jackyc", "CreateWeaponEffect - query line length, %f", query.m_line->m_length)); // SPEWALWAYS(("jackyc", "CreateWeaponEffect - query normal, %f, %f, %f", query.m_normal->x, query.m_normal->y, query.m_normal->z)); // { // Stuff::Point3D target_point; // query.m_line->FindEnd(&target_point); // // SPEWALWAYS(("jackyc", "CreateWeaponEffect - target_point, %f, %f, %f", // target_point.x, // target_point.y, // target_point.z)); // } #ifdef _ARMOR // if (entity_hit != NULL && weapon_packet.target != NULL && weapon_packet.target->instanceName && entity_hit->instanceName ) // SPEW(("jerryeds", "AIMED AT %s, HIT : %s", (char*)weapon_packet.target->instanceName, (char*)entity_hit->instanceName)); // else if (weapon_packet.target != NULL && weapon_packet.target->instanceName) // SPEW(("jerryeds", "AIMED AT %s, MISSEd", (char*)weapon_packet.target->instanceName)); // else // SPEW(("jerryeds", "NO NAMES")); // // SPEW(("jerryeds", "TARGETPOINT : <%f:%f:%f> ", target_point.x, target_point.y, target_point.z)); #endif if (weapon_packet.target.GetCurrent() && weapon_packet.target.GetCurrent()->IsDerivedFrom(Vehicle::DefaultData)) { /* SPEWALWAYS(("jackyc", "CreateWeaponEffect - weapon_packet.target.GetCurrent()")); if (weapon_packet.target.GetCurrent() == NULL) { SPEWALWAYS(("jackyc", "CreateWeaponEffect - First Person Weapon To No Target")); } else if (weapon_packet.target.GetCurrent() == Map::GetInstance()) { SPEWALWAYS(("jackyc", "CreateWeaponEffect - First Person Weapon To Ground or No Target")); } else if (weapon_packet.target.GetCurrent()->GetReplicatorID().connectionID == Connection::Hermit->GetID()) { SPEWALWAYS(("jackyc", "CreateWeaponEffect - First Person Weapon To Ground")); } else if (weapon_packet.target.GetCurrent()->GetReplicatorID().connectionID != Connection::Server->GetID()) { SPEWALWAYS(("jackyc", "CreateWeaponEffect - First Person Weapon To Mech")); SPEWALWAYS(("jackyc", "CreateWeaponEffect - First Person Weapon To Mech")); SPEWALWAYS(("jackyc", "CreateWeaponEffect - Mech connection ID, %d, %d", weapon_packet.target.GetCurrent()->GetReplicatorID().connectionID, weapon_packet.target.GetCurrent()->GetReplicatorID().localID)); Entity* parent_target = weapon_packet.target.GetCurrent(); int class_id = parent_target->GetClassID(); if (class_id == MWMoverClassID) { SPEWALWAYS(("jackyc", "CreateWeaponEffect - Mover Name - NOT AVAILABLE")); } else { SPEWALWAYS(("jackyc", "CreateWeaponEffect - Not a MWMover")); } } else if (weapon_packet.target.GetCurrent()->GetReplicatorID().connectionID == Connection::Server->GetID()) { SPEWALWAYS(("jackyc", "CreateWeaponEffect - First Person Weapon To Server")); } */ query.m_raySource = weapon_packet.target.GetCurrent(); } else { /* SPEWALWAYS(("jackyc", "CreateWeaponEffect - entity_hit")); if (entity_hit == NULL) { SPEWALWAYS(("jackyc", "CreateWeaponEffect - First Person Weapon To No Target")); } else if (entity_hit == Map::GetInstance()) { SPEWALWAYS(("jackyc", "CreateWeaponEffect - First Person Weapon To Ground or No Target")); } else if (entity_hit->GetReplicatorID().connectionID == Connection::Hermit->GetID()) { SPEWALWAYS(("jackyc", "CreateWeaponEffect - First Person Weapon To Ground")); } else if (entity_hit->GetReplicatorID().connectionID != Connection::Server->GetID()) { SPEWALWAYS(("jackyc", "CreateWeaponEffect - First Person Weapon To Mech")); SPEWALWAYS(("jackyc", "CreateWeaponEffect - First Person Weapon To Mech")); SPEWALWAYS(("jackyc", "CreateWeaponEffect - Mech connection ID, %d, %d", entity_hit->GetReplicatorID().connectionID, entity_hit->GetReplicatorID().localID)); Entity* parent_target = entity_hit; int class_id = parent_target->GetClassID(); if (class_id == MWMoverClassID) { // MWMover* mover = Cast_Object(MWMover*, parent_target); // if (entity_hit->instanceName) // { // SPEWALWAYS(("jackyc", "CreateWeaponEffect - Mover Name - %s", (char*)entity_hit->instanceName)); // } // else { SPEWALWAYS(("jackyc", "CreateWeaponEffect - Mover Name - NOT AVAILABLE")); } } else { SPEWALWAYS(("jackyc", "CreateWeaponEffect - Not a MWMover")); } } else if (entity_hit->GetReplicatorID().connectionID == Connection::Server->GetID()) { SPEWALWAYS(("jackyc", "CreateWeaponEffect - First Person Weapon To Server")); } */ query.m_raySource = entity_hit; } // missile lock vector is straight ahead... //UnitVector3D temp_vector; //eye_mat.GetLocalForwardInWorld(&temp_vector); //line_direction = temp_vector; #if 0 Stuff::Normal3D lock_normal(0.0f, 1.0f, 0.0f); Stuff::Line3D locktarget_line; locktarget_line.SetOrigin(origin_point); locktarget_line.SetDirection(line_direction); locktarget_line.m_length = 1000.0f; Adept::Entity::CollisionQuery lock_query(&locktarget_line, &lock_normal, Adept::Entity::CanBeShotFlag, weapon_packet.originator.GetCurrent()); lock_query.m_raySource = weapon_packet.target.GetCurrent(); #endif Stuff::ChainIteratorOf iterator(&vehicle->weaponChain); Weapon *weapon; while ((weapon = iterator.ReadAndNext()) != NULL) { int id = weapon->GetWeaponID(); if (weapon_packet.weaponFired & (0x1 << id)) { if (weapon->IsDerivedFrom(MissileWeapon::DefaultData)) { MissileWeapon *missile_weapon; missile_weapon = Cast_Object(MissileWeapon *, weapon); query.m_raySource = weapon_packet.target.GetCurrent(); if (missile_weapon->IsAMSValid(weapon_packet.target.GetCurrent())) { missile_weapon->SetAMSNumber(weapon_packet.AntiWeaponCount[id]); } weapon->FireWeapon(&query, weapon_packet.lockTime, Stuff::Point3D::Identity); } else { weapon->FireWeapon(&query, weapon_packet.lockTime, Stuff::Point3D::Identity); } } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void MWEntityManager::UpdateDictionaries(void) { if (g_nMR != 2) { MWApplication *app = MWApplication::GetInstance(); for (int i = 0; i < Maximum_Players; ++i) { // if they are connected and have a vehicle // than make them one. if (app->servedConnectionData[i].clientConnected && app->servedConnectionData[i].clientLoaded) { //SPEW(("jerryeds", "%d : SEND INDEX : %d", Connection::Local->GetID(), i)); if (i == Connection::Server->GetID()) { if ((g_nMR != 1) || (g_MRF.m_nCount < 0)) continue; int nForceConnectionSpeedOld = MWApplication::ForceConnectionSpeed; MWApplication::ForceConnectionSpeed = BitDepthManager::HighBandwidth; // BitDepthManager::LowBandwidth, BitDepthManager::MediumBandwidth UpdateDictionaries(i); MWApplication::ForceConnectionSpeed = nForceConnectionSpeedOld; } else { UpdateDictionaries(i); } } else { if (dictionaryManager[i] != NULL) { Unregister_Object(dictionaryManager[i]); delete dictionaryManager[i]; dictionaryManager[i] = NULL; } } } } dictionaryDirtyFlag = false; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void MWEntityManager::UpdateDictionaries(int i) { if (g_nMR != 2) { MWApplication *app = MWApplication::GetInstance(); if (dictionaryManager[i] == NULL) { dictionaryManager[i] = new DictionaryManager(i); Register_Object(dictionaryManager[i]); } int connection_rate = BitDepthManager::LowBandwidth; if (MWApplication::ForceConnectionSpeed != -1) { connection_rate = MWApplication::ForceConnectionSpeed; } else if (app->servedConnectionData[i].bandwidthThrottle) { connection_rate = BitDepthManager::LowBandwidth; } else if (MWApplication::MyConnectionSpeed >= MWApplication::c_1500_kbps) { if (app->servedConnectionData[i].clientConnectionRate >= MWApplication::c_1500_kbps) { connection_rate = BitDepthManager::HighBandwidth; } else if (app->servedConnectionData[i].clientConnectionRate >= MWApplication::c_128_kbps) { connection_rate = BitDepthManager::MediumBandwidth; } else { connection_rate = BitDepthManager::LowBandwidth; } } else if (MWApplication::MyConnectionSpeed >= MWApplication::c_768_kbps) { if (app->servedConnectionData[i].clientConnectionRate > MWApplication::c_64_kbps) { connection_rate = BitDepthManager::MediumBandwidth; } else { connection_rate = BitDepthManager::LowBandwidth; } } else { connection_rate = BitDepthManager::LowBandwidth; } #if defined(LAB_ONLY) MWGameInfo::g_networkDebugLevel[i] = MWApplication::NetworkDebugLevel; MWGameInfo::g_connectRate[i] = connection_rate; #endif Dictionary *dictionary = dictionaryManager[i]->MakeNewDictionary(dictionaryManager[i]->GetNextDictionaryID(), MWApplication::NetworkDebugLevel, connection_rate); MakeDictionaryPages(dictionary); DynamicMemoryStream stream; //dictionaryManager[i]->EncodeDictionary(&stream); stream.WriteBits(&dictionary->versionNumber, 8); stream.WriteBits(&dictionary->debugDictionaryLevel, 2); stream.WriteBits(&dictionary->dictionaryBandwidth, 2); BYTE player_count = 0; for (int j = 0; j < Maximum_Players; ++j) { if (app->servedConnectionData[j].clientConnected && app->servedConnectionData[j].clientPlayer) { ++player_count; } } stream.WriteBits(&player_count, 8); for ( j = 0; j < Maximum_Players; ++j) { if (app->servedConnectionData[j].clientConnected && app->servedConnectionData[j].clientPlayer) { ResourceID id = app->servedConnectionData[j].clientPlayer->vehicle->GetGameModelResourceID(); int sub_id = id.GetRecordID(); stream.WriteBits(&j,8); stream.WriteBits(&sub_id, 32); } } stream.WriteByteAlign(); stream.Rewind(); // This is dangerous as it creates NEW pages that will // be updated. ICK. That doubles the bandwidth on // a armor build!!!! //#if defined(_ARMOR) //dictionaryManager[i]->DecodeDictionary(&stream); //stream.Rewind(); //#endif // send the dictionary Check_Object(Application::GetInstance()); // break up the message... Network::GetInstance()->netStatCollector[Network::OutgoingSystemMessageBitSizeStat].AddToStatistic(i,stream.GetBufferBytesUsed()*8); Network::GetInstance()->SendNetMessage(i, DictionaryIndexMessageID, &stream, true); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void MWEntityManager::MakeDictionaryPages(Dictionary *dictionary) { Stuff::SortedChainIteratorOf iterator(&servedMechs); int connection_rate = dictionary->dictionaryBandwidth; NetUpdateSorter sorter(dictionary->debugDictionaryLevel, dictionary->dictionaryBandwidth); Entity *entity; if (g_nMR && (dictionary->connectionID == 1)) { while ((entity = iterator.ReadAndNext()) != NULL) { Check_Object(entity); //-sorter.AddUpdateToList(entity, UpdateManager::MechPositionUpdateID, bitManager->GetUpdateRate(UpdateManager::MechPositionUpdateID, connection_rate)); //sorter.AddUpdateToList(entity, UpdateManager::MechAnimationUpdateID, bitManager->GetUpdateRate(UpdateManager::MechAnimationUpdateID, connection_rate)); //sorter.AddUpdateToList(entity, UpdateManager::MechMovemntUpdateID, bitManager->GetUpdateRate(UpdateManager::MechMovemntUpdateID, connection_rate)); //sorter.AddUpdateToList(entity, UpdateManager::MechExternalDamageUpdateID, bitManager->GetUpdateRate(UpdateManager::MechExternalDamageUpdateID, connection_rate)); //jcem-dead or alive-sorter.AddUpdateToList(entity, UpdateManager::MechInternalDamageUpdateID, bitManager->GetUpdateRate(UpdateManager::MechExternalDamageUpdateID, connection_rate)); //--sorter.AddUpdateToList(entity, UpdateManager::MechInternalDamageUpdateID, bitManager->GetUpdateRate(UpdateManager::MechInternalDamageUpdateID, connection_rate)); sorter.AddUpdateToList(entity, UpdateManager::MechInternalHeatUpdateID, bitManager->GetUpdateRate(UpdateManager::MechInternalHeatUpdateID, connection_rate)); // sorter.AddUpdateToList(entity, UpdateManager::SubsystemUpdateID, bitManager->GetUpdateRate(UpdateManager::SubsystemUpdateID, connection_rate)); sorter.AddUpdateToList(entity, UpdateManager::FlushUpdateID, bitManager->GetUpdateRate(UpdateManager::FlushUpdateID, connection_rate)); sorter.AddUpdateToList(entity, UpdateManager::SearchLightUpdateID, bitManager->GetUpdateRate(UpdateManager::SearchLightUpdateID, connection_rate)); sorter.AddUpdateToList(entity, UpdateManager::ExternalAMSAmmoUpdateID, bitManager->GetUpdateRate(UpdateManager::ExternalAMSAmmoUpdateID, connection_rate)); //-sorter.AddUpdateToList(entity, UpdateManager::ExternalJumpJetUpdateID, bitManager->GetUpdateRate(UpdateManager::ExternalJumpJetUpdateID, connection_rate)); //--sorter.AddUpdateToList(entity, UpdateManager::InternalAMSAmmoUpdateID, bitManager->GetUpdateRate(UpdateManager::InternalAMSAmmoUpdateID, connection_rate)); //--sorter.AddUpdateToList(entity, UpdateManager::InternalJumpJetUpdateID, bitManager->GetUpdateRate(UpdateManager::InternalJumpJetUpdateID, connection_rate)); sorter.AddUpdateToList(entity, UpdateManager::NearBuildingExternalDamageUpdateID, bitManager->GetUpdateRate(UpdateManager::NearBuildingExternalDamageUpdateID, connection_rate)); sorter.AddUpdateToList(entity, UpdateManager::SecondaryBuildingExternalDamageUpdateID, bitManager->GetUpdateRate(UpdateManager::SecondaryBuildingExternalDamageUpdateID, connection_rate)); sorter.AddUpdateToList(entity, UpdateManager::FarBuildingExternalDamageUpdateID, bitManager->GetUpdateRate(UpdateManager::FarBuildingExternalDamageUpdateID, connection_rate)); if (entity->IsPlayerVehicle()) { //sorter.AddUpdateToList(entity, UpdateManager::PingUpdateID, bitManager->GetUpdateRate(UpdateManager::PingUpdateID, connection_rate)); } } entity = MWApplication::GetInstance()->servedConnectionData[dictionary->connectionID].clientPlayer->vehicle; //-sorter.AddUpdateToList(entity, UpdateManager::SecurityResponseID, bitManager->GetUpdateRate(UpdateManager::SecurityResponseID, connection_rate)); //-sorter.AddUpdateToList(entity, UpdateManager::SecurityQueryID, bitManager->GetUpdateRate(UpdateManager::SecurityQueryID, connection_rate)); //-sorter.AddUpdateToList(entity, UpdateManager::SecurityQueryID, bitManager->GetUpdateRate(UpdateManager::SecurityQueryID, connection_rate)); //-sorter.AddUpdateToList(entity, UpdateManager::TimeUpdateID, bitManager->GetUpdateRate(UpdateManager::TimeUpdateID, connection_rate)); // moved to above : 3 lines //-sorter.AddUpdateToList(entity, UpdateManager::NearBuildingExternalDamageUpdateID, bitManager->GetUpdateRate(UpdateManager::NearBuildingExternalDamageUpdateID, connection_rate)); //-sorter.AddUpdateToList(entity, UpdateManager::SecondaryBuildingExternalDamageUpdateID, bitManager->GetUpdateRate(UpdateManager::SecondaryBuildingExternalDamageUpdateID, connection_rate)); //-sorter.AddUpdateToList(entity, UpdateManager::FarBuildingExternalDamageUpdateID, bitManager->GetUpdateRate(UpdateManager::FarBuildingExternalDamageUpdateID, connection_rate)); //-sorter.AddUpdateToList(entity, UpdateManager::MissionObjectiveUpdateID, bitManager->GetUpdateRate(UpdateManager::MissionObjectiveUpdateID, connection_rate)); sorter.AddUpdateToList(entity, UpdateManager::VehicleDamageUpdateID, bitManager->GetUpdateRate(UpdateManager::VehicleDamageUpdateID, connection_rate)); sorter.AddUpdateToList(entity, UpdateManager::NavPointUpdateID, bitManager->GetUpdateRate(UpdateManager::NavPointUpdateID, connection_rate)); sorter.AddUpdateToList(entity, UpdateManager::FlagUpdateID, bitManager->GetUpdateRate(UpdateManager::FlagUpdateID, connection_rate)); } else { gosASSERT(g_nMR != 2); while ((entity = iterator.ReadAndNext()) != NULL) { Check_Object(entity); if (entity->GetReplicatorID().connectionID != dictionary->connectionID) { sorter.AddUpdateToList(entity, UpdateManager::MechPositionUpdateID, bitManager->GetUpdateRate(UpdateManager::MechPositionUpdateID, connection_rate)); //sorter.AddUpdateToList(entity, UpdateManager::MechAnimationUpdateID, bitManager->GetUpdateRate(UpdateManager::MechAnimationUpdateID, connection_rate)); //sorter.AddUpdateToList(entity, UpdateManager::MechMovemntUpdateID, bitManager->GetUpdateRate(UpdateManager::MechMovemntUpdateID, connection_rate)); //sorter.AddUpdateToList(entity, UpdateManager::MechExternalDamageUpdateID, bitManager->GetUpdateRate(UpdateManager::MechExternalDamageUpdateID, connection_rate)); sorter.AddUpdateToList(entity, UpdateManager::MechInternalDamageUpdateID, bitManager->GetUpdateRate(UpdateManager::MechExternalDamageUpdateID, connection_rate)); sorter.AddUpdateToList(entity, UpdateManager::SubsystemUpdateID, bitManager->GetUpdateRate(UpdateManager::SubsystemUpdateID, connection_rate)); sorter.AddUpdateToList(entity, UpdateManager::FlushUpdateID, bitManager->GetUpdateRate(UpdateManager::FlushUpdateID, connection_rate)); sorter.AddUpdateToList(entity, UpdateManager::SearchLightUpdateID, bitManager->GetUpdateRate(UpdateManager::SearchLightUpdateID, connection_rate)); sorter.AddUpdateToList(entity, UpdateManager::ExternalAMSAmmoUpdateID, bitManager->GetUpdateRate(UpdateManager::ExternalAMSAmmoUpdateID, connection_rate)); sorter.AddUpdateToList(entity, UpdateManager::ExternalJumpJetUpdateID, bitManager->GetUpdateRate(UpdateManager::ExternalJumpJetUpdateID, connection_rate)); if (entity->IsPlayerVehicle()) { sorter.AddUpdateToList(entity, UpdateManager::PingUpdateID, bitManager->GetUpdateRate(UpdateManager::PingUpdateID, connection_rate)); } } else { if (entity->IsPlayerVehicle()) { sorter.AddUpdateToList(entity, UpdateManager::MechInternalDamageUpdateID, bitManager->GetUpdateRate(UpdateManager::MechInternalDamageUpdateID, connection_rate)); sorter.AddUpdateToList(entity, UpdateManager::MechInternalHeatUpdateID, bitManager->GetUpdateRate(UpdateManager::MechInternalHeatUpdateID, connection_rate)); sorter.AddUpdateToList(entity, UpdateManager::SubsystemUpdateID, bitManager->GetUpdateRate(UpdateManager::SubsystemUpdateID, connection_rate)); //sorter.AddUpdateToList(entity, UpdateManager::FlushUpdateID, bitManager->GetUpdateRate(UpdateManager::FlushUpdateID, connection_rate)); sorter.AddUpdateToList(entity, UpdateManager::SearchLightUpdateID, bitManager->GetUpdateRate(UpdateManager::SearchLightUpdateID, connection_rate)); sorter.AddUpdateToList(entity, UpdateManager::InternalAMSAmmoUpdateID, bitManager->GetUpdateRate(UpdateManager::InternalAMSAmmoUpdateID, connection_rate)); sorter.AddUpdateToList(entity, UpdateManager::InternalJumpJetUpdateID, bitManager->GetUpdateRate(UpdateManager::InternalJumpJetUpdateID, connection_rate)); } } } entity = MWApplication::GetInstance()->servedConnectionData[dictionary->connectionID].clientPlayer->vehicle; sorter.AddUpdateToList(entity, UpdateManager::SecurityResponseID, bitManager->GetUpdateRate(UpdateManager::SecurityResponseID, connection_rate)); sorter.AddUpdateToList(entity, UpdateManager::SecurityQueryID, bitManager->GetUpdateRate(UpdateManager::SecurityQueryID, connection_rate)); // sorter.AddUpdateToList(entity, UpdateManager::SecurityQueryID, bitManager->GetUpdateRate(UpdateManager::SecurityQueryID, connection_rate)); sorter.AddUpdateToList(entity, UpdateManager::TimeUpdateID, bitManager->GetUpdateRate(UpdateManager::TimeUpdateID, connection_rate)); sorter.AddUpdateToList(entity, UpdateManager::NearBuildingExternalDamageUpdateID, bitManager->GetUpdateRate(UpdateManager::NearBuildingExternalDamageUpdateID, connection_rate)); sorter.AddUpdateToList(entity, UpdateManager::SecondaryBuildingExternalDamageUpdateID, bitManager->GetUpdateRate(UpdateManager::SecondaryBuildingExternalDamageUpdateID, connection_rate)); sorter.AddUpdateToList(entity, UpdateManager::FarBuildingExternalDamageUpdateID, bitManager->GetUpdateRate(UpdateManager::FarBuildingExternalDamageUpdateID, connection_rate)); sorter.AddUpdateToList(entity, UpdateManager::MissionObjectiveUpdateID, bitManager->GetUpdateRate(UpdateManager::MissionObjectiveUpdateID, connection_rate)); sorter.AddUpdateToList(entity, UpdateManager::VehicleDamageUpdateID, bitManager->GetUpdateRate(UpdateManager::VehicleDamageUpdateID, connection_rate)); sorter.AddUpdateToList(entity, UpdateManager::NavPointUpdateID, bitManager->GetUpdateRate(UpdateManager::NavPointUpdateID, connection_rate)); sorter.AddUpdateToList(entity, UpdateManager::FlagUpdateID, bitManager->GetUpdateRate(UpdateManager::FlagUpdateID, connection_rate)); } Stuff::ChainIteratorOf iterator1(&servedAirplanes); while ((entity = iterator1.ReadAndNext()) != NULL) { sorter.AddUpdateToList(entity, UpdateManager::AirMovementUpdateID, bitManager->GetUpdateRate(UpdateManager::AirMovementUpdateID, connection_rate)); MWObject *object = Cast_Object(MWObject*, entity); if (object->GetTorso()) { sorter.AddUpdateToList(object->GetTorso(), UpdateManager::TorsoMovementUpdateID, bitManager->GetUpdateRate(UpdateManager::TorsoMovementUpdateID, connection_rate)); } } Stuff::ChainIteratorOf iterator2(&servedBoats); while ((entity = iterator2.ReadAndNext()) != NULL) { sorter.AddUpdateToList(entity, UpdateManager::GroundMovementUpdateID, bitManager->GetUpdateRate(UpdateManager::GroundMovementUpdateID, connection_rate)); MWObject *object = Cast_Object(MWObject*, entity); if (object->GetTorso()) { sorter.AddUpdateToList(object->GetTorso(), UpdateManager::TorsoMovementUpdateID, bitManager->GetUpdateRate(UpdateManager::TorsoMovementUpdateID, connection_rate)); } } Stuff::ChainIteratorOf iterator3(&servedDropships); while ((entity = iterator3.ReadAndNext()) != NULL) { sorter.AddUpdateToList(entity, UpdateManager::AirMovementUpdateID, bitManager->GetUpdateRate(UpdateManager::AirMovementUpdateID, connection_rate)); MWObject *object = Cast_Object(MWObject*, entity); if (object->GetTorso()) { sorter.AddUpdateToList(object->GetTorso(), UpdateManager::TorsoMovementUpdateID, bitManager->GetUpdateRate(UpdateManager::TorsoMovementUpdateID, connection_rate)); } } Stuff::ChainIteratorOf iterator4(&servedHelicopters); while ((entity = iterator4.ReadAndNext()) != NULL) { sorter.AddUpdateToList(entity, UpdateManager::AirMovementUpdateID, bitManager->GetUpdateRate(UpdateManager::AirMovementUpdateID, connection_rate)); MWObject *object = Cast_Object(MWObject*, entity); if (object->GetTorso()) { sorter.AddUpdateToList(object->GetTorso(), UpdateManager::TorsoMovementUpdateID, bitManager->GetUpdateRate(UpdateManager::TorsoMovementUpdateID, connection_rate)); } } Stuff::ChainIteratorOf iterator5(&servedHovercraft); while ((entity = iterator5.ReadAndNext()) != NULL) { sorter.AddUpdateToList(entity, UpdateManager::GroundMovementUpdateID, bitManager->GetUpdateRate(UpdateManager::GroundMovementUpdateID, connection_rate)); MWObject *object = Cast_Object(MWObject*, entity); if (object->GetTorso()) { sorter.AddUpdateToList(object->GetTorso(), UpdateManager::TorsoMovementUpdateID, bitManager->GetUpdateRate(UpdateManager::TorsoMovementUpdateID, connection_rate)); } } Stuff::ChainIteratorOf iterator7(&servedTanks); while ((entity = iterator7.ReadAndNext()) != NULL) { sorter.AddUpdateToList(entity, UpdateManager::GroundMovementUpdateID, bitManager->GetUpdateRate(UpdateManager::GroundMovementUpdateID, connection_rate)); MWObject *object = Cast_Object(MWObject*, entity); if (object->GetTorso()) { sorter.AddUpdateToList(object->GetTorso(), UpdateManager::TorsoMovementUpdateID, bitManager->GetUpdateRate(UpdateManager::TorsoMovementUpdateID, connection_rate)); } } Stuff::ChainIteratorOf iterator8(&servedTrucks); while ((entity = iterator8.ReadAndNext()) != NULL) { sorter.AddUpdateToList(entity, UpdateManager::GroundMovementUpdateID, bitManager->GetUpdateRate(UpdateManager::GroundMovementUpdateID, connection_rate)); MWObject *object = Cast_Object(MWObject*, entity); if (object->GetTorso()) { sorter.AddUpdateToList(object->GetTorso(), UpdateManager::TorsoMovementUpdateID, bitManager->GetUpdateRate(UpdateManager::TorsoMovementUpdateID, connection_rate)); } } Stuff::ChainIteratorOf iterator9(&servedTurrets); while ((entity = iterator9.ReadAndNext()) != NULL) { sorter.AddUpdateToList(entity, UpdateManager::TurretMovementUpdateID, bitManager->GetUpdateRate(UpdateManager::TurretMovementUpdateID, connection_rate)); MWObject *object = Cast_Object(MWObject*, entity); if (object->GetTorso()) { sorter.AddUpdateToList(object->GetTorso(), UpdateManager::TorsoMovementUpdateID, bitManager->GetUpdateRate(UpdateManager::TorsoMovementUpdateID, connection_rate)); } } sorter.MakeDictionaryPages(dictionary); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void MWEntityManager::QueCommand(int command) { #if defined(LAB_ONLY) if (commandCount >= 4) { SPEWALWAYS(("jerryeds", "TOO MANY COMMANDS")); } #endif if (Application::GetInstance()->networkingFlag && !Application::GetInstance()->serverFlag) { commandCount++; VehicleCommand *new_command = new VehicleCommand(); new_command->m_Command = command; quedCommands.Add(new_command); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void MWEntityManager::RespawnClient(int connection_id, Point3D trans) { if (serverController != NULL) { serverController->RespawnClient(connection_id, trans); } if (clientController != NULL) { clientController->RespawnClient(connection_id); } // ngLog addition // JKK #if !defined(NO_LOG) MW4log_generic(MW4P_RESPAWN, va("Player_Respawn\t%d", connection_id)); #endif // !defined(NO_LOG) } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void MWEntityManager::AddPlayerVehicle(Mover *mover) { if (mover->GetClassData() == Mech::DefaultData) { Verify(mover->GetClassData() == Mech::DefaultData); Verify(mover->IsPlayerVehicle()); int mech_id = mover->GetReplicatorID().connectionID; Verify(playerVehicle[mech_id] == NULL); playerVehicle[mech_id] = Cast_Object(Vehicle*, mover); // add score member for the player mech Mission::GetInstance()->AddScoreMember (mover->GetReplicatorID(), mover->instanceName); // reset security response if (Application::GetInstance()->serverFlag && serverController != NULL) { serverController->ResetClient(mech_id); } #if defined(LAB_ONLY) int connection = mover->GetReplicatorID().connectionID; MWGameInfo::g_playerJoinTime[connection] = gos_GetElapsedTime(); ++MWGameInfo::g_totalNetworkJoins; ++MWGameInfo::g_currentlyJoined; ++MWGameInfo::g_playerJoins[connection]; MWGameInfo::g_lastJoinID = connection; const char *name; name = mover->GetModelName (); std::string s(name); std::string::size_type last_period = s.find_last_of('.'); if (last_period != std::string::npos) { s.erase(last_period,s.size() - 1 - last_period); } std::string::size_type last_slash = s.find_last_of('\\'); if (last_slash != std::string::npos) { s.erase(0,last_slash + 1); } strncpy (MWGameInfo::g_playerVehicleNames[connection],s.c_str(),s.size() - 1); MWGameInfo::g_playerVehicleNames[connection][s.size()] = 0; if (mover->IsDerivedFrom(Vehicle::DefaultData) == true) { Vehicle* v = Cast_Object(Vehicle*,mover); MWGameInfo::g_playerTeams[connection] = v->GetTeam(); } #endif #if !defined(NO_MR) int conn = mover->GetReplicatorID().connectionID; MWApplication *app = MWApplication::GetInstance(); if(app->m_recordLog) { app->m_recordLog->AddPlayer(Network::GetInstance()->GetConnection(conn)->GetConnectionName(), conn); } #endif // !defined(NO_MR) } //else we are in brb or something } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void MWEntityManager::RemovePlayerVehicle(Mover *mover) { #if defined(LAB_ONLY) int connection = mover->GetReplicatorID().connectionID; MWGameInfo::g_playerLeaveTime[connection] = gos_GetElapsedTime(); ++MWGameInfo::g_totalNetworkLeaves; --MWGameInfo::g_currentlyJoined; ++MWGameInfo::g_playerLeaves[connection]; MWGameInfo::g_lastLeaveID = mover->GetReplicatorID().connectionID; #endif if (MWApplication::GetInstance()->serverFlag) { if (mover->GetClassData() == Mech::DefaultData) { Mech* mech = Cast_Pointer(Mech*, mover); g_RSF.RemoveScoreObject(mech); // jcem } } #if !defined(NO_MR) if (MWApplication::GetInstance()->m_recordLog) { int connection = mover->GetReplicatorID().connectionID; MWApplication::GetInstance()->m_recordLog->RemovePlayer(connection); } #endif // !defined(NO_MR) int mech_id = mover->GetReplicatorID().connectionID; playerVehicle[mech_id] = NULL; if (MWApplication::GetInstance()->servedConnectionData[mech_id].clientPlayer != NULL) { MWApplication::GetInstance()->servedConnectionData[mech_id].clientPlayer->vehicle = NULL; } if(Mission::GetInstance()) { Check_Object(this); Mission::GetInstance()->RemoveScoreMember (mover->GetReplicatorID()); } if (mover != 0) { Flag::RemoveAllFlagsFrom(*mover); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void MWEntityManager::AddMover(Mover *mover) { SetDirtyFlag(); if(mover->GetClassData() == Mech::DefaultData) { Mech *mech = Cast_Object(Mech*, mover); servedMechs.AddValue(mech, mech->GetReplicatorID()); /* if (mover->GetReplicatorMode() == Replicator::MasterMode) { servedMechs.AddValue(mech, mech->GetReplicatorID()); } else if (mover->GetReplicatorMode() == Replicator::ServerMasterMode) { // turn this mech off // mech->executionState->RequestState(Mech::ExecutionStateEngine::NeverExecuteState); servedMechs.AddValue(mech, mech->GetReplicatorID()); } */ } else { switch(mover->GetClassID()) { case AirplaneClassID: { Airplane *obj = Cast_Object(Airplane*, mover); servedAirplanes.Add(obj); } break; case BoatClassID: { Boat *obj = Cast_Object(Boat*, mover); servedBoats.Add(obj); } break; case DropshipClassID: { Dropship *obj = Cast_Object(Dropship*, mover); servedDropships.Add(obj); } break; case HelicopterClassID: { Helicopter *obj = Cast_Object(Helicopter*, mover); servedHelicopters.Add(obj); } break; case HovercraftClassID: { Hovercraft *obj = Cast_Object(Hovercraft*, mover); servedHovercraft.Add(obj); } break; case TankClassID: { Tank *obj = Cast_Object(Tank*, mover); servedTanks.Add(obj); } break; case TruckClassID: { Truck *obj = Cast_Object(Truck*, mover); servedTrucks.Add(obj); } break; case TurretClassID: { Turret *obj = Cast_Object(Turret*, mover); servedTurrets.Add(obj); } break; } } EntityManager::AddMover(mover); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void MWEntityManager::RemoveMover(Mover *mover) { SetDirtyFlag(); if(mover->GetClassData() == Mech::DefaultData) { //Mech *mech = Cast_Object(Mech*, mover); Mech *mech = Cast_Pointer(Mech*, mover); if (mech->IsPlayerVehicle()) { RemovePlayerVehicle(mover); } servedMechs.Remove(mech); /* if (mover->GetReplicatorMode() == Replicator::MasterMode) { servedMechs.Remove(mech); } else if (mover->GetReplicatorMode() == Replicator::ServerMasterMode) { // remove all the server side control buffers for this player if (Application::GetInstance()->serverFlag) { int mech_id = mech->GetReplicatorID().connectionID; if (serverController != NULL) { serverController->RemovePlayer(mech_id); } } servedMechs.Remove(mech); } */ } else { switch(mover->GetClassID()) { case AirplaneClassID: { Airplane *obj = Cast_Pointer(Airplane*, mover); Check_Object(obj); servedAirplanes.Remove(obj); } break; case BoatClassID: { Boat *obj = Cast_Pointer(Boat*, mover); Check_Object(obj); servedBoats.Remove(obj); } break; case DropshipClassID: { Dropship *obj = Cast_Pointer(Dropship*, mover); Check_Object(obj); servedDropships.Remove(obj); } break; case HelicopterClassID: { Helicopter *obj = Cast_Pointer(Helicopter*, mover); Check_Object(obj); servedHelicopters.Remove(obj); } break; case HovercraftClassID: { Hovercraft *obj = Cast_Pointer(Hovercraft*, mover); Check_Object(obj); servedHovercraft.Remove(obj); } break; case TankClassID: { Tank *obj = Cast_Pointer(Tank*, mover); Check_Object(obj); servedTanks.Remove(obj); } break; case TruckClassID: { Truck *obj = Cast_Pointer(Truck*, mover); Check_Object(obj); servedTrucks.Remove(obj); } break; case TurretClassID: { Turret *obj = Cast_Pointer(Turret*, mover); Check_Object(obj); servedTurrets.Remove(obj); } break; } } EntityManager::RemoveMover(mover); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Scalar MWEntityManager::FindGroundHeight(Stuff::Scalar x_position, Stuff::Scalar z_position) { // one would think I can just get the Point3D test_point; test_point.x = x_position; test_point.y = 500.0f; test_point.z = z_position; Stuff::Vector3D world_avg_normal(Stuff::Vector3D::Identity); Stuff::Normal3D normal; Stuff::Line3D line; Adept::Entity::CollisionQuery query(&line, &normal, Adept::Entity::CanBeWalkedOnFlag, NULL); // // Cast ray // Adept::Entity *entity_hit; Check_Object(CollisionGrid::Instance); line.m_length = 1000.0f; line.m_direction = Vector3D::Down; line.m_origin = test_point; entity_hit = CollisionGrid::Instance->ProjectLine(&query); if(entity_hit != NULL) { // if we hit ground, great! Point3D end_point; line.FindEnd(&end_point); return end_point.y; } return 0.0f; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWEntityManager::AIWeaponUpdate(WeaponUpdate *weapon) { if (Application::GetInstance()->networkingFlag) { Check_Object(weapon); Check_Object(weapon->originator.GetCurrent()); #if defined (_ARMOR) if (weapon->target.GetCurrent() != NULL) { Check_Object(weapon->target.GetCurrent()); } #endif weaponUpdates.Add(weapon); } else delete weapon; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWEntityManager::PlayerWeaponUpdate(WeaponUpdate *weapon) { if (Application::GetInstance()->networkingFlag && weapon->weaponFired) { Check_Object(weapon); Check_Object(weapon->originator.GetCurrent()); #if defined (_ARMOR) if (weapon->target.GetCurrent() != NULL) { Check_Object(weapon->target.GetCurrent()); } #endif WeaponUpdate *copy = new WeaponUpdate; if (weapon->originator.GetCurrent()) copy->originator.Add(weapon->originator.GetCurrent()); if (weapon->target.GetCurrent()) copy->target.Add(weapon->target.GetCurrent()); copy->weaponFired = weapon->weaponFired; copy->targetOffset = weapon->targetOffset; copy->lockTime = weapon->lockTime; for (int i = 0; i < 32; ++i) { copy->AntiWeaponCount[i] = weapon->AntiWeaponCount[i]; } weaponUpdates.Add(copy); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWEntityManager::QueWeapon(WeaponUpdate *weapon) { Verify (Application::GetInstance()->networkingFlag); Verify(!weapon->obsolete); networkWeaponsQue.Add(weapon); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWEntityManager::BuildTileBoundDamageList() { EntityManager::BuildTileBoundDamageList(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWEntityManager::TestInstance() const { Verify(IsDerivedFrom(DefaultData)); } void MWEntityManager::QueRespawnLancemate(Mech* lancemateMech) { Check_Object(lancemateMech); // jcem - for delayed lancemate respawn MWMission* mission = Cast_Object(MWMission*, MWMission::GetInstance()); Check_Object(mission); VehicleInterface* pVH = VehicleInterface::GetInstance(); Check_Object(pVH); lancemateMech->m_fTimeRespawnRequestEnd = mission->GetMissionTime() + pVH->GetGameModel()->deathTimer; servedRespawnLances.Add(lancemateMech); }