コード例 #1
0
void CMFXForceFeedbackEffect::Execute(SMFXRunTimeEffectParams& params)
{
	FUNCTION_PROFILER(gEnv->pSystem, PROFILE_ACTION);

	if (params.playflags & MFX_PLAY_FORCEFEEDBACK)
	{
		float distanceToPlayerSqr = FLT_MAX;
		IActor *pClientActor = gEnv->pGame->GetIGameFramework()->GetClientActor();
		if (pClientActor)
		{
			distanceToPlayerSqr = (pClientActor->GetEntity()->GetWorldPos() - params.pos).GetLengthSquared();
		}

		const float testDistanceSqr = clamp_tpl(distanceToPlayerSqr, m_forceFeedbackParams.intensityFallOffMinDistanceSqr, m_forceFeedbackParams.intensityFallOffMaxDistanceSqr);
		const float minMaxDiffSqr = m_forceFeedbackParams.intensityFallOffMaxDistanceSqr - m_forceFeedbackParams.intensityFallOffMinDistanceSqr;
		
		float effectIntensity = (float)__fsel(-minMaxDiffSqr, 0.0f, 1.0f - (testDistanceSqr - m_forceFeedbackParams.intensityFallOffMinDistanceSqr) / (minMaxDiffSqr + FLT_EPSILON));
		effectIntensity *= effectIntensity;
		if (effectIntensity > 0.01f)
		{
			IForceFeedbackSystem* pForceFeedback = CCryAction::GetCryAction()->GetIForceFeedbackSystem();
			assert(pForceFeedback);
			ForceFeedbackFxId fxId = pForceFeedback->GetEffectIdByName(m_forceFeedbackParams.forceFeedbackEventName.c_str());
			pForceFeedback->PlayForceFeedbackEffect(fxId, SForceFeedbackRuntimeParams(effectIntensity, 0.0f));
		}
	}

}
コード例 #2
0
ファイル: PlayerRotation.cpp プロジェクト: aronarts/FireNET
//---------------------------------------------------------------
void CPlayerRotation::ProcessNormalRoll( float frameTime )
{
	//apply lean/roll
	float rollAngleGoal(0);
	const Vec3 velocity = m_player.GetActorPhysics().velocity;
	const float speed2( velocity.len2());

	if ((speed2 > 0.01f) && m_player.m_stats.inAir)
	{
		
		const float maxSpeed = m_player.GetStanceMaxSpeed(STANCE_STAND);
		const float maxSpeedInverse = (float)__fsel(-maxSpeed, 1.0f, __fres(maxSpeed + FLT_EPSILON));
	
		const Vec3 velVec = velocity * maxSpeedInverse;

		const float dotSide(m_viewQuat.GetColumn0() * velVec);

		rollAngleGoal -= DEG2RAD(dotSide * 1.5f);;
	}

	const float tempLean = m_leanAmount;
	const float leanAmountMultiplier = 3.0f;
	const float leanAmount = clamp_tpl(tempLean * leanAmountMultiplier, -1.0f, 1.0f);
	
	rollAngleGoal += DEG2RAD(leanAmount * m_player.m_params.leanAngle);
	Interpolate(m_viewRoll,rollAngleGoal,9.9f,frameTime);

	m_deltaAngles += m_angularImpulseDelta;
}
コード例 #3
0
ファイル: View.cpp プロジェクト: aronarts/FireNET
// "ratio" is the amplitude of the shaking
void CView::ProcessShakeNormal_CalcRatio( SShake *pShake, float frameTime, float endSustain )
{
	const float FADEOUT_TIME_WHEN_INTERRUPTED = 0.5f;
	
	if (pShake->interrupted)
		pShake->ratio = max(0.f, pShake->ratio - ( frameTime / FADEOUT_TIME_WHEN_INTERRUPTED ));  // fadeout after interrupted
	else
	if (pShake->timeDone>=endSustain && pShake->fadeOutDuration>0)  
	{
		float timeFading = pShake->timeDone - endSustain;
		pShake->ratio = clamp_tpl( 1.f - timeFading / pShake->fadeOutDuration, 0.f, 1.f ); // fadeOut
	}
	else
	if (pShake->timeDone>=pShake->fadeInDuration) 
	{
		pShake->ratio = 1.f; // sustain
	}
	else  
	{
		pShake->ratio = min( 1.f, pShake->timeDone / pShake->fadeInDuration ); // fadeIn
	}

	if (pShake->permanent && pShake->timeDone>=pShake->fadeInDuration && !pShake->interrupted)
	pShake->ratio = 1.f;  // permanent standing
}
コード例 #4
0
float GetQuatAbsAngle(const Quat& q)
{
	//float fwd = q.GetColumn1().y;
	float fwd = q.GetFwdY();
	fwd = clamp_tpl(fwd, -1.0f, 1.0f);
	return acos_tpl(fwd);
}
コード例 #5
0
float ApplyAntiOscilationFilter(float value, float filtersize)
{
	float filterfraction = clamp_tpl(abs(value) / filtersize, 0.0f, 1.0f);
	float filter = (0.5f - 0.5f * cos_tpl(filterfraction * gf_PI));
	value *= filter;
	return value;
}
コード例 #6
0
ファイル: WeaponEvent.cpp プロジェクト: aronarts/FireNET
//------------------------------------------------------------------------
void CWeapon::OnDroppedByPlayer(IInventory* pPlayerInventory)
{
	CRY_ASSERT(pPlayerInventory);

	TFireModeVector::const_iterator firemodesEndIt = m_firemodes.end();
	for (TFireModeVector::const_iterator firemodeCit = m_firemodes.begin(); firemodeCit != firemodesEndIt ; ++firemodeCit)
	{
		const CFireMode* pFiremode = *firemodeCit;
		if (pFiremode)
		{
			IEntityClass* pFiremodeAmmo = pFiremode->GetAmmoType();
			if (pFiremodeAmmo)
			{
				// Exchange also ammo pool from inventory to bonus ammo map, for next user who picks it up
				int ammoCount = pPlayerInventory->GetAmmoCount(pFiremodeAmmo);
				if (ammoCount > 0)
				{
					if(gEnv->bMultiplayer)
					{
						int currentClipAmount = GetAmmoCount(pFiremodeAmmo);
						int clipSize = pFiremode->GetClipSize();

						int numForClip = clamp_tpl(clipSize - currentClipAmount, 0, ammoCount);
						SetAmmoCount(pFiremodeAmmo, currentClipAmount + numForClip);

						ammoCount -= numForClip;
					}
					
					SetInventoryAmmoCount(pFiremodeAmmo, 0);
					SWeaponAmmoUtils::SetAmmo(m_bonusammo, pFiremodeAmmo, ammoCount);
				}
			}
		}
	}
}
コード例 #7
0
void EntityEffects::CHeatController::InitWithEntity( IEntity* pEntity, const float baseHeat )
{
	CRY_ASSERT(m_ownerEntity == NULL);
	CRY_ASSERT(pEntity);

	m_ownerEntity = pEntity;
	m_baseHeat = clamp_tpl(baseHeat, 0.0f, 1.0f);
}
コード例 #8
0
// (jh) here it moves
void CPlayerInput::ApplyMovement(Vec3 delta)
{
	//m_deltaMovement += delta;
	m_deltaMovement.x = clamp_tpl(m_deltaMovement.x+delta.x,-1.0f,1.0f);
	m_deltaMovement.y = clamp_tpl(m_deltaMovement.y+delta.y,-1.0f,1.0f);
	m_deltaMovement.z = 0;

	// (jh) debug: this should draw but it dissapers...
	// IRenderer* renderer = gEnv->pRenderer;
	// renderer->Set2DMode(true, renderer->GetWidth(), renderer->GetHeight());
	//static float color[] = {1,1,1,1};
	//renderer->Draw2dLabel(100,50,1.5,color,false,"m_deltaMovement:%f,%f (requested:%f,%f", m_deltaMovement.x, m_deltaMovement.y,delta.x,delta.y);
	//ColorF col(1.0,1.0,1.0,1.0);
	//renderer->Draw2dLabel(100,50,2,col,false,"m_deltaMovement:%f,%f (requested:%f,%f", m_deltaMovement.x, m_deltaMovement.y,delta.x,delta.y);	

	// renderer->Set2DMode(false, 0, 0);
}
コード例 #9
0
void CPlayerStateSwim_WaterTestProxy::UpdateSubmergedFraction(const float referenceHeight, const float playerHeight, const float waterLevel)
{
	const float referenceHeightFinal = max(referenceHeight, 1.3f);
	const float submergedTotal = playerHeight - waterLevel;
	const float submergedFraction = (float)__fsel(submergedTotal, 0.0f, clamp_tpl(-submergedTotal * __fres(referenceHeightFinal), 0.0f, 1.0f));

	SetSubmergedFraction(submergedFraction);
}
コード例 #10
0
float EntityEffects::CHeatController::UpdateCoolDown(const float frameTime)
{
	const float cooldownRate = 0.075f;

	m_baseHeat = clamp_tpl(m_baseHeat - (frameTime * cooldownRate), 0.0f, m_baseHeat);
	m_coolDownHeat = (float)fsel(-(m_baseHeat - m_coolDownHeat), -1.0f, m_coolDownHeat);

	return m_baseHeat;
}
コード例 #11
0
float EntityEffects::CHeatController::UpdateHeat( const float frameTime )
{
	m_heatPulse.runningTime += frameTime;

	const float pulseFraction = clamp_tpl(m_heatPulse.runningTime * (float)fres(m_heatPulse.baseTime), 0.0f, 1.0f);
	const bool pulseActive = (pulseFraction < 1.0f);

	float pulseHeat = 0.0f;

	if (pulseActive)
	{
		pulseHeat = (m_heatPulse.heat * (1.0f - pulseFraction));	
	}
	else
	{
		m_heatPulse.Reset();
	}

	return clamp_tpl(m_baseHeat + pulseHeat, 0.0f, 1.0f);
}
コード例 #12
0
ファイル: WeaponEvent.cpp プロジェクト: aronarts/FireNET
//------------------------------------------------------------------------
bool CWeapon::CAnimationFiringLocator::GetProbableHit(EntityId weaponId, const IFireMode* pFireMode, Vec3& hit)
{
	CRY_ASSERT(m_pOwnerWeapon);

	// [*DavidR | 14/Oct/2010] Note: Basically a Copy & Paste of CSingle::GetProbableHit but without getting info
	// from the movement controller
	static Vec3 pos(ZERO), dir(FORWARD_DIRECTION);

	CActor *pActor = m_pOwnerWeapon->GetOwnerActor();
	IEntity *pWeaponEntity = m_pOwnerWeapon->GetEntity();

	static PhysSkipList skipList;
	skipList.clear();
	CSingle::GetSkipEntities(m_pOwnerWeapon, skipList);

	float rayLength = 250.0f;
	IEntityClass* pAmmoClass = pFireMode->GetAmmoType();
	const SAmmoParams *pAmmoParams = pAmmoClass ? g_pGame->GetWeaponSystem()->GetAmmoParams(pAmmoClass) : NULL;
	if (pAmmoParams)
	{
		//Benito - It could happen that the lifetime/speed are zero, so ensure at least some minimum distance check
		rayLength = clamp_tpl(min(pAmmoParams->speed * pAmmoParams->lifetime, rayLength), 5.0f, rayLength);
	}

	// Change this so it calls this firing locator's GetFiringPos if it gets implemented (no need atm)
	pos = pFireMode->GetFiringPos(Vec3Constants<float>::fVec3_Zero);
	IF_UNLIKELY(!GetFiringDir(weaponId, pFireMode, dir, Vec3Constants<float>::fVec3_Zero, Vec3Constants<float>::fVec3_Zero))
		dir = pFireMode->GetFiringDir(Vec3Constants<float>::fVec3_Zero, pos);
	dir *= rayLength;

	static ray_hit rayHit;	

	// use the ammo's pierceability
	uint32 flags=(geom_colltype_ray|geom_colltype13)<<rwi_colltype_bit|rwi_colltype_any|rwi_force_pierceable_noncoll|rwi_ignore_solid_back_faces;
	uint8 pierceability = 8;
	if (pAmmoParams && pAmmoParams->pParticleParams && !is_unused(pAmmoParams->pParticleParams->iPierceability))
	{
		pierceability=pAmmoParams->pParticleParams->iPierceability;
	}
	flags |= pierceability;

	if (gEnv->pPhysicalWorld->RayWorldIntersection(pos, dir, ent_all, flags, &rayHit, 1, !skipList.empty() ? &skipList[0] : NULL, skipList.size()))
	{
		hit = rayHit.pt;
	}
	else
	{
		hit = pos + dir;
	}

	return true;
}
コード例 #13
0
void SearchSpot::DebugDraw(float searchTimeOut)
{
	ColorB spotColor;

	switch (m_status)
	{
	case NotSearchedYet:
		spotColor = ColorB(0, 0, 255);
		break;
	case BeingSearchedRightAboutNow:
		spotColor = ColorB(255, 255, 0);
		break;
	case Searched:
		spotColor = ColorB(0, 255, 0);
		break;
	case Unreachable:
		spotColor = ColorB(255, 0, 0);
		break;
	case SearchedTimingOut:
		if(searchTimeOut)
		{
			uint8 green = (uint8)(255 * clamp_tpl( (m_searchTimeoutLeft / (searchTimeOut / 2.0f)), 0.0f, 1.0f));
			uint8 blue = (uint8)(255 * clamp_tpl(((searchTimeOut - m_searchTimeoutLeft) / (searchTimeOut / 2.0f)), 0.0f, 1.0f));
			spotColor = ColorB(0, green, blue);
		}
		break;
	}

	IRenderAuxGeom* pDebugRenderer = gEnv->pRenderer->GetIRenderAuxGeom();
	pDebugRenderer->DrawSphere(m_pos, 0.3f, spotColor);

	if (m_assigneeID)
	{
		Agent agent(m_assigneeID);
		if (agent)
			pDebugRenderer->DrawLine(agent.GetPos(), ColorB(255, 255, 0), m_pos, ColorB(255, 255, 0), 2.0f);
	}
}
CForceFeedBackSystem::SFFOutput CForceFeedBackSystem::SActiveEffect::Update( float frameTime )
{
	SFFOutput effectFF;

	bool canPlay = (runtimeParams.delay <= 0.0f);

	if (canPlay)
	{
		bool isLoopingEffect = (effectTime <= 0.0f); 

		const float effectTimeInv = !isLoopingEffect ? (float)__fres(effectTime) : 1.0f;
		const float sampleTime = runningTime * effectTimeInv;

		const float sampleTimeAAtFreq = sampleTime * frequencyA;
		const float sampleTimeAAtFreqNorm = clamp_tpl(sampleTimeAAtFreq - floor_tpl(sampleTimeAAtFreq), 0.0f, 1.0f);

		const float sampleTimeBAtFreq = sampleTime * frequencyB;
		const float sampleTimeBAtFreqNorm = clamp_tpl(sampleTimeBAtFreq - floor_tpl(sampleTimeBAtFreq), 0.0f, 1.0f);

		effectFF.forceFeedbackA = m_patternA.SamplePattern(sampleTimeAAtFreqNorm) * m_envelopeA.SampleEnvelope(sampleTime) * runtimeParams.intensity;
		effectFF.forceFeedbackB = m_patternB.SamplePattern(sampleTimeBAtFreqNorm) * m_envelopeB.SampleEnvelope(sampleTime) * runtimeParams.intensity;
		runningTime += frameTime;

		//Re-start the loop
		if (isLoopingEffect)
		{
			runningTime = (float)__fsel(1.0f - runningTime, runningTime, 0.0f);
		}
	}
	else
	{
		runtimeParams.delay = clamp_tpl(runtimeParams.delay - frameTime, 0.0f, runtimeParams.delay);
	}


	return effectFF;
}
コード例 #15
0
Ang3 CCinematicInput::UpdateAdditiveCameraInputWithMouse( const SUpdateContext& updateCtx, const Ang3& rawMouseInput )
{
#if CINEMATIC_INPUT_PC_MOUSE
	Ang3 rawMouseInputModified = rawMouseInput * updateCtx.m_frameTime * updateCtx.m_frameTime;
	rawMouseInputModified.z = -rawMouseInputModified.z;
	rawMouseInputModified.x *= (g_pGameCVars->cl_invertMouse == 0) ? 1.0f : -1.0f;

	m_mouseAccumulatedInput += rawMouseInputModified;
	m_mouseAccumulatedInput.x = clamp_tpl(m_mouseAccumulatedInput.x, -1.0f, 1.0f);
	m_mouseAccumulatedInput.z = clamp_tpl(m_mouseAccumulatedInput.z, -1.0f, 1.0f);
	m_mouseAccumulatedInput.y = 0.0f;

	//Yaw angle (Z axis)
	m_mouseAccumulatedAngles.z = -(float)fsel(m_mouseAccumulatedInput.z, m_mouseAccumulatedInput.z * updateCtx.m_lookRightLimit, m_mouseAccumulatedInput.z * updateCtx.m_lookLeftLimit);		

	//Pitch angle (X axis)
	m_mouseAccumulatedAngles.x = (float)fsel(m_mouseAccumulatedInput.x, m_mouseAccumulatedInput.x * updateCtx.m_lookUpLimit, m_mouseAccumulatedInput.x * updateCtx.m_lookDownLimit);

	// Recenter after a certain amount of time without input
	if (updateCtx.m_recenter)
	{
		const float rawInputLen = fabs(rawMouseInputModified.x) + fabs(rawMouseInputModified.z);
		const float newRecenterTimeOut = (float)fsel(-rawInputLen, m_mouseRecenterTimeOut - updateCtx.m_frameTime, CINEMATIC_INPUT_MOUSE_RECENTER_TIMEOUT);
		if (newRecenterTimeOut < 0.0f)
		{
			Interpolate(m_mouseAccumulatedInput, Ang3(0.0f, 0.0f, 0.0f), 1.5f, updateCtx.m_frameTime);
		}

		m_mouseRecenterTimeOut = max(newRecenterTimeOut, 0.0f);
	}

	return m_mouseAccumulatedAngles;
#else
	return Ang3(0.0f, 0.0f, 0.0f);
#endif
	
}
コード例 #16
0
float SearchGroup::CalculateScore(SearchSpot& searchSpot, EntityId entityID, SearchSpotQuery* query, Vec3& targetCurrentPos) const
{
	assert(query);

	Agent agent(entityID);
	if (agent.IsValid())
	{
		const Vec3 spotPosition = searchSpot.GetPos();
		const Vec3 agentPosition = agent.GetPos();

		const float agentToSpotDistance = agentPosition.GetDistance(spotPosition);
		if (agentToSpotDistance < query->minDistanceFromAgent)
		{
			return -100.0f;
		}

		float closenessToAgentScore = 0.0f;
		closenessToAgentScore = 1.0f - clamp_tpl(agentToSpotDistance, 1.0f, 50.0f) / 50.0f;
		const float closenessToTargetScore = 1.0f - clamp_tpl(spotPosition.GetDistance(m_targetPos),    1.0f, 50.0f) / 50.0f;

		float closenessToTargetCurrentPosScore = 0.0f;
		if (!targetCurrentPos.IsZeroFast())
		{
			closenessToTargetCurrentPosScore = 1.0f - clamp_tpl(spotPosition.GetDistance(targetCurrentPos), 1.0f, 50.0f) / 50.0f;
		}

		return
			closenessToAgentScore  * query->closenessToAgentWeight +
			closenessToTargetScore * query->closenessToTargetWeight +
			closenessToTargetCurrentPosScore * query->closenessToTargetCurrentPosWeight;
	}
	else
	{
		return -100.0f;
	}
}
コード例 #17
0
void CFlashUIMCVisibleBaseNode::ProcessEvent( EFlowEvent event,SActivationInfo* pActInfo )
{
	if (event == eFE_Initialize)
	{
		UpdateObjectDesc( GetPortString( pActInfo, GetInputPort(eI_UIMovieClip)), pActInfo, m_isTemplate );
	}
	else if (event == eFE_Activate)
	{
		if (IsPortActive( pActInfo, GetInputPort(eI_UIMovieClip)))
		{
			UpdateObjectDesc( GetPortString( pActInfo, GetInputPort(eI_UIMovieClip)), pActInfo, m_isTemplate );
		}

		if (IsTemplate() && !UpdateTmplDesc( GetPortString( pActInfo, GetInputPort(eI_TemplateInstanceName)), pActInfo ))
			return;

		if (GetElement())
		{
			const int instanceId = GetPortInt( pActInfo, GetInputPort(eI_InstanceID));
			if (IsPortActive ( pActInfo, GetInputPort(eI_Set)))
			{
				const bool  bVis  = GetPortBool( pActInfo, GetInputPort(eI_Visible));
				const float alpha = clamp_tpl( GetPortFloat( pActInfo, GetInputPort(eI_Alpha)), 0.0f, 1.f );

				SPerInstanceCall2< bool, float > caller;
				caller.Execute( GetElement(), instanceId, functor(*this, &CFlashUIMCVisibleBaseNode::SetValues), bVis, alpha );

				ActivateOutput( pActInfo, eO_OnSet, true );
				ActivateOutput( pActInfo, eO_Visible, bVis );
				ActivateOutput( pActInfo, eO_Alpha, alpha );
			}
			else if (IsPortActive( pActInfo, GetInputPort(eI_Get)))
			{
				bool  bVis  = false;
				float alpha = 0.f;

				SPerInstanceCall2< bool &, float & > caller;
				if (!caller.Execute( GetElement(), instanceId, functor(*this, &CFlashUIMCVisibleBaseNode::GetValues), bVis, alpha, false ))
				{
					UIACTION_WARNING( "FG: UIElement \"%s\" called get Array for multiple instances! (passed instanceId %i), referenced at node \"%s\"", GetElement()->GetName(),instanceId, pActInfo->pGraph->GetNodeTypeName( pActInfo->myID ));
				}

				ActivateOutput( pActInfo, eO_Visible, bVis );
				ActivateOutput( pActInfo, eO_Alpha, alpha );
			}
		}
	}
}
コード例 #18
0
void CFirstPersonCameraComponent::Update()
{
	auto pPlayer = CPlayerComponent::GetLocalPlayer();
	auto pPlayerInput = pPlayer->GetPlayerInput();

	// Default on failure is to return a cleanly constructed default matrix.
	Matrix34 newCameraMatrix = Matrix34::Create(Vec3(1.0f), IDENTITY, ZERO);

	if (pPlayerInput)
	{
		// Resolve the entity.
		if (auto pEntity = gEnv->pEntitySystem->GetEntity(m_targetEntityID))
		{
			// It's possible there is no actor to query for eye position, in that case, return a safe default
			// value for an average height person.
			Vec3 localEyePosition { AverageEyePosition };

			// If we are attached to an entity that is an actor we can use their eye position.
			auto pActor = CActorComponent::GetActor(m_targetEntityID);
			if (pActor)
				localEyePosition = pActor->GetLocalEyePos();

			// Apply the player input rotation for this frame, and limit the pitch / yaw movement according to the set max and min values.
			if (pPlayer->GetinteractionState().IsCameraMovementAllowed())
			{
				m_viewPitch -= pPlayerInput->GetMousePitchDelta() - pPlayerInput->GetXiPitchDelta();
				m_viewPitch = clamp_tpl(m_viewPitch, DEG2RAD(g_cvars.m_firstPersonCameraPitchMin), DEG2RAD(g_cvars.m_firstPersonCameraPitchMax));
			}

			// Pose is based on entity position and the eye position.
			// We will use the rotation of the entity as a base, and apply pitch based on our own reckoning.
			const Vec3 position = pEntity->GetPos() + localEyePosition;
			const Quat rotation = pEntity->GetRotation() * Quat(Ang3(m_viewPitch, 0.0f, 0.0f));
			newCameraMatrix = Matrix34::Create(Vec3(1.0f), rotation, position + rotation * m_pCameraManager->GetViewOffset());

#if defined(_DEBUG)
			if (g_cvars.m_firstPersonCameraDebug)
			{
				gEnv->pRenderer->GetIRenderAuxGeom()->DrawSphere(position, 0.04f, ColorB(0, 0, 255, 255));
			}
#endif
		}
	}

	// Store the new matrix for later.
	m_cameraMatrix = newCameraMatrix;
}
コード例 #19
0
void CPlayerStateSwim_WaterTestProxy::Update(const CPlayer& player, const float frameTime)
{
	FUNCTION_PROFILER(GetISystem(), PROFILE_GAME);

	if( gEnv->IsEditor() && !gEnv->IsEditorGameMode() )
	{
		m_lastInternalState = m_internalState;
		m_internalState = eProxyInternalState_OutOfWater;
		m_shouldSwim = false;
	}

	float newSwimmingTimer = 0.0f;
	switch(m_internalState)
	{
	case eProxyInternalState_OutOfWater:
		{
			if (m_lastInternalState != eProxyInternalState_OutOfWater)
			{
				Reset(true);
			}
			UpdateOutOfWater(player, frameTime);

			newSwimmingTimer = m_swimmingTimer - frameTime;
		}
		break;

	case eProxyInternalState_PartiallySubmerged:
		{
			UpdateInWater(player, frameTime);

			newSwimmingTimer = m_swimmingTimer - frameTime;
		}
		break;

	case eProxyInternalState_Swimming:
		{
			UpdateInWater(player, frameTime);

			newSwimmingTimer = m_swimmingTimer + frameTime;
		}
		break;
	}

	m_swimmingTimer = clamp_tpl(newSwimmingTimer, -1000.0f, 1000.0f);
}
コード例 #20
0
ファイル: PlayerRotation.cpp プロジェクト: aronarts/FireNET
void CPlayerRotation::ProcessFinalViewEffects( float minAngle, float maxAngle )
{
	if (!m_player.IsClient())
	{
		m_viewQuatFinal = m_viewQuat;
	}
	else
	{
		Ang3 viewAngleOffset = m_frameViewAnglesOffset;

		float currentViewPitch = GetLocalPitch();
		float newPitch = clamp_tpl(currentViewPitch + viewAngleOffset.x, minAngle, maxAngle);
		viewAngleOffset.x = newPitch - currentViewPitch;

		m_viewQuatFinal = m_viewQuat * Quat::CreateRotationXYZ(viewAngleOffset);
	}

}
コード例 #21
0
ファイル: PlayerStateJump.cpp プロジェクト: aronarts/FireNET
const Vec3 CPlayerStateJump::CalculateInAirJumpExtraVelocity( const CPlayer& player, const Vec3& desiredVelocity ) const
{
	const SPlayerStats& stats = player.m_stats;
	const float speedUpFactor = 0.175f;

	Vec3 jumpExtraVelocity(0.0f, 0.0f, 0.0f);

	const SActorPhysics& actorPhysics = player.GetActorPhysics();
	if (actorPhysics.velocity.z > 0.0f)
	{
		//Note: Desired velocity is flat (not 'z' component), so jumpHeight should not be altered
		jumpExtraVelocity = desiredVelocity * speedUpFactor;
	}
	else
	{
		//Note: this makes the jump feel less 'floaty', by accelerating the player slightly down
		//      and compensates the extra traveled distance when going up 
		const float g = actorPhysics.gravity.len();
		if (g > 0.0f)
		{
			const float jumpHeightScale = 1.0f;
			const float jumpHeight = player.m_params.jumpHeight * jumpHeightScale;

			const float estimatedLandTime = sqrt_tpl(2.0f*jumpHeight*(1.0f/g)) * (1.0f - speedUpFactor);
			assert(estimatedLandTime > 0.0f);
			if (estimatedLandTime > 0.0f)
			{
				const float requiredGravity = (2.0f*jumpHeight)/(estimatedLandTime * estimatedLandTime);
				const float initialAccelerationScale = clamp_tpl((-actorPhysics.velocity.z * 0.6f), 0.0f, 1.0f);
				jumpExtraVelocity = (requiredGravity - g) * actorPhysics.gravity.GetNormalized() * initialAccelerationScale;
			}
		}
	}

	return jumpExtraVelocity;
}
//////////////////////////////////////////////////////////////////////////
// NOTE: This function must be thread-safe. Before adding stuff contact MarcoC.
void CVehicleMovementTank::ProcessMovement(const float deltaTime)
{ 
	FUNCTION_PROFILER( gEnv->pSystem, PROFILE_GAME );

	m_netActionSync.UpdateObject(this);

	CryAutoCriticalSection lk(m_lock);

	CVehicleMovementBase::ProcessMovement(deltaTime);

	if (!(m_actorId && m_isEnginePowered))
	{
		IPhysicalEntity* pPhysics = GetPhysics();

		if (m_latFriction != 1.3f)
			SetLatFriction(1.3f);

		if (m_axleFriction != m_axleFrictionMax)
			UpdateAxleFriction(0.f, false, deltaTime);

		m_action.bHandBrake = 1;
		m_action.pedal = 0;
		m_action.steer = 0;
		pPhysics->Action(&m_action, 1);
		return;
	}

	IPhysicalEntity* pPhysics = GetPhysics();
	MARK_UNUSED m_action.clutch;

	Matrix34 worldTM( m_PhysPos.q );
	worldTM.AddTranslation( m_PhysPos.pos );

	const Matrix34 invWTM = worldTM.GetInvertedFast();

	Vec3 localVel = invWTM.TransformVector(m_PhysDyn.v);
	Vec3 localW = invWTM.TransformVector(m_PhysDyn.w);
	float speed = m_PhysDyn.v.len();
	float speedRatio = min(1.f, speed/m_maxSpeed);

	float actionPedal = abs(m_movementAction.power) > 0.001f ? m_movementAction.power : 0.f;        

	// tank specific:
	// avoid steering input around 0.5 (ask Anton)
	float actionSteer = m_movementAction.rotateYaw;
	float absSteer = abs(actionSteer);
	float steerSpeed = (absSteer < 0.01f && abs(m_currSteer) > 0.01f) ? m_steerSpeedRelax : m_steerSpeed;

	if (steerSpeed == 0.f)
	{
		m_currSteer =	(float)sgn(actionSteer);
	}
	else
	{ 
		if (m_movementAction.isAI)
		{
			m_currSteer = actionSteer;
		}
		else
		{
			m_currSteer += min(abs(actionSteer-m_currSteer), deltaTime*steerSpeed) * sgn(actionSteer-m_currSteer);        
		}
	}
	Limit(m_currSteer, -m_steerLimit, m_steerLimit);  

	if (abs(m_currSteer) > 0.0001f) 
	{
		// if steering, apply full throttle to have enough turn power    
		actionPedal = (float)sgn(actionPedal);

		if (actionPedal == 0.f) 
		{
			// allow steering-on-teh-spot only above maxReverseSpeed (to avoid sudden reverse of controls)
			const float maxReverseSpeed = -1.5f;
			actionPedal = max(0.f, min(1.f, 1.f-(localVel.y/maxReverseSpeed)));

			// todo
			float steerLim = 0.8f;
			Limit(m_currSteer, -steerLim*m_steerLimit, steerLim*m_steerLimit);
		}
	}

	if (!pPhysics->GetStatus(&m_vehicleStatus))
		return;

	int currGear = m_vehicleStatus.iCurGear - 1; // indexing for convenience: -1,0,1,2,..

	UpdateAxleFriction(m_movementAction.power, true, deltaTime);
	UpdateSuspension(deltaTime);   	

	float absPedal = abs(actionPedal);  

	// pedal ramping   
	if (m_pedalSpeed == 0.f)
		m_currPedal = actionPedal;
	else
	{
		m_currPedal += deltaTime * m_pedalSpeed * sgn(actionPedal - m_currPedal);  
		m_currPedal = clamp_tpl(m_currPedal, -absPedal, absPedal);
	}

	// only apply pedal after threshold is exceeded
	if (currGear == 0 && fabs_tpl(m_currPedal) < m_pedalThreshold) 
		m_action.pedal = 0;
	else
		m_action.pedal = m_currPedal;

	// change pedal amount based on damages
	float damageMul = 0.0f;
	{
		if (m_movementAction.isAI)
		{
			damageMul = 1.0f - 0.30f * m_damage; 
			m_action.pedal *= damageMul;
		}
		else
		{
			// request from Sten: damage shouldn't affect reversing so much.
			float effectiveDamage = m_damage;
			if(m_action.pedal < -0.1f)
				effectiveDamage = 0.4f * m_damage;

			m_action.pedal *= GetWheelCondition();
			damageMul = 1.0f - 0.7f*effectiveDamage; 
			m_action.pedal *= damageMul;
		}
	}

	// reverse steering value for backward driving
	float effSteer = m_currSteer * sgn(actionPedal);   

	// update lateral friction  
	float latSlipMinGoal = 0.f;
	float latFricMinGoal = m_latFricMin;

	if (abs(effSteer) > 0.01f && !m_movementAction.brake)
	{
		latSlipMinGoal = m_latSlipMin;

		// use steering friction, but not when countersteering
		if (sgn(effSteer) != sgn(localW.z))
			latFricMinGoal = m_latFricMinSteer;
	}

	Interpolate(m_currentSlipMin, latSlipMinGoal, 3.f, deltaTime);   

	if (latFricMinGoal < m_currentFricMin)
		m_currentFricMin = latFricMinGoal;
	else
		Interpolate(m_currentFricMin, latFricMinGoal, 3.f, deltaTime);

	float fractionSpeed = min(1.f, max(0.f, m_avgLateralSlip-m_currentSlipMin) / (m_latSlipMax-m_currentSlipMin));
	float latFric = fractionSpeed * (m_latFricMax-m_currentFricMin) + m_currentFricMin;

	if ( m_movementAction.brake && m_movementAction.isAI )
	{
		// it is natural for ai, apply differnt friction value while handbreaking
		latFric = m_latFricMax;
	}

	if (latFric != m_latFriction)
	{ 
		SetLatFriction(latFric);    
	}      

	const static float maxSteer = gf_PI/4.f; // fix maxsteer, shouldn't change  
	m_action.steer = m_currSteer * maxSteer;  

	if (m_steeringImpulseMin > 0.f && m_wheelContactsLeft != 0 && m_wheelContactsRight != 0)
	{  
		const float maxW = 0.3f*gf_PI;
		float steer = abs(m_currSteer)>0.001f ? m_currSteer : 0.f;    
		float desired = steer * maxW; 
		float curr = -localW.z;
		float err = desired - curr; // err>0 means correction to right 
		Limit(err, -maxW, maxW);

		if (abs(err) > 0.01f)
		{ 
			float amount = m_steeringImpulseMin + speedRatio*(m_steeringImpulseMax-m_steeringImpulseMin);

			// bigger correction for relaxing
			if (desired == 0.f || (desired*curr>0 && abs(desired)<abs(curr))) 
				amount = m_steeringImpulseRelaxMin + speedRatio*(m_steeringImpulseRelaxMax-m_steeringImpulseRelaxMin);

			float corr = -err * amount * m_PhysDyn.mass * deltaTime;

			pe_action_impulse imp;
			imp.iApplyTime = 0;      
			imp.angImpulse = worldTM.GetColumn2() * corr;
			pPhysics->Action(&imp, THREAD_SAFE);
		}    
	}

	m_action.bHandBrake = (m_movementAction.brake) ? 1 : 0;	

	if (currGear > 0 && m_vehicleStatus.iCurGear < m_currentGear) 
	{
		// when shifted down, disengage clutch immediately to avoid power/speed dropdown
		m_action.clutch = 1.f;
	}

	pPhysics->Action(&m_action, 1);

	if (Boosting())  
		ApplyBoost(speed, 1.2f*m_maxSpeed*GetWheelCondition()*damageMul, m_boostStrength, deltaTime);  

	if (m_wheelContacts <= 1 && speed > 5.f)
	{
		ApplyAirDamp(DEG2RAD(20.f), DEG2RAD(10.f), deltaTime, THREAD_SAFE);
		UpdateGravity(-9.81f * 1.4f);
	}

	if (m_netActionSync.PublishActions( CNetworkMovementStdWheeled(this) ))
		CHANGED_NETWORK_STATE(m_pVehicle,  eEA_GameClientDynamic );
}
コード例 #23
0
ファイル: VehicleViewSteer.cpp プロジェクト: joewan/pycmake
//------------------------------------------------------------------------
bool CVehicleViewSteer::Init(IVehicleSeat* pSeat, const CVehicleParams &table)
{
	if (!CVehicleViewBase::Init(pSeat, table))
		return false;

	m_pAimPart = pSeat->GetAimPart();

	CVehicleParams params = table.findChild(m_name);
	if (!params)
		return false;

	CVehicleParams posParams       = params.findChild("Pos");
	CVehicleParams rotationParams  = params.findChild("Rotation");
	CVehicleParams motionParams    = params.findChild("Motion");
	CVehicleParams backwardsParams = params.findChild("Backwards");
	CVehicleParams radiusParams    = params.findChild("Radius");

	if (posParams)
	{
		posParams.getAttr("offset", m_localSpaceCameraOffset);
		posParams.getAttr("aim", m_lookAt0);
		posParams.getAttr("pivotOffset", m_pivotOffset);
	}

	if (rotationParams)
	{
		rotationParams.getAttr("rotationMax", m_maxRotation);
		if (rotationParams.haveAttr("rotationMax2"))
		{
			rotationParams.getAttr("rotationMax2", m_maxRotation2);
		}
		else
		{
			m_maxRotation2 = m_maxRotation / 3.0f;
		}
		m_maxRotation  = DEG2RAD(m_maxRotation);
		m_maxRotation2 = DEG2RAD(m_maxRotation2);
		rotationParams.getAttr("stickSensitivity", m_stickSensitivity);
		rotationParams.getAttr("stickSensitivity2", m_stickSensitivity2);
		rotationParams.getAttr("inheritedElev", m_inheritedElev);
		getFlag(rotationParams, "canRotate", m_flags, eVCam_canRotate);
		m_inheritedElev = clamp_tpl(m_inheritedElev, 0.f, 1.f);
	}

	if (motionParams)
	{
		motionParams.getAttr("returnSpeed", m_angReturnSpeed1);
		motionParams.getAttr("returnSpeed2", m_angReturnSpeed2);
		motionParams.getAttr("angFollow", m_angSpeedCorrection0);
	}

	if (backwardsParams)
	{
		getFlag(backwardsParams, "clamp", m_backwardsFlags, eVCam_rotationClamp);
		getFlag(backwardsParams, "returnSpring", m_backwardsFlags, eVCam_rotationSpring);
	}

	if (radiusParams)
	{
		radiusParams.getAttr("min", m_radiusMin);
		radiusParams.getAttr("max", m_radiusMax);
		radiusParams.getAttr("relaxRate", m_radiusRelaxRate);
		radiusParams.getAttr("dampRate", m_radiusDampRate);
		radiusParams.getAttr("velInfluence", m_radiusVelInfluence);
	}

	Reset();
	return true;
}
コード例 #24
0
ファイル: VehicleViewSteer.cpp プロジェクト: joewan/pycmake
//------------------------------------------------------------------------
void CVehicleViewSteer::Update(float dt)
{
	IEntity* pEntity = m_pVehicle->GetEntity();
	assert(pEntity);

	IVehicleMovement* pVehicleMovement = m_pVehicle->GetMovement();
	if (pVehicleMovement == NULL)
		return;

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

	pe_status_dynamics dynStatus;
	pPhysEntity->GetStatus(&dynStatus);

	SMovementState movementState;
	pVehicleMovement->GetMovementState(movementState);
	const float     pedal        = pVehicleMovement->GetEnginePedal();
	const float     maxSpeed     = movementState.maxSpeed;
	const Matrix34 &pose         = m_pAimPart ? m_pAimPart->GetWorldTM() : pEntity->GetWorldTM();
	const Vec3      entityPos    = pose.GetColumn3();
	const Vec3      xAxis        = pose.GetColumn0();
	const Vec3      yAxis        = pose.GetColumn1();
	const Vec3      zAxis        = pose.GetColumn2();
	const float     forwardSpeed = dynStatus.v.dot(yAxis);
	const float     speedNorm    = clamp_tpl(forwardSpeed / maxSpeed, 0.0f, 1.0f);
	const Vec3      maxRotation  = m_maxRotation + speedNorm * (m_maxRotation2 - m_maxRotation);

	CalcLookAt(pose);
	if (m_lookAt.IsValid())
	{
		if (!m_lastOffset.IsValid())
		{
			m_position             = pose * m_localSpaceCameraOffset;
			m_lastOffset           = m_position - m_lookAt;
			m_lastOffsetBeforeElev = m_lastOffset;
		}

		Vec3 offset = m_lastOffsetBeforeElev;

		if (pedal < 0.1f && forwardSpeed < 1.0f)
		{
			// Going Backwards
			m_flags &= ~(eVCam_goingForwards | m_forwardFlags);
			m_flags |= m_backwardsFlags;
		}

		if (offset.dot(yAxis) < 0.8f && forwardSpeed > 1.f)
		{
			// Going Forwards
			m_flags &= ~m_backwardsFlags;
			m_flags |= eVCam_goingForwards | m_forwardFlags;
		}

		float sensitivity = (1.f - speedNorm) * m_stickSensitivity.z + speedNorm * m_stickSensitivity2.z;
		float rotate      = -m_rotatingAction.z * sensitivity;
		rotate = rotate * dt;

		if (zAxis.z > 0.1f)
		{
			// Safe to update curYaw
			Vec3 projectedX = xAxis;
			projectedX.z = 0.f;
			Vec3 projectedY = yAxis;
			projectedY.z = 0.f;
			const float newYaw    = atan2_tpl(offset.dot(projectedX), -(offset.dot(projectedY)));
			const float maxChange = DEG2RAD(270.f) * dt;
			const float delta     = clamp_tpl(newYaw - m_curYaw, -maxChange, +maxChange);
			m_curYaw += delta;
		}

		// Rotation Action
		{
			if (m_flags & eVCam_rotationClamp)
			{
				float newYaw = clamp_tpl(m_curYaw + rotate, -maxRotation.z, +maxRotation.z);
				rotate        = newYaw - m_curYaw;
				rotate        = clamp_tpl(newYaw - m_curYaw, -fabsf(rotate), +fabsf(rotate));
				m_rotation.z += rotate;
			}
			else
			{
				m_rotation.z = 0.f;
			}

			if (speedNorm > 0.1f)
			{
				float reduce = dt * 1.f;
				m_rotation.z = m_rotation.z - reduce * m_rotation.z / (fabsf(m_rotation.z) + reduce);
			}
		}

		// Ang Spring
		{
			float angSpeedCorrection = dt * dt * m_angSpeedCorrection / (dt * m_angSpeedCorrection + 1.f) * dynStatus.w.z;
			if ((m_flags & eVCam_rotationSpring) == 0)
			{
				m_angReturnSpeed   = 0.f;
				angSpeedCorrection = 0.f;
			}

			float difference = m_rotation.z - m_curYaw;
			float relax      = difference * (m_angReturnSpeed * dt) / ((m_angReturnSpeed * dt) + 1.f);

			const float delta = +relax + angSpeedCorrection + rotate;
			m_curYaw += delta;

			Matrix33 rot = Matrix33::CreateRotationZ(delta);
			offset = rot * offset;

			// Lerp the spring speed
			float angSpeedTarget = m_angReturnSpeed1 + speedNorm * (m_angReturnSpeed2 - m_angReturnSpeed1);
			m_angReturnSpeed     += (angSpeedTarget - m_angReturnSpeed) * (dt / (dt + 0.3f));
			m_angSpeedCorrection += (m_angSpeedCorrection0 - m_angSpeedCorrection) * (dt / (dt + 0.3f));
		}

		if (!offset.IsValid()) offset = m_lastOffset;

		// Velocity influence
		Vec3 displacement = -((2.f - speedNorm) * dt) * dynStatus.v;// - yAxis*(0.0f*speedNorm*(yAxis.dot(dynStatus.v))));

		float dot = offset.dot(displacement);
		if (dot < 0.f)
		{
			displacement = displacement + offset * -0.1f * (offset.dot(displacement) / offset.GetLengthSquared());
		}
		offset = offset + displacement;

		const float radius0   = fabsf(m_localSpaceCameraOffset.y);
		const float minRadius = radius0 * m_radiusMin;
		const float maxRadius = radius0 * m_radiusMax;
		float       radiusXY  = sqrtf(sqr(offset.x) + sqr(offset.y));

		Vec3 offsetXY = offset;
		offsetXY.z = 0.f;
		Vec3  accelerationV = (dynStatus.v - m_lastVehVel);
		float acceleration  = offsetXY.dot(accelerationV) / radiusXY;

		m_lastVehVel = dynStatus.v;
		m_radiusVel -= acceleration;
		m_radius    += m_radiusVel * dt - dt * m_radiusVelInfluence * offsetXY.dot(dynStatus.v) / radiusXY;
		m_radiusVel *= expf(-dt * m_radiusDampRate);
		m_radius    += (radius0 - m_radius) * (dt * m_radiusRelaxRate) / (dt * m_radiusRelaxRate + 1.f);
		m_radius     = clamp_tpl(m_radius, minRadius, maxRadius);
		offset       = offset * (m_radius / radiusXY);

		// Vertical motion
		float targetOffsetHeight = m_localSpaceCameraOffset.z * (m_radius / radius0);
		float oldOffsetHeight    = offset.z;
		offset.z += (targetOffsetHeight - offset.z) * (dt / (dt + 0.3f));
		Limit(offset.z, targetOffsetHeight - 2.f, targetOffsetHeight + 2.f);
		float verticalChange = offset.z - oldOffsetHeight;

		m_lastOffsetBeforeElev = offset;

		// Add up and down camera tilt
		{
			offset.z     -= verticalChange;
			m_rotation.x += dt * m_stickSensitivity.x * m_rotatingAction.x;
			m_rotation.x  = clamp_tpl(m_rotation.x, -maxRotation.x, +maxRotation.x);

			float elevAngleVehicle = m_inheritedElev * yAxis.z;     // yAxis.z == approx elevation angle

			float elevationAngle = m_rotation.x - elevAngleVehicle;

			float sinElev, cosElev;
			sincos_tpl(elevationAngle, &sinElev, &cosElev);
			float horizLen    = sqrtf(offset.GetLengthSquared2D());
			float horizLenNew = horizLen * cosElev - sinElev * offset.z;
			if (horizLen > 1e-4f)
			{
				horizLenNew /= horizLen;
				offset.x    *= horizLenNew;
				offset.y    *= horizLenNew;
				offset.z     = offset.z * cosElev + sinElev * horizLen;
			}
			offset.z += verticalChange;
		}

		if (!offset.IsValid()) offset = m_lastOffset;

		m_position = m_lookAt + offset;

		// Perform world intersection test.
		{
			// Initialise sphere and direction.
			primitives::sphere sphere;

			sphere.center = m_lookAt;
			sphere.r      = g_SteerCameraRadius;

			Vec3 direction = m_position - m_lookAt;

			// Calculate camera bounds.
			AABB localBounds;

			m_pVehicle->GetEntity()->GetLocalBounds(localBounds);

			const float cameraBoundsScale = 0.75f;

			localBounds.min *= cameraBoundsScale;
			localBounds.max *= cameraBoundsScale;

			OBB cameraBounds;

			Matrix34 worldTM = m_pVehicle->GetEntity()->GetWorldTM();

			cameraBounds.SetOBBfromAABB(Matrix33(worldTM), localBounds);

			// Try to find point on edge of camera bounds to begin swept sphere intersection test.
			Vec3 rayBoxIntersect;

			if (Intersect::Ray_OBB(Ray(m_position, -direction), worldTM.GetTranslation(), cameraBounds, rayBoxIntersect) > 0)
			{
				Vec3 temp = m_position - rayBoxIntersect;

				if (direction.Dot(temp) > 0.0f)
				{
					sphere.center = rayBoxIntersect;
					direction     = temp;
				}
			}

			// Perform swept sphere intersection test against world.
			geom_contact* pContact = NULL;

			IPhysicalEntity* pSkipEntities[10];

			float distance = gEnv->pPhysicalWorld->PrimitiveWorldIntersection(sphere.type, &sphere, direction, ent_static | ent_terrain | ent_rigid | ent_sleeping_rigid,
			                                                                  &pContact, 0, (geom_colltype_player << rwi_colltype_bit) | rwi_stop_at_pierceable, 0, 0, 0,
			                                                                  pSkipEntities, m_pVehicle->GetSkipEntities(pSkipEntities, 10));

			if (distance > 0.0f)
			{
				// Sweep intersects world so calculate new offset.
				offset = (sphere.center + (direction.GetNormalizedSafe() * distance)) - m_lookAt;
			}
		}

		Interpolate(m_lastOffset, offset, 10.f, dt);

		m_position = m_lookAt + m_lastOffset;
	}
	else
	{
		CRY_ASSERT_MESSAGE(0, "camera will fail because lookat position is invalid");
	}

	m_rotatingAction.zero();
}
コード例 #25
0
ファイル: FireModePlugin.cpp プロジェクト: aronarts/FireNET
//------------------------------------------------------------------------
bool CFireModePlugin_Overheat::Update(float frameTime, uint32 frameId)
{
	CWeapon* pWeapon = m_pOwnerFiremode->GetWeapon();

	CRY_ASSERT(pWeapon);

	CActor *pActor = pWeapon->GetOwnerActor();
	bool isOwnerAIControlled = pActor ? !pActor->IsPlayer() : false;

	if(isOwnerAIControlled)
		return false;

	float oldheat = m_heat;

	if (m_overheat > 0.0f)
	{
		m_overheat -= frameTime;
		if (m_overheat <= 0.0f)
		{
			m_overheat = 0.0f;
			FragmentID fragment = pWeapon->GetFragmentID(m_pParams->cooldown.c_str());
			pWeapon->PlayAction(fragment);				
		}
	}
	else
	{
		float add=0.0f;
		float sub=0.0f;

		if (m_firedThisFrame)
		{
			add = m_pParams->attack;

			if(pActor && pActor->GetLinkedVehicle())
			{
				const static float k_VehicleCombatMode_ScaleOverheat = 0.5f;
				add = m_pParams->attack * k_VehicleCombatMode_ScaleOverheat;	
			}

		}
		else if (m_pOwnerFiremode->GetNextShotTime()<=0.0001f && !m_pOwnerFiremode->IsFiring())
		{
			sub=frameTime / m_pParams->decay;
		}

		m_heat = clamp_tpl(m_heat + (add-sub), 0.0f, 1.0f);

		if (m_heat >= 0.999f && oldheat<0.999f)
		{
			m_overheat = m_pParams->duration;
			m_isCoolingDown = true;

			m_pOwnerFiremode->StopFire();
			FragmentID fragment = pWeapon->GetFragmentID(m_pParams->overheating.c_str());
			pWeapon->PlayAction(fragment);

			int slot = pWeapon->GetStats().fp ? eIGS_FirstPerson : eIGS_ThirdPerson;
			if (!m_pParams->effect[slot].empty())
			{
				if (m_heatEffectId)
				{
					pWeapon->DetachEffect(m_heatEffectId);
					m_heatEffectId = 0;
				}

				m_heatEffectId = pWeapon->AttachEffect(slot, false, m_pParams->effect[slot].c_str(), m_pParams->helper[slot].c_str());
			}
		}
		else if(m_heat <= m_pParams->refire_heat)
		{
			m_isCoolingDown = false;
		}
	}

	m_firedThisFrame = false;

	return (m_heat > 0.0001f);
}
コード例 #26
0
//------------------------------------------------------------------------
void CVehicleSeatActionRotateTurret::UpdatePartRotation(EVehicleTurretRotationType eType, float frameTime)
{
	CRY_ASSERT( eType < eVTRT_NumRotationTypes );

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

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

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

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

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

	Limit( delta, -max_rotation, max_rotation);

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

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

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

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

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

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

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

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

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

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

}
コード例 #27
0
ファイル: XInputDevice.cpp プロジェクト: aronarts/FireNET
void CXInputDevice::SetDeadZone(float fThreshold)
{
	m_fDeadZone = clamp_tpl(fThreshold, 0.001f, 1.0f) * INPUT_DEADZONE_MULTIPLIER;
}
コード例 #28
0
ファイル: BoidBird.cpp プロジェクト: aronarts/FireNET
void CBoidBird::Think( float dt,SBoidContext &bc )
{
	m_accel.zero();
	

	float factorAlignment = bc.factorAlignment;
	float factorCohesion = bc.factorCohesion;
	float factorSeparation = bc.factorSeparation;
	float factorAvoidLand = bc.factorAvoidLand;
	float factorAttractToOrigin = bc.factorAttractToOrigin;
	float factorKeepHeight = bc.factorKeepHeight;

	if(m_status == Bird::LANDING)
	{
		//factorAlignment /= 3.f;
		factorCohesion *=10.f;
		factorSeparation = 0;
		factorAvoidLand = 0;
		factorAttractToOrigin *=10;
		factorKeepHeight = 0;
	}
	
	if (m_spawnFromPt)
	{
		// Set the acceleration of the boid
		float fHalfDesired = m_desiredHeigh * .5f;
		if (m_pos.z < fHalfDesired)
		{
			m_accel.z = 3.f;
		}
		else
		{
			m_accel.z = .5f;
			// Set z-acceleration
			float fRange = 1.f - (m_pos.z-fHalfDesired)/fHalfDesired;	// 1..0 range

			if (m_heading.z > 0.2f)
				m_accel.z = .5f + fRange;	// 2..1

			m_accel.x += m_heading.x * .1f;
			m_accel.y += m_heading.y * .1f;
		}

		if (m_pos.z > m_desiredHeigh)
			SetSpawnFromPt(false);

		// Limits birds to above water and land.
		if (m_pos.z < bc.terrainZ-0.2f)
		{
			m_pos.z = bc.terrainZ-0.2f;
		}
		if (m_pos.z < bc.waterLevel-0.2f)
		{
			m_pos.z = bc.waterLevel-0.2f;
		}
		return;
	}
	
	float height = m_pos.z - bc.flockPos.z;

	// Free will.
	// Continue accelerating in same dir until target speed reached.
	// Try to maintain average speed of (maxspeed+minspeed)/2
	float targetSpeed = (bc.MaxSpeed + bc.MinSpeed)/2;
	m_accel -= m_heading*(m_speed-targetSpeed)*0.5f;

	// Desired height.
	float dh = m_desiredHeigh - m_pos.z;
	float dhexp = -(dh*dh)/(3*3);

	dhexp = clamp_tpl(dhexp,-70.0f,70.0f); // Max values for expf
	// Gaussian weight.
	float fKeepHeight = factorKeepHeight - m_fNoKeepHeight;
	m_fNoKeepHeight = max(0.f, m_fNoKeepHeight - .01f*dt);
	m_accel.z = exp_tpl(dhexp) * fKeepHeight;

	if (factorAlignment != 0)
	{
		//CalcCohesion();
		Vec3 alignmentAccel;
		Vec3 cohesionAccel;
		Vec3 separationAccel;
		CalcFlockBehavior(bc,alignmentAccel,cohesionAccel,separationAccel);

		//! Adjust for allignment,
		//m_accel += alignmentAccel.Normalized()*ALIGNMENT_FACTOR;

		m_accel += alignmentAccel*factorAlignment;
		m_accel += cohesionAccel*factorCohesion;
		m_accel += separationAccel*factorSeparation;
	}

	// Avoid land.
	if (height < bc.MinHeight && m_status != Bird::LANDING)
	{
		float v = (1.0f - height/bc.MinHeight);
		m_accel += Vec3(0,0,v*v)*bc.factorAvoidLand;
	}
	else if (height > bc.MaxHeight)
	{		// Avoid max height.
		float v = (height - bc.MaxHeight)*0.1f;
		m_accel += Vec3(0,0,-v);
	}
	else if(m_status != Bird::TAKEOFF)
	{
		// Always try to accelerate in direction opposite to current in Z axis.
		m_accel.z = -(m_heading.z*m_heading.z*m_heading.z * 100.0f);
	}

		// Attract to origin point.
	float fAttractToOrigin = factorAttractToOrigin - m_fNoCenterAttract;
	m_fNoCenterAttract = max(0.f, m_fNoCenterAttract - .01f*dt);
	if (bc.followPlayer)
	{
		m_accel += (bc.playerPos - m_pos) * fAttractToOrigin;
	}
	else
	{
		if ((rand()&31) == 1)
		{
			m_birdOriginPos = Vec3(	bc.flockPos.x+Boid::Frand()*bc.fSpawnRadius,bc.flockPos.y+Boid::Frand()*bc.fSpawnRadius,bc.flockPos.z+Boid::Frand()*bc.fSpawnRadius );
			if (m_birdOriginPos.z - bc.terrainZ < bc.MinHeight)
			{
				m_birdOriginPos.z = bc.terrainZ + bc.MinHeight;
			}
		}

		m_accel += (m_birdOriginPos - m_pos) * fAttractToOrigin;
	}

	// Attract to bc.attractionPoint
	if (m_pos.GetSquaredDistance2D(bc.attractionPoint) < 5.f)
	{
		SetAttracted(false);

		CBirdsFlock *pFlock = (CBirdsFlock *)m_flock;
		if (!pFlock->GetAttractOutput())
		{	// Activate the AttractTo flownode output
			pFlock->SetAttractOutput(true);

			// Activate the flow node output
			IEntity *pFlockEntity = pFlock->GetEntity();
			if (pFlockEntity)
			{
				IScriptTable *scriptObject = pFlockEntity->GetScriptTable();
				if (scriptObject)
					Script::CallMethod(scriptObject, "OnAttractPointReached");
			}
		}
	}
	if (m_attractedToPt)
	{
		if(m_status == Bird::ON_GROUND)
			TakeOff(bc);
		else
			SetStatus(Bird::FLYING);

		m_accel += (bc.attractionPoint - m_pos) * m_fAttractionFactor;
		if (m_fAttractionFactor < 300.f * factorAttractToOrigin) m_fAttractionFactor += 3.f*dt;
	}

	// Avoid collision with Terrain and Static objects.
	float fCollisionAvoidanceWeight = 1.0f;

	m_alignHorizontally = 0;

	if(m_status == Bird::TAKEOFF)
	{ 
		if(m_accel.z < 0)
			m_accel.z = -m_accel.z;

		m_accel.z *= bc.factorTakeOff;
	}

	if (bc.avoidObstacles)
	{
		// Avoid obstacles & terrain.
		float fCollDistance = m_collisionInfo.CheckDistance() ;

		if(m_collisionInfo.IsColliding())
		{
				float w = (1.0f - m_collisionInfo.Distance()/fCollDistance);
				m_accel += m_collisionInfo.Normal() * w*w * bc.factorAvoidLand * fCollisionAvoidanceWeight;
		}
	}

	// Limits birds to above water and land.
	if (m_pos.z < bc.terrainZ-0.2f)
	{
		m_pos.z = bc.terrainZ-0.2f;
	}
	if (m_pos.z < bc.waterLevel-0.2f)
	{
		m_pos.z = bc.waterLevel-0.2f;
	}
}
コード例 #29
0
void CPlayerStateGround::OnPrePhysicsUpdate( CPlayer& player, const SActorFrameMovementParams &movement, float frameTime, const bool isHeavyWeapon, const bool isPlayer )
{
	const Matrix34A baseMtx = Matrix34A(player.GetBaseQuat());
	Matrix34A baseMtxZ(baseMtx * Matrix33::CreateScale(Vec3Constants<float>::fVec3_OneZ));
	baseMtxZ.SetTranslation(Vec3Constants<float>::fVec3_Zero);

	const CAutoAimManager& autoAimManager = g_pGame->GetAutoAimManager();
	const EntityId closeCombatTargetId = autoAimManager.GetCloseCombatSnapTarget();
	const IActor* pCloseCombatTarget = isPlayer && closeCombatTargetId && player.IsClient() ? g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(closeCombatTargetId) : NULL;

	if (pCloseCombatTarget)
	{
		ProcessAlignToTarget(autoAimManager, player, pCloseCombatTarget);
	}
	else
	{
		// This is to restore inertia if the ProcessAlignToTarget set it previously.
		if( m_inertiaIsZero )
		{
			CPlayerStateUtil::RestorePlayerPhysics( player );

			m_inertiaIsZero = false;
		}

		//process movement
		const bool isRemote = isPlayer && !player.IsClient();

		Vec3 move(ZERO);
		CPlayerStateUtil::CalculateGroundOrJumpMovement( player, movement, isHeavyWeapon, move );
		player.GetMoveRequest().type = eCMT_Normal;






		//apply movement
		Vec3 desiredVel(ZERO);
		Vec3 entityPos = player.GetEntity()->GetWorldPos();
		Vec3 entityRight(player.GetBaseQuat().GetColumn0());

		hwvec3 xmDesiredVel = HWV3Zero();

		hwmtx33 xmBaseMtxZ;
		HWMtx33LoadAligned(xmBaseMtxZ, baseMtxZ);
		hwmtx33 xmBaseMtxZOpt = HWMtx33GetOptimized(xmBaseMtxZ);

		hwvec3 xmMove					= HWVLoadVecUnaligned(&move);	
		simdf fGroundNormalZ;

#ifdef STATE_DEBUG
		bool debugJumping = (g_pGameCVars->pl_debug_jumping != 0);
#endif

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

		{
			xmDesiredVel = xmMove;

			Vec3 groundNormal = player.GetActorPhysics().groundNormal;

			if(!gEnv->bMultiplayer)
			{
				if (player.IsAIControlled())
					fGroundNormalZ = SIMDFLoadFloat(square(groundNormal.z));
				else
					fGroundNormalZ = SIMDFLoadFloat(groundNormal.z);
			}
			else
			{
				//If the hill steepness is greater than our minimum threshold
				if(groundNormal.z > 1.f - cosf(g_pGameCVars->pl_movement.mp_slope_speed_multiplier_minHill))
				{
					//Check if we are trying to move up or downhill
					groundNormal.z = 0.f;
					groundNormal.Normalize();

					Vec3 moveDir = move;
					moveDir.z = 0.f;
					moveDir.Normalize();

					float normalDotMove = groundNormal.Dot(moveDir);
					//Apply speed multiplier based on moving up/down hill and hill steepness
					float multiplier = normalDotMove < 0.f ? g_pGameCVars->pl_movement.mp_slope_speed_multiplier_uphill : g_pGameCVars->pl_movement.mp_slope_speed_multiplier_downhill;
					fGroundNormalZ = SIMDFLoadFloat(1.f - (1.f - player.GetActorPhysics().groundNormal.z) * multiplier);
				}
				else
				{
					fGroundNormalZ = SIMDFLoadFloat(1.0f);
				}
			}

			const float depthHi = g_pGameCVars->cl_shallowWaterDepthHi;
			const float depthLo = g_pGameCVars->cl_shallowWaterDepthLo;
			const float relativeBottomDepth = player.m_playerStateSwim_WaterTestProxy.GetRelativeBottomDepth();

			if( relativeBottomDepth > depthLo )
			{ // Shallow water speed slowdown
				float shallowWaterMultiplier = 1.0f;

				shallowWaterMultiplier = isPlayer
					? g_pGameCVars->cl_shallowWaterSpeedMulPlayer
					: g_pGameCVars->cl_shallowWaterSpeedMulAI;

				shallowWaterMultiplier = max(shallowWaterMultiplier, 0.1f);
				assert(shallowWaterMultiplier <= 1.0f);


				float shallowWaterDepthSpan = (depthHi - depthLo);
				shallowWaterDepthSpan = max(0.1f, shallowWaterDepthSpan);

				float slowdownFraction = (relativeBottomDepth - depthLo) / shallowWaterDepthSpan;
				slowdownFraction = clamp_tpl(slowdownFraction, 0.0f, 1.0f);
				shallowWaterMultiplier = LERP(1.0f, shallowWaterMultiplier, slowdownFraction);

				//avoid branch if m_stats.relativeBottomDepth <= 0.0f;
				shallowWaterMultiplier = (float)__fsel(-relativeBottomDepth, 1.0f, shallowWaterMultiplier);

				simdf vfShallowWaterMultiplier = SIMDFLoadFloat(shallowWaterMultiplier);

				xmDesiredVel = HWVMultiplySIMDF(xmDesiredVel, vfShallowWaterMultiplier);
			}
		}





		// Slow down on sloped terrain, simply proportional to the slope. 
		xmDesiredVel = HWVMultiplySIMDF(xmDesiredVel, fGroundNormalZ);

		//be sure desired velocity is flat to the ground
		hwvec3 vDesiredVelVert = HWMtx33RotateVecOpt(xmBaseMtxZOpt, xmDesiredVel);

		xmDesiredVel = HWVSub(xmDesiredVel, vDesiredVelVert);

		HWVSaveVecUnaligned(&desiredVel, xmDesiredVel);

		if (isPlayer)
		{
			Vec3 modifiedSlopeNormal = player.GetActorPhysics().groundNormal;
			float h = Vec2(modifiedSlopeNormal.x, modifiedSlopeNormal.y).GetLength(); // TODO: OPT: sqrt(x*x+y*y)
			float v = modifiedSlopeNormal.z;
			float slopeAngleCur = RAD2DEG(atan2_tpl(h, v));

			const float divisorH = (float)__fsel(-h, 1.0f, h);
			const float divisorV = (float)__fsel(-v, 1.0f, v);

			const float invV = __fres(divisorV);
			const float invH = __fres(divisorH);

			const float slopeAngleHor = 10.0f;
			const float slopeAngleVer = 50.0f;
			float slopeAngleFraction = clamp_tpl((slopeAngleCur - slopeAngleHor) * __fres(slopeAngleVer - slopeAngleHor), 0.0f, 1.0f);

			slopeAngleFraction = slopeAngleFraction * slopeAngleFraction * slopeAngleFraction;

			float slopeAngleMod = LERP(0.0f, 90.0f, slopeAngleFraction);

			float s, c;

			sincos_tpl(DEG2RAD(slopeAngleMod), &s, &c);

			const float hMultiplier = (float)__fsel(-h, 1.0f, s * invH);
			const float vMultiplier = (float)__fsel(-v, 1.0f, c * invV);

			modifiedSlopeNormal.x *= hMultiplier;
			modifiedSlopeNormal.y *= hMultiplier;
			modifiedSlopeNormal.z *= vMultiplier;

			//Normalize the slope normal if possible
			const float fSlopeNormalLength = modifiedSlopeNormal.len();
			const float fSlopeNormalLengthSafe = (float)__fsel(fSlopeNormalLength - 0.000001f, fSlopeNormalLength, 1.0f);
			modifiedSlopeNormal = modifiedSlopeNormal * __fres(fSlopeNormalLengthSafe);

			float alignment = min(modifiedSlopeNormal * desiredVel, 0.0f);

			// Also affect air control (but not as much), to prevent jumping up against steep slopes.

			alignment *= (float)__fsel(-fabsf(stats.onGround), LERP(0.7f, 1.0f, 1.0f - clamp_tpl(modifiedSlopeNormal.z * 100.0f, 0.0f, 1.0f)), 1.0f);

			modifiedSlopeNormal.z = modifiedSlopeNormal.z;

			desiredVel -= modifiedSlopeNormal * alignment;


#ifdef STATE_DEBUG
			if (debugJumping)
			{
				player.DebugGraph_AddValue("GroundSlope", slopeAngleCur);
				player.DebugGraph_AddValue("GroundSlopeMod", slopeAngleMod);
			}
#endif
		}





		Vec3 newVelocity = desiredVel;

		const float fNewSpeed = newVelocity.len();

		const float fVelocityMultiplier = (float)__fsel(fNewSpeed - 22.0f, __fres(fNewSpeed+FLT_EPSILON) * 22.0f, 1.0f);

		// TODO: Maybe we should tell physics about this new velocity ? Or maybe SPlayerStats::velocity ? (stephenn).
		player.GetMoveRequest().velocity = newVelocity * (stats.flashBangStunMult * fVelocityMultiplier);

#ifdef STATE_DEBUG
		if(g_pGameCVars->pl_debug_movement > 0)
		{
			const char* filter = g_pGameCVars->pl_debug_filter->GetString();
			const char* name = player.GetEntity()->GetName();
			if ((strcmp(filter, "0") == 0) || (strcmp(filter, name) == 0))
			{
				float white[] = {1.0f,1.0f,1.0f,1.0f};
				gEnv->pRenderer->Draw2dLabel(20, 450, 2.0f, white, false, "Speed: %.3f m/s", player.GetMoveRequest().velocity.len());

				if(g_pGameCVars->pl_debug_movement > 1)
				{
					gEnv->pRenderer->Draw2dLabel(35, 470, 1.8f, white, false, "Stance Speed: %.3f m/s - (%sSprinting)", player.GetStanceMaxSpeed(player.GetStance()), player.IsSprinting() ? "" : "Not ");
				}
			}
		}
#endif


























	}

	if( isPlayer )
	{
		CheckForVaultTrigger(player, frameTime);
	}
}
コード例 #30
0
bool CDialogActorContext::DoLocalPlayerChecks(const float dt)
{
	// don't check this every frame, but only every .2 secs
	m_checkPlayerTimeOut-=dt;
	if (m_checkPlayerTimeOut <= 0.0f)
	{
		do // a dummy loop to use break
		{
			float awareDistance;
			float awareDistanceSq;
			float awareAngle;
			m_pSession->GetPlayerAwarenessValues(awareDistance, awareAngle);
			awareDistanceSq=awareDistance*awareDistance;

			m_checkPlayerTimeOut = PLAYER_CHECKTIME;
			const float spotAngleCos = cos_tpl(DEG2RAD(awareAngle));
	
			const CDialogSession::TActorContextMap& contextMap = m_pSession->GetAllContexts();
			if (contextMap.size() == 1 && contextMap.begin()->first == m_actorID)
			{
				m_bIsAware = true;
				break;
			}
	
			// early out, when we don't have to do any checks
			if (awareDistance <= 0.0f && awareAngle <= 0.0f)
			{
				m_bIsAware = true;
				break;
			}

			IEntity* pThisEntity = m_pSession->GetActorEntity(m_actorID);
			if (!pThisEntity)
			{
				assert (false);
				m_bIsAware = true;
				break;
			}
			IMovementController* pMC = (m_pIActor != NULL) ? m_pIActor->GetMovementController() : NULL;
			if (!pMC)
			{
				assert (false);
				m_bIsAware = true;
				break;
			}
			SMovementState moveState;
			pMC->GetMovementState(moveState);
			Vec3 viewPos = moveState.eyePosition;
			Vec3 viewDir = moveState.eyeDirection;
			viewDir.z = 0.0f;
			viewDir.NormalizeSafe();
	
			// check the player's position
			// check the player's view direction
			AABB groupBounds;
			groupBounds.Reset();

			CDialogSession::TActorContextMap::const_iterator iter = contextMap.begin();
			CDialogScript::SActorSet lookingAt = 0;
			while (iter != contextMap.end())
			{
				if (iter->first != m_actorID)
				{
					IEntity* pActorEntity = m_pSession->GetActorEntity(iter->first);
					if (pActorEntity)
					{
						Vec3 vEntityPos = pActorEntity->GetWorldPos();
						AABB worldBounds;
						pActorEntity->GetWorldBounds(worldBounds);
						groupBounds.Add(worldBounds);
						// calc if we look at it somehow
						Vec3 vEntityDir = vEntityPos - viewPos;
						vEntityDir.z = 0.0f;
						vEntityDir.NormalizeSafe();
						if (viewDir.IsUnit() && vEntityDir.IsUnit())
						{
							const float dot = clamp_tpl(viewDir.Dot(vEntityDir),-1.0f,+1.0f); // clamping should not be needed
							if (spotAngleCos <= dot)
								lookingAt.SetActor(iter->first);
							DiaLOG::Log(DiaLOG::eDebugC, "Angle to actor %d is %f deg", iter->first, RAD2DEG(acos_tpl(dot)));
						}
					}
				}
				++iter;
			}

			const float distanceSq = pThisEntity->GetWorldPos().GetSquaredDistance(groupBounds.GetCenter());
			CCamera& camera=gEnv->pSystem->GetViewCamera();
			const bool bIsInAABB  = camera.IsAABBVisible_F(groupBounds);
			const bool bIsInRange = distanceSq <= awareDistanceSq;
			const bool bIsLooking = contextMap.empty() || lookingAt.NumActors() > 0;
			m_bIsAwareLooking = awareAngle <= 0.0f || (bIsInAABB || bIsLooking);
			m_bIsAwareInRange = awareDistance <= 0.0f || bIsInRange;
			m_bIsAware = m_bIsAwareLooking && m_bIsAwareInRange;

			DiaLOG::Log(DiaLOG::eDebugB, "[DIALOG] LPC: %s awDist=%f awAng=%f AABBVis=%d IsLooking=%d InRange=%d [Distance=%f LookingActors=%d] Final=%saware", 
				m_pSession->GetDebugName(), awareDistance, awareAngle, bIsInAABB, bIsLooking, bIsInRange, sqrt_tpl(distanceSq), lookingAt.NumActors(), m_bIsAware ? "" : "not ");
		
		} while (false);
	}

	if (m_bIsAware)
	{
		m_playerAwareTimeOut = m_pSession->GetPlayerAwarenessGraceTime();
	}
	else
	{
		m_playerAwareTimeOut-= dt;
		if (m_playerAwareTimeOut <= 0)
		{
			return false;
		}
	}

	return true;
}