//===========================================================================//
// File:	NetVehicleMovement.cpp											
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
// 01/06/2000  JSE  Inital coding
//---------------------------------------------------------------------------//
// Copyright (C) 1998, Microsoft Corp.										 //
// All Rights reserved worldwide                                             //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================//


#include "MW4Headers.hpp"

#include "NetVehicleMovement.hpp"
#include "MWEntityManager.hpp"

#include "Airplane.hpp"
#include "Boat.hpp"
#include "Dropship.hpp"
#include "Helicopter.hpp"
#include "Hovercraft.hpp"
#include "Tank.hpp"
#include "Truck.hpp"
#include "Turret.hpp"
#include "Torso.hpp"

#include <Adept\Map.hpp>
#include <Adept\NetStatCollector.hpp>

//====================================================================================================================================================
//

void AirMovementUpdate::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);

	

	int current_bit = memory_stream->GetCurrentBitCount();

	Vehicle *vehicle = Cast_Object(Vehicle*, entity);
	const Vehicle::GameModel *model = vehicle->GetGameModel();
	
	bool vehicle_on;
	memory_stream->ReadBit(vehicle_on);

	int local_vehicle_on = (vehicle->executionState->GetState() != Entity::ExecutionStateEngine::NeverExecuteState)?1:0;
