void CLaserBeam::SetLaserEntitySlots(bool freeSlots) { if(m_pLaserParams) { IEntity* pLaserEntity = GetLaserEntity(); if(pLaserEntity) { if(freeSlots) { if(m_laserDotSlot != -1) pLaserEntity->FreeSlot(m_laserDotSlot); if(m_laserGeometrySlot != -1) pLaserEntity->FreeSlot(m_laserGeometrySlot); m_laserDotSlot = m_laserGeometrySlot = -1; pLaserEntity->DetachThis(); if(m_usingEntityAttachment) { if(IAttachmentManager* pAttachmentManager = GetLaserCharacterAttachmentManager()) { if(IAttachment* pAttachment = pAttachmentManager->GetInterfaceByName(LASER_ATTACH_NAME)) { pAttachment->ClearBinding(); } } } } else { m_laserGeometrySlot = pLaserEntity->LoadGeometry(-1, m_pLaserParams->laser_geometry_tp.c_str()); pLaserEntity->SetSlotFlags(m_laserGeometrySlot, pLaserEntity->GetSlotFlags(m_laserGeometrySlot)|ENTITY_SLOT_RENDER); if (m_pLaserParams->show_dot) { IParticleEffect* pEffect = gEnv->pParticleManager->FindEffect(m_pLaserParams->laser_dot[GetIndexFromGeometrySlot()].c_str()); if(pEffect) m_laserDotSlot = pLaserEntity->LoadParticleEmitter(-1,pEffect); } FixAttachment(pLaserEntity); } } } else { GameWarning("LASER PARAMS: Item of type CLaser is missing it's laser params!"); } }
//------------------------------------------------------------------------ void CVehiclePartParticleEffect::ActivateParticleEffect(bool activate) { IEntity *pEntity = m_pVehicle->GetEntity(); if(activate) { m_slot = pEntity->LoadParticleEmitter(-1, m_pParticleEffect, NULL, false, true); if(m_slot > 0) { SpawnParams spawnParams; spawnParams.fPulsePeriod = 1.0f; pEntity->GetParticleEmitter(m_slot)->SetSpawnParams(spawnParams); if(m_pHelper) { Matrix34 tm; m_pHelper->GetVehicleTM(tm); pEntity->SetSlotLocalTM(m_slot, tm); } } } else if(m_slot > 0) { pEntity->FreeSlot(m_slot); m_slot = -1; } }
//--------------------------------------------------------------------------- void CLam::CreateLaserEntity() { if(m_pLaserEntityId) { //Check if entity is valid IEntity *pEntity = m_pEntitySystem->GetEntity(m_pLaserEntityId); if(!pEntity) m_pLaserEntityId = 0; } if (!m_pLaserEntityId) { SEntitySpawnParams spawnParams; spawnParams.pClass = gEnv->pEntitySystem->GetClassRegistry()->GetDefaultClass(); spawnParams.sName = "LAMLaser"; spawnParams.nFlags = (GetEntity()->GetFlags() | ENTITY_FLAG_NO_SAVE) & ~ENTITY_FLAG_CASTSHADOW; IEntity *pNewEntity =gEnv->pEntitySystem->SpawnEntity(spawnParams); //assert(pNewEntity && "Laser entity could no be spawned!!"); if(pNewEntity) { pNewEntity->FreeSlot(0); pNewEntity->FreeSlot(1); m_pLaserEntityId = pNewEntity->GetId(); if(IEntity* pEntity = GetEntity()) pEntity->AttachChild(pNewEntity); IEntityRenderProxy *pRenderProxy = (IEntityRenderProxy*)pNewEntity->GetProxy(ENTITY_PROXY_RENDER); IRenderNode * pRenderNode = pRenderProxy?pRenderProxy->GetRenderNode():NULL; if(pRenderNode) pRenderNode->SetRndFlags(ERF_RENDER_ALWAYS,true); } } }
//------------------------------------------------------------------------ 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_physStatus[k_mainThread].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); const Vec3& localW = m_localSpeed; 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_factorMaxSpeed)); 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 += cry_random(0.0f, 0.4f); m_wakeSlot = pEntity->LoadParticleEmitter(m_wakeSlot, m_pWaveEffect, &spawnParams); } // handle splash sound ExecuteTrigger(eSID_Splash); 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; }