//===========================================================================// // File: NetDamage.cpp // Contents : All movement messages and rewind capabilites //---------------------------------------------------------------------------// // Date Who Modification // // -------- --- ---------------------------------------------------------- // // 01/06/1999 JSE Inital coding //---------------------------------------------------------------------------// // Copyright (C) 1998, Microsoft Corp. // // All Rights reserved worldwide // // This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // //===========================================================================// #include "MW4Headers.hpp" #include "NetDamage.hpp" #include "MWEntityManager.hpp" #include "MWDamageObject.hpp" #include "Mech.hpp" #include "MWApplication.hpp" #include #include #include "Adept\NetStatCollector.hpp" //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MechExternalDamageUpdate::Decode(Entity *entity, MemoryStream *memory_stream, Time till, Scalar packet_latency, int connection, int debug_level, int bandwidth, Scalar rate) { Check_Object(entity); Check_Object(memory_stream); Mech *mech = Cast_Object(Mech*, entity); int current_bit = memory_stream->GetCurrentBitCount(); DamageObject *damage_object; SortedChainIteratorOf damage_iterator(&mech->damageObjects); int current_life = 0; // jcem: critical error - should clear before ReadBits(...)... memory_stream->ReadBits(¤t_life,2); bool destroyed; memory_stream->ReadBit(destroyed); if (destroyed) { memory_stream->ReadBytes(&mech->m_whoShotMeLast.connectionID, sizeof(mech->m_whoShotMeLast.connectionID)); memory_stream->ReadBytes(&mech->m_whoShotMeLast.localID, sizeof(mech->m_whoShotMeLast.localID)); } // if the lives match... if (current_life == (mech->respawnCount % 4)) { if (destroyed && !entity->IsDestroyed()) { entity->ReactToDestruction(InternalDamageObject::DestructionDamageMode, 0); } while((damage_object = damage_iterator.ReadAndNext()) != NULL) { Check_Object(damage_object); int damage_level = 0; memory_stream->ReadBits(&damage_level,2); damage_object->SetCurrentDamageLevel(damage_level); } MWInternalDamageObject *internal_damage_object; SortedChainIteratorOf internal_iterator(&mech->internalDamageObjects); while((internal_damage_object = internal_iterator.ReadAndNext()) != NULL) { Check_Object(internal_damage_object); int damage_level = 0; memory_stream->ReadBits(&damage_level,2); internal_damage_object->SetCurrentDamageLevel(damage_level); } } else { //if (destroyed) // SPEW(("jerryeds","SKIP DESTROY")); //else // SPEW(("jerryeds", "SKIP DAMAGE")); while((damage_object = damage_iterator.ReadAndNext()) != NULL) { Check_Object(damage_object); int damage_level = 0; memory_stream->ReadBits(&damage_level,2); } MWInternalDamageObject *internal_damage_object; SortedChainIteratorOf internal_iterator(&mech->internalDamageObjects); while((internal_damage_object = internal_iterator.ReadAndNext()) != NULL) { Check_Object(internal_damage_object); int damage_level = 0; memory_stream->ReadBits(&damage_level,2); } } Network::GetInstance()->netStatCollector[Network::MechInternalBitSizeStat].AddToStatistic(connection, memory_stream->GetCurrentBitCount() - current_bit); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int MechExternalDamageUpdate::SizeFunction(Entity *entity) { Check_Object(entity); Mech *mech = Cast_Object(Mech*, entity); int size = 0; DamageObject *damage_object; SortedChainIteratorOf damage_iterator(&mech->damageObjects); while((damage_object = damage_iterator.ReadAndNext()) != NULL) { Check_Object(damage_object); ++size; } MWInternalDamageObject *internal_damage_object; SortedChainIteratorOf internal_iterator(&mech->internalDamageObjects); while((internal_damage_object = internal_iterator.ReadAndNext()) != NULL) { Check_Object(internal_damage_object); ++size; } return size; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int MechExternalDamageUpdate::MaxSize(Entity *entity, int debug_level, int bandwidth) { Mech *mech = Cast_Object(Mech*, entity); int size = 0; DamageObject *damage_object; SortedChainIteratorOf damage_iterator(&mech->damageObjects); while((damage_object = damage_iterator.ReadAndNext()) != NULL) { Check_Object(damage_object); ++size; } MWInternalDamageObject *internal_damage_object; SortedChainIteratorOf internal_iterator(&mech->internalDamageObjects); while((internal_damage_object = internal_iterator.ReadAndNext()) != NULL) { Check_Object(internal_damage_object); ++size; } return (size * 2)+3; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool MechExternalDamageUpdate::MaintainActiveFlagFunction(Entity *entity,Point3D cull_location) { Point3D entity_location; entity_location = entity->GetLocalToWorld(); Point3D distance; distance.Subtract(cull_location, entity_location); // if the mech is within 1200 meters and is on than it is active if (distance.GetLengthSquared() < 1440000.0f) { Mech *mech = Cast_Object(Mech*, entity); if (mech->takenDamageThisFrame) { return true; } } return false; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MechExternalDamageUpdate::Skip(MemoryStream *memory_stream, int size, Time till, int connection, int debug_level, int bandwidth) { Check_Object(memory_stream); int current_bit = memory_stream->GetCurrentBitCount(); int throw_away; // MSL 5.03 Merc Fix memory_stream->ReadBits(&throw_away,3); // memory_stream->ReadBits(&throw_away,2); // // int destroyed = 0; // memory_stream->ReadBits(&destroyed,1); // if (destroyed) { // memory_stream->ReadBytes(&throw_away, sizeof(BYTE/*connectionID*/)); // memory_stream->ReadBytes(&throw_away, sizeof(WORD/*localID*/)); // } for (int i = 0; i < size; ++i) { memory_stream->ReadBits(&throw_away,2); } Network::GetInstance()->netStatCollector[Network::MechInternalBitSizeStat].AddToStatistic(connection,memory_stream->GetCurrentBitCount() - current_bit); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MechExternalDamageUpdate::Encode(Entity *entity, DynamicMemoryStream *memory_stream, int connection, int debug_level, int bandwidth) { Check_Object(entity); Check_Object(memory_stream); Mech *mech = Cast_Object(Mech*, entity); int current_bit = memory_stream->GetCurrentBitCount(); int current_life = (mech->respawnCount % 4); memory_stream->WriteBits(¤t_life,2); if (entity->IsDestroyed()) { memory_stream->WriteBit(true); // MSL 5.03 Merc Fix // memory_stream->WriteBytes(&mech->m_whoShotMeLast.connectionID, sizeof(mech->m_whoShotMeLast.connectionID)); // memory_stream->WriteBytes(&mech->m_whoShotMeLast.localID, sizeof(mech->m_whoShotMeLast.localID)); } else { memory_stream->WriteBit(false); } DamageObject *damage_object; SortedChainIteratorOf damage_iterator(&mech->damageObjects); while((damage_object = damage_iterator.ReadAndNext()) != NULL) { Check_Object(damage_object); int damage_level = damage_object->GetCurrentDamageLevel(); memory_stream->WriteBits(&damage_level,2); } MWInternalDamageObject *internal_damage_object; SortedChainIteratorOf internal_iterator(&mech->internalDamageObjects); while((internal_damage_object = internal_iterator.ReadAndNext()) != NULL) { Check_Object(internal_damage_object); int damage_level = internal_damage_object->GetCurrentDamageLevel(); memory_stream->WriteBits(&damage_level,2); } Network::GetInstance()->netStatCollector[Network::MechInternalBitSizeStat].AddToStatistic(connection,memory_stream->GetCurrentBitCount() - current_bit); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MechInternalDamageUpdate::Decode(Entity *entity, MemoryStream *memory_stream, Time till, Scalar packet_latency, int connection, int debug_level, int bandwidth, Scalar rate) { Check_Object(entity); Check_Object(memory_stream); Mech *mech = Cast_Object(Mech*, entity); int current_bit = memory_stream->GetCurrentBitCount(); int current_life = 0; // jcem: critical error - should clear before ReadBits(...)... memory_stream->ReadBits(¤t_life,2); // if the lives match... if (current_life == mech->respawnCount % 4) { DamageObject *damage_object; SortedChainIteratorOf damage_iterator(&mech->damageObjects); while((damage_object = damage_iterator.ReadAndNext()) != NULL) { Check_Object(damage_object); Scalar damage_level = 0.0f; memory_stream->ReadBitsToScaledFloat(damage_level,0.0f, 1.0f,BitDepthManager::BitDepth(UpdateType,InternalDamageEntryID)); damage_object->SetHighResDamageLevel(damage_level); //SPEW(("jerryeds", "DECODE - EXT : %f", damage_level)); } MWInternalDamageObject *internal_damage_object; SortedChainIteratorOf internal_iterator(&mech->internalDamageObjects); while((internal_damage_object = internal_iterator.ReadAndNext()) != NULL) { Check_Object(internal_damage_object); Scalar damage_level = 0.0f; memory_stream->ReadBitsToScaledFloat(damage_level,0.0f, 1.0f,BitDepthManager::BitDepth(UpdateType,InternalDamageEntryID)); internal_damage_object->SetHighResDamageLevel(damage_level); //SPEW(("jerryeds", "DECODE - INT : %f", damage_level)); } } else { DamageObject *damage_object; SortedChainIteratorOf damage_iterator(&mech->damageObjects); while((damage_object = damage_iterator.ReadAndNext()) != NULL) { Check_Object(damage_object); Scalar damage_level = 0.0f; memory_stream->ReadBitsToScaledFloat(damage_level,0.0f, 1.0f,BitDepthManager::BitDepth(UpdateType,InternalDamageEntryID)); } MWInternalDamageObject *internal_damage_object; SortedChainIteratorOf internal_iterator(&mech->internalDamageObjects); while((internal_damage_object = internal_iterator.ReadAndNext()) != NULL) { Check_Object(internal_damage_object); Scalar damage_level = 0.0f; memory_stream->ReadBitsToScaledFloat(damage_level,0.0f, 1.0f,BitDepthManager::BitDepth(UpdateType,InternalDamageEntryID)); } } Network::GetInstance()->netStatCollector[Network::MechInternalBitSizeStat].AddToStatistic(connection, memory_stream->GetCurrentBitCount() - current_bit); //SPEW(("jerryeds","")); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int MechInternalDamageUpdate::SizeFunction(Entity *entity) { Check_Object(entity); Mech *mech = Cast_Object(Mech*, entity); int size = 0; DamageObject *damage_object; SortedChainIteratorOf damage_iterator(&mech->damageObjects); while((damage_object = damage_iterator.ReadAndNext()) != NULL) { Check_Object(damage_object); ++size; } MWInternalDamageObject *internal_damage_object; SortedChainIteratorOf internal_iterator(&mech->internalDamageObjects); while((internal_damage_object = internal_iterator.ReadAndNext()) != NULL) { Check_Object(internal_damage_object); ++size; } return size; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int MechInternalDamageUpdate::MaxSize(Entity *entity, int debug_level, int bandwidth) { Mech *mech = Cast_Object(Mech*, entity); int size = 0; DamageObject *damage_object; SortedChainIteratorOf damage_iterator(&mech->damageObjects); while((damage_object = damage_iterator.ReadAndNext()) != NULL) { Check_Object(damage_object); ++size; } MWInternalDamageObject *internal_damage_object; SortedChainIteratorOf internal_iterator(&mech->internalDamageObjects); while((internal_damage_object = internal_iterator.ReadAndNext()) != NULL) { Check_Object(internal_damage_object); ++size; } return (size * BitDepthManager::BitDepth(UpdateType,InternalDamageEntryID)) + 2; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool MechInternalDamageUpdate::MaintainActiveFlagFunction(Entity *entity,Point3D cull_location) { Mech *mech = Cast_Object(Mech*, entity); // MSL 5.03 Merc Fix Point3D entity_location; entity_location = entity->GetLocalToWorld(); Point3D distance; distance.Subtract(cull_location, entity_location); if (distance.GetLengthSquared() < 1440000.0f) { if (mech->takenDamageThisFrame) { return true; } } return false; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MechInternalDamageUpdate::Skip(MemoryStream *memory_stream, int size, Time till, int connection, int debug_level, int bandwidth) { Check_Object(memory_stream); int current_bit = memory_stream->GetCurrentBitCount(); int throw_away; memory_stream->ReadBits(&throw_away,2); for (int i = 0; i < size; ++i) { memory_stream->ReadBits(&throw_away,BitDepthManager::BitDepth(UpdateType,InternalDamageEntryID)); } Network::GetInstance()->netStatCollector[Network::MechInternalBitSizeStat].AddToStatistic(connection, memory_stream->GetCurrentBitCount() - current_bit); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MechInternalDamageUpdate::Encode(Entity *entity, DynamicMemoryStream *memory_stream, int connection, int debug_level, int bandwidth) { Check_Object(entity); Check_Object(memory_stream); Mech *mech = Cast_Object(Mech*, entity); int current_bit = memory_stream->GetCurrentBitCount(); int current_life = mech->respawnCount % 4; memory_stream->WriteBits(¤t_life,2); DamageObject *damage_object; SortedChainIteratorOf damage_iterator(&mech->damageObjects); while((damage_object = damage_iterator.ReadAndNext()) != NULL) { Check_Object(damage_object); Scalar damage_level = damage_object->GetHighResDamageLevel(); //SPEW(("jerryeds", "ENCODE - EXT : %f", damage_level)); DWORD scaled_damage = Scaled_Float_To_Bits(damage_level,0.0f,1.0f,BitDepthManager::BitDepth(UpdateType,InternalDamageEntryID)); if (scaled_damage == 0) { if (damage_level > 0.0f) scaled_damage+=1; } memory_stream->WriteBits(&scaled_damage,BitDepthManager::BitDepth(UpdateType,InternalDamageEntryID)); } MWInternalDamageObject *internal_damage_object; SortedChainIteratorOf internal_iterator(&mech->internalDamageObjects); while((internal_damage_object = internal_iterator.ReadAndNext()) != NULL) { Check_Object(internal_damage_object); Scalar damage_level = internal_damage_object->GetHighResDamageLevel(); //SPEW(("jerryeds", "ENCODE - INT : %f", damage_level)); DWORD scaled_damage = Scaled_Float_To_Bits(damage_level,0.0f,1.0f,BitDepthManager::BitDepth(UpdateType,InternalDamageEntryID)); if (scaled_damage == 0) { if (damage_level > 0.0f) scaled_damage+=1; } memory_stream->WriteBits(&scaled_damage,BitDepthManager::BitDepth(UpdateType,InternalDamageEntryID)); } Network::GetInstance()->netStatCollector[Network::MechInternalBitSizeStat].AddToStatistic(connection, memory_stream->GetCurrentBitCount() - current_bit); //SPEW(("jerryeds","")); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void VehicleDamageUpdate::Decode(Entity *, MemoryStream *memory_stream, Time till, Scalar packet_latency, int connection, int debug_level, int bandwidth, Scalar rate) { Check_Object(memory_stream); int current_bit = memory_stream->GetCurrentBitCount(); MWEntityManager *manager = Cast_Object(MWEntityManager*, MWEntityManager::GetInstance()); Stuff::ChainIteratorOf iterator1(&manager->servedAirplanes); Entity *entity; while ((entity = iterator1.ReadAndNext()) != NULL) { bool destroyed; memory_stream->ReadBit(destroyed); if (destroyed && !entity->IsDestroyed()) { entity->ReactToDestruction(InternalDamageObject::DestructionDamageMode, 0); } } Stuff::ChainIteratorOf iterator2(&manager->servedBoats); while ((entity = iterator2.ReadAndNext()) != NULL) { bool destroyed; memory_stream->ReadBit(destroyed); if (destroyed && !entity->IsDestroyed()) { entity->ReactToDestruction(InternalDamageObject::DestructionDamageMode, 0); } } Stuff::ChainIteratorOf iterator3(&manager->servedDropships); while ((entity = iterator3.ReadAndNext()) != NULL) { bool destroyed; memory_stream->ReadBit(destroyed); if (destroyed && !entity->IsDestroyed()) { entity->ReactToDestruction(InternalDamageObject::DestructionDamageMode, 0); } } Stuff::ChainIteratorOf iterator4(&manager->servedHelicopters); while ((entity = iterator4.ReadAndNext()) != NULL) { bool destroyed; memory_stream->ReadBit(destroyed); if (destroyed && !entity->IsDestroyed()) { entity->ReactToDestruction(InternalDamageObject::DestructionDamageMode, 0); } } Stuff::ChainIteratorOf iterator5(&manager->servedHovercraft); while ((entity = iterator5.ReadAndNext()) != NULL) { bool destroyed; memory_stream->ReadBit(destroyed); if (destroyed && !entity->IsDestroyed()) { entity->ReactToDestruction(InternalDamageObject::DestructionDamageMode, 0); } } Stuff::ChainIteratorOf iterator7(&manager->servedTanks); while ((entity = iterator7.ReadAndNext()) != NULL) { bool destroyed; memory_stream->ReadBit(destroyed); if (destroyed && !entity->IsDestroyed()) { entity->ReactToDestruction(InternalDamageObject::DestructionDamageMode, 0); } } Stuff::ChainIteratorOf iterator8(&manager->servedTrucks); while ((entity = iterator8.ReadAndNext()) != NULL) { bool destroyed; memory_stream->ReadBit(destroyed); if (destroyed && !entity->IsDestroyed()) { entity->ReactToDestruction(InternalDamageObject::DestructionDamageMode, 0); } } Stuff::ChainIteratorOf iterator9(&manager->servedTurrets); while ((entity = iterator9.ReadAndNext()) != NULL) { bool destroyed; memory_stream->ReadBit(destroyed); if (destroyed && !entity->IsDestroyed()) { entity->ReactToDestruction(InternalDamageObject::DestructionDamageMode, 0); } } Network::GetInstance()->netStatCollector[Network::VehicleBitSizeStat].AddToStatistic(connection, memory_stream->GetCurrentBitCount() - current_bit); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int VehicleDamageUpdate::SizeFunction(Entity *) { int size = 0; MWEntityManager *manager = Cast_Object(MWEntityManager*, MWEntityManager::GetInstance()); Stuff::ChainIteratorOf iterator1(&manager->servedAirplanes); Entity *entity; while ((entity = iterator1.ReadAndNext()) != NULL) { ++size; } Stuff::ChainIteratorOf iterator2(&manager->servedBoats); while ((entity = iterator2.ReadAndNext()) != NULL) { ++size; } Stuff::ChainIteratorOf iterator3(&manager->servedDropships); while ((entity = iterator3.ReadAndNext()) != NULL) { ++size; } Stuff::ChainIteratorOf iterator4(&manager->servedHelicopters); while ((entity = iterator4.ReadAndNext()) != NULL) { ++size; } Stuff::ChainIteratorOf iterator5(&manager->servedHovercraft); while ((entity = iterator5.ReadAndNext()) != NULL) { ++size; } Stuff::ChainIteratorOf iterator7(&manager->servedTanks); while ((entity = iterator7.ReadAndNext()) != NULL) { ++size; } Stuff::ChainIteratorOf iterator8(&manager->servedTrucks); while ((entity = iterator8.ReadAndNext()) != NULL) { ++size; } Stuff::ChainIteratorOf iterator9(&manager->servedTurrets); while ((entity = iterator9.ReadAndNext()) != NULL) { ++size; } return size; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int VehicleDamageUpdate::MaxSize(Entity *entity, int debug_level, int bandwidth) { return SizeFunction(entity); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void VehicleDamageUpdate::Skip(MemoryStream *memory_stream, int size, Time till, int connection, int debug_level, int bandwidth) { Check_Object(memory_stream); int current_bit = memory_stream->GetCurrentBitCount(); for (int i = 0; i < size; ++i) { int throw_away; memory_stream->ReadBits(&throw_away,1); } Network::GetInstance()->netStatCollector[Network::VehicleBitSizeStat].AddToStatistic(connection, memory_stream->GetCurrentBitCount() - current_bit); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void VehicleDamageUpdate::Encode(Entity *, DynamicMemoryStream *memory_stream, int connection, int debug_level, int bandwidth) { Check_Object(memory_stream); int current_bit = memory_stream->GetCurrentBitCount(); MWEntityManager *manager = Cast_Object(MWEntityManager*, MWEntityManager::GetInstance()); Stuff::ChainIteratorOf iterator1(&manager->servedAirplanes); Entity *entity; while ((entity = iterator1.ReadAndNext()) != NULL) { if (entity->IsDestroyed()) { memory_stream->WriteBit(true); } else { memory_stream->WriteBit(false); } } Stuff::ChainIteratorOf iterator2(&manager->servedBoats); while ((entity = iterator2.ReadAndNext()) != NULL) { if (entity->IsDestroyed()) { memory_stream->WriteBit(true); } else { memory_stream->WriteBit(false); } } Stuff::ChainIteratorOf iterator3(&manager->servedDropships); while ((entity = iterator3.ReadAndNext()) != NULL) { if (entity->IsDestroyed()) { memory_stream->WriteBit(true); } else { memory_stream->WriteBit(false); } } Stuff::ChainIteratorOf iterator4(&manager->servedHelicopters); while ((entity = iterator4.ReadAndNext()) != NULL) { if (entity->IsDestroyed()) { memory_stream->WriteBit(true); } else { memory_stream->WriteBit(false); } } Stuff::ChainIteratorOf iterator5(&manager->servedHovercraft); while ((entity = iterator5.ReadAndNext()) != NULL) { if (entity->IsDestroyed()) { memory_stream->WriteBit(true); } else { memory_stream->WriteBit(false); } } Stuff::ChainIteratorOf iterator7(&manager->servedTanks); while ((entity = iterator7.ReadAndNext()) != NULL) { if (entity->IsDestroyed()) { memory_stream->WriteBit(true); } else { memory_stream->WriteBit(false); } } Stuff::ChainIteratorOf iterator8(&manager->servedTrucks); while ((entity = iterator8.ReadAndNext()) != NULL) { if (entity->IsDestroyed()) { memory_stream->WriteBit(true); } else { memory_stream->WriteBit(false); } } Stuff::ChainIteratorOf iterator9(&manager->servedTurrets); while ((entity = iterator9.ReadAndNext()) != NULL) { if (entity->IsDestroyed()) { memory_stream->WriteBit(true); } else { memory_stream->WriteBit(false); } } Network::GetInstance()->netStatCollector[Network::VehicleBitSizeStat].AddToStatistic(connection, memory_stream->GetCurrentBitCount() - current_bit); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // //Some helpfull stuff for finding tiles in the far clip //row column int TileBlockOffsets[16][2] = { { 6,-6}, { 6,-3}, { 6, 0}, { 6, 3}, { 6, 6}, { 3, 6}, { 0, 6}, {-3, 6}, {-6, 6}, {-6, 3}, {-6, 0}, {-6,-3}, {-6,-6}, {-3,-6}, { 0,-6}, { 3,-6} }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // //this is how damage updates work... // you get a 3x3 block of tiles that is centered on you at a high frequency. This is the ImidiateAreaUpdate /* ImidiateAreaUpdate. Each box is a tile. Each group of 3x3's is a block The center X represents where you are standing in the world. Every tile is updated - - - | | | | - - - | |X| | - - - | | | | _ _ _ */ // you get 8 3x3 blocks of tiles that immidiatly surrund your imidiatearea block. // This is lower frequency and is the SecondaryAreaUpdate /* SecondaryAreaUpdate. Each box is a block of tiles (3x3). The center X represents where you are standing in the world. ( in the center square of that 3x3 of tiles ) Only the boxes with *'s in them are updated. The 3x3 block you are in is not updated. -- -- -- |* |* |* | -- -- -- |* |X |* | -- -- -- |* |* |* | -- -- -- */ /* FarAreaUpdate. Each box is a block of tiles (3x3). The center X represents where you are standing in the world ( in the center square of that 3x3 of tiles ) These are infrequent. You only receive updates for 9 boxes. The start box is 4 counter clockwise of the direction you are facing -- -- -- -- -- | 4| 3| 2| 1| 0| -- -- -- -- -- | 5| | | |15| -- -- -- -- -- | 6| |X | |14| -- -- -- -- -- | 7| | | |13| -- -- -- -- -- | 8| 9|10|11|12| -- -- -- -- -- */ /* // if the degree is between the minimum for that tile and the minum for the next tile // use that index number Scalar TileBlockRanges[16] { -56.25, -33.75 //1 -33.75, -11.25 //2 -11.25, 11.25 //3 11.25, 33.75 //4 33.75, 56.25 //5 56.25, 78.75 //6 78.75, 101.25 //7 101.25, 123.75 //8 123.75, 146.25 //9 146.25, 168.75 //10 168.75, -168.75 //11 -- special... -146.25, -168.75, //12 -123.75, -146.25, //13 -101.25, -123.75, //14 -78.75, -101.25, //15 -56.25, -78.75, //16 } */ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int CalculateStartTile(Scalar degrees) { // just a balance to make less if checks... if (degrees < -11.25) { if (degrees < -101.25) { if (degrees < -168.75) //10 -- special...this is on the radian border { return 6; } else if (degrees < -146.25) //11 { return 7; } else if (degrees < -123.75) //12 { return 8; } else //13 { Verify(degrees < -101.25); return 9; } } else { if (degrees < -78.75) //14 { return 10; } else if (degrees < -56.25) //15 { return 11; } else if (degrees < -33.75) //0 { return 12; } else //1 { Verify (degrees < -11.25); Verify (degrees >= -33.75); return 13; } } } else { if (degrees < 101.25) { if (degrees < 13.25) //2 { return 14; } else if (degrees < 33.75) //3 { return 15; } else if (degrees < 56.25) //4 { return 0; } else if (degrees < 78.75) //5 { return 1; } else //6 { Verify (degrees < 101.25); return 2; } } else { if (degrees < 123.75) //7 { return 3; } else if (degrees < 146.25) //8 { return 4; } else if (degrees < 168.75) //9 { return 5; } else //if (degrees > 168.75 || degrees < -168.75) //10 -- special...this is on the radian border { Verify (degrees > 168.75); return 6; } } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void FindRowAndColumn(WORD tile, int *row, int *column) { BYTE l_row, l_column; CollisionGrid::Instance->FindRowAndColumn(tile, &l_row, &l_column); *row = (int)l_row; *column = (int)l_column; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void GetSize(int *max_row, int *max_column) { BYTE l_max_row, l_max_column; CollisionGrid::Instance->GetSize(&l_max_row, &l_max_column); *max_row = l_max_row; *max_column = l_max_column; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void NearBuildingExternalDamageUpdate::Decode(Entity *entity, MemoryStream *memory_stream, Time till, Scalar packet_latency, int connection, int debug_level, int bandwidth, Scalar rate) { Check_Object(entity); Check_Object(memory_stream); Check_Object(CollisionGrid::Instance); int row, column; WORD tile = 0; // jcem: critical error - should clear before ReadBits(...)... memory_stream->ReadBits(&tile, 11);//1024 FindRowAndColumn(tile, &row, &column); ReadTileBlock(row,column,memory_stream, connection); Network::GetInstance()->netStatCollector[Network::BuildingDamageBitSizeStat].AddToStatistic(connection,11); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void NearBuildingExternalDamageUpdate::Skip(MemoryStream *memory_stream, int size, Time till, int connection, int debug_level, int bandwidth) { Check_Object(memory_stream); Check_Object(CollisionGrid::Instance); int row, column; WORD tile = 0; // jcem: critical error - should clear before ReadBits(...)... memory_stream->ReadBits(&tile, 11);//1024 FindRowAndColumn(tile, &row, &column); ReadTileBlock(row,column,memory_stream, connection, true); Network::GetInstance()->netStatCollector[Network::BuildingDamageBitSizeStat].AddToStatistic(connection,11); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int NearBuildingExternalDamageUpdate::MaxSize(Entity *entity, int debug_level, int bandwidth) { MWEntityManager *manager = Cast_Object(MWEntityManager*, MWEntityManager::GetInstance()); int current_bit = 0; current_bit += 11; current_bit += manager->maximumNearBuildings; return current_bit; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void NearBuildingExternalDamageUpdate::Encode(Entity *entity, DynamicMemoryStream *memory_stream, int connection, int debug_level, int bandwidth) { Check_Object(entity); Check_Object(memory_stream); // figure out our tile and send all the appropriate tiles... Point3D position = MWApplication::GetInstance()->servedConnectionData[entity->GetReplicatorID().connectionID].vehiclePosition; Check_Object(CollisionGrid::Instance); int row, column; WORD tile; tile = CollisionGrid::Instance->FindElementIndex(position.z, position.x); FindRowAndColumn(tile, &row, &column); Verify(tile < 2048); memory_stream->WriteBits(&tile, 11);//1024 WriteTileBlock(row,column,memory_stream, connection); Network::GetInstance()->netStatCollector[Network::BuildingDamageBitSizeStat].AddToStatistic(connection,11); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void NearBuildingExternalDamageUpdate::WriteTileBlock(int row, int column, DynamicMemoryStream *memory_stream, int connection) { Check_Object(memory_stream); int min_row = 0; int max_row = 0; int min_column = 0; int max_column = 0; GetSize(&max_row, &max_column); //SPEW(("jerryeds", "CENTER - ROW:%d COL:%d - MaxRow:%d -- MaxCol:%d", row, column, max_row, max_column)); for (int row_counter=(row-1); row_counter<=row+1; ++row_counter) { if (row_counter < min_row || row_counter >= max_row) { //SPEW(("jerryeds","SKIP ROW:%d", row_counter)); continue; } for (int column_counter=(column-1); column_counter<=column+1; ++column_counter) { if (column_counter < min_column || column_counter >= max_column) { //SPEW(("jerryeds","SKIP COL:%d", column_counter)); continue; } WORD index = (WORD)((row_counter*max_column)+column_counter); //SPEW(("jerryeds","WRITING %d:<%d:%d>", index, row_counter, column_counter)); WriteTileDamageStream(index, memory_stream, connection); } } //SPEW(("jerryeds","")); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void NearBuildingExternalDamageUpdate::ReadTileBlock(int row, int column, MemoryStream *memory_stream, int connection, bool skip) { Check_Object(memory_stream); int min_row = 0; int max_row = 0; int min_column = 0; int max_column = 0; GetSize(&max_row, &max_column); //SPEW(("jerryeds", "CENTER - ROW:%d COL:%d - MaxRow:%d -- MaxCol:%d", row, column, max_row, max_column)); for (int row_counter=(row-1); row_counter<=row+1; ++row_counter) { if (row_counter < min_row || row_counter >= max_row) { //SPEW(("jerryeds","SKIP ROW:%d", row_counter)); continue; } for (int column_counter=(column-1); column_counter<=column+1; ++column_counter) { if (column_counter < min_column || column_counter >= max_column) { //SPEW(("jerryeds","SKIP COL:%d", column_counter)); continue; } WORD index = (WORD)((row_counter*max_column)+column_counter); //SPEW(("jerryeds","READING %d:<%d:%d>", index, row_counter, column_counter)); ReadTileDamageStream(index, memory_stream, connection, skip); } } //SPEW(("jerryeds","")); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void NearBuildingExternalDamageUpdate::WriteTileDamageStream(WORD index, DynamicMemoryStream *mem_stream, int connection) { Tile *tile = CollisionGrid::Instance->GetTile(index); Check_Object(tile); // if we don't have anything don't write anything.. if (!tile->GetDamagableEntityCount()) { //SPEW(("jerryeds", "SKIP EMPTY TILE")); return; } Network::GetInstance()->netStatCollector[Network::BuildingDamageBitSizeStat].AddToStatistic(connection,tile->GetDamagableEntityCount()); int bytes_left = tile->GetDamagableEntityCount() >> 3; BYTE bits_left = (BYTE)(tile->GetDamagableEntityCount() & 0x7); int current_index = tile->GetDamageBitStart() >> 3; Verify(current_index+bytes_left < EntityManager::GetInstance()->tileBoundDamage.GetSize()); BYTE *memory = (BYTE*)EntityManager::GetInstance()->tileBoundDamage.GetPointer(); while (bytes_left > 0) { //for (int i = 0; i < 8; ++i) //{ // int value = (memory[current_index]&(0x1 << i))?1:0; // SPEW(("jerryeds", "%d +", value)); //} mem_stream->WriteBits(&memory[current_index], 8); ++current_index; --bytes_left; } if (bits_left > 0) { //for (int i = 0; i < bits_left; ++i) //{ // int value = (memory[current_index]&(0x1 << i))?1:0; // SPEW(("jerryeds", "%d +", value)); //} mem_stream->WriteBits(&memory[current_index], bits_left); ++current_index; bits_left = 0; } //SPEW(("jerryeds","")); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void NearBuildingExternalDamageUpdate::ReadTileDamageStream(WORD index, MemoryStream *mem_stream, int connection, bool skip ) { Tile *tile = CollisionGrid::Instance->GetTile(index); Check_Object(tile); // if we don't have anything don't read anything.. if (!tile->GetDamagableEntityCount()) { return; } Network::GetInstance()->netStatCollector[Network::BuildingDamageBitSizeStat].AddToStatistic(connection,tile->GetDamagableEntityCount()); // set up all the initilization variables... bool different = false; int start_bit = tile->GetDamageBitStart() >> 3; int bytes_left = tile->GetDamagableEntityCount() >> 3; BYTE bits_left = (BYTE)(tile->GetDamagableEntityCount() & 0x7); int current_index = 0; Verify(current_index+bytes_left < EntityManager::GetInstance()->tileBoundDamage.GetSize()); BYTE *memory = (BYTE*)EntityManager::GetInstance()->tileBoundDamage.GetPointer(); // read all the damage bytes... BYTE comp_memory[256]; while (bytes_left) { mem_stream->ReadBits(&comp_memory[current_index], 8); // if we have different bits mark it down if (comp_memory[current_index] != memory[start_bit+current_index]) { different = true; } ++current_index; --bytes_left; } // read the remainder bits.. if (bits_left) { comp_memory[current_index] = 0; mem_stream->ReadBits(&comp_memory[current_index], bits_left); if (comp_memory[current_index] != memory[start_bit+current_index]) { different = true; } ++current_index; bits_left = 0; } // if we are in skip mode don't apply this stuff. if (skip) return; // if the incomming data is different than our state... if (different) { bytes_left = tile->GetDamagableEntityCount() >> 3; bits_left = (BYTE)(tile->GetDamagableEntityCount() & 0x7); current_index = tile->GetDamageBitStart() >> 3; int current_bit = 0; #if defined (_ARMOR) int entity_count = 0; #endif Entity *entity; // step thru all the entities... for (int i = 0; i < tile->GetDamagableEntityCount(); ++i) { entity = tile->GetDamagableEntity(i); Check_Object(entity); //Verify (entity->damageObject != NULL); #if defined (_ARMOR) ++entity_count; #endif int byte = current_bit >> 3; BYTE bit = (BYTE)(current_bit & 0x7); bool destroyed = (comp_memory[byte] & (0x1<IsDestroyed()) { entity->ReactToDestruction(InternalDamageObject::DestructionDamageMode, 0); } ++current_bit; } #if defined (_ARMOR) if (entity_count != tile->GetDamagableEntityCount()) STOP(("Damage is messed up")); #endif } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void SecondaryBuildingExternalDamageUpdate::Decode(Entity *entity, MemoryStream *memory_stream, Time till, Scalar packet_latency, int connection, int debug_level, int bandwidth, Scalar rate) { Check_Object(entity); Check_Object(memory_stream); // figure out our tile and send all the appropriate tiles... Check_Object(CollisionGrid::Instance); int row, column; WORD tile = 0; // jcem: critical error - should clear before ReadBits(...)... memory_stream->ReadBits(&tile, 11);//2048 FindRowAndColumn(tile, &row, &column); Network::GetInstance()->netStatCollector[Network::BuildingDamageBitSizeStat].AddToStatistic(connection,11); NearBuildingExternalDamageUpdate::ReadTileBlock((row+3),(column+3),memory_stream, connection); NearBuildingExternalDamageUpdate::ReadTileBlock((row+3),column,memory_stream, connection); NearBuildingExternalDamageUpdate::ReadTileBlock((row+3),(column-3),memory_stream, connection); NearBuildingExternalDamageUpdate::ReadTileBlock(row,(column+3),memory_stream, connection); NearBuildingExternalDamageUpdate::ReadTileBlock(row,(column-3),memory_stream, connection); NearBuildingExternalDamageUpdate::ReadTileBlock((row-3),(column+3),memory_stream, connection); NearBuildingExternalDamageUpdate::ReadTileBlock((row-3),column,memory_stream, connection); NearBuildingExternalDamageUpdate::ReadTileBlock((row-3),(column-3),memory_stream, connection); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void SecondaryBuildingExternalDamageUpdate::Skip(MemoryStream *memory_stream, int size, Time till, int connection, int debug_level, int bandwidth) { Check_Object(memory_stream); // figure out our tile and send all the appropriate tiles... Check_Object(CollisionGrid::Instance); int row, column; WORD tile = 0; // jcem: critical error - should clear before ReadBits(...)... memory_stream->ReadBits(&tile, 11);//2048 FindRowAndColumn(tile, &row, &column); Network::GetInstance()->netStatCollector[Network::BuildingDamageBitSizeStat].AddToStatistic(connection,11); NearBuildingExternalDamageUpdate::ReadTileBlock((row+3),(column+3),memory_stream, connection, true); NearBuildingExternalDamageUpdate::ReadTileBlock((row+3),column,memory_stream, connection, true); NearBuildingExternalDamageUpdate::ReadTileBlock((row+3),(column-3),memory_stream, connection, true); NearBuildingExternalDamageUpdate::ReadTileBlock(row,(column+3),memory_stream, connection, true); NearBuildingExternalDamageUpdate::ReadTileBlock(row,(column-3),memory_stream, connection, true); NearBuildingExternalDamageUpdate::ReadTileBlock((row-3),(column+3),memory_stream, connection, true); NearBuildingExternalDamageUpdate::ReadTileBlock((row-3),column,memory_stream, connection, true); NearBuildingExternalDamageUpdate::ReadTileBlock((row-3),(column-3),memory_stream, connection, true); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int SecondaryBuildingExternalDamageUpdate::MaxSize(Entity *entity, int debug_level, int bandwidth) { MWEntityManager *manager = Cast_Object(MWEntityManager*, MWEntityManager::GetInstance()); int current_bit = 0; current_bit += 11; current_bit += manager->maximumMidBuildings; return current_bit; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void SecondaryBuildingExternalDamageUpdate::Encode(Entity *entity, DynamicMemoryStream *memory_stream, int connection, int debug_level, int bandwidth) { Check_Object(entity); Check_Object(memory_stream); // figure out our tile and send all the appropriate tiles... Point3D position = MWApplication::GetInstance()->servedConnectionData[entity->GetReplicatorID().connectionID].vehiclePosition; Check_Object(CollisionGrid::Instance); int row, column; WORD tile; tile = CollisionGrid::Instance->FindElementIndex(position.z, position.x); FindRowAndColumn(tile, &row, &column); Verify(tile < 2048); memory_stream->WriteBits(&tile, 11);//2048 Network::GetInstance()->netStatCollector[Network::BuildingDamageBitSizeStat].AddToStatistic(connection,11); NearBuildingExternalDamageUpdate::WriteTileBlock((row+3),(column+3),memory_stream, connection); NearBuildingExternalDamageUpdate::WriteTileBlock((row+3),column,memory_stream, connection); NearBuildingExternalDamageUpdate::WriteTileBlock((row+3),(column-3),memory_stream, connection); NearBuildingExternalDamageUpdate::WriteTileBlock(row,(column+3),memory_stream, connection); NearBuildingExternalDamageUpdate::WriteTileBlock(row,(column-3),memory_stream, connection); NearBuildingExternalDamageUpdate::WriteTileBlock((row-3),(column+3),memory_stream, connection); NearBuildingExternalDamageUpdate::WriteTileBlock((row-3),column,memory_stream, connection); NearBuildingExternalDamageUpdate::WriteTileBlock((row-3),(column-3),memory_stream, connection); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void FarBuildingExternalDamageUpdate::Decode(Entity *entity, MemoryStream *memory_stream, Time till, Scalar packet_latency, int connection, int debug_level, int bandwidth, Scalar rate) { Check_Object(entity); Check_Object(memory_stream); Check_Object(CollisionGrid::Instance); int row, column; WORD tile = 0; // jcem: critical error - should clear before ReadBits(...)... memory_stream->ReadBits(&tile, 11);//2048 FindRowAndColumn(tile, &row, &column); int start_tile = 0; // jcem: critical error - should clear before ReadBits(...)... memory_stream->ReadBits(&start_tile, 4);//16 //SPEW(("jerryeds", "READ FAR TILE : %d : %d ", tile, start_tile)); Network::GetInstance()->netStatCollector[Network::BuildingDamageBitSizeStat].AddToStatistic(connection,14); int current_tile = start_tile; for (int i = 0; i < 9; ++i) { NearBuildingExternalDamageUpdate::ReadTileBlock( (row+TileBlockOffsets[current_tile][0]), (column+TileBlockOffsets[current_tile][1]), memory_stream, connection ); //SPEW(("jerryeds", "READ_TILE : %d : %d", row+TileBlockOffsets[current_tile][0], column+TileBlockOffsets[current_tile][1])); current_tile++; if (current_tile > 15) current_tile = 0; } //SPEW(("jerryeds", "")); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void FarBuildingExternalDamageUpdate::Skip(MemoryStream *memory_stream, int size, Time till, int connection, int debug_level, int bandwidth) { Check_Object(memory_stream); Check_Object(CollisionGrid::Instance); int row, column; WORD tile = 0; // jcem: critical error - should clear before ReadBits(...)... memory_stream->ReadBits(&tile, 11);//2048 FindRowAndColumn(tile, &row, &column); int start_tile = 0; // jcem: critical error - should clear before ReadBits(...)... memory_stream->ReadBits(&start_tile, 4);//16 Network::GetInstance()->netStatCollector[Network::BuildingDamageBitSizeStat].AddToStatistic(connection,14); int current_tile = start_tile; for (int i = 0; i < 9; ++i) { NearBuildingExternalDamageUpdate::ReadTileBlock( (row+TileBlockOffsets[current_tile][0]), (column+TileBlockOffsets[current_tile][1]), memory_stream, connection, true ); current_tile++; if (current_tile > 15) current_tile = 0; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int FarBuildingExternalDamageUpdate::MaxSize(Entity *entity, int debug_level, int bandwidth) { MWEntityManager *manager = Cast_Object(MWEntityManager*, MWEntityManager::GetInstance()); int current_bit = 0; current_bit += 15; current_bit += manager->maximumFarBuildings; return current_bit; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void FarBuildingExternalDamageUpdate::Encode(Entity *entity, DynamicMemoryStream *memory_stream, int connection, int debug_level, int bandwidth) { Check_Object(entity); Check_Object(memory_stream); Point3D position = MWApplication::GetInstance()->servedConnectionData[entity->GetReplicatorID().connectionID].vehiclePosition; Check_Object(CollisionGrid::Instance); int row, column; WORD tile; tile = CollisionGrid::Instance->FindElementIndex(position.z, position.x); FindRowAndColumn(tile, &row, &column); //figure out which friggin square to start with... YawPitchRange angle = MWApplication::GetInstance()->servedConnectionData[entity->GetReplicatorID().connectionID].vehicleRotation; Scalar degrees = angle.yaw * Degrees_Per_Radian; // Actually what we want is the 4 squares less ( counter clockwise ) // than the square we hit. Then we update 9 tiles clockwise from that number... int start_tile = CalculateStartTile(degrees); Verify(tile < 2048); Verify(start_tile < 16); memory_stream->WriteBits(&tile, 11);//2048 memory_stream->WriteBits(&start_tile, 4);//16 //SPEW(("jerryeds", "WRITE FAR : %d : %d ", tile, start_tile)); Network::GetInstance()->netStatCollector[Network::BuildingDamageBitSizeStat].AddToStatistic(connection,14); int current_tile = start_tile; for (int i = 0; i < 9; ++i) { //int t_row = row+TileBlockOffsets[current_tile][0]; //int t_col = column+TileBlockOffsets[current_tile][1]; //SPEW(("jerryeds", "WriteBlock - %d - TILEBLOCK : %d : %d", current_tile, t_row, t_col)); NearBuildingExternalDamageUpdate::WriteTileBlock( (row+TileBlockOffsets[current_tile][0]), (column+TileBlockOffsets[current_tile][1]), memory_stream, connection ); //SPEW(("jerryeds", "WRITE_TILE : %d : %d", row+TileBlockOffsets[current_tile][0], column+TileBlockOffsets[current_tile][1])); current_tile++; if (current_tile > 15) current_tile = 0; } //SPEW(("jerryeds", "")); }