Exemplo n.º 1
0
	void Update(float elapsed)
	{
		float maxTime = GetPortFloat(&m_actInfo, EIP_Duration);
		float percent = maxTime > FLT_EPSILON ? elapsed / maxTime : 1.0f;
		if(percent >= 1.0f)
		{
			m_actInfo.pGraph->SetRegularlyUpdated(m_actInfo.myID, false);
			m_triggered = false;
			return;
		}

		Vec3 N = GetPortVec3(&m_actInfo, EIP_Normal);

		float rangeMin = GetPortFloat(&m_actInfo, EIP_RangeMin);
		float rangeMax = GetPortFloat(&m_actInfo, EIP_RangeMax);
		const float range = rangeMax - rangeMin;
		Vec3 boxDim(rangeMax, rangeMax, rangeMax);
		Vec3 ptmin = m_effectCenter - boxDim;
		Vec3 ptmax = m_effectCenter + boxDim;

		float speed = GetPortFloat(&m_actInfo, EIP_Speed);
		float waveFront = elapsed * speed;

		float decay = GetPortFloat(&m_actInfo, EIP_Decay);
		if(decay > FLT_EPSILON) decay = 1.0f / decay;

		float force = GetPortFloat(&m_actInfo, EIP_Force);
		force = pow_tpl(force * (1-percent), decay);

		float amplitude = GetPortFloat(&m_actInfo, EIP_Amplitude);
		amplitude = pow_tpl(amplitude * (1-percent), decay);

		if (gEnv->bMultiplayer) // Turned off for performance and network issues
		{
			return;
		}

		IPhysicalEntity** pEntityList = NULL;
		static const int iObjTypes = ent_rigid | ent_sleeping_rigid | ent_living;// | ent_allocate_list;
		int numEntities = gEnv->pPhysicalWorld->GetEntitiesInBox(ptmin, ptmax, pEntityList, iObjTypes);
		AABB bounds;
		for(int i=0; i<numEntities; ++i)
		{
			IPhysicalEntity* pPhysicalEntity = pEntityList[i];
			IEntity* pEntity = static_cast<IEntity*>(pPhysicalEntity->GetForeignData(PHYS_FOREIGN_ID_ENTITY));

			// Has the entity already been affected?
			if(pEntity)
			{
				bool affected = stl::find(m_entitiesAffected, pEntity->GetId());
				if(!affected)
				{
					IEntityPhysicalProxy* pPhysicalProxy = static_cast<IEntityPhysicalProxy*>(pEntity->GetProxy(ENTITY_PROXY_PHYSICS));
					if(pPhysicalProxy)
					{
						pPhysicalProxy->GetWorldBounds(bounds);
						Vec3 p = bounds.GetCenter();
						Vec3 v = p - m_effectCenter;
						float distFromCenter = v.GetLength() + FLT_EPSILON;
						if(distFromCenter < rangeMax)
						{
							if(waveFront > distFromCenter) // has the wavefront passed the entity?
							{
								//pPhysicalEntity->GetStatus(&dyn);

								// normalize v, cheaper than another sqrt
								v /= distFromCenter;

								Vec3 dir = N + v * force;
								static bool usePos = false;
								float impulse = 1.0f - (max(0.0f, distFromCenter - rangeMin) / range);
								impulse = impulse * amplitude;// / dyn.mass;
								if(impulse > FLT_EPSILON)
								{
									pPhysicalProxy->AddImpulse(-1, p, dir * impulse, usePos, 1.0f);
									m_entitiesAffected.push_back(pEntity->GetId());
								}
							}
						}
					}
				}
			}
		}
	}