//bug fix #4820
	if (vehicle_on && !local_vehicle_on)
	{
		vehicle->TurnOn();
		vehicle->executionState->RequestState(Airplane::ExecutionStateEngine::FlyingMotionState);
	}
	if (!vehicle_on && local_vehicle_on)
	{
		vehicle->TurnOff();
	}

	if (vehicle_on)
	{
		
		YawPitchRoll vehicle_rotation_local_to_world(YawPitchRoll::Identity);
		Point3D vehicle_translation_local_to_world(Point3D::Identity);

		Scalar min_z, max_z, min_x, max_x;
		Map::GetInstance()->GetMapExtents(&min_z, &max_z, &min_x, &max_x);

		Point3D current_speed = Point3D::Identity;

		memory_stream->ReadBitsToScaledFloat(vehicle_translation_local_to_world.x, min_x, max_x, BitDepthManager::BitDepth(UpdateType,XPositionUpdateEntryID));
		memory_stream->ReadBitsToScaledFloat(vehicle_translation_local_to_world.y, -2005.0f, 1005.0f, BitDepthManager::BitDepth(UpdateType,YPositionUpdateEntryID));
		memory_stream->ReadBitsToScaledFloat(vehicle_translation_local_to_world.z, min_z, max_z, BitDepthManager::BitDepth(UpdateType,ZPositionUpdateEntryID));
		memory_stream->ReadBitsToScaledFloat(vehicle_rotation_local_to_world.yaw.angle, -Pi, Pi, BitDepthManager::BitDepth(UpdateType,YawPositionUpdateEntryID));
		memory_stream->ReadBitsToScaledFloat(vehicle_rotation_local_to_world.pitch.angle, -Pi, Pi, BitDepthManager::BitDepth(UpdateType,PitchPositionUpdateEntryID));
		memory_stream->ReadBitsToScaledFloat(vehicle_rotation_local_to_world.roll.angle, -Pi, Pi, BitDepthManager::BitDepth(UpdateType,RollPositionUpdateEntryID));
		
		memory_stream->ReadBitsToScaledFloat(current_speed.z, model->maxReverseSpeed, model->maxSpeed*1.25f, BitDepthManager::BitDepth(UpdateType,CurrentSpeedUpdateEntryID));
		memory_stream->ReadBitsToScaledFloat(vehicle->speedDemand, -1.0f, 1.0f, BitDepthManager::BitDepth(UpdateType,SpeedDemandUpdateEntryID));
		memory_stream->ReadBitsToScaledFloat(vehicle->yawDemand, -1.0f, 1.0f, BitDepthManager::BitDepth(UpdateType,YawDemandUpdateEntryID));
		memory_stream->ReadBitsToScaledFloat(vehicle->pitchDemand, -1.0f, 1.0f, BitDepthManager::BitDepth(UpdateType,PitchDemandUpdateEntryID));
		memory_stream->ReadBitsToScaledFloat(vehicle->rollDemand, -1.0f, 1.0f, BitDepthManager::BitDepth(UpdateType,RollDemandUpdateEntryID));


		vehicle->SetNetworkCorretionPosition(vehicle_translation_local_to_world, vehicle_rotation_local_to_world, current_speed, current_speed.z, packet_latency, rate);
		vehicle->currentSpeedMPS = current_speed.z;

	}
	else
	{
	}

	
	Network::GetInstance()->netStatCollector[Network::VehicleBitSizeStat].AddToStatistic(connection,memory_stream->GetCurrentBitCount() - current_bit);
	
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void AirMovementUpdate::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();

	bool vehicle_on;
	memory_stream->ReadBit(vehicle_on);

	if (vehicle_on)
	{
		int throw_away;
		memory_stream->ReadBits(&throw_away, BitDepthManager::BitDepth(UpdateType,XPositionUpdateEntryID));
		memory_stream->ReadBits(&throw_away, BitDepthManager::BitDepth(UpdateType,YPositionUpdateEntryID));
		memory_stream->ReadBits(&throw_away, BitDepthManager::BitDepth(UpdateType,ZPositionUpdateEntryID));
		memory_stream->ReadBits(&throw_away, BitDepthManager::BitDepth(UpdateType,YawPositionUpdateEntryID));
		memory_stream->ReadBits(&throw_away, BitDepthManager::BitDepth(UpdateType,PitchPositionUpdateEntryID));
		memory_stream->ReadBits(&throw_away, BitDepthManager::BitDepth(UpdateType,RollPositionUpdateEntryID));
		memory_stream->ReadBits(&throw_away, BitDepthManager::BitDepth(UpdateType,CurrentSpeedUpdateEntryID));
		memory_stream->ReadBits(&throw_away, BitDepthManager::BitDepth(UpdateType,SpeedDemandUpdateEntryID));
		memory_stream->ReadBits(&throw_away, BitDepthManager::BitDepth(UpdateType,YawDemandUpdateEntryID));
		memory_stream->ReadBits(&throw_away, BitDepthManager::BitDepth(UpdateType,PitchDemandUpdateEntryID));
		memory_stream->ReadBits(&throw_away, BitDepthManager::BitDepth(UpdateType,RollDemandUpdateEntryID));

	}
	else
	{
	}
	
	Network::GetInstance()->netStatCollector[Network::VehicleBitSizeStat].AddToStatistic(connection,memory_stream->GetCurrentBitCount() - current_bit);
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int AirMovementUpdate::MaxSize(Entity *entity, int debug_level, int bandwidth)
{
	
	int current_bit = 0;

	current_bit += 1;
	current_bit += BitDepthManager::BitDepth(UpdateType,XPositionUpdateEntryID);
	current_bit += BitDepthManager::BitDepth(UpdateType,YPositionUpdateEntryID);
	current_bit += BitDepthManager::BitDepth(UpdateType,ZPositionUpdateEntryID);
	current_bit += BitDepthManager::BitDepth(UpdateType,YawPositionUpdateEntryID);
	current_bit += BitDepthManager::BitDepth(UpdateType,PitchPositionUpdateEntryID);
	current_bit += BitDepthManager::BitDepth(UpdateType,RollPositionUpdateEntryID);
	current_bit += BitDepthManager::BitDepth(UpdateType,CurrentSpeedUpdateEntryID);
	current_bit += BitDepthManager::BitDepth(UpdateType,SpeedDemandUpdateEntryID);
	current_bit += BitDepthManager::BitDepth(UpdateType,YawDemandUpdateEntryID);
	current_bit += BitDepthManager::BitDepth(UpdateType,PitchDemandUpdateEntryID);
	current_bit += BitDepthManager::BitDepth(UpdateType,RollDemandUpdateEntryID);

	return current_bit;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

bool AirMovementUpdate::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)
	{
	
		if (entity->executionState->GetState() != Entity::ExecutionStateEngine::NeverExecuteState)
		{
			return true;

		}
	}
	

	return false;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void AirMovementUpdate::Encode(Entity *entity, DynamicMemoryStream *memory_stream, int connection, int debug_level, int bandwidth)
{
	Check_Object(entity);
	Check_Object(memory_stream);

	int current_bit = memory_stream->GetCurrentBitCount();

	Vehicle *vehicle = Cast_Object(Vehicle*, entity);
	const Vehicle::GameModel *model = vehicle->GetGameModel();
	Check_Object(model);

	int vehicle_on = (vehicle->executionState->GetState() != Entity::ExecutionStateEngine::NeverExecuteState)?1:0;

	if (vehicle_on)
	{
		memory_stream->WriteBit(true);

		Point3D vehicle_translation_local_to_world;
		YawPitchRoll vehicle_rotation_local_to_world;
		
		vehicle->GetNetworkPosition(vehicle_translation_local_to_world, vehicle_rotation_local_to_world);


		Scalar min_z, max_z, min_x, max_x;
		Map::GetInstance()->GetMapExtents(&min_z, &max_z, &min_x, &max_x);


		memory_stream->WriteScaledFloatToBits(vehicle_translation_local_to_world.x, min_x, max_x, BitDepthManager::BitDepth(UpdateType,XPositionUpdateEntryID));
		memory_stream->WriteScaledFloatToBits(vehicle_translation_local_to_world.y, -2005.0f, 1005.0f, BitDepthManager::BitDepth(UpdateType,YPositionUpdateEntryID));
		memory_stream->WriteScaledFloatToBits(vehicle_translation_local_to_world.z, min_z, max_z, BitDepthManager::BitDepth(UpdateType,ZPositionUpdateEntryID));
		memory_stream->WriteScaledFloatToBits(vehicle_rotation_local_to_world.yaw, -Pi, Pi, BitDepthManager::BitDepth(UpdateType,YawPositionUpdateEntryID));
		memory_stream->WriteScaledFloatToBits(vehicle_rotation_local_to_world.pitch, -Pi, Pi, BitDepthManager::BitDepth(UpdateType,PitchPositionUpdateEntryID));
		memory_stream->WriteScaledFloatToBits(vehicle_rotation_local_to_world.roll, -Pi, Pi, BitDepthManager::BitDepth(UpdateType,RollPositionUpdateEntryID));
		
		memory_stream->WriteScaledFloatToBits(vehicle->currentSpeedMPS, model->maxReverseSpeed, model->maxSpeed*1.25f, BitDepthManager::BitDepth(UpdateType,CurrentSpeedUpdateEntryID));
		memory_stream->WriteScaledFloatToBits(vehicle->speedDemand, -1.0f, 1.0f, BitDepthManager::BitDepth(UpdateType,SpeedDemandUpdateEntryID));
		memory_stream->WriteScaledFloatToBits(vehicle->yawDemand, -1.0f, 1.0f, BitDepthManager::BitDepth(UpdateType,YawDemandUpdateEntryID));
		memory_stream->WriteScaledFloatToBits(vehicle->pitchDemand, -1.0f, 1.0f, BitDepthManager::BitDepth(UpdateType,PitchDemandUpdateEntryID));
		memory_stream->WriteScaledFloatToBits(vehicle->rollDemand, -1.0f, 1.0f, BitDepthManager::BitDepth(UpdateType,RollDemandUpdateEntryID));
		

	}
	else
	{
		memory_stream->WriteBit(false);
	}

	Network::GetInstance()->netStatCollector[Network::VehicleBitSizeStat].AddToStatistic(connection, memory_stream->GetCurrentBitCount() - current_bit);

}

