//------------------------------------------------------------------------ void CGameRules::CullEntitiesInExplosion(const ExplosionInfo &explosionInfo) { if (!g_pGameCVars->g_ec_enable || explosionInfo.damage <= 0.1f) return; IPhysicalEntity **pents; float radiusScale = g_pGameCVars->g_ec_radiusScale; float minVolume = g_pGameCVars->g_ec_volume; float minExtent = g_pGameCVars->g_ec_extent; int removeThreshold = max(1, g_pGameCVars->g_ec_removeThreshold); IActor *pClientActor = g_pGame->GetIGameFramework()->GetClientActor(); Vec3 radiusVec(radiusScale * explosionInfo.physRadius); int i = gEnv->pPhysicalWorld->GetEntitiesInBox(explosionInfo.pos-radiusVec,explosionInfo.pos+radiusVec,pents, ent_rigid|ent_sleeping_rigid); int removedCount = 0; static IEntityClass* s_pInteractiveEntityClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass("InteractiveEntity"); static IEntityClass* s_pDeadBodyClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass("DeadBody"); if (i > removeThreshold) { int entitiesToRemove = i - removeThreshold; for(--i;i>=0;i--) { if(removedCount>=entitiesToRemove) break; IEntity * pEntity = (IEntity*) pents[i]->GetForeignData(PHYS_FOREIGN_ID_ENTITY); if (pEntity) { // don't remove if entity is held by the player if (pClientActor && pEntity->GetId()==pClientActor->GetGrabbedEntityId()) continue; // don't remove items/pickups if (IItem* pItem = g_pGame->GetIGameFramework()->GetIItemSystem()->GetItem(pEntity->GetId())) { continue; } // don't remove enemies/ragdolls if (IActor* pActor = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(pEntity->GetId())) { continue; } // if there is a flowgraph attached, never remove! if (pEntity->GetProxy(ENTITY_PROXY_FLOWGRAPH) != 0) continue; IEntityClass* pClass = pEntity->GetClass(); if (pClass == s_pInteractiveEntityClass || pClass == s_pDeadBodyClass) continue; // get bounding box if (IEntityPhysicalProxy* pPhysProxy = (IEntityPhysicalProxy*)pEntity->GetProxy(ENTITY_PROXY_PHYSICS)) { AABB aabb; pPhysProxy->GetWorldBounds(aabb); // don't remove objects which are larger than a predefined minimum volume if (aabb.GetVolume() > minVolume) continue; // don't remove objects which are larger than a predefined minimum volume Vec3 size(aabb.GetSize().abs()); if (size.x > minExtent || size.y > minExtent || size.z > minExtent) continue; } // marcok: somehow editor doesn't handle deleting non-dynamic entities very well // but craig says, hiding is not synchronized for DX11 breakable MP, so we remove entities only when playing pure game // alexl: in SinglePlayer, we also currently only hide the object because it could be part of flowgraph logic // which would break if Entity was removed and could not propagate events anymore if (gEnv->bMultiplayer == false || gEnv->IsEditor()) { pEntity->Hide(true); } else { gEnv->pEntitySystem->RemoveEntity(pEntity->GetId()); } removedCount++; } } } }
void CTornado::UpdateFlow() { IVehicleSystem* pVehicleSystem = g_pGame->GetIGameFramework()->GetIVehicleSystem(); assert(pVehicleSystem); float frameTime(gEnv->pTimer->GetFrameTime()); IPhysicalWorld *ppWorld = gEnv->pPhysicalWorld; Vec3 pos(GetEntity()->GetWorldPos()); //first, check the entities in range m_nextEntitiesCheck -= frameTime; if (m_nextEntitiesCheck<0.0f) { m_nextEntitiesCheck = 1.0f; Vec3 radiusVec(m_radius,m_radius,0); IPhysicalEntity **ppList = NULL; int numEnts = ppWorld->GetEntitiesInBox(pos-radiusVec,pos+radiusVec+Vec3(0,0,m_cloudHeight*0.5f),ppList,ent_sleeping_rigid|ent_rigid|ent_living); m_spinningEnts.clear(); for (int i=0;i<numEnts;++i) { // add check for spectating players... EntityId id = ppWorld->GetPhysicalEntityId(ppList[i]); CActor* pActor = static_cast<CActor*>(g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(id)); if(!pActor || !pActor->GetSpectatorMode()) { m_spinningEnts.push_back(id); } } //OutputDistance(); } //mess entities around for (size_t i=0;i<m_spinningEnts.size();++i) { IPhysicalEntity *ppEnt = ppWorld->GetPhysicalEntityById(m_spinningEnts[i]); if (ppEnt) { pe_status_pos spos; pe_status_dynamics sdyn; if (!ppEnt->GetStatus(&spos) || !ppEnt->GetStatus(&sdyn)) continue; //gEnv->pRenderer->GetIRenderAuxGeom()->DrawSphere(spos.pos,2.0f,ColorB(255,0,255,255)); Vec3 delta(pos - spos.pos); delta.z = 0.0f; float dLen(delta.len()); float forceMult(max(0.0f,(m_radius-dLen)/m_radius)); if (dLen>0.001f) delta /= dLen; else delta.zero(); Vec3 upVector(0,0,1); float spinImpulse(m_spinImpulse); float attractionImpulse(m_attractionImpulse); float upImpulse(m_upImpulse); if (ppEnt->GetType() == PE_LIVING) { upImpulse *= 0.75f; attractionImpulse *= 0.35f; spinImpulse *= 1.5f; } if (IVehicle* pVehicle = pVehicleSystem->GetVehicle(m_spinningEnts[i])) { IVehicleMovement* pMovement = pVehicle->GetMovement(); if (pMovement && pMovement->GetMovementType() == IVehicleMovement::eVMT_Air) { SVehicleMovementEventParams params; params.fValue = forceMult; pMovement->OnEvent(IVehicleMovement::eVME_Turbulence, params); } } Vec3 spinForce( (delta % upVector) * spinImpulse ); Vec3 attractionForce(delta * attractionImpulse); Vec3 upForce(0,0,upImpulse); pe_action_impulse aimpulse; aimpulse.impulse = (spinForce + attractionForce + upForce) * (forceMult * sdyn.mass * frameTime); aimpulse.angImpulse = (upVector + (delta % upVector)) * (gf_PI * 0.33f * forceMult * sdyn.mass * frameTime); aimpulse.iApplyTime = 0; ppEnt->Action(&aimpulse); //gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine(spos.pos,ColorB(255,0,255,255),spos.pos+aimpulse.impulse.GetNormalizedSafe(ZERO),ColorB(255,0,255,255)); } } }