//------------------------------------------------------------------------ void CVehicleMovementStdBoat::UpdateRunSound(const float deltaTime) { Vec3 localAccel(ZERO); m_measureSpeedTimer+=deltaTime; if (m_measureSpeedTimer > 0.25f) { const Vec3& v = m_physStatus[k_mainThread].v; Vec3 accel = (v - m_lastMeasuredVel) * (1.f/m_measureSpeedTimer); localAccel = accel * m_physStatus[k_mainThread].q; m_lastMeasuredVel = v; m_measureSpeedTimer = 0.f; } if (m_pVehicle->IsProbablyDistant()) return; // rpm dropdown for waves if (m_rpmPitchDir != 0) { float speed = (m_rpmPitchDir > 0) ? 0.1f : -0.8f; // quick down, slow up m_waveSoundPitch += deltaTime * speed; if (m_waveSoundPitch < -m_waveSoundAmount) // dropdown amount { m_waveSoundPitch = -m_waveSoundAmount; m_rpmPitchDir = 1; } else if (m_waveSoundPitch > 0.f) { m_waveSoundPitch = 0.f; m_rpmPitchDir = 0; } } if (m_rpmPitchSpeed>0.f) { const float maxPedal = (!m_inWater) ? 1.f : Boosting() ? 0.8f : 0.7f; // pitch rpm with pedal float pedal = GetEnginePedal(); pedal = sgnnz(pedal)*max(ms_engineSoundIdleRatio, min(maxPedal, abs(pedal))); // clamp "pedal" to [0.2..0.7] range float delta = pedal - m_rpmScaleSgn; m_rpmScaleSgn = max(-1.f, min(1.f, m_rpmScaleSgn + sgn(delta)*min(abs(delta), m_rpmPitchSpeed*deltaTime))); // skip transition around 0 when on pedal (sounds more realistic) if (abs(GetEnginePedal()) > 0.001f && abs(delta) > 0.001f && sgn(m_rpmScaleSgn) != sgn(delta) && abs(m_rpmScaleSgn) <= 0.3f) m_rpmScaleSgn = sgn(delta)*0.3f; // for normal driving, rpm is clamped at max defined by sound dept m_rpmScale = abs(m_rpmScaleSgn); m_rpmScale = min(1.f, max(ms_engineSoundIdleRatio, m_rpmScale + m_waveSoundPitch)); m_pIEntityAudioProxy->SetRtpcValue(m_audioControlIDs[eSID_VehicleRPM], m_rpmScale); } }
//------------------------------------------------------------------------ bool CGunTurret::GetTargetAngles(const Vec3 &targetPos, float &z, float &x) const { // turret rotation reachability check Vec3 weaponPos = GetWeaponPos(); Vec3 targetDir = targetPos - weaponPos; if(targetDir.len2() < minLenSqr) return false; // local dir to target Vec3 targetDirLocal = GetEntity()->GetWorldTM().GetInverted().TransformVector(targetDir); // angle around z Vec3 targetDirZ(targetDirLocal.x, targetDirLocal.y, 0.f); if(targetDirZ.len2() < minLenSqr) z = 0.f; else { targetDirZ.Normalize(); float cosZ = max(-1.f, min(1.f, FORWARD_DIRECTION * targetDirZ)); z = acos_tpl(cosZ) * -sgnnz(targetDirZ.x); if(z<0.0f) z+=gf_PI2; } // angle around x Vec3 targetDirX(targetDirLocal); Vec3 targetDirBase(targetDirLocal.x, targetDirLocal.y, 0); if(targetDirBase.len2() < minLenSqr) x = 0.0f; else { targetDirX.Normalize(); targetDirBase.Normalize(); float cosX = max(-1.f, min(1.f, targetDirBase * targetDirX)); x = acos_tpl(cosX) * sgnnz(targetDirX.z); } return true; }
//---------------------------------------------------------------------------- void CHomingMissile::UpdateCruiseMissile(float frameTime) { IRenderer* pRenderer = gEnv->pRenderer; IRenderAuxGeom* pGeom = pRenderer->GetIRenderAuxGeom(); float color[4] = {1,1,1,1}; const static float step = 15.f; float y = 20.f; bool bDebug = g_pGameCVars->i_debug_projectiles > 0; if (m_targetId) { IEntity* pTarget = gEnv->pEntitySystem->GetEntity(m_targetId); if (pTarget) { AABB box; pTarget->GetWorldBounds(box); SetDestination( box.GetCenter() ); //if (bDebug) //pRenderer->Draw2dLabel(5.0f, y+=step, 1.5f, color, false, "Target Entity: %s", pTarget->GetName()); } } else { // update destination pos from weapon static IItemSystem* pItemSystem = g_pGame->GetIGameFramework()->GetIItemSystem(); IItem* pItem = pItemSystem->GetItem(m_weaponId); if (pItem && pItem->GetIWeapon()) { const Vec3& dest = pItem->GetIWeapon()->GetDestination(); SetDestination( dest ); //if (bDebug) //pRenderer->Draw2dLabel(5.0f, y+=step, 1.5f, color, false, "Weapon Destination: (%.1f %.1f %.1f)", dest.x, dest.y, dest.z); } } pe_status_dynamics status; if (!GetEntity()->GetPhysics()->GetStatus(&status)) return; float currentSpeed = status.v.len(); Vec3 currentPos = GetEntity()->GetWorldPos(); Vec3 goalDir(ZERO); if (!m_destination.IsZero()) { if((currentPos-m_destination).len2()<(m_detonationRadius*m_detonationRadius)) { Explode(true, true, m_destination, -status.v.normalized(), status.v, m_targetId); return; } if (bDebug) pGeom->DrawCone(m_destination, Vec3(0,0,-1), 2.5f, 7.f, ColorB(255,0,0,255)); float heightDiff = (m_cruiseAltitude-m_alignAltitude) - currentPos.z; if (!m_isCruising && heightDiff * sgn(status.v.z) > 0.f) { // if heading towards align altitude (but not yet reached) accelerate to max speed if (bDebug) pRenderer->Draw2dLabel(5.0f, y+=step, 1.5f, color, false, "[HomingMissile] accelerating (%.1f / %.1f)", currentSpeed, m_maxSpeed); } else if (!m_isCruising && heightDiff * sgnnz(status.v.z) < 0.f && (status.v.z<0 || status.v.z>0.25f)) { // align to cruise if (currentSpeed != 0) { goalDir = status.v; goalDir.z = 0; goalDir.normalize(); } if (bDebug) pRenderer->Draw2dLabel(5.0f, y+=step, 1.5f, color, false, "[HomingMissile] aligning"); } else { if (bDebug) pRenderer->Draw2dLabel(5.0f, y+=step, 1.5f, color, false, "[HomingMissile] cruising..."); // cruise m_isCruising = true; if (!m_destination.IsZero()) { float groundDistSq = m_destination.GetSquaredDistance2D(currentPos); float distSq = m_destination.GetSquaredDistance(currentPos); float descendDistSq = sqr(m_descendDistance); if (m_isDescending || groundDistSq <= descendDistSq) { if (bDebug) pRenderer->Draw2dLabel(5.0f, y+=step, 1.5f, color, false, "[HomingMissile] descending!"); if (distSq != 0) goalDir = (m_destination - currentPos).normalized(); else goalDir.zero(); m_isDescending = true; } else { Vec3 airPos = m_destination; airPos.z = currentPos.z; goalDir = airPos - currentPos; if (goalDir.len2() != 0) goalDir.Normalize(); } } } } float desiredSpeed = currentSpeed; if (currentSpeed < m_maxSpeed-0.1f) { desiredSpeed = min(m_maxSpeed, desiredSpeed + m_accel*frameTime); } Vec3 currentDir = status.v.GetNormalizedSafe(FORWARD_DIRECTION); Vec3 dir = currentDir; if (!goalDir.IsZero()) { float cosine = max(min(currentDir.Dot(goalDir), 0.999f), -0.999f); float goalAngle = RAD2DEG(acos_tpl(cosine)); float maxAngle = m_turnSpeed * frameTime; if (bDebug) { pGeom->DrawCone( currentPos, goalDir, 0.4f, 12.f, ColorB(255,0,0,255) ); pRenderer->Draw2dLabel(5.0f, y+=step, 1.5f, color, false, "[HomingMissile] goalAngle: %.2f", goalAngle); } if (goalAngle > maxAngle+0.05f) dir = (Vec3::CreateSlerp(currentDir, goalDir, maxAngle/goalAngle)).normalize(); else //if (goalAngle < 0.005f) dir = goalDir; } pe_action_set_velocity action; action.v = dir * desiredSpeed; GetEntity()->GetPhysics()->Action(&action); if (bDebug) { pGeom->DrawCone( currentPos, dir, 0.4f, 12.f, ColorB(128,128,0,255) ); pRenderer->Draw2dLabel(5.0f, y+=step, 1.5f, color, false, "[HomingMissile] currentSpeed: %.1f (max: %.1f)", currentSpeed, m_maxSpeed); } }
//------------------------------------------------------------------------ void CVehicleMovementStdBoat::UpdateRunSound(const float deltaTime) { Vec3 localAccel(ZERO); m_measureSpeedTimer+=deltaTime; if(m_measureSpeedTimer > 0.25f) { Vec3 accel = (m_statusDyn.v - m_lastMeasuredVel) * (1.f/m_measureSpeedTimer); Matrix33 worldTM(!m_statusPos.q); localAccel = worldTM * accel; m_lastMeasuredVel = m_statusDyn.v; m_measureSpeedTimer = 0.f; } if(m_pVehicle->IsProbablyDistant()) return; float soundSpeedRatio = ms_engineSoundIdleRatio + (1.f-ms_engineSoundIdleRatio) * m_speedRatio; SetSoundParam(eSID_Run, "speed", soundSpeedRatio); SetSoundParam(eSID_Ambience, "speed", soundSpeedRatio); //SetSoundParam(eSID_Run, "boost", Boosting() ? 1.f : 0.f); float acceleration = min(1.f, abs(localAccel.y) / m_accel*max(1.f, m_accelCoeff)); if(acceleration > 0.5f) { if(ISound *pSound = GetOrPlaySound(eSID_Acceleration, 2.f)) SetSoundParam(pSound, "acceleration", acceleration); } float damage = GetSoundDamage(); if(damage > 0.1f) { if(ISound *pSound = GetOrPlaySound(eSID_Damage, 5.f, m_enginePos)) SetSoundParam(pSound, "damage", damage); } // rpm dropdown for waves if(m_rpmPitchDir != 0) { float speed = (m_rpmPitchDir > 0) ? 0.1f : -0.8f; // quick down, slow up m_waveSoundPitch += deltaTime * speed; if(m_waveSoundPitch < -m_waveSoundAmount) // dropdown amount { m_waveSoundPitch = -m_waveSoundAmount; m_rpmPitchDir = 1; } else if(m_waveSoundPitch > 0.f) { m_waveSoundPitch = 0.f; m_rpmPitchDir = 0; } } if(m_rpmPitchSpeed>0.f) { const float maxPedal = (!m_inWater) ? 1.f : Boosting() ? 0.8f : 0.7f; // pitch rpm with pedal float pedal = GetEnginePedal(); pedal = sgnnz(pedal)*max(ms_engineSoundIdleRatio, min(maxPedal, abs(pedal))); // clamp "pedal" to [0.2..0.7] range float delta = pedal - m_rpmScaleSgn; m_rpmScaleSgn = max(-1.f, min(1.f, m_rpmScaleSgn + sgn(delta)*min(abs(delta), m_rpmPitchSpeed*deltaTime))); // skip transition around 0 when on pedal (sounds more realistic) if(abs(GetEnginePedal()) > 0.001f && abs(delta) > 0.001f && sgn(m_rpmScaleSgn) != sgn(delta) && abs(m_rpmScaleSgn) <= 0.3f) m_rpmScaleSgn = sgn(delta)*0.3f; // for normal driving, rpm is clamped at max defined by sound dept m_rpmScale = abs(m_rpmScaleSgn); m_rpmScale = min(1.f, max(ms_engineSoundIdleRatio, m_rpmScale + m_waveSoundPitch)); SetSoundParam(eSID_Run, "rpm_scale", m_rpmScale); SetSoundParam(eSID_Ambience, "rpm_scale", m_rpmScale); } }