virtual void ProcessEvent( EFlowEvent event,SActivationInfo *pActInfo )
	{
		if (event != eFE_Activate)
			return;

		if (!InputEntityIsLocalPlayer( pActInfo )) 
			return;

		const bool bTriggered = IsPortActive(pActInfo, EIP_Trigger);
		const bool bFreqTriggered = IsPortActive(pActInfo, EIP_Frequency);
		if (bTriggered == false && bFreqTriggered == false)
			return;

		IGameFramework* pGF = gEnv->pGame->GetIGameFramework();
		IView* pView = 0;
		IView* pActiveView = pGF->GetIViewSystem()->GetActiveView();
		int viewType = GetPortInt(pActInfo, EIP_ViewType);
		if (viewType == VT_FirstPerson) // use player's view
		{
			IActor* pActor = pGF->GetClientActor();
			if (pActor == 0)
				return;

			const int restriction = GetPortInt(pActInfo, EIP_Restriction);
			if (restriction != ER_None)
			{
				IVehicle* pVehicle = pActor->GetLinkedVehicle();
				if (restriction == ER_InVehicle && pVehicle == 0)
					return;
				if (restriction == ER_NoVehicle && pVehicle != 0 /* && pVehicle->GetSeatForPassenger(entityId) != 0 */)
					return;
			}

			EntityId entityId = pActor->GetEntityId();
			pView = pGF->GetIViewSystem()->GetViewByEntityId(entityId);
		}
		else // active view 
		{
			pView = pActiveView;
		}
		if (pView == 0 || pView != pActiveView)
			return;

		const bool  bGroundOnly = GetPortBool(pActInfo, EIP_GroundOnly);
		Ang3  angles = Ang3(DEG2RAD(GetPortVec3(pActInfo, EIP_Angle)));
		Vec3  shift = GetPortVec3(pActInfo, EIP_Shift);
		const float duration = GetPortFloat(pActInfo, EIP_Duration);
		float freq = GetPortFloat(pActInfo, EIP_Frequency);
		if (iszero(freq) == false)
			freq = 1.0f / freq;
		const float randomness = GetPortFloat(pActInfo, EIP_Randomness);
		static const bool bFlip = true; // GetPortBool(pActInfo, EIP_Flip);
		const bool bUpdateOnly = !bTriggered && bFreqTriggered; // it's an update if and only if Frequency has been changed

		const float distance = GetPortFloat(pActInfo, EIP_Distance);
		const float rangeMin = GetPortFloat(pActInfo, EIP_RangeMin);
		const float rangeMax = GetPortFloat(pActInfo, EIP_RangeMax);
		float amount = min(1.f, max(0.f, (rangeMax-distance) / (rangeMax-rangeMin) ));

		angles *= amount;
		shift *= amount;

		pView->SetViewShake(angles, shift, duration, freq, randomness, FLOWGRAPH_SHAKE_ID, bFlip, bUpdateOnly, bGroundOnly);
	}