//====================================================================================================================================================
//

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void GroundMovementUpdate::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);

	

	int current_bit = memory_stream->GetCurrentBitCount();


	Vehicle *vehicle = Cast_Object(Vehicle*, entity);
	const Vehicle::GameModel *model = vehicle->GetGameModel();
	
	bool vehicle_on;
	memory_stream->ReadBit(vehicle_on);

	int local_vehicle_on = (vehicle->executionState->GetState() != Entity::ExecutionStateEngine::NeverExecuteState)?1:0;
	if (vehicle_on && !local_vehicle_on)
	{
		vehicle->TurnOn();
	}
	if (!vehicle_on && local_vehicle_on)
	{
		vehicle->TurnOff();
	}

	if (vehicle_on)
	{
		
		YawPitchRoll vehicle_rotation_local_to_world(YawPitchRoll::Identity);
		Point3D vehicle_translation_local_to_world(Point3D::Identity);

		Scalar min_z, max_z, min_x, max_x;
		Map::GetInstance()->GetMapExtents(&min_z, &max_z, &min_x, &max_x);


		
		Point3D current_speed = Point3D::Identity;

		memory_stream->ReadBitsToScaledFloat(vehicle_translation_local_to_world.x, min_x, max_x, BitDepthManager::BitDepth(UpdateType,XPositionUpdateEntryID));
		memory_stream->ReadBitsToScaledFloat(vehicle_translation_local_to_world.y, -2005.0f, 1005.0f, BitDepthManager::BitDepth(UpdateType,YPositionUpdateEntryID));
		memory_stream->ReadBitsToScaledFloat(vehicle_translation_local_to_world.z, min_z, max_z, BitDepthManager::BitDepth(UpdateType,ZPositionUpdateEntryID));
		memory_stream->ReadBitsToScaledFloat(vehicle_rotation_local_to_world.yaw.angle, -Pi, Pi, BitDepthManager::BitDepth(UpdateType,YawPositionUpdateEntryID));
		memory_stream->ReadBitsToScaledFloat(current_speed.z, model->maxReverseSpeed, model->maxSpeed*1.25f, BitDepthManager::BitDepth(UpdateType,CurrentSpeedUpdateEntryID));
		memory_stream->ReadBitsToScaledFloat(vehicle->speedDemand, -1.0f, 1.0f, BitDepthManager::BitDepth(UpdateType,SpeedDemandUpdateEntryID));
		memory_stream->ReadBitsToScaledFloat(vehicle->yawDemand, -1.0f, 1.0f, BitDepthManager::BitDepth(UpdateType,YawDemandUpdateEntryID));


		vehicle->SetNetworkCorretionPosition(vehicle_translation_local_to_world, vehicle_rotation_local_to_world, current_speed, current_speed.z, packet_latency, rate);

		vehicle->currentSpeedMPS = current_speed.z;
	}
	else
	{
	}


	
	Network::GetInstance()->netStatCollector[Network::VehicleBitSizeStat].AddToStatistic(connection,memory_stream->GetCurrentBitCount() - current_bit);
	
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void GroundMovementUpdate::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();

	bool vehicle_on;
	memory_stream->ReadBit(vehicle_on);

	if (vehicle_on)
	{
		int throw_away;
		memory_stream->ReadBits(&throw_away, BitDepthManager::BitDepth(UpdateType,XPositionUpdateEntryID));
		memory_stream->ReadBits(&throw_away, BitDepthManager::BitDepth(UpdateType,YPositionUpdateEntryID));
		memory_stream->ReadBits(&throw_away, BitDepthManager::BitDepth(UpdateType,ZPositionUpdateEntryID));
		memory_stream->ReadBits(&throw_away, BitDepthManager::BitDepth(UpdateType,YawPositionUpdateEntryID));
		memory_stream->ReadBits(&throw_away, BitDepthManager::BitDepth(UpdateType,CurrentSpeedUpdateEntryID));
		memory_stream->ReadBits(&throw_away, BitDepthManager::BitDepth(UpdateType,SpeedDemandUpdateEntryID));
		memory_stream->ReadBits(&throw_away, BitDepthManager::BitDepth(UpdateType,YawDemandUpdateEntryID));

	}
	else
	{
	}

	
	Network::GetInstance()->netStatCollector[Network::VehicleBitSizeStat].AddToStatistic(connection,memory_stream->GetCurrentBitCount() - current_bit);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int GroundMovementUpdate::MaxSize(Entity *entity, int debug_level, int bandwidth)
{
	
	int current_bit = 0;

	current_bit += 1;
	current_bit += BitDepthManager::BitDepth(UpdateType,XPositionUpdateEntryID);
	current_bit += BitDepthManager::BitDepth(UpdateType,YPositionUpdateEntryID);
	current_bit += BitDepthManager::BitDepth(UpdateType,ZPositionUpdateEntryID);
	current_bit += BitDepthManager::BitDepth(UpdateType,YawPositionUpdateEntryID);
	current_bit += BitDepthManager::BitDepth(UpdateType,CurrentSpeedUpdateEntryID);
	current_bit += BitDepthManager::BitDepth(UpdateType,SpeedDemandUpdateEntryID);
	current_bit += BitDepthManager::BitDepth(UpdateType,YawDemandUpdateEntryID);
	
	return current_bit;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

bool GroundMovementUpdate::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)
	{
	
		if (entity->executionState->GetState() != Entity::ExecutionStateEngine::NeverExecuteState)
		{
			return true;

		}
	}
	

	return false;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void GroundMovementUpdate::Encode(Entity *entity, DynamicMemoryStream *memory_stream, int connection, int debug_level, int bandwidth)
{
	Check_Object(entity);
	Check_Object(memory_stream);

	int current_bit = memory_stream->GetCurrentBitCount();


	Vehicle *vehicle = Cast_Object(Vehicle*, entity);
	const Vehicle::GameModel *model = vehicle->GetGameModel();
	Check_Object(model);

	int vehicle_on = (vehicle->executionState->GetState() != Entity::ExecutionStateEngine::NeverExecuteState)?1:0;

	if (vehicle_on)
	{
		memory_stream->WriteBit(true);

		Point3D vehicle_translation_local_to_world;
		YawPitchRoll vehicle_rotation_local_to_world;
		
		vehicle->GetNetworkPosition(vehicle_translation_local_to_world, vehicle_rotation_local_to_world);


		Scalar min_z, max_z, min_x, max_x;
		Map::GetInstance()->GetMapExtents(&min_z, &max_z, &min_x, &max_x);


		memory_stream->WriteScaledFloatToBits(vehicle_translation_local_to_world.x, min_x, max_x, BitDepthManager::BitDepth(UpdateType,XPositionUpdateEntryID));
		memory_stream->WriteScaledFloatToBits(vehicle_translation_local_to_world.y, -2005.0f, 1005.0f, BitDepthManager::BitDepth(UpdateType,YPositionUpdateEntryID));
		memory_stream->WriteScaledFloatToBits(vehicle_translation_local_to_world.z, min_z, max_z, BitDepthManager::BitDepth(UpdateType,ZPositionUpdateEntryID));
		memory_stream->WriteScaledFloatToBits(vehicle_rotation_local_to_world.yaw, -Pi, Pi, BitDepthManager::BitDepth(UpdateType,YawPositionUpdateEntryID));
		memory_stream->WriteScaledFloatToBits(vehicle->currentSpeedMPS, model->maxReverseSpeed, model->maxSpeed*1.25f, BitDepthManager::BitDepth(UpdateType,CurrentSpeedUpdateEntryID));
		memory_stream->WriteScaledFloatToBits(vehicle->speedDemand, -1.0f, 1.0f, BitDepthManager::BitDepth(UpdateType,SpeedDemandUpdateEntryID));
		memory_stream->WriteScaledFloatToBits(vehicle->yawDemand, -1.0f, 1.0f, BitDepthManager::BitDepth(UpdateType,YawDemandUpdateEntryID));
		

	}
	else
	{
		memory_stream->WriteBit(false);
	}



	Network::GetInstance()->netStatCollector[Network::VehicleBitSizeStat].AddToStatistic(connection, memory_stream->GetCurrentBitCount() - current_bit);

}

