Exemplo n.º 1
0
void CCameraFlight::DetectCollisions()
{
	primitives::sphere	sph;
	sph.r				= 0.15f;
	sph.center	= m_vTargetFadePos + m_vLookingDirection * RAY_SCAN_DISTANCE;
	CCameraRayScan *pRayScan = g_pGame->GetCameraManager()->GetCamView()->GetCamRayScan();
	if (m_RayId == INVALID_RAY_ID)
	{
		m_RayId = pRayScan->ShootRay(sph.center, -m_vLookingDirection * RAY_SCAN_DISTANCE, ent_all & ~(ent_living | ent_independent | ent_rigid), geom_colltype0);
	}
	const RayCastResult* pRayRes = pRayScan->GetExternalHit(m_RayId);
	const ray_hit *pHit = pRayRes->hitCount > 0 ? &pRayRes->hits[0] : NULL;
	static int iNumHits = 0;
	if(pHit && pHit->dist > 0.0f)
	{
		iNumHits++;
		if(iNumHits > 2)
		{
			bool bIgnore = false;
			IPhysicalEntity *pPhysEntity = pHit->pCollider;
			if(pPhysEntity)
			{
				int iForeignData = pPhysEntity->GetiForeignData();
				if (iForeignData == PHYS_FOREIGN_ID_STATIC)
				{
					//check whether the hit rendernode is "vegetation"
					void *pForeignData = pPhysEntity->GetForeignData(PHYS_FOREIGN_ID_STATIC);
					IRenderNode * pRN = (IRenderNode*)pForeignData;
					if(pRN && pRN->GetRenderNodeType() == eERType_Vegetation)
						bIgnore = true;
				}
				else if(iForeignData == PHYS_FOREIGN_ID_ENTITY)
				{
					IEntity *pEntity = gEnv->pEntitySystem->GetEntityFromPhysics(pPhysEntity);
					if(pEntity && (pEntity == m_pRefEnt || pEntity->GetId() == LOCAL_PLAYER_ENTITY_ID))
						bIgnore = true;
				}
				else if(iForeignData == -1)
					bIgnore = true;
			}

			if(!bIgnore)
				m_vTargetFadePos = m_vTargetFadePos + m_vLookingDirection * max(0.0f, (RAY_SCAN_DISTANCE - pHit->dist));
			else
				iNumHits = 0;
		}
	}
	else
		iNumHits = 0;

	if (pRayRes)
	{
		pRayScan->RemoveExternalHit(m_RayId);
		m_RayId = INVALID_RAY_ID;
	}
}
Exemplo n.º 2
0
void CDeflectorShield::ProcessCollision(const EventPhysCollision& pCollision)
{
	int id = 0;
	IPhysicalEntity* pTarget = pCollision.pEntity[id];
	if (pTarget == GetEntity()->GetPhysics())
	{
		id = 1;
		pTarget = pCollision.pEntity[id];
	}

	IEntity* pTargetEntity = (IEntity*)pTarget->GetForeignData(PHYS_FOREIGN_ID_ENTITY);
	if (pTargetEntity == 0)
		return;

	CProjectile* pProjectile = g_pGame->GetWeaponSystem()->GetProjectile(pTargetEntity->GetId());

	if (pProjectile)
		ProcessProjectile(pProjectile, pCollision.pt, pCollision.n, pCollision.vloc[id].GetNormalized());
}
Exemplo n.º 3
0
//------------------------------------------------------------------------
IEntity *CWorkOnTarget::CanWork()
{
	static Vec3 pos,dir; 
	static ICVar* pAimDebug = gEnv->pConsole->GetCVar("g_aimdebug");
	
	CActor *pActor=m_pWeapon->GetOwnerActor();
	
	static IPhysicalEntity* pSkipEntities[10];
	int nSkip = CSingle::GetSkipEntities(m_pWeapon, pSkipEntities, 10);

	IEntity *pEntity=0;
	float range=m_workparams.range;
	
	IMovementController * pMC = pActor ? pActor->GetMovementController() : 0;
	if (pMC)
	{ 
		SMovementState info;
		pMC->GetMovementState(info);

		pos = info.weaponPosition;

		if (!pActor->IsPlayer())
		{
			dir = range * (info.fireTarget-pos).normalized();
		}
		else
		{
			dir = range * info.fireDirection;    

			// marcok: leave this alone
			if (g_pGameCVars->goc_enable && pActor->IsClient())
			{
				CPlayer *pPlayer = (CPlayer*)pActor;
				pos = pPlayer->GetViewMatrix().GetTranslation();
			}
		}
	}
	else
	{ 
		assert(0);
	}

	primitives::sphere sphere;
	sphere.center = pos;
	sphere.r = m_workparams.radius;
	Vec3 end = pos+dir;

	geom_contact *pContact=0;
	float dst=gEnv->pPhysicalWorld->PrimitiveWorldIntersection(sphere.type, &sphere, end-sphere.center, ent_all,
		&pContact, 0, (geom_colltype_player<<rwi_colltype_bit)|rwi_stop_at_pierceable, 0, 0, 0, pSkipEntities, nSkip);

	if (pContact && dst>=0.0f)
	{
		IPhysicalEntity *pCollider = gEnv->pPhysicalWorld->GetPhysicalEntityById(pContact->iPrim[0]);

		if(pCollider && pCollider->GetiForeignData() == PHYS_FOREIGN_ID_ENTITY)
		{
			if (pEntity = static_cast<IEntity *>(pCollider->GetForeignData(PHYS_FOREIGN_ID_ENTITY)))
			{
				if (CGameRules *pGameRules=g_pGame->GetGameRules())
				{
					if (IScriptTable *pScriptTable=pGameRules->GetEntity()->GetScriptTable())
					{
						HSCRIPTFUNCTION pfnCanWork=0;
						if (pScriptTable->GetValueType("CanWork")==svtFunction && pScriptTable->GetValue("CanWork", pfnCanWork))
						{
							bool result=false;
							Script::CallReturn(gEnv->pScriptSystem, pfnCanWork, pScriptTable, ScriptHandle(pEntity->GetId()), ScriptHandle(m_pWeapon->GetOwnerId()), m_workparams.work_type.c_str(), result);
							gEnv->pScriptSystem->ReleaseFunc(pfnCanWork);

							if (result)
								return pEntity;
						}
					}
				}
			}
		}
	}

	return 0;
}
Exemplo n.º 4
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());
								}
							}
						}
					}
				}
			}
		}
	}
