//------------------------------------------------------------------------------------
// Adjust the aim dir before we pass it to the torsoAim pose modifier, this allows us
// to have the weapon deviate from the camera in certain circumstances
// Should only be called once per frame as it time-steps internal vars
//------------------------------------------------------------------------------------
void CLocalPlayerComponent::AdjustTorsoAimDir(float fFrameTime, Vec3 &aimDir)
{
	const f32 HALF_PI = gf_PI * 0.5f;
	float newElevLimit = HALF_PI;

	const f32 MIN_FLATTEN_LEVEL		= -0.3f;
	const f32 MAX_FLATTEN_LEVEL		= -0.1f;
	const f32 TARGET_FLATTEN_ELEV	= -0.2f;
	const f32 LIMIT_CHANGE_RATE		= HALF_PI;

	if (g_pGameCVars->pl_swimAlignArmsToSurface && m_rPlayer.IsSwimming() && (m_rPlayer.m_playerStateSwim_WaterTestProxy.GetRelativeWaterLevel() > MIN_FLATTEN_LEVEL))
	{
		newElevLimit = (m_rPlayer.m_playerStateSwim_WaterTestProxy.GetRelativeWaterLevel() - MIN_FLATTEN_LEVEL) / (MAX_FLATTEN_LEVEL - MIN_FLATTEN_LEVEL);
		newElevLimit = LERP(gf_PI * 0.5f, TARGET_FLATTEN_ELEV, clamp_tpl(newElevLimit, 0.0f, 1.0f));
	}

	float limitDelta = LIMIT_CHANGE_RATE * fFrameTime;
	float limitDiff	 = newElevLimit - m_stapElevLimit;
	float smoothedLimit = (float) fsel(fabs_tpl(limitDiff) - limitDelta, m_stapElevLimit + (fsgnf(limitDiff) * limitDelta), newElevLimit);
	m_stapElevLimit = smoothedLimit;

	if (smoothedLimit < HALF_PI)
	{
		//--- Need to limit, convert to yaw & elev, limit & then convert back
		float yaw, elev;
		float xy = aimDir.GetLengthSquared2D();
		if (xy > 0.001f)
		{
			yaw = atan2_tpl(aimDir.y,aimDir.x);
			elev = asin_tpl(clamp_tpl(aimDir.z, -1.f, +1.f));
		}
		else
		{
			yaw = 0.f;
			elev = (float)fsel(aimDir.z, +1.f, -1.f) * (gf_PI*0.5f);
		}

		elev = min(elev, smoothedLimit);

		float sinYaw, cosYaw;
		float sinElev, cosElev;

		sincos_tpl(yaw, &sinYaw, &cosYaw);
		sincos_tpl(elev, &sinElev, &cosElev);

		aimDir.x = cosYaw * cosElev;
		aimDir.y = sinYaw * cosElev;
		aimDir.z = sinElev;
	}
}
Exemplo n.º 2
0
void CPlayerRotation::ProcessTargetAssistance( IItem* pCurrentPlayerItem )
{
	// aim assistance
	float targetAimAssistAngleFollowH;
	float targetAimAssistAngleFollowV;
	float targetAimAssistAngleScale;

	IPlayerInput * pIPlayerInput = m_player.GetPlayerInput();
	float absInput = 0.0f;

	float aimAssistPowerFactor = 1.0f;
	bool isUsingDedicatedInput = gEnv->IsDedicated();

#if (USE_DEDICATED_INPUT)
	isUsingDedicatedInput |= g_pGameCVars->g_playerUsesDedicatedInput ? true : false;
#endif

	if(pIPlayerInput && !isUsingDedicatedInput)
	{
		CRY_ASSERT(pIPlayerInput->GetType() == IPlayerInput::PLAYER_INPUT);
		CPlayerInput * pPlayerInput = static_cast<CPlayerInput*>(pIPlayerInput);

		const Ang3 rawDeltas = pPlayerInput->GetRawControllerInput();

		absInput = min((fabsf(rawDeltas.x) + fabsf(rawDeltas.z)) * 1.4f, 1.0f);

		aimAssistPowerFactor = 2.0f - absInput;
	}

	//Gather weapon info before processing target aim assistance
	bool playerWeaponIsRequestingSnap = false;
	CWeapon* pWeapon = GetCurrentWeapon( pCurrentPlayerItem );
	if (pWeapon)
	{
		playerWeaponIsRequestingSnap = pWeapon->ShouldSnapToTarget();
	}

	IMovementController* pMovementController = m_player.GetMovementController();
	CRY_ASSERT(pMovementController);
	SMovementState moveState;
	pMovementController->GetMovementState(moveState);

	Vec3 playerView[4] =
	{
		m_viewQuat.GetColumn0(), // Right
		m_viewQuat.GetColumn1(), // Forward
		m_viewQuat.GetColumn2(), // Up
		moveState.eyePosition    // Pos
	};

	IVehicle* pVehicle = m_player.GetLinkedVehicle();
	if (pVehicle)
	{
		Vec3 up(0.f,0.f,1.f);
		playerView[1] = moveState.eyeDirection;	// Forward
		playerView[0] = (playerView[1].cross(up)).GetNormalizedSafe(); // Right
		playerView[2] = playerView[0].cross(playerView[1]); // Up
	}

	float fZoomAmount = 0.0f;
	TargetAimAssistance(pWeapon, targetAimAssistAngleFollowH, targetAimAssistAngleFollowV, targetAimAssistAngleScale, fZoomAmount, playerView);

	targetAimAssistAngleScale = powf(targetAimAssistAngleScale, aimAssistPowerFactor);

	//TODO: Fix so it's not using auto aim unless selected

	float fFollowAssistScale = (absInput * (1.0f - fZoomAmount)) + min(absInput * fZoomAmount * __fres(g_pGameCVars->aim_assistInputForFullFollow_Ironsight), 1.0f);

	m_deltaAngles.z = (m_deltaAngles.z * targetAimAssistAngleScale) + (absInput * targetAimAssistAngleFollowH);
	m_deltaAngles.x = (m_deltaAngles.x * targetAimAssistAngleScale) + (absInput * targetAimAssistAngleFollowV);

	const bool snapToTarget = (!gEnv->bMultiplayer && playerWeaponIsRequestingSnap && !m_snap_target_dir.IsZero());
	const EntityId closeCombatSnapTargetId = g_pGame->GetAutoAimManager().GetCloseCombatSnapTarget();

	if (closeCombatSnapTargetId)
	{
		Vec3 snapDirection = GetCloseCombatSnapTargetDirection(closeCombatSnapTargetId);
		if (!snapDirection.IsZero())
		{
			const float blendSpeed = clamp_tpl( g_pGameCVars->pl_melee.melee_snap_blend_speed , 0.0f, 1.0f);
			m_deltaAngles.z = -asin_tpl(snapDirection * m_viewQuat.GetColumn0()) * blendSpeed;
			m_deltaAngles.x = asin_tpl(snapDirection * m_viewQuat.GetColumn2()) * blendSpeed;
		}
	}
	else if (snapToTarget)
	{
		const float zoomInTime = pWeapon->GetZoomInTime();
		const float blendFactor = clamp_tpl(pow_tpl((1.0f-zoomInTime),2.0f), 0.0f, 1.0f);
		m_deltaAngles.z = -asin_tpl(m_snap_target_dir * m_viewQuat.GetColumn0()) * blendFactor;
		m_deltaAngles.x = asin_tpl(m_snap_target_dir * m_viewQuat.GetColumn2()) * blendFactor;	
	}
	m_currently_snapping = playerWeaponIsRequestingSnap;

#if !defined(_RELEASE)
	if(g_pGameCVars->ctrlr_OUTPUTDEBUGINFO)
	{
		float white[] = {1,1,1,1};
		gEnv->pRenderer->Draw2dLabel( 20, 100, 1.4f, white, false, "Aim Acceleration & Assist\n  absInput: %.6f", absInput );
	}
#endif
}