//====================================================================================================================================================
//

void TurretMovementUpdate::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);

	
	Turret *vehicle = Cast_Object(Turret*, entity);

	int current_bit = memory_stream->GetCurrentBitCount();


	
	bool vehicle_on;
	memory_stream->ReadBit(vehicle_on);

	int local_vehicle_on = (vehicle->executionState->GetState() != Entity::ExecutionStateEngine::NeverExecuteState)?1:0;
	if (vehicle_on && !local_vehicle_on)
	{
		vehicle->TurnOn();
	}
	if (!vehicle_on && local_vehicle_on)
	{
		vehicle->TurnOff();
	}


	if (vehicle_on)
	{

	
	}
	else
	{
		
	}
	
	
	Network::GetInstance()->netStatCollector[Network::VehicleBitSizeStat].AddToStatistic(connection,memory_stream->GetCurrentBitCount() - current_bit);
	
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void TurretMovementUpdate::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();

	bool vehicle_on;
	memory_stream->ReadBit(vehicle_on);

	if (vehicle_on)
	{
		
	
	}
	
	Network::GetInstance()->netStatCollector[Network::VehicleBitSizeStat].AddToStatistic(connection,memory_stream->GetCurrentBitCount() - current_bit);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int TurretMovementUpdate::MaxSize(Entity *entity, int debug_level, int bandwidth)
{

	
	return 1;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

bool TurretMovementUpdate::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)
	{
	
		if (entity->executionState->GetState() != Entity::ExecutionStateEngine::NeverExecuteState)
		{
			return true;

		}
	}
	

	return false;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void TurretMovementUpdate::Encode(Entity *entity, DynamicMemoryStream *memory_stream, int connection, int debug_level, int bandwidth)
{
	Check_Object(entity);
	Check_Object(memory_stream);

	int current_bit = memory_stream->GetCurrentBitCount();

	MWObject *vehicle = Cast_Object(MWObject*, entity);


	

	int vehicle_on = (vehicle->executionState->GetState() != Entity::ExecutionStateEngine::NeverExecuteState)?1:0;

	if (vehicle_on)
	{
		memory_stream->WriteBit(true);

	
	}
	else
	{
		memory_stream->WriteBit(false);
	}


	Network::GetInstance()->netStatCollector[Network::VehicleBitSizeStat].AddToStatistic(connection, memory_stream->GetCurrentBitCount() - current_bit);

}