Exemplo n.º 5
0
//--------------------------------------------------------------------------------------------------
// Name: HandleImpact
// Desc: Passes an impact on to the simulation
//--------------------------------------------------------------------------------------------------
int CBreakableGlassSystem::HandleImpact(const EventPhys* pPhysEvent)
{
	if (CCryAction* pCryAction = CCryAction::GetCryAction())
	{
		if (CBreakableGlassSystem* pGlassSystem = static_cast<CBreakableGlassSystem*>(pCryAction->GetIBreakableGlassSystem()))
		{
			pGlassSystem->AssertUnusedIfDisabled();

			if (pGlassSystem->m_enabled)
			{
				if (const EventPhysCollision* pCollEvent = static_cast<const EventPhysCollision*>(pPhysEvent))
				{
					// Glass fragments always get destroyed on their first collision
					const uint physFrag = (pCollEvent->iForeignData[0] == PHYS_FOREIGN_ID_BREAKABLE_GLASS_FRAGMENT) ? 0 : 1;
					IPhysicalEntity* pPhysEnt = pCollEvent->pEntity[physFrag];

					if (pPhysEnt && pCollEvent->iForeignData[physFrag] == PHYS_FOREIGN_ID_BREAKABLE_GLASS_FRAGMENT)
					{
						// Fragments only collide with non-glass geometry
						const int nonFragType = pCollEvent->iForeignData[1-physFrag];

						if (nonFragType != PHYS_FOREIGN_ID_BREAKABLE_GLASS
							&& nonFragType != PHYS_FOREIGN_ID_BREAKABLE_GLASS_FRAGMENT
							&& nonFragType != PHYS_FOREIGN_ID_ENTITY) // Only break on floors, walls, etc.
						{
							// Verify parent glass node, then allow it to handle impact
							if (SGlassPhysFragment* pPhysFrag = (SGlassPhysFragment*)pCollEvent->pForeignData[physFrag])
							{
								if (IBreakableGlassRenderNode* pRenderNode = (IBreakableGlassRenderNode*)pPhysFrag->m_pRenderNode)
								{
									pRenderNode->DestroyPhysFragment(pPhysFrag);
								}
							}	
						}	
					}
					else if (pCollEvent->iForeignData[PHYSEVENT_COLLIDEE] == PHYS_FOREIGN_ID_BREAKABLE_GLASS)
					{
						// Get breakable glass data
						PodArray<IBreakableGlassRenderNode*>& glassPlanes = pGlassSystem->m_glassPlanes;
						const int numPlanes = glassPlanes.Count();

						// Duplicate event so we can freely manipulate it
						EventPhysCollision dupeEvent = *pCollEvent;
						const EventPhysCollision* pDupeEvent = (const EventPhysCollision*)&dupeEvent;

						// Some actors can force breaks for gameplay reasons
						IPhysicalEntity* pCollider = dupeEvent.pEntity[PHYSEVENT_COLLIDER];

						if (pCollider && pCollider->GetType() == PE_LIVING)
						{
							IEntity* pColliderEntity = (IEntity*)pCollider->GetForeignData(PHYS_FOREIGN_ID_ENTITY);
							IActor* pActor = pColliderEntity ? gEnv->pGame->GetIGameFramework()->GetIActorSystem()->GetActor(pColliderEntity->GetId()) : NULL;

							if (pActor && pActor->MustBreakGlass())
							{
								pGlassSystem->ModifyEventToForceBreak(&dupeEvent);
							}		
						}

						// Verify glass node and pass impact through
						IBreakableGlassRenderNode* pRenderNode = (IBreakableGlassRenderNode*)pCollEvent->pForeignData[PHYSEVENT_COLLIDEE];
						const int targetId = pRenderNode ? pRenderNode->GetId() : numPlanes;

						if (targetId < numPlanes && pRenderNode == glassPlanes[targetId])
						{
							pGlassSystem->PassImpactToNode(pRenderNode, pDupeEvent);
						}
					}
				}
			}
		}
	}

	return 1; // Pass event to other handlers even if we processed it
}//-------------------------------------------------------------------------------------------------