//-------------------------------------------
void CGameRules::ProcessClientExplosionScreenFX(const ExplosionInfo &explosionInfo)
{
	IActor *pClientActor = g_pGame->GetIGameFramework()->GetClientActor();
	if (pClientActor)
	{
		//Distance
		float dist = (pClientActor->GetEntity()->GetWorldPos() - explosionInfo.pos).len();

		//Is the explosion in Player's FOV (let's suppose the FOV a bit higher, like 80)
		CActor *pActor = (CActor *)pClientActor;
		SMovementState state;
		if (IMovementController *pMV = pActor->GetMovementController())
		{
			pMV->GetMovementState(state);
		}

		Vec3 eyeToExplosion = explosionInfo.pos - state.eyePosition;
		eyeToExplosion.Normalize();
		bool inFOV = (state.eyeDirection.Dot(eyeToExplosion) > 0.68f);
		
		// if in a vehicle eyeDirection is wrong
		if(pActor && pActor->GetLinkedVehicle())
		{
			Vec3 eyeDir = static_cast<CPlayer*>(pActor)->GetVehicleViewDir();
			inFOV = (eyeDir.Dot(eyeToExplosion) > 0.68f);
		}

		//All explosions have radial blur (default 30m radius, to make Sean happy =))
		float maxBlurDistance = (explosionInfo.maxblurdistance>0.0f)?explosionInfo.maxblurdistance:30.0f;
		if (maxBlurDistance>0.0f && g_pGameCVars->g_radialBlur>0.0f && m_explosionScreenFX && explosionInfo.radius>0.5f)
		{		
			if (inFOV && dist < maxBlurDistance)
			{
				ray_hit hit;
				int col = gEnv->pPhysicalWorld->RayWorldIntersection(explosionInfo.pos , -eyeToExplosion*dist, ent_static | ent_terrain, rwi_stop_at_pierceable|rwi_colltype_any, &hit, 1);

				//If there was no obstacle between flashbang grenade and player
				if(!col)
				{
					if (CScreenEffects* pSE = pActor->GetScreenEffects())
					{
						float blurRadius = (-1.0f/maxBlurDistance)*dist + 1.0f;

						gEnv->p3DEngine->SetPostEffectParam("FilterRadialBlurring_Radius", blurRadius);
						gEnv->p3DEngine->SetPostEffectParam("FilterRadialBlurring_Amount", 1.0f);

						IBlendedEffect *pBlur	= CBlendedEffect<CPostProcessEffect>::Create(CPostProcessEffect(pClientActor->GetEntityId(),"FilterRadialBlurring_Amount", 0.0f));
						IBlendType   *pLinear = CBlendType<CLinearBlend>::Create(CLinearBlend(1.0f));
						pSE->StartBlend(pBlur, pLinear, 1.0f, CScreenEffects::eSFX_GID_RBlur);
						pSE->SetUpdateCoords("FilterRadialBlurring_ScreenPosX","FilterRadialBlurring_ScreenPosY", explosionInfo.pos);
					}

					float distAmp = 1.0f - (dist / maxBlurDistance);
					if (gEnv->pInput) 
						gEnv->pInput->ForceFeedbackEvent( SFFOutputEvent(eDI_XI, eFF_Rumble_Basic, 0.5f, distAmp*3.0f, 0.0f));
				}
			}
		}

		//Flashbang effect 
		if(dist<explosionInfo.radius && inFOV &&
			(!strcmp(explosionInfo.effect_class,"flashbang") || !strcmp(explosionInfo.effect_class,"FlashbangAI")))
		{
			ray_hit hit;
			int col = gEnv->pPhysicalWorld->RayWorldIntersection(explosionInfo.pos , -eyeToExplosion*dist, ent_static | ent_terrain, rwi_stop_at_pierceable|rwi_colltype_any, &hit, 1);

			//If there was no obstacle between flashbang grenade and player
			if(!col)
			{
				float power = explosionInfo.flashbangScale;
				power *= max(0.0f, 1 - (dist/explosionInfo.radius));
				float lookingAt = (eyeToExplosion.Dot(state.eyeDirection.normalize()) + 1)*0.5f;
				power *= lookingAt;

				SAFE_GAMEAUDIO_SOUNDMOODS_FUNC(AddSoundMood(SOUNDMOOD_EXPLOSION,MIN(power*40.0f,100.0f)));

				gEnv->p3DEngine->SetPostEffectParam("Flashbang_Time", 1.0f + (power * 4));
				gEnv->p3DEngine->SetPostEffectParam("FlashBang_BlindAmount",explosionInfo.blindAmount);
				gEnv->p3DEngine->SetPostEffectParam("Flashbang_DifractionAmount", (power * 2));
				gEnv->p3DEngine->SetPostEffectParam("Flashbang_Active", 1);
			}
		}
		else if(inFOV && (dist < explosionInfo.radius))
		{
			if (explosionInfo.damage>10.0f || explosionInfo.pressure>100.0f)
			{
				//Add some angular impulse to the client actor depending on distance, direction...
				float dt = (1.0f - dist/explosionInfo.radius);
				dt = dt * dt;
				float angleZ = gf_PI*0.15f*dt;
				float angleX = gf_PI*0.15f*dt;

				pActor->AddAngularImpulse(Ang3(Random(-angleX*0.5f,angleX),0.0f,Random(-angleZ,angleZ)),0.0f,dt*2.0f);
			}
		}


		float fDist2=(pClientActor->GetEntity()->GetWorldPos()-explosionInfo.pos).len2();
		if (fDist2<250.0f*250.0f)
		{		
			if (fDist2<sqr(SAFE_GAMEAUDIO_BATTLESTATUS_FUNC_RET(GetBattleRange())))
				SAFE_GAMEAUDIO_BATTLESTATUS_FUNC(TickBattleStatus(1.0f));
		}
	}

}
//--------------------------------------------------------------------------
//--- ViewPreProcess
//--------------------------------------------------------------------------
// Fetch all the data we need to work on.
//--------------------------------------------------------------------------
void CPlayerView::ViewPreProcess(const CPlayer &rPlayer, SViewParams &viewParams, SViewStateIn &m_in)
{
	// SViewStateIn --- the constants
	{
		m_in.lastPos = viewParams.position;
		m_in.lastQuat = viewParams.rotation;
		m_in.defaultFov = g_pGameCVars->cl_fov;
		m_in.frameTime = min(gEnv->pTimer->GetFrameTime(), 0.1f);
		m_in.pCharacter = rPlayer.GetEntity()->GetCharacter(0);
		m_in.pVehicle = rPlayer.GetLinkedVehicle();
		m_in.bIsGrabbing = false;
		/*if (rPlayer.m_grabStats.grabId>0)
		{
			m_in.bIsGrabbing=true;
			// *****
			viewParams.nearplane = 0.1f;
			// *****
		}*/
		m_in.stats_isRagDoll = rPlayer.m_stats.isRagDoll;
		m_in.stats_isStandingUp = rPlayer.m_stats.isStandingUp;
		m_in.stats_isFrozen = rPlayer.m_stats.isFrozen.Value();
		m_in.stats_isShattered = rPlayer.m_stats.isShattered.Value();
		m_in.stats_followCharacterHead = rPlayer.m_stats.followCharacterHead.Value();
		m_in.stats_flatSpeed = rPlayer.m_stats.speedFlat;
		m_in.stats_leanAmount = rPlayer.m_stats.leanAmount;
		m_in.stats_inAir = rPlayer.m_stats.inAir;
		m_in.stats_inWater = rPlayer.m_stats.inWaterTimer;
		m_in.stats_headUnderWater = (rPlayer.m_stats.headUnderWaterTimer > 0.0f);
		m_io.stats_jumped = rPlayer.m_stats.jumped;
		m_in.stats_firstPersonBody = rPlayer.m_stats.firstPersonBody.Value();
		m_in.stats_onGround = rPlayer.m_stats.onGround;
		m_io.stats_landed = rPlayer.m_stats.landed;
		m_in.stats_velocity = rPlayer.m_stats.velocity;
		m_in.bSprinting = rPlayer.m_stats.bSprinting;
		m_io.stats_inFreefall = rPlayer.m_stats.inFreefall.Value();
		m_in.stats_onLadder = rPlayer.m_stats.isOnLadder;
		m_in.bLookingAtFriendlyAI = rPlayer.m_stats.bLookingAtFriendlyAI;
		m_in.bIsGrabbed = rPlayer.m_stats.isGrabbed;
		m_in.params_viewFoVScale = rPlayer.m_params.viewFoVScale;
		m_in.params_viewPivot = rPlayer.m_params.viewPivot;
		m_in.params_viewDistance = rPlayer.m_params.viewDistance;
		m_in.params_weaponInertiaMultiplier = rPlayer.m_params.weaponInertiaMultiplier;
		m_in.params_hudAngleOffset = rPlayer.m_params.hudAngleOffset;
		m_in.params_hudOffset = rPlayer.m_params.hudOffset;
		m_in.params_viewHeightOffset = rPlayer.m_params.viewHeightOffset;
		m_in.params_weaponBobbingMultiplier = rPlayer.m_params.weaponBobbingMultiplier;
		m_io.bobMul = g_pGameCVars->cl_bob * m_in.params_weaponBobbingMultiplier;
		m_in.bIsThirdPerson = rPlayer.IsThirdPerson();
		m_in.vEntityWorldPos = rPlayer.GetEntity()->GetWorldPos();
		m_in.entityId = rPlayer.GetEntityId();

		// use absolute entity matrix when frozen
		if (rPlayer.m_stats.isFrozen.Value())
		{
			m_in.entityWorldMatrix = Matrix34(rPlayer.GetEntity()->GetWorldTM());
		}
		else
		{
			m_in.entityWorldMatrix = Matrix34(rPlayer.GetEntity()->GetSlotWorldTM(0));
		}

		m_in.localEyePos = rPlayer.GetLocalEyePos();
		m_in.worldEyePos = m_in.entityWorldMatrix * m_in.localEyePos;
		m_in.headMtxLocal.SetIdentity();

		if (m_in.stats_followCharacterHead)
		{
			int16 joint_id = rPlayer.GetBoneID(BONE_HEAD);

			if (joint_id >= 0)
			{
				m_in.headMtxLocal = Matrix33(m_in.pCharacter->GetISkeletonPose()->GetAbsJointByID(joint_id).q.GetNormalized());
			}
		}

		m_in.thirdPersonDistance = g_pGameCVars->cl_tpvDist;
		m_in.thirdPersonYaw = g_pGameCVars->cl_tpvYaw;
		EStance refStance((rPlayer.m_stance == STANCE_PRONE) ? STANCE_PRONE : STANCE_STAND);
		m_in.stand_MaxSpeed = rPlayer.GetStanceInfo(refStance)->maxSpeed;
		m_in.standSpeed = rPlayer.GetStanceMaxSpeed(refStance);
		m_in.health = rPlayer.GetHealth();
		m_in.stance = rPlayer.m_stance;
		m_in.shake = g_pGameCVars->cl_sprintShake;
		m_in.deathTime = rPlayer.GetDeathTime();
	}
	// SViewStateInOut -- temporaries and output
	{
		//--- temporaries - FirstThird shared
		//m_io.bUsePivot
		//m_io.bobMul
		//m_io.viewQuatForWeapon
		//m_io.eyeOffsetGoal
		//--- temporaries - view shared
		m_io.wAngles = Ang3(0, 0, 0);
		//--- I/O
		//m_io.m_lastPos=rPlayer.m_lastPos;
		// Integ
		//if (m_io.m_lastPos.len2()>0.01f)
		//{
		//	m_io.blendViewOffset = m_io.m_lastPos - rPlayer.GetEntity()->GetWorldPos();
		//	m_io.m_lastPos.Set(0,0,0);
		//}
	}
	// *****
	viewParams.fov = m_in.defaultFov * rPlayer.m_params.viewFoVScale * (gf_PI / 180.0f);
	viewParams.nearplane = 0.0f;
	// *****
	m_io.eyeOffsetViewGoal = rPlayer.GetStanceViewOffset(rPlayer.m_stance);
	m_io.viewQuatFinal = rPlayer.m_viewQuatFinal;
	m_io.viewQuat = rPlayer.m_viewQuat;
	m_io.stats_FPWeaponAngles = rPlayer.m_stats.FPWeaponAngles;
	m_io.stats_FPWeaponPos = rPlayer.m_stats.FPWeaponPos;
	m_io.vFPWeaponOffset = rPlayer.m_FPWeaponOffset;
	m_io.stats_FPSecWeaponAngles = rPlayer.m_stats.FPSecWeaponAngles;
	m_io.stats_FPSecWeaponPos = rPlayer.m_stats.FPSecWeaponPos;
	//m_io.viewShake=rPlayer.m_viewShake;
	m_io.eyeOffsetView = rPlayer.m_eyeOffsetView;
	m_io.baseQuat = rPlayer.m_baseQuat;
	m_io.vFPWeaponAngleOffset = rPlayer.m_FPWeaponAngleOffset;
	m_io.stats_bobCycle = rPlayer.m_stats.bobCycle;
	m_io.vFPWeaponLastDirVec = rPlayer.m_FPWeaponLastDirVec;
	m_io.bobOffset = rPlayer.m_bobOffset;
	m_io.angleOffset = rPlayer.m_angleOffset;
	m_io.viewAngleOffset = rPlayer.m_viewAnglesOffset;
	m_in.stats_flyMode = rPlayer.m_stats.flyMode;
	m_in.stats_spectatorMode = rPlayer.m_stats.spectatorMode;
	m_in.stats_spectatorTarget = rPlayer.m_stats.spectatorTarget;
	m_io.stats_smoothViewZ = rPlayer.m_stats.smoothViewZ;
	m_io.stats_smoothZType = rPlayer.m_stats.smoothZType;
	//-- Any individual PreProcess handlers should be called here
}
			inputParams.rangeMin = GetPortFloat(pActInfo, EIP_RangeMin);
			inputParams.rangeMax = GetPortFloat(pActInfo, EIP_RangeMax);
			inputParams.sustainDuration = GetPortFloat(pActInfo, EIP_SustainDuration);
			inputParams.fadeInDuration = GetPortFloat(pActInfo, EIP_FadeInDuration);
			inputParams.fadeOutDuration = GetPortFloat(pActInfo, EIP_FadeOutDuration);
		}
	}
	
	static SInputParams m_Presets[NUM_PRESETS];
	int m_lastShakeFrameID;
};