//====================================================================================================================================================
//

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void TorsoMovementUpdate::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);

	

	int current_bit = memory_stream->GetCurrentBitCount();

	Torso *torso = Cast_Object(Torso*, entity);
	Check_Object(torso);
	const Torso::GameModel *torso_model;
	torso_model = torso->GetGameModel();
	Check_Object(torso_model);

	
	bool vehicle_on;
	memory_stream->ReadBit(vehicle_on);


	if (vehicle_on)
	{

		Scalar pitch_value;
		Scalar yaw_value;

		memory_stream->ReadBitsToScaledFloat(pitch_value, -torso_model->pitchRadius, torso_model->pitchRadius,BitDepthManager::BitDepth(UpdateType,PitchTorsoPositionUpdateEntryID));
		memory_stream->ReadBitsToScaledFloat(yaw_value, -torso_model->twistRadius, torso_model->twistRadius, BitDepthManager::BitDepth(UpdateType,YawTorsoPositionUpdateEntryID));
		memory_stream->ReadBitsToScaledFloat(torso->pitchDemand, -torso_model->twistRadius, torso_model->twistRadius, BitDepthManager::BitDepth(UpdateType,PitchTorsoDemandUpdateEntryID));
		memory_stream->ReadBitsToScaledFloat(torso->yawDemand, -torso_model->twistRadius, torso_model->twistRadius, BitDepthManager::BitDepth(UpdateType,YawTorsoDemandUpdateEntryID));

		torso->oldYawValue = torso->yawValue;
		torso->oldPitchValue = torso->pitchValue;
		torso->pitchValueCorrection = pitch_value;
		torso->yawValueCorrection = yaw_value;
		torso->correctionTime = rate;
		torso->correctionCurTime = 0.0f;
	}
	else
	{
		
	}
	
	
	Network::GetInstance()->netStatCollector[Network::VehicleBitSizeStat].AddToStatistic(connection,memory_stream->GetCurrentBitCount() - current_bit);
	
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void TorsoMovementUpdate::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();

	bool vehicle_on;
	memory_stream->ReadBit(vehicle_on);

	if (vehicle_on)
	{
		int throw_away;
		memory_stream->ReadBits(&throw_away, BitDepthManager::BitDepth(UpdateType,PitchTorsoPositionUpdateEntryID));
		memory_stream->ReadBits(&throw_away, BitDepthManager::BitDepth(UpdateType,PitchTorsoPositionUpdateEntryID));
		memory_stream->ReadBits(&throw_away, BitDepthManager::BitDepth(UpdateType,PitchTorsoDemandUpdateEntryID));
		memory_stream->ReadBits(&throw_away, BitDepthManager::BitDepth(UpdateType,YawTorsoDemandUpdateEntryID));
	}
	
	Network::GetInstance()->netStatCollector[Network::VehicleBitSizeStat].AddToStatistic(connection,memory_stream->GetCurrentBitCount() - current_bit);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int TorsoMovementUpdate::MaxSize(Entity *entity, int debug_level, int bandwidth)
{
	
	int current_bit = 0;

	current_bit += 1;
	current_bit += BitDepthManager::BitDepth(UpdateType,PitchTorsoPositionUpdateEntryID);
	current_bit += BitDepthManager::BitDepth(UpdateType,PitchTorsoPositionUpdateEntryID);
	current_bit += BitDepthManager::BitDepth(UpdateType,PitchTorsoDemandUpdateEntryID);
	current_bit += BitDepthManager::BitDepth(UpdateType,YawTorsoDemandUpdateEntryID);
	

	return current_bit;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void TorsoMovementUpdate::Encode(Entity *entity, DynamicMemoryStream *memory_stream, int connection, int debug_level, int bandwidth)
{
	Check_Object(entity);
	Check_Object(memory_stream);

	int current_bit = memory_stream->GetCurrentBitCount();

	Torso *torso = Cast_Object(Torso*, entity);
	Check_Object(torso);
	const Torso::GameModel *torso_model;
	torso_model = torso->GetGameModel();
	Check_Object(torso_model);

	int vehicle_on = (torso->executionState->GetState() != Entity::ExecutionStateEngine::NeverExecuteState)?1:0;

	if (vehicle_on)
	{
		memory_stream->WriteBit(true);

		memory_stream->WriteScaledFloatToBits(torso->pitchValue, -torso_model->pitchRadius, torso_model->pitchRadius, BitDepthManager::BitDepth(UpdateType,PitchTorsoPositionUpdateEntryID));
		memory_stream->WriteScaledFloatToBits(torso->yawValue, -torso_model->twistRadius, torso_model->twistRadius, BitDepthManager::BitDepth(UpdateType,YawTorsoPositionUpdateEntryID));
		memory_stream->WriteScaledFloatToBits(torso->pitchDemand, -torso_model->twistRadius, torso_model->twistRadius, BitDepthManager::BitDepth(UpdateType,PitchTorsoDemandUpdateEntryID));
		memory_stream->WriteScaledFloatToBits(torso->yawDemand, -torso_model->twistRadius, torso_model->twistRadius, BitDepthManager::BitDepth(UpdateType,YawTorsoDemandUpdateEntryID));

	}
	else
	{
		memory_stream->WriteBit(false);
	}


	Network::GetInstance()->netStatCollector[Network::VehicleBitSizeStat].AddToStatistic(connection, memory_stream->GetCurrentBitCount() - current_bit);

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

bool TorsoMovementUpdate::MaintainActiveFlagFunction(Entity *entity,Point3D cull_location)
{
	Torso *torso = Cast_Object(Torso*, entity);
	Check_Object(torso);

	Point3D entity_location;
	entity_location = torso->GetParentEntity()->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)
	{
	
		if (entity->executionState->GetState() != Entity::ExecutionStateEngine::NeverExecuteState)
		{
			return true;

		}
	}
	

	return false;
}
