bool CSmartMine::ShouldStartTrackingEntity( const EntityId entityId ) const
{
	// Always track player...
	if (entityId == g_pGame->GetIGameFramework()->GetClientActorId())
	{
		return true;
	}

	// ... or any AI
	const SAutoaimTarget* pTargetInfo = g_pGame->GetAutoAimManager().GetTargetInfo( entityId );
	if(pTargetInfo != NULL)
	{
		return (pTargetInfo->pActorWeak.lock() != NULL);
	}

	// Also track kickable and pickable objects
	IEntity* pEntity = gEnv->pEntitySystem->GetEntity( entityId );
	IScriptTable* pScriptTable = (pEntity != NULL) ? pEntity->GetScriptTable() : NULL;
	if(pScriptTable != NULL)
	{
		SmartScriptTable propertiesTable;
		if(pScriptTable->GetValue("Properties", propertiesTable))
		{
			int pickable = 0, kickable = 0;
			propertiesTable->GetValue("bPickable", pickable);
			propertiesTable->GetValue("bInteractLargeObject", kickable);

			if(pickable)
			{
				// Filter out items/weapons
				pickable = (g_pGame->GetIGameFramework()->GetIItemSystem()->GetItem(entityId) == NULL);
			}

			if (pickable || kickable)
			{
				//Check if object is moving
				IPhysicalEntity* pEntityPhysics = pEntity->GetPhysics();
				if(pEntityPhysics != NULL)
				{
					pe_status_dynamics entityDynamics;
					if(pEntityPhysics->GetStatus(&entityDynamics))
					{
						return (entityDynamics.v.len2() > 0.1f);
					}
				}
			}
		}
	}

	return false;
}
//------------------------------------------------------------------------
void CVehicleDamageBehaviorImpulse::OnDamageEvent(EVehicleDamageBehaviorEvent event, const SVehicleDamageBehaviorEventParams& behaviorParams)
{
	if (event == eVDBE_Hit || event == eVDBE_VehicleDestroyed || event == eVDBE_ComponentDestroyed)  
	{
		IEntity* pEntity = m_pVehicle->GetEntity();
		CRY_ASSERT(pEntity);

		IPhysicalEntity* pPhysEntity = pEntity->GetPhysics();
		if (!pPhysEntity)
			return;

		pe_status_dynamics dyn;
		pPhysEntity->GetStatus(&dyn);
		float vehicleMass = dyn.mass;

		float r = cry_random(0.0f, 2.f);
		float impulseForce = cry_random(m_forceMin, m_forceMax) * vehicleMass;		

    Vec3 impulseDir(m_impulseDir);
    if (!m_worldSpace)
      impulseDir = m_pVehicle->GetEntity()->GetWorldTM().TransformVector(impulseDir);

		pe_action_impulse actionImpulse;
		Vec3& impulse = actionImpulse.impulse;
		Vec3& angImpulse = actionImpulse.angImpulse;

		impulse = impulseDir * impulseForce;
		angImpulse = m_pVehicle->GetEntity()->GetWorldTM().TransformVector(m_angImpulse);

		if (r <= 0.75f)
		{
			float r1 = cry_random(-0.35f, 0.35f);

			angImpulse += dyn.v * r1 * max(1.0f, dyn.w.GetLength());
			angImpulse *= vehicleMass;
		}
		else
		{
			float r1 = cry_random(-0.25f, 0.25f);
			float r2 = cry_random(-0.5f, 0.5f);

			impulse.z += abs(dyn.v.y) * r1 * vehicleMass;
			angImpulse.x += dyn.v.y * r2 * vehicleMass * max(1.0f, dyn.w.GetLength() * 1.5f);
		}

		if (m_pImpulseLocation)
			actionImpulse.point = m_pImpulseLocation->GetWorldSpaceTranslation();

		pPhysEntity->Action(&actionImpulse);
	}
}
Exemple #3
0
//-----------------------------------------------------------------------
void CSpectacularKill::DeathBlow(CActor& targetActor)
{
	CRY_ASSERT_MESSAGE(m_isBusy, "spectacular kill should be in progress when triggering the death blow");
	if (!m_isBusy)
		return;

	if (targetActor.IsDead())
		return;

	Vec3 targetDir = targetActor.GetEntity()->GetForwardDir();

	{
		HitInfo hitInfo;
		hitInfo.shooterId = m_pOwner->GetEntityId();
		hitInfo.targetId = targetActor.GetEntityId();
		hitInfo.damage = 99999.0f; // CERTAIN_DEATH
		hitInfo.dir = targetDir;
		hitInfo.normal = -hitInfo.dir; // this has to be in an opposite direction from the hitInfo.dir or the hit is ignored as a 'backface' hit
		hitInfo.type = CGameRules::EHitType::StealthKill;

		g_pGame->GetGameRules()->ClientHit(hitInfo);
	}

	// WARNING: RagDollize resets the entity's rotation!
	//  [7/30/2010 davidr] FixMe: If the entity isn't dead here (because is immortal or any other reason) ragdollizing it will
	// leave it on an inconsistent state (usually only reproducible on debug scenarios)
	targetActor.GetGameObject()->SetAspectProfile(eEA_Physics, eAP_Ragdoll);

	// Give a small nudge in the hit direction to make the target fall over
	const SSpectacularKillParams* pSpectacularKillParams = GetParamsForClass(targetActor.GetEntity()->GetClass());
	CRY_ASSERT(pSpectacularKillParams);
	if (pSpectacularKillParams && (pSpectacularKillParams->impulseScale > 0.0f) && (pSpectacularKillParams->impulseBone != -1))
	{
		const float killDeathBlowVelocity = pSpectacularKillParams->impulseScale; // desired velocity after impulse in meters per second

		IPhysicalEntity* pTargetPhysics = targetActor.GetEntity()->GetPhysics();
		if (pTargetPhysics)
		{
			pe_simulation_params simulationParams;
			pTargetPhysics->GetParams(&simulationParams);

			pe_action_impulse impulse;
			impulse.partid = pSpectacularKillParams->impulseBone;
			impulse.impulse = targetDir*killDeathBlowVelocity*simulationParams.mass; // RagDollize reset the entity's rotation so I have to use the value I cached earlier
			pTargetPhysics->Action(&impulse);
		}
	}

	m_deathBlowState = eDBS_Done;
}
void CPlayerStateFly::OnExit( CPlayer& player )
{
    player.CreateScriptEvent("printhud",0,"FlyMode/NoClip OFF");

    pe_player_dynamics simPar;

    IPhysicalEntity* piPhysics = player.GetEntity()->GetPhysics();
    if (!piPhysics || piPhysics->GetParams(&simPar) == 0)
        {
            return;
        }

    CPlayerStateUtil::PhySetNoFly( player, simPar.gravity );
}
Exemple #5
0
void CNetPlayerInput::UpdateInterpolation()
{
	Vec3 desiredPosition = m_curInput.position;
	Vec3 desiredVelocity = m_curInput.deltaMovement * g_pGameCVars->pl_netSerialiseMaxSpeed;

	// Use the physics pos as the entity position is a frame behind at this point
	IPhysicalEntity * pent = m_pPlayer->GetEntity()->GetPhysics();
	pe_status_pos psp;
	pent->GetStatus(&psp);
	Vec3 entPos = psp.pos;

	pe_status_living psl;
	psl.velGround.zero();
	pent->GetStatus(&psl);
	
	float dt = gEnv->pTimer->GetFrameTime();

	// New data?
	if (m_newInterpolation)
		m_lerper.AddNewPoint(m_curInput.position, desiredVelocity, entPos, m_curInput.standingOn);

	bool bInAirOrJumping = m_pPlayer->GetActorStats()->inAir > 0.01f || m_pPlayer->GetActorStats()->onGround < 0.01f;

	// Predict
	CNetLerper::SPrediction prediction;
	m_lerper.Update(gEnv->pTimer->GetFrameTime(), entPos, prediction, psl.velGround, bInAirOrJumping);

	// Update lerp velocity
	m_lerpVel = prediction.lerpVel;

	// Should Snap
	if (prediction.shouldSnap)
	{
		m_pPlayer->GetEntity()->SetPos(prediction.predictedPos);

		pe_action_set_velocity actionVel;
		actionVel.v = prediction.lerpVel;
		pent->Action(&actionVel);
	}

#if !defined(_RELEASE)
	// Debug Draw
	if (g_pGameCVars->pl_debugInterpolation)
		m_lerper.DebugDraw(prediction, entPos, m_newInterpolation);
	else
		SAFE_DELETE(m_lerper.m_debug);
#endif

	m_newInterpolation = false;
}
void CGameRealtimeRemoteUpdateListener::CameraSync()
{
	IGame *pGame = gEnv->pGame;
	if(!pGame)
		return;

	IGameFramework *pGameFramework=pGame->GetIGameFramework();
	if(!pGameFramework)
		return;

	IViewSystem *pViewSystem=pGameFramework->GetIViewSystem();	
	if(!pViewSystem)
		return;

	IView *pView=pViewSystem->GetActiveView();
	if(!pView)
		return;

	IEntity *pEntity = gEnv->pEntitySystem->GetEntity(pView->GetLinkedId());
	if(!pEntity)
		return;

	IActor *pPlayer=pGameFramework->GetClientActor();
	if ( !pPlayer )
		return;

	IEntity * pPlayerEntity = pPlayer->GetEntity();
	if (!pPlayerEntity)
		return;

	IPhysicalEntity * piPlayerPhysics = pPlayerEntity->GetPhysics();
	if ( !piPlayerPhysics )
		return;

	pe_player_dimensions dim;
	piPlayerPhysics->GetParams( &dim );

	//TODO: only GDCE2011, in the future make this game magic constant be gone in LiveCreate 2.0
	// game player view code has a complex position code path, the sync position should be
	// honoured by game code when live creaate camera sync is enabled
	m_Position.z -= 1.62f;
	pEntity->SetPos(m_Position);
	pPlayerEntity->Hide(false);
	pViewSystem->SetOverrideCameraRotation(true,Quat::CreateRotationVDir(m_ViewDirection));

	pPlayerEntity->Hide(true);
	SEntityUpdateContext ctx;
	pPlayer->Update( ctx, 0 );
	m_bCameraSync = true;
}
	void ResetVelocity(SActivationInfo* pActInfo)
	{
		IEntity* pGraphEntity = pActInfo->pEntity;
		if (pGraphEntity)
		{
			IPhysicalEntity* pPhysicalEntity = pGraphEntity->GetPhysics();
			if (pPhysicalEntity && pPhysicalEntity->GetType() != PE_STATIC)
			{
				pe_action_set_velocity setVel;
				setVel.v.zero();
				setVel.w.zero();
				pPhysicalEntity->Action(&setVel);
			}
		}
	}