CFlowNode_CameraViewShakeEx::SInputParams CFlowNode_CameraViewShakeEx::m_Presets[]=
{
	//                                             Ground Smooth      angle                      shift													fr  rnd			d   rm  rm   sd   fi     fo
	{ "DistantExplosion", ER_None, VT_FirstPerson, false, false, Ang3(0.6f, 0.6f, 0.6f), Vec3(0.001f, 0.001f, 0.001f),					10,  2,			0,  0,  30,  0,  0.2f,  1.2f },
	{ "CloseExplosion",   ER_None, VT_FirstPerson, false, false, Ang3(0.5f, 0.5f, 0.5f), Vec3(0.003f, 0.003f, 0.003f),					30,  5,			0,  0,  30,  0,  0,     1.1f },
	{ "SmallTremor",      ER_None, VT_FirstPerson, false, false, Ang3(0.2f, 0.2f, 0.2f), Vec3(0.0001f, 0.0001f, 0.0001f),				18,  1.3f,  0,  0,  30,  2,  1.2f,  3.f  },
	{ "SmallTremor2",     ER_None, VT_FirstPerson, false, false, Ang3(0.25f, 0.25f, 0.25f), Vec3(0.00045f, 0.00045f, 0.00045f), 13,  2,			0,  0,  30,  2,  1.2f,  3.f  },
};

