//------------------------------------------------------------------------
float CVehicleMovementWarrior::RotatePart(IVehiclePart *pPart, float angleGoal, int axis, float speed, float deltaTime, float maxDelta)
{
	assert(axis >= AXIS_X && axis <= AXIS_Z);

	if(!pPart)
		return 0.f;

	const Matrix34 &tm = pPart->GetLocalBaseTM();
	Matrix33 tm33(tm);

	float ang = Ang3::GetAnglesXYZ(tm33)[axis];

	float absDelta = abs(angleGoal - ang);

	if(absDelta > 0.01f)
	{
		float angleDelta = min(absDelta, speed*deltaTime);

		if(maxDelta > 0.f)
			angleDelta = min(angleDelta, maxDelta);

		angleDelta *= sgn(angleGoal-ang);

		Matrix34 newTM(tm33 * CreateRotation<Matrix33>(axis, angleDelta), tm.GetTranslation());
		pPart->SetLocalBaseTM(newTM);

		return angleDelta;
	}

	return 0.f;
}
//------------------------------------------------------------------------
void CVehicleSeatActionRotateTurret::Serialize(TSerialize ser, EEntityAspects aspects)
{
	// MR: for network, only turret parts are serialized
	// for savegame, all parts are serialized (by CVehicle)
	if (ser.GetSerializationTarget() == eST_Network)
	{
		for (int i = 0; i < eVTRT_NumRotationTypes; ++i)
		{
			if (m_rotations[i].m_pPart)
			{
				m_rotations[i].m_pPart->Serialize(ser, aspects);
			}
		}
	}
	else
	{
		// save rotation details
		CryFixedStringT<16> tag;
		for (int i = 0; i < eVTRT_NumRotationTypes; ++i)
		{
			if (m_rotations[i].m_pPart)
			{
				Quat     q;
				Matrix34 currentTM = m_rotations[i].m_pPart->GetLocalBaseTM();
				if (ser.IsWriting())
					q = Quat(currentTM);

				tag = (i == eVTRT_Pitch) ? "rotation_pitch" : "rotation_yaw";
				ser.Value(tag.c_str(), q, 'ori1');

				if (ser.IsReading())
				{
					Matrix34 newTM(q);
					newTM.SetTranslation(currentTM.GetTranslation());
					m_rotations[i].m_pPart->SetLocalBaseTM(newTM);
					m_rotations[i].m_orientation.Set(q);
				}
			}
		}
	}
}
//------------------------------------------------------------------------
void CVehicleSeatActionRotateTurret::UpdatePartRotation(EVehicleTurretRotationType eType, float frameTime)
{
	CRY_ASSERT( eType < eVTRT_NumRotationTypes );

	const float threshold = 0.01f;
	if (frameTime > 0.08f) frameTime = 0.08f;

	CVehiclePartBase* pPart   = m_rotations[eType].m_pPart;
	IVehiclePart*     pParent = pPart->GetParent();
	IActor*           pActor  = m_pSeat->GetPassengerActor();

	float rot_dir      = fsgnf(m_rotations[eType].m_action);
	float max_rotation = fabsf(m_rotations[eType].m_action);
	float rot_speed    = DEG2RAD(fabsf(m_rotations[eType].m_speed)) * GetDamageSpeedMul(pPart);

	float delta = rot_dir * rot_speed  * frameTime;
	delta += m_rotations[eType].m_aimAssist;

	delta = fmod(delta, gf_PI2);
	if (delta > gf_PI)  delta -= gf_PI2;
	if (delta < -gf_PI) delta += gf_PI2;

	Limit( delta, -max_rotation, max_rotation);

	Ang3 deltaAngles(ZERO);
	if (eType == eVTRT_Pitch)
		deltaAngles.x = delta;
	else if (eType == eVTRT_Yaw)
		deltaAngles.z = delta;
	else
		CRY_ASSERT(false && "Unknown turret rotation");

	Matrix34 tm     = pPart->GetLocalBaseTM();
	Ang3     angles = Ang3::GetAnglesXYZ(tm) + deltaAngles;

	float lerp = 0.f;
	if (eType == eVTRT_Pitch)
	{
		Vec3 yAxis = m_rotations[eVTRT_Yaw].m_pPart->GetLocalBaseTM().GetColumn1();
		yAxis.z = 0.f;
		yAxis.normalize();
		lerp = 0.5f - 0.5f * yAxis.y;
		Limit(lerp, 0.0f, 1.0f);
	}

	// clamp to limits
	if (m_rotations[eType].m_minLimitF != 0.0f || m_rotations[eType].m_maxLimit != 0.0f)
	{
		// Different clamp angles facing forwards/backwards
		float minLimit = m_rotations[eType].m_minLimitF + (m_rotations[eType].m_minLimitB - m_rotations[eType].m_minLimitF) * lerp;
		float angle    = (eType == eVTRT_Pitch) ? angles.x : angles.z;
		if (angle > m_rotations[eType].m_maxLimit || angle < minLimit)
		{
			angle                             = clamp_tpl(angle, minLimit, m_rotations[eType].m_maxLimit);
			m_rotations[eType].m_currentValue = 0.f;

			if (eType == eVTRT_Pitch)
				angles.x = angle;
			else
				angles.z = angle;
		}
	}

	m_rotations[eType].m_orientation.Set(Quat::CreateRotationXYZ(angles));
	m_rotations[eType].m_orientation.Update(frameTime);

	m_rotations[eType].m_action    = 0.0f;
	m_rotations[eType].m_aimAssist = 0.0f;

	Matrix34 newTM(m_rotations[eType].m_orientation.Get().GetNormalized());
	newTM.SetTranslation(tm.GetTranslation());
	pPart->SetLocalBaseTM(newTM);

	// store world-space rotation
	const Matrix34 &worldTM = pPart->GetWorldTM();
	m_rotations[eType].m_prevWorldQuat = Quat(worldTM);
	CRY_ASSERT(m_rotations[eType].m_prevWorldQuat.IsValid());

	// now update the turret sound based on the calculated rotation speed
	UpdateRotationSound(eType, delta, frameTime);

}