CExactPositioningTrigger::CExactPositioningTrigger( const Vec3& pos, float width, const Vec3& triggerSize, const Quat& orient, float orientTolerance, float animMovementLength )
	: m_pos(pos)
	, m_width(width)
	, m_posSize(triggerSize)
	, m_orient(orient)
	, m_cosOrientTolerance(cos(orientTolerance))
	, m_sideTime(0)
	, m_distanceErrorFactor(1.0f)
	, m_animMovementLength(0)
	, m_distanceError(1000.0f)
	, m_orientError(1000.0f)
	, m_oldFwdDir(0.0f)
	, m_state(eS_Initializing)
	, m_userPos(pos)
	, m_userOrient(orient)
{
	CRY_ASSERT(m_pos.IsValid());
	CRY_ASSERT(m_userPos.IsValid());
	CRY_ASSERT(m_orient.IsValid());
	CRY_ASSERT(m_userOrient.IsValid());
	CRY_ASSERT(m_posSize.IsValid());
	CRY_ASSERT(NumberValid(m_cosOrientTolerance));
	CRY_ASSERT(NumberValid(m_width));

	// Make sure we have bigger than zero length, 
	// so that the error measurement is not zero no matter what direction.
	m_animMovementLength = max(animMovementLength, 2.0f);

	// Make sure the trigger is not rotated, only Z-axis rotations are allowed
	m_orient.v.x = m_orient.v.y = 0.0f; m_orient.Normalize();
	m_userOrient = m_orient;
}
void CExactPositioningTrigger::ResetRadius( const Vec3& triggerSize, float orientTolerance )
{
	CRY_ASSERT(m_pos.IsValid());
	CRY_ASSERT(m_userPos.IsValid());
	CRY_ASSERT(m_orient.IsValid());
	CRY_ASSERT(m_userOrient.IsValid());
	CRY_ASSERT(m_posSize.IsValid());
	CRY_ASSERT(NumberValid(m_cosOrientTolerance));

	if (m_state == eS_Invalid)
		return;
	m_state = eS_Initializing;
	m_posSize = triggerSize;
	m_cosOrientTolerance = cos(orientTolerance);

	// TODO: Update should not be called here. Maybe it's only used to set some values or something, not really an update.
	Update( 0.0f, m_userPos, m_userOrient, false );
}
Exemplo n.º 3
0
void CPlayerStateUtil::ApplyFallDamage( CPlayer& player, const float startFallingHeight, const float fHeightofEntity )
{
	CRY_ASSERT(player.IsClient());

	// Zero downwards impact velocity used for fall damage calculations if player was in water within the last 0.5 seconds.
	// Strength jumping straight up and down should theoretically land with a safe velocity, 
	// but together with the water surface stickyness the velocity can sometimes go above the safe impact velocity threshold.

	// DEPRECATED: comment left for prosterity in case dedicated server problems re-appear (author cannot test it).
	// On dedicated server the player can still be flying this frame as well, 
	// since synced pos from client is interpolated/smoothed and will not land immediately,
	// even though the velocity is set to zero.
	// Thus we need to use the velocity change instead of landing to identify impact.

	// DT: 12475: Falling a huge distance to a ledge grab results in no damage.
	// Now using the last velocity because when ledge grabbing the velocity is unchanged for this frame, thus zero damage is applied.
	// Assuming this a physics lag issue, using the last good velocity should be more-or-less ok.
	const float downwardsImpactSpeed = -(float)__fsel(-(player.m_playerStateSwim_WaterTestProxy.GetSwimmingTimer() + 0.5f), player.GetActorPhysics().velocityUnconstrainedLast.z, 0.0f);

	const SPlayerStats& stats = *player.GetActorStats();

	CRY_ASSERT(NumberValid(downwardsImpactSpeed));
	const float MIN_FALL_DAMAGE_DISTANCE = 3.0f;
	const float fallDist = startFallingHeight - fHeightofEntity;
	if ((downwardsImpactSpeed > 0.0f) && (fallDist > MIN_FALL_DAMAGE_DISTANCE))
	{
		const SPlayerHealth& healthCVars = g_pGameCVars->pl_health;

		float velSafe = healthCVars.fallDamage_SpeedSafe;
		float velFatal = healthCVars.fallDamage_SpeedFatal;
		float velFraction = (float)__fsel(-(velFatal - velSafe), 1.0f , (downwardsImpactSpeed - velSafe) * (float)__fres(velFatal - velSafe));

		CRY_ASSERT(NumberValid(velFraction));

		if (velFraction > 0.0f)
		{
			//Stop crouching after taking falling damage
			if(player.GetStance() == STANCE_CROUCH)
			{
				static_cast<CPlayerInput*>(player.GetPlayerInput())->ClearCrouchAction();
			}

			velFraction = powf(velFraction, gEnv->bMultiplayer ? healthCVars.fallDamage_CurveAttackMP : healthCVars.fallDamage_CurveAttack);

			const float maxHealth = player.GetMaxHealth();
			const float currentHealth  = player.GetHealth();

			HitInfo hit;
			hit.dir.zero();
			hit.type = CGameRules::EHitType::Fall;
			hit.shooterId = hit.targetId = hit.weaponId = player.GetEntityId();

			const float maxDamage = (float)__fsel(velFraction - 1.0f, maxHealth, max(0.0f, (gEnv->bMultiplayer?maxHealth:currentHealth) - healthCVars.fallDamage_health_threshold));

			hit.damage = velFraction * maxDamage;

			g_pGame->GetGameRules()->ClientHit(hit);

#ifdef PLAYER_MOVEMENT_DEBUG_ENABLED
			player.GetMovementDebug().LogFallDamage(player.GetEntity(), velFraction, downwardsImpactSpeed, hit.damage);
		}
		else
		{
			player.GetMovementDebug().LogFallDamageNone(player.GetEntity(), downwardsImpactSpeed);
		}
#else
		}
#endif
	}