//////////////////////////////////////////////////////////////////////////
class CFlowNode_CameraView : public CFlowBaseNode<eNCT_Instanced>
{
private:
	IView* m_pView;
	IView* m_pLocalPlayerView;
	IViewSystem* m_pViewSystem;

public:
	CFlowNode_CameraView( SActivationInfo * pActInfo ):
void CPlayerView::ViewThirdPerson(SViewParams &viewParams)
{
	if (m_in.thirdPersonYaw > 0.001f)
	{
		viewParams.rotation *= Quat::CreateRotationXYZ(Ang3(0, 0, m_in.thirdPersonYaw * gf_PI / 180.0f));
		m_io.viewQuatFinal = viewParams.rotation;
	}

	if (g_pGameCVars->goc_enable)
	{
		Vec3 target(g_pGameCVars->goc_targetx, g_pGameCVars->goc_targety, g_pGameCVars->goc_targetz);
		static Vec3 current(target);
		Interpolate(current, target, 5.0f, m_in.frameTime);
		// make sure we don't clip through stuff that much
		Vec3 offsetX(0, 0, 0);
		Vec3 offsetY(0, 0, 0);
		Vec3 offsetZ(0, 0, 0);
		offsetX = m_io.viewQuatFinal.GetColumn0() * current.x;
		offsetY = m_io.viewQuatFinal.GetColumn1() * (current.y - 0.25f);
		offsetZ = m_io.viewQuatFinal.GetColumn2() * current.z;
		IActor *pActor = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(m_in.entityId);

		if (pActor)
		{
			static ray_hit hit;
			IPhysicalEntity *pSkipEntities[10];
			int nSkip = 0;
			IItem *pItem = pActor->GetCurrentItem();

			if (pItem)
			{
				CWeapon *pWeapon = (CWeapon *)pItem->GetIWeapon();

				if (pWeapon)
				{
					nSkip = CSingle::GetSkipEntities(pWeapon, pSkipEntities, 10);
				}
			}

			float oldLen = offsetY.len();
			Vec3 start = m_io.baseQuat * m_io.eyeOffsetView + viewParams.position + offsetX + offsetZ;

			if (gEnv->pPhysicalWorld->RayWorldIntersection(start, offsetY, ent_static | ent_terrain | ent_rigid,
					rwi_ignore_noncolliding | rwi_stop_at_pierceable, &hit, 1, pSkipEntities, nSkip))
			{
				offsetY = hit.pt - start;
				current.y = current.y * (hit.dist / oldLen);
			}
		}

		//viewParams.position += m_io.viewQuatFinal.GetColumn0() * current.x;		// right
		//viewParams.position += m_io.viewQuatFinal.GetColumn1() * current.y;	// back
		//viewParams.position += m_io.viewQuatFinal.GetColumn2() * current.z;	// up
		viewParams.position += offsetX + offsetY + offsetZ;
	}
	else
	{
		if (m_io.bUsePivot)
		{
			viewParams.position += m_io.viewQuatFinal.GetColumn1() * m_in.params_viewDistance + m_io.viewQuatFinal.GetColumn2() * (0.25f + m_in.params_viewHeightOffset);
		}
		else
		{
			viewParams.position += m_io.viewQuatFinal.GetColumn1() * -m_in.thirdPersonDistance + m_io.viewQuatFinal.GetColumn2() * (0.25f + m_in.params_viewHeightOffset);
		}
	}
}
//
// Extract the various modifiers out into their own function.
//
// Aim is to make the code easier to understand and modify, as
// well as to ease the addition of new modifiers.
//
void CPlayerView::ViewFirstPerson(SViewParams &viewParams)
{
	//headbob
	Ang3 angOffset(0, 0, 0);
	Vec3 weaponOffset(0, 0, 0);
	Ang3 weaponAngleOffset(0, 0, 0);
	// jump/land spring effect. Adjust the eye and weapon pos as required.
	FirstPersonJump(viewParams, weaponOffset, weaponAngleOffset);
	//float standSpeed(GetStanceMaxSpeed(STANCE_STAND));
	Vec3 vSpeed(0, 0, 0);

	if (m_in.standSpeed > 0.001f)
	{
		vSpeed = (m_in.stats_velocity / m_in.standSpeed);
	}

	float vSpeedLen(vSpeed.len());

	if (vSpeedLen > 1.5f)
	{
		vSpeed = vSpeed / vSpeedLen * 1.5f;
	}

	float speedMul(0);

	if (m_in.standSpeed > 0.001f)
	{
		speedMul = (m_in.stats_flatSpeed / m_in.standSpeed * 1.1f);
	}

	speedMul = min(1.5f, speedMul);
	bool crawling(m_in.stance == STANCE_PRONE /*&& m_in.stats_flatSpeed>0.1f*/ && m_in.stats_onGround > 0.1f);
	bool weaponZoomed = false;
	bool weaponZooming = false;
	//Not crawling while in zoom mode
	IActor *owner = gEnv->pGame->GetIGameFramework()->GetIActorSystem()->GetActor(m_in.entityId);

	if(owner && owner->IsPlayer())
	{
		IItem *pItem = owner->GetCurrentItem();

		if(pItem)
		{
			CWeapon *pWeapon = static_cast<CWeapon *>(pItem->GetIWeapon());

			if(pWeapon)
			{
				weaponZoomed = pWeapon->IsZoomed();
				weaponZooming = pWeapon->IsZoomingInOrOut();

				if(weaponZoomed || weaponZooming)
				{
					crawling = false;
				}
			}
		}
	}

	// On the ground.
	if (m_in.stats_inAir < 0.1f /*&& m_in.stats_inWater < 0.1f*/)
	{
		//--- Bobbing.
		// bobCycle is a speed varying time step running (looping) from 0 to 1
		// this feeds into a sin eqn creating a double horizontal figure of 8.
		// ( a lissajous figure with the vertical freq twice the horz freq ).
		// To tweak the total speed of the curve:
		// To tweak the effect speed has on the curve:
		float kSpeedToBobFactor = 1.15f; //0.9f
		// To tweak the width of the bob:
		float kBobWidth = 0.1f;
		// To tweak the height of the bob:
		float kBobHeight = 0.05f;
		// To tweak the scale of strafing lag: (may need to manually adjust the strafing angle offsets as well.)
		const float kStrafeHorzScale = 0.05f;
		kBobWidth = 0.15f;
		kBobHeight = 0.06f;
		m_io.stats_bobCycle += m_in.frameTime * kSpeedToBobFactor * speedMul;// * (m_in.bSprinting?1.25f:1.0f);

		//if player is standing set the bob to rest. (bobCycle reaches 1.0f within 1 second)
		if (speedMul < 0.1f)
		{
			m_io.stats_bobCycle = min(m_io.stats_bobCycle + m_in.frameTime * 1.0f, 1.0f);
		}

		// bobCycle loops between 0 and 1
		if (m_io.stats_bobCycle > 1.0f)
		{
			m_io.stats_bobCycle = m_io.stats_bobCycle - 1.0f;
		}

		if (crawling)
		{
			kBobWidth *= 2.0f * speedMul;
		}
		else if (m_in.bSprinting)
		{
			kBobWidth *= 1.25f * speedMul;
		}

		//set the bob offset
		Vec3 bobDir(cry_sinf(m_io.stats_bobCycle * gf_PI * 2.0f)*kBobWidth * speedMul, 0, cry_sinf(m_io.stats_bobCycle * gf_PI * 4.0f)*kBobHeight * speedMul);
		//not the bob offset for the weapon
		bobDir *= 0.25f;

		//if player is strafing shift a bit the weapon on left/right
		if (speedMul > 0.01f)
		{
			// right vector dot speed vector
			float dot(m_io.viewQuatFinal.GetColumn0() * vSpeed);
			bobDir.x -= dot * kStrafeHorzScale;	// the faster we move right, the more the gun lags to the left and vice versa

			//tweak the right strafe for weapon laser
			if (dot > 0.0f)
			{
				weaponAngleOffset.z += dot * 1.5f;    // kStrafeHorzScale
			}
			else
			{
				weaponAngleOffset.z -= dot * 2.0f;    // kStrafeHorzScale
			}

			weaponAngleOffset.y += dot * 5.0f;		// kStrafeHorzScale
		}

		//CryLogAlways("bobDir.z: %f", bobDir.z);
		if (bobDir.z < 0.0f)
		{
			bobDir.x *= 1.0f;
			bobDir.y *= 1.0f;
			bobDir.z *= 0.35f;
			speedMul *= 0.65f;
		}
		else
		{
			bobDir.z *= 1.85f;
		}

		//CryLogAlways("bobDir.z: %f after", bobDir.z);
		weaponOffset += m_io.viewQuatFinal * bobDir;
		weaponOffset -= m_io.baseQuat.GetColumn2() * 0.035f * speedMul;
		weaponAngleOffset.y += cry_sinf(m_io.stats_bobCycle * gf_PI * 2.0f) * speedMul * -1.5f;

		if (crawling)
		{
			weaponAngleOffset.y *= 3.0f;
		}

		weaponAngleOffset.x += speedMul * 1.5f;

		if (crawling)
		{
			weaponAngleOffset.z += cry_sinf(m_io.stats_bobCycle * gf_PI * 2.0f) * speedMul * 3.0f;
		}

		//FIXME: viewAngles must include all the view offsets, otherwise aiming wont be precise.
		angOffset.x += cry_sinf(m_io.stats_bobCycle * gf_PI * 4.0f) * 0.7f * speedMul;

		if (crawling)
		{
			angOffset.x *= 2.5f;
			angOffset.y += cry_sinf(m_io.stats_bobCycle * gf_PI * 2.0f) * 1.25f * speedMul;
			angOffset.z -= cry_sinf(m_io.stats_bobCycle * gf_PI * 2.0f) * 2.5f * speedMul;
		}
		else if (m_in.bSprinting)
		{
			angOffset.x *= 2.5f;
			angOffset.y += cry_sinf(m_io.stats_bobCycle * gf_PI * 2.0f) * 1.0f * speedMul;
			angOffset.z -= cry_sinf(m_io.stats_bobCycle * gf_PI * 2.0f) * 2.25f * speedMul;
		}
		else if(m_in.stance == STANCE_CROUCH && !weaponZoomed && !weaponZooming)
		{
			weaponOffset.z   += 0.035f;
			weaponOffset.y   -= m_io.viewQuatFinal.GetColumn1().y * 0.03f;
		}
		else if(m_in.stance == STANCE_CROUCH && weaponZooming)
		{
			weaponOffset.z	-= 0.07f;
			weaponOffset.y	+=  m_io.viewQuatFinal.GetColumn1().y * 0.06f;
		}
		else
		{
			//angOffset.x *= 2.25f;
			//angOffset.y += cry_sinf(m_io.stats_bobCycle*gf_PI*2.0f)*0.5f*speedMul;
			//angOffset.z -= cry_sinf(m_io.stats_bobCycle*gf_PI*2.0f)*1.125f*speedMul;
		}
	}
	else
	{
		m_io.stats_bobCycle = 0;

		//while flying offset a bit the weapon model by the player speed
		if (m_in.stats_velocity.len2() > 0.001f)
		{
			float dotFwd(m_io.viewQuatFinal.GetColumn1() * vSpeed);
			float dotSide(m_io.viewQuatFinal.GetColumn0() * vSpeed);
			float dotUp(m_io.viewQuatFinal.GetColumn2() * vSpeed);
			weaponOffset += m_io.viewQuatFinal * Vec3(dotSide * -0.05f, dotFwd * -0.035f, dotUp * -0.05f);
			weaponAngleOffset.x += dotUp * 2.0f;
			weaponAngleOffset.y += dotSide * 5.0f;
			weaponAngleOffset.z -= dotSide * 2.0f;
		}
	}

	//add some inertia to weapon due view direction change.
	float deltaDotSide(m_io.vFPWeaponLastDirVec * m_io.viewQuatFinal.GetColumn0());
	float deltaDotUp(m_io.vFPWeaponLastDirVec * m_io.viewQuatFinal.GetColumn2());
	weaponOffset += m_io.viewQuatFinal * Vec3(deltaDotSide * 0.1f + m_in.stats_leanAmount * 0.05f, 0, deltaDotUp * 0.1f - fabs(m_in.stats_leanAmount) * 0.05f) * m_in.params_weaponInertiaMultiplier;
	weaponAngleOffset.x -= deltaDotUp * 5.0f * m_in.params_weaponInertiaMultiplier;
	weaponAngleOffset.z += deltaDotSide * 5.0f * m_in.params_weaponInertiaMultiplier;
	weaponAngleOffset.y += deltaDotSide * 5.0f * m_in.params_weaponInertiaMultiplier;

	if(m_in.stats_leanAmount < 0.0f)
	{
		weaponAngleOffset.y += m_in.stats_leanAmount * 5.0f;
	}

	//the weapon model tries to stay parallel to the terrain when the player is freefalling/parachuting

	if (m_in.stats_inWater > 0.0f)
	{
		weaponOffset -= m_io.viewQuat.GetColumn2() * 0.15f;
	}

	if (m_in.stats_inWater > 0.1f && !m_in.stats_headUnderWater)
	{
		Ang3 offset(m_io.viewQuatFinal);
		offset.z = 0;

		if (offset.x < 0.0f)
		{
			offset.x = 0;
		}

		weaponAngleOffset -= offset * (180.0f / gf_PI) * 0.75f;
	}
	else if (m_io.stats_inFreefall)
	{
		Ang3 offset(m_io.viewQuatFinal);
		offset.z = 0;
		weaponAngleOffset -= offset * (180.0f / gf_PI) * 0.5f;
	}
	//same thing with crawling
	else if (crawling)
	{
		//FIXME:to optimize, looks like a bit too expensive
		Vec3 forward(m_io.viewQuatFinal.GetColumn1());
		Vec3 up(m_io.baseQuat.GetColumn2());
		Vec3 right(-(up % forward));
		Matrix33 mat;
		mat.SetFromVectors(right, up % right, up);
		mat.OrthonormalizeFast();
		Ang3 offset(m_io.viewQuatFinal.GetInverted() * Quat(mat));
		weaponAngleOffset += offset * (180.0f / gf_PI) * 0.5f;
		float lookDown(m_io.viewQuatFinal.GetColumn1() * m_io.baseQuat.GetColumn2());
		weaponOffset += m_io.baseQuat * Vec3(0, -0.5f * max(-lookDown, 0.0f), -0.05f);
		float scale = 0.5f;;

		if(weaponAngleOffset.x > 0.0f)
		{
			scale = min(0.5f, weaponAngleOffset.x / 15.0f);
			weaponAngleOffset.x *= scale;
		}
		else
		{
			scale = min(0.5f, -weaponAngleOffset.x / 20.0f);
			weaponAngleOffset *= (1.0f - scale);
			weaponOffset *= scale;
		}

		if(vSpeedLen > 0.1f)
		{
			weaponAngleOffset += Ang3(-8.0f, 0, -12.5f);
		}
	}
	else if (m_in.bSprinting && vSpeedLen > 0.5f)
	{
		weaponAngleOffset += Ang3(-20.0f, 0, 10.0f);
		weaponOffset += m_io.viewQuatFinal * Vec3(0.0f, -.01f, .1f);
	}
	else if (m_in.bLookingAtFriendlyAI && !weaponZooming && !weaponZoomed)
	{
		weaponAngleOffset += Ang3(-15.0f, 0, 8.0f);
		weaponOffset += m_io.viewQuatFinal * Vec3(0.0f, -.01f, .05f);
	}

	//apply some multipliers
	weaponOffset *= m_in.params_weaponBobbingMultiplier;
	angOffset *= m_io.bobMul * 0.25f;

	if (m_io.bobMul * m_io.bobMul != 1.0f)
	{
		weaponOffset *= m_io.bobMul;
		weaponAngleOffset *= m_io.bobMul;
	}

	float bobSpeedMult(1.0f);

	if(m_in.stats_inWater > 0.1)
	{
		bobSpeedMult = 0.75f;
	}

	//		m_io.viewQuatForWeapon *= Quat::CreateRotationXYZ(Ang3(rx,ry,rz));
	Interpolate(m_io.vFPWeaponOffset, weaponOffset, 3.95f * bobSpeedMult, m_in.frameTime);
	Interpolate(m_io.vFPWeaponAngleOffset, weaponAngleOffset, 10.0f * bobSpeedMult, m_in.frameTime);
	Interpolate(m_io.vFPWeaponLastDirVec, m_io.viewQuatFinal.GetColumn1(), 5.0f * bobSpeedMult, m_in.frameTime);
	Interpolate(m_io.angleOffset, angOffset, 10.0f, m_in.frameTime, 0.002f);

	if(weaponZooming)
	{
		m_io.vFPWeaponLastDirVec = m_io.viewQuatFinal.GetColumn1();
		m_io.vFPWeaponOffset.Set(0.0f, 0.0f, 0.0f);
		m_io.vFPWeaponAngleOffset.Set(0.0f, 0.0f, 0.0f);
		m_io.bobOffset.Set(0.0f, 0.0f, 0.0f);
	}

	if (m_in.bSprinting)
	{
		float headBobScale = (m_in.stats_flatSpeed / m_in.standSpeed);
		headBobScale = min(1.0f, headBobScale);
		m_io.bobOffset = m_io.vFPWeaponOffset * 2.5f * g_pGameCVars->cl_headBob * headBobScale;
		float bobLenSq = m_io.bobOffset.GetLengthSquared();
		float bobLenLimit = g_pGameCVars->cl_headBobLimit;

		if (bobLenSq > bobLenLimit * bobLenLimit)
		{
			float bobLen = sqrt_tpl(bobLenSq);
			m_io.bobOffset *= bobLenLimit / bobLen;
		}

		viewParams.position += m_io.bobOffset;
	}
}
Example #7
0
void CPlayerInput::PreUpdate()
{
	CMovementRequest request;
	
	// get rotation into a manageable form
	float mouseSensitivity;
	if (m_pPlayer->InZeroG())
		mouseSensitivity = 0.00333f*MAX(0.01f, g_pGameCVars->cl_sensitivityZeroG);
	else
		mouseSensitivity = 0.00333f*MAX(0.01f, g_pGameCVars->cl_sensitivity);

	mouseSensitivity *= gf_PI / 180.0f;//doesnt make much sense, but after all helps to keep reasonable values for the sensitivity cvars
	//these 2 could be moved to CPlayerRotation
	mouseSensitivity *= m_pPlayer->m_params.viewSensitivity;
	mouseSensitivity *= m_pPlayer->GetMassFactor();
	COffHand * pOffHand=static_cast<COffHand*>(m_pPlayer->GetWeaponByClass(CItem::sOffHandClass));
	if(pOffHand && (pOffHand->GetOffHandState()&eOHS_HOLDING_NPC))
		mouseSensitivity *= pOffHand->GetObjectMassScale();

	// When carrying object/enemy, adapt mouse sensitiviy to feel the weight
	// Designers requested we ignore single-handed objects (1 == m_iCarryingObject)
	if(2 == m_iCarryingObject)
	{
		mouseSensitivity /= 2.0f;
	}

	if(m_fCrouchPressedTime>0.0f)
	{
		float fNow = gEnv->pTimer->GetAsyncTime().GetMilliSeconds();
		if((fNow - m_fCrouchPressedTime) > 300.0f)
		{
			if(m_actions & ACTION_CROUCH)
			{
				m_actions &= ~ACTION_CROUCH;
				m_actions |= ACTION_PRONE;
			}
			m_fCrouchPressedTime = -1.0f;
		}
	}

	Ang3 deltaRotation(m_deltaRotation * mouseSensitivity);

	if (m_pStats->isFrozen.Value() && m_pPlayer->IsPlayer() && m_pPlayer->GetHealth()>0)
	{
		float sMin = g_pGameCVars->cl_frozenSensMin;
		float sMax = g_pGameCVars->cl_frozenSensMax;

		float mult = sMin + (sMax-sMin)*(1.f-m_pPlayer->GetFrozenAmount(true));    
		deltaRotation *= mult;

		m_pPlayer->UpdateUnfreezeInput(m_deltaRotation, m_deltaMovement-m_deltaMovementPrev, mult);
	}

	// apply rotation from xinput controller
	if(!m_bDisabledXIRot)
	{
		// Controller framerate compensation needs frame time! 
		// The constant is to counter for small frame time values.
		// adjust some too small values, should be handled differently later on
		Ang3 xiDeltaRot=m_xi_deltaRotation*gEnv->pTimer->GetFrameTime() * mouseSensitivity * 50.0f;
		SmoothControllerInput(xiDeltaRot);
		ControlCameraMode();

		// Applying aspect modifiers
		if (g_pGameCVars->ctrl_aspectCorrection > 0)
		{
			int vx, vy, vw, vh;
			gEnv->pRenderer->GetViewport(&vx, &vy, &vw, &vh);
			float med=((float)vw+vh)/2.0f;
			float crW=((float)vw)/med;
			float crH=((float)vh)/med;
			xiDeltaRot.x*=g_pGameCVars->ctrl_aspectCorrection == 2 ? crW : crH;
			xiDeltaRot.z*=g_pGameCVars->ctrl_aspectCorrection == 2 ? crH : crW;
		}

		if(g_pGameCVars->cl_invertController)
			xiDeltaRot.x*=-1;

		deltaRotation+=xiDeltaRot;

		IVehicle *pVehicle = m_pPlayer->GetLinkedVehicle();
		if (pVehicle)
		{
			if (m_pPlayer->m_pVehicleClient)
			{
				m_pPlayer->m_pVehicleClient->PreUpdate(pVehicle, m_pPlayer->GetEntityId(), gEnv->pTimer->GetFrameTime());
			}

			//FIXME:not really good
			m_actions = 0;
			m_deltaMovement.Set(0,0,0);
			m_deltaRotation.Set(0,0,0);
		}
	}

	if(m_bUseXIInput)
	{
		m_deltaMovement.x = m_xi_deltaMovement.x;
		m_deltaMovement.y = m_xi_deltaMovement.y;
		m_deltaMovement.z = 0;

		if (m_xi_deltaMovement.len2()>0.0f)
			m_actions |= ACTION_MOVE;
		else
			m_actions &= ~ACTION_MOVE;
	}

	bool animControlled(m_pPlayer->m_stats.animationControlled);

	// If there was a recent serialization, ignore the delta rotation, since it's accumulated over several frames.
	if ((m_lastSerializeFrameID + 2) > gEnv->pRenderer->GetFrameID())
		deltaRotation.Set(0,0,0);

	//if(m_pPlayer->m_stats.isOnLadder)
		//deltaRotation.z = 0.0f;

	const SCVars* pGameCVars = g_pGameCVars;
	if(pGameCVars->cl_cam_orbit != 0 && m_pPlayer->IsClient() && m_pPlayer->IsThirdPerson())
	{
		static bool IsInit = false;
		if (!IsInit)
		{
			m_pPlayer->m_camViewMtxFinal = Matrix33(gEnv->pRenderer->GetCamera().GetViewMatrix());
			IsInit = true;
		}

		float frameTime=gEnv->pTimer->GetFrameTime();
		float frameTimeNormalised=(frameTime>1 ? 1 : frameTime<0.0001f ? 0.0001f : frameTime)*30;	// 1/30th => 1 1/60th =>0.5 etc
		float frameTimeClamped=(frameTime>1 ? 1 : frameTime<0.0001f ? 0.0001f : frameTime);
		m_pCameraInputHelper->UpdateCameraInput(deltaRotation, frameTimeClamped,frameTimeNormalised);	// also modifies deltaRotation.
	}

	if (!animControlled)
		request.AddDeltaRotation( deltaRotation );

	// add some movement...
	if (!m_pStats->isFrozen.Value() && !animControlled)  
		request.AddDeltaMovement( FilterMovement(m_deltaMovement) );

  m_deltaMovementPrev = m_deltaMovement;

	// handle actions
	if (m_actions & ACTION_JUMP)
	{
		if (m_pPlayer->GetStance() != STANCE_PRONE)
			request.SetJump();
		else
			m_actions &= ~ACTION_JUMP;

		//m_actions &= ~ACTION_PRONE;

		/*if (m_pPlayer->GetStance() != STANCE_PRONE)
		{
			if(m_pPlayer->GetStance() == STANCE_STAND || m_pPlayer->TrySetStance(STANCE_STAND))
 				request.SetJump();
		}
		else if(!m_pPlayer->TrySetStance(STANCE_STAND))
			m_actions &= ~ACTION_JUMP;
		else
			m_actions &= ~ACTION_PRONE;*/
	}

	if (m_pPlayer->m_stats.isOnLadder)
	{
		m_actions &= ~ACTION_PRONE;
		m_actions &= ~ACTION_CROUCH;
	}
	
	request.SetStance(FigureOutStance());

	float pseudoSpeed = 0.0f;
	if (m_deltaMovement.len2() > 0.0f)
	{
		pseudoSpeed = m_pPlayer->CalculatePseudoSpeed(m_pPlayer->m_stats.bSprinting);
	}
	/* design changed: sprinting with controller is removed from full stick up to Left Bumper
	if(m_bUseXIInput && m_xi_deltaMovement.len2() > 0.999f)
	{
		m_actions |= ACTION_SPRINT;
	}
	else if(m_bUseXIInput)
	{
		m_actions &= ~ACTION_SPRINT;
	}*/
	request.SetPseudoSpeed(pseudoSpeed);

	if (m_deltaMovement.GetLength() > 0.1f)
	{
		float moveAngle = (float)RAD2DEG(fabs_tpl(cry_atan2f(-m_deltaMovement.x, fabsf(m_deltaMovement.y)<0.01f?0.01f:m_deltaMovement.y)));
		request.SetAllowStrafing(moveAngle > 20.0f);
	}
	else
	{
		request.SetAllowStrafing(true);
	}

	// send the movement request to the appropriate spot!
	m_pPlayer->m_pMovementController->RequestMovement( request );
	m_pPlayer->m_actions = m_actions;

	// reset things for next frame that need to be
	m_lastMouseRawInput = m_deltaRotation;
	m_deltaRotation = Ang3(0,0,0);

	//static float color[] = {1,1,1,1};    
  //gEnv->pRenderer->Draw2dLabel(100,50,1.5,color,false,"deltaMovement:%f,%f", m_deltaMovement.x,m_deltaMovement.y);

  // PLAYERPREDICTION
  m_pPlayer->GetGameObject()->ChangedNetworkState(INPUT_ASPECT);
  // ~PLAYERPREDICTION

}
void CPlayerView::ViewFirstThirdSharedPost(SViewParams &viewParams)
{
	//--- Update the eye offset and apply
	{
		// Blend towards the goal eye offset
		float stanceTransitionSpeed = g_pGameCVars->g_stanceTransitionSpeed;

		if (m_in.stance == STANCE_PRONE)
		{
			stanceTransitionSpeed = 8;
		}

		Interpolate(m_io.eyeOffsetView, m_io.eyeOffsetViewGoal, stanceTransitionSpeed, m_in.frameTime);

		//apply eye offset
		if (!m_io.bUsePivot)
		{
			//apply some more offset to the view
			viewParams.position += m_io.baseQuat * m_io.eyeOffsetView;

			if (m_in.stats_firstPersonBody == 2)
			{
				float lookDown(m_io.viewQuatFinal.GetColumn1() * m_io.baseQuat.GetColumn2());
				float forwardOffset(0.0f);

				if (m_in.stance == STANCE_STAND)
				{
					forwardOffset = 0.15f;
				}

				viewParams.position += m_io.viewQuatFinal.GetColumn1() * max(-lookDown, 0.0f) * forwardOffset + m_io.viewQuatFinal.GetColumn2() * max(-lookDown, 0.0f) * 0.0f;

				//Grabbed by the Hunter
				if(m_in.bIsGrabbed && !m_in.bIsThirdPerson)
				{
					viewParams.position = m_in.entityWorldMatrix.TransformPoint(m_io.eyeOffsetView);
				}
			}
		}
	}

	if(g_pGameCVars->g_detachCamera != 0)
	{
		viewParams.position = m_in.lastPos;
		viewParams.rotation = m_in.lastQuat;
	}

	//--- Weapon orientation
	//FIXME: this should be done in the player update anyway.
	//And all the view position update. (because the game may need to know other players eyepos and such)
	//update first person weapon model position/angles
	{
		Quat wQuat(m_io.viewQuatForWeapon * Quat::CreateRotationXYZ(m_io.vFPWeaponAngleOffset * gf_PI / 180.0f));
		//wQuat *= Quat::CreateSlerp(viewParams.shakeQuat,IDENTITY,0.5f);
		wQuat *= Quat::CreateSlerp(viewParams.currentShakeQuat, IDENTITY, 0.5f);
		wQuat.NormalizeSafe();
		m_io.wAngles = Ang3(wQuat);
	}

	//smooth out the view elevation
	if (m_in.stats_inAir < 0.1f && !m_in.stats_flyMode && !m_in.stats_spectatorMode && !m_io.bUsePivot)
	{
		if (m_io.stats_smoothZType != 1)
		{
			m_io.stats_smoothViewZ = viewParams.position.z;
			m_io.stats_smoothZType = 1;
		}

		Interpolate(m_io.stats_smoothViewZ, viewParams.position.z, 15.0f, m_in.frameTime);
		viewParams.position.z = m_io.stats_smoothViewZ;
	}
	else
	{
		if (m_io.stats_smoothZType == 1)
		{
			m_io.stats_smoothViewZ = m_in.lastPos.z - m_io.stats_smoothViewZ;
			m_io.stats_smoothZType = 2;
		}

		Interpolate(m_io.stats_smoothViewZ, 0.0f, 15.0f, m_in.frameTime);
		viewParams.position.z += m_io.stats_smoothViewZ;
	}
}
//------------------------------------------------------------------------
void CRapid::Update(float frameTime, uint32 frameId)
{
	FUNCTION_PROFILER( GetISystem(), PROFILE_GAME );
	CSingle::Update(frameTime, frameId);

	if (m_speed <= 0.0f && m_acceleration < 0.0001f)
	{
		if(m_decelerating)
		{
			FinishDeceleration();
		}

		return;
	}

	m_pWeapon->RequireUpdate(eIUS_FireMode);
	m_speed = m_speed + m_acceleration * frameTime;

	if (m_speed > m_pShared->rapidparams.max_speed)
	{
		m_speed = m_pShared->rapidparams.max_speed;
		m_accelerating = false;
	}

	if ((m_speed >= m_pShared->rapidparams.min_speed) && (!m_decelerating))
	{
		float dt = 1.0f;

		if (cry_fabsf(m_speed) > 0.001f && cry_fabsf(m_pShared->rapidparams.max_speed > 0.001f))
		{
			dt = m_speed / m_pShared->rapidparams.max_speed;
		}

		m_next_shot_dt = 60.0f / (m_pShared->fireparams.rate * dt);
		bool canShoot = CanFire(false);

		if (canShoot)
		{
			if (!OutOfAmmo())
			{
				if (m_netshooting)
				{
					Firing(true);
				}
				else
				{
					Firing(Shoot(true, false));
				}

				if (m_firing && !(m_pShared->rapidparams.camshake_rotate.IsZero() && m_pShared->rapidparams.camshake_shift.IsZero()))
				{
					CActor *act = m_pWeapon->GetOwnerActor();

					if (act && act->IsClient())
					{
						IView *pView = g_pGame->GetIGameFramework()->GetIViewSystem()->GetActiveView();

						if (pView)
						{
							pView->SetViewShake(Ang3(m_pShared->rapidparams.camshake_rotate), m_pShared->rapidparams.camshake_shift, m_next_shot_dt / m_pShared->rapidparams.camshake_perShot, m_next_shot_dt / m_pShared->rapidparams.camshake_perShot, 0, 1);
						}
					}
				}
			}
			else
			{
				Firing(false);
				Accelerate(m_pShared->rapidparams.deceleration);

				if (m_pWeapon->GetOwnerActor() && m_pWeapon->GetOwnerActor()->IsPlayer())
				{
					SmokeEffect();
					m_pWeapon->Reload();
				}
			}
		}
	}
	else if (m_firing)
	{
		Firing(false);

		if (OutOfAmmo() && m_pWeapon->GetOwnerActor() && m_pWeapon->GetOwnerActor()->IsPlayer())
		{
			SmokeEffect();
			m_pWeapon->Reload();
		}
	}

	if ((m_speed < m_pShared->rapidparams.min_speed) && (m_acceleration < 0.0f) && (!m_decelerating))
	{
		Accelerate(m_pShared->rapidparams.deceleration);
	}

	UpdateRotation(frameTime);
	UpdateSound(frameTime);
}
	virtual void ProcessEvent( EFlowEvent event,SActivationInfo* pActInfo )
	{
		switch (event)
		{
		case eFE_Activate:
		{
			m_lastTime = gEnv->pTimer->GetFrameStartTime();
			m_bActive  = !GetPortBool(pActInfo, 1);
			pActInfo->pGraph->SetRegularlyUpdated( pActInfo->myID, m_bActive );

			if (!m_bActive)
			{
				ResetVelocity(pActInfo);
			}
		}

		break;
		case eFE_Initialize:
		{
			if (pActInfo->pEntity)
				m_localRot = pActInfo->pEntity->GetRotation();
			else
				m_localRot.SetIdentity();
			m_worldRot.SetIdentity();
			m_lastTime = gEnv->pTimer->GetFrameStartTime();
			m_bActive  = !GetPortBool(pActInfo, 1);
			pActInfo->pGraph->SetRegularlyUpdated( pActInfo->myID, m_bActive );
			break;
		}

		case eFE_Update:
		{
			if (m_bActive && pActInfo->pEntity)
			{
				CTimeValue time           = gEnv->pTimer->GetFrameStartTime();
				float      timeDifference = (time - m_lastTime).GetSeconds();
				m_lastTime = time;

				IEntity*   pEntity   = pActInfo->pEntity;
				const bool bUseWorld = GetPortInt(pActInfo, 2) == 0 ? true : false;
				Vec3       speed     = GetPortVec3(pActInfo, 0);
				speed *= timeDifference;
				Quat deltaRot (Ang3(DEG2RAD(speed)));
				Quat finalRot;
				if (bUseWorld == false)
				{
					finalRot  = pEntity->GetRotation();
					finalRot *= deltaRot;
				}
				else
				{
					m_worldRot *= deltaRot;
					finalRot    = m_worldRot;
					finalRot   *= m_localRot;
				}
				finalRot.NormalizeSafe();

				IPhysicalEntity* piPhysEnt = pEntity->GetPhysics();
				if (piPhysEnt && piPhysEnt->GetType() != PE_STATIC)
				{
					if (timeDifference > 0.0001f)
					{
						pe_action_set_velocity asv;
						asv.w                    = Quat::log(deltaRot) * (2.f / timeDifference);
						asv.bRotationAroundPivot = 1;
						pEntity->GetPhysics()->Action(&asv);
					}
				}
				else
				{
					pEntity->SetRotation(finalRot);
				}
				Ang3 currentAng = Ang3(finalRot);
				ActivateOutput(pActInfo, 1, Vec3(currentAng));
				currentAng = RAD2DEG(currentAng);
				ActivateOutput(pActInfo, 0, Vec3(currentAng));
			}
			break;
		}
		}
	}
Example #11
0
//--------------------------------------------------------------------------------------------------
// Name: SpawnScreenExplosionEffect
// Desc: Spawns screen explosion effect
//--------------------------------------------------------------------------------------------------
void CExplosionGameEffect::SpawnScreenExplosionEffect(const SExplosionContainer &explosionContainer)
{
	// Disclaimer: this code was originally from GameRulesClientServer::ProcessClientExplosionScreenFX()

	const ExplosionInfo& explosionInfo = explosionContainer.m_explosionInfo;

	if(explosionInfo.pressure < 1.0f)
		return;

	IActor *pClientActor = g_pGame->GetIGameFramework()->GetClientActor();
	if(pClientActor != NULL && !pClientActor->IsDead())
	{
		CPlayer* pPlayer = static_cast<CPlayer*>(pClientActor);
		bool hasFlashBangEffect = explosionInfo.blindAmount > 0.0f;

		// Flashbang friends and self?...
		if(hasFlashBangEffect)
		{
			bool flashBangSelf = true;
			bool flashBangFriends = false;
#ifndef _RELEASE
			flashBangSelf = g_pGameCVars->g_flashBangSelf != 0;
			flashBangFriends = g_pGameCVars->g_flashBangFriends != 0;
#endif
			bool ownFlashBang = pPlayer->GetEntityId() == explosionInfo.shooterId;
			if((!flashBangSelf && ownFlashBang) || // FlashBang self?
				((g_pGame->GetGameRules()->GetFriendlyFireRatio()<=0.0f) && (!flashBangFriends) && (!ownFlashBang) && pPlayer->IsFriendlyEntity(explosionInfo.shooterId))) // FlashBang friends?
			{
				return;
			}
		}

		// Distance
		float dist = (pClientActor->GetEntity()->GetWorldPos() - explosionInfo.pos).len();

		// Is the explosion in Player's FOV (let's suppose the FOV a bit higher, like 80)
		SMovementState state;
		if(IMovementController *pMV = pClientActor->GetMovementController())
		{
			pMV->GetMovementState(state);
		}

		Vec3 eyeToExplosion = explosionInfo.pos - state.eyePosition;
		Vec3 eyeDir = pClientActor->GetLinkedVehicle() ? pPlayer->GetVehicleViewDir() : state.eyeDirection;
		eyeToExplosion.Normalize();
		float eyeDirectionDP = eyeDir.Dot(eyeToExplosion);
		bool inFOV = (eyeDirectionDP > 0.68f);

		// All explosions have radial blur (default 30m radius)
		const float maxBlurDistance = (explosionInfo.maxblurdistance >0.0f) ? explosionInfo.maxblurdistance : 30.0f;
		if((maxBlurDistance > 0.0f) && (g_pGameCVars->g_radialBlur > 0.0f) && (explosionInfo.radius > 0.5f))
		{		
			if (inFOV && (dist < maxBlurDistance))
			{
				const int intersectionObjTypes = ent_static | ent_terrain;
				const unsigned int intersectionFlags = rwi_stop_at_pierceable|rwi_colltype_any;

				m_deferredScreenEffects.RequestRayCast(CDeferredExplosionEffect::eDET_RadialBlur, 
														explosionInfo.pos, -eyeToExplosion, dist, maxBlurDistance, intersectionObjTypes, intersectionFlags, NULL, 0);
			}
		}

		// Flashbang effect 
		if(hasFlashBangEffect && ((dist < (explosionInfo.radius*g_pGameCVars->g_flashBangNotInFOVRadiusFraction)) 
			|| (inFOV && (dist < explosionInfo.radius))))
		{
			ray_hit hit;
			const int intersectionObjTypes = ent_static | ent_terrain;
			const unsigned int intersectionFlags = rwi_stop_at_pierceable|rwi_colltype_any;
			const int intersectionMaxHits = 1;

			int collision = gEnv->pPhysicalWorld->RayWorldIntersection(	explosionInfo.pos, 
																																	-eyeToExplosion*dist, 
																																	intersectionObjTypes, 
																																	intersectionFlags, 
																																	&hit, 
																																	intersectionMaxHits);

			// If there was no obstacle between flashbang grenade and player
			if(!collision)
			{
				bool enabled = true;
				if(enabled)
				{
					CCCPOINT (FlashBang_Explode_BlindLocalPlayer);
					float timeScale = max(0.0f, 1 - (dist/explosionInfo.radius));
					float lookingAt = max(g_pGameCVars->g_flashBangMinFOVMultiplier, (eyeDirectionDP + 1)*0.5f);

					float time = explosionInfo.flashbangScale * timeScale *lookingAt;	// time is determined by distance to explosion		

					CRY_ASSERT_MESSAGE(pClientActor->IsPlayer(),"Effect shouldn't be spawned if not a player");

					SPlayerStats* pStats = static_cast<SPlayerStats*>(pPlayer->GetActorStats());

					NET_BATTLECHATTER(BC_Blinded, pPlayer);

					if(pClientActor->GetEntityId() == explosionInfo.shooterId)
					{
						g_pGame->GetPersistantStats()->IncrementClientStats(EIPS_BlindSelf);
					}
					else
					{
						g_pGame->GetGameRules()->SuccessfulFlashBang(explosionInfo, time);
					}

					pPlayer->StartFlashbangEffects(time, explosionInfo.shooterId);

					gEnv->p3DEngine->SetPostEffectParam("Flashbang_Time", time);
					gEnv->p3DEngine->SetPostEffectParam("FlashBang_BlindAmount", explosionInfo.blindAmount);
					gEnv->p3DEngine->SetPostEffectParam("Flashbang_DifractionAmount", time);
					gEnv->p3DEngine->SetPostEffectParam("Flashbang_Active", 1.0f);

					CRecordingSystem *pRecordingSystem = g_pGame->GetRecordingSystem();
					if (pRecordingSystem)
					{
						pRecordingSystem->OnPlayerFlashed(time, explosionInfo.blindAmount);
					}
				}
			}
			else
			{
				CCCPOINT (FlashBang_Explode_NearbyButBlockedByGeometry);
			}
		}
		else if(inFOV && (dist < explosionInfo.radius))
		{
			if(explosionInfo.damage>10.0f || explosionInfo.pressure>100.0f)
			{
				// Add some angular impulse to the client actor depending on distance, direction...
				float dt = (1.0f - dist/explosionInfo.radius);
				dt = dt * dt;
				float angleZ = gf_PI*0.15f*dt;
				float angleX = gf_PI*0.15f*dt;

				if (pClientActor)
				{
					static_cast<CActor*>(pClientActor)->AddAngularImpulse(Ang3(Random(-angleX*0.5f,angleX),0.0f,Random(-angleZ,angleZ)),0.0f,dt*2.0f);
				}
			}
		}
	}
}//-------------------------------------------------------------------------------------------------
Example #12
0
	virtual void ProcessEvent(EFlowEvent event, SActivationInfo *pActInfo)
	{
		switch (event)
		{
		case eFE_Initialize:
			{
				if (pActInfo->pGraph != nullptr)
				{
					const bool enabled = GetPortBool( pActInfo, EIP_Enabled );
					pActInfo->pGraph->SetRegularlyUpdated( pActInfo->myID, enabled );
				}
			}
			break;

		case eFE_Activate:
			{
				if (IsPortActive(pActInfo, EIP_Enabled)) 
				{
					const bool enabled = GetPortBool( pActInfo, EIP_Enabled );
					pActInfo->pGraph->SetRegularlyUpdated( pActInfo->myID, enabled );
				}
			}
			break;

		case eFE_Update:
			{
				// Camera info
				IRenderer * pRenderer = gEnv->pRenderer;
				if (pRenderer)
				{
					const CCamera &rCam = pRenderer->GetCamera();
					const Ang3 angles = RAD2DEG(rCam.GetAngles());

					ActivateOutput(pActInfo, EOP_CamPos, rCam.GetPosition());
					ActivateOutput(pActInfo, EOP_CamRot, Vec3(angles));
				}
				
				ActivateOutput(pActInfo, EOP_CamDataValid, pRenderer != nullptr);
				
				// HMD info
				IHMDManager * pHmdManager = gEnv->pSystem->GetHMDManager();
				bool bHmdOk = false;
				if (pHmdManager != nullptr)
				{	
					const HMDTrackingState& sensorState = pHmdManager->GetHMDDevice()->GetWorldTrackingState();
					if (sensorState.CheckStatusFlags(HS_IsUsable))
					{
						bHmdOk = true;
						Ang3 hmdAngles(sensorState.pose.orientation);
						ActivateOutput(pActInfo, EOP_HmdRot, Vec3(RAD2DEG(hmdAngles)));
						ActivateOutput(pActInfo, EOP_HmdPos, sensorState.pose.position);
					}
				}

				ActivateOutput(pActInfo, EOP_HmdDataValid, bHmdOk);

				// Player Info
				CPlayer* pLocalPlayer = static_cast<CPlayer*>(g_pGame->GetIGameFramework()->GetClientActor());
				if (pLocalPlayer)
				{
					Vec3 entityRotationInDegrees(RAD2DEG(Ang3(pLocalPlayer->GetViewQuat())));
					ActivateOutput(pActInfo, EOP_PlayerViewRot, entityRotationInDegrees);
					ActivateOutput(pActInfo, EOP_PlayerPos, pLocalPlayer->GetEntity()->GetWorldPos());
				}

				ActivateOutput(pActInfo, EOP_PlayerDataValid, pLocalPlayer != nullptr);
			}
			break;
		}
	}
Example #13
0
//------------------------------------------------------------------------
EntityId CScriptBind_GameRules::SpawnPlayer(int channelId, mono::string name, mono::string className, Vec3 pos, Vec3 angles)
{
	return g_pGame->GetGameRules()->SpawnPlayer(channelId, *name, *className, pos, Ang3(angles))->GetEntityId();
}
	virtual void OnEditorMovedTransformGizmo(const QuatT& gizmoLocation)
	{
		posOffset = gizmoLocation.t;
		rotOffset = Ang3(gizmoLocation.q);
	}
Example #15
0
void CUIHUD3D::UpdateView(const SViewParams &viewParams)
{
	CActor* pLocalPlayer = (CActor*)g_pGame->GetIGameFramework()->GetClientActor();
	
	if (gEnv->IsEditor() && !gEnv->IsEditing() && !m_pHUDRootEntity)
		SpawnHudEntities();

	// When you die we destroy the HUD, so this will make sure it re-spawns when you respawned
	if (!gEnv->IsEditor() && !m_pHUDRootEntity)
		SpawnHudEntities();
	
	const CUICVars* pCVars = g_pGame->GetUI()->GetCVars();
	if (m_pHUDRootEntity && pLocalPlayer)
	{
		if(pCVars->hud_detach)
			return;

		const QuatT& cameraTran = pLocalPlayer->GetCameraTran();
		const QuatT& hudTran = pLocalPlayer->GetHUDTran();

		const Quat& cameraRotation = cameraTran.q;
		const Quat& hudRotation = hudTran.q;
		Quat deltaHudRotation = cameraRotation.GetInverted() * hudRotation;

		if(pCVars->hud_bobHud > 0.0f && !pLocalPlayer->IsDead())
		{
			deltaHudRotation.w *= (float)__fres(pCVars->hud_bobHud);

			// Avoid divide by 0  
			if (!(fabs(deltaHudRotation.w) < FLT_EPSILON)) // IsValid() doesn't catch it
			{
				deltaHudRotation.Normalize();
			}
		}
		else
		{
			deltaHudRotation.SetIdentity();
		}

		// In general use the player position + viewparams override
		Vec3 viewPosition = pLocalPlayer->GetEntity()->GetPos() + viewParams.position;
		Quat clientRotation = viewParams.rotation * deltaHudRotation;
		
		// Override special cases: Third person should use camera-oriented HUD instead of HUD-bone oriented
		// Sliding should use the Bone instead of the viewParams solution
		if(pLocalPlayer->IsThirdPerson() || pLocalPlayer->GetLinkedVehicle() != NULL)
		{
			viewPosition = viewParams.position;
		}
		else
		{
			CPlayer* player = (CPlayer*)pLocalPlayer;
			if(player && player->IsSliding())
			{
				viewPosition = pLocalPlayer->GetEntity()->GetWorldTM().TransformPoint(hudTran.t);
			}
		}
		//

		const Vec3 forward(clientRotation.GetColumn1());
		const Vec3 up(clientRotation.GetColumn2());
		const Vec3 right(-(up % forward));

		const float distance = pCVars->hud_cameraOverride ? pCVars->hud_cameraDistance : m_fHudDist;
		const float offset = pCVars->hud_cameraOverride ? pCVars->hud_cameraOffsetZ  : m_fHudZOffset;

		float offsetScale = 1.0f;
		if(viewParams.fov > 0.0f)
		{
			offsetScale = (pCVars->hud_cgf_positionScaleFOV * __fres(viewParams.fov )) + distance;
		}
		
		// Allow overscanBorders to control safe zones
		Vec2 overscanBorders = ZERO;
		if(gEnv->pRenderer)
		{	
			gEnv->pRenderer->EF_Query(EFQ_OverscanBorders, overscanBorders);
		}
		const float viewDepth = 1.0f + (pCVars->hud_overscanBorder_depthScale * overscanBorders.y);
		viewPosition += forward*viewDepth*offsetScale;

		viewPosition += (up * offset);
		viewPosition += (right * pCVars->hud_cgf_positionRightScale);
		const Vec3 posVec(viewPosition + (forward * 0.001f));

		static const Quat rot90Deg = Quat::CreateRotationXYZ( Ang3(gf_PI * 0.5f, 0, 0) );
		const Quat rotation = clientRotation * rot90Deg; // rotate 90 degrees around X-Axis

		m_pHUDRootEntity->SetPosRotScale(posVec, rotation, m_pHUDRootEntity->GetScale(), ENTITY_XFORM_NO_SEND_TO_ENTITY_SYSTEM);
	}

	if (gEnv->pRenderer && m_pHUDRootEntity && pCVars->hud_debug3dpos > 0)
	{
		gEnv->pRenderer->GetIRenderAuxGeom()->DrawSphere(m_pHUDRootEntity->GetWorldPos(), 0.2f, ColorB(255,0,0));
		const int children = m_pHUDRootEntity->GetChildCount();
		for (int i = 0; i < children && pCVars->hud_debug3dpos > 1; ++i)
		{
			IEntity* pChild = m_pHUDRootEntity->GetChild(i);
			gEnv->pRenderer->GetIRenderAuxGeom()->DrawSphere(pChild->GetWorldPos(), 0.1f, ColorB(255,255,0));
		}
	}
}