2768 lines
99 KiB
C++
2768 lines
99 KiB
C++
//
|
|
// audio/heliaudioentity.cpp
|
|
//
|
|
// Copyright (C) 1999-2006 Rockstar Games. All Rights Reserved.
|
|
//
|
|
|
|
#include "heliaudioentity.h"
|
|
#include "northaudioengine.h"
|
|
#include "speechmanager.h"
|
|
#include "audio/scannermanager.h"
|
|
|
|
#include "audioengine/engine.h"
|
|
#include "Vehicles/Heli.h"
|
|
#include "audiosoundtypes/simplesound.h"
|
|
#include "audiohardware/submix.h"
|
|
#include "audioeffecttypes/waveshapereffect.h"
|
|
#include "camera/cinematic/CinematicDirector.h"
|
|
#include "camera/CamInterface.h"
|
|
#include "game/weather.h"
|
|
|
|
#include "Peds/ped.h"
|
|
|
|
AUDIO_VEHICLES_OPTIMISATIONS()
|
|
|
|
float g_MinHealthForHeliWarning = 200.0f; // also declared externally
|
|
bank_float g_JetpackStrafeThrusterTriggerLimit = 2.f;
|
|
bank_float g_MinValidThrusterForce = 0.05f;
|
|
bank_u32 g_MinJetpackRetriggerTime = 0;
|
|
bank_float g_HeliIntraFlipProb = 3.0f;
|
|
bank_float g_HeliInterFlipProb = 3.0f;
|
|
bank_float g_HeliDamageRate = 100.0f;
|
|
bank_float g_HeliDamageVolumeRange = -6.0f;
|
|
bank_float g_MinRotorHealthForHeliGoingDown = 200.0f;
|
|
bank_float g_HeliReplayStartupTime = 500.0f;
|
|
bank_float g_HeliStartupTime = 5000.0f;
|
|
bank_float g_HeliShutdownWaterTime = 1000.0f;
|
|
bank_float g_HeliWinddownTime = 10000.0f;
|
|
bank_float g_OverridenHeliHealth = 100.0f;
|
|
bank_float g_HeliActivationDistSq = 300.0f * 300.0f;
|
|
bank_s32 g_HeliSlowMoPitch = -200;
|
|
bank_bool g_DebugHeli = false;
|
|
bank_bool g_PlayCabinTone = false;
|
|
bank_bool g_OverrideHeliHealth = false;
|
|
bank_float g_InteriorSmoothingRate = 0.1f;
|
|
bank_float g_HeliSlowmoSmoothingTime = 2000.0f;
|
|
bank_u32 g_TimeBetweenRestartSounds = 5000;
|
|
bank_u32 g_MaxFailedToStartTries = 5;
|
|
|
|
#if __BANK
|
|
f32 g_HeliRotorTriggerRate = 1.0f;
|
|
f32 g_HeliLowPassFilter = 23999.0f;
|
|
#endif
|
|
|
|
extern u32 g_SuperDummyRadiusSq;
|
|
extern const u32 g_TemperatureVariableHash;
|
|
extern CWeather g_weather;
|
|
extern audScannerManager g_AudioScannerManager;
|
|
|
|
audCurve g_HeliMinigunSpinToVol, g_HeliMinigunSpinToPitch;
|
|
|
|
audCurve audHeliAudioEntity::sm_SuspensionVolCurve;
|
|
audCurve audHeliAudioEntity::sm_GritSpeedToLinVolCurve;
|
|
extern AmbientRadioLeakage g_AircraftPositionedPlayerVehicleRadioLeakage;
|
|
|
|
#if __BANK
|
|
f32 g_DebugHeliTrackerFlybyTime = 50.0f;
|
|
f32 g_DebugHeliTrackerFlybyDist = 2000.0f;
|
|
f32 g_DebugHeliTrackerFlybyHeight = 200.0f;
|
|
f32 g_DebugHeliTrackerTimer = 0.0f;
|
|
bool g_UseDebugHeliTracker = false;
|
|
bool g_DebugSuspension = false;
|
|
s32 g_PitchShiftIndex = -1;
|
|
bool g_ShowHeliEngineCooling = false;
|
|
bool g_EnableCrazyHeliSounds = false;
|
|
|
|
f32 g_HeliTimeWarpGap = 0.1f;
|
|
#endif
|
|
|
|
extern u32 g_audVehicleLoopReleaseTime;
|
|
|
|
audCurve audHeliAudioEntity::sm_HeliStartupToNormalCurve;
|
|
s16 audHeliAudioEntity::sm_PitchShiftIndex = 0;
|
|
s16 audHeliAudioEntity::sm_PitchShift[NUM_NPC_PICH_SHIFTS] = {0, 100, 200};
|
|
|
|
|
|
enum
|
|
{
|
|
AUD_HELI_OFF,
|
|
AUD_HELI_STARTING,
|
|
AUD_HELI_ON,
|
|
AUD_HELI_STOPPING
|
|
};
|
|
|
|
// ----------------------------------------------------------------
|
|
// audHeliAudioEntity constructor
|
|
// ----------------------------------------------------------------
|
|
audHeliAudioEntity::audHeliAudioEntity() :
|
|
audVehicleAudioEntity()
|
|
{
|
|
m_VehicleType = AUD_VEHICLE_HELI;
|
|
m_HeliBank = m_HeliExhaust = m_HeliRotor = m_HeliRearRotor = m_HeliRotorSlowmo = m_HeliRotorLowFreqSlowmo = NULL;
|
|
m_HeliDamage = m_HeliDamageOneShots = m_HeliDamageBelow600 = NULL;
|
|
m_HeliDownwash = m_HeliGoingDown = m_HeliRotorLowFreq = m_DistantRotor = NULL;
|
|
m_CrazyWarning = NULL;
|
|
m_CustomLandingGearLoop = NULL;
|
|
m_FailedToStartSound = NULL;
|
|
|
|
for(int i=0; i<NUM_VEH_CWHEELS_MAX; i++)
|
|
{
|
|
m_SuspensionSounds[i] = NULL;
|
|
m_LastCompressionChange[i] = 0.0f;
|
|
}
|
|
|
|
m_HeliState = AUD_HELI_OFF;
|
|
m_HeliAudioSettings = NULL;
|
|
m_AltitudeWarning = NULL;
|
|
m_HeliDamageWarning = NULL;
|
|
m_ScrapeSound = NULL;
|
|
m_HardScrapeSound = NULL;
|
|
m_StartupSound = NULL;
|
|
m_EngineCoolingSound = NULL;
|
|
m_RotorImpactSound = NULL;
|
|
m_PrevScrapeSound = 0;
|
|
m_SpeechSlotId = -1;
|
|
m_EnableCrazyHeliSounds = false;
|
|
m_RequiresSFXBank = false;
|
|
m_RequiresLowLatencyWaveSlot = true;
|
|
m_Shotdown = false;
|
|
m_ShockwaveId = kInvalidShockwaveId;
|
|
m_PitchShiftIndex = 0;
|
|
m_Exploded = false;
|
|
m_LastRotorImpactTime = 0;
|
|
m_LastRotorImpactSoundTime = 0;
|
|
m_BackFireTime = 0;
|
|
m_PrevLandingGearState = CLandingGear::STATE_LOCKED_DOWN;
|
|
REPLAY_ONLY(m_LastReplaySpeechSlotAllocTime = 0;)
|
|
|
|
m_FailedToStartCount = 0;
|
|
m_LastFailToStartTime = 0;
|
|
|
|
m_PlayGoingDown = false;
|
|
m_HasBeenScannerDecremented = false;
|
|
|
|
BANK_ONLY(m_DebugOcclusion = 0.0f;)
|
|
}
|
|
|
|
audHeliAudioEntity::~audHeliAudioEntity()
|
|
{
|
|
CHeli* heli = static_cast<CHeli*>(m_Vehicle);
|
|
if(heli &&(heli->GetIsPoliceDispatched() || heli->GetIsSwatDispatched()) && !m_HasBeenScannerDecremented)
|
|
{
|
|
g_AudioScannerManager.DecrementHelisInChase();
|
|
}
|
|
|
|
if(m_ShockwaveId != kInvalidShockwaveId)
|
|
{
|
|
audNorthAudioEngine::GetGtaEnvironment()->FreeShockwave(m_ShockwaveId);
|
|
m_ShockwaveId = kInvalidShockwaveId;
|
|
}
|
|
|
|
StopAndForgetSounds(m_HeliGoingDown, m_ScrapeSound, m_HardScrapeSound, m_HeliDownwash, m_HeliDamageWarning, m_EngineCoolingSound, m_CrazyWarning, m_FailedToStartSound);
|
|
StopHeliEngineSounds();
|
|
FreeSpeechSlot();
|
|
};
|
|
|
|
|
|
// ----------------------------------------------------------------
|
|
// audHeliAudioEntity Reset
|
|
// ----------------------------------------------------------------
|
|
void audHeliAudioEntity::Reset()
|
|
{
|
|
audVehicleAudioEntity::Reset();
|
|
m_HeliState = AUD_HELI_OFF;
|
|
m_HeliStartupRatio = 0.0f;
|
|
m_HeliStartupSmoother.Init(1.0f/g_HeliStartupTime, 1.0f/g_HeliWinddownTime, true);
|
|
m_HeliShutdownWaterSmoother.Init(1.0f/g_HeliShutdownWaterTime, 1.0f/g_HeliShutdownWaterTime, true);
|
|
m_HeliSlowmoSmoother.Init(1.0f, 1.0f/g_HeliSlowmoSmoothingTime, true);
|
|
|
|
m_HeliShouldSkipStartup = false;
|
|
m_MainRotorVolume = 0.0f;
|
|
m_PrevJetpackThrusterLeftForce = 0.f;
|
|
m_PrevJetpackThrusterRightForce = 0.f;
|
|
m_Throttle = 0.0f;
|
|
m_MainRotorSpeed = 0.0f;
|
|
m_PlayGoingDown = false;
|
|
m_Exploded = false;
|
|
m_LastTimeInStrafeMode = 0u;
|
|
m_LastJetpackStrafeTime = 0u;
|
|
m_FailedToStartCount = 0;
|
|
m_LastFailToStartTime = 0;
|
|
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// Acquire a wave slot
|
|
// ----------------------------------------------------------------
|
|
bool audHeliAudioEntity::AcquireWaveSlot()
|
|
{
|
|
m_RequiresSFXBank = false;
|
|
m_RequiresLowLatencyWaveSlot = true;
|
|
|
|
if(GetVehicleModelNameHash() == ATSTRINGHASH("THRUSTER", 0x58CDAF30))
|
|
{
|
|
m_RequiresLowLatencyWaveSlot = false;
|
|
|
|
if(m_IsFocusVehicle)
|
|
{
|
|
m_RequiresSFXBank = true;
|
|
|
|
RequestSFXWaveSlot(ATSTRINGHASH("DLC_XM_PLAYER_JATO_ROCKET_THRUST", 0xF1DFB27E), true);
|
|
|
|
if(!m_SFXWaveSlot)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(m_RequiresLowLatencyWaveSlot && !m_LowLatencyWaveSlot)
|
|
{
|
|
RequestLowLatencyWaveSlot(m_HeliAudioSettings->RotorLoop);
|
|
|
|
// We're quite limited on low latency slots, so in the event that we can't load the correct bank, default back to something that we can
|
|
if(!m_LowLatencyWaveSlot && sm_LowLatencyWaveSlotManager.GetNumUsedSlots() == sm_LowLatencyWaveSlotManager.GetNumSlots())
|
|
{
|
|
for(u32 loop = 0; loop < sm_LowLatencyWaveSlotManager.GetNumSlots(); loop++)
|
|
{
|
|
const audDynamicWaveSlot* waveSlot = sm_LowLatencyWaveSlotManager.GetWaveSlot(loop);
|
|
|
|
if(waveSlot && waveSlot->registeredEntities.GetCount() > 0)
|
|
{
|
|
audVehicleAudioEntity* vehicleEntity = (audVehicleAudioEntity*) waveSlot->registeredEntities[0];
|
|
audAssertf(vehicleEntity, "Registered entity is invalid!");
|
|
|
|
if(vehicleEntity)
|
|
{
|
|
audAssertf(vehicleEntity->GetAudioVehicleType() == AUD_VEHICLE_HELI, "Registered entity is not a heli! (%d)", vehicleEntity->GetAudioVehicleType());
|
|
|
|
if(vehicleEntity->GetAudioVehicleType() == AUD_VEHICLE_HELI)
|
|
{
|
|
HeliAudioSettings* settings = ((audHeliAudioEntity*)vehicleEntity)->GetHeliAudioSettings();
|
|
|
|
if(settings)
|
|
{
|
|
audWarningf("Insufficient helicopter slots, reusing already loaded helicopter settings");
|
|
RequestLowLatencyWaveSlot(settings->RotorLoop);
|
|
|
|
if(m_LowLatencyWaveSlot)
|
|
{
|
|
m_HeliAudioSettings = settings;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(m_LowLatencyWaveSlot || !m_RequiresLowLatencyWaveSlot)
|
|
{
|
|
if(!m_EngineWaveSlot)
|
|
{
|
|
if(m_HeliAudioSettings->SimpleSoundForLoading != g_NullSoundHash)
|
|
{
|
|
RequestWaveSlot(&audVehicleAudioEntity::sm_StandardWaveSlotManager, m_HeliAudioSettings->SimpleSoundForLoading);
|
|
}
|
|
else
|
|
{
|
|
RequestWaveSlot(&audVehicleAudioEntity::sm_StandardWaveSlotManager, m_HeliAudioSettings->StartUpOneShot);
|
|
}
|
|
|
|
// If we didn't acquire a proper wave slot, free up our low latency one so that the two remain in sync
|
|
if(!m_EngineWaveSlot)
|
|
{
|
|
audWaveSlotManager::FreeWaveSlot(m_LowLatencyWaveSlot, this);
|
|
audWaveSlotManager::FreeWaveSlot(m_SFXWaveSlot, this);
|
|
}
|
|
}
|
|
}
|
|
else if(m_RequiresSFXBank)
|
|
{
|
|
audWaveSlotManager::FreeWaveSlot(m_SFXWaveSlot, this);
|
|
}
|
|
|
|
return m_EngineWaveSlot != NULL && (!m_RequiresLowLatencyWaveSlot ||m_LowLatencyWaveSlot != NULL) && (!m_RequiresSFXBank || m_SFXWaveSlot != NULL);
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// Get the desired lod for the vehicle
|
|
// ----------------------------------------------------------------
|
|
audVehicleLOD audHeliAudioEntity::GetDesiredLOD(f32 UNUSED_PARAM(fwdSpeedRatio), u32 distFromListenerSq, bool UNUSED_PARAM(visibleBySniper))
|
|
{
|
|
if(m_IsFocusVehicle)
|
|
{
|
|
return AUD_VEHICLE_LOD_REAL;
|
|
}
|
|
else if(RequiresWaveSlot())
|
|
{
|
|
if(distFromListenerSq < (g_HeliActivationDistSq * sm_ActivationRangeScale))
|
|
{
|
|
return AUD_VEHICLE_LOD_REAL;
|
|
}
|
|
}
|
|
|
|
return distFromListenerSq < g_SuperDummyRadiusSq ? AUD_VEHICLE_LOD_SUPER_DUMMY : AUD_VEHICLE_LOD_DISABLED;
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// ConvertFromDummy
|
|
// ----------------------------------------------------------------
|
|
void audHeliAudioEntity::ConvertFromDummy()
|
|
{
|
|
m_HeliState = AUD_HELI_OFF;
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// ConvertToDisabled
|
|
// ----------------------------------------------------------------
|
|
void audHeliAudioEntity::ConvertToDisabled()
|
|
{
|
|
StopHeliEngineSounds();
|
|
}
|
|
|
|
void audHeliAudioEntity::SetTracker(audSoundInitParams &initParams)
|
|
{
|
|
initParams.TrackEntityPosition = true;
|
|
#if __BANK
|
|
if(g_UseDebugHeliTracker)
|
|
{
|
|
initParams.Tracker = &m_DebugTracker;
|
|
initParams.TrackEntityPosition = false;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// Initialise our helicopter settings
|
|
// ----------------------------------------------------------------
|
|
void audHeliAudioEntity::InitHeliSettings()
|
|
{
|
|
m_HeliAudioSettings = GetHeliAudioSettings();
|
|
|
|
if(m_HeliAudioSettings)
|
|
{
|
|
if(m_Vehicle->GetVehicleType()==VEHICLE_TYPE_HELI || m_Vehicle->GetVehicleType()==VEHICLE_TYPE_AUTOGYRO || m_Vehicle->GetVehicleType()==VEHICLE_TYPE_BLIMP)
|
|
{
|
|
SetupHeliVolumeCones();
|
|
|
|
ConditionalWarning(m_BankAngleVolCurve.Init(m_HeliAudioSettings->BankAngleVolumeCurve), "Invalid BankAngleVolumeCurve");
|
|
ConditionalWarning(m_RotorThrottleVolCurve.Init(m_HeliAudioSettings->RotorThrottleVolumeCurve), "Invalid RotorThrottleVolumeCurve");
|
|
ConditionalWarning(m_RotorThrottlePitchCurve.Init(m_HeliAudioSettings->RotorThrottlePitchCurve), "Invalid RotorThrottlePitchCurve");
|
|
ConditionalWarning(m_RearRotorThrottleVolCurve.Init(m_HeliAudioSettings->RearRotorThrottleVolumeCurve), "Invalid RearRotorThrottleVolumeCurve");
|
|
ConditionalWarning(m_ExhaustThrottleVolCurve.Init(m_HeliAudioSettings->ExhaustThrottleVolumeCurve), "Invalid ExhaustThrottleVolumeCurve");
|
|
ConditionalWarning(m_BankThrottleVolumeCurve.Init(m_HeliAudioSettings->BankThrottleVolumeCurve), "Invalid BankThrottleVolumeCurve");
|
|
ConditionalWarning(m_BankThrottlePitchCurve.Init(m_HeliAudioSettings->BankThrottlePitchCurve), "Invalid BankThrottlePitchCurve");
|
|
ConditionalWarning(m_ExhaustThrottlePitchCurve.Init(m_HeliAudioSettings->ExhaustThrottlePitchCurve), "Invalid ExhaustThrottlePitchCurve");
|
|
ConditionalWarning(m_HeliThrottleResonanceCurve1.Init(m_HeliAudioSettings->Filter1ThrottleResonanceCurve), "Invalid Filter1ThrottleResonanceCurve");
|
|
ConditionalWarning(m_HeliThrottleResonanceCurve2.Init(m_HeliAudioSettings->Filter2ThrottleResonanceCurve), "Invalid Filter2ThrottleResonanceCurve");
|
|
ConditionalWarning(m_HeliBankingResonanceCurve.Init(m_HeliAudioSettings->BankingResonanceCurve), "Invalid HeliBankingResonanceCurve");
|
|
ConditionalWarning(m_RotorVolStartupCurve.Init(m_HeliAudioSettings->RotorVolumeStartupCurve), "Invalid RotorVolumeStartupCurve");
|
|
ConditionalWarning(m_BladeVolStartupCurve.Init(m_HeliAudioSettings->BladeVolumeStartupCurve), "Invalid BladeVolumeStartupCurve");
|
|
ConditionalWarning(m_RotorPitchStartupCurve.Init(m_HeliAudioSettings->RotorPitchStartupCurve), "Invalid RotorPitchStartupCurve");
|
|
ConditionalWarning(m_RearRotorVolStartupCurve.Init(m_HeliAudioSettings->RearRotorVolumeStartupCurve), "Invalid RearRotorVolumeStartupCurve");
|
|
ConditionalWarning(m_ExhaustVolStartupCurve.Init(m_HeliAudioSettings->ExhaustVolumeStartupCurve), "Invalid ExhaustVolumeStartupCurve");
|
|
ConditionalWarning(m_RotorSpeedToTriggerSpeedCurve.Init(m_HeliAudioSettings->RotorSpeedToTriggerSpeedCurve), "Invalid RotorSpeedToTriggerSpeedCurve");
|
|
|
|
m_ExhaustPitchStartupCurve.Init(m_HeliAudioSettings->ExhaustPitchStartupCurve);
|
|
m_HeliThrottleSmoother.Init(m_HeliAudioSettings->ThrottleSmoothRate, m_HeliAudioSettings->ThrottleSmoothRate, -1.0f, 1.0f);
|
|
m_VehicleModelSoundHash = m_HeliAudioSettings->ScannerModel;
|
|
m_VehicleMakeSoundHash = m_HeliAudioSettings->ScannerMake;
|
|
m_VehicleCategorySoundHash = m_HeliAudioSettings->ScannerCategory;
|
|
m_ScannerVehicleSettingsHash = m_HeliAudioSettings->ScannerVehicleSettings;
|
|
|
|
ConditionalWarning(m_DamageVolumeCurve.Init(m_HeliAudioSettings->HealthToDamageVolumeCurve), "Invalid HealthToDamageVolumeCurve");
|
|
ConditionalWarning(m_DamageVolumeBelow600Curve.Init(m_HeliAudioSettings->HealthBelow600ToDamageVolumeCurve), "Invalid HealthBelow600ToDamageVolumeCurve");
|
|
|
|
#if NA_RADIO_ENABLED
|
|
m_AmbientRadioDisabled = (AUD_GET_TRISTATE_VALUE(m_HeliAudioSettings->Flags, FLAG_ID_HELIAUDIOSETTINGS_DISABLEAMBIENTRADIO) == AUD_TRISTATE_TRUE);
|
|
m_RadioType = (RadioType)m_HeliAudioSettings->RadioType;
|
|
m_RadioGenre = (RadioGenre)m_HeliAudioSettings->RadioGenre;
|
|
#endif
|
|
|
|
m_HasCustomLandingGear = (GetVehicleModelNameHash() == ATSTRINGHASH("AKULA", 0x46699F47) || GetVehicleModelNameHash() == ATSTRINGHASH("Annihilator2", 0x11962E49));
|
|
m_HeliDamageFluctuator.Init(g_HeliDamageRate/1000.0f, g_HeliDamageRate/1000.0f, 0.0f, 0.2f, 0.8f, 1.0f, g_HeliIntraFlipProb/30.0f, g_HeliInterFlipProb/30.0f, 0.0f);
|
|
|
|
if(AUD_GET_TRISTATE_VALUE(m_HeliAudioSettings->Flags, FLAG_ID_PLANEAUDIOSETTINGS_HASMISSILELOCKSYSTEM) == AUD_TRISTATE_TRUE)
|
|
{
|
|
m_HasMissileLockWarningSystem = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// Get the helicopter settings data
|
|
// ----------------------------------------------------------------
|
|
HeliAudioSettings* audHeliAudioEntity::GetHeliAudioSettings()
|
|
{
|
|
HeliAudioSettings *settings = NULL;
|
|
|
|
if(g_AudioEngine.IsAudioEnabled())
|
|
{
|
|
if(m_ForcedGameObject != 0u)
|
|
{
|
|
settings = audNorthAudioEngine::GetObject<HeliAudioSettings>(m_ForcedGameObject);
|
|
m_ForcedGameObject = 0u;
|
|
}
|
|
|
|
if(!settings)
|
|
{
|
|
if(m_Vehicle->GetVehicleModelInfo()->GetAudioNameHash() != 0)
|
|
{
|
|
settings = audNorthAudioEngine::GetObject<HeliAudioSettings>(m_Vehicle->GetVehicleModelInfo()->GetAudioNameHash());
|
|
}
|
|
|
|
if(!settings)
|
|
{
|
|
settings = audNorthAudioEngine::GetObject<HeliAudioSettings>(GetVehicleModelNameHash());
|
|
}
|
|
}
|
|
|
|
if(!audVerifyf(settings, "Couldn't find heli settings for heli: %s", GetVehicleModelName()))
|
|
{
|
|
settings = audNorthAudioEngine::GetObject<HeliAudioSettings>(ATSTRINGHASH("DEFAULT_HELI", 0xA882C8B0));
|
|
}
|
|
}
|
|
return settings;
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// Get the vehicle collision settings
|
|
// ----------------------------------------------------------------
|
|
VehicleCollisionSettings* audHeliAudioEntity::GetVehicleCollisionSettings() const
|
|
{
|
|
if(m_HeliAudioSettings)
|
|
{
|
|
return audNorthAudioEngine::GetObject<VehicleCollisionSettings>(m_HeliAudioSettings->VehicleCollisions);
|
|
}
|
|
|
|
return audVehicleAudioEntity::GetVehicleCollisionSettings();
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// Initialise the class
|
|
// ----------------------------------------------------------------
|
|
void audHeliAudioEntity::InitClass()
|
|
{
|
|
StaticConditionalWarning(sm_HeliStartupToNormalCurve.Init(ATSTRINGHASH("HELI_STARTUP_TO_NORMAL", 0x8DCE9DE2)), "Invalid sm_HeliStartupToNormalCurve");
|
|
StaticConditionalWarning(g_HeliMinigunSpinToVol.Init(ATSTRINGHASH("HELI_MINIGUN_SPEED_TO_VOL", 0xED1EB500)), "Invalid minigun speed to vol curve");
|
|
StaticConditionalWarning(g_HeliMinigunSpinToPitch.Init(ATSTRINGHASH("HELI_MINIGUN_SPEED_TO_PITCH", 0xB4EE8A74)), "Invalid minigun speed to pitch curve");
|
|
StaticConditionalWarning(sm_SuspensionVolCurve.Init(ATSTRINGHASH("HELI_SUSPENSION_COMPRESSION_TO_VOL",0xD9991BE)), "Invalid SuspVolCurve");
|
|
StaticConditionalWarning(sm_GritSpeedToLinVolCurve.Init(ATSTRINGHASH("HELI_SPEED_TO_LANDING_GEAR_SCRAPE_VOLUME",0xC02B81D7)), "Invalid GritSpeedCurve");
|
|
|
|
audVehicleGrapplingHook::InitClass();
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// Get the leakage for any positional player radio
|
|
// ----------------------------------------------------------------
|
|
AmbientRadioLeakage audHeliAudioEntity::GetPositionalPlayerRadioLeakage() const
|
|
{
|
|
return g_AircraftPositionedPlayerVehicleRadioLeakage;
|
|
}
|
|
|
|
bool audHeliAudioEntity::IsRadioUpgraded() const
|
|
{
|
|
return GetVehicleModelNameHash() == ATSTRINGHASH("BLIMP3", 0xEDA4ED97);
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// Init anything helicopter specific
|
|
// ----------------------------------------------------------------
|
|
bool audHeliAudioEntity::InitVehicleSpecific()
|
|
{
|
|
m_MainRotorVolume = g_SilenceVolume;
|
|
|
|
m_CrazyFlyingRotorPitchSmoother.Init(20.0f, 50.0f, -1000.0f, 0.0f);
|
|
m_CrazyFlyingDamageSmoother.Init(2.0f, 2.0f, -100.0f, 0.0f);
|
|
|
|
InitHeliSettings();
|
|
|
|
if(!m_HeliAudioSettings)
|
|
{
|
|
return false;
|
|
}
|
|
m_EngineOffTemperature = 100.0f;
|
|
|
|
#if 0
|
|
f32 innerMap[5][3] = { { 0.0f, 0.0f, 0.0f},
|
|
{ 1.2f, 4.0f, 0.0f},
|
|
{ 1.2f, -8.0f, 0.0f},
|
|
{-1.2f, 4.0f, 0.0f},
|
|
{-1.2f, -8.0f, 0.0f}};
|
|
|
|
f32 outerMap[8][3] = { { 4.0f, 6.0f, 6.0f},
|
|
{ 4.0f, -12.0f, 6.0f},
|
|
{-4.0f, 6.0f, 6.0f},
|
|
{-4.0f, -12.0f, 6.0f},
|
|
{ 4.0f, 6.0f, -2.0f},
|
|
{ 4.0f, -12.0f, -2.0f},
|
|
{-4.0f, 6.0f, -2.0f},
|
|
{-4.0f, -12.0f, -2.0f}};
|
|
|
|
if (m_OcclusionGroup)
|
|
{
|
|
m_OcclusionGroup->SetBounds(innerMap, outerMap);
|
|
}
|
|
#endif
|
|
SetEnvironmentGroupSettings(false, audNorthAudioEngine::GetOcclusionManager()->GetMaxOcclusionPathDepth());
|
|
|
|
// GTAV specific fix - should be moved into the gameobject when we get a chance
|
|
if(GetVehicleModelNameHash() == ATSTRINGHASH("SWIFT", 0xEBC24DF2))
|
|
{
|
|
m_LandingGearSoundSet.Init(ATSTRINGHASH("SWIFT_LANDING_GEAR", 0x1CCAA017));
|
|
}
|
|
else if(GetVehicleModelNameHash() == ATSTRINGHASH("SWIFT2", 0x4019CB4C))
|
|
{
|
|
m_LandingGearSoundSet.Init(ATSTRINGHASH("SWIFT2_LANDING_GEAR", 0x55A3666B));
|
|
}
|
|
else if(GetVehicleModelNameHash() == ATSTRINGHASH("SAVAGE", 0xFB133A17))
|
|
{
|
|
m_LandingGearSoundSet.Init(ATSTRINGHASH("SAVAGE_LANDING_GEAR", 0xE1A6253F));
|
|
}
|
|
else if(GetVehicleModelNameHash() == ATSTRINGHASH("VOLATUS", 0x920016F1))
|
|
{
|
|
m_LandingGearSoundSet.Init(ATSTRINGHASH("VOLATUS_LANDING_GEAR", 0x990EA6F3));
|
|
}
|
|
else if(GetVehicleModelNameHash() == ATSTRINGHASH("AKULA", 0x46699F47))
|
|
{
|
|
m_LandingGearSoundSet.Init(ATSTRINGHASH("AKULA_SOUNDS", 0x6CC7612D));
|
|
}
|
|
else if(GetVehicleModelNameHash() == ATSTRINGHASH("THRUSTER", 0x58CDAF30))
|
|
{
|
|
m_LandingGearSoundSet.Init(ATSTRINGHASH("thruster_turbine_sounds", 0x9C4F5C78));
|
|
}
|
|
else if (GetVehicleModelNameHash() == ATSTRINGHASH("Annihilator2", 0x11962E49))
|
|
{
|
|
m_LandingGearSoundSet.Init(ATSTRINGHASH("annihilator2_sounds", 0x7CDB0FE7));
|
|
}
|
|
|
|
m_KersSystem.Init(this);
|
|
m_VehicleSpeedToHullSlapVol.Init(ATSTRINGHASH("BOAT_SPEED_TO_HULL_SLAP_VOLUME", 0x7DE7B14A));
|
|
|
|
return true;
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// OnFocusVehicleChanged
|
|
// ----------------------------------------------------------------
|
|
void audHeliAudioEntity::OnFocusVehicleChanged()
|
|
{
|
|
if(m_SFXWaveSlot && !m_IsFocusVehicle)
|
|
{
|
|
audWaveSlotManager::FreeWaveSlot(m_SFXWaveSlot, this);
|
|
m_RequiresSFXBank = false;
|
|
}
|
|
else if(GetVehicleModelNameHash() == ATSTRINGHASH("THRUSTER", 0x58CDAF30) && m_IsFocusVehicle && m_EngineWaveSlot && !m_SFXWaveSlot)
|
|
{
|
|
RequestSFXWaveSlot(ATSTRINGHASH("DLC_XM_PLAYER_JATO_ROCKET_THRUST", 0xF1DFB27E), true);
|
|
m_RequiresSFXBank = true;
|
|
}
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------
|
|
// Check if the helicopter requires a wave slot
|
|
// ----------------------------------------------------------------
|
|
bool audHeliAudioEntity::RequiresWaveSlot() const
|
|
{
|
|
return ((CHeli*)m_Vehicle)->GetMainRotorSpeed() > 0.0f;
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// Update anything helicopter specific
|
|
// ----------------------------------------------------------------
|
|
void audHeliAudioEntity::UpdateVehicleSpecific(audVehicleVariables& UNUSED_PARAM(vehicleVariables), audVehicleDSPSettings& dspSettings)
|
|
{
|
|
#if __BANK
|
|
if (m_HeliAudioSettings)
|
|
{
|
|
m_HeliThrottleSmoother.SetRates(m_HeliAudioSettings->ThrottleSmoothRate, m_HeliAudioSettings->ThrottleSmoothRate);
|
|
m_HeliDamageFluctuator.SetFlipProbabilities(g_HeliIntraFlipProb/30.0f, g_HeliInterFlipProb/30.0f);
|
|
m_HeliDamageFluctuator.SetRates(g_HeliDamageRate/1000.0f, g_HeliDamageRate/1000.0f);
|
|
}
|
|
#endif
|
|
|
|
if(m_Exploded)
|
|
{
|
|
m_HeliState = AUD_HELI_OFF;
|
|
StopHeliEngineSounds();
|
|
if(m_ShockwaveId != kInvalidShockwaveId)
|
|
{
|
|
audNorthAudioEngine::GetGtaEnvironment()->FreeShockwave(m_ShockwaveId);
|
|
m_ShockwaveId = kInvalidShockwaveId;
|
|
}
|
|
}
|
|
|
|
if(IsReal() || m_HeliState != AUD_HELI_OFF)
|
|
{
|
|
audHeliValues heliValues;
|
|
|
|
// Work out what the engine's doing now, what state we're in, and what we need to do
|
|
bool engineOn = IsEngineOn();
|
|
|
|
// See how much we're banking
|
|
// Get the up vector from the Heli, and see it's angle to straight up
|
|
heliValues.banking = Dot(m_Vehicle->GetTransform().GetC(), Vec3V(V_Z_AXIS_WZERO)).Getf();
|
|
|
|
m_Throttle = ((CHeli*)m_Vehicle)->GetThrottleControl();
|
|
m_MainRotorSpeed = ((CHeli*)m_Vehicle)->GetMainRotorSpeed();
|
|
|
|
f32 entityVariableThrottle = 0.0f;
|
|
f32 entityVariableRevs = 0.0f;
|
|
f32 entityVariableLats = 0.0f;
|
|
f32 fakeEngineFactor = 0.0f;
|
|
|
|
if(HasEntityVariableBlock())
|
|
{
|
|
entityVariableThrottle = GetEntityVariableValue(ATSTRINGHASH("fakethrottle", 0xEB27990));
|
|
entityVariableRevs = GetEntityVariableValue(ATSTRINGHASH("fakerevs", 0xCEB98BEB));
|
|
entityVariableLats = GetEntityVariableValue(ATSTRINGHASH("fakelatslip", 0x34DA17A0));
|
|
|
|
// Reduce this each frame so that that the behavior gets canceled even if a sound forgets to do so
|
|
fakeEngineFactor = GetEntityVariableValue(ATSTRINGHASH("usefakeengine", 0x91DF7F97));
|
|
SetEntityVariable(ATSTRINGHASH("usefakeengine", 0x91DF7F97), Clamp(fakeEngineFactor - 0.1f, 0.0f, 1.0f));
|
|
}
|
|
|
|
if(fakeEngineFactor > 0.1f)
|
|
{
|
|
m_Throttle = entityVariableThrottle;
|
|
heliValues.banking = entityVariableRevs;
|
|
m_MainRotorSpeed = entityVariableLats;
|
|
}
|
|
|
|
m_Throttle = Clamp(m_Throttle, 0.0f, 2.0f);
|
|
heliValues.banking = Clamp(heliValues.banking, 0.0f, 1.0f);
|
|
|
|
// Transition state and do updates
|
|
switch (m_HeliState)
|
|
{
|
|
case AUD_HELI_OFF:
|
|
if(engineOn)
|
|
{
|
|
if(CReplayMgr::IsEditModeActive() && !CReplayMgr::IsJustPlaying()) // if we are in the editor and doing anything but playing(such as loading) we are not going to try to start the engines, because the LOD system will stop them and then restart
|
|
{
|
|
break;
|
|
}
|
|
if(m_EngineWaveSlot && m_EngineWaveSlot->IsLoaded() &&
|
|
(!m_RequiresLowLatencyWaveSlot || (m_LowLatencyWaveSlot && m_LowLatencyWaveSlot->IsLoaded())) &&
|
|
(!m_RequiresSFXBank || (m_SFXWaveSlot && m_SFXWaveSlot->IsLoaded())))
|
|
{
|
|
if (m_HeliShouldSkipStartup) // removed because it was always true preventing scripts from playing the startup sound || m_WasEngineOnLastFrame)
|
|
{
|
|
// dive straight into being on, then unset this flag so we can be turned off again
|
|
#if GTA_REPLAY
|
|
if(CReplayMgr::IsPlaying()) // startup faster on replays
|
|
{
|
|
m_HeliStartupSmoother.Init(1.0f/g_HeliReplayStartupTime, 1.0f/g_HeliWinddownTime, true);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
m_HeliStartupSmoother.Init(1.0f/g_HeliStartupTime, 1.0f/g_HeliWinddownTime, true);
|
|
}
|
|
heliValues.startup = m_HeliStartupSmoother.CalculateValue(1.0f, fwTimer::GetTimeInMilliseconds());
|
|
StartHeliEngineSounds(heliValues, true); // skip the startup sound. This'll do an Update as part of starting
|
|
m_HeliState = AUD_HELI_ON;
|
|
m_HeliShouldSkipStartup = false;
|
|
}
|
|
else
|
|
{
|
|
heliValues.startup = m_HeliStartupSmoother.CalculateValue(0.0f, fwTimer::GetTimeInMilliseconds());
|
|
if (engineOn)
|
|
{
|
|
m_HeliState = AUD_HELI_STARTING;
|
|
StartHeliEngineSounds(heliValues);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case AUD_HELI_STARTING:
|
|
heliValues.startup = m_HeliStartupSmoother.CalculateValue(1.0f, fwTimer::GetTimeInMilliseconds());
|
|
UpdateHeliEngineSoundStartingStopping(heliValues);
|
|
if (!engineOn)
|
|
{
|
|
m_HeliState = AUD_HELI_STOPPING;
|
|
|
|
if(m_StartupSound)
|
|
{
|
|
m_StartupSound->StopAndForget(true);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (heliValues.startup >= 1.0f)
|
|
{
|
|
m_HeliState = AUD_HELI_ON;
|
|
}
|
|
}
|
|
if(m_Vehicle && m_Vehicle->GetWillEngineStart())
|
|
{
|
|
m_FailedToStartCount = 0;
|
|
m_LastFailToStartTime = 0;
|
|
}
|
|
break;
|
|
|
|
case AUD_HELI_STOPPING:
|
|
if(m_Vehicle->m_nVehicleFlags.bIsDrowning)
|
|
heliValues.startup = m_HeliShutdownWaterSmoother.CalculateValue(m_MainRotorSpeed, fwTimer::GetTimeInMilliseconds());
|
|
else
|
|
heliValues.startup = m_HeliStartupSmoother.CalculateValue(m_MainRotorSpeed, fwTimer::GetTimeInMilliseconds());
|
|
UpdateHeliEngineSoundStartingStopping(heliValues);
|
|
if (engineOn)
|
|
{
|
|
m_HeliState = AUD_HELI_STARTING;
|
|
}
|
|
else
|
|
{
|
|
static bank_float minRotorSpeedForStop = 0.1f;
|
|
if (heliValues.startup <= minRotorSpeedForStop)
|
|
{
|
|
m_HeliState = AUD_HELI_OFF;
|
|
StopHeliEngineSounds();
|
|
}
|
|
}
|
|
|
|
if(m_ShockwaveId != kInvalidShockwaveId)
|
|
{
|
|
audNorthAudioEngine::GetGtaEnvironment()->FreeShockwave(m_ShockwaveId);
|
|
m_ShockwaveId = kInvalidShockwaveId;
|
|
}
|
|
break;
|
|
|
|
case AUD_HELI_ON:
|
|
heliValues.startup = m_HeliStartupSmoother.CalculateValue(1.0f, fwTimer::GetTimeInMilliseconds());
|
|
UpdateHeliEngineSoundsOn(heliValues);
|
|
UpdateCrazyFlying(heliValues);
|
|
|
|
if (!engineOn)
|
|
{
|
|
m_HeliState = AUD_HELI_STOPPING;
|
|
|
|
if(GetVehicleModelNameHash() == ATSTRINGHASH("THRUSTER", 0x58CDAF30))
|
|
{
|
|
audSoundSet soundset;
|
|
const u32 soundsetName = ATSTRINGHASH("thruster_turbine_sounds", 0x9C4F5C78);
|
|
const u32 soundName = ATSTRINGHASH("shutdown", 0xE99B0DCB);
|
|
|
|
if(soundset.Init(soundsetName))
|
|
{
|
|
audSoundInitParams initParams;
|
|
initParams.UpdateEntity = true;
|
|
initParams.TrackEntityPosition = true;
|
|
initParams.EnvironmentGroup = GetEnvironmentGroup();
|
|
initParams.u32ClientVar = (u32)AUD_VEHICLE_SOUND_UNKNOWN;
|
|
CreateAndPlaySound(soundset.Find(soundName), &initParams);
|
|
REPLAY_ONLY(CReplayMgr::ReplayRecordSound(soundsetName, soundName, &initParams, m_Vehicle));
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
if (m_HeliState != AUD_HELI_OFF)
|
|
{
|
|
UpdateHeliEngineSounds(heliValues);
|
|
f32 resonanceScalingFactor = m_HeliBankingResonanceCurve.CalculateValue(heliValues.banking);
|
|
f32 resonance1 = audDriverUtil::ComputeLinearVolumeFromDb(m_HeliThrottleResonanceCurve1.CalculateValue(heliValues.throttle) * resonanceScalingFactor);
|
|
f32 resonance2 = audDriverUtil::ComputeLinearVolumeFromDb(m_HeliThrottleResonanceCurve2.CalculateValue(heliValues.throttle) * resonanceScalingFactor);
|
|
|
|
dspSettings.AddDSPParameter(atHashString("Throttle", 0xEA0151DC), heliValues.throttle);
|
|
dspSettings.AddDSPParameter(atHashString("Banking", 0x57F8C1F8), heliValues.banking);
|
|
dspSettings.AddDSPParameter(atHashString("RotorSpeed", 0x4F4CEFD4), m_MainRotorSpeed);
|
|
dspSettings.AddDSPParameter(atHashString("Filter1Resonance", 0x96A1524), resonance1);
|
|
dspSettings.AddDSPParameter(atHashString("Filter2Resonance", 0x7FFE9BC7), resonance2);
|
|
dspSettings.enginePostSubmixAttenuation = m_HeliAudioSettings->RotorVolumePostSubmix/100.f;
|
|
}
|
|
|
|
#if __DEV
|
|
if (g_DebugHeli && g_AudioDebugEntity == m_Vehicle)
|
|
{
|
|
char heliDebug[128] = "";
|
|
formatf(heliDebug, sizeof(heliDebug), "state: %d; startup: %.2f; bVol: %.2f, throttle: %f", m_HeliState, heliValues.startup, heliValues.bladeVolume, m_Throttle);
|
|
grcDebugDraw::PrintToScreenCoors(heliDebug,20,20);
|
|
}
|
|
#endif
|
|
|
|
if(m_LastHeliDownwashTime + 300 < fwTimer::GetTimeInMilliseconds() && m_HeliDownwash)
|
|
{
|
|
m_HeliDownwash->StopAndForget();
|
|
}
|
|
|
|
// altitude warning tone
|
|
if(!m_AltitudeWarning)
|
|
{
|
|
CreateAndPlaySound_Persistent(m_HeliAudioSettings->AltitudeWarning, &m_AltitudeWarning);
|
|
}
|
|
|
|
if(m_AltitudeWarning)
|
|
{
|
|
f32 rotorHealth = ((CHeli*)m_Vehicle)->GetMainRotorHealth();
|
|
f32 rearRotorHealth = ((CHeli*)m_Vehicle)->GetRearRotorHealth();
|
|
f32 tailBoomHealth = ((CHeli*)m_Vehicle)->GetTailBoomHealth();
|
|
f32 overallhealth = m_Vehicle->GetHealth();
|
|
f32 health = Min(rotorHealth, rearRotorHealth, tailBoomHealth, overallhealth);
|
|
|
|
//if( !m_Vehicle->m_nVehicleFlags.bEngineOn ||
|
|
// CGameWorld::FindLocalPlayerVehicle() != m_Vehicle ||
|
|
// health > g_MinHealthForHeliWarning ||
|
|
// (CGameWorld::FindLocalPlayer() && CGameWorld::FindLocalPlayer()->IsDead()))
|
|
f32 airSpeedZ = m_CachedVehicleVelocity.z;
|
|
|
|
static bank_float verticalSpeed = -20.0f;
|
|
if( CGameWorld::FindLocalPlayerVehicle() != m_Vehicle ||
|
|
health > g_MinHealthForHeliWarning ||
|
|
!AreWarningSoundsValid() ||
|
|
(CGameWorld::FindLocalPlayer() && CGameWorld::FindLocalPlayer()->IsDead()))
|
|
{
|
|
m_AltitudeWarning->SetRequestedVolume(g_SilenceVolume);
|
|
}
|
|
else
|
|
{
|
|
m_AltitudeWarning->SetRequestedVolume(0.f);
|
|
if(airSpeedZ < verticalSpeed && ((rotorHealth < g_MinRotorHealthForHeliGoingDown) || (!m_Vehicle->m_nVehicleFlags.bEngineOn)))
|
|
TriggerGoingDownSound();
|
|
}
|
|
}
|
|
|
|
static bank_float mainRotorSpeedForDamageWarning = 0.3f;
|
|
if(m_IsPlayerVehicle && m_Vehicle->GetVehicleDamage()->GetEngineHealth() < 200.0f && m_Vehicle->GetStatus() != STATUS_WRECKED && !m_HeliDamageWarning && m_MainRotorSpeed >= mainRotorSpeedForDamageWarning && AreWarningSoundsValid())
|
|
{
|
|
audSoundInitParams initParams;
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
initParams.TrackEntityPosition = true;
|
|
CreateAndPlaySound_Persistent(m_HeliAudioSettings->DamageWarning, &m_HeliDamageWarning, &initParams);
|
|
}
|
|
else if(m_HeliDamageWarning && (m_MainRotorSpeed < mainRotorSpeedForDamageWarning || m_Vehicle->GetStatus() == STATUS_WRECKED || !m_IsPlayerVehicle || m_Vehicle->GetVehicleDamage()->GetEngineHealth() > 200.0f || !AreWarningSoundsValid()))
|
|
{
|
|
m_HeliDamageWarning->StopAndForget();
|
|
}
|
|
UpdateSuspension();
|
|
UpdateWheelSounds();
|
|
UpdateDamageSounds(heliValues);
|
|
UpdateRotorImpactSounds(heliValues);
|
|
m_KersSystem.Update();
|
|
UpdateCustomLandingGearSounds();
|
|
UpdateJetPackSounds();
|
|
|
|
#if __BANK
|
|
ShowHeliValues(heliValues);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
StopAndForgetSounds(m_ScrapeSound, m_HardScrapeSound, m_HeliDownwash, m_HeliDamageWarning, m_RotorImpactSound, m_CrazyWarning, m_CustomLandingGearLoop);
|
|
m_KersSystem.StopAllSounds();
|
|
}
|
|
|
|
if (IsSeaPlane())
|
|
{
|
|
if (!IsDisabled())
|
|
{
|
|
UpdateSeaPlane();
|
|
}
|
|
}
|
|
|
|
if(m_PlayGoingDown)
|
|
{
|
|
PlayGoingDownSound();
|
|
}
|
|
if(!m_HeliGoingDown)
|
|
{
|
|
// In replay playback, the heli owns the wave slot reference but not the sound, so allow a little leeway between allocating the slot and freeing it so
|
|
// that the sound has a chance to trigger and bump up the slot reference count (which will automatically prevent anything else from stealing the slot
|
|
// whilst it is playing.
|
|
REPLAY_ONLY(if(!CReplayMgr::IsEditorActive() || (g_AudioEngine.GetSoundManager().GetTimeInMilliseconds(0) - m_LastReplaySpeechSlotAllocTime) > 1000))
|
|
{
|
|
FreeSpeechSlot();
|
|
}
|
|
}
|
|
if(m_Vehicle->GetStatus() == STATUS_WRECKED)
|
|
{
|
|
if(m_CrazyWarning)
|
|
{
|
|
m_CrazyWarning->StopAndForget();
|
|
}
|
|
}
|
|
UpdateEngineCooling();
|
|
|
|
SetEnvironmentGroupSettings(false, audNorthAudioEngine::GetOcclusionManager()->GetMaxOcclusionPathDepth());
|
|
|
|
#if __BANK
|
|
UpdateDebug();
|
|
#endif
|
|
}
|
|
|
|
void audHeliAudioEntity::PostUpdate()
|
|
{
|
|
audVehicleAudioEntity::PostUpdate();
|
|
UpdateShockwave();
|
|
}
|
|
|
|
bool audHeliAudioEntity::CalculateIsInWater() const
|
|
{
|
|
if (IsSeaPlane())
|
|
{
|
|
return m_Vehicle->m_Buoyancy.GetSubmergedLevel() >= 0.05f;
|
|
}
|
|
|
|
return audVehicleAudioEntity::CalculateIsInWater();
|
|
}
|
|
|
|
u32 audHeliAudioEntity::GetWaveHitSound() const
|
|
{
|
|
if (IsSeaPlane())
|
|
{
|
|
return ATSTRINGHASH("BOAT_WAVE_HIT_MEDIUM", 0x5D9D2B9B);
|
|
}
|
|
|
|
return audVehicleAudioEntity::GetWaveHitSound();
|
|
}
|
|
|
|
u32 audHeliAudioEntity::GetWaveHitBigSound() const
|
|
{
|
|
if (IsSeaPlane())
|
|
{
|
|
return ATSTRINGHASH("BOAT_WAVE_HIT_BIG_AIR", 0x73E4FA98);
|
|
}
|
|
|
|
return audVehicleAudioEntity::GetWaveHitSound();
|
|
}
|
|
|
|
u32 audHeliAudioEntity::GetIdleHullSlapSound() const
|
|
{
|
|
if (IsSeaPlane())
|
|
{
|
|
return ATSTRINGHASH("IDLE_HULL_SLAP", 0xFFFF62BC);
|
|
}
|
|
|
|
return audVehicleAudioEntity::GetIdleHullSlapSound();
|
|
}
|
|
|
|
f32 audHeliAudioEntity::GetIdleHullSlapVolumeLinear(f32 speed) const
|
|
{
|
|
return m_VehicleSpeedToHullSlapVol.CalculateValue(speed);
|
|
}
|
|
|
|
void audHeliAudioEntity::UpdateSeaPlane()
|
|
{
|
|
if (CalculateIsInWater() && GetVehicleModelNameHash() == ATSTRINGHASH("SEASPARROW", 0xD4AE63D9))
|
|
{
|
|
if (!m_WaterTurbulenceSound)
|
|
{
|
|
audSoundInitParams initParams;
|
|
initParams.UpdateEntity = true;
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
SetTracker(initParams);
|
|
CreateAndPlaySound_Persistent(ATSTRINGHASH("seasparrow_water_turbulence", 0x4C4922), &m_WaterTurbulenceSound, &initParams);
|
|
}
|
|
}
|
|
else if (m_WaterTurbulenceSound)
|
|
{
|
|
m_WaterTurbulenceSound->StopAndForget();
|
|
}
|
|
}
|
|
|
|
void audHeliAudioEntity::UpdateShockwave()
|
|
{
|
|
bool shockwaveValid = false;
|
|
CPed* pPlayer = CGameWorld::FindLocalPlayer();
|
|
|
|
if(m_Vehicle && pPlayer)
|
|
{
|
|
u32 distFromListenerSq = static_cast<u32>(MagSquared(m_Vehicle->GetTransform().GetPosition() - g_AudioEngine.GetEnvironment().GetVolumeListenerPosition()).Getf());
|
|
bool shouldTriggerShockwave = m_Vehicle->GetIsInExterior() && pPlayer->GetIsInExterior();
|
|
shouldTriggerShockwave = shouldTriggerShockwave || (m_Vehicle->GetIsInInterior() && pPlayer && pPlayer->GetIsInInterior() && m_Vehicle->GetAudioInteriorLocation().IsSameLocation(pPlayer->GetAudioInteriorLocation()));
|
|
shouldTriggerShockwave &= (IsReal() && m_HeliState == AUD_HELI_ON);
|
|
|
|
if(shouldTriggerShockwave && distFromListenerSq < (120.f*120.f))
|
|
{
|
|
audShockwave shockwave;
|
|
shockwave.centre = VEC3V_TO_VECTOR3(m_Vehicle->GetTransform().GetPosition()) + Vector3(0.f,0.f,3.5f);
|
|
shockwave.maxRadius = shockwave.radius = naEnvironment::sm_HeliShockwaveRadius;
|
|
shockwave.intensity = 1.f;
|
|
shockwave.centered = true;
|
|
audNorthAudioEngine::GetGtaEnvironment()->UpdateShockwave(m_ShockwaveId, shockwave);
|
|
shockwaveValid = true;
|
|
}
|
|
}
|
|
|
|
if(!shockwaveValid && m_ShockwaveId != kInvalidShockwaveId)
|
|
{
|
|
audNorthAudioEngine::GetGtaEnvironment()->FreeShockwave(m_ShockwaveId);
|
|
m_ShockwaveId = kInvalidShockwaveId;
|
|
}
|
|
}
|
|
|
|
void audHeliAudioEntity::UpdateCrazyFlying(audHeliValues& heliValues)
|
|
{
|
|
if(m_CrazyWarning && m_HeliDamageWarning)
|
|
{
|
|
m_CrazyWarning->StopAndForget();
|
|
}
|
|
|
|
#if __BANK
|
|
if(g_EnableCrazyHeliSounds)
|
|
m_EnableCrazyHeliSounds = true;
|
|
#endif
|
|
|
|
if(!m_EnableCrazyHeliSounds)
|
|
{
|
|
if(m_CrazyWarning)
|
|
{
|
|
m_CrazyWarning->StopAndForget();
|
|
}
|
|
return;
|
|
}
|
|
|
|
static bank_float bank = 0.9f;
|
|
if(heliValues.banking < bank)
|
|
{
|
|
if(m_IsPlayerVehicle && !m_CrazyWarning && !m_HeliDamageWarning)
|
|
{
|
|
audSoundInitParams initParams;
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
initParams.TrackEntityPosition = true;
|
|
CreateAndPlaySound_Persistent(m_HeliAudioSettings->DamageWarning, &m_CrazyWarning, &initParams);
|
|
}
|
|
|
|
static bank_float smooth = -1000.0f;
|
|
heliValues.rotorPitch += (s32)m_CrazyFlyingRotorPitchSmoother.CalculateValue(smooth);
|
|
heliValues.damageVolume = m_CrazyFlyingDamageSmoother.CalculateValue(0.0f);
|
|
}
|
|
else
|
|
{
|
|
if(m_CrazyWarning)
|
|
m_CrazyWarning->StopAndForget();
|
|
|
|
heliValues.rotorPitch += (s32)m_CrazyFlyingRotorPitchSmoother.CalculateValue(0.0f);
|
|
heliValues.damageVolume = m_CrazyFlyingDamageSmoother.CalculateValue(-100.0f);
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------
|
|
// audHeliAudioEntity SetHeliShouldSkipStartup
|
|
// ----------------------------------------------------------------
|
|
void audHeliAudioEntity::SetHeliShouldSkipStartup(bool skipStartup)
|
|
{
|
|
// don't set this to if we're in anything other than a stopped state - it's almost certainly not what's intended
|
|
if (m_HeliState == AUD_HELI_OFF)
|
|
{
|
|
m_HeliShouldSkipStartup = skipStartup;
|
|
}
|
|
}
|
|
|
|
|
|
// -------------------------------------------------------------------------------
|
|
// Get the engine submix synth def
|
|
// -------------------------------------------------------------------------------
|
|
u32 audHeliAudioEntity::GetEngineSubmixSynth() const
|
|
{
|
|
if(ShouldUseDSPEffects() && m_HeliAudioSettings)
|
|
{
|
|
return m_HeliAudioSettings->EngineSynthDef;
|
|
}
|
|
else
|
|
{
|
|
return audVehicleAudioEntity::GetEngineSubmixSynth();
|
|
}
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------
|
|
// Get the engine submix synth preset
|
|
// -------------------------------------------------------------------------------
|
|
u32 audHeliAudioEntity::GetEngineSubmixSynthPreset() const
|
|
{
|
|
if(ShouldUseDSPEffects() && m_HeliAudioSettings)
|
|
{
|
|
return m_HeliAudioSettings->EngineSynthPreset;
|
|
}
|
|
else
|
|
{
|
|
return audVehicleAudioEntity::GetEngineSubmixSynthPreset();
|
|
}
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------
|
|
// Get the exhaust submix synth def
|
|
// -------------------------------------------------------------------------------
|
|
u32 audHeliAudioEntity::GetExhaustSubmixSynth() const
|
|
{
|
|
if(ShouldUseDSPEffects() && m_HeliAudioSettings)
|
|
{
|
|
return m_HeliAudioSettings->ExhaustSynthDef;
|
|
}
|
|
else
|
|
{
|
|
return audVehicleAudioEntity::GetExhaustSubmixSynth();
|
|
}
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------
|
|
// Get the exhaust submix synth preset
|
|
// -------------------------------------------------------------------------------
|
|
u32 audHeliAudioEntity::GetExhaustSubmixSynthPreset() const
|
|
{
|
|
if(ShouldUseDSPEffects() && m_HeliAudioSettings)
|
|
{
|
|
return m_HeliAudioSettings->ExhaustSynthPreset;
|
|
}
|
|
else
|
|
{
|
|
return audVehicleAudioEntity::GetExhaustSubmixSynthPreset();
|
|
}
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------
|
|
// Get the engine submix voice
|
|
// -------------------------------------------------------------------------------
|
|
u32 audHeliAudioEntity::GetEngineSubmixVoice() const
|
|
{
|
|
if(m_HeliAudioSettings)
|
|
{
|
|
return m_HeliAudioSettings->EngineSubmixVoice;
|
|
}
|
|
else
|
|
{
|
|
return audVehicleAudioEntity::GetEngineSubmixVoice();
|
|
}
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------
|
|
// Get the exhaust submix voice
|
|
// -------------------------------------------------------------------------------
|
|
u32 audHeliAudioEntity::GetExhaustSubmixVoice() const
|
|
{
|
|
if(m_HeliAudioSettings)
|
|
{
|
|
return m_HeliAudioSettings->ExhaustSubmixVoice;
|
|
}
|
|
else
|
|
{
|
|
return audVehicleAudioEntity::GetExhaustSubmixVoice();
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// audHeliAudioEntity StartHeliEngineSounds
|
|
// ----------------------------------------------------------------
|
|
void audHeliAudioEntity::StartHeliEngineSounds(audHeliValues& heliValues, bool instantStart)
|
|
{
|
|
if (m_HeliBank || m_HeliExhaust || m_HeliRearRotor || m_HeliRotor || m_HeliRotorLowFreq || m_DistantRotor)
|
|
{
|
|
naErrorf("Can't start new heli sounds when they're already playing");
|
|
return;
|
|
}
|
|
|
|
if (m_HeliAudioSettings)
|
|
{
|
|
audSoundInitParams initParams;
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
SetTracker(initParams);
|
|
if(instantStart)// REPLAY_ONLY( && !CReplayMgr::IsPlaying()))
|
|
{
|
|
if(CReplayMgr::IsPlaying())
|
|
{
|
|
// if we've skipped startup, give them a 500ms attack time, otherwise they chop in
|
|
initParams.AttackTime = 300;
|
|
}
|
|
else
|
|
{
|
|
// if we've skipped startup, give them a 2 second attack time, otherwise they chop in
|
|
initParams.AttackTime = sm_LodSwitchFadeTime;
|
|
}
|
|
}
|
|
if((m_Vehicle->m_nVehicleFlags.bCreatedByFactory && m_Vehicle->m_nVehicleFlags.bSkipEngineStartup REPLAY_ONLY( && !CReplayMgr::IsPlaying())) || m_WasScheduledCreation)
|
|
{
|
|
initParams.AttackTime = sm_ScheduledVehicleSpawnFadeTime;
|
|
}
|
|
if(m_Vehicle->m_nVehicleFlags.bSkipEngineStartup)
|
|
{
|
|
instantStart = true;
|
|
}
|
|
CreateSound_PersistentReference(m_HeliAudioSettings->BankingLoop, &m_HeliBank, &initParams);
|
|
CreateSound_PersistentReference(m_HeliAudioSettings->ExhaustLoop, &m_HeliExhaust, &initParams);
|
|
CreateSound_PersistentReference(m_HeliAudioSettings->RotorLowFreqLoop, &m_HeliRotorLowFreq, &initParams);
|
|
CreateSound_PersistentReference(m_HeliAudioSettings->DistantLoop, &m_DistantRotor, &initParams);
|
|
|
|
Assign(initParams.EffectRoute, GetEngineEffectRoute());
|
|
CreateSound_PersistentReference(m_HeliAudioSettings->RotorLoop, &m_HeliRotor, &initParams);
|
|
initParams.EffectRoute = 0;
|
|
|
|
// Rear rotor doesn't get a tracker
|
|
#if __BANK
|
|
if(g_UseDebugHeliTracker)
|
|
SetTracker(initParams);
|
|
else
|
|
#endif
|
|
{
|
|
initParams.Tracker = NULL;
|
|
initParams.TrackEntityPosition = false;
|
|
}
|
|
CreateSound_PersistentReference(m_HeliAudioSettings->RearRotorLoop, &m_HeliRearRotor, &initParams);
|
|
|
|
if(instantStart)
|
|
{
|
|
UpdateHeliEngineSoundsOn(heliValues);
|
|
}
|
|
else
|
|
{
|
|
UpdateHeliEngineSoundStartingStopping(heliValues);
|
|
}
|
|
|
|
if (m_HeliBank)
|
|
{
|
|
m_HeliBank->SetReleaseTime(g_audVehicleLoopReleaseTime);
|
|
m_HeliBank->PrepareAndPlay();
|
|
}
|
|
|
|
if (m_HeliExhaust)
|
|
{
|
|
m_HeliExhaust->SetReleaseTime(g_audVehicleLoopReleaseTime);
|
|
m_HeliExhaust->PrepareAndPlay();
|
|
}
|
|
|
|
if (m_HeliRearRotor)
|
|
{
|
|
m_HeliRearRotor->SetReleaseTime(g_audVehicleLoopReleaseTime);
|
|
m_HeliRearRotor->PrepareAndPlay();
|
|
}
|
|
|
|
if (m_HeliRotor)
|
|
{
|
|
m_HeliRotor->SetReleaseTime(g_audVehicleLoopReleaseTime);
|
|
m_HeliRotor->PrepareAndPlay();
|
|
}
|
|
|
|
if(m_HeliRotorLowFreq)
|
|
{
|
|
m_HeliRotorLowFreq->SetReleaseTime(g_audVehicleLoopReleaseTime);
|
|
m_HeliRotorLowFreq->PrepareAndPlay();
|
|
}
|
|
|
|
if (m_DistantRotor)
|
|
{
|
|
m_DistantRotor->SetReleaseTime(g_audVehicleLoopReleaseTime);
|
|
m_DistantRotor->PrepareAndPlay();
|
|
}
|
|
|
|
|
|
// Kick off our one-shot startup sound, unless we're instant starting
|
|
if (!instantStart)
|
|
{
|
|
if(m_StartupSound)
|
|
{
|
|
m_StartupSound->StopAndForget();
|
|
}
|
|
|
|
audSoundInitParams initParams;
|
|
SetTracker(initParams);
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
CreateAndPlaySound_Persistent(m_HeliAudioSettings->StartUpOneShot, &m_StartupSound, &initParams);
|
|
}
|
|
|
|
m_PitchShiftIndex = 0;
|
|
if(!m_IsPlayerVehicle)
|
|
{
|
|
sm_PitchShiftIndex = (sm_PitchShiftIndex + 1) % NUM_NPC_PICH_SHIFTS;
|
|
m_PitchShiftIndex = sm_PitchShiftIndex;
|
|
}
|
|
|
|
m_EngineEffectWetSmoother.Reset();
|
|
m_EngineEffectWetSmoother.CalculateValue(0.0f,fwTimer::GetTimeStep());
|
|
UpdateHeliEngineSounds(heliValues);
|
|
}
|
|
}
|
|
|
|
|
|
void audHeliAudioEntity::UpdateDamageSounds(audHeliValues& heliValues)
|
|
{
|
|
if (m_HeliAudioSettings && (m_IsPlayerVehicle || m_EnableCrazyHeliSounds) && m_HeliState != AUD_HELI_OFF)
|
|
{
|
|
f32 engineHealth = m_Vehicle->GetVehicleDamage()->GetEngineHealth();
|
|
if(!m_HeliDamage && (m_EnableCrazyHeliSounds || (engineHealth < 950.0f && engineHealth > 600.0f)) )
|
|
{
|
|
audSoundInitParams initParams;
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
SetTracker(initParams);
|
|
|
|
CreateSound_PersistentReference(m_HeliAudioSettings->DamageLoop, &m_HeliDamage, &initParams);
|
|
|
|
if(m_HeliDamage)
|
|
{
|
|
m_HeliDamage->SetReleaseTime(g_audVehicleLoopReleaseTime);
|
|
m_HeliDamage->PrepareAndPlay();
|
|
m_HeliDamage->SetRequestedVolume(heliValues.damageVolume);
|
|
}
|
|
|
|
if(m_HeliDamageBelow600)
|
|
{
|
|
m_HeliDamageBelow600->StopAndForget();
|
|
}
|
|
if (m_HeliDamageOneShots)
|
|
{
|
|
m_HeliDamageOneShots->StopAndForget();
|
|
}
|
|
}
|
|
if(engineHealth <= 600.0f)
|
|
{
|
|
if(!m_HeliDamageBelow600)
|
|
{
|
|
audSoundInitParams initParams;
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
SetTracker(initParams);
|
|
|
|
CreateSound_PersistentReference(m_HeliAudioSettings->DamageBelow600Loop, &m_HeliDamageBelow600, &initParams);
|
|
|
|
if(m_HeliDamageBelow600)
|
|
{
|
|
m_HeliDamageBelow600->SetReleaseTime(g_audVehicleLoopReleaseTime);
|
|
m_HeliDamageBelow600->PrepareAndPlay();
|
|
m_HeliDamageBelow600->SetRequestedVolume(heliValues.damageVolumeBelow600);
|
|
}
|
|
if(m_HeliDamage)
|
|
{
|
|
m_HeliDamage->StopAndForget();
|
|
}
|
|
}
|
|
|
|
if(!m_HeliDamageOneShots)
|
|
{
|
|
audSoundInitParams initParams;
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
SetTracker(initParams);
|
|
|
|
CreateSound_PersistentReference(m_HeliAudioSettings->DamageOneShots, &m_HeliDamageOneShots, &initParams);
|
|
|
|
if (m_HeliDamageOneShots)
|
|
{
|
|
m_HeliDamageOneShots->SetReleaseTime(g_audVehicleLoopReleaseTime);
|
|
m_HeliDamageOneShots->PrepareAndPlay();
|
|
m_HeliDamageOneShots->SetRequestedVolume(heliValues.damageVolumeBelow600);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(m_HeliDamage)
|
|
m_HeliDamage->StopAndForget();
|
|
if(m_HeliDamageBelow600)
|
|
m_HeliDamageBelow600->StopAndForget();
|
|
if(m_HeliDamageOneShots)
|
|
m_HeliDamageOneShots->StopAndForget();
|
|
}
|
|
|
|
u32 currentTime = fwTimer::GetTimeInMilliseconds();
|
|
CHeli* heli = static_cast<CHeli*>(m_Vehicle);
|
|
if(m_HeliState != AUD_HELI_OFF && heli->m_Transmission.GetCurrentlyMissFiring() && currentTime > (m_BackFireTime + 2000))
|
|
{
|
|
TriggerBackFire();
|
|
}
|
|
|
|
}
|
|
|
|
void audHeliAudioEntity::TriggerBackFire()
|
|
{
|
|
if(m_HeliAudioSettings == NULL)
|
|
return;
|
|
|
|
audSoundInitParams initParams;
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
SetTracker(initParams);
|
|
|
|
if(GetVehicleModelNameHash() == ATSTRINGHASH("THRUSTER", 0x58CDAF30))
|
|
{
|
|
CreateAndPlaySound(ATSTRINGHASH("thruster_missfire", 0xE9ED2B72), &initParams);
|
|
}
|
|
else
|
|
{
|
|
CreateAndPlaySound(ATSTRINGHASH("HELICOPTER_MISSFIRE", 0xE9062F56), &initParams);
|
|
}
|
|
|
|
m_BackFireTime = fwTimer::GetTimeInMilliseconds();
|
|
}
|
|
|
|
|
|
bool audHeliAudioEntity::IsEngineOn() const
|
|
{
|
|
bool engineOn = m_Vehicle->m_nVehicleFlags.bEngineOn;
|
|
|
|
if(m_Vehicle->GetStatus() == STATUS_WRECKED)
|
|
{
|
|
engineOn = false;
|
|
}
|
|
|
|
return engineOn;
|
|
}
|
|
// ----------------------------------------------------------------
|
|
// audHeliAudioEntity UpdateHeliEngineSounds
|
|
// ----------------------------------------------------------------
|
|
void audHeliAudioEntity::UpdateHeliEngineSounds(audHeliValues& heliValues)
|
|
{
|
|
#if __BANK
|
|
SetupHeliVolumeCones();
|
|
#endif
|
|
|
|
s32 slowMoRotorPitch = 0;
|
|
|
|
s16 pitchShift = sm_PitchShift[m_PitchShiftIndex];
|
|
#if __BANK
|
|
if(m_IsPlayerVehicle && g_PitchShiftIndex != -1)
|
|
{
|
|
pitchShift = sm_PitchShift[g_PitchShiftIndex];
|
|
}
|
|
#endif
|
|
|
|
// ensure there is always some predelay on the blades when in slow mo
|
|
if(fwTimer::GetTimeWarp()<1.f || audNorthAudioEngine::IsInSlowMoVideoEditor())
|
|
{
|
|
slowMoRotorPitch = g_HeliSlowMoPitch;
|
|
}
|
|
|
|
f32 slowmoVolume = UpdateSlowmoRotorSounds();
|
|
|
|
// Set the position of the rear rotor
|
|
CVehicleModelInfo* modelInfo = (CVehicleModelInfo *)m_Vehicle->GetBaseModelInfo();
|
|
audAssert(modelInfo);
|
|
|
|
// check for broken-off rotors
|
|
f32 brokenRotorVolume = 0.0f;
|
|
f32 rearRotorBrokenVolume = 0.0f;
|
|
if (((CHeli*)m_Vehicle)->GetMainRotorHealth()<=0.0f)
|
|
{
|
|
brokenRotorVolume = g_SilenceVolume;
|
|
}
|
|
if (((CHeli*)m_Vehicle)->GetRearRotorHealth()<=0.0f || ((CHeli*)m_Vehicle)->GetTailBoomHealth()<=0.0f)
|
|
{
|
|
rearRotorBrokenVolume = g_SilenceVolume;
|
|
}
|
|
if(((CHeli*)m_Vehicle)->GetIsCargobob())
|
|
{
|
|
if(brokenRotorVolume == g_SilenceVolume && rearRotorBrokenVolume != g_SilenceVolume)
|
|
{
|
|
brokenRotorVolume = 0.0f;
|
|
}
|
|
}
|
|
|
|
bool playerInInterior = audNorthAudioEngine::GetGtaEnvironment()->AreWeInAnInterior();
|
|
if(!m_IsPlayerVehicle && playerInInterior)
|
|
{
|
|
f32 exteriorOcclusionFactor = audNorthAudioEngine::GetOcclusionManager()->GetExteriorOcclusionFor3DPosition(VEC3V_TO_VECTOR3(m_Vehicle->GetTransform().GetPosition()));
|
|
static bank_float maxOcclusion = 0.25f;
|
|
exteriorOcclusionFactor = Clamp(exteriorOcclusionFactor, 0.0f, maxOcclusion);
|
|
BANK_ONLY(m_DebugOcclusion = exteriorOcclusionFactor;)
|
|
if(m_EnvironmentGroup)
|
|
{
|
|
m_EnvironmentGroup->SetExtraOcclusionValue(exteriorOcclusionFactor);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(m_EnvironmentGroup)
|
|
{
|
|
m_EnvironmentGroup->SetExtraOcclusionValue(0.0f);
|
|
}
|
|
BANK_ONLY(m_DebugOcclusion = 0.0f;)
|
|
}
|
|
|
|
static s32 heliPitchClamp = -600;
|
|
|
|
f32 timewarp = fwTimer::GetTimeWarpActive();
|
|
if(timewarp > 0.0f)
|
|
{
|
|
timewarp = 1.0f/timewarp;
|
|
}
|
|
|
|
f32 onlyReplayWarp = 1.0f;
|
|
f32 onlyReplayLFFilter = 23999.0f;
|
|
#if GTA_REPLAY
|
|
if(CReplayMgr::IsEditModeActive())
|
|
{
|
|
timewarp = CReplayMgr::GetMarkerSpeed();
|
|
if(timewarp < 0.36f)
|
|
{
|
|
onlyReplayLFFilter = 600.0f;
|
|
}
|
|
else if(timewarp <= 0.55f)
|
|
{
|
|
onlyReplayLFFilter = 1200.0f;
|
|
}
|
|
static const audThreePointPiecewiseLinearCurve replayTimeScaleCurve(0.05f, 0.175f, 0.475f, 0.55f, 2.0f, 2.0f);
|
|
timewarp = replayTimeScaleCurve.CalculateValue(timewarp);
|
|
timewarp = 1.0f/timewarp;
|
|
onlyReplayWarp = timewarp;
|
|
|
|
BANK_ONLY( if(g_HeliLowPassFilter < 23000.0f) onlyReplayLFFilter = g_HeliLowPassFilter; )
|
|
BANK_ONLY( if(g_HeliRotorTriggerRate != 1.0f) onlyReplayWarp = g_HeliRotorTriggerRate; )
|
|
}
|
|
#endif
|
|
if(m_HeliRotor)
|
|
{
|
|
if(onlyReplayLFFilter < 23000.0f)
|
|
{
|
|
m_HeliRotor->SetRequestedLPFCutoff(onlyReplayLFFilter);
|
|
}
|
|
m_HeliRotor->SetRequestedVolume(brokenRotorVolume + (m_HeliRotorSlowmo? slowmoVolume : 0.0f));
|
|
m_HeliRotor->SetRequestedPitch(Max(heliPitchClamp, heliValues.rotorPitch+slowMoRotorPitch+pitchShift));
|
|
m_HeliRotor->FindAndSetVariableValue(ATSTRINGHASH("triggerRate", 0x38F36A3D), heliValues.triggerRate*onlyReplayWarp);
|
|
m_HeliRotor->FindAndSetVariableValue(ATSTRINGHASH("ROTOR_VOLUME", 0x43824A32), heliValues.rotorVolume);
|
|
m_HeliRotor->FindAndSetVariableValue(ATSTRINGHASH("BLADE_VOLUME", 0x5785CE8E), heliValues.bladeVolume);
|
|
m_HeliRotor->FindAndSetVariableValue(ATSTRINGHASH("BankingAngle", 0xD6BB74F6), heliValues.banking);
|
|
m_HeliRotor->FindAndSetVariableValue(ATSTRINGHASH("throttle", 0xEA0151DC), heliValues.throttle);
|
|
}
|
|
|
|
if(m_HeliRotorSlowmo)
|
|
{
|
|
m_HeliRotorSlowmo->SetRequestedVolume(brokenRotorVolume);
|
|
m_HeliRotorSlowmo->SetRequestedPitch(Max(heliPitchClamp, heliValues.rotorPitch+pitchShift));
|
|
m_HeliRotorSlowmo->FindAndSetVariableValue(ATSTRINGHASH("triggerRate", 0x38F36A3D), heliValues.triggerRate*timewarp);
|
|
m_HeliRotorSlowmo->FindAndSetVariableValue(ATSTRINGHASH("ROTOR_VOLUME", 0x43824A32), heliValues.rotorVolume);
|
|
m_HeliRotorSlowmo->FindAndSetVariableValue(ATSTRINGHASH("BLADE_VOLUME", 0x5785CE8E), heliValues.bladeVolume);
|
|
m_HeliRotorSlowmo->FindAndSetVariableValue(ATSTRINGHASH("BankingAngle", 0xD6BB74F6), heliValues.banking);
|
|
m_HeliRotorSlowmo->FindAndSetVariableValue(ATSTRINGHASH("throttle", 0xEA0151DC), heliValues.throttle);
|
|
}
|
|
|
|
if(m_HeliRotorLowFreq)
|
|
{
|
|
m_HeliRotorLowFreq->SetRequestedVolume(brokenRotorVolume + (m_HeliRotorLowFreqSlowmo? slowmoVolume : 0.0f));
|
|
m_HeliRotorLowFreq->SetRequestedPitch(Max(heliPitchClamp, heliValues.rotorPitch+slowMoRotorPitch+pitchShift));
|
|
m_HeliRotorLowFreq->FindAndSetVariableValue(ATSTRINGHASH("triggerRate", 0x38F36A3D), heliValues.triggerRate*onlyReplayWarp);
|
|
m_HeliRotorLowFreq->FindAndSetVariableValue(ATSTRINGHASH("ROTOR_VOLUME", 0x43824A32), heliValues.rotorVolume);
|
|
m_HeliRotorLowFreq->FindAndSetVariableValue(ATSTRINGHASH("BLADE_VOLUME", 0x5785CE8E), heliValues.bladeVolume);
|
|
m_HeliRotorLowFreq->FindAndSetVariableValue(ATSTRINGHASH("BankingAngle", 0xD6BB74F6), heliValues.banking);
|
|
m_HeliRotorLowFreq->FindAndSetVariableValue(ATSTRINGHASH("throttle", 0xEA0151DC), heliValues.throttle);
|
|
}
|
|
|
|
if(m_HeliRotorLowFreqSlowmo)
|
|
{
|
|
m_HeliRotorLowFreqSlowmo->SetRequestedVolume(brokenRotorVolume);
|
|
m_HeliRotorLowFreqSlowmo->SetRequestedPitch(Max(heliPitchClamp, heliValues.rotorPitch+pitchShift));
|
|
m_HeliRotorLowFreqSlowmo->FindAndSetVariableValue(ATSTRINGHASH("triggerRate", 0x38F36A3D), heliValues.triggerRate*timewarp);
|
|
m_HeliRotorLowFreqSlowmo->FindAndSetVariableValue(ATSTRINGHASH("ROTOR_VOLUME", 0x43824A32), heliValues.rotorVolume);
|
|
m_HeliRotorLowFreqSlowmo->FindAndSetVariableValue(ATSTRINGHASH("BLADE_VOLUME", 0x5785CE8E), heliValues.bladeVolume);
|
|
m_HeliRotorLowFreqSlowmo->FindAndSetVariableValue(ATSTRINGHASH("BankingAngle", 0xD6BB74F6), heliValues.banking);
|
|
m_HeliRotorLowFreqSlowmo->FindAndSetVariableValue(ATSTRINGHASH("throttle", 0xEA0151DC), heliValues.throttle);
|
|
}
|
|
|
|
if(m_DistantRotor)
|
|
{
|
|
m_DistantRotor->SetRequestedVolume(brokenRotorVolume);
|
|
m_DistantRotor->SetRequestedPitch(Max(heliPitchClamp, heliValues.rotorPitch+slowMoRotorPitch+pitchShift));
|
|
m_DistantRotor->FindAndSetVariableValue(ATSTRINGHASH("triggerRate", 0x38F36A3D), heliValues.triggerRate*timewarp);
|
|
m_DistantRotor->FindAndSetVariableValue(ATSTRINGHASH("ROTOR_VOLUME", 0x43824A32), heliValues.rotorVolume);
|
|
m_DistantRotor->FindAndSetVariableValue(ATSTRINGHASH("BLADE_VOLUME", 0x5785CE8E), heliValues.bladeVolume);
|
|
m_DistantRotor->FindAndSetVariableValue(ATSTRINGHASH("BankingAngle", 0xD6BB74F6), heliValues.banking);
|
|
m_DistantRotor->FindAndSetVariableValue(ATSTRINGHASH("throttle", 0xEA0151DC), heliValues.throttle);
|
|
}
|
|
|
|
|
|
if(m_HeliRearRotor)
|
|
{
|
|
m_HeliRearRotor->SetRequestedVolume(heliValues.rearRotorVolume + rearRotorBrokenVolume);
|
|
|
|
BANK_ONLY(if(!g_UseDebugHeliTracker))
|
|
{
|
|
s32 rearRotorBoneIndex = modelInfo->GetBoneIndex(HELI_ROTOR_REAR);
|
|
if(rearRotorBoneIndex > -1)
|
|
{
|
|
Matrix34 rearRotorMatrix = RCC_MATRIX34(m_Vehicle->GetSkeletonData().GetDefaultTransform(rearRotorBoneIndex));
|
|
rearRotorMatrix.d = m_Vehicle->TransformIntoWorldSpace(rearRotorMatrix.d);
|
|
m_HeliRearRotor->SetRequestedPosition(rearRotorMatrix.d);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(m_HeliExhaust)
|
|
{
|
|
m_HeliExhaust->SetRequestedVolume(heliValues.exhaustVolume);
|
|
m_HeliExhaust->SetRequestedPitch(heliValues.exhaustPitch + pitchShift);
|
|
m_HeliExhaust->FindAndSetVariableValue(ATSTRINGHASH("BankingAngle", 0xD6BB74F6), heliValues.banking);
|
|
m_HeliExhaust->FindAndSetVariableValue(ATSTRINGHASH("throttle", 0xEA0151DC), heliValues.throttle);
|
|
|
|
if(GetVehicleModelNameHash() == ATSTRINGHASH("THRUSTER", 0x58CDAF30))
|
|
{
|
|
f32 rollAngle = m_Vehicle->GetTransform().GetRoll() * RtoD;
|
|
f32 pitchAngle = AcosfSafe(Dot(m_Vehicle->GetTransform().GetB(), Vec3V(V_Z_AXIS_WZERO)).Getf()) * RtoD;
|
|
f32 yawAngle = m_Vehicle->GetTransform().GetHeading() * RtoD;
|
|
f32 angularVelocity = GetCachedAngularVelocity().Mag();
|
|
m_HeliExhaust->FindAndSetVariableValue(ATSTRINGHASH("throttleInput", 0x918028C4), heliValues.throttleInput);
|
|
m_HeliExhaust->FindAndSetVariableValue(ATSTRINGHASH("rollAngle", 0x94FC4D71), rollAngle);
|
|
m_HeliExhaust->FindAndSetVariableValue(ATSTRINGHASH("pitchAngle", 0x809A226D), pitchAngle);
|
|
m_HeliExhaust->FindAndSetVariableValue(ATSTRINGHASH("yawAngle", 0x15DE02B1), yawAngle);
|
|
m_HeliExhaust->FindAndSetVariableValue(ATSTRINGHASH("angularVelocity", 0xC90EACC2), angularVelocity);
|
|
}
|
|
}
|
|
|
|
if(m_HeliBank)
|
|
{
|
|
m_HeliBank->SetRequestedVolume(heliValues.bankingVolume);
|
|
m_HeliBank->SetRequestedPitch(heliValues.bankingPitch + pitchShift);
|
|
m_HeliBank->FindAndSetVariableValue(ATSTRINGHASH("throttle", 0xEA0151DC), heliValues.throttle);
|
|
}
|
|
|
|
if(m_HeliDamage)
|
|
{
|
|
m_HeliDamage->SetRequestedVolume(heliValues.damageVolume);
|
|
}
|
|
|
|
if(m_HeliDamageBelow600)
|
|
{
|
|
m_HeliDamageBelow600->SetRequestedVolume(heliValues.damageVolume);
|
|
}
|
|
|
|
if(m_HeliDamageOneShots)
|
|
{
|
|
m_HeliDamageOneShots->SetRequestedVolume(heliValues.damageVolume);
|
|
}
|
|
|
|
// Update filters
|
|
m_MainRotorVolume = heliValues.rotorVolume + brokenRotorVolume;
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// Updates engine sounds when the engine is turned on
|
|
// ----------------------------------------------------------------
|
|
void audHeliAudioEntity::UpdateHeliEngineSoundsOn(audHeliValues& heliValues)
|
|
{
|
|
// Use the throttle value from CHeli - this is already quite smoothed, possibly too smoothed for us
|
|
heliValues.throttle = m_Throttle;
|
|
f32 throttleInput = m_Throttle;
|
|
|
|
if(m_IsPlayerDrivingVehicle)
|
|
{
|
|
const CPed* playerPed = FindPlayerPed();
|
|
|
|
if(playerPed)
|
|
{
|
|
const CControl* pedControl = playerPed->GetControlFromPlayer();
|
|
|
|
if(pedControl)
|
|
{
|
|
throttleInput = 1.0f + (pedControl->GetVehicleFlyThrottleUp().GetNorm01() - pedControl->GetVehicleFlyThrottleDown().GetNorm01());
|
|
}
|
|
}
|
|
}
|
|
|
|
heliValues.throttleInput = throttleInput;
|
|
heliValues.rotorVolume = m_RotorThrottleVolCurve.CalculateValue(m_Throttle);
|
|
heliValues.bladeVolume = m_RotorThrottleVolCurve.CalculateValue(m_Throttle);
|
|
heliValues.rotorPitch = (s32)m_RotorThrottlePitchCurve.CalculateValue(m_Throttle);
|
|
heliValues.rearRotorVolume = m_RearRotorThrottleVolCurve.CalculateValue(m_Throttle);
|
|
heliValues.exhaustVolume = m_ExhaustThrottleVolCurve.CalculateValue(m_Throttle);
|
|
heliValues.bankingVolume = m_BankThrottleVolumeCurve.CalculateValue(m_Throttle);
|
|
heliValues.triggerRate = m_RotorSpeedToTriggerSpeedCurve.CalculateValue(m_MainRotorSpeed);
|
|
|
|
f32 vehicleHealth = m_Vehicle->GetHealth();
|
|
if (g_OverrideHeliHealth)
|
|
{
|
|
vehicleHealth = g_OverridenHeliHealth;
|
|
}
|
|
heliValues.health = Clamp(vehicleHealth/1000.0f, 0.0f, 1.0f);
|
|
heliValues.damageVolume = audDriverUtil::ComputeDbVolumeFromLinear(m_DamageVolumeCurve.CalculateValue(vehicleHealth));
|
|
heliValues.damageVolumeBelow600 = audDriverUtil::ComputeDbVolumeFromLinear(m_DamageVolumeBelow600Curve.CalculateValue(vehicleHealth));
|
|
// Do a few pitch changes too
|
|
heliValues.bankingPitch = (s32)m_BankThrottlePitchCurve.CalculateValue(m_Throttle);
|
|
heliValues.exhaustPitch = (s32)m_ExhaustThrottlePitchCurve.CalculateValue(m_Throttle);
|
|
|
|
f32 bankingAngleVolume = m_BankAngleVolCurve.CalculateValue(heliValues.banking);
|
|
|
|
// Calculate coning attenuations
|
|
const Mat34V mat = m_Vehicle->GetMatrix();
|
|
heliValues.rotorVolume += (m_EngineVolumeCone.ComputeAttenuation(mat) + m_RotorThumpVolumeCone.ComputeAttenuation(mat));
|
|
heliValues.bladeVolume += (m_EngineVolumeCone.ComputeAttenuation(mat) + m_RotorBladeVolumeCone.ComputeAttenuation(mat));
|
|
heliValues.rearRotorVolume += m_RearRotorVolumeCone.ComputeAttenuation(mat);
|
|
heliValues.exhaustVolume += m_ExhaustVolumeCone.ComputeAttenuation(mat);
|
|
heliValues.bankingVolume += bankingAngleVolume;
|
|
|
|
if (m_Vehicle->m_nVehicleFlags.bIsDrowning)
|
|
{
|
|
m_HeliDamageFluctuator.SetBands(1.0f, 1.0f, 1.0f, 1.0f);
|
|
}
|
|
else
|
|
{
|
|
m_HeliDamageFluctuator.SetBands(0.0f, 0.2f, 0.8f, 1.0f);
|
|
}
|
|
|
|
f32 damageVolumeOffsetLinear = m_HeliDamageFluctuator.CalculateValue();
|
|
f32 damageVolumeOffset = g_HeliDamageVolumeRange*damageVolumeOffsetLinear;
|
|
|
|
heliValues.damageVolume += damageVolumeOffset;
|
|
heliValues.damageVolumeBelow600 += damageVolumeOffset;
|
|
|
|
// duck the exhaust inversely to the main damage loop
|
|
f32 exhastDamageVolumeOffset = g_HeliDamageVolumeRange - damageVolumeOffset;
|
|
exhastDamageVolumeOffset *= (1.0f-heliValues.health);
|
|
|
|
heliValues.exhaustVolume += exhastDamageVolumeOffset;
|
|
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// Update engine sounds when its in the process of starting/stopping
|
|
// ----------------------------------------------------------------
|
|
void audHeliAudioEntity::UpdateHeliEngineSoundStartingStopping(audHeliValues& heliValues)
|
|
{
|
|
// get the usual in-flight values, then interp between them and us, so it's fully them when we hand over control
|
|
UpdateHeliEngineSoundsOn(heliValues);
|
|
|
|
f32 starting = sm_HeliStartupToNormalCurve.CalculateValue(heliValues.startup);
|
|
f32 regular = 1.0f - starting;
|
|
|
|
audHeliValues startingHeliValues;
|
|
startingHeliValues.throttle = 0.0f;
|
|
startingHeliValues.rotorVolume = audDriverUtil::ComputeDbVolumeFromLinear(m_RotorVolStartupCurve.CalculateValue(heliValues.startup));
|
|
startingHeliValues.bladeVolume = audDriverUtil::ComputeDbVolumeFromLinear(m_BladeVolStartupCurve.CalculateValue(heliValues.startup));
|
|
startingHeliValues.rearRotorVolume = audDriverUtil::ComputeDbVolumeFromLinear(m_RearRotorVolStartupCurve.CalculateValue(heliValues.startup));
|
|
startingHeliValues.exhaustVolume = audDriverUtil::ComputeDbVolumeFromLinear(m_ExhaustVolStartupCurve.CalculateValue(heliValues.startup));
|
|
startingHeliValues.bankingVolume = g_SilenceVolume;
|
|
startingHeliValues.damageVolume = g_SilenceVolume;
|
|
startingHeliValues.damageVolumeBelow600 = g_SilenceVolume;
|
|
startingHeliValues.health = 1.0f;
|
|
|
|
// Do a few pitch changes too
|
|
startingHeliValues.bankingPitch = 0;
|
|
startingHeliValues.rotorPitch = (s32)m_RotorPitchStartupCurve.CalculateValue(heliValues.startup);
|
|
startingHeliValues.exhaustPitch = (s32)m_ExhaustPitchStartupCurve.CalculateValue(heliValues.startup);
|
|
// Calculate coning attenuations
|
|
const Mat34V mat = m_Vehicle->GetMatrix();
|
|
startingHeliValues.rotorVolume += (m_EngineVolumeCone.ComputeAttenuation(mat) + m_RotorThumpVolumeCone.ComputeAttenuation(mat));
|
|
startingHeliValues.bladeVolume += (m_EngineVolumeCone.ComputeAttenuation(mat) + m_RotorBladeVolumeCone.ComputeAttenuation(mat));
|
|
startingHeliValues.rearRotorVolume += m_RearRotorVolumeCone.ComputeAttenuation(mat);
|
|
startingHeliValues.exhaustVolume += m_ExhaustVolumeCone.ComputeAttenuation(mat);
|
|
|
|
// now interp
|
|
heliValues.throttle = starting*startingHeliValues.throttle + regular*heliValues.throttle;
|
|
heliValues.rotorVolume = starting*startingHeliValues.rotorVolume + regular*heliValues.rotorVolume;
|
|
heliValues.bladeVolume = starting*startingHeliValues.bladeVolume + regular*heliValues.bladeVolume;
|
|
heliValues.rearRotorVolume = starting*startingHeliValues.rearRotorVolume + regular*heliValues.rearRotorVolume;
|
|
heliValues.exhaustVolume = starting*startingHeliValues.exhaustVolume + regular*heliValues.exhaustVolume;
|
|
heliValues.bankingVolume = starting*startingHeliValues.bankingVolume + regular*heliValues.bankingVolume;
|
|
heliValues.damageVolume = starting*startingHeliValues.damageVolume + regular*heliValues.damageVolume;
|
|
heliValues.damageVolumeBelow600 = starting*startingHeliValues.damageVolumeBelow600 + regular*heliValues.damageVolumeBelow600;
|
|
heliValues.bankingPitch = (s32)(starting*(f32)(startingHeliValues.bankingPitch) + regular*(f32)(heliValues.bankingPitch));
|
|
heliValues.exhaustPitch = (s32)(starting*(f32)(startingHeliValues.exhaustPitch) + regular*(f32)(heliValues.exhaustPitch));
|
|
heliValues.rotorPitch = (s32)(starting*(f32)(startingHeliValues.rotorPitch) + regular*(f32)(heliValues.rotorPitch));
|
|
heliValues.triggerRate = heliValues.triggerRate;
|
|
|
|
if (m_Vehicle->m_nVehicleFlags.bIsDrowning)
|
|
{
|
|
m_HeliDamageFluctuator.SetBands(1.0f, 1.0f, 1.0f, 1.0f);
|
|
}
|
|
else
|
|
{
|
|
m_HeliDamageFluctuator.SetBands(0.0f, 0.2f, 0.8f, 1.0f);
|
|
}
|
|
|
|
f32 damageVolumeOffsetLinear = m_HeliDamageFluctuator.CalculateValue();
|
|
f32 damageVolumeOffset = g_HeliDamageVolumeRange*damageVolumeOffsetLinear;
|
|
|
|
heliValues.damageVolume += damageVolumeOffset;
|
|
heliValues.damageVolumeBelow600 += damageVolumeOffset;
|
|
|
|
// duck the exhaust inversely to the main damage loop
|
|
f32 exhastDamageVolumeOffset = g_HeliDamageVolumeRange - damageVolumeOffset;
|
|
exhastDamageVolumeOffset *= (1.0f-heliValues.health);
|
|
|
|
heliValues.exhaustVolume += exhastDamageVolumeOffset;
|
|
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// Stop all the helicopter related sounds
|
|
// ----------------------------------------------------------------
|
|
void audHeliAudioEntity::StopHeliEngineSounds()
|
|
{
|
|
StopAndForgetSounds(m_HeliBank, m_HeliExhaust, m_HeliRotor, m_HeliRotorLowFreq, m_HeliRearRotor, m_HeliDamage, m_HeliDamageBelow600, m_HeliDamageOneShots);
|
|
StopAndForgetSounds(m_DistantRotor, m_HeliDamageWarning, m_HeliRotorSlowmo, m_HeliRotorLowFreqSlowmo);
|
|
|
|
if(((CHeli*)m_Vehicle)->GetMainRotorSpeed() < 0.1f && m_HeliGoingDown)
|
|
{
|
|
StopGoingDownSound();
|
|
}
|
|
m_EngineOffTemperature = m_Vehicle->m_EngineTemperature;
|
|
}
|
|
|
|
void audHeliAudioEntity::VehicleExploded()
|
|
{
|
|
StopGoingDownSound();
|
|
m_Exploded = true;
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// Play the tail break sound
|
|
// ----------------------------------------------------------------
|
|
void audHeliAudioEntity::PlayTailBreakSound()
|
|
{
|
|
if(m_HeliAudioSettings)
|
|
CreateDeferredSound(m_HeliAudioSettings->TailBreak, m_Vehicle, NULL, true, true);
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// Play the rotor break sound
|
|
// ----------------------------------------------------------------
|
|
void audHeliAudioEntity::PlayRotorBreakSound()
|
|
{
|
|
if(m_HeliAudioSettings)
|
|
CreateDeferredSound(m_HeliAudioSettings->RotorBreak, m_Vehicle, NULL, true, true);
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// Play rear rotor break sound
|
|
// ----------------------------------------------------------------
|
|
void audHeliAudioEntity::PlayRearRotorBreakSound()
|
|
{
|
|
if(m_HeliAudioSettings)
|
|
CreateDeferredSound(m_HeliAudioSettings->RearRotorBreak, m_Vehicle, NULL, true, true);
|
|
}
|
|
|
|
void audHeliAudioEntity::PlayHookDeploySound()
|
|
{
|
|
if(m_HeliAudioSettings)
|
|
CreateDeferredSound(m_HeliAudioSettings->CableDeploy, m_Vehicle, NULL, true, true);
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// audHeliAudioEntity GetCabinToneSound
|
|
// ----------------------------------------------------------------
|
|
u32 audHeliAudioEntity::GetCabinToneSound() const
|
|
{
|
|
if(m_HeliAudioSettings)
|
|
{
|
|
return m_HeliAudioSettings->CabinToneLoop;
|
|
}
|
|
|
|
return audVehicleAudioEntity::GetCabinToneSound();
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// audHeliAudioEntity GetVehicleRainSound
|
|
// ----------------------------------------------------------------
|
|
u32 audHeliAudioEntity::GetVehicleRainSound(bool interiorView) const
|
|
{
|
|
if(m_HeliAudioSettings)
|
|
{
|
|
if(interiorView)
|
|
{
|
|
return m_HeliAudioSettings->VehicleRainSoundInterior;
|
|
}
|
|
else
|
|
{
|
|
return m_HeliAudioSettings->VehicleRainSound;
|
|
}
|
|
}
|
|
|
|
return audVehicleAudioEntity::GetVehicleRainSound(interiorView);
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// Setup volume cones
|
|
// ----------------------------------------------------------------
|
|
void audHeliAudioEntity::SetupHeliVolumeCones()
|
|
{
|
|
Vec3V frontConeDir = Vec3V(V_Y_AXIS_WZERO);
|
|
Vec3V rearConeDir = -Vec3V(V_Y_AXIS_WZERO);
|
|
Vec3V upConeDir = Vec3V(V_Z_AXIS_WZERO);
|
|
Vec3V downConeDir = -Vec3V(V_Z_AXIS_WZERO);
|
|
|
|
m_EngineVolumeCone.Init(frontConeDir, m_HeliAudioSettings->RotorConeAtten/100.f, m_HeliAudioSettings->RotorConeFrontAngle, m_HeliAudioSettings->RotorConeRearAngle);
|
|
m_ExhaustVolumeCone.Init(rearConeDir, m_HeliAudioSettings->ExhaustConeAtten/100.f, m_HeliAudioSettings->ExhaustConeFrontAngle, m_HeliAudioSettings->ExhaustConeRearAngle);
|
|
|
|
m_RotorBladeVolumeCone.Init(upConeDir, m_HeliAudioSettings->BladeConeAtten/100.f, m_HeliAudioSettings->BladeConeUpAngle, m_HeliAudioSettings->BladeConeDownAngle);
|
|
m_RotorThumpVolumeCone.Init(downConeDir, m_HeliAudioSettings->ThumpConeAtten/100.f, m_HeliAudioSettings->ThumpConeDownAngle, m_HeliAudioSettings->ThumpConeUpAngle);
|
|
m_RearRotorVolumeCone.Init(rearConeDir, m_HeliAudioSettings->RearRotorConeAtten/100.f, m_HeliAudioSettings->RearRotorConeFrontAngle, m_HeliAudioSettings->RearRotorConeRearAngle);
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// Trigger downwash effect
|
|
// ----------------------------------------------------------------
|
|
void audHeliAudioEntity::TriggerDownwash(const u32 soundHash, const Vector3 &pos, const f32 distEvo, const f32 UNUSED_PARAM(speedEvo), const f32 UNUSED_PARAM(angleEvo), const f32 rotorEvo)
|
|
{
|
|
if(!m_HeliDownwash || m_HeliDownwashHash != soundHash)
|
|
{
|
|
if(m_HeliDownwash)
|
|
{
|
|
m_HeliDownwash->StopAndForget();
|
|
}
|
|
audSoundInitParams initParams;
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
CreateAndPlaySound_Persistent(soundHash, &m_HeliDownwash, &initParams);
|
|
m_HeliDownwashHash = soundHash;
|
|
}
|
|
|
|
m_LastHeliDownwashTime = fwTimer::GetTimeInMilliseconds();
|
|
|
|
if(m_HeliDownwash)
|
|
{
|
|
#if __BANK
|
|
if(g_UseDebugHeliTracker)
|
|
m_HeliDownwash->SetRequestedPosition(m_DebugTracker.GetPosition());
|
|
else
|
|
#endif
|
|
m_HeliDownwash->SetRequestedPosition(pos);
|
|
|
|
const f32 dbVol = audDriverUtil::ComputeDbVolumeFromLinear(rotorEvo * Min(1.f, 2.f*(1.f-distEvo)));
|
|
m_HeliDownwash->SetRequestedVolume(dbVol+m_MainRotorVolume);
|
|
}
|
|
}
|
|
|
|
void audHeliAudioEntity::TriggerEngineFailedToStart()
|
|
{
|
|
if(m_Vehicle && m_Vehicle->GetWillEngineStart())
|
|
{
|
|
m_FailedToStartCount = 0;
|
|
m_LastFailToStartTime = 0;
|
|
return;
|
|
}
|
|
|
|
u32 currentTime = fwTimer::GetTimeInMilliseconds();
|
|
if(currentTime > m_LastFailToStartTime + g_TimeBetweenRestartSounds && m_FailedToStartCount < g_MaxFailedToStartTries)
|
|
{
|
|
if(m_HeliAudioSettings)
|
|
{
|
|
if(!m_FailedToStartSound)
|
|
{
|
|
audSoundInitParams initParams;
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
SetTracker(initParams);
|
|
CreateAndPlaySound_Persistent(m_HeliAudioSettings->StartUpFailOneShot, &m_FailedToStartSound, &initParams);
|
|
}
|
|
}
|
|
|
|
m_FailedToStartCount++;
|
|
m_LastFailToStartTime = currentTime;
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// Deploy landing gear
|
|
// ----------------------------------------------------------------
|
|
void audHeliAudioEntity::DeployLandingGear()
|
|
{
|
|
const u32 modelNameHash = GetVehicleModelNameHash();
|
|
|
|
if(!m_HasCustomLandingGear)
|
|
{
|
|
if(m_LandingGearSoundSet.IsInitialised())
|
|
{
|
|
TriggerLandingGearSound(m_LandingGearSoundSet, modelNameHash == ATSTRINGHASH("THRUSTER", 0x58CDAF30)? ATSTRINGHASH("legs_down", 0xE91F08B4) : ATSTRINGHASH("deploy", 0xC9200261));
|
|
}
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// Retract landing gear
|
|
// ----------------------------------------------------------------
|
|
void audHeliAudioEntity::RetractLandingGear()
|
|
{
|
|
const u32 modelNameHash = GetVehicleModelNameHash();
|
|
|
|
if(m_HasCustomLandingGear)
|
|
{
|
|
if(m_LandingGearSoundSet.IsInitialised())
|
|
{
|
|
TriggerLandingGearSound(m_LandingGearSoundSet, modelNameHash == ATSTRINGHASH("THRUSTER", 0x58CDAF30)? ATSTRINGHASH("legs_up", 0x18C3884B) : ATSTRINGHASH("retract", 0x8E1F66E6));
|
|
}
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// Trigger a door open sound
|
|
// ----------------------------------------------------------------
|
|
void audHeliAudioEntity::TriggerDoorOpenSound(eHierarchyId doorId)
|
|
{
|
|
if(!m_HasCustomLandingGear || (doorId != VEH_FOLDING_WING_L && doorId != VEH_FOLDING_WING_R))
|
|
{
|
|
if(m_HeliAudioSettings)
|
|
{
|
|
u32 hash = m_HeliAudioSettings->DoorOpen;
|
|
if(doorId == VEH_DOOR_DSIDE_R)
|
|
{
|
|
hash = m_HeliAudioSettings->SecondaryDoorStartOpen;
|
|
}
|
|
TriggerDoorSound(hash, doorId);
|
|
}
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// Trigger a door shut sound
|
|
// ----------------------------------------------------------------
|
|
void audHeliAudioEntity::TriggerDoorCloseSound(eHierarchyId doorId, const bool UNUSED_PARAM(isBroken))
|
|
{
|
|
if(!m_HasCustomLandingGear || (doorId != VEH_FOLDING_WING_L && doorId != VEH_FOLDING_WING_R))
|
|
{
|
|
// if it's the player vehicle, and they're pissed off - slam the door. Note that this'll have his passengers slam the door too - oh well.
|
|
f32 volumeOffset = 0.0f;
|
|
|
|
if (m_Vehicle && m_Vehicle == CGameWorld::FindLocalPlayerVehicle() &&
|
|
CGameWorld::GetMainPlayerInfo()->PlayerIsPissedOff())
|
|
{
|
|
if (doorId == VEH_DOOR_DSIDE_F ||
|
|
doorId == VEH_DOOR_DSIDE_R ||
|
|
doorId == VEH_DOOR_PSIDE_F ||
|
|
doorId == VEH_DOOR_PSIDE_R)
|
|
{
|
|
volumeOffset = 6.0f;
|
|
}
|
|
}
|
|
|
|
if(m_HeliAudioSettings)
|
|
{
|
|
u32 hash = m_HeliAudioSettings->DoorClose;
|
|
if(doorId == VEH_DOOR_DSIDE_R && m_HeliAudioSettings->SecondaryDoorClose != g_NullSoundHash)
|
|
{
|
|
hash = m_HeliAudioSettings->SecondaryDoorClose;
|
|
}
|
|
TriggerDoorSound(m_HeliAudioSettings->DoorClose, doorId, volumeOffset);
|
|
}
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// Trigger door open sound
|
|
// ----------------------------------------------------------------
|
|
void audHeliAudioEntity::TriggerDoorFullyOpenSound(eHierarchyId doorId)
|
|
{
|
|
if(m_HeliAudioSettings)
|
|
{
|
|
if(!m_HasCustomLandingGear || (doorId != VEH_FOLDING_WING_L && doorId != VEH_FOLDING_WING_R))
|
|
{
|
|
u32 hash = m_HeliAudioSettings->DoorLimit;
|
|
if(doorId == VEH_DOOR_DSIDE_R && m_HeliAudioSettings->SecondaryDoorLimit != g_NullSoundHash)
|
|
{
|
|
hash = m_HeliAudioSettings->SecondaryDoorLimit;
|
|
}
|
|
TriggerDoorSound(m_HeliAudioSettings->DoorLimit, doorId);
|
|
}
|
|
}
|
|
}
|
|
|
|
void audHeliAudioEntity::TriggerDoorStartOpenSound(eHierarchyId doorId)
|
|
{
|
|
if(m_HeliAudioSettings)
|
|
{
|
|
if(!m_HasCustomLandingGear || (doorId != VEH_FOLDING_WING_L && doorId != VEH_FOLDING_WING_R))
|
|
{
|
|
u32 hash = m_HeliAudioSettings->DoorOpen;
|
|
if(doorId == VEH_DOOR_DSIDE_R && m_HeliAudioSettings->SecondaryDoorStartOpen != g_NullSoundHash)
|
|
{
|
|
hash = m_HeliAudioSettings->SecondaryDoorStartOpen;
|
|
}
|
|
TriggerDoorSound(hash, doorId);
|
|
}
|
|
}
|
|
}
|
|
|
|
void audHeliAudioEntity::TriggerDoorStartCloseSound(eHierarchyId doorId)
|
|
{
|
|
if(m_HeliAudioSettings && m_Vehicle->GetStatus() != STATUS_WRECKED)
|
|
{
|
|
if(doorId == VEH_DOOR_DSIDE_R && m_HeliAudioSettings->SecondaryDoorStartClose != g_NullSoundHash)
|
|
{
|
|
u32 hash = m_HeliAudioSettings->SecondaryDoorStartClose;
|
|
TriggerDoorSound(hash, doorId);
|
|
}
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// Trigger going down sound
|
|
//
|
|
void audHeliAudioEntity::TriggerGoingDownSound()
|
|
{
|
|
m_PlayGoingDown = true;
|
|
}
|
|
|
|
void audHeliAudioEntity::PlayGoingDownSound()
|
|
{
|
|
m_PlayGoingDown = false;
|
|
|
|
if(GetVehicleModelNameHash() == ATSTRINGHASH("THRUSTER", 0x58CDAF30))
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Only allow if there are lots of slots free, and we're not already playing the sound
|
|
if(m_Shotdown || (g_SpeechManager.GetNumVacantAmbientSlots() <= 3) || m_HeliGoingDown)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if(m_Vehicle->m_nVehicleFlags.bIsDrowning || ((CHeli*)m_Vehicle)->GetMainRotorSpeed() < 0.1f)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Try to grab a free ambient speech slot at low priority
|
|
s32 speechSlotId = g_SpeechManager.GetAmbientSpeechSlot(NULL, NULL, -1.0f);
|
|
|
|
if(speechSlotId >= 0)
|
|
{
|
|
audWaveSlot* speechSlot = g_SpeechManager.GetAmbientWaveSlotFromId(speechSlotId);
|
|
|
|
// Success! Use this slot to load and play our asset
|
|
if(speechSlot)
|
|
{
|
|
audSoundInitParams initParams;
|
|
m_SpeechSlotId = speechSlotId;
|
|
//m_PlayingRules[index].speechSlot = speechSlot;
|
|
initParams.WaveSlot = speechSlot;
|
|
initParams.AllowLoad = true;
|
|
initParams.PrepareTimeLimit = 5000;
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
SetTracker(initParams);
|
|
g_SpeechManager.PopulateAmbientSpeechSlotWithPlayingSpeechInfo(speechSlotId, 0,
|
|
#if __BANK
|
|
"HELI_GOING_DOWN",
|
|
#endif
|
|
0);
|
|
|
|
u32 soundHash = m_IsPlayerVehicle ? ATSTRINGHASH("HeliGoingDownPlayer", 0x2CF24ECF) : ATSTRINGHASH("HeliGoingDown", 0xB60C2298);
|
|
CreateAndPlaySound_Persistent(audVehicleAudioEntity::GetExtrasSoundSet()->Find(soundHash), &m_HeliGoingDown, &initParams);
|
|
|
|
REPLAY_ONLY(CReplayMgr::ReplayRecordSoundPersistant(audVehicleAudioEntity::GetExtrasSoundSet()->GetNameHash(), soundHash, &initParams, m_HeliGoingDown, m_Vehicle, eNoGlobalSoundEntity, ReplaySound::CONTEXT_HELI_GOING_DOWN);)
|
|
}
|
|
else
|
|
{
|
|
g_SpeechManager.FreeAmbientSpeechSlot(speechSlotId, true);
|
|
}
|
|
}
|
|
g_AudioScannerManager.TriggerCopDispatchInteraction(SCANNER_CDIT_HELI_MAYDAY_DISPATCH);
|
|
m_Shotdown = true;
|
|
}
|
|
|
|
void audHeliAudioEntity::StopGoingDownSound()
|
|
{
|
|
if(m_HeliGoingDown)
|
|
{
|
|
m_HeliGoingDown->StopAndForget();
|
|
}
|
|
|
|
CHeli* heli = static_cast<CHeli*>(m_Vehicle);
|
|
if(heli && (heli->GetIsPoliceDispatched() || heli->GetIsSwatDispatched()) && !m_HasBeenScannerDecremented)
|
|
{
|
|
g_AudioScannerManager.DecrementHelisInChase();
|
|
m_HasBeenScannerDecremented = true;
|
|
}
|
|
}
|
|
|
|
|
|
void audHeliAudioEntity::FreeSpeechSlot()
|
|
{
|
|
if(m_SpeechSlotId >= 0)
|
|
{
|
|
g_SpeechManager.FreeAmbientSpeechSlot(m_SpeechSlotId, true);
|
|
m_SpeechSlotId = -1;
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// Get a sound from the object data
|
|
// ----------------------------------------------------------------
|
|
u32 audHeliAudioEntity::GetSoundFromObjectData(u32 fieldHash) const
|
|
{
|
|
if(m_HeliAudioSettings)
|
|
{
|
|
u32 *ret = (u32 *)m_HeliAudioSettings->GetFieldPtr(fieldHash);
|
|
return (ret) ? *ret : 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void audHeliAudioEntity::UpdateJetPackSounds()
|
|
{
|
|
if(GetVehicleModelNameHash() == ATSTRINGHASH("THRUSTER", 0x58CDAF30))
|
|
{
|
|
CHeli* heli = (CHeli*)m_Vehicle;
|
|
const u32 timeMs = fwTimer::GetTimeInMilliseconds();
|
|
const bool inStrafeMode = heli->GetStrafeMode();
|
|
|
|
if(inStrafeMode || timeMs - m_LastTimeInStrafeMode < 200)
|
|
{
|
|
const f32 thrusterForce = ((CHeli*)m_Vehicle)->GetJetpackStrafeForceScale();
|
|
const f32 thrusterLeftForce = Max(thrusterForce, 0.f);
|
|
const f32 thrusterRightForce = Abs(Min(thrusterForce, 0.f));
|
|
|
|
const f32 thrustLeftChangeRate = (thrusterLeftForce - m_PrevJetpackThrusterLeftForce) * fwTimer::GetInvTimeStep();
|
|
const f32 thrustRightChangeRate = (thrusterRightForce - m_PrevJetpackThrusterRightForce) * fwTimer::GetInvTimeStep();
|
|
|
|
const bool triggerThrusterLeft = thrustLeftChangeRate >= g_JetpackStrafeThrusterTriggerLimit;
|
|
const bool triggerThrusterRight = thrustRightChangeRate >= g_JetpackStrafeThrusterTriggerLimit;
|
|
|
|
if((triggerThrusterLeft || triggerThrusterRight) && timeMs - m_LastJetpackStrafeTime > g_MinJetpackRetriggerTime)
|
|
{
|
|
if (m_Vehicle->m_nVehicleFlags.bEngineOn && !m_Vehicle->m_nVehicleFlags.bIsDrowning && !m_Vehicle->m_nVehicleFlags.bDisableParticles)
|
|
{
|
|
audSoundSet soundset;
|
|
const u32 soundsetName = ATSTRINGHASH("thruster_turbine_sounds", 0x9C4F5C78);
|
|
const u32 soundName = ATSTRINGHASH("strafe", 0xC90654B7);
|
|
|
|
if(soundset.Init(soundsetName))
|
|
{
|
|
audSoundInitParams initParams;
|
|
initParams.u32ClientVar = triggerThrusterRight ? (u32)AUD_VEHICLE_SOUND_AIRBRAKE_R : (u32)AUD_VEHICLE_SOUND_AIRBRAKE_L;
|
|
initParams.UpdateEntity = true;
|
|
initParams.EnvironmentGroup = GetEnvironmentGroup();
|
|
CreateAndPlaySound(soundset.Find(soundName), &initParams);
|
|
REPLAY_ONLY(CReplayMgr::ReplayRecordSound(soundsetName, soundName, &initParams, m_Vehicle));
|
|
m_LastJetpackStrafeTime = timeMs;
|
|
}
|
|
}
|
|
}
|
|
|
|
m_PrevJetpackThrusterLeftForce = thrusterLeftForce;
|
|
m_PrevJetpackThrusterRightForce = thrusterRightForce;
|
|
}
|
|
else
|
|
{
|
|
m_PrevJetpackThrusterLeftForce = 0.f;
|
|
m_PrevJetpackThrusterRightForce = 0.f;
|
|
}
|
|
|
|
if(inStrafeMode)
|
|
{
|
|
m_LastTimeInStrafeMode = timeMs;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void audHeliAudioEntity::UpdateCustomLandingGearSounds()
|
|
{
|
|
if(m_HasCustomLandingGear)
|
|
{
|
|
audSoundInitParams initParams;
|
|
initParams.UpdateEntity = true;
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
initParams.TrackEntityPosition = true;
|
|
initParams.u32ClientVar = (u32)AUD_VEHICLE_SOUND_UNKNOWN;
|
|
|
|
const CLandingGear::eLandingGearPublicStates landingGearState = ((CHeli*)m_Vehicle)->GetLandingGear().GetPublicState();
|
|
|
|
if(landingGearState != m_PrevLandingGearState)
|
|
{
|
|
if(m_CustomLandingGearLoop)
|
|
{
|
|
m_CustomLandingGearLoop->StopAndForget(true);
|
|
}
|
|
|
|
switch(landingGearState)
|
|
{
|
|
case CLandingGear::STATE_LOCKED_DOWN:
|
|
break;
|
|
case CLandingGear::STATE_LOCKED_UP:
|
|
{
|
|
CreateAndPlaySound(m_LandingGearSoundSet.Find(ATSTRINGHASH("wheel_flaps_close", 0xF29107C4)), &initParams);
|
|
REPLAY_ONLY(CReplayMgr::ReplayRecordSound(m_LandingGearSoundSet.GetNameHash(), ATSTRINGHASH("wheel_flaps_close", 0xF29107C4), &initParams, m_Vehicle));
|
|
}
|
|
break;
|
|
case CLandingGear::STATE_DEPLOYING:
|
|
{
|
|
CreateAndPlaySound(m_LandingGearSoundSet.Find(ATSTRINGHASH("wheel_flaps_open", 0xE2C58753)), &initParams);
|
|
REPLAY_ONLY(CReplayMgr::ReplayRecordSound(m_LandingGearSoundSet.GetNameHash(), ATSTRINGHASH("wheel_flaps_open", 0xE2C58753), &initParams, m_Vehicle));
|
|
}
|
|
break;
|
|
case CLandingGear::STATE_RETRACTING:
|
|
{
|
|
CreateAndPlaySound_Persistent(m_LandingGearSoundSet.Find(ATSTRINGHASH("landing_gear_retract", 0xD020783)), &m_CustomLandingGearLoop, &initParams);
|
|
REPLAY_ONLY(CReplayMgr::ReplayRecordSoundPersistant(m_LandingGearSoundSet.GetNameHash(), ATSTRINGHASH("landing_gear_retract", 0xD020783), &initParams, m_CustomLandingGearLoop, m_Vehicle));
|
|
}
|
|
break;
|
|
case CLandingGear::STATE_BROKEN:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
m_PrevLandingGearState = landingGearState;
|
|
}
|
|
// If we're in the deploying state, defer the wheel deploy loop until the bay doors are fully open
|
|
else if(landingGearState == CLandingGear::STATE_DEPLOYING && !m_CustomLandingGearLoop && ((CHeli*)m_Vehicle)->GetLandingGear().GetAuxDoorOpenRatio() >= 0.95f)
|
|
{
|
|
CreateAndPlaySound_Persistent(m_LandingGearSoundSet.Find(ATSTRINGHASH("landing_gear_deploy", 0x18CA1D46)), &m_CustomLandingGearLoop, &initParams);
|
|
REPLAY_ONLY(CReplayMgr::ReplayRecordSoundPersistant(m_LandingGearSoundSet.GetNameHash(), ATSTRINGHASH("landing_gear_deploy", 0x18CA1D46), &initParams, m_CustomLandingGearLoop, m_Vehicle));
|
|
}
|
|
}
|
|
}
|
|
|
|
void audHeliAudioEntity::TriggerRotorImpactSounds()
|
|
{
|
|
m_LastRotorImpactTime = fwTimer::GetTimeInMilliseconds();
|
|
}
|
|
|
|
void audHeliAudioEntity::UpdateRotorImpactSounds(audHeliValues& heliValues)
|
|
{
|
|
u32 currentTime = fwTimer::GetTimeInMilliseconds();
|
|
|
|
static bank_s32 delayMult = 2; // multiple of actual retrigger rate because it's not a low latency sound
|
|
static bank_s32 stopTimeOut = 500;
|
|
if(m_Vehicle->GetStatus() != STATUS_WRECKED && (currentTime < (m_LastRotorImpactTime + stopTimeOut)))
|
|
{
|
|
if(!m_RotorImpactSound)
|
|
{
|
|
audSoundInitParams initParams;
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
static bank_float volume = 0.0f;
|
|
initParams.Volume = volume;
|
|
SetTracker(initParams);
|
|
CreateAndPlaySound_Persistent(ATSTRINGHASH("HELICOPTER_ROTOR_GENERIC_COLLISION_RETRIG", 0x22E7400), (audSound**)&m_RotorImpactSound, &initParams);
|
|
|
|
REPLAY_ONLY(CReplayMgr::ReplayRecordSoundPersistant(ATSTRINGHASH("HELICOPTER_ROTOR_GENERIC_COLLISION_RETRIG", 0x22E7400), &initParams, (audSound*)m_RotorImpactSound, GetOwningEntity(), eNoGlobalSoundEntity);)
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(m_RotorImpactSound)
|
|
m_RotorImpactSound->StopAndForget();
|
|
}
|
|
|
|
if(m_RotorImpactSound)
|
|
{
|
|
f32 volume = audDriverUtil::ComputeDbVolumeFromLinear(m_RearRotorVolStartupCurve.CalculateValue(m_MainRotorSpeed));
|
|
m_RotorImpactSound->SetRequestedVolume(volume);
|
|
if(m_RotorImpactSound->GetSoundTypeID() == RetriggeredOverlappedSound::TYPE_ID)
|
|
{
|
|
s32 delay = (s32)(heliValues.triggerRate * 1000.0f * (f32)delayMult);
|
|
delay = Clamp(delay, 0, 1000);
|
|
m_RotorImpactSound->SetDelayTime(delay);
|
|
}
|
|
}
|
|
}
|
|
|
|
f32 audHeliAudioEntity::UpdateSlowmoRotorSounds()
|
|
{
|
|
f32 volume = 0.0f;
|
|
|
|
// never use slowmo heli sounds in replay
|
|
bool isSlowMo = audNorthAudioEngine::IsInSlowMo() REPLAY_ONLY( && !CReplayMgr::IsEditModeActive());
|
|
if(isSlowMo)
|
|
{
|
|
volume = m_HeliSlowmoSmoother.CalculateValue(0.0f, g_AudioEngine.GetTimeInMilliseconds()); //should be a timer that doesn't slow down
|
|
volume = audDriverUtil::ComputeDbVolumeFromLinear(volume);
|
|
|
|
if (m_HeliAudioSettings)
|
|
{
|
|
audSoundInitParams initParams;
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
SetTracker(initParams);
|
|
|
|
if(!m_HeliRotorLowFreqSlowmo && m_HeliRotorLowFreq) // only start it up if the main rotor sound is playing, prevent starts during shut down
|
|
{
|
|
CreateAndPlaySound_Persistent(m_HeliAudioSettings->SlowMoRotorLowFreqLoop, &m_HeliRotorLowFreqSlowmo, &initParams);
|
|
}
|
|
|
|
if(!m_HeliRotorSlowmo && m_HeliRotor) // only start it up if the main rotor sound is playing, prevent starts during shut down
|
|
{
|
|
Assign(initParams.EffectRoute, GetEngineEffectRoute());
|
|
CreateAndPlaySound_Persistent(m_HeliAudioSettings->SlowMoRotorLoop, &m_HeliRotorSlowmo, &initParams);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
volume = m_HeliSlowmoSmoother.CalculateValue(1.0f, g_AudioEngine.GetTimeInMilliseconds()); //should be a timer that doesn't slow down
|
|
volume = audDriverUtil::ComputeDbVolumeFromLinear(volume);
|
|
if(m_HeliRotorSlowmo)
|
|
{
|
|
m_HeliRotorSlowmo->Stop();
|
|
}
|
|
|
|
if(m_HeliRotorLowFreqSlowmo)
|
|
{
|
|
m_HeliRotorLowFreqSlowmo->Stop();
|
|
}
|
|
}
|
|
return volume;
|
|
}
|
|
|
|
void audHeliAudioEntity::UpdateWheelSounds()
|
|
{
|
|
CWheel* touchingWheel = NULL;
|
|
for(u32 loop = 0; loop < m_Vehicle->GetNumWheels(); loop++)
|
|
{
|
|
CWheel* wheel = m_Vehicle->GetWheel(loop);
|
|
if(wheel && wheel->GetIsTouching())
|
|
{
|
|
touchingWheel = wheel;
|
|
}
|
|
}
|
|
|
|
u32 gritSound = g_NullSoundHash;
|
|
f32 finalVolLin = 0.0f;
|
|
f32 speed = 0.0f;
|
|
if(touchingWheel)
|
|
{
|
|
speed = m_CachedVehicleVelocity.Mag();
|
|
|
|
f32 gritSpeedVol = sm_GritSpeedToLinVolCurve.CalculateValue(Abs(speed));
|
|
finalVolLin = touchingWheel->GetIsTouching() ? gritSpeedVol : 0.0f;
|
|
|
|
if(m_CachedMaterialSettings)
|
|
{
|
|
if(touchingWheel->GetFragChild(0) > 0) // this means it's an actual wheel, not a runner
|
|
{
|
|
gritSound = m_CachedMaterialSettings->DetailTyreRoll;
|
|
}
|
|
else
|
|
{
|
|
gritSound = m_CachedMaterialSettings->ScrapeSound;
|
|
}
|
|
}
|
|
}
|
|
|
|
static bank_float minSpeedThreshold = 0.01f;
|
|
if(m_ScrapeSound && (gritSound != m_PrevScrapeSound || speed < minSpeedThreshold))
|
|
{
|
|
m_ScrapeSound->StopAndForget();
|
|
if(m_HardScrapeSound)
|
|
{
|
|
m_HardScrapeSound->StopAndForget();
|
|
}
|
|
BANK_ONLY(if(g_DebugSuspension) Displayf("Stop scrape speed %f", speed);)
|
|
}
|
|
|
|
if(gritSound != g_NullSoundHash)
|
|
{
|
|
if(finalVolLin > g_SilenceVolumeLin && speed > minSpeedThreshold)
|
|
{
|
|
audSoundInitParams initParams;
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
initParams.TrackEntityPosition = true;
|
|
if(!m_ScrapeSound)
|
|
{
|
|
CreateAndPlaySound_Persistent(gritSound, &m_ScrapeSound, &initParams);
|
|
BANK_ONLY(if(g_DebugSuspension) Displayf("Play scrape speed %f vol %f", speed, finalVolLin);)
|
|
}
|
|
if(touchingWheel->GetFragChild(0) == 0 && m_CachedMaterialSettings->HardImpact != g_NullSoundHash && !m_HardScrapeSound)
|
|
{
|
|
CreateAndPlaySound_Persistent(m_HeliAudioSettings->HardScrape, &m_HardScrapeSound, &initParams);
|
|
BANK_ONLY(if(g_DebugSuspension) Displayf("Play scrape speed %f vol %f", speed, finalVolLin);)
|
|
}
|
|
|
|
if(m_ScrapeSound)
|
|
{
|
|
m_ScrapeSound->SetRequestedVolume(audDriverUtil::ComputeDbVolumeFromLinear(finalVolLin));
|
|
}
|
|
if(m_HardScrapeSound)
|
|
{
|
|
m_HardScrapeSound->SetRequestedVolume(audDriverUtil::ComputeDbVolumeFromLinear(finalVolLin));
|
|
}
|
|
}
|
|
else if(m_ScrapeSound)
|
|
{
|
|
if(m_ScrapeSound)
|
|
{
|
|
m_ScrapeSound->StopAndForget();
|
|
BANK_ONLY(if(g_DebugSuspension) Displayf("Stop scrape speed %f", speed);)
|
|
}
|
|
if(m_HardScrapeSound)
|
|
{
|
|
m_HardScrapeSound->StopAndForget();
|
|
}
|
|
}
|
|
}
|
|
|
|
m_PrevScrapeSound = gritSound;
|
|
}
|
|
|
|
void audHeliAudioEntity::UpdateSuspension()
|
|
{
|
|
if(m_IsPlayerVehicle)
|
|
{
|
|
// suspension sounds
|
|
for(s32 i = 0; i < m_Vehicle->GetNumWheels(); i++)
|
|
{
|
|
Vector3 pos;
|
|
GetWheelPosition(i, pos);
|
|
|
|
f32 compressionChange = m_Vehicle->GetWheel(i)->GetCompressionChange() * fwTimer::GetInvTimeStep();
|
|
|
|
// use the max of the previous frame and this frame, since physics is double stepped otherwise we'll miss some
|
|
f32 compression = Max(m_Vehicle->GetWheel(i)->GetCompression()-m_Vehicle->GetWheel(i)->GetCompressionChange(),m_Vehicle->GetWheel(i)->GetCompression());
|
|
|
|
if(m_Vehicle->m_nVehicleFlags.bIsAsleep)
|
|
{
|
|
// ignore physics if asleep or the wheel isn't touching anything
|
|
compressionChange = 0.0f;
|
|
compression = 0.0f;
|
|
}
|
|
|
|
const f32 absCompressionChange = Abs(compressionChange);
|
|
f32 damageFactor = 1.0f - m_Vehicle->GetWheel(i)->GetSuspensionHealth() * SUSPENSION_HEALTH_DEFAULT_INV;
|
|
|
|
f32 ratio = Clamp((absCompressionChange - m_HeliAudioSettings->MinSuspCompThresh) / (m_HeliAudioSettings->MaxSuspCompThres - m_HeliAudioSettings->MinSuspCompThresh - (damageFactor*2.f)), 0.0f,1.0f);
|
|
#if __BANK
|
|
if(g_DebugSuspension)
|
|
{
|
|
static f32 peakComp = 0.0f;
|
|
if(absCompressionChange > peakComp)
|
|
{
|
|
peakComp= absCompressionChange;
|
|
Displayf("Peak Suspension Compression %f LinearVol %f", peakComp, (f32)sm_SuspensionVolCurve.CalculateValue(ratio));
|
|
}
|
|
}
|
|
#endif
|
|
if(m_SuspensionSounds[i])
|
|
{
|
|
if(compressionChange*m_LastCompressionChange[i] < 0.f)
|
|
{
|
|
// suspension has changed direction - cancel previous sound
|
|
m_SuspensionSounds[i]->StopAndForget();
|
|
}
|
|
else
|
|
{
|
|
// Disabling volume update so that we hear the whole one shot rather than it being played then immediately muted
|
|
// m_SuspensionSounds[i]->SetRequestedVolume(audDriverUtil::ComputeDbVolumeFromLinear(sm_SuspensionVolCurve.CalculateValue(ratio)));
|
|
m_SuspensionSounds[i]->SetRequestedPosition(pos);
|
|
}
|
|
}
|
|
|
|
if(absCompressionChange > m_HeliAudioSettings->MinSuspCompThresh)
|
|
{
|
|
if(!m_SuspensionSounds[i])
|
|
{
|
|
// trigger a suspension sound
|
|
u32 soundHash;
|
|
if(compressionChange > 0)
|
|
{
|
|
BANK_ONLY(if(g_DebugSuspension) Displayf("Suspension Down");)
|
|
soundHash = m_HeliAudioSettings->SuspensionDown;
|
|
}
|
|
else
|
|
{
|
|
BANK_ONLY(if(g_DebugSuspension) Displayf("Suspension Up");)
|
|
soundHash = m_HeliAudioSettings->SuspensionUp;
|
|
}
|
|
|
|
audSoundInitParams initParams;
|
|
initParams.UpdateEntity = true;
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
initParams.Position = pos;
|
|
initParams.Volume = audDriverUtil::ComputeDbVolumeFromLinear(sm_SuspensionVolCurve.CalculateValue(ratio));
|
|
CreateAndPlaySound_Persistent(soundHash, &m_SuspensionSounds[i], &initParams);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void audHeliAudioEntity::UpdateEngineCooling()
|
|
{
|
|
CHeli* heli = static_cast<CHeli*>(m_Vehicle);
|
|
|
|
if(heli)
|
|
{
|
|
static const f32 engineCooldownTemperatureRange = 20.0f;
|
|
const f32 baseTemperature = g_weather.GetTemperature(m_Vehicle->GetTransform().GetPosition());
|
|
const bool shouldEngineCoolingStop = (m_Vehicle->m_nVehicleFlags.bIsDrowning || m_Vehicle->m_nVehicleFlags.bEngineOn || m_Vehicle->m_EngineTemperature <= m_EngineOffTemperature - engineCooldownTemperatureRange);
|
|
const bool shouldEngineCoolingStart = (!m_Vehicle->m_nVehicleFlags.bIsDrowning && ((m_HeliState == AUD_HELI_STOPPING || m_HeliState == AUD_HELI_OFF) && m_Vehicle->m_EngineTemperature > baseTemperature + 50.f));
|
|
const f32 engineCoolingProgress = Clamp((engineCooldownTemperatureRange - (m_EngineOffTemperature - m_Vehicle->m_EngineTemperature))/engineCooldownTemperatureRange, 0.0f, 1.0f);
|
|
|
|
#if __BANK
|
|
if(g_ShowHeliEngineCooling)
|
|
{
|
|
char tempString[128];
|
|
sprintf(tempString, "Cooling Progress %4.2f OffTemp %4.2f Temp:%4.2f Occ:%4.2f", engineCoolingProgress, m_EngineOffTemperature, m_Vehicle->m_EngineTemperature, m_DebugOcclusion);
|
|
grcDebugDraw::Text(m_Vehicle->GetTransform().GetPosition(), Color_green, tempString);
|
|
}
|
|
#endif
|
|
|
|
if(m_EngineCoolingSound)
|
|
{
|
|
if(shouldEngineCoolingStop)
|
|
{
|
|
m_EngineCoolingSound->StopAndForget();
|
|
}
|
|
else
|
|
{
|
|
((audSound*)m_EngineCoolingSound)->FindAndSetVariableValue(g_TemperatureVariableHash, engineCoolingProgress);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(shouldEngineCoolingStart && !shouldEngineCoolingStop)
|
|
{
|
|
audSoundInitParams initParams;
|
|
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
CreateSound_PersistentReference(m_HeliAudioSettings->EngineCooling, &m_EngineCoolingSound, &initParams);
|
|
|
|
if(m_EngineCoolingSound)
|
|
{
|
|
m_EngineCoolingSound->SetUpdateEntity(true);
|
|
m_EngineCoolingSound->SetClientVariable((u32)AUD_VEHICLE_SOUND_ENGINE);
|
|
((audSound*)m_EngineCoolingSound)->FindAndSetVariableValue(g_TemperatureVariableHash, engineCoolingProgress);
|
|
|
|
m_EngineCoolingSound->PrepareAndPlay();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool audHeliAudioEntity::AircraftWarningVoiceIsMale()
|
|
{
|
|
if(m_HeliAudioSettings)
|
|
{
|
|
return AUD_GET_TRISTATE_VALUE(m_HeliAudioSettings->Flags, FLAG_ID_HELIAUDIOSETTINGS_AIRCRAFTWARNINGVOICEISMALE) == AUD_TRISTATE_TRUE;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
#if GTA_REPLAY
|
|
void audHeliAudioEntity::ProcessReplayAudioState(u8 PacketState)
|
|
{
|
|
if( m_HeliState == AUD_HELI_OFF && PacketState == AUD_HELI_ON && !m_HeliShouldSkipStartup )
|
|
{
|
|
SetHeliShouldSkipStartup(true);
|
|
}
|
|
}
|
|
|
|
void audHeliAudioEntity::SetSpeechSlotID(s32 speechSlotId)
|
|
{
|
|
m_SpeechSlotId = speechSlotId;
|
|
m_LastReplaySpeechSlotAllocTime = g_AudioEngine.GetSoundManager().GetTimeInMilliseconds(0);
|
|
}
|
|
#endif //GTA_REPLAY
|
|
|
|
#if __BANK
|
|
|
|
void audHeliAudioEntity::ShowHeliValues(audHeliValues& heliValues)
|
|
{
|
|
CHeli* heli = static_cast<CHeli*>(m_Vehicle);
|
|
|
|
if(heli && g_DebugHeli && (m_IsPlayerVehicle || heli == g_pFocusEntity))
|
|
{
|
|
s16 pitchShift = sm_PitchShift[m_PitchShiftIndex];
|
|
#if __BANK
|
|
if(m_IsPlayerVehicle && g_PitchShiftIndex != -1)
|
|
{
|
|
pitchShift = sm_PitchShift[g_PitchShiftIndex];
|
|
}
|
|
#endif
|
|
|
|
char tempString[512];
|
|
static bank_float lineInc = 0.015f;
|
|
f32 lineBase = 0.1f;
|
|
formatf(tempString, "bladeVolume %4.2f", heliValues.bladeVolume); grcDebugDraw::Text(Vector2(0.1f, lineBase), Color32(255,255,255), tempString ); lineBase += lineInc;
|
|
formatf(tempString, "rotorVolume %4.2f", heliValues.rotorVolume); grcDebugDraw::Text(Vector2(0.1f, lineBase), Color32(255,255,255), tempString ); lineBase += lineInc;
|
|
formatf(tempString, "rotorPitch %5d", heliValues.rotorPitch+pitchShift);grcDebugDraw::Text(Vector2(0.1f, lineBase), Color32(255,255,255), tempString ); lineBase += lineInc;
|
|
formatf(tempString, "exhaustVolume %4.2f", heliValues.exhaustVolume); grcDebugDraw::Text(Vector2(0.1f, lineBase), Color32(255,255,255), tempString ); lineBase += lineInc;
|
|
formatf(tempString, "exhaustPitch %5d", heliValues.exhaustPitch+pitchShift);grcDebugDraw::Text(Vector2(0.1f, lineBase), Color32(255,255,255), tempString ); lineBase += lineInc;
|
|
formatf(tempString, "bankingVolume %4.2f", heliValues.bankingVolume); grcDebugDraw::Text(Vector2(0.1f, lineBase), Color32(255,255,255), tempString ); lineBase += lineInc;
|
|
formatf(tempString, "bankingPitch %5d", heliValues.bankingPitch+pitchShift);grcDebugDraw::Text(Vector2(0.1f, lineBase), Color32(255,255,255), tempString ); lineBase += lineInc;
|
|
formatf(tempString, "rearRotorVolume %4.2f", heliValues.rearRotorVolume); grcDebugDraw::Text(Vector2(0.1f, lineBase), Color32(255,255,255), tempString ); lineBase += lineInc;
|
|
formatf(tempString, "throttleInput %4.2f", heliValues.throttleInput); grcDebugDraw::Text(Vector2(0.1f, lineBase), Color32(255,255,255), tempString ); lineBase += lineInc;
|
|
formatf(tempString, "throttle %4.2f", heliValues.throttle); grcDebugDraw::Text(Vector2(0.1f, lineBase), Color32(255,255,255), tempString ); lineBase += lineInc;
|
|
formatf(tempString, "startup %4.2f", heliValues.startup); grcDebugDraw::Text(Vector2(0.1f, lineBase), Color32(255,255,255), tempString ); lineBase += lineInc;
|
|
formatf(tempString, "banking %4.2f", heliValues.banking); grcDebugDraw::Text(Vector2(0.1f, lineBase), Color32(255,255,255), tempString ); lineBase += lineInc;
|
|
formatf(tempString, "health %4.2f", heliValues.health); grcDebugDraw::Text(Vector2(0.1f, lineBase), Color32(255,255,255), tempString ); lineBase += lineInc;
|
|
formatf(tempString, "damageVolume %4.2f %s", heliValues.damageVolume, m_HeliDamage?"on":"off"); grcDebugDraw::Text(Vector2(0.1f, lineBase), Color32(255,255,255), tempString ); lineBase += lineInc;
|
|
formatf(tempString, "damageVolume600 %4.2f %s", heliValues.damageVolumeBelow600, m_HeliDamageBelow600?"on":"off"); grcDebugDraw::Text(Vector2(0.1f, lineBase), Color32(255,255,255), tempString ); lineBase += lineInc;
|
|
formatf(tempString, "occlusion %4.2f", m_DebugOcclusion); grcDebugDraw::Text(Vector2(0.1f, lineBase), Color32(255,255,255), tempString ); lineBase += lineInc;
|
|
formatf(tempString, "triggerRate %4.2f", heliValues.triggerRate); grcDebugDraw::Text(Vector2(0.1f, lineBase), Color32(255,255,255), tempString ); lineBase += lineInc;
|
|
formatf(tempString, "Throttle %4.2f", m_Throttle); grcDebugDraw::Text(Vector2(0.1f, lineBase), Color32(255,255,255), tempString ); lineBase += lineInc;
|
|
formatf(tempString, "RotorSpeed %4.2f", m_MainRotorSpeed); grcDebugDraw::Text(Vector2(0.1f, lineBase), Color32(255,255,255), tempString ); lineBase += lineInc;
|
|
formatf(tempString, "EngineOn flag %d EngineOn %d", m_Vehicle->m_nVehicleFlags.bEngineOn, IsEngineOn()); grcDebugDraw::Text(Vector2(0.1f, lineBase), Color32(255,255,255), tempString ); lineBase += lineInc;
|
|
formatf(tempString, "Health %4.2f MissFire %d RecoverMissFire %d Time %4.2f",
|
|
m_Vehicle->GetVehicleDamage()->GetEngineHealth(), heli->m_Transmission.GetCurrentlyMissFiring(),
|
|
heli->m_Transmission.GetCurrentlyRecoveringFromMissFiring(),
|
|
heli->m_Transmission.GetOverrideMissFireTime());
|
|
grcDebugDraw::Text(Vector2(0.1f, lineBase), Color32(255,255,255), tempString );
|
|
}
|
|
}
|
|
// ----------------------------------------------------------------
|
|
// Update debug stuff
|
|
// ----------------------------------------------------------------
|
|
void audHeliAudioEntity::UpdateDebug()
|
|
{
|
|
// If this is enabled, we fudge the tracker position to simulate the plane flying overhead every x seconds
|
|
if(g_UseDebugHeliTracker)
|
|
{
|
|
const ScalarV distanceTravelled = ScalarV((g_DebugHeliTrackerFlybyDist/2.0f) - (g_DebugHeliTrackerFlybyDist * (g_DebugHeliTrackerTimer/g_DebugHeliTrackerFlybyTime)));
|
|
const Vec3V height(0.0f, 0.0f, g_DebugHeliTrackerFlybyHeight);
|
|
Vec3V newPosition = m_Vehicle->GetTransform().GetPosition() + (m_Vehicle->GetTransform().GetForward() * distanceTravelled);
|
|
newPosition = newPosition + height;
|
|
m_DebugTracker.SetPosition(RCC_VECTOR3(newPosition));
|
|
|
|
//for(u32 loop = 0; loop < PLANE_LOOPS_MAX; loop++)
|
|
//{
|
|
// if(m_PlaneLoops[loop])
|
|
// {
|
|
// m_PlaneLoops[loop]->SetRequestedPosition(VECTOR3_TO_VEC3V(newPosition));
|
|
// }
|
|
//}
|
|
|
|
m_ExhaustOffsetPos = newPosition;
|
|
m_EngineOffsetPos = newPosition;
|
|
|
|
g_DebugHeliTrackerTimer += fwTimer::GetTimeStep();
|
|
|
|
if(g_DebugHeliTrackerTimer > g_DebugHeliTrackerFlybyTime)
|
|
{
|
|
g_DebugHeliTrackerTimer = 0.0f;
|
|
}
|
|
|
|
static bank_float size = 1.0f;
|
|
grcDebugDraw::Sphere(newPosition, size, Color_red);
|
|
}
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------
|
|
// Add widgets to RAG tool
|
|
// ----------------------------------------------------------------
|
|
void audHeliAudioEntity::AddWidgets(bkBank &bank)
|
|
{
|
|
bank.PushGroup("Helicopters", false);
|
|
|
|
|
|
|
|
bank.AddSlider("g_HeliRotorTriggerRate", &g_HeliRotorTriggerRate, 0.0f, 10.0f, 0.01f);
|
|
bank.AddSlider("g_HeliLowPassFilter", &g_HeliLowPassFilter, 0.0f, 23999.0f, 100.0f);
|
|
|
|
bank.AddSlider("Time Between Failed Restart Sounds(ms)", &g_TimeBetweenRestartSounds, 0, 10000, 1);
|
|
bank.AddSlider("Max Failed To Start Tries", &g_MaxFailedToStartTries, 0, 10, 1);
|
|
|
|
bank.AddSlider("g_HeliStartupTime(ms)", &g_HeliStartupTime, 0.0f, 10000.0f, 1.0f);
|
|
bank.AddSlider("g_HeliWinddownTime(ms)", &g_HeliWinddownTime, 0.0f, 10000.0f, 1.0f);
|
|
bank.AddSlider("g_HeliSlowMoPitch", &g_HeliSlowMoPitch, -3200, 0, 1);
|
|
bank.AddSlider("Player PitchShiftIndex", &g_PitchShiftIndex, -1, 2, 1);
|
|
bank.AddToggle("g_DebugHeli", &g_DebugHeli);
|
|
bank.AddToggle("Show Engine Cooling", &g_ShowHeliEngineCooling);
|
|
bank.AddToggle("EnableCrazyHeliSounds", &g_EnableCrazyHeliSounds);
|
|
bank.AddSlider("g_HeliTimeWarpGap", &g_HeliTimeWarpGap, 0.f, 1000.f, 0.001f);
|
|
bank.AddSlider("g_HeliDamageRate", &g_HeliDamageRate, 0.0f, 10000.f, 1.0f);
|
|
bank.AddSlider("g_HeliInterFlipProb", &g_HeliInterFlipProb, 0.0f, 1000.f, 1.0f);
|
|
bank.AddSlider("g_HeliIntraFlipProb", &g_HeliIntraFlipProb, 0.0f, 1000.f, 1.0f);
|
|
bank.AddToggle("g_OverrideHeliHealth", &g_OverrideHeliHealth);
|
|
bank.AddSlider("g_OverridenHeliHealth", &g_OverridenHeliHealth, 0.0f, 1000.f, 1.0f);
|
|
bank.AddSlider("g_HeliDamageVolumeRange", &g_HeliDamageVolumeRange, -100.0f, 0.f, 1.0f);
|
|
bank.AddSlider("g_MinHealthForHeliWarning", &g_MinHealthForHeliWarning, 0.0f, 1000.f, 1.0f);
|
|
bank.AddSlider("Jetpack Thruster Trigger Limit", &g_JetpackStrafeThrusterTriggerLimit, 0.0f, 5.f, 0.01f);
|
|
|
|
bank.AddToggle("g_PlayCabinTone", &g_PlayCabinTone);
|
|
bank.AddToggle("g_DebugSuspension", &g_DebugSuspension);
|
|
|
|
bank.PushGroup("Debug Flybys", false);
|
|
bank.AddToggle("Enable Debug Flybys", &g_UseDebugHeliTracker);
|
|
bank.AddSlider("Flyby Time", &g_DebugHeliTrackerFlybyTime, 0.0f, 1000.0f, 0.5f);
|
|
bank.AddSlider("Flyby Distance", &g_DebugHeliTrackerFlybyDist, 0.0f, 10000.0f, 10.0f);
|
|
bank.AddSlider("Flyby Height", &g_DebugHeliTrackerFlybyHeight, 0.0f, 10000.0f, 10.0f);
|
|
bank.PopGroup();
|
|
|
|
bank.PopGroup();
|
|
}
|
|
#endif
|