void CVehicleDamageBehaviorBlowTire::DamagePlayers()
{
	// check for the nasty case when the player is shooting at the vehicle tires while prone 
	// under or behind the car, In that case the player should get killed by the vehicle, 
	// otherwise he gets stuck forever. Note that he should only get killed when the tier
	// is actually destroyed and not by collision resulting by the impulse added by just 
	// shooting at the tiers. Unfortunately using physics for doing this check is not reliable
	// enough so we have to check it explicitly
	
	IEntityPhysicalProxy *pPhysicsProxy = (IEntityPhysicalProxy*)m_pVehicle->GetEntity()->GetProxy(ENTITY_PROXY_PHYSICS);
	if (!pPhysicsProxy)
		return;

	AABB bbox;
	pPhysicsProxy->GetWorldBounds( bbox );

	IPhysicalWorld *pWorld = gEnv->pSystem->GetIPhysicalWorld();
	IPhysicalEntity **ppColliders;
	// check entities in collision with the car
	int cnt = pWorld->GetEntitiesInBox( bbox.min,bbox.max, ppColliders,ent_living);
	for (int i = 0; i < cnt; i++)
	{

		IEntity *pEntity = gEnv->pEntitySystem->GetEntityFromPhysics( ppColliders[i] );
		if (!pEntity)
			continue;
		
		// skip the vehicle itself
		if (pEntity==m_pVehicle->GetEntity())
			continue;

		IPhysicalEntity *pPhysEnt = pEntity->GetPhysics();
		if (!pPhysEnt) 
			continue;

		IActor* pActor = gEnv->pGame->GetIGameFramework()->GetIActorSystem()->GetActor(pEntity->GetId());            
		if(!pActor)
			continue;

		//Jan M.: the player is killed when he entered the vehicle while prone although he is still passenger!
		if(m_pVehicle == pActor->GetLinkedVehicle())
			continue;

		//the player must be prone under the vehicle
		IAnimatedCharacter * animatedCharacter=pActor->GetAnimatedCharacter();
		if (!animatedCharacter)
			continue;

		int stance = animatedCharacter->GetCurrentStance();
		if (stance!=STANCE_PRONE)
			continue;

		pe_player_dimensions dim;
		if (!pPhysEnt->GetParams(&dim))
			continue;
		// position returned is at entity's feet, add head position from physics
		Vec3 vPos1=pEntity->GetPos();
		vPos1.z = vPos1.z + dim.heightHead;

		float fZ=bbox.GetCenter().z;
		if (vPos1.z>fZ)
			continue; // not under the vehicle

		// at this point we have a collision with the car moving down and the guy prone under the car, it is safe
		// to assume he has been squished so let's kill him.
		if (gEnv->bServer && pActor->GetHealth()>0)
		{
			// adding a server hit to make it working in MP
			IGameRules *pGameRules = gEnv->pGame->GetIGameFramework()->GetIGameRulesSystem()->GetCurrentGameRules();
			if (pGameRules)
			{
				HitInfo hit;

				EntityId shooterId=m_pVehicle->GetEntityId();
				if (m_pVehicle->GetDriver())
					shooterId=m_pVehicle->GetDriver()->GetEntityId();					

				hit.targetId = pEntity->GetId();      
				hit.shooterId = shooterId;
				hit.weaponId = m_pVehicle->GetEntityId();
				hit.damage = 1000.f;
				hit.type = 0;
				hit.pos = pActor->GetEntity()->GetWorldPos();

				pGameRules->ServerHit(hit); 
			}  
		} 
	} //i
}
Exemplo n.º 3
0
//---------------------------------------------------------------------------
IEntity* CFireModePlugin_AutoAim::CalculateBestProjectileAutoAimTarget(const Vec3& attackerPos, const Vec3& attackerDir, const bool bCurrentlyZoomed, const EntityId ownerId) const
{

#if ALLOW_PROJECTILEHELPER_DEBUGGING
	static const ColorB red(127,0,0);
	static const ColorB green(0,127,0);
	static const ColorB brightGreen(0,255,0);
	static const float s_sphereDebugRad = 0.15f;
#endif


	IEntity* pBestTarget = NULL;
	float    fBestScore  = 0.0f;

	const TAutoaimTargets& players = g_pGame->GetAutoAimManager().GetAutoAimTargets();

	// Cache commonly required constants for scoring
	const ConeParams& aimConeSettings = GetAimConeSettings(bCurrentlyZoomed);

	const float minAutoAimDistSqrd   = cry_sqr(aimConeSettings.m_minDistance);
	const float maxAutoAimDistSqrd   = cry_sqr(aimConeSettings.m_maxDistance);
	const float  coneSizeRads		 = aimConeSettings.m_outerConeRads;
	IEntitySystem* pEntitySystem	 = gEnv->pEntitySystem;
	CPlayerVisTable* pVisTable		 = g_pGame->GetPlayerVisTable();

	const float distanceConstant	 = __fres(max(aimConeSettings.m_maxDistance, FLT_EPSILON));
	const float	coneAngleConstant	 = __fres(max(coneSizeRads*0.5f, FLT_EPSILON));

	// For each potential target we do a dist + cone check
	TAutoaimTargets::const_iterator endIter = players.end();
	for(TAutoaimTargets::const_iterator iter = players.begin(); iter != endIter; ++iter)
	{
		// If entity exists and we are allowed to target them
		EntityId targetEntityId = iter->entityId;
		IEntity* pEntity = pEntitySystem->GetEntity(targetEntityId);
		if(pEntity && AllowedToTargetPlayer(ownerId,targetEntityId))
		{
			// If further than allowed dist, discard
			Vec3 targetTestPos;

			// Test against primary Auto aim position
			const SAutoaimTarget* pAutoAimInfo = g_pGame->GetAutoAimManager().GetTargetInfo(targetEntityId);
			if(pAutoAimInfo)
			{
				targetTestPos = pAutoAimInfo->primaryAimPosition; 
			}
			else
			{
				// Then  ABBB centre as backup
				IEntityPhysicalProxy* pPhysProxy = static_cast<IEntityPhysicalProxy*>(pEntity->GetProxy(ENTITY_PROXY_PHYSICS));
				if(pPhysProxy)
				{
					AABB aabb;
					pPhysProxy->GetWorldBounds(aabb);
					targetTestPos = aabb.GetCenter();
				}
				else
				{
					targetTestPos = pEntity->GetWorldPos();
				}
			}

			Vec3 toTarget = targetTestPos - attackerPos;
			float distSqrd = toTarget.GetLengthSquared();
			if( distSqrd >= minAutoAimDistSqrd &&
				distSqrd <= maxAutoAimDistSqrd )
			{

				// If not within cone.. discard
				float theta = 0.0f;
				if(TargetPositionWithinFrontalCone(attackerPos,targetTestPos, attackerDir,coneSizeRads, theta))
				{
					// If cant see them .. next
					if(!pVisTable->CanLocalPlayerSee(targetEntityId, 5))
					{

#if ALLOW_PROJECTILEHELPER_DEBUGGING
						m_lastTargetRejectionReason.append("VISION BLOCKED"); 	
#endif // #if ALLOW_PROJECTILEHELPER_DEBUGGING

						continue;
					}

					// For each candidate, generate their Auto Aim score.

					// 1) [0.0f,1.0f] score comprised of DISTANCE based score (closer is better)
					float targetDistScore    =  1.0f - ( sqrtf(distSqrd) *  distanceConstant );

					// Lets try squaring this to make candidates with only small gaps between them reflect distance scoring better and reduce the importance of distance at super long ranges
					targetDistScore *= targetDistScore;

					// 2) +  [0.0f,1.0f]  cone based score (central is better)
					const float targetConeScore		 =  1.0f - ( theta * coneAngleConstant );

					// Factor in designer controlled multipliers
					const float finalScore = (targetDistScore * g_pGameCVars->pl_pickAndThrow.chargedThrowAutoAimDistanceHeuristicWeighting) +  // TODO - move these weightings into params
						(targetConeScore * g_pGameCVars->pl_pickAndThrow.chargedThrowAutoAimAngleHeuristicWeighting);

					if(finalScore > fBestScore)
					{
						fBestScore  = finalScore;
						pBestTarget = pEntity;
					}

					// Debug rendering!
#if ALLOW_PROJECTILEHELPER_DEBUGGING
					if(g_pGameCVars->pl_debug_projectileAimHelper)
					{
						CryWatch("Entity [%s - %d] DistScore [%.2f] , ConeScore[%.2f], totalScore [%.3f]", pEntity->GetName(), pEntity->GetId(), targetDistScore, targetConeScore, finalScore);
						
						// Draw a green sphere to indicate valid
						gEnv->pRenderer->GetIRenderAuxGeom()->DrawSphere(targetTestPos, s_sphereDebugRad,green);
					}
#endif //#if ALLOW_PROJECTILEHELPER_DEBUGGING

				}
#if ALLOW_PROJECTILEHELPER_DEBUGGING
				else
				{
					m_lastTargetRejectionReason.Format("OUTSIDE CONE [%.3f]",RAD2DEG(theta));

					if(g_pGameCVars->pl_debug_projectileAimHelper)
					{
						// Draw a red sphere to indicate not valid
						gEnv->pRenderer->GetIRenderAuxGeom()->DrawSphere(targetTestPos, s_sphereDebugRad, red);
					}
				}
#endif //#if ALLOW_PROJECTILEHELPER_DEBUGGING
			}
#if ALLOW_PROJECTILEHELPER_DEBUGGING
			else
			{
				if(distSqrd >= minAutoAimDistSqrd)
				{
					m_lastTargetRejectionReason.Format("TOO CLOSE [%.3f]", cry_sqrtf_fast(distSqrd)); 
				}
				else
				{
					m_lastTargetRejectionReason.Format("TOO FAR [%.3f]",cry_sqrtf_fast(distSqrd));  
				}
			}
#endif //#if ALLOW_PROJECTILEHELPER_DEBUGGING
		}
	}

	// Draw a Really bright sphere on BEST target
#if ALLOW_PROJECTILEHELPER_DEBUGGING
	if(pBestTarget && g_pGameCVars->pl_debug_projectileAimHelper)
	{
		// If further than allowed dist, discard
		Vec3 targetTestPos = pBestTarget->GetPos();

		// We use aabb centre to reduce error
		IEntityPhysicalProxy* pPhysProxy = static_cast<IEntityPhysicalProxy*>(pBestTarget->GetProxy(ENTITY_PROXY_PHYSICS));
		if(pPhysProxy)
		{
			AABB aabb;
			pPhysProxy->GetWorldBounds(aabb);
			targetTestPos = aabb.GetCenter();
		}

		// Draw a bright green sphere to indicate target chosen
		gEnv->pRenderer->GetIRenderAuxGeom()->DrawSphere(targetTestPos, s_sphereDebugRad*1.05f, brightGreen);
	}
#endif //#if ALLOW_PROJECTILEHELPER_DEBUGGING

	return pBestTarget;
}