Exemple #8
0
void CPlayerStateUtil::PhySetNoFly( CPlayer& player, const Vec3& gravity )
{
	IPhysicalEntity* pPhysEnt = player.GetEntity()->GetPhysics();
	if (pPhysEnt != NULL)
	{
		pe_player_dynamics pd;
		pd.kAirControl = player.GetAirControl();
		pd.kAirResistance = player.GetAirResistance();
		pd.bSwimming = false;
		pd.gravity = gravity;
		player.m_actorPhysics.gravity = gravity;

		pPhysEnt->SetParams(&pd);
	}
}
	virtual void ProcessEvent( EFlowEvent event, SActivationInfo *pActInfo )
	{
		switch (event)
		{
		case eFE_Initialize:
			pActInfo->pGraph->SetRegularlyUpdated( pActInfo->myID, true );
			m_Activated = false;
			break;

		case eFE_Update:
			{
				bool bReset = GetPortBool(pActInfo, IN_RESET);
				bool bCondition = GetPortBool(pActInfo, IN_CONDITION);

				if(bReset)
				{
					ActivateOutput(pActInfo, OUT_SLEEPING, !bCondition);
				} else
				{
					if(bCondition != m_Activated)
					{
						IEntity * pEntity = pActInfo->pEntity;

						if (pEntity)
						{
							IPhysicalEntity * pPhysEntity = pEntity->GetPhysics();

							if (pPhysEntity)
							{
								pe_status_awake psa;

								bool isSleeping = pPhysEntity->GetStatus( &psa ) ? false : true;

								ActivateOutput(pActInfo, OUT_SLEEPING, isSleeping);

								if(isSleeping)
									ActivateOutput(pActInfo, OUT_ONSLEEP, true);
								else
									ActivateOutput(pActInfo, OUT_ONAWAKE, true);
							}
						}

						m_Activated = bCondition;
					}
				}
			}
		}
	}
