Files
Cyd 2b8ca921cb Initial full mirror of c:\VWE (source + assets + toolchain + outputs) via Git LFS
Complete disaster-recovery snapshot: engine/game source, game data assets,
VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive.
Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false,
no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
2026-06-24 21:28:16 -05:00

1849 lines
48 KiB
C++

//===========================================================================//
// 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 <Adept\CollisionGrid.hpp>
#include <Adept\Tile.hpp>
#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<DamageObject *, int> damage_iterator(&mech->damageObjects);
int current_life = 0; // jcem: critical error - should clear before ReadBits(...)...
memory_stream->ReadBits(&current_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<MWInternalDamageObject *, int> 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<MWInternalDamageObject *, int> 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<DamageObject *, int> damage_iterator(&mech->damageObjects);
while((damage_object = damage_iterator.ReadAndNext()) != NULL)
{
Check_Object(damage_object);
++size;
}
MWInternalDamageObject *internal_damage_object;
SortedChainIteratorOf<MWInternalDamageObject *, int> 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<DamageObject *, int> damage_iterator(&mech->damageObjects);
while((damage_object = damage_iterator.ReadAndNext()) != NULL)
{
Check_Object(damage_object);
++size;
}
MWInternalDamageObject *internal_damage_object;
SortedChainIteratorOf<MWInternalDamageObject *, int> 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(&current_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<DamageObject *, int> 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<MWInternalDamageObject *, int> 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(&current_life,2);
// if the lives match...
if (current_life == mech->respawnCount % 4)
{
DamageObject *damage_object;
SortedChainIteratorOf<DamageObject *, int> 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<MWInternalDamageObject *, int> 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<DamageObject *, int> 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<MWInternalDamageObject *, int> 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<DamageObject *, int> damage_iterator(&mech->damageObjects);
while((damage_object = damage_iterator.ReadAndNext()) != NULL)
{
Check_Object(damage_object);
++size;
}
MWInternalDamageObject *internal_damage_object;
SortedChainIteratorOf<MWInternalDamageObject *, int> 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<DamageObject *, int> damage_iterator(&mech->damageObjects);
while((damage_object = damage_iterator.ReadAndNext()) != NULL)
{
Check_Object(damage_object);
++size;
}
MWInternalDamageObject *internal_damage_object;
SortedChainIteratorOf<MWInternalDamageObject *, int> 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(&current_life,2);
DamageObject *damage_object;
SortedChainIteratorOf<DamageObject *, int> 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<MWInternalDamageObject *, int> 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<Airplane*> 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<Boat*> 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<Dropship*> 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<Helicopter*> 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<Hovercraft*> 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<Tank*> 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<Truck*> 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<Turret*> 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<Airplane*> iterator1(&manager->servedAirplanes);
Entity *entity;
while ((entity = iterator1.ReadAndNext()) != NULL)
{
++size;
}
Stuff::ChainIteratorOf<Boat*> iterator2(&manager->servedBoats);
while ((entity = iterator2.ReadAndNext()) != NULL)
{
++size;
}
Stuff::ChainIteratorOf<Dropship*> iterator3(&manager->servedDropships);
while ((entity = iterator3.ReadAndNext()) != NULL)
{
++size;
}
Stuff::ChainIteratorOf<Helicopter*> iterator4(&manager->servedHelicopters);
while ((entity = iterator4.ReadAndNext()) != NULL)
{
++size;
}
Stuff::ChainIteratorOf<Hovercraft*> iterator5(&manager->servedHovercraft);
while ((entity = iterator5.ReadAndNext()) != NULL)
{
++size;
}
Stuff::ChainIteratorOf<Tank*> iterator7(&manager->servedTanks);
while ((entity = iterator7.ReadAndNext()) != NULL)
{
++size;
}
Stuff::ChainIteratorOf<Truck*> iterator8(&manager->servedTrucks);
while ((entity = iterator8.ReadAndNext()) != NULL)
{
++size;
}
Stuff::ChainIteratorOf<Turret*> 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<Airplane*> iterator1(&manager->servedAirplanes);
Entity *entity;
while ((entity = iterator1.ReadAndNext()) != NULL)
{
if (entity->IsDestroyed())
{
memory_stream->WriteBit(true);
}
else
{
memory_stream->WriteBit(false);
}
}
Stuff::ChainIteratorOf<Boat*> iterator2(&manager->servedBoats);
while ((entity = iterator2.ReadAndNext()) != NULL)
{
if (entity->IsDestroyed())
{
memory_stream->WriteBit(true);
}
else
{
memory_stream->WriteBit(false);
}
}
Stuff::ChainIteratorOf<Dropship*> iterator3(&manager->servedDropships);
while ((entity = iterator3.ReadAndNext()) != NULL)
{
if (entity->IsDestroyed())
{
memory_stream->WriteBit(true);
}
else
{
memory_stream->WriteBit(false);
}
}
Stuff::ChainIteratorOf<Helicopter*> iterator4(&manager->servedHelicopters);
while ((entity = iterator4.ReadAndNext()) != NULL)
{
if (entity->IsDestroyed())
{
memory_stream->WriteBit(true);
}
else
{
memory_stream->WriteBit(false);
}
}
Stuff::ChainIteratorOf<Hovercraft*> iterator5(&manager->servedHovercraft);
while ((entity = iterator5.ReadAndNext()) != NULL)
{
if (entity->IsDestroyed())
{
memory_stream->WriteBit(true);
}
else
{
memory_stream->WriteBit(false);
}
}
Stuff::ChainIteratorOf<Tank*> iterator7(&manager->servedTanks);
while ((entity = iterator7.ReadAndNext()) != NULL)
{
if (entity->IsDestroyed())
{
memory_stream->WriteBit(true);
}
else
{
memory_stream->WriteBit(false);
}
}
Stuff::ChainIteratorOf<Truck*> iterator8(&manager->servedTrucks);
while ((entity = iterator8.ReadAndNext()) != NULL)
{
if (entity->IsDestroyed())
{
memory_stream->WriteBit(true);
}
else
{
memory_stream->WriteBit(false);
}
}
Stuff::ChainIteratorOf<Turret*> 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<<bit))?true:false;
// if it needs to be destroyed than do it.
if (destroyed && !entity->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", ""));
}