void CExactPositioningTrigger::Update( float frameTime, Vec3 userPos, Quat userOrient, bool allowTriggering )
{
	if (m_state == eS_Invalid)
		return;

	CRY_ASSERT(m_pos.IsValid());
	CRY_ASSERT(m_userPos.IsValid());
	CRY_ASSERT(m_orient.IsValid());
	CRY_ASSERT(m_userOrient.IsValid());
	CRY_ASSERT(m_posSize.IsValid());
	CRY_ASSERT(NumberValid(m_cosOrientTolerance));

	CRY_ASSERT(NumberValid(frameTime));
	CRY_ASSERT(userPos.IsValid());
	CRY_ASSERT(userOrient.IsValid());

	m_userPos = userPos;
	m_userOrient = userOrient;

	if (m_state == eS_Initializing)
		m_state = eS_Before;

	Plane threshold;
	threshold.SetPlane( m_orient.GetColumn1(), m_pos );
	if (threshold.DistFromPlane(userPos) >= 0.0f)
	{
		if (m_sideTime < 0.0f)
			m_sideTime = 0.0f;
		else
			m_sideTime += frameTime;
	}
	else
	{
		if (m_sideTime > 0.0f)
			m_sideTime = 0.0f;
		else
			m_sideTime -= frameTime;
	}

	Vec3 curDir = userOrient.GetColumn1();
	Vec3 wantDir = m_orient.GetColumn1();

	if (m_state == eS_Before)
	{
		OBB triggerBox;
		triggerBox.SetOBB( Matrix33(m_orient), m_posSize+Vec3(0.5f,0.5f,0), ZERO );
		if (Overlap::Point_OBB(m_userPos, m_pos, triggerBox))
			m_state = eS_Optimizing;
	}

	if ((m_state == eS_Optimizing) && allowTriggering)
	{
#ifdef INCLUDE_EXACTPOS_DEBUGGING
		bool debug = (CAnimationGraphCVars::Get().m_debugExactPos != 0);
		CPersistantDebug* pPD = CCryAction::GetCryAction()->GetPersistantDebug();
#endif

		Vec3 bump(0.0f, 0.0f, 0.1f);

		Vec3 posDistanceError = m_userPos - m_pos;
		if ( posDistanceError.z > -1.0f && posDistanceError.z < 1.0f )
			posDistanceError.z = 0;

		Vec3 orientFwd = m_orient.GetColumn1(); orientFwd.z = 0.0f; orientFwd.Normalize();
		Vec3 rotAnimMovementWanted = orientFwd * m_animMovementLength;

		Vec3 userFwd = m_userOrient.GetColumn1(); userFwd.z = 0.0f; userFwd.Normalize();
		Vec3 rotAnimMovementUser = userFwd * m_animMovementLength;

		float cosRotError = orientFwd.Dot( userFwd );
		float rotError = CLAMP(m_cosOrientTolerance - cosRotError, 0.0f, 1.0f);
		//Vec3 rotDistanceError = rotAnimMovementUser - rotAnimMovementWanted;

		float fwdDistance = fabsf(orientFwd.Dot( posDistanceError ));
		float sideDistance = max( 0.0f, sqrtf( MAX(0,posDistanceError.GetLengthSquared2D() - sqr(fwdDistance)) ) - m_width );

		float deltaFwd = m_oldFwdDir < fwdDistance ? fwdDistance - m_oldFwdDir : 0.0f;
		m_oldFwdDir = fwdDistance;
		fwdDistance += deltaFwd * 0.5f;
		deltaFwd = max(0.1f, deltaFwd);

		f32 distanceError = sqrtf(sqr(fwdDistance) + sqr(sideDistance)); // posDistanceError.len() * m_distanceErrorFactor;
		f32 temp = 1.0f-sqr(1.0f-rotError*rotError);
		temp = max(temp,0.0f); //never do a sqrtf with a negative value 
		f32 orientError = sqrtf(temp) * m_animMovementLength; // rotDistanceError.len();
		f32 totalDistanceError = distanceError + orientError;
		if (((m_distanceError * 1.05f) < distanceError) && ((m_orientError * 1.05f) < orientError) && (totalDistanceError < deltaFwd) ||
			(totalDistanceError < deltaFwd*0.5f))
		{ // found local minimum in distance error, force triggering.
			m_state = eS_Triggered;
			m_oldFwdDir = 0.0f;

#ifdef INCLUDE_EXACTPOS_DEBUGGING
			if (debug)
			{
				pPD->Begin("AnimationTrigger LocalMinima Triggered", false);
				pPD->AddPlanarDisc(m_pos + bump, 0.0f, m_distanceError, ColorF(0,1,0,0.5), 10.0f);
			}
#endif
		}
		else
		{
			m_distanceError = m_distanceError > distanceError ? distanceError : m_distanceError * 0.999f; // should timeout in ~2 secs. on 50 FPS
			m_orientError = m_orientError > orientError ? orientError : m_orientError - 0.0001f;

#ifdef INCLUDE_EXACTPOS_DEBUGGING
			if (debug)
			{
				pPD->Begin("AnimationTrigger LocalMinima Optimizing", true);
				pPD->AddPlanarDisc(m_pos + bump, 0.0f, m_distanceError, ColorF(1,1,0,0.5), 10.0f);
			}
#endif
		}

#ifdef INCLUDE_EXACTPOS_DEBUGGING
		if (debug)
		{
			pPD->AddLine(m_userPos + bump, m_pos + bump, ColorF(1,0,0,1), 10.0f);
			pPD->AddLine(m_userPos + rotAnimMovementUser + bump, m_pos + rotAnimMovementWanted + bump, ColorF(1,0,0,1), 10.0f);
			pPD->AddLine(m_pos + bump, m_pos + rotAnimMovementWanted + bump, ColorF(1,0.5,0,1), 10.0f);
			pPD->AddLine(m_userPos + bump, m_pos + rotAnimMovementUser + bump, ColorF(1,0.5,0,1), 10.0f);
		}
#endif
	}

	CRY_ASSERT(m_pos.IsValid());
	CRY_ASSERT(m_userPos.IsValid());
	CRY_ASSERT(m_orient.IsValid());
	CRY_ASSERT(m_userOrient.IsValid());
	CRY_ASSERT(m_posSize.IsValid());
	CRY_ASSERT(NumberValid(m_cosOrientTolerance));
}
Exemplo n.º 5
0
// ----------------------------------------------------------------------------
void CExactPositioning::UpdateTargetPointToFinishPoint() 
{
	if ( !m_pAnimatedCharacter )
		return;

	IEntity* pEntity = m_pAnimatedCharacter->GetEntity();
	if ( !pEntity )
		return;

	IActionController* pActionController = m_pAnimatedCharacter->GetActionController();
	if ( !pActionController )
		return;

	/*
	CPersistantDebug* pPD = CCryAction::GetCryAction()->GetPersistantDebug();
	bool debug = CAnimationGraphCVars::Get().m_debugExactPos != 0;
	if (debug)
		pPD->Begin( string( pEntity->GetName() ) + "_recalculatetriggerpositions", true );			

	Quat actorRot = pEntity->GetWorldRotation();

	Vec3 targetPosition = m_animationTargetRequest.position;
	Vec3 targetDirection = m_animationTargetRequest.direction.GetNormalizedSafe(ZERO);

	Vec3 bumpUp(0,0, pEntity->GetWorldPos().z+4);

	SAnimationMovement movement;
	float seconds = 0.0f;
	ColorF dbgClr1, dbgClr2;

	// TODO: figure out animationmovement and duration

	//seconds = m_triggerMovement.duration;
	//movement = m_triggerMovement;

	if ( m_pExactPositioningTarget->isNavigationalSO && movement.translation.IsZero( FLT_EPSILON ) )
	{
#if STORE_TAG_STRINGS
		const char* fragmentName = pActionController->GetContext().controllerDef.m_fragmentIDs.GetTagName( m_fragmentID );
#else
		const char* fragmentName = "<n/a>";
#endif

		CryWarning(
			VALIDATOR_MODULE_GAME,
			VALIDATOR_WARNING,
			"MannequinAGExactPositioning: Beaming back to the beginning of the smart object because the fragment had no translation: '%s' (id = %d) (entity = '%s'; controllerDef = '%s')",
			fragmentName ? fragmentName : "<invalid>",
			m_fragmentID,
			pEntity ? pEntity->GetName() : "<invalid>",
			pActionController->GetContext().controllerDef.m_filename );
	}

	targetPosition += Quat::CreateRotationV0V1( FORWARD_DIRECTION, targetDirection ) * movement.translation;
	targetDirection = movement.rotation * targetDirection;
	seconds = movement.duration;
	dbgClr1 = ColorF(1,1,0,1);
	dbgClr2 = ColorF(1,0,0,1);

	Vec3 realStartPosition = pEntity->GetWorldPos();
	Quat realStartOrientation = actorRot;

	if (debug)
	{
		pPD->Begin( string(pEntity->GetName()) + "_finalpathline", true );
		Vec3 targetPosition2D(targetPosition.x, targetPosition.y, realStartPosition.z);
		Vec3 realStartDirection = realStartOrientation.GetColumn1();
		pPD->AddLine(realStartPosition, targetPosition2D, ColorF(1,1,0,1), 5.0f);
		pPD->AddDirection(realStartPosition, 0.5f, realStartDirection, ColorF(1,0,0,1), 5.0f);
		pPD->AddDirection(targetPosition2D, 0.5f, targetDirection, ColorF(1,1,1,1), 5.0f);

		pPD->AddDirection(realStartPosition + bumpUp, 1, realStartOrientation.GetColumn1(), dbgClr1, 5);
		pPD->AddSphere(realStartPosition + bumpUp, 0.1f, dbgClr1, 5);
	}

	Quat startOrientation = realStartOrientation;
	// start orientation may not be within bounds; we'll fake things to get it there
	// figure out our expected end orientation, and hence direction
	Quat realEndOrientation = startOrientation * movement.rotation;
	Quat endOrientation = realEndOrientation;
	Vec3 realEndDirection = realEndOrientation.GetColumn1();
	Vec3 endDirection = realEndDirection;
	// how much are we out from our limitations?
	float dot = realEndDirection.Dot(targetDirection);
	float angleToDesiredDirection = acos_tpl( clamp_tpl(dot,-1.f,1.f) );
	if (angleToDesiredDirection > m_animationTargetRequest.directionTolerance)
	{
		float fractionOfTurnNeeded = m_animationTargetRequest.directionTolerance / angleToDesiredDirection;
		Quat rotationFromDesiredToCurrent = Quat::CreateRotationV0V1( targetDirection, realEndDirection );
		Quat amountToRotate = Quat::CreateSlerp( Quat::CreateIdentity(), rotationFromDesiredToCurrent, fractionOfTurnNeeded );
		endDirection = amountToRotate * targetDirection;
		endOrientation = Quat::CreateRotationV0V1( FORWARD_DIRECTION, endDirection );
		startOrientation = endOrientation * movement.rotation.GetInverted();
	}
	// find out approx. where the animation ends
	Vec3 realEndPoint = realStartPosition + realStartOrientation * movement.translation;
	Vec3 endPoint = realStartPosition + startOrientation * movement.translation;
	if (debug)
	{
		pPD->AddDirection(realEndPoint + bumpUp, 1, realEndDirection, dbgClr1, 5);
		pPD->AddSphere(realEndPoint + bumpUp, 0.1f, dbgClr1, 5);
		pPD->AddSphere(endPoint + bumpUp, 0.1f, dbgClr2, 5);
	}
	// if the animation is outside of the target sphere, project it to the boundary
	Vec3 dirTargetToEndPoint = endPoint - targetPosition;
	float distanceTargetToEndPoint = dirTargetToEndPoint.GetLength();
	if (distanceTargetToEndPoint > 0.1f)
	{
		dirTargetToEndPoint /= distanceTargetToEndPoint;
		dirTargetToEndPoint *= 0.08f;
		endPoint = targetPosition + dirTargetToEndPoint;
	}
	// calculate error velocities (between where we expect we'll end up, and where we'll really end up)
	if (seconds > FLT_EPSILON)
	{
		m_pExactPositioningTarget->errorRotationalVelocity = Quat::CreateSlerp( Quat::CreateIdentity(), realEndOrientation.GetInverted() * endOrientation, 1.0f/seconds );
		m_pExactPositioningTarget->errorVelocity = (endPoint - realEndPoint)/ seconds;
		if (debug)
			pPD->AddDirection(endPoint + bumpUp, 1, m_pExactPositioningTarget->errorVelocity, dbgClr2, 5);
	}
	else
	{
		m_pExactPositioningTarget->errorRotationalVelocity = Quat::CreateIdentity();
		m_pExactPositioningTarget->errorVelocity = ZERO;
		endPoint = targetPosition;
		endOrientation = m_pExactPositioningTarget->orientation;
	}
	*/

	// Until we can figure out where the animation is going to end, only
	// update the animtarget on Completing
	if (m_state == eTS_Completing)
	{
		Vec3 endPoint = pEntity->GetWorldPos();
		const Quat& endOrientation = pEntity->GetWorldRotation();

		// Project end point on ground.
		if (m_actorTargetParams.projectEnd == true)
		{
			ray_hit hit;
			int rayFlags = rwi_stop_at_pierceable|(geom_colltype_player<<rwi_colltype_bit);
			IPhysicalEntity* skipEnts[1];
			skipEnts[0] = pEntity->GetPhysics();
			if (gEnv->pPhysicalWorld->RayWorldIntersection(endPoint + Vec3(0,0,1.0f), Vec3(0,0,-2.0f), 
				ent_terrain | ent_static | ent_rigid | ent_sleeping_rigid, rayFlags, &hit, 1, skipEnts, 1))
			{
				endPoint = hit.pt;
			}
		}

		// set the position/orientation
		m_pExactPositioningTarget->location.t = endPoint;

		m_pExactPositioningTarget->location.q = endOrientation;
		m_pExactPositioningTarget->orientationTolerance = m_actorTargetParams.directionTolerance;
		m_pExactPositioningTarget->startWidth = m_actorTargetParams.startWidth;
		m_pExactPositioningTarget->positionWidth = 0.05f;
		m_pExactPositioningTarget->positionDepth = 0.05f;

		CRY_ASSERT(m_pExactPositioningTarget->location.IsValid());
		CRY_ASSERT(NumberValid(m_pExactPositioningTarget->startWidth));
		CRY_ASSERT(NumberValid(m_pExactPositioningTarget->positionWidth));
		CRY_ASSERT(NumberValid(m_pExactPositioningTarget->positionDepth));
		CRY_ASSERT(NumberValid(m_pExactPositioningTarget->orientationTolerance));
	}

	// tell AI the ending position
	if ( m_pExactPositioningListener )
	{
		m_pExactPositioningListener->ExactPositioningNotifyFinishPoint( m_pExactPositioningTarget->location.t );
	}
}
Exemplo n.º 6
0
void CMFXEffect::Execute(SMFXRunTimeEffectParams& params)
{
	FUNCTION_PROFILER(gEnv->pSystem, PROFILE_ACTION);

	// TEMP Code: testing footsteps; can this stay here???
	IEntity *pEnt = NULL;

	if (m_effectParams.libName == "footstep_player")
	{
		if (params.audioProxyEntityId != 0)
		{
			pEnt = gEnv->pEntitySystem->GetEntity(params.audioProxyEntityId);

			if (pEnt != NULL)
			{
				IEntityAudioProxyPtr pIEntityAudioProxy = crycomponent_cast<IEntityAudioProxyPtr>(pEnt->CreateProxy(ENTITY_PROXY_AUDIO));

				TAudioControlID nFootstepTriggerID = INVALID_AUDIO_CONTROL_ID;
				gEnv->pAudioSystem->GetAudioTriggerID(m_effectParams.libName, nFootstepTriggerID);

				TAudioControlID nFirstPersonSwitchID		= INVALID_AUDIO_CONTROL_ID;
				TAudioSwitchStateID nFirstPersonStateID	= INVALID_AUDIO_SWITCH_STATE_ID;
				gEnv->pAudioSystem->GetAudioSwitchID("1stOr3rdP", nFirstPersonSwitchID);
				gEnv->pAudioSystem->GetAudioSwitchStateID(nFirstPersonSwitchID, params.playSoundFP ? "1stP" : "3rdP", nFirstPersonStateID);

				TAudioControlID nSurfaceSwitchID		= INVALID_AUDIO_CONTROL_ID;
				TAudioSwitchStateID nSurfaceStateID	= INVALID_AUDIO_SWITCH_STATE_ID;
				gEnv->pAudioSystem->GetAudioSwitchID("SurfaceType", nSurfaceSwitchID);
				gEnv->pAudioSystem->GetAudioSwitchStateID(nSurfaceSwitchID, m_effectParams.name, nSurfaceStateID);

				TAudioControlID nSpeedRtpcId = INVALID_AUDIO_CONTROL_ID;
				gEnv->pAudioSystem->GetAudioRtpcID("character_speed", nSpeedRtpcId);

				float fSpeed = 0.0f;

				for (int i=0; i < params.MAX_SOUND_PARAMS; ++i)
				{
					const char* soundParamName = params.soundParams[i].paramName;
					
					if ((soundParamName != NULL) && (soundParamName[0] != '\0') && (_stricmp(soundParamName, "speed") == 0))
					{
						float const fValue = params.soundParams[i].paramValue;
						CRY_ASSERT(NumberValid(fValue));

						fSpeed = fValue;
						break;
					}
				} 

				pIEntityAudioProxy->SetSwitchState(nFirstPersonSwitchID, nFirstPersonStateID);
				pIEntityAudioProxy->SetSwitchState(nSurfaceSwitchID, nSurfaceStateID);
				pIEntityAudioProxy->SetRtpcValue(nSpeedRtpcId, fSpeed);
				pIEntityAudioProxy->ExecuteTrigger(nFootstepTriggerID, eLSM_None);
			}
		}
	}
	else if ((m_effectParams.libName == "bulletimpacts") && ((params.playflags & MFX_PLAY_SOUND) != 0))
	{
		TAudioControlID nAudioTriggerID = INVALID_AUDIO_CONTROL_ID;
		gEnv->pAudioSystem->GetAudioTriggerID(m_effectParams.name, nAudioTriggerID);

		if (nAudioTriggerID != INVALID_AUDIO_CONTROL_ID)
		{
			IAudioProxy* const pIAudioProxy = gEnv->pAudioSystem->GetFreeAudioProxy();

			if (pIAudioProxy != NULL)
			{
				pIAudioProxy->Initialize("Projectile");
				pIAudioProxy->SetPosition(params.pos);
				pIAudioProxy->SetObstructionCalcType(eAOOCT_SINGLE_RAY);
				pIAudioProxy->SetCurrentEnvironments();
				pIAudioProxy->ExecuteTrigger(nAudioTriggerID, eLSM_None);
				pIAudioProxy->Release();
			}
		}
	}
	else if ((m_effectParams.libName == "collisions") && ((params.playflags & MFX_PLAY_SOUND) != 0))
	{
		TAudioControlID nAudioTriggerID = INVALID_AUDIO_CONTROL_ID;
		gEnv->pAudioSystem->GetAudioTriggerID(m_effectParams.name, nAudioTriggerID);

		if (nAudioTriggerID != INVALID_AUDIO_CONTROL_ID)
		{
			IAudioProxy* const pIAudioProxy = gEnv->pAudioSystem->GetFreeAudioProxy();

			if (pIAudioProxy != NULL)
			{
				pIAudioProxy->Initialize("Collision");
				pIAudioProxy->SetPosition(params.pos);
				pIAudioProxy->SetObstructionCalcType(eAOOCT_SINGLE_RAY);
				pIAudioProxy->SetCurrentEnvironments();
				pIAudioProxy->ExecuteTrigger(nAudioTriggerID, eLSM_None);
				pIAudioProxy->Release();
			}
		}
	}

	std::vector<IMFXEffectPtr>::iterator iter = m_effects.begin();
	std::vector<IMFXEffectPtr>::iterator iterEnd = m_effects.end();
	while (iter != iterEnd)
	{
		IMFXEffectPtr& cur = *iter;
		if (cur)
		{
			if (cur->CanExecute(params))
				cur->Execute(params);
		}
		++iter;
	}
}