bool CCannonBall::RayTraceGeometry( const EventPhysCollision* pCollision, const Vec3& pos, const Vec3& hitDirection, SBackHitInfo* pBackHitInfo )
{
	FUNCTION_PROFILER(GetISystem(), PROFILE_GAME);

	bool exitPointFound = false;

	IPhysicalEntity* pCollider = pCollision->pEntity[1];
	assert(pCollider);

	pe_params_part partParams;
	partParams.partid = pCollision->partid[1];
	pe_status_pos posStatus;

	if (pCollider->GetParams(&partParams) && pCollider->GetStatus(&posStatus))
	{
		if (partParams.pPhysGeom && partParams.pPhysGeom->pGeom)
		{
			geom_world_data geomWorldData;
			geomWorldData.R = Matrix33(posStatus.q*partParams.q);
			geomWorldData.offset = posStatus.pos + (posStatus.q * partParams.pos);
			geomWorldData.scale = posStatus.scale * partParams.scale;

			geom_contact *pContacts;
			intersection_params intersectionParams;
			IGeometry* pRayGeometry = s_pRayWrapper->GetRay(pos, hitDirection);
			const Vec3 hitDirectionNormalized = hitDirection.GetNormalized();

			{ WriteLockCond lock; 
			const int contactCount = partParams.pPhysGeom->pGeom->IntersectLocked(pRayGeometry,&geomWorldData,0,&intersectionParams,pContacts,lock);
			if (contactCount > 0)
			{
				float bestDistance = 10.0f;
				
				for (int i = (contactCount-1); (i >= 0) && (pContacts[i].t < bestDistance) && ((pContacts[i].n*hitDirectionNormalized) < 0); i--)
				{
					bestDistance = (float)pContacts[i].t;
					pBackHitInfo->pt = pContacts[i].pt;
					exitPointFound = true;
				}
			}
			} // lock
		}
	}

	s_pRayWrapper->ResetRay();

	return exitPointFound;
}
Exemple #11
0
void CFists::RaiseWeapon(bool raise, bool faster /*= false*/)
{
	//Only when colliding something while running
	if(raise && (GetCurrentAnimState()==eFAS_RUNNING || GetCurrentAnimState()==eFAS_JUMPING) && !IsWeaponRaised())
	{
		if((m_fm && m_fm->IsFiring())||(m_melee && m_melee->IsFiring()))
			return;

		PlayAction(g_pItemStrings->raise);

		SetDefaultIdleAnimation( eIGS_FirstPerson,g_pItemStrings->idle_relaxed);
		SetWeaponRaised(true);

		//Also give the player some impulse into the opposite direction
		CActor *pPlayer = GetOwnerActor();
		Vec3		pos;
		if(pPlayer)
		{
			IPhysicalEntity* playerPhysics = pPlayer->GetEntity()->GetPhysics();
			if(playerPhysics)
			{
				IMovementController *pMC = pPlayer->GetMovementController();
				if(pMC)
				{
					SMovementState state;
					pMC->GetMovementState(state);
					
					pe_action_impulse impulse;
					impulse.iApplyTime = 1;
					impulse.impulse = -state.eyeDirection*600.0f;
					playerPhysics->Action(&impulse);

					pos = state.eyePosition + state.eyeDirection*0.5f;
				}
				
			}
		}

		GetScheduler()->TimerAction(GetCurrentAnimationTime(eIGS_FirstPerson), CSchedulerAction<EndRaiseWeaponAction>::Create(EndRaiseWeaponAction(this)), true);

		//Sound and FX feedback
		CollisionFeeback(pos,m_currentAnimState);
	}
	else if(!raise)
		SetWeaponRaised(false);

}
//------------------------------------------------------------------------
void CVehicleMovementTank::SetLatFriction(float latFric)
{
	// todo: do calculation per-wheel?
	IPhysicalEntity* pPhysics = GetPhysics();  
	int numWheels = m_pVehicle->GetWheelCount();    

	pe_params_wheel params;
	params.kLatFriction = latFric;

	for (int i=0; i<numWheels; ++i)
	{    
		params.iWheel = i;    
		pPhysics->SetParams(&params, THREAD_SAFE);
	}

	m_latFriction = latFric;
}
//------------------------------------------------------------------------
void CVehicleActionDeployRope::AttachOnRope(IEntity *pEntity)
{
	assert(pEntity);

	if(!pEntity)
		return;

	IRopeRenderNode *pRopeUpper = GetRopeRenderNode(m_ropeUpperId);

	if(!pRopeUpper)
		return;

	assert(pRopeUpper->GetPointsCount() >= 2);

	IPhysicalEntity *pRopePhys = pRopeUpper->GetPhysics();
	assert(pRopePhys);

	typedef std::vector <Vec3> TVec3Vector;
	TVec3Vector points;

	int pointCount;

	pe_status_rope ropeStatus;

	if(pRopePhys->GetStatus(&ropeStatus))
		pointCount = ropeStatus.nSegments + 1;
	else
		pointCount = 0;

	if(pointCount < 2)
		return;

	points.resize(pointCount);
	ropeStatus.pPoints = &points[0];

	if(pRopePhys->GetStatus(&ropeStatus))
	{
		Matrix34 worldTM;
		worldTM.SetIdentity();
		worldTM = Matrix33(m_pVehicle->GetEntity()->GetWorldTM());
		worldTM.SetTranslation(ropeStatus.pPoints[1]);
		pEntity->SetWorldTM(worldTM);
	}

	pRopeUpper->LinkEndEntities(m_pVehicle->GetEntity()->GetPhysics(), pEntity->GetPhysics());
}
void CRecoil::RecoilImpulse(const Vec3& firingPos, const Vec3& firingDir)
{
	if (m_recoilParams.impulse > 0.f)
	{
		EntityId id = (m_pWeapon->GetHostId()) ? m_pWeapon->GetHostId() : m_pWeapon->GetOwnerId();
		IEntity* pEntity = gEnv->pEntitySystem->GetEntity(id);
		IPhysicalEntity* pPhysicalEntity = pEntity ? pEntity->GetPhysics() : NULL;

		if (pPhysicalEntity)
		{        
			pe_action_impulse impulse;
			impulse.impulse = -firingDir * m_recoilParams.impulse; 
			impulse.point = firingPos;
			pPhysicalEntity->Action(&impulse);
		}
	}
}
void CIntersectionAssistanceUnit::DebugUpdate() const
{
    if(g_pGameCVars->pl_pickAndThrow.intersectionAssistDebugEnabled)
        {
            IEntity* pEntity = gEnv->pEntitySystem->GetEntity(m_subjectEntityId);
            if(pEntity)
                {
                    IPhysicalEntity *pPhysical = pEntity->GetPhysics();
                    if(pPhysical)
                        {
                            const float fFontSize = 1.2f;
                            float drawColor[4] = {1.0f, 1.0f, 1.0f, 1.0f};

                            string sMsg(string().Format(" Entity ID: [%d]", m_subjectEntityId));
                            sMsg += string().Format("\n Entity Name: [%s]", pEntity->GetName());

                            sMsg += string().Format("\n EmbedTimer: [%.3f]", m_embedTimer);
                            sMsg += string().Format("\n EmbedState: [%s]",(m_embedState == eES_None) ? "NONE" : (m_embedState == eES_Evaluating) ? "EVALUATING" : (m_embedState == eES_ReEvaluating) ? "REEVALUATING" : (m_embedState == eES_NotEmbedded) ? "NOT EMBEDDED" : (m_embedState == eES_Embedded) ? "EMBEDDED" : "UNKNOWN");

                            Vec3 vCurrTrans = m_entityStartingWPos - pEntity->GetWorldPos();
                            sMsg += string().Format("\n Translation: < %.3f, %.3f, %.3f >", vCurrTrans.x, vCurrTrans.y, vCurrTrans.z );
                            sMsg += string().Format("\n Trans magnitude: < %.3f >", vCurrTrans.GetLength() );
                            sMsg += string().Format("\n Trans per sec: < %.3f >", vCurrTrans.GetLength() / g_pGameCVars->pl_pickAndThrow.intersectionAssistTimePeriod );

                            sMsg += string().Format("\n Collision count: %u", m_collisionCount );

                            // RENDER
                            Vec3 vDrawPos = pEntity->GetWorldPos() + Vec3(0.0f,0.0f,0.6f);
                            gEnv->pRenderer->DrawLabelEx(vDrawPos, fFontSize, drawColor, true, true, sMsg.c_str());

                            // Box
                            pe_params_bbox bbox;
                            if(pPhysical->GetParams(&bbox))
                                {
                                    ColorB colDefault = ColorB( 127,127,127 );
                                    ColorB embedded = ColorB(255, 0, 0);
                                    ColorB notEmbedded = ColorB(0, 255, 0);

                                    gEnv->pRenderer->GetIRenderAuxGeom()->DrawAABB( AABB(bbox.BBox[0],bbox.BBox[1]), Matrix34(IDENTITY), false, (m_embedState == eES_Embedded) ? embedded : (m_embedState == eES_NotEmbedded) ? notEmbedded : colDefault, eBBD_Faceted);
                                }
                        }
                }

        }
}
//------------------------------------------------------------------------
void CVehicleMovementHelicopter::Physicalize()
{
	CVehicleMovementBase::Physicalize();

	IPhysicalEntity * pPhysicalEntity = GetPhysics();

	pe_params_flags pf;
	pf.flagsOR = pef_ignore_areas;
	pPhysicalEntity->SetParams(&pf);

	pe_simulation_params simParams;
	simParams.iSimClass = SC_ACTIVE_RIGID;
	simParams.damping = 0.0f;
	simParams.dampingFreefall = 0.0f;
	simParams.gravity = Vec3(0.0f, 0.0f, 0.0f);
	simParams.minEnergy = 0.0f;
	pPhysicalEntity->SetParams(&simParams);
}
void CLocalPlayerComponent::UpdateStumble( const float frameTime )
{
	IEntity * pEntity = m_rPlayer.GetEntity();

	IPhysicalEntity * pPhysEntity = pEntity->GetPhysics();

	if ( pPhysEntity )
	{
		pe_status_dynamics dynamics;
		pPhysEntity->GetStatus( &dynamics );
		if ( m_playerStumble.Update( frameTime, dynamics ) )
		{
			pe_action_impulse ai; 
			ai.impulse = m_playerStumble.GetCurrentActionImpulse();
			pPhysEntity->Action( &ai );
		}
	}
}
//------------------------------------------------------------------------
void CVehicleActionEntityAttachment::Update(const float deltaTime)
{
	if(m_isAttached)
		return;

	IEntitySystem *pEntitySystem = gEnv->pEntitySystem;
	assert(pEntitySystem);

	IEntity *pEntity = pEntitySystem->GetEntity(m_entityId);

	if(!pEntity)
		return;

	IPhysicalEntity *pPhysEntity = pEntity->GetPhysics();

	if(!pPhysEntity)
		return;

	pe_simulation_params paramsSim;
	float gravity;

	if(pPhysEntity->GetParams(&paramsSim))
		gravity = abs(paramsSim.gravity.z);
	else
		gravity = 9.82f;

	pe_status_dynamics dyn;

	if(pPhysEntity->GetStatus(&dyn))
	{
		pe_action_impulse impulse;
		impulse.impulse  = Matrix33(pEntity->GetWorldTM()) * Vec3(0.0f, 0.0f, 1.0f) * g_parachuteForce * gravity;
		impulse.impulse = impulse.impulse - dyn.v;
		impulse.impulse *= dyn.mass * deltaTime;
		impulse.iSource = 3;

		pPhysEntity->Action(&impulse);
	}

	m_timer -= deltaTime;

	if(m_timer <= 0.0f || dyn.v.z >= 0.0f)
		m_pVehicle->SetObjectUpdate(this, IVehicle::eVOU_NoUpdate);
}
Exemple #19
0
void CPlayerInput::GetState( SSerializedPlayerInput& input )
{
	SMovementState movementState;
	m_pPlayer->GetMovementController()->GetMovementState( movementState );

	Quat worldRot = m_pPlayer->GetBaseQuat();
	input.stance = FigureOutStance();
	
	// PLAYERPREDICTION
  	if (g_pGameCVars->pl_serialisePhysVel)
  	{
    	//--- Serialise the physics vel instead, velocity over the NET_SERIALISE_PLAYER_MAX_SPEED will be clamped by the network so no guards here
    	IPhysicalEntity* pEnt = m_pPlayer->GetEntity()->GetPhysics();
    	if (pEnt)
    	{
      		pe_status_dynamics dynStat;
      		pEnt->GetStatus(&dynStat);

      		input.deltaMovement = dynStat.v / g_pGameCVars->pl_netSerialiseMaxSpeed;
      		input.deltaMovement.z = 0.0f;
    	}
  	}
  	else
  	{
	  	input.deltaMovement = worldRot.GetNormalized() * m_filteredDeltaMovement;
	  	// ensure deltaMovement has the right length
	  	input.deltaMovement = input.deltaMovement.GetNormalizedSafe(ZERO) * m_filteredDeltaMovement.GetLength();
  	}
	// ~PLAYERPREDICTION
	
	input.sprint = (((m_actions & ACTION_SPRINT) != 0) && !m_pPlayer->m_stats.bIgnoreSprinting);
	input.usinglookik = true;
	input.aiming = true;
	input.leanl = (m_actions & ACTION_LEANLEFT) != 0;
	input.leanr = (m_actions & ACTION_LEANRIGHT) != 0;
	input.lookDirection = movementState.eyeDirection;
	
	// PLAYERPREDICTION
	input.bodyDirection = movementState.entityDirection;
	// ~PLAYERPREDICTION

	m_lastPos = movementState.pos;
}
Exemple #20
0
void CDeflectorShield::ProcessCollision(const EventPhysCollision& pCollision)
{
	int id = 0;
	IPhysicalEntity* pTarget = pCollision.pEntity[id];
	if (pTarget == GetEntity()->GetPhysics())
	{
		id = 1;
		pTarget = pCollision.pEntity[id];
	}

	IEntity* pTargetEntity = (IEntity*)pTarget->GetForeignData(PHYS_FOREIGN_ID_ENTITY);
	if (pTargetEntity == 0)
		return;

	CProjectile* pProjectile = g_pGame->GetWeaponSystem()->GetProjectile(pTargetEntity->GetId());

	if (pProjectile)
		ProcessProjectile(pProjectile, pCollision.pt, pCollision.n, pCollision.vloc[id].GetNormalized());
}
Exemple #21
0
void CPlayerStateSwim::OnEnter( CPlayer& player )
{
	player.m_playerStateSwim_WaterTestProxy.OnEnterWater(player);
	
	IPhysicalEntity* pPhysEnt = player.GetEntity()->GetPhysics();
	if (pPhysEnt != NULL)
	{
		// get current gravity before setting to zero.
		pe_player_dynamics simPar;
		if( pPhysEnt->GetParams(&simPar) != 0 )
		{
			m_gravity = simPar.gravity;
		}
		CPlayerStateUtil::PhySetFly( player );
	}

	m_lastWaterLevel = player.m_playerStateSwim_WaterTestProxy.GetWaterLevel();
	m_lastWaterLevelTime = player.m_playerStateSwim_WaterTestProxy.GetWaterLevelTimeUpdated();

	player.m_stats.inAir = 0.0f;

	if (player.IsClient())
	{
		ICameraMode::AnimationSettings animationSettings;
		animationSettings.positionFactor = 1.0f;
		animationSettings.rotationFactor = GetSwimParams().m_stateSwim_animCameraFactor;
		
		player.GetPlayerCamera()->SetCameraModeWithAnimationBlendFactors( eCameraMode_PartialAnimationControlled, animationSettings, "Entering swim state" );
		player.SendMusicLogicEvent(eMUSICLOGICEVENT_PLAYER_SWIM_ENTER);

		if (!player.IsCinematicFlagActive(SPlayerStats::eCinematicFlag_HolsterWeapon))
			player.HolsterItem(true);

		if (gEnv->bMultiplayer)	// any left hand holding in SP?
		{
			player.HideLeftHandObject(true);
		}
	}

	// Record 'Swim' telemetry stats.
	CStatsRecordingMgr::TryTrackEvent(&player, eGSE_Swim, true);
}
Exemple #22
0
//------------------------------------------------------------------------
int CScriptBind_Actor::IsFlying(IFunctionHandler *pH)
{
	CActor *pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();

	if (pActor)
	{
		pe_status_living livStat;
		IPhysicalEntity *pPhysEnt = pActor->GetEntity()->GetPhysics();

		if (!pPhysEnt)
			return pH->EndFunction();

		if(pPhysEnt->GetStatus(&livStat))
			return pH->EndFunction(livStat.bFlying!=0);
	}

	return pH->EndFunction();
}
void CPlayerStateFly::OnEnter( CPlayer& player )
{
    pe_player_dynamics simPar;

    IPhysicalEntity* piPhysics = player.GetEntity()->GetPhysics();
    if (!piPhysics || piPhysics->GetParams(&simPar) == 0)
        {
            return;
        }

    player.m_actorPhysics.velocity = player.m_actorPhysics.velocityUnconstrained.Set(0,0,0);
    player.m_actorPhysics.speed = player.m_stats.speedFlat = 0.0f;
    player.m_actorPhysics.groundMaterialIdx = -1;
    player.m_actorPhysics.gravity = simPar.gravity;

    player.m_stats.fallSpeed = 0.0f;
    player.m_stats.inFiring = 0;

    CPlayerStateUtil::PhySetFly( player );
}
Exemple #24
0
void CBaseGrabHandler::IgnoreCollision(EntityId eID,unsigned int flags,bool ignore)
{
	IEntity *pGrab = gEnv->pEntitySystem->GetEntity(eID);
	IPhysicalEntity *ppGrab = pGrab ? pGrab->GetPhysics() : NULL;

	if(!ppGrab) return;

	if(ignore)
	{
		// NOTE Dez 14, 2006: <pvl> this whole block just fills in
		// a request structure and passes it to physics
		IEntity *pEnt = m_pActor->GetEntity();

		pe_action_add_constraint ac;
		ac.flags = constraint_inactive|constraint_ignore_buddy;
		ac.pBuddy = pEnt->GetPhysics();
		ac.pt[0].Set(0,0,0);

		ICharacterInstance *pCharacter = pEnt->GetCharacter(0);
		IPhysicalEntity *pPhysEnt = pCharacter?pCharacter->GetISkeletonPose()->GetCharacterPhysics(-1):NULL;

		if(pPhysEnt)
		{
			pe_simulation_params sp;
			pPhysEnt->GetParams(&sp);

			if(sp.iSimClass <= 2)
				ac.pBuddy = pPhysEnt;
		}

		ppGrab->Action(&ac);
	}
	else
	{
		// NOTE Dez 14, 2006: <pvl> the same as the other branch - just
		// fill in a request and pass it to the physics engine
		pe_action_update_constraint uc;
		uc.bRemove = 1;

		ppGrab->Action(&uc);
	}

	// NOTE Dez 14, 2006: <pvl> flag manipulation is basically a legacy
	// code - probably not used anymore, scheduled for removal.
	if(flags)
	{
		pe_params_part pp;
		pp.flagsAND = pp.flagsColliderAND = ~flags;
		pp.flagsOR = pp.flagsColliderOR = flags * (ignore?0:1);

		pe_status_nparts status_nparts;

		for(pp.ipart = ppGrab->GetStatus(&status_nparts)-1; pp.ipart>=0; pp.ipart--)
			ppGrab->SetParams(&pp);
	}
}
bool CStickyProjectile::IsValid() const
{
	if (!IsStuck())
		return false;

	if(m_parentId == 0)
		return true;

	pe_params_part part;
	part.partid = m_stuckPartId;
	IEntity* pEntity = gEnv->pEntitySystem->GetEntity(m_parentId);
	if(pEntity)
	{
		if (pEntity->IsHidden())
		{
			return false;
		}
		if(ICharacterInstance* pCharacter = pEntity->GetCharacter(0))
		{
			if(ISkeletonPose* pSkel = pCharacter->GetISkeletonPose())
			{
				IPhysicalEntity* pSkelPhysics = pSkel->GetCharacterPhysics();
				if (pSkelPhysics)
				{
					return pSkelPhysics->GetParams(&part) != 0;
				}
			}
		}
		else
		{
			IPhysicalEntity* pPhysics = pEntity->GetPhysics();
			if (pPhysics)
			{
				return pPhysics->GetParams(&part) != 0;
			}
		}
	}

	return false;
}
int CVehicleMovementAerodynamic::AddBox(Vec3 *_pvPos,Vec3 *_pvSize,float _fMass,int _iID/*=-1*/)
{
  IPhysicalEntity* pPhysics = GetPhysics();
	IGeomManager *pGeomManager = gEnv->pPhysicalWorld->GetGeomManager();

	primitives::box Box;
	Box.Basis.SetIdentity();
	Box.center.Set(0.0f,0.0f,0.0f);
	Box.size = (*_pvSize) / 2.0f;
	Box.bOriented = 0;
	IGeometry *pGeometry = pGeomManager->CreatePrimitive(primitives::box::type,&Box);
	phys_geometry *pPhysGeometry = pGeomManager->RegisterGeometry(pGeometry);
	pGeometry->Release();

	pe_geomparams partpos;
	partpos.pos = *_pvPos;
	partpos.mass = _fMass;
	int id = pPhysics->AddGeometry(pPhysGeometry,&partpos,_iID);

	pGeomManager->UnregisterGeometry(pPhysGeometry);

  return id;
}
Exemple #27
0
void CLivingEntitySample::OnPrePhysicsUpdate()
{
	IEntity* pEntity = GetEntity();
	IPhysicalEntity* pPhysEntity = pEntity->GetPhysics();
	if ( pPhysEntity == NULL )
	{
		return;
	}

	// The desired speed is chosen with a value within the motion capabilities 
	// of the walk animation used for this sample.
	const float desiredSpeed = 1.5f;

	const Vec3 desiredLocalDirection = CalculateDesiredLocalDirection();
	const Vec3 desiredLocalVelocity = desiredLocalDirection * desiredSpeed;

	const Quat worldOrientation = pEntity->GetWorldRotation();
	const Vec3 desiredWorldVelocity = worldOrientation * desiredLocalVelocity;

	pe_action_move pam;
	pam.dir = desiredWorldVelocity;
	
	pPhysEntity->Action( &pam );
}
//////////////////////////////////////////////////////////////////////////
// IsMountedWeaponUsableWithTarget
// A piece of game-code moved from CryAction when scriptbind_AI moved to the AI system
//////////////////////////////////////////////////////////////////////////
int CScriptBind_Game::IsMountedWeaponUsableWithTarget(IFunctionHandler *pH)
{
	int paramCount = pH->GetParamCount();
	if(paramCount<2)
	{
		GameWarning("%s: too few parameters.", __FUNCTION__);
		return pH->EndFunction();
	}

	GET_ENTITY(1);

	if(!pEntity)
	{
		GameWarning("%s: wrong entity id in parameter 1.", __FUNCTION__);
		return pH->EndFunction();
	}

	IAIObject* pAI = pEntity->GetAI();
	if (!pAI)
	{
		GameWarning("%s: Entity '%s' does not have AI.",__FUNCTION__,  pEntity->GetName());
		return pH->EndFunction();
	}

	EntityId itemEntityId;
	ScriptHandle hdl2;

	if(!pH->GetParam(2,hdl2))
	{
		GameWarning("%s: wrong parameter 2 format.", __FUNCTION__);
		return pH->EndFunction();
	}

	itemEntityId = (EntityId)hdl2.n;

	if (!itemEntityId)
	{
		GameWarning("%s: wrong entity id in parameter 2.", __FUNCTION__);
		return pH->EndFunction();
	}
	
	IGameFramework *pGameFramework = gEnv->pGame->GetIGameFramework();
	IItem* pItem = pGameFramework->GetIItemSystem()->GetItem(itemEntityId);
	if (!pItem)
	{
		//gEnv->pAISystem->Warning("<CScriptBind> ", "entity in parameter 2 is not an item/weapon");
		GameWarning("%s: entity in parameter 2 is not an item/weapon.", __FUNCTION__);
		return pH->EndFunction();
	}

	float minDist = 7;
	bool bSkipTargetCheck = false;
	Vec3 targetPos(ZERO);

	if(paramCount > 2)
	{
		for(int i=3;i <= paramCount ; i++)
		{
			if(pH->GetParamType(i) == svtBool)
				pH->GetParam(i,bSkipTargetCheck);
			else if(pH->GetParamType(i) == svtNumber)
				pH->GetParam(i,minDist);
			else if(pH->GetParamType(i) == svtObject)
				pH->GetParam(i,targetPos);
		}
	}

	IAIActor* pAIActor = CastToIAIActorSafe(pAI);
	if (!pAIActor)
	{
		GameWarning("%s: entity '%s' in parameter 1 is not an AI actor.", __FUNCTION__, pEntity->GetName());
		return pH->EndFunction();
	}


	IEntity* pItemEntity = pItem->GetEntity();
	if(!pItemEntity)
		return pH->EndFunction();


	if(!pItem->GetOwnerId())
	{
		// weapon is not used, check if it is on a vehicle
		IEntity* pParentEntity = pItemEntity->GetParent();
		if(pParentEntity)
		{
			IAIObject* pParentAI = pParentEntity->GetAI();
			if(pParentAI && pParentAI->GetAIType()==AIOBJECT_VEHICLE)
			{
				// (MATT) Feature was cut and code was tricky, hence ignore weapons in vehicles  {2008/02/15:11:08:51}
				return pH->EndFunction();
			}
		}
	}
	else if( pItem->GetOwnerId()!= pEntity->GetId()) // item is used by someone else?
		return pH->EndFunction(false);

	// check target
	if(bSkipTargetCheck)
		return pH->EndFunction(true);

	IAIObject* pTarget = pAIActor->GetAttentionTarget();
	if(targetPos.IsZero())
	{
		if(!pTarget)
			return pH->EndFunction();
		targetPos = pTarget->GetPos();
	}

	Vec3 targetDir(targetPos - pItemEntity->GetWorldPos());
	Vec3 targetDirXY(targetDir.x, targetDir.y, 0);

	float length2D = targetDirXY.GetLength();
	if(length2D < minDist || length2D<=0)
		return pH->EndFunction();

	targetDirXY /= length2D;//normalize

	IWeapon* pWeapon = pItem->GetIWeapon(); 
	bool vehicleGun = pWeapon && pWeapon->GetHostId();

	if (!vehicleGun)
	{
		Vec3 mountedAngleLimits(pItem->GetMountedAngleLimits());

		float yawRange = DEG2RAD(mountedAngleLimits.z);
		if(yawRange > 0 && yawRange < gf_PI)
		{
			float deltaYaw = pItem->GetMountedDir().Dot(targetDirXY);
			if(deltaYaw < cosf(yawRange))
				return pH->EndFunction(false);
		}

		float minPitch = DEG2RAD(mountedAngleLimits.x);
		float maxPitch = DEG2RAD(mountedAngleLimits.y);

		//maxPitch = (maxPitch - minPitch)/2;
		//minPitch = -maxPitch;

		float pitch = atanf(targetDir.z / length2D);

		if ( pitch < minPitch || pitch > maxPitch )
			return pH->EndFunction(false);
	}

	if(pTarget)
	{
		IEntity* pTargetEntity = pTarget->GetEntity();
		if(pTargetEntity)
		{
			// check target distance and where he's going
			IPhysicalEntity *phys = pTargetEntity->GetPhysics();
			if(phys)
			{
				pe_status_dynamics	dyn;
				phys->GetStatus(&dyn);
				Vec3 velocity ( dyn.v);
				velocity.z = 0;

				float speed = velocity.GetLength2D();
				if(speed>0)
				{
					//velocity /= speed;
					if(length2D< minDist * 0.75f && velocity.Dot(targetDirXY)<=0)
						return pH->EndFunction(false);
				}
			}
		}
	}
	return pH->EndFunction(true);

}
//////////////////////////////////////////////////////////////////////////
// NOTE: This function must be thread-safe. Before adding stuff contact MarcoC.
void CVehicleMovementHelicopter::ProcessMovement(const float deltaTime)
{
	FUNCTION_PROFILER( GetISystem(), PROFILE_GAME );

	IPhysicalEntity* pPhysics = GetPhysics();
	assert(pPhysics);
	
	if (m_arcade.m_handling.maxSpeedForward>0.f) // Use the new handling code
	{
		CryAutoCriticalSection lk(m_lock);

		if (!m_isEnginePowered)
			return;

		CVehicleMovementBase::ProcessMovement(deltaTime);
		SVehiclePhysicsStatus* physStatus = &m_physStatus[k_physicsThread];

		if(m_bApplyNoiseAsVelocity)
		{
			physStatus->v -= m_pNoise->m_posDifference;
			physStatus->w -= m_pNoise->m_angDifference;

			m_pNoise->Update(deltaTime);
		}

	
		///////////////////////////////////////////////////////////////
		// Pass on the movement request to the active physics handler
		// NB: m_physStatus is update by this call
		SVehiclePhysicsHelicopterProcessParams params;
		params.pPhysics = pPhysics;
		params.pPhysStatus = physStatus;
		params.pInputAction = &m_inputAction;
		params.dt = deltaTime;
		params.haveDriver = (m_actorId!=0)||m_remotePilot;
		params.isAI = m_movementAction.isAI;
		params.aiRequiredVel = m_CurrentVel;
		
		m_arcade.ProcessMovement(params);
		
		// Network error adjustment
		m_netPosAdjust *= max(0.f, 1.f-deltaTime*k_netErrorPosScale);
		physStatus->v += m_netPosAdjust * k_netErrorPosScale;

		if(m_bApplyNoiseAsVelocity)
		{
			physStatus->v += m_pNoise->m_posDifference;
			physStatus->w += m_pNoise->m_angDifference;
		}

		//===============================================
		// Commit the velocity back to the physics engine
		//===============================================
		// if (fabsf(m_movementAction.rotateYaw)>0.05f || vel.GetLengthSquared()>0.001f || m_chassis.vel.GetLengthSquared()>0.001f || angVel.GetLengthSquared()>0.001f || angVel.GetLengthSquared()>0.001f) 
		{
			pe_action_set_velocity setVelocity;
			setVelocity.v = physStatus->v;
			setVelocity.w = physStatus->w;
			pPhysics->Action(&setVelocity, 1);
		}
		///////////////////////////////////////////////////////////////
	}
	else
	{
		if (m_isEnginePowered && pPhysics)
		{
			m_movementAction.isAI = true;
	
			pe_status_pos psp;
			pe_status_dynamics psd;
			if (!pPhysics->GetStatus(&psp) || !pPhysics->GetStatus(&psd))
				return;
			UpdatePhysicsStatus(&m_physStatus[k_physicsThread], &psp, &psd);

			ProcessAI(deltaTime);
		}
	}
}
void CVehicleMovementHelicopter::ProcessAI(const float deltaTime)
{
	FUNCTION_PROFILER( GetISystem(), PROFILE_GAME );

	CryAutoCriticalSection lk(m_lock);
	SVehiclePhysicsStatus* physStatus = &m_physStatus[k_physicsThread];
		
	if (m_arcade.m_handling.maxSpeedForward>0.f) // Use the new handling code
	{
		//ResetActions();
		m_movementAction.Clear();
		m_movementAction.isAI = true;

		SVehiclePhysicsHelicopterProcessAIParams params;
		params.pPhysStatus = physStatus;
		params.pInputAction = &m_inputAction;
		params.pAiRequest = &m_aiRequest;
		params.dt = deltaTime;
		params.aiRequiredVel = m_CurrentVel;
		params.aiCurrentSpeed = m_CurrentSpeed;
		params.aiYawResponseScalar = m_yawResponseScalar;
		m_yawResponseScalar = 1.f;
	
		// Use helper class to process the AI input
		// It will return a requested velocity, and change the input
		m_arcade.ProcessAI(params);

		// Get the output velocity
		m_CurrentVel = params.aiRequiredVel;
		m_CurrentSpeed = params.aiCurrentSpeed;
		return;
	}
	////////////////////// OLD DEPRECATED CODE :( //////////////////////////////////

	m_movementAction.Clear();
	ResetActions();

	// Our current state
	const Vec3 worldPos =  physStatus->pos;
	const Matrix33 worldMat( physStatus->q);
	const Matrix33 localMat( physStatus->q.GetInverted());
	const Ang3 worldAngles = Ang3::GetAnglesXYZ(worldMat);
	const Ang3 localAngles = Ang3::GetAnglesXYZ(localMat);

	const Vec3 currentVel = physStatus->v;
	const Vec3 currentVel2D(currentVel.x, currentVel.y, 0.0f);
	m_CurrentSpeed = m_CurrentVel.len(); //currentVel.len();
  float currentSpeed2d = currentVel2D.len();

	// +ve direction mean rotation anti-clocwise about the z axis - 0 means along y
	float currentDir = worldAngles.z;

	// to avoid singularity
	const Vec3 vWorldDir = worldMat.GetRow(1);
	const Vec3 vSideWays = worldMat.GetRow(0);
	const Vec3 vWorldDir2D =  Vec3( vWorldDir.x,  vWorldDir.y, 0.0f ).GetNormalizedSafe();

	// Our inputs
	float desiredSpeed = m_aiRequest.HasDesiredSpeed() ? m_aiRequest.GetDesiredSpeed() : 0.0f;
	Limit(desiredSpeed, -m_maxSpeed, m_maxSpeed);

	const Vec3 desiredMoveDir = m_aiRequest.HasMoveTarget() ? (m_aiRequest.GetMoveTarget() - worldPos).GetNormalizedSafe() : vWorldDir;
	Vec3 desiredMoveDir2D = Vec3(desiredMoveDir.x, desiredMoveDir.y, 0.0f);
	desiredMoveDir2D = desiredMoveDir2D.GetNormalizedSafe(desiredMoveDir2D);

	const Vec3 desiredVel = desiredMoveDir * desiredSpeed; 
	const Vec3 desiredVel2D(desiredVel.x, desiredVel.y, 0.0f);

  Vec3 desiredLookDir(desiredMoveDir);

  if (m_aiRequest.HasDesiredBodyDirectionAtTarget())
  {
	    desiredLookDir = m_aiRequest.GetDesiredBodyDirectionAtTarget().GetNormalizedSafe(desiredMoveDir);
  }
  else if (m_aiRequest.HasLookTarget())
  {
    desiredLookDir = (m_aiRequest.GetLookTarget() - worldPos).GetNormalizedSafe(desiredMoveDir);  
  }


	//const Vec3 desiredLookDir = m_aiRequest.HasLookTarget() ? (m_aiRequest.GetLookTarget() - worldPos).GetNormalizedSafe() : desiredMoveDir;
	const Vec3 desiredLookDir2D = Vec3(desiredLookDir.x, desiredLookDir.y, 0.0f).GetNormalizedSafe(vWorldDir2D);

  Vec3 prediction = m_aiRequest.HasBodyTarget() ? m_aiRequest.GetBodyTarget() : ZERO;

  prediction = (prediction.IsEquivalent(ZERO)) ? desiredMoveDir2D : prediction - worldPos;
  prediction.z = 0.0f;

  float speedLimit = prediction.GetLength2D();

	if(speedLimit > 0.0f)
	{
		prediction *= 1.0f / speedLimit;
	}

  Vec3 tempDir = currentVel2D.IsEquivalent(ZERO) ? localMat.GetRow(1) : currentVel2D;
  tempDir.z = 0.0f;
  tempDir.NormalizeFast();

	float dotProd = tempDir.dot(prediction);
	Limit(dotProd, FLT_EPSILON, 1.0f);

	float accel = m_enginePowerMax * min(2.0f,  1.0f / dotProd); // * dotProd;

	if (!m_aiRequest.HasDesiredBodyDirectionAtTarget())
	{
		dotProd *= dotProd;
		dotProd *= dotProd;
		float tempf = min(max(speedLimit * speedLimit, 2.0f), m_maxSpeed * dotProd);
		Limit(desiredSpeed, -tempf, tempf);
	}
	else if (dotProd < 0.0125f)
	{
		Limit(desiredSpeed, -m_maxSpeed * 0.25f, m_maxSpeed * 0.25f);
	}
  
  float posNeg = (float)__fsel(desiredSpeed - m_CurrentSpeed, 1.0f, -5.0f);

  if (desiredVel2D.GetLengthSquared() > FLT_EPSILON)
  {
	  m_CurrentSpeed = m_CurrentSpeed + posNeg * accel * deltaTime;
  }
  else
  {
    m_CurrentSpeed = m_CurrentSpeed + posNeg * accel * deltaTime;
  }

	if (posNeg > 0.0f && m_CurrentSpeed > desiredSpeed)
	{
		m_CurrentSpeed = desiredSpeed;
	}
	else if (posNeg < 0.0f && m_CurrentSpeed < desiredSpeed)
	{
		m_CurrentSpeed = desiredSpeed;
	}

	
	// ---------------------------- Rotation ----------------------------
	
	float desiredDir = (desiredLookDir2D.GetLengthSquared() > 0.0f) ? atan2f(-desiredLookDir2D.x, desiredLookDir2D.y) : atan2f(-vWorldDir2D.x, vWorldDir2D.y);
	while (currentDir < desiredDir - gf_PI)
		currentDir += 2.0f * gf_PI;
	while (currentDir > desiredDir + gf_PI)
		currentDir -= 2.0f * gf_PI;

	// ---------------------------- Yaw ----------------------------

	Ang3 dirDiff(0.0f, 0.0f, desiredDir - currentDir);
	dirDiff.RangePI();
	float absDiff   = fabsf(dirDiff.z);

	float rotSpeed		= (float)__fsel(dirDiff.z, m_yawPerRoll, -m_yawPerRoll);
	m_actionYaw		= m_actionYaw + deltaTime * (rotSpeed - m_actionYaw);

	float temp = fabsf(m_actionYaw);

	float multiplier = ((absDiff / (temp + 0.001f)) + 1.0f) * 0.5f;
	
	m_actionYaw	*= (float)__fsel(absDiff - temp, 1.0f, multiplier);

	// ---------------------------- Yaw ------------------------------

	m_CurrentVel = desiredMoveDir * m_CurrentSpeed;

  // ---------------------------- Pitch ----------------------------

  if (m_CurrentVel.GetLengthSquared2D() > 0.1f)
  {
    CalculatePitch(worldAngles, desiredMoveDir, currentSpeed2d, desiredSpeed, deltaTime);
  }
  else
  {
    Quat rot;
    rot.SetRotationVDir(desiredLookDir, 0.0f);
    float desiredXRot = Ang3::GetAnglesXYZ(rot).x + m_steeringDamage.x;

    m_actionPitch = worldAngles.x + (desiredXRot - worldAngles.x) * deltaTime/* * 10.0f*/;
    Limit(m_actionPitch, -m_maxPitchAngle * 2.0f, m_maxPitchAngle * 2.0f);
  }


	// ---------------------------- Roll ----------------------------
	float rollSpeed = GetRollSpeed();

	rollSpeed *= deltaTime;
	rollSpeed		= (float)__fsel(absDiff - rollSpeed, rollSpeed, absDiff);
	float roll		=(float) __fsel(dirDiff.z, -rollSpeed, rollSpeed);

	float speedPerUnit	   = 1.5f;
	float desiredRollSpeed = absDiff * speedPerUnit * (float)__fsel(dirDiff.z, 1.0f, -1.0f);
  
	desiredRollSpeed = -m_actionYaw * 2.5f;
  desiredRollSpeed += m_steeringDamage.y;

	m_actionRoll = m_actionRoll + deltaTime * (desiredRollSpeed - m_actionRoll);
	Limit(m_actionRoll, -m_maxRollAngle + m_steeringDamage.y, m_maxRollAngle - m_steeringDamage.y);
	m_actionRoll *= m_rollDamping;
	// ---------------------------- Roll ----------------------------


	// ---------------------------- Convert and apply ----------------------------
	Ang3 angles(m_actionPitch, m_actionRoll, worldAngles.z + deltaTime * m_actionYaw);
	
	pe_params_pos paramPos;
	paramPos.q.SetRotationXYZ(angles);
	paramPos.q.Normalize();

	IPhysicalEntity * pPhysicalEntity = GetPhysics();
	pPhysicalEntity->SetParams(&paramPos, 1);

	pe_action_set_velocity vel;
	vel.v = m_CurrentVel + m_netPosAdjust;
	pPhysicalEntity->Action(&vel, 1);

	// ---------------------------- Convert and apply ----------------------------

  m_rpmScale = max(0.2f, cry_fabsf(m_CurrentSpeed / m_maxSpeed));
}