void CCannonBall::HandlePierceableSurface( const EventPhysCollision* pCollision, IEntity* pHitTarget, const Vec3& hitDirection, bool bProcessedCollisionEvent )
{
	FUNCTION_PROFILER(GetISystem(), PROFILE_GAME);

	const SPierceabilityParams& pierceabilityParams = m_pAmmoParams->pierceabilityParams;
	
	const int maxPenetrationCount = 4;
	const float entryAngleDot = pCollision->n.Dot(hitDirection);
	bool backFace = (entryAngleDot >= 0);

#ifdef DEBUG_CannonBall_PENETRATION
	bool debugCannonBallPenetration = (g_pGameCVars->g_bulletPenetrationDebug != 0);
#endif

	if (backFace == false)
	{
		//Front face hit, accumulate damage falloff after penetration
		float bouncy, friction;
		uint32 pierceabilityMat;
		gEnv->pPhysicalWorld->GetSurfaceParameters(pCollision->idmat[1], bouncy, friction, pierceabilityMat);
		pierceabilityMat &= sf_pierceable_mask;

#ifdef DEBUG_CannonBall_PENETRATION
		const float damageBeforePenetration = GetDamageAfterPenetrationFallOff();
#endif

		m_penetrationCount++;

		//1- Check if collided surface might stop the Cannon Ball
		const bool collisionStopsCannonBall = (!bProcessedCollisionEvent) || 
			(pCollision->idCollider == -1) || 
			((int16)pierceabilityMat <= GetCannonBallPierceability()) || 
			(m_penetrationCount >= maxPenetrationCount);
		
		if (collisionStopsCannonBall)
		{
#ifdef DEBUG_CannonBall_PENETRATION
			if (debugCannonBallPenetration)
			{
				s_debugCannonBallPenetration.AddCannonBallHit(pCollision->pt, hitDirection, damageBeforePenetration, (pCollision->idCollider == -1) ? -1 : pierceabilityMat, false, true, false);
			}
#endif
			m_accumulatedDamageFallOffAfterPenetration += (float)m_damage;
			return;
		}

		//2- If not stopped, add fall off damage, and see if can still penetrate
		m_accumulatedDamageFallOffAfterPenetration += (float)m_damage * (pierceabilityParams.GetDamageFallOffForPierceability(pierceabilityMat) * 0.01f);
		
		bool needsBackFaceCheck = (GetDamageAfterPenetrationFallOff() > 0.0f) && pierceabilityParams.SurfaceRequiresBackFaceCheck(pierceabilityMat);

#ifdef DEBUG_CannonBall_PENETRATION
		if (debugCannonBallPenetration)
		{
			if (ShouldDestroyCannonBall())
			{
				s_debugCannonBallPenetration.AddCannonBallHit(pCollision->pt, hitDirection, damageBeforePenetration, pierceabilityMat, false, true, false);
			}
		}
#endif

		if (needsBackFaceCheck)
		{
			//3- Raytrace backwards, to check thickness & exit point if any
			const float angleFactor = 1.0f/max(0.2f, -entryAngleDot);
			const float distCheck = pierceabilityParams.maxPenetrationThickness * angleFactor;

			SBackHitInfo hit;
			bool exitPointFound = RayTraceGeometry(pCollision, pCollision->pt + (hitDirection * (distCheck + 0.035f)), -hitDirection * distCheck ,&hit);

			if (exitPointFound)
			{
				//Exit point found
				if(ShouldSpawnBackSideEffect(pHitTarget))
				{
					//Spawn effect
					IMaterialEffects* pMaterialEffects = g_pGame->GetIGameFramework()->GetIMaterialEffects();
					TMFXEffectId effectId = pMaterialEffects->GetEffectId(GetEntity()->GetClass(), pCollision->idmat[1]);
					if (effectId != InvalidEffectId)
					{
						SMFXRunTimeEffectParams params;
						params.src = GetEntityId();
						params.trg = pHitTarget ? pHitTarget->GetId() : 0;
						params.srcSurfaceId = pCollision->idmat[0];
						params.trgSurfaceId = pCollision->idmat[1]; 
						params.soundSemantic = eSoundSemantic_Physics_Collision;
						params.srcRenderNode = (pCollision->iForeignData[0] == PHYS_FOREIGN_ID_STATIC) ? (IRenderNode*)pCollision->pForeignData[0] : NULL;
						params.trgRenderNode = (pCollision->iForeignData[1] == PHYS_FOREIGN_ID_STATIC) ? (IRenderNode*)pCollision->pForeignData[1] : NULL;
						params.pos = hit.pt;
						params.normal = hitDirection; //Use Cannon direction, more readable for exits than normal
						params.partID = pCollision->partid[1];
						params.dir[0] = -hitDirection;
						params.playflags = MFX_PLAY_ALL&(~MFX_PLAY_SOUND); //Do not play the sound on backface
						params.playflags &= ~MFX_PLAY_DECAL; //We disable also decals, since hit.pt is not refined with render mesh
						params.fDecalPlacementTestMaxSize = pCollision->fDecalPlacementTestMaxSize;

						pMaterialEffects->ExecuteEffect(effectId, params);
					}
				}

#ifdef DEBUG_CannonBall_PENETRATION
				if (debugCannonBallPenetration)
				{
					s_debugCannonBallPenetration.AddCannonBallHit(pCollision->pt, hitDirection, damageBeforePenetration, pierceabilityMat, false, false, false);
					s_debugCannonBallPenetration.AddCannonBallHit(hit.pt, hitDirection, GetDamageAfterPenetrationFallOff(), pierceabilityMat, true, false, false);
				}
#endif
			}
			else
			{
#ifdef DEBUG_CannonBall_PENETRATION
				if (debugCannonBallPenetration)
				{
					s_debugCannonBallPenetration.AddCannonBallHit(pCollision->pt, hitDirection, damageBeforePenetration, pierceabilityMat, false, true, true);
				}
#endif
				//Surface must be too thick, add enough fall off to destroy the Cannon Ball
				m_accumulatedDamageFallOffAfterPenetration += (float)m_damage;
			}
		}
	}
}
Beispiel #2
0
void CPlayerRotation::Process(IItem* pCurrentItem, const SActorFrameMovementParams& movement, const SAimAccelerationParams& verticalAcceleration, float frameTime)
{
	FUNCTION_PROFILER(GetISystem(), PROFILE_GAME);

	// reset to the new impulse.
	m_angularImpulseDelta = m_angularImpulse;

	m_deltaAngles = movement.deltaAngles;

	PR_CHECKQNAN_FLT(m_deltaAngles);

	// Store the previous rotation to get the correct rotation for linked actors.
	const Quat previousBaseQuat = m_baseQuat;
	const Quat previousViewQuat = m_viewQuat;

	ProcessForcedLookDirection(m_viewQuatFinal, frameTime);

	ProcessAngularImpulses( frameTime );

	ProcessLeanAndPeek( movement );

	ProcessNormalRoll( frameTime );

	bool shouldProcessTargetAssistance = ShouldProcessTargetAssistance();
	if (shouldProcessTargetAssistance)
	{
		ProcessTargetAssistance( pCurrentItem );
	}

#if TALOS
	if(stricmp(g_pGameCVars->pl_talos->GetString(), m_player.GetEntity()->GetName()) == 0)
	{
		IMovementController* pMovementController = m_player.GetMovementController();
		CRY_ASSERT(pMovementController);
		SMovementState moveState;
		pMovementController->GetMovementState(moveState);

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

		GetTalosInput(this, m_player, m_deltaAngles.x, m_deltaAngles.z, playerView, frameTime);
	}
#endif

	float minAngle,maxAngle;
	GetStanceAngleLimits(verticalAcceleration, pCurrentItem, minAngle, maxAngle);
	ClampAngles( minAngle, maxAngle );

	ProcessNormal( frameTime );

	if(shouldProcessTargetAssistance)
	{
		IVehicle* pVehicle = m_player.GetLinkedVehicle();
		if (pVehicle && GetCurrentItem(true))
		{
			if (m_deltaAngles.x!=0.f)
				pVehicle->OnAction(eVAI_RotatePitchAimAssist, eAAM_Always, m_deltaAngles.x, m_player.GetEntity()->GetId());
			if (m_deltaAngles.z!=0.f)
				pVehicle->OnAction(eVAI_RotateYawAimAssist, eAAM_Always, m_deltaAngles.z, m_player.GetEntity()->GetId());
		}
	}

	//update freelook when linked to an entity
	ProcessLinkedState(m_player.m_linkStats, previousBaseQuat, previousViewQuat);

	//Recoil/Zoom sway offset for local player
	ProcessFinalViewEffects( minAngle, maxAngle );

	m_frameViewAnglesOffset.Set(0.0f, 0.0f, 0.0f);
	m_forceLookVector.zero();
	m_externalAngles.Set(0.f, 0.f, 0.f);

	NormalizeQuats();
}
bool CDevMode::OnInputEvent( const SInputEvent& evt )
{
	FUNCTION_PROFILER(GetISystem(), PROFILE_ACTION);
	bool handled = false;
	bool canCheat = CCryAction::GetCryAction()->CanCheat();

	IActor* pActor = CCryAction::GetCryAction()->GetClientActor();
	if (!pActor) return false;
	IEntity* pEntity = pActor->GetEntity();
	if (!pEntity) return false;

	// tag-point functionality is provided by the editor already, so we should ignore it
	// when running in the editor
	if (!gEnv->IsEditor())
	{
		if ((evt.state == eIS_Pressed) && canCheat)
		{
			if ((evt.modifiers & eMM_Shift)!=0 && (evt.modifiers & eMM_Alt) == 0) // Shift ONLY
			{
				if (handled = (evt.keyId == eKI_F1)) GotoTagPoint(0);
				if (handled = (evt.keyId == eKI_F2)) GotoTagPoint(1);
				if (handled = (evt.keyId == eKI_F3)) GotoTagPoint(2);
				if (handled = (evt.keyId == eKI_F4)) GotoTagPoint(3);
				if (handled = (evt.keyId == eKI_F5)) GotoTagPoint(4);
				if (handled = (evt.keyId == eKI_F6)) GotoTagPoint(5);
				if (handled = (evt.keyId == eKI_F7)) GotoTagPoint(6);
				if (handled = (evt.keyId == eKI_F8)) GotoTagPoint(7);
				if (handled = (evt.keyId == eKI_F9)) GotoTagPoint(8);
				if (handled = (evt.keyId == eKI_F10)) GotoTagPoint(9);
				if (handled = (evt.keyId == eKI_F11)) GotoTagPoint(10);
				if (handled = (evt.keyId == eKI_F12)) GotoTagPoint(11);
			}
			else if ((evt.modifiers & eMM_Shift) == 0 && ((evt.modifiers & eMM_Alt)!=0 || (evt.modifiers & eMM_Ctrl)!=0)) // Alt or Ctrl and NO Shift
			{
				if (handled = (evt.keyId == eKI_F1)) SaveTagPoint(0);
				if (handled = (evt.keyId == eKI_F2)) SaveTagPoint(1);
				if (handled = (evt.keyId == eKI_F3)) SaveTagPoint(2);
				if (handled = (evt.keyId == eKI_F4)) SaveTagPoint(3);
				if (handled = (evt.keyId == eKI_F5)) SaveTagPoint(4);
				if (handled = (evt.keyId == eKI_F6)) SaveTagPoint(5);
				if (handled = (evt.keyId == eKI_F7)) SaveTagPoint(6);
				if (handled = (evt.keyId == eKI_F8)) SaveTagPoint(7);
				if (handled = (evt.keyId == eKI_F9)) SaveTagPoint(8);
				if (handled = (evt.keyId == eKI_F10)) SaveTagPoint(9);
				if (handled = (evt.keyId == eKI_F11)) SaveTagPoint(10);
				if (handled = (evt.keyId == eKI_F12)) SaveTagPoint(11);
			}
		}
	}
	else
	{
		// place commands which should only be dealt with in game mode here
	}

	// shared commands
	if (canCheat)
	{
		if (!handled && (evt.state == eIS_Pressed) && (evt.modifiers & eMM_Shift) != 0 && (evt.modifiers & eMM_Alt) != 0)
		{
			if (handled = (evt.keyId == eKI_NP_1)) GotoSpecialSpawnPoint(1);
			if (handled = (evt.keyId == eKI_NP_2)) GotoSpecialSpawnPoint(2);
			if (handled = (evt.keyId == eKI_NP_3)) GotoSpecialSpawnPoint(3);
			if (handled = (evt.keyId == eKI_NP_4)) GotoSpecialSpawnPoint(4);
			if (handled = (evt.keyId == eKI_NP_5)) GotoSpecialSpawnPoint(5);
			if (handled = (evt.keyId == eKI_NP_6)) GotoSpecialSpawnPoint(6);
			if (handled = (evt.keyId == eKI_NP_7)) GotoSpecialSpawnPoint(7);
			if (handled = (evt.keyId == eKI_NP_8)) GotoSpecialSpawnPoint(8);
			if (handled = (evt.keyId == eKI_NP_9)) GotoSpecialSpawnPoint(9);
		}
		else if (!handled && (evt.state == eIS_Pressed) && !(evt.modifiers & eMM_Modifiers))
		{
			if (handled = (evt.keyId == eKI_NP_1) && !gEnv->bMultiplayer)	// give all items
			{
				CCryAction::GetCryAction()->GetIItemSystem()->GetIEquipmentManager()->GiveEquipmentPack(pActor, "Player_Default", true, true);
			}
			else if (handled = (evt.keyId == eKI_F2))	// go to next spawnpoint
			{
				Vec3 oldPos = pEntity->GetWorldPos();
				if (gEnv->pScriptSystem->BeginCall("BasicActor", "OnNextSpawnPoint"))
				{
					gEnv->pScriptSystem->PushFuncParam(pEntity->GetScriptTable());
					gEnv->pScriptSystem->EndCall();

					if (gEnv->pStatoscope)
					{
						char buffer[100];
						Vec3 pos = pEntity->GetWorldPos();
						sprintf(buffer, "Teleported from (%.2f, %.2f, %.2f) to (%.2f, %.2f, %.2f)", oldPos.x, oldPos.y, oldPos.z, pos.x, pos.y, pos.z);
						gEnv->pStatoscope->AddUserMarker("Player", buffer);
					}
				}
			}
		}
	}

	if (handled == false && evt.state == eIS_Pressed && (evt.modifiers & eMM_Alt)!=0)
	{
		if(evt.keyId == eKI_F7)
			SwitchSlowDownGameSpeed();
		else if(evt.keyId==eKI_F8)
			SwitchHUD();
	}

	// AlexL: don't mark commands as handled for now. Would stop processing/propagating to other
	//        listeners. especially for non-modifier keys like f7,f8,f9 problematic
	return false; // handled;
}
//------------------------------------------------------------------------
void CCannonBall::HandleEvent(const SGameObjectEvent &event)
{
	FUNCTION_PROFILER(GetISystem(), PROFILE_GAME);

	BaseClass::HandleEvent(event);

	if (event.event == eGFE_OnCollision)
	{
		if (CheckAnyProjectileFlags(ePFlag_destroying))
			return;

		EventPhysCollision *pCollision = reinterpret_cast<EventPhysCollision *>(event.ptr);
		if (!pCollision)
			return;

		float finalDamage = GetFinalDamage(pCollision->pt);
		if (finalDamage <= 0.0f)
			m_alive = false;
        
		IEntity *pTarget = pCollision->iForeignData[1]==PHYS_FOREIGN_ID_ENTITY ? (IEntity*)pCollision->pForeignData[1]:0;
		CGameRules *pGameRules = g_pGame->GetGameRules();
		const int hitMatId = pCollision->idmat[1];

		Vec3 hitDir(ZERO);
		if (pCollision->vloc[0].GetLengthSquared() > 1e-6f)
		{
			hitDir = pCollision->vloc[0].GetNormalized();
		}

		const bool bProcessCollisionEvent = ProcessCollisionEvent(pTarget);
		if (bProcessCollisionEvent)
		{
			//================================= Process Hit =====================================
			//Only process hits that have a target
			if(pTarget)
			{
				if(FilterFriendlyAIHit(pTarget) == false)
				{
					ProcessHit(*pGameRules, *pCollision, *pTarget, finalDamage, hitMatId, hitDir);
				}
			}
			//====================================~ Process Hit ======================================

			//==================================== Notify AI    ======================================
			if (gEnv->pAISystem)
			{
				if (gEnv->pEntitySystem->GetEntity(m_ownerId))
				{
					ISurfaceType *pSurfaceType = gEnv->p3DEngine->GetMaterialManager()->GetSurfaceType(hitMatId);
					const ISurfaceType::SSurfaceTypeAIParams* pParams = pSurfaceType ? pSurfaceType->GetAIParams() : 0;
					const float radius = pParams ? pParams->fImpactRadius : 2.5f;
					const float soundRadius = pParams ? pParams->fImpactSoundRadius : 20.0f;

					SAIStimulus stim(AISTIM_BULLET_HIT, 0, m_ownerId, pTarget ? pTarget->GetId() : 0, pCollision->pt, pCollision->vloc[0].GetNormalizedSafe(ZERO), radius);
					gEnv->pAISystem->RegisterStimulus(stim);

					SAIStimulus stimSound(AISTIM_SOUND, AISTIM_BULLET_HIT, m_ownerId, 0, pCollision->pt, ZERO, soundRadius);
					gEnv->pAISystem->RegisterStimulus(stim);
				}
			}
			//=========================================~ Notify AI ===============================
		}

		//========================================= Surface Pierceability ==============================
		if (pCollision->pEntity[0]->GetType() == PE_PARTICLE)
		{
			const SPierceabilityParams& pierceabilityParams = m_pAmmoParams->pierceabilityParams;

			//If collided water
			if( s_materialLookup.IsMaterial( pCollision->idmat[1], CProjectile::SMaterialLookUp::eType_Water ) )
			{
				if(pierceabilityParams.DestroyOnWaterImpact())
				{
					DestroyAtHitPosition(pCollision->pt);
				}
				else
				{
					EmitUnderwaterTracer(pCollision->pt, pCollision->pt + (pCollision->vloc[0].GetNormalizedSafe() * 100.0f));
				}
			}
			else if (m_pAmmoParams->bounceableBullet == 0)
			{
				float bouncy, friction;
				uint32 pierceabilityMat;
				gEnv->pPhysicalWorld->GetSurfaceParameters(pCollision->idmat[1], bouncy, friction, pierceabilityMat);
				pierceabilityMat &= sf_pierceable_mask;
				
				const bool terrainHit = (pCollision->idCollider == -1);

				bool thouShallNotPass = terrainHit;
				if (!CheckAnyProjectileFlags(ePFlag_ownerIsPlayer))
					thouShallNotPass = thouShallNotPass || pierceabilityParams.DestroyOnImpact(pierceabilityMat);

				if (!thouShallNotPass)
					HandlePierceableSurface(pCollision, pTarget, hitDir, bProcessCollisionEvent);

				const bool destroy = thouShallNotPass || ShouldDestroyCannonBall();
				if (destroy)
				{
					DestroyAtHitPosition(pCollision->pt);
				}
			}
		}
	}
}
//------------------------------------------------------------------------
void CVehicleMovementVTOL::ProcessActions(const float deltaTime)
{
	FUNCTION_PROFILER( GetISystem(), PROFILE_GAME );
	UpdateDamages(deltaTime);
	UpdateEngine(deltaTime);
	m_velDamp = 0.25f;
	m_playerControls.ProcessActions(deltaTime);
	Limit(m_forwardAction, -1.0f, 1.0f);
	Limit(m_strafeAction, -1.0f, 1.0f);
	m_actionYaw = 0.0f;
	Vec3 worldPos = m_pEntity->GetWorldPos();
	IPhysicalEntity *pPhysics = GetPhysics();
	// get the current state
	// roll pitch + yaw
	Matrix34 worldTM = m_pRotorPart ? m_pRotorPart->GetWorldTM() : m_pEntity->GetWorldTM();
	//	if (m_pRotorPart)
	//		worldTM = m_pRotorPart->GetWorldTM();
	//	else
	//		worldTM = m_pEntity->GetWorldTM();
	Vec3 specialPos = worldTM.GetTranslation();
	Ang3 angles = Ang3::GetAnglesXYZ(Matrix33(worldTM));
	Matrix33 tm;
	tm.SetRotationXYZ((angles));
	// +ve pitch means nose up
	const float &currentPitch = angles.x;
	// +ve roll means to the left
	const float &currentRoll = angles.y;
	// +ve direction mean rotation anti-clockwise about the z axis - 0 means along y
	float currentDir = angles.z;
	const float maxPitchAngle = 60.0f;
	float pitchDeg = RAD2DEG(currentPitch);

	if (pitchDeg >= (maxPitchAngle * 0.75f))
	{
		float mult = pitchDeg / (maxPitchAngle);

		if (mult > 1.0f && m_desiredPitch < 0.0f)
		{
			m_desiredPitch *= 0.0f;
			m_actionPitch *= 0.0f;
			m_desiredPitch += 0.2f * mult;
		}
		else if (m_desiredPitch < 0.0f)
		{
			m_desiredPitch *= (1.0f - mult);
			m_desiredPitch += 0.05f;
		}
	}
	else if (pitchDeg <= (-maxPitchAngle * 0.75f))
	{
		float mult = abs(pitchDeg) / (maxPitchAngle);

		if (mult > 1.0f && m_desiredPitch > 0.0f)
		{
			m_desiredPitch *= 0.0f;
			m_actionPitch *= 0.0f;
			m_desiredPitch += 0.2f * mult;
		}
		else if (m_desiredPitch > 0.0f)
		{
			m_desiredPitch *= (1.0f - mult);
			m_desiredPitch -= 0.05f;
		}
	}

	if (currentRoll >= DEG2RAD(m_maxRollAngle * 0.7f) && m_desiredRoll > 0.001f)
	{
		float r = currentRoll / DEG2RAD(m_maxRollAngle);
		r = min(1.0f, r * 1.0f);
		r = 1.0f - r;
		m_desiredRoll *= r;
		m_desiredRoll = min(1.0f, m_desiredRoll);
	}
	else if (currentRoll <= DEG2RAD(-m_maxRollAngle * 0.7f) && m_desiredRoll < 0.001f)
	{
		float r = abs(currentRoll) / DEG2RAD(m_maxRollAngle);
		r = min(1.0f, r * 1.0f);
		r = 1.0f - r;
		m_desiredRoll *= r;
		m_desiredRoll = max(-1.0f, m_desiredRoll);
	}

	Vec3 currentFwdDir2D = m_currentFwdDir;
	currentFwdDir2D.z = 0.0f;
	currentFwdDir2D.NormalizeSafe();
	Vec3 currentLeftDir2D(-currentFwdDir2D.y, currentFwdDir2D.x, 0.0f);
	Vec3 currentVel = m_PhysDyn.v;
	Vec3 currentVel2D = currentVel;
	currentVel2D.z = 0.0f;
	float currentHeight = worldPos.z;
	float currentFwdSpeed = currentVel.Dot(currentFwdDir2D);
	ProcessActions_AdjustActions(deltaTime);
	float inputMult = m_basicSpeedFraction;
	// desired things
	float turnDecreaseScale = m_yawDecreaseWithSpeed / (m_yawDecreaseWithSpeed + fabs(currentFwdSpeed));
	Vec3 desired_vel2D =
		currentFwdDir2D * m_forwardAction * m_maxFwdSpeed * inputMult +
		currentLeftDir2D * m_strafeAction * m_maxLeftSpeed * inputMult;
	// calculate the angle changes
	Vec3 desiredVelChange2D = desired_vel2D - currentVel2D;
	float desiredTiltAngle = m_tiltPerVelDifference * desiredVelChange2D.GetLength();
	Limit(desiredTiltAngle, -m_maxTiltAngle, m_maxTiltAngle);
	float goal = abs(m_desiredPitch) + abs(m_desiredRoll);
	goal *= 1.5f;
	Interpolate(m_playerAcceleration, goal, 0.25f, deltaTime);
	Limit(m_playerAcceleration, 0.0f, 5.0f);

	//static float g_angleLift = 4.0f;

	if (abs(m_liftAction) > 0.001f && abs(m_forwardAction) < 0.001)
	{
		//		float pitch = RAD2DEG(currentPitch);
		if (m_liftPitchAngle < 0.0f && m_liftAction > 0.0f)
		{
			m_liftPitchAngle = 0.0f;
		}
		else if (m_liftPitchAngle > 0.0f && m_liftAction < 0.0f)
		{
			m_liftPitchAngle = 0.0f;
		}

		Interpolate(m_liftPitchAngle, 1.25f * m_liftAction, 0.75f, deltaTime);

		if (m_liftPitchAngle < 1.0f && m_liftPitchAngle > -1.0f)
		{
			m_desiredPitch += 0.05f * m_liftAction;
		}
	}
	else if (m_liftAction < 0.001f && abs(m_liftPitchAngle) > 0.001)
	{
		Interpolate(m_liftPitchAngle, 0.0f, 1.0f, deltaTime);
		m_desiredPitch += 0.05f * -m_liftPitchAngle;
	}

	/* todo
	else if (m_liftAction < -0.001f)
	{
		m_desiredPitch += min(0.0f, (DEG2RAD(-5.0f) - currentPitch)) * 0.5f * m_liftAction;
	}*/

	if (!iszero(m_desiredPitch))
	{
		m_actionPitch -= m_desiredPitch * m_pitchInputConst;
		Limit(m_actionPitch, -m_maxYawRate, m_maxYawRate);
	}

	float rollAccel = 1.0f;

	if (abs(currentRoll + m_desiredRoll) < abs(currentRoll))
	{
		rollAccel *= 1.25f;
	}

	m_actionRoll += m_pitchActionPerTilt * m_desiredRoll * rollAccel * (m_playerAcceleration + 1.0f);
	Limit(m_actionRoll, -10.0f, 10.0f);
	Limit(m_actionPitch, -10.0f, 10.0f);

	// roll as we turn
	if (!m_strafeAction)
	{
		m_actionYaw += m_yawPerRoll * currentRoll;
	}

	if (abs(m_strafeAction) > 0.001f)
	{
		float side = 0.0f;
		side = min(1.0f, max(-1.0f, m_strafeAction));
		float roll = DEG2RAD(m_extraRollForTurn * 0.25f * side) - (currentRoll);
		m_actionRoll += max(0.0f, abs(roll)) * side * 1.0f;
	}

	float relaxRollTolerance = 0.0f;

	if (abs(m_turnAction) > 0.01f || abs(m_PhysDyn.w.z) > DEG2RAD(3.0f))
	{
		m_actionYaw += -m_turnAction * m_yawInputConst * GetDamageMult();
		float side = 0.0f;

		if (abs(m_turnAction) > 0.01f)
		{
			side = min(1.0f, max(-1.0f, m_turnAction));
		}

		float roll = DEG2RAD(m_extraRollForTurn * side) - (currentRoll);
		m_actionRoll += max(0.0f, abs(roll)) * side * m_rollForTurnForce;
		roll *= max(1.0f, abs(m_PhysDyn.w.z));
		m_actionRoll += roll;
		Limit(m_actionYaw, -m_maxYawRate, m_maxYawRate);
	}

	m_desiredDir = currentDir;
	m_lastDir = currentDir;
	float boost = Boosting() ? m_boostMult : 1.0f;
	float liftActionMax = 1.0f;

	if (m_pAltitudeLimitVar)
	{
		float altitudeLimit = m_pAltitudeLimitVar->GetFVal();

		if (!iszero(altitudeLimit))
		{
			float altitudeLowerOffset;

			if (m_pAltitudeLimitLowerOffsetVar)
			{
				float r = 1.0f - min(1.0f, max(0.0f, m_pAltitudeLimitLowerOffsetVar->GetFVal()));
				altitudeLowerOffset = r * altitudeLimit;
			}
			else
			{
				altitudeLowerOffset = altitudeLimit;
			}

			float mult = 1.0f;

			if (currentHeight >= altitudeLimit)
			{
				if (m_liftAction > 0.f)
				{
					mult = 0.0f;
				}
			}
			else if (currentHeight >= altitudeLowerOffset)
			{
				float zone = altitudeLimit - altitudeLowerOffset;
				mult = (altitudeLimit - currentHeight) / (zone);
			}

			m_liftAction *= mult;

			if (currentPitch > DEG2RAD(0.0f))
			{
				if (m_forwardAction > 0.0f)
				{
					m_forwardAction *= mult;
				}

				if (m_actionPitch > 0.0f)
				{
					m_actionPitch *= mult;
					m_actionPitch += -currentPitch;
				}
			}

			m_desiredHeight = min(altitudeLowerOffset, currentHeight);
		}
	}
	else
	{
		m_desiredHeight = currentHeight;
	}

	if (abs(m_liftAction) > 0.001f)
	{
		m_liftAction = min(liftActionMax, max(-0.2f, m_liftAction));
		m_hoveringPower = (m_powerInputConst * m_liftAction) * boost;
		m_noHoveringTimer = 0.0f;
	}
	else if (!m_isTouchingGround)
	{
		if (m_noHoveringTimer <= 0.0f)
		{
			float gravity;
			pe_simulation_params paramsSim;

			if (pPhysics->GetParams(&paramsSim))
			{
				gravity = abs(paramsSim.gravity.z);
			}
			else
			{
				gravity = 9.2f;
			}

			float upDirZ = m_workingUpDir.z;

			if (abs(m_forwardAction) > 0.01 && upDirZ > 0.0f)
			{
				upDirZ = 1.0f;
			}
			else if (upDirZ > 0.8f)
			{
				upDirZ = 1.0f;
			}

			float upPower = upDirZ;
			upPower -= min(1.0f, abs(m_forwardAction) * abs(angles.x));
			float turbulenceMult = 1.0f - min(m_turbulenceMultMax, m_turbulence);
			Vec3 &impulse = m_control.impulse;
			impulse += Vec3(0.0f, 0.0f, upPower) * gravity * turbulenceMult * GetDamageMult();
			impulse.z -= m_PhysDyn.v.z * turbulenceMult;
		}
		else
		{
			m_noHoveringTimer -= deltaTime;
		}
	}

	if (m_pStabilizeVTOL)
	{
		float stabilizeTime = m_pStabilizeVTOL->GetFVal();

		if (stabilizeTime > 0.0f)
		{
			if (m_relaxTimer < 6.0f)
			{
				m_relaxTimer += deltaTime;
			}
			else
			{
				float r = currentRoll - relaxRollTolerance;
				r = min(1.0f, max(-1.0f, r));
				m_actionRoll += -r * m_relaxForce * (m_relaxTimer / 6.0f);
			}
		}
	}

	if (m_netActionSync.PublishActions( CNetworkMovementHelicopter(this) ))
	{
		m_pVehicle->GetGameObject()->ChangedNetworkState(eEA_GameClientDynamic);
	}
}
Beispiel #6
0
//------------------------------------------------------------------
void CLam::UpdateTPLaser(float frameTime, CItem* parent)
{
	FUNCTION_PROFILER(GetISystem(), PROFILE_GAME);

	const int frameId = gEnv->pRenderer->GetFrameID();

	if (s_lastUpdateFrameId != frameId)
	{
		// Check how many LAMs to update this frame.
		float dt = frameTime; // + s_laserUpdateTimeError;

		const int n = s_lasers.size();

		int nActive = 0;
		for (int i = 0; i < n; ++i)
		{
			if (!s_lasers[i]->IsLaserActivated() && !s_lasers[i]->IsLightActivated())
				continue;
			nActive++;
		}

		float updatedPerSecond = (nActive / LASER_UPDATE_TIME) + s_laserUpdateTimeError;
		int updateCount = (int)floorf(updatedPerSecond * dt);
		if(dt==0.0f)
			s_laserUpdateTimeError = 0.0f;
		else
			s_laserUpdateTimeError = updatedPerSecond - updateCount/dt;

		s_curLaser %= n;
		for (int i = 0, j = 0; i < n && j < updateCount ; ++i)
		{
			s_curLaser = (s_curLaser + 1) % n;
			if (!s_lasers[s_curLaser]->IsLaserActivated() && !s_lasers[s_curLaser]->IsLightActivated())
				continue;
			s_lasers[s_curLaser]->SetAllowUpdate();
			++j;
		}

		s_lastUpdateFrameId = frameId;
	}

	IEntity* pRootEnt = GetEntity();
	if (!pRootEnt)
		return;

	IEntity *pLaserEntity = m_pEntitySystem->GetEntity(m_pLaserEntityId);
//	if(!pLaserEntity)
//		return;

	const CCamera& camera = gEnv->pRenderer->GetCamera();

	Vec3   lamPos = pRootEnt->GetWorldPos(); //pLaserEntity->GetParent()->GetWorldPos();
	Vec3   dir = pRootEnt->GetWorldRotation().GetColumn1(); //pLaserEntity->GetParent()->GetWorldRotation().GetColumn1();

	bool charNotVisible = false;

	float  dsg1Scale = 1.0f;

	//If character not visible, laser is not correctly updated
	if(parent)
	{
		if(CActor* pOwner = parent->GetOwnerActor())
		{
			ICharacterInstance* pCharacter = pOwner->GetEntity()->GetCharacter(0);
			if(pCharacter && !pCharacter->IsCharacterVisible())
				charNotVisible = true;
		}
		if(parent->GetEntity()->GetClass()==CItem::sDSG1Class)
			dsg1Scale = 3.0f;
	}
 
//	if (!pLaserEntity->GetParent())
//		return;

	Vec3 hitPos(0,0,0);
	float laserLength = 0.0f;

	// HACK??: Use player movement controller locations, or else the laser
	// pops all over the place when character out of the screen.
	CActor *pActor = parent->GetOwnerActor();
	if (pActor && (!pActor->IsPlayer() || charNotVisible))
	{
		if (IMovementController* pMC = pActor->GetMovementController())
		{
			SMovementState state;
			pMC->GetMovementState(state);
			if(!charNotVisible)
				lamPos = state.weaponPosition;
			else
			{
				float oldZPos = lamPos.z;
				lamPos = state.weaponPosition;
				if(m_lastZPos>0.0f)
					lamPos.z = m_lastZPos; //Stabilize somehow z position (even if not accurate)
				else
					lamPos.z = oldZPos;
			}
			const float angleMin = DEG2RAD(3.0f);
			const float angleMax = DEG2RAD(7.0f);
			const float thr = cosf(angleMax);
			float dot = dir.Dot(state.aimDirection);
			if (dot > thr)
			{
				float a = acos_tpl(dot);
				float u = 1.0f - clamp((a - angleMin) / (angleMax - angleMin), 0.0f, 1.0f);
				dir = dir + u * (state.aimDirection - dir);
				dir.Normalize();
			}
		}
	}

	if(!charNotVisible)
		m_lastZPos = lamPos.z;

	lamPos += (dir*0.10f);

	if (m_allowUpdate)
	{
		m_allowUpdate = false;

		IPhysicalEntity* pSkipEntity = NULL;
		if(parent->GetOwner())
			pSkipEntity = parent->GetOwner()->GetPhysics();

		const float range = m_lamparams.laser_range[eIGS_ThirdPerson]*dsg1Scale;

		// Use the same flags as the AI system uses for visbility.
		const int objects = ent_terrain|ent_static|ent_rigid|ent_sleeping_rigid|ent_independent; //ent_living;
		const int flags = (geom_colltype_ray << rwi_colltype_bit) | rwi_colltype_any | (10 & rwi_pierceability_mask) | (geom_colltype14 << rwi_colltype_bit);

		ray_hit hit;
		if (gEnv->pPhysicalWorld->RayWorldIntersection(lamPos, dir*range, objects, flags,
			&hit, 1, &pSkipEntity, pSkipEntity ? 1 : 0))
		{
			laserLength = hit.dist;
			m_lastLaserHitPt = hit.pt;
			m_lastLaserHitSolid = true;
		}
		else
		{
			m_lastLaserHitSolid = false;
			m_lastLaserHitPt = lamPos + dir * range;
			laserLength = range + 0.1f;
		}

		// Hit near plane
		if (dir.Dot(camera.GetViewdir()) < 0.0f)
		{
			Plane nearPlane;
			nearPlane.SetPlane(camera.GetViewdir(), camera.GetPosition());
			nearPlane.d -= camera.GetNearPlane()+0.15f;
			Ray ray(lamPos, dir);
			Vec3 out;
			m_lastLaserHitViewPlane = false;
			if (Intersect::Ray_Plane(ray, nearPlane, out))
			{
				float dist = Distance::Point_Point(lamPos, out);
				if (dist < laserLength)
				{
					laserLength = dist;
					m_lastLaserHitPt = out;
					m_lastLaserHitSolid = true;
					m_lastLaserHitViewPlane = true;
				}
			}
		}

		hitPos = m_lastLaserHitPt;
	}
	else
	{
		laserLength = Distance::Point_Point(m_lastLaserHitPt, lamPos);
		hitPos = lamPos + dir * laserLength;
	}

	if (m_smoothLaserLength < 0.0f)
		m_smoothLaserLength = laserLength;
	else
	{
		if (laserLength < m_smoothLaserLength)
			m_smoothLaserLength = laserLength;
		else
			m_smoothLaserLength += (laserLength - m_smoothLaserLength) * min(1.0f, 10.0f * frameTime);
	}

	float laserAIRange = 0.0f;
	if (m_laserActivated && pLaserEntity)
	{
		// Orient the laser towards the point point.
		Matrix34 parentTMInv;
		parentTMInv = pRootEnt->GetWorldTM().GetInverted();

		Vec3 localDir = parentTMInv.TransformPoint(hitPos);
		float finalLaserLen = localDir.NormalizeSafe();
		Matrix33 rot;
		rot.SetIdentity();
		rot.SetRotationVDir(localDir);
		pLaserEntity->SetLocalTM(rot);

		laserAIRange = finalLaserLen;

		const float assetLength = 2.0f;
		finalLaserLen = CLAMP(finalLaserLen,0.01f,m_lamparams.laser_max_len*dsg1Scale);
		float scale = finalLaserLen / assetLength; 

		// Scale the laser based on the distance.
		if (m_laserEffectSlot >= 0)
		{
			Matrix33 scl;
			scl.SetIdentity();
			scl.SetScale(Vec3(1,scale,1));
			pLaserEntity->SetSlotLocalTM(m_laserEffectSlot, scl);
		}

		if (m_dotEffectSlot >= 0)
		{
			if (m_lastLaserHitSolid)
			{
				Matrix34 mt = Matrix34::CreateTranslationMat(Vec3(0,finalLaserLen,0));
				if(m_lastLaserHitViewPlane)
					mt.Scale(Vec3(0.2f,0.2f,0.2f));
				pLaserEntity->SetSlotLocalTM(m_dotEffectSlot, mt);
			}
			else
			{
				Matrix34 scaleMatrix;
				scaleMatrix.SetIdentity();
				scaleMatrix.SetScale(Vec3(0.001f,0.001f,0.001f));
				pLaserEntity->SetSlotLocalTM(m_dotEffectSlot, scaleMatrix);
			}
		}
	}

	float lightAIRange = 0.0f;
	if (m_lightActivated)
	{
		float range = clamp(m_smoothLaserLength, 0.5f, m_lamparams.light_range[eIGS_ThirdPerson]);
		lightAIRange = range * 1.5f;

		if (m_lightID[eIGS_ThirdPerson] && m_smoothLaserLength > 0.0f)
		{
			CItem* pLightEffect = this;
			if (IItem *pOwnerItem = m_pItemSystem->GetItem(GetParentId()))
				pLightEffect = (CItem *)pOwnerItem;
			pLightEffect->SetLightRadius(range, m_lightID[eIGS_ThirdPerson]);
		}
	}


	if (laserAIRange > 0.0001f || lightAIRange > 0.0001f)
		UpdateAILightAndLaser(lamPos, dir, lightAIRange, m_lamparams.light_fov[eIGS_ThirdPerson], laserAIRange);

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

	float dt = max(deltaTime, 0.005f);

	// It is copyed from CVehicleMoventTank::ProcessAI
	m_movementAction.brake = false;
	m_movementAction.rotateYaw = 0.0f;
	m_movementAction.power = 0.0f;

	float inputSpeed = 0.0f;
	{
		if(m_aiRequest.HasDesiredSpeed())
			inputSpeed = m_aiRequest.GetDesiredSpeed();

		Limit(inputSpeed, -m_maxSpeed, m_maxSpeed);
	}

	Vec3 vMove(ZERO);
	{
		if(m_aiRequest.HasMoveTarget())
			vMove = (m_aiRequest.GetMoveTarget() - m_pEntity->GetWorldPos()).GetNormalizedSafe();
	}

	//start calculation
	if(fabsf(inputSpeed) < 0.0001f)
	{
		m_movementAction.brake = true;

		if(m_PhysDyn.v.GetLength() > 1.0f)
		{
			m_movementAction.power =-1.0f;
		}

	}
	else
	{
		Matrix33 entRotMatInvert(m_PhysPos.q);
		entRotMatInvert.Invert();
		float currentAngleSpeed = RAD2DEG(-m_PhysDyn.w.z);

		const static float maxSteer = RAD2DEG(gf_PI/4.f); // fix maxsteer, shouldn't change
		Vec3 vVel = m_PhysDyn.v;
		Vec3 vVelR = entRotMatInvert * vVel;
		float currentSpeed =vVel.GetLength();
		vVelR.NormalizeSafe();

		if(vVelR.Dot(FORWARD_DIRECTION) < 0)
			currentSpeed *= -1.0f;

		// calculate pedal
		static float accScale = 0.5f;
		m_movementAction.power = (inputSpeed - currentSpeed) * accScale;
		Limit(m_movementAction.power, -1.0f, 1.0f);

		// calculate angles
		Vec3 vMoveR = entRotMatInvert * vMove;
		Vec3 vFwd	= FORWARD_DIRECTION;

		vMoveR.z =0.0f;
		vMoveR.NormalizeSafe();

		if(inputSpeed < 0.0f)	// when going back
		{
			vFwd *= -1.0f;
			vMoveR *= -1.0f;
			currentAngleSpeed *=-1.0f;
		}

		float cosAngle = vFwd.Dot(vMoveR);
		float angle = RAD2DEG(acos_tpl(cosAngle));

		if(vMoveR.Dot(Vec3(1.0f,0.0f,0.0f))< 0)
			angle = -angle;

		//int step =0;
		m_movementAction.rotateYaw = angle * 1.75f/ maxSteer;

		// implementation 1. if there is enough angle speed, we don't need to steer more
		if(fabsf(currentAngleSpeed) > fabsf(angle) && angle*currentAngleSpeed > 0.0f)
		{
			m_movementAction.rotateYaw = m_movementAction.rotateYaw*0.995f; //step =1;
		}

		// implementation 2. if we can guess we reach the distination angle soon, start counter steer.
		float predictDelta = inputSpeed < 0.0f ? 0.1f : 0.1f;
		float dict = angle + predictDelta * (angle - m_prevAngle) / dt ;

		if(dict*currentAngleSpeed<0.0f)
		{
			if(fabsf(angle) < 2.0f)
			{
				m_movementAction.rotateYaw = angle* 1.75f/ maxSteer;// ; step =3;
			}
			else
			{
				m_movementAction.rotateYaw = currentAngleSpeed < 0.0f ? 1.0f : -1.0f;// step =2;
			}
		}

		if(fabsf(angle) > 20.0f && currentSpeed > 3.0f)
		{
			m_movementAction.power = 0.1f ;
			//step =4;
		}

		m_prevAngle =  angle;
		//CryLog("steering	%4.2f	%4.2f %4.2f	%4.2f	%4.2f	%4.2f	%d", deltaTime,inputSpeed - currentSpeed,angle,currentAngleSpeed, m_movementAction.rotateYaw,currentAngleSpeed-m_prevAngle,step);

	}

}
//------------------------------------------------------------------------
void CMelee::Update(float frameTime, uint32 frameId)
{
	FUNCTION_PROFILER( GetISystem(), PROFILE_GAME );

	bool remote = false;
	bool doMelee = false;
	bool requireUpdate = false;

	Vec3 dirToTarget(ZERO);
	if(m_pMeleeAction && s_meleeSnapTargetId && g_pGameCVars->pl_melee.mp_melee_system_camera_lock_and_turn)
	{
		m_attackTime += frameTime;

		CActor* pOwner = m_pWeapon->GetOwnerActor();
		IEntity* pTarget = gEnv->pEntitySystem->GetEntity(s_meleeSnapTargetId);
		if(pOwner && pTarget)
		{
			Vec3 targetPos = pTarget->GetWorldPos();

			if(s_bMeleeSnapTargetCrouched)
			{
				targetPos.z -= g_pGameCVars->pl_melee.mp_melee_system_camera_lock_crouch_height_offset;
			}

			dirToTarget = targetPos - pOwner->GetEntity()->GetWorldPos();
			dirToTarget.Normalize();

			static const float smooth_time = 0.1f;
			SmoothCD(m_attackTurnAmount, m_attackTurnAmountSmoothRate, frameTime, 1.f, smooth_time);
			Quat newViewRotation;
			newViewRotation.SetSlerp(pOwner->GetViewRotation(), Quat::CreateRotationVDir(dirToTarget), m_attackTurnAmount);
			Ang3 newAngles(newViewRotation);
			newAngles.y = 0.f; //No head tilting
			newViewRotation = Quat(newAngles);
			pOwner->SetViewRotation( newViewRotation );
		}

		if(m_attackTime >= g_pGameCVars->pl_melee.mp_melee_system_camera_lock_time && pOwner && pOwner->IsClient())
		{
			pOwner->GetActorParams().viewLimits.ClearViewLimit(SViewLimitParams::eVLS_Item);
		}
	}

	if (m_attacking)
	{
		MeleeDebugLog ("CMelee<%p> Update while attacking: m_attacked=%d, delay=%f", this, m_attacked, m_delayTimer);

		requireUpdate = true;
		if (m_delayTimer>0.0f)
		{
			RequestAlignmentToNearestTarget();
			m_delayTimer-=frameTime;
			if (m_delayTimer<=0.0f)
			{
				m_delayTimer=0.0f;
			}
		}
		else if (m_netAttacking)
		{
			remote = true;
			doMelee = true;
			m_attacking = false;
			m_slideKick = false;
			m_netAttacking = false;

			m_pWeapon->SetBusy(false);
		}	
		else if (!m_attacked)
		{
			doMelee = true;
			m_attacked = true;
		}

		if ( !m_collisionHelper.IsBlocked() && doMelee)
		{
			if (CActor *pActor = m_pWeapon->GetOwnerActor())
			{
				if (IMovementController * pMC = pActor->GetMovementController())
				{
					SMovementState info;
					pMC->GetMovementState(info);

					if(!dirToTarget.IsZeroFast())
					{
						PerformMelee(info.weaponPosition, dirToTarget, remote); //We know where we will be facing at the point of impact - using our current fire direction is not accurate enough
					}
					else
					{
						PerformMelee(info.weaponPosition, info.fireDirection, remote);
					}
				}
			}
		}

		if( (m_useMeleeWeaponDelay <= 0.0f && m_useMeleeWeaponDelay > -1.0f) )
		{
			m_useMeleeWeaponDelay = -1.0f;

			// Switch to the MELEE WEAPON.
			SwitchToMeleeWeaponAndAttack();

			m_attacking = false;
		}
		m_useMeleeWeaponDelay -= frameTime;
	}

	if (requireUpdate)
		m_pWeapon->RequireUpdate(eIUS_FireMode);
}
Beispiel #9
0
CGame::CGame()
	: m_pGameFramework(nullptr)
{
	GetISystem()->SetIGame(this);
}
//------------------------------------------------------------------------
void CVehicleMovementStdBoat::UpdateSurfaceEffects(const float deltaTime)
{
	FUNCTION_PROFILER(GetISystem(), PROFILE_GAME);

	if(0 == g_pGameCVars->v_pa_surface)
	{
		ResetParticles();
		return;
	}

	IEntity *pEntity = m_pVehicle->GetEntity();
	const Matrix34 &worldTM = pEntity->GetWorldTM();

	float distSq = worldTM.GetTranslation().GetSquaredDistance(gEnv->pRenderer->GetCamera().GetPosition());

	if(distSq > sqr(300.f) || (distSq > sqr(50.f) && !m_pVehicle->GetGameObject()->IsProbablyVisible()))
		return;

	Matrix34 worldTMInv = worldTM.GetInverted();
	const SVehicleStatus &status = m_pVehicle->GetStatus();
	float velDot = status.vel * worldTM.GetColumn1();
	float powerNorm = min(abs(m_movementAction.power), 1.f);

	SEnvironmentParticles *envParams = m_pPaParams->GetEnvironmentParticles();

	SEnvParticleStatus::TEnvEmitters::iterator end = m_paStats.envStats.emitters.end();

	for(SEnvParticleStatus::TEnvEmitters::iterator emitterIt = m_paStats.envStats.emitters.begin(); emitterIt!=end; ++emitterIt)
	{
		if(emitterIt->layer < 0)
		{
			assert(0);
			continue;
		}

		const SEnvironmentLayer &layer = envParams->GetLayer(emitterIt->layer);

		SEntitySlotInfo info;
		info.pParticleEmitter = 0;
		pEntity->GetSlotInfo(emitterIt->slot, info);

		float countScale = 1.f;
		float sizeScale = 1.f;
		float speedScale = 1.f;
		float speed = 0.f;

		// check if helper position is beneath water level

		Vec3 emitterWorldPos = worldTM * emitterIt->quatT.t;
		float waterLevel = gEnv->p3DEngine->GetWaterLevel(&emitterWorldPos);
		int matId = 0;

		if(emitterWorldPos.z <= waterLevel+0.1f && m_statusDyn.submergedFraction<0.999f)
		{
			matId = gEnv->pPhysicalWorld->GetWaterMat();
			speed = status.speed;

			bool spray = !strcmp(layer.GetName(), "spray");

			if(spray)
			{
				// slip based
				speed -= abs(velDot);
			}

			GetParticleScale(layer, speed, powerNorm, countScale, sizeScale, speedScale);
		}
		else
		{
			countScale = 0.f;
		}

		if(matId && matId != emitterIt->matId)
		{
			// change effect
			IParticleEffect *pEff = 0;
			const char *effect = GetEffectByIndex(matId, layer.GetName());

			if(effect && (pEff = gEnv->pParticleManager->FindEffect(effect)))
			{
#if ENABLE_VEHICLE_DEBUG

				if(DebugParticles())
					CryLog("%s changes water sfx to %s (slot %i)", pEntity->GetName(), effect, emitterIt->slot);

#endif

				if(info.pParticleEmitter)
				{
					info.pParticleEmitter->Activate(false);
					pEntity->FreeSlot(emitterIt->slot);
				}

				emitterIt->slot = pEntity->LoadParticleEmitter(emitterIt->slot, pEff);

				if(emitterIt->slot != -1)
					pEntity->SetSlotLocalTM(emitterIt->slot, Matrix34(emitterIt->quatT));

				info.pParticleEmitter = 0;
				pEntity->GetSlotInfo(emitterIt->slot, info);
			}
			else
				countScale = 0.f;
		}

		if(matId)
			emitterIt->matId = matId;

		if(info.pParticleEmitter)
		{
			SpawnParams sp;
			sp.fSizeScale = sizeScale;
			sp.fCountScale = countScale;
			sp.fSpeedScale = speedScale;
			info.pParticleEmitter->SetSpawnParams(sp);

			if(layer.alignToWater && countScale > 0.f)
			{
				Vec3 worldPos(emitterWorldPos.x, emitterWorldPos.y, waterLevel+0.05f);

				Matrix34 localTM(emitterIt->quatT);
				localTM.SetTranslation(worldTMInv * worldPos);
				pEntity->SetSlotLocalTM(emitterIt->slot, localTM);
			}
		}

#if ENABLE_VEHICLE_DEBUG

		if(DebugParticles() && m_pVehicle->IsPlayerDriving())
		{
			float color[] = {1,1,1,1};
			ColorB red(255,0,0,255);
			IRenderAuxGeom *pAuxGeom = gEnv->pRenderer->GetIRenderAuxGeom();

			const char *effect = info.pParticleEmitter ? info.pParticleEmitter->GetName() : "";
			const Matrix34 &slotTM = m_pEntity->GetSlotWorldTM(emitterIt->slot);
			Vec3 ppos = slotTM.GetTranslation();

			pAuxGeom->DrawSphere(ppos, 0.2f, red);
			pAuxGeom->DrawCone(ppos, slotTM.GetColumn1(), 0.1f, 0.5f, red);
			gEnv->pRenderer->Draw2dLabel(50.f, (float)(400+10*emitterIt->slot), 1.2f, color, false, "<%s> water fx: slot %i [%s], speed %.1f, sizeScale %.2f, countScale %.2f (pos %.0f,%0.f,%0.f)", pEntity->GetName(), emitterIt->slot, effect, speed, sizeScale, countScale, ppos.x, ppos.y, ppos.z);
		}

#endif
	}

	// generate water splashes
	Vec3 wakePos;

	if(m_pSplashPos)
	{
		wakePos = m_pSplashPos->GetWorldSpaceTranslation();
	}
	else
	{
		wakePos = worldTM.GetTranslation();
	}

	float wakeWaterLevel = gEnv->p3DEngine->GetWaterLevel(&wakePos);

	Vec3 localW = worldTMInv.TransformVector(m_statusDyn.w);

	if(localW.x >= 0.f)
		m_diving = false;

	if(!m_diving && localW.x < -0.03f && status.speed > 10.f && wakePos.z < m_lastWakePos.z && wakeWaterLevel+0.1f >= wakePos.z)
	{
		float speedRatio = min(1.f, status.speed/m_maxSpeed);
		m_diving = true;

		if(m_pWaveEffect)
		{
			if(IParticleEmitter *pEmitter = pEntity->GetParticleEmitter(m_wakeSlot))
			{
				pEmitter->Activate(false);
				pEntity->FreeSlot(m_wakeSlot);
				m_wakeSlot = -1;
			}

			SpawnParams spawnParams;
			spawnParams.fSizeScale = spawnParams.fCountScale = 0.5f + 0.25f*speedRatio;
			spawnParams.fSizeScale  += 0.4f*m_waveRandomMult;
			spawnParams.fCountScale += 0.4f*Random();

			m_wakeSlot = pEntity->LoadParticleEmitter(m_wakeSlot, m_pWaveEffect, &spawnParams);
		}

		// handle splash sound
		PlaySound(eSID_Splash, 0.f, Vec3(0,5,1));
		SetSoundParam(eSID_Splash, "intensity", 0.2f*speedRatio + 0.5f*m_waveRandomMult);

		if(m_rpmPitchDir == 0)
		{
			m_rpmPitchDir = -1;
			m_waveSoundPitch = 0.f;
			m_waveSoundAmount = 0.02f + m_waveRandomMult*0.08f;
		}
	}

	if(m_wakeSlot != -1)
	{
		// update emitter local pos to short above waterlevel
		Matrix34 tm;

		if(m_pSplashPos)
			m_pSplashPos->GetVehicleTM(tm);
		else
			tm.SetIdentity();

		Vec3 pos = tm.GetTranslation();
		pos.z = worldTMInv.TransformPoint(Vec3(wakePos.x,wakePos.y,wakeWaterLevel)).z + 0.2f;
		tm.SetTranslation(pos);
		pEntity->SetSlotLocalTM(m_wakeSlot, tm);

#if ENABLE_VEHICLE_DEBUG

		if(IsProfilingMovement())
		{
			Vec3 wPos = worldTM * tm.GetTranslation();
			ColorB col(128, 128, 0, 200);
			gEnv->pRenderer->GetIRenderAuxGeom()->DrawSphere(wPos, 0.4f, col);
			gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine(wPos, col, wPos+Vec3(0,0,1.5f), col);
		}

#endif
	}

	m_lastWakePos = wakePos;
}
//------------------------------------------------------------------------
void CVehicleMovementVTOL::Update(const float deltaTime)
{
	FUNCTION_PROFILER(GetISystem(), PROFILE_GAME);

	CVehicleMovementHelicopter::Update(deltaTime);
	CryAutoCriticalSection lk(m_lock);

	if(m_pWingsAnimation)
	{
		m_pWingsAnimation->SetTime(m_wingsAnimTime);
	}

	IActorSystem *pActorSystem = g_pGame->GetIGameFramework()->GetIActorSystem();
	assert(pActorSystem);

	IActor *pActor = pActorSystem->GetActor(m_actorId);

	if(pActor && pActor->IsClient())
	{
		float turbulence = m_turbulence;

		if(m_pAltitudeLimitVar)
		{
			float altitudeLimit = m_pAltitudeLimitVar->GetFVal();
			float currentHeight = m_pEntity->GetWorldPos().z;

			if(!iszero(altitudeLimit))
			{
				float altitudeLowerOffset;

				if(m_pAltitudeLimitLowerOffsetVar)
				{
					float r = 1.0f - min(1.0f, max(0.0f, m_pAltitudeLimitLowerOffsetVar->GetFVal()));
					altitudeLowerOffset = r * altitudeLimit;

					if(currentHeight >= altitudeLowerOffset)
					{
						if(currentHeight > altitudeLowerOffset)
						{
							float zone = altitudeLimit - altitudeLowerOffset;
							turbulence += (currentHeight - altitudeLowerOffset) / (zone);
						}
					}
				}
			}
		}

		if(turbulence > 0.0f)
		{
			static_cast<CActor *>(pActor)->CameraShake(0.50f * turbulence, 0.0f, 0.05f, 0.04f, Vec3(0.0f, 0.0f, 0.0f), 10, "VTOL_Update_Turbulence");
		}

		float enginePowerRatio = m_enginePower / m_enginePowerMax;

		if(enginePowerRatio > 0.0f)
		{
			float rpmScaleDesired = 0.2f;
			rpmScaleDesired += abs(m_forwardAction) * 0.8f;
			rpmScaleDesired += abs(m_strafeAction) * 0.4f;
			rpmScaleDesired += abs(m_turnAction) * 0.25f;
			rpmScaleDesired = min(1.0f, rpmScaleDesired);
			Interpolate(m_rpmScale, rpmScaleDesired, 1.0f, deltaTime);
		}

		float turnParamGoal = min(1.0f, abs(m_turnAction)) * 0.6f;
		turnParamGoal *= (min(1.0f, max(0.0f, m_speedRatio)) + 1.0f) * 0.50f;
		turnParamGoal += turnParamGoal * m_boost * 0.25f;
		Interpolate(m_soundParamTurn, turnParamGoal, 0.5f, deltaTime);
		SetSoundParam(eSID_Run, "turn", m_soundParamTurn);

		float damage = GetSoundDamage();

		if(damage > 0.1f)
		{
			//if (ISound* pSound = GetOrPlaySound(eSID_Damage, 5.f, m_enginePos))
			//SetSoundParam(pSound, "damage", damage);
		}
	}
}
bool CScriptSurfaceType::Load( int nId )
{
	m_nId = nId;
	IScriptSystem *pScriptSystem = gEnv->pScriptSystem;

	SmartScriptTable mtlTable;

	if (!pScriptSystem->GetGlobalValue("Materials", mtlTable))
	{
		return false;
	}

	//////////////////////////////////////////////////////////////////////////
	if (!pScriptSystem->ExecuteFile( m_script,true ))
	{
		GetISystem()->Warning(
			VALIDATOR_MODULE_3DENGINE,VALIDATOR_WARNING,
			VALIDATOR_FLAG_FILE|VALIDATOR_FLAG_SCRIPT,
			m_script.c_str(),
			"'%s' failed to load surface type definition script",m_name.c_str() );
		return false;
	}

	if (!mtlTable->GetValue( m_name,m_pScriptTable ))
		return false;

	XmlNodeRef matNode = m_root->newChild("SurfaceType");
	matNode->setAttr( "name",m_name );

	// Load physics params.
	SmartScriptTable pPhysicsTable,props;
	float fBouncyness = 0.0f;
	float fFriction = 1.0f;
	int		iPiercingResistence = sf_max_pierceable;	// physics traces range 0-15
	int   imatBreakable = -1, bManuallyBreakable=0;
	m_iBreakability=0; m_nHitpoints=0; m_breakEnergy=0;
	if (m_pScriptTable->GetValue("physics",pPhysicsTable))
	{
		pPhysicsTable->GetValue("friction",fFriction);
		pPhysicsTable->GetValue("bouncyness",fBouncyness);
		pPhysicsTable->GetValue("breakable_id",imatBreakable);
		if (pPhysicsTable->GetValue("pierceability",iPiercingResistence))
		{
			if(iPiercingResistence>sf_max_pierceable)
				iPiercingResistence = sf_max_pierceable;
		}
		int nBreakable2d = 0;
		int bNoCollide = 0;
		pPhysicsTable->GetValue("no_collide", bNoCollide);
		if (pPhysicsTable->GetValue("break_energy",m_breakEnergy))
		{
			bManuallyBreakable = sf_manually_breakable;
			m_iBreakability = 2;
			pPhysicsTable->GetValue("hit_points",m_nHitpoints);
		} else if (m_pScriptTable->GetValue("breakable_2d",props))
		{
			nBreakable2d = 1;
			bManuallyBreakable = sf_manually_breakable;
			m_iBreakability = 1;
			props->GetValue("break_energy",m_breakEnergy);
			props->GetValue("hit_points",m_nHitpoints);
		}

		m_nFlags &= ~SURFACE_TYPE_NO_COLLIDE;
		if (bNoCollide)
			m_nFlags |= SURFACE_TYPE_NO_COLLIDE;

		XmlNodeRef physNode = matNode->newChild("Physics");
		physNode->setAttr( "friction",fFriction );
		physNode->setAttr( "elasticity",fBouncyness );
		physNode->setAttr( "breakable_id",imatBreakable );
		physNode->setAttr( "pierceability",iPiercingResistence );
		physNode->setAttr( "no_collide",bNoCollide );
		physNode->setAttr( "break_energy",m_breakEnergy );
		physNode->setAttr( "hit_points",m_nHitpoints );
		physNode->setAttr( "breakable_2d",nBreakable2d );
	}

	SmartScriptTable pAITable;
	if (m_pScriptTable->GetValue("AI",pAITable))
	{
		XmlNodeRef aiNode = matNode->newChild("AI");
		float fImpactRadius = 1;
		float fFootStepRadius = 1;
		float proneMult = 1;
		float crouchMult = 1;
		float movingMult = 1;
		pAITable->GetValue( "fImpactRadius",fImpactRadius );
		pAITable->GetValue( "fFootStepRadius",fFootStepRadius );
		pAITable->GetValue( "proneMult",proneMult );
		pAITable->GetValue( "crouchMult",crouchMult );
		pAITable->GetValue( "movingMult",movingMult );

		aiNode->setAttr( "fImpactRadius",fImpactRadius );
		aiNode->setAttr( "fFootStepRadius",fFootStepRadius );
		aiNode->setAttr( "proneMult",proneMult );
		aiNode->setAttr( "crouchMult",crouchMult );
		aiNode->setAttr( "movingMult",movingMult );
	}
	gEnv->pPhysicalWorld->SetSurfaceParameters(m_nId,fBouncyness,fFriction,
		(uint32)(sf_pierceability(iPiercingResistence) | sf_matbreakable(imatBreakable) | bManuallyBreakable));


	return true;
}
bool CScriptSurfaceTypesLoader::LoadSurfaceTypes( const char *sFolder,bool bReload )
{
	{
		if (!gEnv->p3DEngine)
			return false;

		I3DEngine *pEngine = gEnv->p3DEngine;
		ISurfaceTypeEnumerator *pEnum = pEngine->GetMaterialManager()->GetSurfaceTypeManager()->GetEnumerator();
		if (pEnum)
		{
			for (ISurfaceType *pSurfaceType = pEnum->GetFirst(); pSurfaceType; pSurfaceType = pEnum->GetNext())
			{
				SmartScriptTable mtlTable(gEnv->pScriptSystem);
				gEnv->pScriptSystem->SetGlobalValue( pSurfaceType->GetName(),mtlTable );

				SmartScriptTable aiTable(gEnv->pScriptSystem);
				mtlTable->SetValue("AI",aiTable);
				aiTable->SetValue( "fImpactRadius",5.0f );
				aiTable->SetValue( "fFootStepRadius",15.0f );
				aiTable->SetValue( "proneMult",0.2f );
				aiTable->SetValue( "crouchMult",0.5f );
				aiTable->SetValue( "movingMult",2.5f );
			}

			pEnum->Release();
		}
	}

	return true; // Do not load surface types from script anymore.

	m_root = GetISystem()->CreateXmlNode("SurfaceTypes");

	IScriptSystem *pScriptSystem = gEnv->pScriptSystem;
	//////////////////////////////////////////////////////////////////////////
	// Make sure Materials table exist.
	//////////////////////////////////////////////////////////////////////////
	SmartScriptTable mtlTable;

	if (!pScriptSystem->GetGlobalValue("Materials", mtlTable) || bReload)
	{
		mtlTable = pScriptSystem->CreateTable();
		pScriptSystem->SetGlobalValue("Materials", mtlTable);
	}

	ICryPak *pIPak = gEnv->pCryPak;

	ISurfaceTypeManager *pSurfaceManager = gEnv->p3DEngine->GetMaterialManager()->GetSurfaceTypeManager();

	if (!bReload)
		stl::push_back_unique( m_folders,sFolder );

	string searchFolder = string(sFolder) + "/";;
	string searchFilter = searchFolder + "mat_*.lua";

	gEnv->pScriptSystem->ExecuteFile(searchFolder+"common.lua", false, bReload);

	_finddata_t fd;
	intptr_t fhandle;
	fhandle = pIPak->FindFirst( searchFilter,&fd );
	if (fhandle != -1)
	{
		do {
			// Skip back folders.
			if (fd.attrib & _A_SUBDIR) // skip if directory.
				continue;

			char name[_MAX_PATH];
			_splitpath( fd.name,NULL,NULL,name,NULL );

			if (strlen(name) == 0)
				continue;

			if (bReload)
			{
				ISurfaceType *pSurfaceType = pSurfaceManager->GetSurfaceTypeByName(name);
				if (pSurfaceType)
				{
					pSurfaceType->Load( pSurfaceType->GetId() );
					continue;
				}
			}

			ISurfaceType *pSurfaceType = new CScriptSurfaceType( this,name,searchFolder+fd.name,0 );
			if (pSurfaceManager->RegisterSurfaceType( pSurfaceType ))
				m_surfaceTypes.push_back(pSurfaceType);
			else
				pSurfaceType->Release();
		} while (pIPak->FindNext( fhandle,&fd ) == 0);
		pIPak->FindClose(fhandle);
	}

	if (m_root)
	{
		m_root->saveToFile( "SurfaceTypes.xml" );
	}

	return true;
}
Beispiel #14
0
void CPlayerRotation::TargetAimAssistance(CWeapon* pWeapon, float& followH, float& followV, float& scale, float& _fZoomAmount, const Vec3 playerView[4])
{
	FUNCTION_PROFILER(GetISystem(), PROFILE_GAME);

	CRY_ASSERT(m_player.IsClient());

	followH = 0.0f;
	followV = 0.0f;
	scale = 1.0f;
	float bestScale = 1.0f;

	const Vec3 playerFwd = playerView[1];
	const Vec3 playerRgt = playerView[0];
	const Vec3 playerUp = playerView[2];
	const Vec3 playerPos = playerView[3];

	Vec3 follow_target_pos(ZERO);
	float follow_vote_leader = 0.0f;
	float snap_vote_leader = 0.0f;
	Vec3 follow_target_dir(ZERO);
	Vec3 snap_target_dir(ZERO);
	EntityId follow_target_id = 0;
	EntityId snap_target_id = 0;

	CGameRules * pGameRules = g_pGame->GetGameRules();
	float distance_follow_threshold_near	= max(0.0f, g_pGameCVars->aim_assistMinDistance);
	float distance_follow_threshold_far		= max(20.0f, g_pGameCVars->aim_assistMaxDistance);
	int playerTeam = pGameRules->GetTeam(m_player.GetEntity()->GetId());
	float cloakedPlayerMultiplier = g_pGameCVars->pl_aim_cloaked_multiplier;
	const bool multipleTeams = pGameRules->GetTeamCount() > 0;
	const float fFollowFalloffDist = g_pGameCVars->aim_assistFalloffDistance + FLT_EPSILON*g_pGameCVars->aim_assistFalloffDistance;
	const bool playerIsScoped = m_player.GetActorStats()->isScoped;

	float minTurnScale, fAimAssistStrength, fMaxDistMult;

	if(pWeapon)
	{
		const float fZoomAmount = pWeapon->GetZoomTransition();
		_fZoomAmount = fZoomAmount;
		
		const float fStrength						= g_pGameCVars->aim_assistStrength;
		const float fStrengthIronSight              = playerIsScoped ? g_pGameCVars->aim_assistStrength_SniperScope : g_pGameCVars->aim_assistStrength_IronSight;
		const float fDiff								= fStrengthIronSight - fStrength;
		fAimAssistStrength							= fStrength + (fZoomAmount * fDiff);
		
		const float fMinTurn						= g_pGameCVars->aim_assistMinTurnScale;
		const float fMinTurnIronSight               = playerIsScoped ? g_pGameCVars->aim_assistMinTurnScale_SniperScope : g_pGameCVars->aim_assistMinTurnScale_IronSight;
		const float fMinTurnDiff				= fMinTurnIronSight - fMinTurn;
		minTurnScale										= fMinTurn + (fZoomAmount * fMinTurnDiff);

		const float fMaxAssistDist			= g_pGameCVars->aim_assistMaxDistance;
		const float fMaxAssistDist_Iron             = playerIsScoped ? g_pGameCVars->aim_assistMaxDistance_SniperScope : g_pGameCVars->aim_assistMaxDistance_IronSight;
		const float fMaxAssistDistDiff	= (fMaxAssistDist_Iron - fMaxAssistDist) * fZoomAmount;
		fMaxDistMult                                = (fMaxAssistDist + fMaxAssistDistDiff) * __fres(fMaxAssistDist);
	}
	else
	{
		_fZoomAmount = 0.0f;
		fMaxDistMult = 1.0f;
		fAimAssistStrength = g_pGameCVars->aim_assistStrength;
		minTurnScale = g_pGameCVars->aim_assistMinTurnScale;
	}

	const float falloffStartDistance = g_pGameCVars->aim_assistSlowFalloffStartDistance;
	const float falloffPerMeter = 1.0f / (g_pGameCVars->aim_assistSlowDisableDistance - falloffStartDistance);

	const TAutoaimTargets& aaTargets = g_pGame->GetAutoAimManager().GetAutoAimTargets();
	const int targetCount = aaTargets.size();
	float fBestTargetDistance = FLT_MAX;

#if DBG_AUTO_AIM
	SAuxGeomRenderFlags oldFlags = gEnv->pRenderer->GetIRenderAuxGeom()->GetRenderFlags();
	SAuxGeomRenderFlags newFlags = e_Def3DPublicRenderflags;
	newFlags.SetAlphaBlendMode(e_AlphaBlended);
	newFlags.SetDepthTestFlag(e_DepthTestOff);
	newFlags.SetCullMode(e_CullModeNone); 
	gEnv->pRenderer->GetIRenderAuxGeom()->SetRenderFlags(newFlags);
#endif

	for (int i = 0; i < targetCount; ++i)
	{
		const SAutoaimTarget& target = aaTargets[i];

		CRY_ASSERT(target.entityId != m_player.GetEntityId());

		//Skip friendly ai
		if(gEnv->bMultiplayer)
		{
			if(multipleTeams &&  (pGameRules->GetTeam(target.entityId) == playerTeam))
			{
				continue;
			}

		}
		else 
		{		
			if (target.HasFlagSet(eAATF_AIHostile) == false)
				continue;

			distance_follow_threshold_far = fMaxDistMult * (target.HasFlagSet(eAATF_AIRadarTagged) ? g_pGameCVars->aim_assistMaxDistanceTagged : g_pGameCVars->aim_assistMaxDistance);
		}
		
		Vec3 targetPos = target.primaryAimPosition;
		Vec3 targetDistVec = (targetPos - playerPos);
		float distance = targetDistVec.GetLength();
		
		if (distance <= 0.1f)
			continue;

		Vec3 dirToTarget = targetDistVec / distance;

		// fast reject everything behind player, too far away or too near from line of view
		// sort rest by angle to crosshair and distance from player
		float alignment = playerFwd * dirToTarget;
		if (alignment <= 0.0f)
			continue;

		if ((distance < distance_follow_threshold_near) || (distance > distance_follow_threshold_far))
			continue;

		const int kAutoaimVisibilityLatency = 2;
		CPlayerVisTable::SVisibilityParams visParams(target.entityId);
		visParams.queryParams = eVQP_IgnoreGlass;
		if (!g_pGame->GetPlayerVisTable()->CanLocalPlayerSee(visParams, kAutoaimVisibilityLatency))
		{
			// Since both player and target entities are ignored, and the ray still intersected something, there's something in the way.
			// Need to profile this and see if it's faster to do the below checks before doing the linetest. It's fairly expensive but
			// linetests generally are as well... - Richard
			continue;
		}

#if DBG_AUTO_AIM
		const ColorB green(0,255,0,255);
		const ColorB darkgreen(0,155,0,225);
		gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine( playerPos, darkgreen, targetPos, green);
#endif

		const float angleDot = dirToTarget.dot(-playerRgt);
		const float angle = (RAD2DEG(cry_acosf(angleDot)) - 90.f);
		const float absAngle = fabsf(angle);

		const float angleDotV = playerUp.dot(dirToTarget);
		const float angleToTargetV = (RAD2DEG(cry_acosf(angleDotV)) - 90.f);
		const float absAngleV = fabsf(angleToTargetV);

		const float slowModifiedDistance = distance * g_pGameCVars->aim_assistSlowDistanceModifier;
		const float radius_slow_threshold_inner = 0.5f;
		const float radius_slow_threshold_outer = g_pGameCVars->aim_assistSlowThresholdOuter;
		const float angle_slow_threshold_inner = RAD2DEG(cry_atanf(radius_slow_threshold_inner / slowModifiedDistance));
		const float angle_slow_threshold_outer = RAD2DEG(cry_atanf(radius_slow_threshold_outer / slowModifiedDistance));
		float angle_slow_fractionH = clamp((absAngle - angle_slow_threshold_inner) / (angle_slow_threshold_outer - angle_slow_threshold_inner), 0.0f, 1.0f);
		float angle_slow_fractionV = clamp((absAngleV - angle_slow_threshold_inner) / (angle_slow_threshold_outer - angle_slow_threshold_inner), 0.0f, 1.0f);

		float angle_slow_fraction = max(angle_slow_fractionH, angle_slow_fractionV);

		const float distance_follow_fraction = clamp((distance - fFollowFalloffDist) / (distance_follow_threshold_far - fFollowFalloffDist), 0.0f, 1.0f);
		const float radius_follow_threshold_inner = target.innerRadius;
		const float radius_follow_threshold_outer = target.outerRadius;
		const float radius_snap = target.HasFlagSet(eAATF_AIRadarTagged) ?	target.snapRadiusTagged * g_pGameCVars->aim_assistSnapRadiusTaggedScale : 
																			target.snapRadius * g_pGameCVars->aim_assistSnapRadiusScale;
		const float angle_follow_threshold_inner = RAD2DEG(cry_atanf(radius_follow_threshold_inner / distance));
		const float angle_follow_threshold_outer = RAD2DEG(cry_atanf(radius_follow_threshold_outer / distance));
		const float angle_follow_fraction = clamp((absAngle - angle_follow_threshold_inner) / (angle_follow_threshold_outer - angle_follow_threshold_inner), 0.0f, 1.0f);
		const float angle_follow_fractionV = clamp((absAngleV - angle_follow_threshold_inner) / (angle_follow_threshold_outer - angle_follow_threshold_inner), 0.0f, 1.0f);
		const float worst_follow_fraction = (float)__fsel(angle_follow_fraction - angle_follow_fractionV, angle_follow_fraction, angle_follow_fractionV);
		float follow_fraction = ((1.0f - worst_follow_fraction) * (1.0f - distance_follow_fraction));
		float follow_vote = follow_fraction;

		//clamp the lower bound of the distance_slow_modifier so it can't be lower than the angle slow fraction
		//  which prevents close but off-centre targets slowing us too much
		const float distance_slow_modifier = clamp( 1.0f - ((distance - falloffStartDistance) * falloffPerMeter), angle_slow_fraction, 1.0f);


		const float fCombinedModifier = angle_slow_fraction * distance_slow_modifier;
		fBestTargetDistance = (float)__fsel(fCombinedModifier - bestScale, fBestTargetDistance, distance);
		bestScale = min(fCombinedModifier, bestScale);		

		if (follow_vote > follow_vote_leader)
		{
			follow_vote_leader = follow_vote;

			//m_follow_target_id only gets set after the loop -> this won't get hit when a target is selected
			// as a follow target for the first time. This doesn't need to be in the loop.
			if ( m_follow_target_id == target.entityId)
			{
				const Vec3 follow_target_dir_local = m_follow_target_dir;
				Vec3 target_rgt = playerRgt;
				Vec3 target_up = target_rgt.cross(follow_target_dir_local);
				target_rgt = follow_target_dir_local.cross(target_up);
				target_rgt.Normalize();
				target_up.Normalize();
				
				float alignH = dirToTarget * -target_rgt;
				float alignV = dirToTarget.z - follow_target_dir_local.z;
				float angleH = min(fabsf(alignH * fAimAssistStrength), fabsf(angleDot));
				float angleV = min(fabsf(alignV * fAimAssistStrength), fabsf(angleDotV));

				followH = follow_fraction * (float)__fsel(angleDot, angleH, -angleH);
				followV = follow_fraction * (float)__fsel(angleDotV, angleV, -angleV);	
								
				follow_vote_leader += 0.05f; // anti oscillation between different targets
				follow_target_pos = targetPos;
			}

			follow_target_id = target.entityId;
			snap_target_id = target.entityId;
			follow_target_dir = dirToTarget;
			snap_target_dir = PickBestSnapDirection(playerPos, playerFwd, target);

		}
		else if (!follow_target_id && (radius_snap > 0.0f))
		{
			Lineseg lineSegment;
			lineSegment.start = playerPos;
			lineSegment.end = playerPos + (playerFwd * (distance + radius_snap));
			Sphere sphere;
			sphere.center = targetPos;
			sphere.radius = radius_snap;
			Vec3 intersectionPoint;

			if (Intersect::Lineseg_SphereFirst(lineSegment, sphere, intersectionPoint))
			{
				float t = 0.0f;
				const float snap_fraction = 1.0f - (Distance::Point_Lineseg(targetPos, lineSegment, t) * (float)__fres(radius_snap));

				if (snap_fraction > snap_vote_leader)
				{
					snap_vote_leader = snap_fraction;
					snap_target_id = target.entityId;
					snap_target_dir = PickBestSnapDirection(playerPos, playerFwd, target);
				}
			}
		}
	}

#if DBG_AUTO_AIM
	if ((!follow_target_pos.IsZeroFast()) && (g_pGameCVars->pl_targeting_debug != 0))
	{
		float radius_inner = 0.30f;
		float radius_outer = 0.33f;
		ColorB colorInner(255,255,0,0x40);
		ColorB colorOuter(255,255,0,0x40);
		DrawDisc(follow_target_pos, follow_target_dir, radius_inner, radius_outer, colorInner, colorOuter);
	}

	gEnv->pRenderer->GetIRenderAuxGeom()->SetRenderFlags(oldFlags);
#endif

	m_follow_target_id  = follow_target_id;
	m_follow_target_dir = follow_target_dir;

	//IMPORTANT: Apply the minimum-distance scaling of the slowdown _after_ calculating the slowdown for the best target
	//						as we want to help the player aim at the nearest target, and modifying the slowdown multiplier prior to this
	//						could result in a different target being selected

	const float fSlowDownProximityFadeInBand = (g_pGameCVars->aim_assistSlowStopFadeinDistance - g_pGameCVars->aim_assistSlowStartFadeinDistance) + FLT_EPSILON;
	float fSlowDownProximityScale = (fBestTargetDistance - g_pGameCVars->aim_assistSlowStartFadeinDistance) / fSlowDownProximityFadeInBand; 
	Limit(fSlowDownProximityScale, 0.0f, 1.0f);
	float fInvBestScale = (1.0f - bestScale) * fSlowDownProximityScale;
	bestScale = 1.0f - fInvBestScale;

	scale = minTurnScale + ((1.0f - minTurnScale) * bestScale);

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

	static const float fWaterLevelMaxDiff = 0.15f; // max allowed height difference between propeller center and water level
	static const float fSubmergedMin = 0.01f;
	static const float fMinSpeedForTurn = 0.5f; // min speed so that turning becomes possible

	if(m_bNetSync)
		m_netActionSync.UpdateObject(this);

	CryAutoCriticalSection lk(m_lock);

	CVehicleMovementBase::ProcessMovement(deltaTime);

	IEntity *pEntity = m_pVehicle->GetEntity();
	IPhysicalEntity *pPhysics = pEntity->GetPhysics();
	assert(pPhysics);

	float frameTime = min(deltaTime, 0.1f);

	if(abs(m_movementAction.power) < 0.001f)
		m_movementAction.power = 0.f;

	if(abs(m_movementAction.rotateYaw) < 0.001f)
		m_movementAction.rotateYaw = 0.f;

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

	Matrix34 wTMInv = wTM.GetInvertedFast();

	Vec3 localVel = wTMInv.TransformVector(m_PhysDyn.v);
	Vec3 localW = wTMInv.TransformVector(m_PhysDyn.w);

	const Vec3 xAxis = wTM.GetColumn0();
	const Vec3 yAxis = wTM.GetColumn1();
	const Vec3 zAxis = wTM.GetColumn2();

	// check if propeller is in water
	Vec3 worldPropPos = wTM * m_pushOffset;
	float waterLevelWorld = gEnv->p3DEngine->GetWaterLevel(&worldPropPos);
	float fWaterLevelDiff = worldPropPos.z - waterLevelWorld;

	bool submerged = m_PhysDyn.submergedFraction > fSubmergedMin;
	m_inWater = submerged && fWaterLevelDiff < fWaterLevelMaxDiff;

	float speed = m_PhysDyn.v.len2() > 0.001f ? m_PhysDyn.v.len() : 0.f;
	float speedRatio = min(1.f, speed/m_maxSpeed);
	float absPedal = abs(m_movementAction.power);
	float absSteer = abs(m_movementAction.rotateYaw);

	// wave stuff
	float waveFreq = 1.f;
	waveFreq += 3.f*speedRatio;

	float waveTimerPrev = m_waveTimer;
	m_waveTimer += frameTime*waveFreq;

	// new randomized amount for this oscillation
	if(m_waveTimer >= gf_PI && waveTimerPrev < gf_PI)
		m_waveRandomMult = Random();

	if(m_waveTimer >= 2*gf_PI)
		m_waveTimer -= 2*gf_PI;

	float kx = m_waveIdleStrength.x*(m_waveRandomMult+0.3f) * (1.f-speedRatio + m_waveSpeedMult*speedRatio);
	float ky = m_waveIdleStrength.y * (1.f - 0.5f*absPedal - 0.5f*absSteer);

	Vec3 waveLoc = m_massOffset;
	waveLoc.y += speedRatio*min(0.f, m_pushOffset.y-m_massOffset.y);
	waveLoc = wTM * waveLoc;

	bool visible = m_pVehicle->GetGameObject()->IsProbablyVisible();
	bool doWave = visible && submerged && m_PhysDyn.submergedFraction < 0.99f;

	if(doWave && !m_isEnginePowered)
		m_pVehicle->NeedsUpdate(IVehicle::eVUF_AwakePhysics, true);

	if(m_isEnginePowered || (visible && !m_pVehicle->IsProbablyDistant()))
	{
		if(doWave && (m_isEnginePowered || g_pGameCVars->v_rockBoats))
		{
			pe_action_impulse waveImp;
			waveImp.angImpulse.x = Boosting() ? 0.f : sinf(m_waveTimer) * frameTime * m_Inertia.x * kx;

			if(isneg(waveImp.angImpulse.x))
				waveImp.angImpulse.x *= (1.f - min(1.f, 2.f*speedRatio)); // less amplitude for negative impulse

			waveImp.angImpulse.y = sinf(m_waveTimer-0.5f*gf_PI) * frameTime * m_Inertia.y * ky;
			waveImp.angImpulse.z = 0.f;
			waveImp.angImpulse = wTM.TransformVector(waveImp.angImpulse);
			waveImp.point = waveLoc;

			if(!m_movementAction.isAI)
				pPhysics->Action(&waveImp, 1);
		}
	}

	// ~wave stuff

	if(!m_isEnginePowered)
		return;

	pe_action_impulse linearImp, angularImp, dampImp, liftImp;
	float turnAccel = 0, turnAccelNorm = 0;

	if(m_inWater)
	{
		// Lateral damping
		if(m_lateralDamping>0.f)
		{
			pe_action_impulse impulse;
			impulse.impulse = - m_PhysDyn.mass * xAxis * (localVel.x * (frameTime * m_lateralDamping)/(1.f + frameTime*m_lateralDamping));
			pPhysics->Action(&impulse, 1);
		}

		// optional lifting (catamarans)
		if(m_velLift > 0.f)
		{
			if(localVel.y > m_velLift && !IsLifted())
				Lift(true);
			else if(localVel.y < m_velLift && IsLifted())
				Lift(false);
		}

		if(Boosting() && IsLifted())
		{
			// additional lift force
			liftImp.impulse = Vec3(0,0,m_PhysDyn.mass*frameTime*(localVel.y/m_velMax)*3.f);
			liftImp.point = wTM * m_massOffset;
			pPhysics->Action(&liftImp, 1);
		}

		// apply driving force
		float a = m_movementAction.power;

		if(sgn(a)*sgn(localVel.y) > 0)
		{
			// reduce acceleration with increasing speed
			float ratio = (localVel.y > 0.f) ? localVel.y/m_velMax : -localVel.y/m_velMaxReverse;
			a = (ratio>1.f) ? 0.f : sgn(a)*min(abs(a), 1.f-((1.f-m_accelVelMax)*sqr(ratio)));
		}

		if(a != 0)
		{
			if(sgn(a) * sgn(localVel.y) < 0)  // "braking"
				a *= m_accelCoeff;
			else
				a = max(a, -m_pedalLimitReverse);

			Vec3 pushDir(FORWARD_DIRECTION);

			// apply force downwards a bit for more realistic response
			if(a > 0)
				pushDir = Quat_tpl<float>::CreateRotationAA(DEG2RAD(m_pushTilt), Vec3(-1,0,0)) * pushDir;

			pushDir = wTM.TransformVector(pushDir);
			linearImp.impulse = pushDir * m_PhysDyn.mass * a * m_accel * frameTime;

			linearImp.point = m_pushOffset;
			linearImp.point.x = m_massOffset.x;
			linearImp.point = wTM * linearImp.point;
			pPhysics->Action(&linearImp, 1);
		}

		float roll = (float)__fsel(zAxis.z - 0.2f, xAxis.z / (frameTime + frameTime*frameTime), 0.f);		// Roll damping (with a exp. time constant of 1 sec)

		// apply steering
		if(m_movementAction.rotateYaw != 0)
		{
			if(abs(localVel.y) < fMinSpeedForTurn)   // if forward speed too small, no turning possible
			{
				turnAccel = 0;
			}
			else
			{
				int iDir = m_movementAction.power != 0.f ? sgn(m_movementAction.power) : sgn(localVel.y);
				turnAccelNorm = m_movementAction.rotateYaw * iDir * max(1.f, m_turnVelocityMult * speedRatio);

				// steering and current w in same direction?
				int sgnSteerW = sgn(m_movementAction.rotateYaw) * iDir * sgn(-localW.z);

				if(sgnSteerW < 0)
				{
					// "braking"
					turnAccelNorm *= m_turnAccelCoeff;
				}
				else
				{
					// reduce turn vel towards max
					float maxRatio = 1.f - 0.15f*min(1.f, abs(localW.z)/m_turnRateMax);
					turnAccelNorm = sgn(turnAccelNorm) * min(abs(turnAccelNorm), maxRatio);
				}

				turnAccel = turnAccelNorm * m_turnAccel;
				//roll = 0.2f * turnAccel; // slight roll
			}
		}

		// Use the centripetal acceleration to determine the amount of roll
		float centripetalAccel = clamp(speed * localW.z, -10.f, +10.f);
		roll -= (1.f - 2.f*fabsf(xAxis.z)) * m_rollAccel * centripetalAccel;

		// Always damp rotation!
		turnAccel += localW.z * m_turnDamping;

		if(turnAccel != 0)
		{
			Vec3 &angImp = angularImp.angImpulse;

			angImp.x = 0.f;
			angImp.y = roll * frameTime * m_Inertia.y;
			angImp.z = -turnAccel * frameTime * m_Inertia.z;

			angImp = wTM.TransformVector(angImp);
			pPhysics->Action(&angularImp, 1);
		}

		if(abs(localVel.x) > 0.01f)
		{
			// lateral force
			Vec3 &cornerForce = dampImp.impulse;

			cornerForce.x = -localVel.x * m_cornerForceCoeff * m_PhysDyn.mass * frameTime;
			cornerForce.y = 0.f;
			cornerForce.z = 0.f;

			if(m_cornerTilt != 0)
				cornerForce = Quat_tpl<float>::CreateRotationAA(sgn(localVel.x)*DEG2RAD(m_cornerTilt), Vec3(0,1,0)) * cornerForce;

			dampImp.impulse = wTM.TransformVector(cornerForce);

			dampImp.point = m_cornerOffset;
			dampImp.point.x = m_massOffset.x;
			dampImp.point = wTM.TransformPoint(dampImp.point);
			pPhysics->Action(&dampImp, 1);
		}
	}

	EjectionTest(deltaTime);

	if(m_bNetSync && m_netActionSync.PublishActions(CNetworkMovementStdBoat(this)))
		CHANGED_NETWORK_STATE(m_pVehicle,  eEA_GameClientDynamic);
}
Beispiel #16
0
//------------------------------------------------------------------------
void CWeapon::OnPickedUp(EntityId actorId, bool destroyed)
{
	BROADCAST_WEAPON_EVENT(OnPickedUp, (this, actorId, destroyed));

	BaseClass::OnPickedUp(actorId, destroyed);

	GetEntity()->SetFlags(GetEntity()->GetFlags() | ENTITY_FLAG_NO_PROXIMITY);	

	// bonus ammo is always put in the actor's inv
	if (!m_bonusammo.empty())
	{
		for (TAmmoVector::iterator it = m_bonusammo.begin(); it != m_bonusammo.end(); ++it)
		{
			const SWeaponAmmo& currentBonusAmmo = *it;

			SetInventoryAmmoCount(currentBonusAmmo.pAmmoClass, GetInventoryAmmoCount(currentBonusAmmo.pAmmoClass)+currentBonusAmmo.count);
		}

		m_bonusammo.clear();
	}

	if(GetISystem()->IsSerializingFile() == 1)
		return;

	CActor *pActor = GetActor(actorId);
	if (!pActor)
		return;
	
	// current ammo is only added to actor's inv, if we already have this weapon
	if (destroyed && m_sharedparams->params.unique)
	{
		for (TAmmoVector::iterator it = m_ammo.begin(); it!=m_ammo.end(); ++it)
		{
			//Only add ammo to inventory, if not accessory ammo (accessories give ammo already)
			const SWeaponAmmo& currentAmmo = *it;
			const SWeaponAmmo* pAccessoryAmmo = SWeaponAmmoUtils::FindAmmo(m_weaponsharedparams->ammoParams.accessoryAmmo, currentAmmo.pAmmoClass);
			if(pAccessoryAmmo != NULL)
			{
				SetInventoryAmmoCount(currentAmmo.pAmmoClass, GetInventoryAmmoCount(currentAmmo.pAmmoClass)+currentAmmo.count);
			}
		}
	}

	TestClipAmmoCountIsValid();

	if (!gEnv->bServer && pActor->IsPlayer())
	{
		IEntityClass* pCurrentAmmoClass = m_fm ? m_fm->GetAmmoType() : NULL;
		if (pCurrentAmmoClass)
		{
			//server has serialised the inventory count already

			if(IInventory* pInventory = GetActorInventory(GetOwnerActor()))
			{
				if(m_lastRecvInventoryAmmo > pInventory->GetAmmoCapacity(pCurrentAmmoClass))
				{
					pInventory->SetAmmoCapacity(pCurrentAmmoClass, m_lastRecvInventoryAmmo);
				}

				SetInventoryAmmoCountInternal(pInventory, pCurrentAmmoClass, m_lastRecvInventoryAmmo);
			}
		}
	}

	if(gEnv->bMultiplayer)
	{
		HighlightWeapon(false);
	}

	m_expended_ammo = 0;
}
int CFlowConvoyNode::OnPhysicsPostStep(const EventPhys * pEvent)
{
	FUNCTION_PROFILER(GetISystem(), PROFILE_GAME);

  if(m_bFirstUpdate)
    return 0; //after QuickLoad OnPhysicsPostStep called before ProcessEvent

	const EventPhysPostStep *pPhysPostStepEvent = (const EventPhysPostStep *)pEvent;

	IPhysicalEntity *pEventPhysEnt = pPhysPostStepEvent->pEntity;

	Vec3 posBack, posFront, posCenter;

	for (size_t i = 0; i < m_coaches.size(); ++i)
	{
		IPhysicalEntity *pPhysEnt = m_coaches[i].m_pEntity->GetPhysics();

		if (pEventPhysEnt == pPhysEnt)
		{
			if (m_ShiftTime > 0.0f)
			{
				m_speed = m_speed * (1.0f - breakValue * pPhysPostStepEvent->dt / m_MaxShiftTime);
				m_ShiftTime -= pPhysPostStepEvent->dt;
			}
			else
			{
				m_speed = m_speed + min(1.0f, (pPhysPostStepEvent->dt / 5.0f)) * (m_desiredSpeed - m_speed);
			}
		

			float speed = (m_splitCoachIndex > 0 && (int)i >= m_splitCoachIndex) ? m_splitSpeed : m_speed;
			float distance = (m_coaches[i].m_distanceOnPath += pPhysPostStepEvent->dt * speed);
			
			if(m_splitCoachIndex>0)
			{//train splitted
				if(i==m_splitCoachIndex-1) // update m_distanceOnPath for serialization
					m_distanceOnPath=distance-m_coaches[i].m_coachOffset;
				else if(i==m_coaches.size()-1) // update m_splitDistanceOnPath for serialization
					m_splitDistanceOnPath=distance-m_coaches[i].m_coachOffset;
			}
			else
			{//train in one piece
				if(i==m_coaches.size()-1)// update m_distanceOnPath for serialization
					m_distanceOnPath=distance-m_coaches[i].m_coachOffset;
			}

			posBack  = m_path.GetPointAlongPath(distance - m_coaches[i].m_wheelDistance, m_coaches[i].m_backWheelIterator[0]);
			posFront = m_path.GetPointAlongPath(distance + m_coaches[i].m_wheelDistance, m_coaches[i].m_frontWheelIterator[0]);
			posCenter = (posBack+posFront)*0.5f;


			Vec3 posDiff = posFront - posBack;
			float magnitude = posDiff.GetLength();

			if (magnitude > FLT_EPSILON)
			{
				posDiff *= 1.0f / magnitude;

				pe_params_pos ppos;
				ppos.pos = posCenter;
				ppos.q = Quat::CreateRotationVDir(posDiff);
				if (m_bXAxisFwd)
					ppos.q *= Quat::CreateRotationZ(gf_PI*-0.5f);
				pPhysEnt->SetParams(&ppos, 0 /* bThreadSafe=0 */); // as we are calling from the physics thread

				Vec3 futurePositionBack, futurePositionFront;
				futurePositionBack  = m_path.GetPointAlongPath(distance + PATH_DERIVATION_TIME * speed - m_coaches[i].m_wheelDistance, m_coaches[i].m_backWheelIterator[1]);
				futurePositionFront = m_path.GetPointAlongPath(distance + PATH_DERIVATION_TIME * speed + m_coaches[i].m_wheelDistance, m_coaches[i].m_frontWheelIterator[1]);

				Vec3 futurePosDiff = futurePositionFront - futurePositionBack;
				magnitude = futurePosDiff.GetLength();

				if (magnitude > FLT_EPSILON)
				{
					futurePosDiff *= 1.0f / magnitude;

					pe_action_set_velocity setVel;
					setVel.v = ((futurePositionBack+ futurePositionFront)*0.5f - posCenter) * (1.0f/PATH_DERIVATION_TIME);

					//Vec3 dir=(posFront-posBack).GetNormalized();
					//Vec3 future_dir=(futurePositionFront-futurePositionBack).GetNormalized();
					Vec3 w=posDiff.Cross(futurePosDiff);
					float angle=cry_asinf(w.GetLength());
					setVel.w=(angle/PATH_DERIVATION_TIME)*w.GetNormalized();
					pPhysEnt->Action(&setVel, 0 /* bThreadSafe=0 */); // as we are calling from the physics thread
					break;
				}
			}
		}
	}

	// Done processing once we reach end of path
	if (m_atEndOfPath)
		m_processNode = false;

	return 0;
}
//------------------------------------------------------------------------
void CWeapon::OnPickedUp(EntityId actorId, bool destroyed)
{
	BROADCAST_WEAPON_EVENT(OnPickedUp, (this, actorId, destroyed));

	CItem::OnPickedUp(actorId, destroyed);

	GetEntity()->SetFlags(GetEntity()->GetFlags() | ENTITY_FLAG_NO_PROXIMITY);
	GetEntity()->SetFlags(GetEntity()->GetFlags() & ~ENTITY_FLAG_ON_RADAR);

	if(GetISystem()->IsSerializingFile() == 1)
		return;

	if (!IsServer())
		return;

	CActor *pActor=GetActor(actorId);
	if (!pActor)
		return;

	// bonus ammo is always put in the actor's inv
	if (!m_bonusammo.empty())
	{
		for (TAmmoMap::iterator it=m_bonusammo.begin(); it!=m_bonusammo.end(); ++it)
		{
			int count=it->second;

			SetInventoryAmmoCount(it->first, GetInventoryAmmoCount(it->first)+count);
		}

		m_bonusammo.clear();
	}

	if (!m_ammoCapacity.empty())
	{
		IInventory* pInventory = GetActorInventory(GetOwnerActor());
		if (pInventory)
		{
			for (TAmmoMap::iterator it=m_ammoCapacity.begin(); it!=m_ammoCapacity.end(); ++it)
				pInventory->SetAmmoCapacity(it->first, it->second);
		}
		m_ammoCapacity.clear();
	}

	// current ammo is only added to actor's inv, if we already have this weapon
	if (destroyed && m_sharedparams->params.unique)
	{
		for (TAmmoMap::iterator it=m_ammo.begin(); it!=m_ammo.end(); ++it)
		{
			//Only add ammo to inventory, if not accessory ammo (accessories give ammo already)
			if(m_accessoryAmmo.find(it->first)==m_accessoryAmmo.end())
			{
				int count=it->second;

				SetInventoryAmmoCount(it->first, GetInventoryAmmoCount(it->first)+count);
			}
		}
	}

	if(!gEnv->bMultiplayer && !m_initialSetup.empty() && pActor->IsClient())
	{
		for (TAccessoryMap::iterator it=m_accessories.begin(); it!=m_accessories.end(); ++it)
			FixAccessories(GetAccessoryParams(it->first), true);
	}

	m_expended_ammo = 0;
}
Beispiel #19
0
CHUDObituary::CHUDObituary()
:	m_deathHead(0), m_empty(true)
{
	m_pDefaultFont = GetISystem()->GetICryFont()->GetFont("default");
	CRY_ASSERT(m_pDefaultFont);
}
//////////////////////////////////////////////////////////////////////////
// NOTE: This function must be thread-safe. Before adding stuff contact MarcoC.
void CVehicleMovementVTOL::ProcessAI(const float deltaTime)
{
	FUNCTION_PROFILER( GetISystem(), PROFILE_GAME );

	if (!m_isVTOLMovement)
	{
		CVehicleMovementHelicopter::ProcessAI(deltaTime);
		return;
	}

	m_velDamp = 0.15f;
	const float maxDirChange = 15.0f;

	// it's useless to progress further if the engine has yet to be turned on
	if (!m_isEnginePowered)
	{
		return;
	}

	m_movementAction.Clear();
	m_movementAction.isAI = true;
	ResetActions();
	// Our current state
	const Vec3 worldPos =  m_PhysPos.pos;
	const Matrix33 worldMat( m_PhysPos.q);
	Ang3 worldAngles = Ang3::GetAnglesXYZ(worldMat);
	const Vec3 currentVel = m_PhysDyn.v;
	const Vec3 currentVel2D(currentVel.x, currentVel.y, 0.0f);
	// +ve direction mean rotation anti-clocwise about the z axis - 0 means along y
	float currentDir = worldAngles.z;
	// to avoid singularity
	const Vec3 vWorldDir = worldMat * FORWARD_DIRECTION;
	const Vec3 vWorldDir2D =  Vec3( vWorldDir.x,  vWorldDir.y, 0.0f ).GetNormalizedSafe();
	// Our inputs
	const float desiredSpeed = m_aiRequest.HasDesiredSpeed() ? m_aiRequest.GetDesiredSpeed() : 0.0f;
	const Vec3 desiredMoveDir = m_aiRequest.HasMoveTarget() ? (m_aiRequest.GetMoveTarget() - worldPos).GetNormalizedSafe() : vWorldDir;
	const Vec3 desiredMoveDir2D = Vec3(desiredMoveDir.x, desiredMoveDir.y, 0.0f).GetNormalizedSafe(vWorldDir2D);
	const Vec3 desiredVel = desiredMoveDir * desiredSpeed;
	const Vec3 desiredVel2D(desiredVel.x, desiredVel.y, 0.0f);
	const Vec3 desiredLookDir = m_aiRequest.HasLookTarget() ? (m_aiRequest.GetLookTarget() - worldPos).GetNormalizedSafe() : desiredMoveDir;
	const Vec3 desiredLookDir2D = Vec3(desiredLookDir.x, desiredLookDir.y, 0.0f).GetNormalizedSafe(vWorldDir2D);
	// Calculate the desired 2D velocity change
	Vec3 desiredVelChange2D = desiredVel2D - currentVel2D;
	float velChangeLength = desiredVelChange2D.GetLength2D();
	bool isLandingMode = false;

	if (m_pLandingGears && m_pLandingGears->AreLandingGearsOpen())
	{
		isLandingMode = true;
	}

	bool isHorizontal = (desiredSpeed >= 5.0f) && (desiredMoveDir.GetLength2D() > desiredMoveDir.z);
	float desiredPitch = 0.0f;
	float desiredRoll = 0.0f;
	float desiredDir = atan2f(-desiredLookDir2D.x, desiredLookDir2D.y);

	while (currentDir < desiredDir - gf_PI)
	{
		currentDir += 2.0f * gf_PI;
	}

	while (currentDir > desiredDir + gf_PI)
	{
		currentDir -= 2.0f * gf_PI;
	}

	float diffDir = (desiredDir - currentDir);
	m_actionYaw = diffDir * m_yawInputConst;
	m_actionYaw += m_yawInputDamping * (currentDir - m_lastDir) / deltaTime;
	m_lastDir = currentDir;

	if (isHorizontal && !isLandingMode)
	{
		float desiredFwdSpeed = desiredVelChange2D.GetLength();
		desiredFwdSpeed *= min(1.0f, diffDir / DEG2RAD(maxDirChange));

		if (!iszero(desiredFwdSpeed))
		{
			const Vec3 desiredWorldTiltAxis = Vec3(-desiredVelChange2D.y, desiredVelChange2D.x, 0.0f);
			const Vec3 desiredLocalTiltAxis = worldMat.GetTransposed() * desiredWorldTiltAxis;
			m_forwardAction = m_fwdPID.Update(currentVel.y, desiredLocalTiltAxis.GetLength(), -1.0f, 1.0f);
			float desiredTiltAngle = m_tiltPerVelDifference * desiredVelChange2D.GetLength();
			Limit(desiredTiltAngle, -m_maxTiltAngle, m_maxTiltAngle);

			if (desiredTiltAngle > 0.0001f)
			{
				const Vec3 desiredWorldTiltAxis2 = Vec3(-desiredVelChange2D.y, desiredVelChange2D.x, 0.0f).GetNormalizedSafe();
				const Vec3 desiredLocalTiltAxis2 = worldMat.GetTransposed() * desiredWorldTiltAxis2;
				Vec3 vVelLocal = worldMat.GetTransposed() * desiredVel;
				vVelLocal.NormalizeSafe();
				float dotup = vVelLocal.Dot(Vec3( 0.0f, 0.0f, 1.0f ) );
				float currentSpeed = currentVel.GetLength();
				desiredPitch = dotup * currentSpeed / 100.0f;
				desiredRoll = desiredTiltAngle * desiredLocalTiltAxis2.y * currentSpeed / 30.0f;
			}
		}
	}
	else
	{
		float desiredTiltAngle = m_tiltPerVelDifference * desiredVelChange2D.GetLength();
		Limit(desiredTiltAngle, -m_maxTiltAngle, m_maxTiltAngle);

		if (desiredTiltAngle > 0.0001f)
		{
			const Vec3 desiredWorldTiltAxis = Vec3(-desiredVelChange2D.y, desiredVelChange2D.x, 0.0f).GetNormalizedSafe();
			const Vec3 desiredLocalTiltAxis = worldMat.GetTransposed() * desiredWorldTiltAxis;
			desiredPitch = desiredTiltAngle * desiredLocalTiltAxis.x;
			desiredRoll = desiredTiltAngle * desiredLocalTiltAxis.y;
		}
	}

	float currentHeight = m_PhysPos.pos.z;

	if ( m_aiRequest.HasMoveTarget() )
	{
		m_hoveringPower = m_powerPID.Update(currentVel.z, desiredVel.z, -1.0f, 4.0f);

		//m_hoveringPower = (m_desiredHeight - currentHeight) * m_powerInputConst;
		//m_hoveringPower += m_powerInputDamping * (currentHeight - m_lastHeight) / deltaTime;

		if (isHorizontal)
		{
			if (desiredMoveDir.z > 0.6f || desiredMoveDir.z < -0.85f)
			{
				desiredPitch = max(-0.5f, min(0.5f, desiredMoveDir.z)) * DEG2RAD(35.0f);
				m_forwardAction += abs(desiredMoveDir.z);
			}

			m_liftAction = min(2.0f, max(m_liftAction, m_hoveringPower * 2.0f));
		}
		else
		{
			m_liftAction = 0.0f;
		}
	}
	else
	{
		// to keep hovering at the same place
		m_hoveringPower = m_powerPID.Update(currentVel.z, m_desiredHeight - currentHeight, -1.0f, 1.0f);
		m_liftAction = 0.0f;

		if (m_pVehicle->GetAltitude() > 10.0f)	//TODO: this line is not MTSafe
		{
			m_liftAction = m_forwardAction;
		}
	}

	m_actionPitch += m_pitchActionPerTilt * (desiredPitch - worldAngles.x);
	m_actionRoll += m_pitchActionPerTilt * (desiredRoll - worldAngles.y);
	Limit(m_actionPitch, -1.0f, 1.0f);
	Limit(m_actionRoll, -1.0f, 1.0f);
	Limit(m_actionYaw, -1.0f, 1.0f);

	if (m_horizontal > 0.0001f)
	{
		m_desiredHeight = m_PhysPos.pos.z;
	}

	Limit(m_forwardAction, -1.0f, 1.0f);
}
Beispiel #21
0
//------------------------------------------------------------------------
void CViewSystem::Update(float frameTime)
{
	FUNCTION_PROFILER(GetISystem(), PROFILE_ACTION);

	if (gEnv->IsDedicated())
		return;

	CView* const __restrict pActiveView = static_cast<CView*>(GetActiveView());

	TViewMap::const_iterator       Iter(m_views.begin());
	TViewMap::const_iterator const IterEnd(m_views.end());

	for (; Iter != IterEnd; ++Iter)
	{
		CView* const __restrict pView = Iter->second;

		bool const bIsActive = (pView == pActiveView);

		pView->Update(frameTime, bIsActive);

		if (bIsActive)
		{
			CCamera &rCamera = pView->GetCamera();
			pView->UpdateAudioListener(rCamera.GetMatrix());
			SViewParams currentParams = *(pView->GetCurrentParams());

			rCamera.SetJustActivated(currentParams.justActivated);

			currentParams.justActivated = false;
			pView->SetCurrentParams(currentParams);

			if (m_bOverridenCameraRotation)
			{
				// When camera rotation is overridden.
				Vec3     pos = rCamera.GetMatrix().GetTranslation();
				Matrix34 camTM(m_overridenCameraRotation);
				camTM.SetTranslation(pos);
				rCamera.SetMatrix(camTM);
			}
			else
			{
				// Normal setting of the camera

				if (m_fCameraNoise > 0)
				{
					Matrix33 m = Matrix33(rCamera.GetMatrix());
					m.OrthonormalizeFast();
					Ang3 aAng1 = Ang3::GetAnglesXYZ(m);
					//Ang3 aAng2 = RAD2DEG(aAng1);

					Matrix34 camTM = rCamera.GetMatrix();
					Vec3     pos   = camTM.GetTranslation();
					camTM.SetIdentity();

					const float fScale = 0.1f;
					CPNoise3*   pNoise = m_pSystem->GetNoiseGen();
					float       fRes   = pNoise->Noise1D(gEnv->pTimer->GetCurrTime() * m_fCameraNoiseFrequency);
					aAng1.x += fRes * m_fCameraNoise * fScale;
					pos.z   -= fRes * m_fCameraNoise * fScale;
					fRes     = pNoise->Noise1D(17 + gEnv->pTimer->GetCurrTime() * m_fCameraNoiseFrequency);
					aAng1.y -= fRes * m_fCameraNoise * fScale;

					//aAng1.z+=fRes*0.025f; // left / right movement should be much less visible

					camTM.SetRotationXYZ(aAng1);
					camTM.SetTranslation(pos);
					rCamera.SetMatrix(camTM);
				}
			}

			m_pSystem->SetViewCamera(rCamera);
		}
	}

	// Display debug info on screen
	if (m_nViewSystemDebug)
	{
		DebugDraw();
	}

	// perform dynamic color grading
	// Beni - Commented for console demo stuff
	/******************************************************************************************
	   if (!IsPlayingCutScene() && gEnv->pAISystem)
	   {
	   SAIDetectionLevels detection;
	   gEnv->pAISystem->GetDetectionLevels(nullptr, detection);
	   float factor = detection.puppetThreat;

	   // marcok: magic numbers taken from Maciej's tweaked values (final - initial)
	   {
	    float percentage = (0.0851411f - 0.0509998f)/0.0509998f * factor;
	    float amount = 0.0f;
	    gEnv->p3DEngine->GetPostEffectParam("ColorGrading_GrainAmount", amount);
	    gEnv->p3DEngine->SetPostEffectParam("ColorGrading_GrainAmount_Offset", amount*percentage);
	   }
	   {
	    float percentage = (0.405521f - 0.256739f)/0.256739f * factor;
	    float amount = 0.0f;
	    gEnv->p3DEngine->GetPostEffectParam("ColorGrading_SharpenAmount", amount);
	    //gEnv->p3DEngine->SetPostEffectParam("ColorGrading_SharpenAmount_Offset", amount*percentage);
	   }
	   {
	    float percentage = (0.14f - 0.11f)/0.11f * factor;
	    float amount = 0.0f;
	    gEnv->p3DEngine->GetPostEffectParam("ColorGrading_PhotoFilterColorDensity", amount);
	    gEnv->p3DEngine->SetPostEffectParam("ColorGrading_PhotoFilterColorDensity_Offset", amount*percentage);
	   }
	   {
	    float percentage = (234.984f - 244.983f)/244.983f * factor;
	    float amount = 0.0f;
	    gEnv->p3DEngine->GetPostEffectParam("ColorGrading_maxInput", amount);
	    //gEnv->p3DEngine->SetPostEffectParam("ColorGrading_maxInput_Offset", amount*percentage);
	   }
	   {
	    float percentage = (239.984f - 247.209f)/247.209f * factor;
	    float amount = 0.0f;
	    gEnv->p3DEngine->GetPostEffectParam("ColorGrading_maxOutput", amount);
	    //gEnv->p3DEngine->SetPostEffectParam("ColorGrading_maxOutput_Offset", amount*percentage);
	   }
	   {
	    Vec4 dest(0.0f/255.0f, 22.0f/255.0f, 33.0f/255.0f, 1.0f);
	    Vec4 initial(2.0f/255.0f, 154.0f/255.0f, 226.0f/255.0f, 1.0f);
	    Vec4 percentage = (dest - initial)/initial * factor;
	    Vec4 amount;
	    gEnv->p3DEngine->GetPostEffectParamVec4("clr_ColorGrading_SelectiveColor", amount);
	    //gEnv->p3DEngine->SetPostEffectParamVec4("clr_ColorGrading_SelectiveColor_Offset", amount*percentage);
	   }
	   {
	    float percentage = (-5.0083 - -1.99999)/-1.99999 * factor;
	    float amount = 0.0f;
	    gEnv->p3DEngine->GetPostEffectParam("ColorGrading_SelectiveColorCyans", amount);
	    //gEnv->p3DEngine->SetPostEffectParam("ColorGrading_SelectiveColorCyans_Offset", amount*percentage);
	   }
	   {
	    float percentage = (10.0166 - -5.99999)/-5.99999 * factor;
	    float amount = 0.0f;
	    gEnv->p3DEngine->GetPostEffectParam("ColorGrading_SelectiveColorMagentas", amount);
	    //gEnv->p3DEngine->SetPostEffectParam("ColorGrading_SelectiveColorMagentas_Offset", amount*percentage);
	   }
	   {
	    float percentage = (10.0166 - 1.99999)/1.99999 * factor;
	    float amount = 0.0f;
	    gEnv->p3DEngine->GetPostEffectParam("ColorGrading_SelectiveColorYellows", amount);
	    //gEnv->p3DEngine->SetPostEffectParam("ColorGrading_SelectiveColorYellows_Offset", amount*percentage);
	   }
	   }
	 ********************************************************************************************/
}