//-------------------------------------------------------------------------------------------------- // Name: SpawnMaterialEffect // Desc: Spawns material effect //-------------------------------------------------------------------------------------------------- void CExplosionGameEffect::SpawnMaterialEffect(const SExplosionContainer &explosionContainer) { // Disclaimer: this code was originally from GameRulesClientServer::ProcessExplosionMaterialFX() const ExplosionInfo& explosionInfo = explosionContainer.m_explosionInfo; // impact stuff here SMFXRunTimeEffectParams params; //params.soundSemantic = eSoundSemantic_Explosion; params.pos = params.decalPos = explosionInfo.pos; params.trg = 0; params.trgRenderNode = 0; params.trgSurfaceId = 0; if(explosionInfo.impact && (explosionInfo.impact_velocity.len2() > 0.000001f)) { params.dir[0] = explosionInfo.impact_velocity.normalized(); params.normal = explosionInfo.impact_normal; } else { const Vec3 gravityDir = Vec3(0.0f, 0.0f, -1.0f); params.dir[0] = gravityDir; params.normal = -gravityDir; } const SDeferredMfxExplosion& mfxInfo = explosionContainer.m_mfxInfo; if(mfxInfo.m_state == eDeferredMfxExplosionState_ResultImpact) { params.trgSurfaceId = mfxInfo.m_mfxTargetSurfaceId; if (mfxInfo.m_pMfxTargetPhysEnt.get()) { if (mfxInfo.m_pMfxTargetPhysEnt->GetiForeignData() == PHYS_FOREIGN_ID_STATIC) { params.trgRenderNode = (IRenderNode*)mfxInfo.m_pMfxTargetPhysEnt->GetForeignData(PHYS_FOREIGN_ID_STATIC); } } } // Create query name stack_string effectClass = explosionInfo.effect_class; if(effectClass.empty()) effectClass = "generic"; const float waterLevel = gEnv->p3DEngine->GetWaterLevel(¶ms.pos); stack_string query = effectClass + "_explode"; if(waterLevel > explosionInfo.pos.z) query = query + "_underwater"; // Get material effect id IMaterialEffects* pMaterialEffects = gEnv->pGame->GetIGameFramework()->GetIMaterialEffects(); TMFXEffectId effectId = pMaterialEffects->GetEffectId(query.c_str(), params.trgSurfaceId); if(effectId == InvalidEffectId) { // Get default surface id effectId = pMaterialEffects->GetEffectId(query.c_str(), pMaterialEffects->GetDefaultSurfaceIndex()); } // Execute material effect if(effectId != InvalidEffectId) { pMaterialEffects->ExecuteEffect(effectId, params); bool hasFlashBangEffect = explosionInfo.blindAmount > 0.0f; if(hasFlashBangEffect) { // Calc screen pos Vec3 screenspace; gEnv->pRenderer->ProjectToScreen(explosionInfo.pos.x, explosionInfo.pos.y, explosionInfo.pos.z, &screenspace.x, &screenspace.y, &screenspace.z); // Pass screen pos to flow graph node SMFXCustomParamValue paramPosX; paramPosX.fValue = screenspace.x*0.01f; pMaterialEffects->SetCustomParameter(effectId,"Intensity",paramPosX); // Use intensity param to pass x pos SMFXCustomParamValue paramPosY; paramPosY.fValue = screenspace.y*0.01f; pMaterialEffects->SetCustomParameter(effectId,"BlendOutTime",paramPosY); // Use blendOutTime param to pass y pos } } }//-------------------------------------------------------------------------------------------------
void CPlayerStateJump::Landed(CPlayer& player, const bool isHeavyWeapon, float fallSpeed) { #ifdef STATE_DEBUG bool remoteControlled = false; IVehicle* pVehicle = player.GetLinkedVehicle(); if(pVehicle) { IVehicleSeat* pVehicleSeat = pVehicle->GetSeatForPassenger(player.GetEntityId()); if(pVehicleSeat && pVehicleSeat->IsRemoteControlled()) { remoteControlled = true; } } CRY_ASSERT_MESSAGE( player.GetLinkedEntity()==NULL || remoteControlled, "Cannot 'land' when you're linked to another entity!" ); #endif const SPlayerStats& stats = player.m_stats; Vec3 playerPosition = player.GetEntity()->GetWorldPos(); IPhysicalEntity *phys = player.GetEntity()->GetPhysics(); IMaterialEffects *mfx = gEnv->pGame->GetIGameFramework()->GetIMaterialEffects(); const SActorPhysics& actorPhysics = player.GetActorPhysics(); int matID = actorPhysics.groundMaterialIdx != -1 ? actorPhysics.groundMaterialIdx : mfx->GetDefaultSurfaceIndex(); const float fHeightofEntity = playerPosition.z; const float worldWaterLevel = player.m_playerStateSwim_WaterTestProxy.GetWaterLevel(); TMFXEffectId effectId = mfx->GetEffectId("bodyfall", matID); if (effectId != InvalidEffectId) { SMFXRunTimeEffectParams params; Vec3 direction = Vec3(0,0,0); if (IMovementController *pMV = player.GetMovementController()) { SMovementState state; pMV->GetMovementState(state); direction = state.aimDirection; } params.pos = playerPosition + direction; //params.soundSemantic = eSoundSemantic_Player_Foley; float landFallParamVal = (float)__fsel( -(fallSpeed - 7.5f), 0.25f, 0.75f); params.AddAudioRtpc("landfall", landFallParamVal); const float speedParamVal = min(fabsf((actorPhysics.velocity.z * 0.1f)), 1.0f); params.AddAudioRtpc("speed", speedParamVal); mfx->ExecuteEffect(effectId, params); } bool heavyLanded = false; IItem* pCurrentItem = player.GetCurrentItem(); CWeapon* pCurrentWeapon = pCurrentItem ? static_cast<CWeapon*>(pCurrentItem->GetIWeapon()) : NULL; if (fallSpeed > 0.0f && player.IsPlayer()) { if(!gEnv->bMultiplayer) { const float verticalSpeed = fabs(fallSpeed); const float speedForHeavyLand = g_pGameCVars->pl_health.fallSpeed_HeavyLand; if ((verticalSpeed >= speedForHeavyLand) && (player.GetPickAndThrowEntity() == 0) && !player.IsDead()) { if ( !isHeavyWeapon ) { if (pCurrentWeapon) { pCurrentWeapon->FumbleGrenade(); pCurrentWeapon->CancelCharge(); } player.StartInteractiveActionByName("HeavyLand", false); } heavyLanded = true; } } } if(player.m_isClient) { if (fallSpeed > 0.0f) { const float fallIntensityMultiplier = stats.wasHit ? g_pGameCVars->pl_fall_intensity_hit_multiplier : g_pGameCVars->pl_fall_intensity_multiplier; const float fallIntensityMax = g_pGameCVars->pl_fall_intensity_max; const float fallTimeMultiplier = g_pGameCVars->pl_fall_time_multiplier; const float fallTimeMax = g_pGameCVars->pl_fall_time_max; const float zoomMultiplayer = (pCurrentWeapon && pCurrentWeapon->IsZoomed()) ? 0.2f : 1.0f; const float direction = ((cry_rand()%2)==0) ? -1.0f : 1.0f; const float intensity = clamp_tpl(fallIntensityMultiplier*fallSpeed*zoomMultiplayer, 0.0f, fallIntensityMax); const float shakeTime = clamp_tpl(fallTimeMultiplier*fallSpeed*zoomMultiplayer, 0.0f, fallTimeMax); const Vec3 rotation = Vec3(-0.5f, 0.15f*direction, 0.05f*direction); if (CScreenEffects* pGameScreenEffects = g_pGame->GetScreenEffects()) { pGameScreenEffects->CamShake(rotation*intensity, Vec3(0, 0, 0), shakeTime, shakeTime, 0.05f, CScreenEffects::eCS_GID_Player); } IForceFeedbackSystem* pForceFeedback = g_pGame->GetIGameFramework()->GetIForceFeedbackSystem(); assert(pForceFeedback); ForceFeedbackFxId fxId = pForceFeedback->GetEffectIdByName("landFF"); pForceFeedback->PlayForceFeedbackEffect(fxId, SForceFeedbackRuntimeParams(intensity, 0.0f)); if(fallSpeed > 7.0f) { player.PlaySound(CPlayer::ESound_Fall_Drop); } CPlayer::EPlayerSounds playerSound = heavyLanded ? CPlayer::ESound_Gear_HeavyLand : CPlayer::ESound_Gear_Land; player.PlaySound(playerSound, true); } CCCPOINT(PlayerMovement_LocalPlayerLanded); } if( gEnv->pAISystem ) { // Notify AI //If silent feet active, ignore here const float noiseSupression = 0.0f; const float fAISoundRadius = (g_pGameCVars->ai_perception.landed_baseRadius + (g_pGameCVars->ai_perception.landed_speedMultiplier * fallSpeed)) * (1.0f - noiseSupression); SAIStimulus stim(AISTIM_SOUND, AISOUND_MOVEMENT_LOUD, player.GetEntityId(), 0, player.GetEntity()->GetWorldPos() + player.GetEyeOffset(), ZERO, fAISoundRadius); gEnv->pAISystem->RegisterStimulus(stim); } // Record 'Land' telemetry stats. CStatsRecordingMgr::TryTrackEvent(&player, eGSE_Land, fallSpeed); if (fallSpeed > 0.0f) { player.CreateScriptEvent( heavyLanded ? "heavylanded" : "landed",stats.fallSpeed); } }
//--------------------------------------------------- void CGameRules::ProcessExplosionMaterialFX(const ExplosionInfo &explosionInfo) { // if an effect was specified, don't use MFX if (explosionInfo.pParticleEffect) return; // impact stuff here SMFXRunTimeEffectParams params; params.soundSemantic = eSoundSemantic_Explosion; params.pos = params.decalPos = explosionInfo.pos; params.trg = 0; params.trgRenderNode = 0; Vec3 gravity; pe_params_buoyancy buoyancy; gEnv->pPhysicalWorld->CheckAreas(params.pos, gravity, &buoyancy); // 0 for water, 1 for air Vec3 pos=params.pos; params.inWater = (buoyancy.waterPlane.origin.z > params.pos.z) && (gEnv->p3DEngine->GetWaterLevel(&pos)>=params.pos.z); params.inZeroG = (gravity.len2() < 0.0001f); params.trgSurfaceId = 0; static const int objTypes = ent_all; static const unsigned int flags = rwi_stop_at_pierceable|rwi_colltype_any; ray_hit ray; if (explosionInfo.impact) { params.dir[0] = explosionInfo.impact_velocity.normalized(); params.normal = explosionInfo.impact_normal; if (gEnv->pPhysicalWorld->RayWorldIntersection(params.pos-params.dir[0]*0.0125f, params.dir[0]*0.25f, objTypes, flags, &ray, 1)) { params.trgSurfaceId = ray.surface_idx; if (ray.pCollider->GetiForeignData()==PHYS_FOREIGN_ID_STATIC) params.trgRenderNode = (IRenderNode*)ray.pCollider->GetForeignData(PHYS_FOREIGN_ID_STATIC); } } else { params.dir[0] = gravity; params.normal = -gravity.normalized(); if (gEnv->pPhysicalWorld->RayWorldIntersection(params.pos, gravity, objTypes, flags, &ray, 1)) { params.trgSurfaceId = ray.surface_idx; if (ray.pCollider->GetiForeignData()==PHYS_FOREIGN_ID_STATIC) params.trgRenderNode = (IRenderNode*)ray.pCollider->GetForeignData(PHYS_FOREIGN_ID_STATIC); } } string effectClass = explosionInfo.effect_class; if (effectClass.empty()) effectClass = "generic"; string query = effectClass + "_explode"; if(gEnv->p3DEngine->GetWaterLevel(&explosionInfo.pos)>explosionInfo.pos.z) query = query + "_underwater"; IMaterialEffects* pMaterialEffects = gEnv->pGame->GetIGameFramework()->GetIMaterialEffects(); TMFXEffectId effectId = pMaterialEffects->GetEffectId(query.c_str(), params.trgSurfaceId); if (effectId == InvalidEffectId) effectId = pMaterialEffects->GetEffectId(query.c_str(), pMaterialEffects->GetDefaultSurfaceIndex()); if (effectId != InvalidEffectId) pMaterialEffects->ExecuteEffect(effectId, params); }
//------------------------------------------------------------------------ void CTornado::Update(SEntityUpdateContext &ctx, int updateSlot) { if (g_pGame->GetIGameFramework()->IsEditing()) return; // wandering Matrix34 m = GetEntity()->GetWorldTM(); Vec3 dir(m.GetColumn(1)); Vec3 pos(GetEntity()->GetWorldPos()); if(!gEnv->bServer) pos = m_currentPos; Vec3 wanderPos(dir * 1.414214f); float wanderStrength(1.0f); float wanderRate(0.6f); Vec3 wanderOffset; wanderOffset.SetRandomDirection(); wanderOffset.z = 0.0f; wanderOffset.NormalizeSafe(Vec3(1,0,0)); m_wanderDir += wanderOffset * wanderRate + (m_wanderDir - wanderPos) * wanderStrength; m_wanderDir = (m_wanderDir - wanderPos).GetNormalized() + wanderPos; Vec3 wanderSteer = (dir + m_wanderDir * gEnv->pTimer->GetFrameTime()); wanderSteer.z = 0; wanderSteer.NormalizeSafe(Vec3(1,0,0)); Vec3 targetSteer(0,0,0); // go to target if (m_pTargetEntity) { Vec3 target = m_pTargetEntity->GetWorldPos() - pos; if (target.GetLength() < 10.0f) { // emit target reached event SEntityEvent event( ENTITY_EVENT_SCRIPT_EVENT ); event.nParam[0] = (INT_PTR)"TargetReached"; event.nParam[1] = IEntityClass::EVT_BOOL; bool bValue = true; event.nParam[2] = (INT_PTR)&bValue; GetEntity()->SendEvent( event ); if (m_pTargetCallback) m_pTargetCallback->Done(); m_pTargetEntity = 0; m_pTargetCallback = 0; } targetSteer = (target - dir); targetSteer.z = 0; targetSteer.NormalizeSafe(Vec3(1,0,0)); } Vec3 steerDir = (0.4f * wanderSteer + 0.6f * targetSteer).GetNormalized(); Matrix34 tm = Matrix34(Matrix33::CreateRotationVDir(steerDir)); pos = pos + steerDir * gEnv->pTimer->GetFrameTime() * m_wanderSpeed; pos.z = gEnv->p3DEngine->GetTerrainElevation(pos.x, pos.y); float waterLevel = gEnv->p3DEngine->GetWaterLevel(&pos); bool prevIsOnWater = m_isOnWater; m_isOnWater = (pos.z < waterLevel); if (m_isOnWater) { pos.z = waterLevel; } // raycast does not work for oceans if (prevIsOnWater != m_isOnWater && m_isOnWater) { m_pGroundEffect->SetParticleEffect("weather.tornado.water"); } else if (!m_isOnWater) { IMaterialEffects *mfx = gEnv->pGame->GetIGameFramework()->GetIMaterialEffects(); Vec3 down = Vec3(0,0,-1.0f); int matID = mfx->GetDefaultSurfaceIndex(); static const int objTypes = ent_all; static const unsigned int flags = rwi_stop_at_pierceable|rwi_colltype_any; ray_hit hit; int col = gEnv->pPhysicalWorld->RayWorldIntersection(pos, (down * 5.0f), objTypes, flags, &hit, 1, GetEntity()->GetPhysics()); if (col) { matID = hit.surface_idx; } if (m_curMatID != matID) { TMFXEffectId effectId = mfx->GetEffectId("tornado", matID); SMFXResourceListPtr pList = mfx->GetResources(effectId); if (pList && pList->m_particleList) { m_pGroundEffect->SetParticleEffect(pList->m_particleList->m_particleParams.name); } m_curMatID = matID; } } if(gEnv->bServer) { tm.SetTranslation(pos); m_currentPos = pos; CHANGED_NETWORK_STATE(this, POSITION_ASPECT); GetEntity()->SetWorldTM(tm); } else { tm.SetTranslation(m_currentPos); GetEntity()->SetWorldTM(tm); } UpdateParticleEmitters(); UpdateTornadoSpline(); UpdateFlow(); }