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.
1849 lines
48 KiB
C++
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(¤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<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(¤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<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(¤t_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(¤t_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", ""));
|
|
|
|
} |