void WaterEffects::addWaterSplash(const Vec2f &pos, int size){ for(int i=0; i<waterSplashes.size(); ++i){ if(!waterSplashes[i].getEnabled()){ waterSplashes[i]= WaterSplash(pos,size); return; } } waterSplashes.push_back(WaterSplash(pos,size)); }
void obj_Grenade::onExplode() { // if owner disappeared, do nothing. const GameObject* owner = GameWorld().GetObject(ownerID); if(!owner) return; bool closeToGround = false; PxRaycastHit hit; PxSceneQueryFilterData filter(PxFilterData(COLLIDABLE_STATIC_MASK, 0, 0, 0), PxSceneQueryFilterFlag::eSTATIC); if(g_pPhysicsWorld->raycastSingle(PxVec3(GetPosition().x, GetPosition().y+1, GetPosition().z), PxVec3(0, -1, 0), 50.0f, PxSceneQueryFlag::eDISTANCE, hit, filter)) { if(hit.distance < 5.0f) closeToGround = true; } if(closeToGround) { // add decal DecalParams params; params.Dir = lastCollisionNormal; params.Pos = GetPosition(); params.TypeID = GetDecalID( r3dHash::MakeHash(""), r3dHash::MakeHash(m_Weapon->m_PrimaryAmmo->getDecalSource()) ); if( params.TypeID != INVALID_DECAL_ID ) g_pDecalChief->Add( params ); } //check for underwater splash r3dPoint3D waterSplashPos; extern bool TraceWater(const r3dPoint3D& start, const r3dPoint3D& finish, r3dPoint3D& waterSplashPos); if( TraceWater( GetPosition() - r3dPoint3D(0.0f, m_Weapon->m_AmmoArea, 0.0f), GetPosition() + r3dPoint3D(0.0f, m_Weapon->m_AmmoArea, 0.0f), waterSplashPos)) { SpawnImpactParticle(r3dHash::MakeHash("Water"), r3dHash::MakeHash(m_Weapon->m_PrimaryAmmo->getDecalSource()), waterSplashPos, r3dPoint3D(0,1,0)); extern void WaterSplash(const r3dPoint3D& waterSplashPos, float height, float size, float amount, int texIdx); WaterSplash(GetPosition(), m_Weapon->m_AmmoArea, 10.0f/m_Weapon->m_AmmoArea, 0.04f, 1); } SpawnImpactParticle(r3dHash::MakeHash(""), r3dHash::MakeHash(m_Weapon->m_PrimaryAmmo->getDecalSource()), GetPosition(), r3dPoint3D(0,1,0)); // Start radial blur effect gExplosionVisualController.AddExplosion(GetPosition(), m_Weapon->m_AmmoArea); // for now hard coded for flash bang grenade if(m_Weapon->m_itemID == 101137) { // only apply flashbank for local player if(gClientLogic().localPlayer_ && !gClientLogic().localPlayer_->bDead) { // check that player can actually see explosion (need better test, for when explosion is behind wall) bool explosionVisible = r3dRenderer->IsSphereInsideFrustum(GetPosition(), 2.0f)>0; if(explosionVisible) { float radiusAdd = 0.0f; float durationAdd = 0.0f; float dist = (GetPosition()-gClientLogic().localPlayer_->GetPosition()).Length(); float str = 1.0f - R3D_CLAMP(dist / (GPP->c_fFlashBangRadius+radiusAdd), 0.0f, 1.0f); if (str > 0.01f) { FlashBangEffectParams fbep; fbep.duration = (GPP->c_fFlashBangDuration+durationAdd) * str; fbep.pos = GetPosition(); gFlashbangVisualController.StartEffect(fbep); } } } } // do damage only if owner is local player, otherwise we will broadcast damage multiple times r3d_assert(owner); if(owner->NetworkLocal) { gClientLogic().ApplyExplosionDamage(GetPosition(), m_Weapon->m_AmmoArea, 0, r3dVector(0,0,0), 360.0f); } setActiveFlag(0); #if APEX_ENABLED // Apply apex destructions g_pApexWorld->ApplyAreaDamage(m_Weapon->m_AmmoDamage * 0.01f, 1, GetPosition(), m_Weapon->m_AmmoArea, true); #endif }