7518 lines
271 KiB
C++
7518 lines
271 KiB
C++
//
|
|
// audio/vehicleaudioentity.cpp
|
|
//
|
|
// Copyright (C) 1999-2006 Rockstar Games. All Rights Reserved.
|
|
//
|
|
#include "caraudioentity.h"
|
|
#include "frontendaudioentity.h"
|
|
#include "debugaudio.h"
|
|
#include "northaudioengine.h"
|
|
#include "audio/environment/environment.h"
|
|
#include "pedaudioentity.h"
|
|
#include "peds/PedFactory.h"
|
|
#include "vehicleaudioentity.h"
|
|
#include "policescanner.h"
|
|
#include "radioaudioentity.h"
|
|
#include "radiostation.h"
|
|
#include "radioslot.h"
|
|
#include "scriptaudioentity.h"
|
|
#include "weatheraudioentity.h"
|
|
#include "modelinfo/VehicleModelInfoEnums.h"
|
|
#include "vehiclereflectionsaudioentity.h"
|
|
#include "vehicles/VehicleFactory.h"
|
|
#include "vehicles/Submarine.h"
|
|
#include "entity/archetypemanager.h"
|
|
|
|
#include "boataudioentity.h"
|
|
#include "heliaudioentity.h"
|
|
#include "animation/animbones.h"
|
|
#include "audioeffecttypes/waveshapereffect.h"
|
|
#include "audioengine/categorymanager.h"
|
|
#include "audioengine/engine.h"
|
|
#include "audioengine/engineutil.h"
|
|
#include "audioengine/environment.h"
|
|
#include "audioengine/environment_game.h"
|
|
#include "audioengine/soundfactory.h"
|
|
#include "audioengine/widgets.h"
|
|
#include "audiohardware/device.h"
|
|
#include "audiohardware/driver.h"
|
|
#include "audiohardware/driverdefs.h"
|
|
#include "audiohardware/driverutil.h"
|
|
#include "audiosoundtypes/envelopesound.h"
|
|
#include "audiosoundtypes/simplesound.h"
|
|
#include "audiosoundtypes/granularsound.h"
|
|
#include "audiosoundtypes/sound.h"
|
|
#include "audiosoundtypes/soundcontrol.h"
|
|
#include "audiosoundtypes/sounddefs.h"
|
|
#include "atl/staticpool.h"
|
|
#include "camera/CamInterface.h"
|
|
#include "camera/cinematic/CinematicDirector.h"
|
|
#include "camera/cinematic/camera/tracking/CinematicHeliChaseCamera.h"
|
|
#include "camera/cinematic/camera/tracking/CinematicStuntCamera.h"
|
|
#include "camera/gameplay/GameplayDirector.h"
|
|
#include "camera/gameplay/follow/FollowVehicleCamera.h"
|
|
#include "camera/cutscene/CutsceneDirector.h"
|
|
#include "camera/CamInterface.h"
|
|
#include "camera/system/CameraMetadata.h"
|
|
#include "debug/DebugScene.h"
|
|
#include "vehicleAi/vehicleintelligence.h"
|
|
#include "control/record.h"
|
|
#include "crskeleton/skeleton.h"
|
|
#include "vfx/systems/VfxWheel.h"
|
|
#include "debug/debugglobals.h"
|
|
#include "grcore/debugdraw.h"
|
|
#include "game/ModelIndices.h"
|
|
#include "game/weather.h"
|
|
#include "modelinfo/vehiclemodelinfo.h"
|
|
#include "network/NetworkInterface.h"
|
|
#include "phbound/boundcomposite.h"
|
|
#include "physics/gtaMaterialManager.h"
|
|
#include "physics/physics.h"
|
|
#include "profile/element.h"
|
|
#include "fwsys/timer.h"
|
|
#include "vehicles/automobile.h"
|
|
#include "vehicles/boat.h"
|
|
#include "vehicles/bike.h"
|
|
#include "vehicles/door.h"
|
|
#include "vehicles/heli.h"
|
|
#include "vehicles/vehicle.h"
|
|
#include "vehicles/Trailer.h"
|
|
#include "vfx/Systems/VfxVehicle.h"
|
|
#include "peds/pedeventscanner.h"
|
|
#include "peds/PopCycle.h"
|
|
#include "peds/PedIntelligence.h"
|
|
#include "peds/Ped.h"
|
|
#include "system/controlMgr.h"
|
|
#include "Task/Vehicle/TaskEnterVehicle.h"
|
|
#include "Task/Vehicle/TaskExitVehicle.h"
|
|
#include "renderer/water.h"
|
|
#include "vehicleAi/task/TaskVehicleAnimation.h"
|
|
#include "control/replay/Vehicle/VehiclePacket.h"
|
|
#include "Control/Replay/Audio/WeaponAudioPacket.h"
|
|
#include "control/replay/replay.h"
|
|
#include "camera/helpers/ControlHelper.h"
|
|
#include "task/Vehicle/TaskInVehicle.h"
|
|
#include "vehicles/AmphibiousAutomobile.h"
|
|
|
|
#include "debugaudio.h"
|
|
|
|
AUDIO_VEHICLES_OPTIMISATIONS()
|
|
|
|
XPARAM(audiodesigner);
|
|
|
|
PF_PAGE(VehicleAudioEntityPage,"audVehicleAudioEntity");
|
|
PF_GROUP(VehicleAudioEntity);
|
|
PF_LINK(VehicleAudioEntityPage, VehicleAudioEntity);
|
|
PF_VALUE_FLOAT(Revs, VehicleAudioEntity);
|
|
PF_VALUE_FLOAT(RawRevs, VehicleAudioEntity);
|
|
PF_VALUE_FLOAT(PowerFactor, VehicleAudioEntity);
|
|
PF_VALUE_FLOAT(Throttle, VehicleAudioEntity);
|
|
PF_VALUE_INT(Gear, VehicleAudioEntity);
|
|
|
|
PF_PAGE(VehicleAudioTimingPage, "audVehicleAudioEntity Timings");
|
|
PF_GROUP(VehicleAudioTimings);
|
|
PF_LINK(VehicleAudioTimingPage, VehicleAudioTimings);
|
|
PF_TIMER(UpdateInternal, VehicleAudioTimings);
|
|
PF_TIMER(UpdateEngineAndExhaust, VehicleAudioTimings);
|
|
PF_TIMER(UpdateEngineFilters, VehicleAudioTimings);
|
|
PF_TIMER(UpdateStartLoop, VehicleAudioTimings);
|
|
PF_TIMER(UpdateBrakes, VehicleAudioTimings);
|
|
PF_TIMER(PopulateVariables, VehicleAudioTimings);
|
|
|
|
extern CVfxWheel g_vfxWheel;
|
|
|
|
bool audCarAudioEntity::sm_ShouldDisplayEngineDebug = false;
|
|
bool audCarAudioEntity::sm_ShouldFlipPlayerCones = false;
|
|
|
|
extern bank_float g_FakeRevsOffsetBelow;
|
|
extern bank_float g_FakeRevsOffsetAbove;
|
|
extern bank_float g_FakeRevsMaxHoldTimeMin;
|
|
extern bank_float g_FakeRevsMaxHoldTimeMax;
|
|
extern bank_float g_FakeRevsMinHoldTimeMin;
|
|
extern bank_float g_FakeRevsMinHoldTimeMax;
|
|
extern bank_float g_FakeRevsIncreaseRateBase;
|
|
extern bank_float g_FakeRevsIncreaseRateScale;
|
|
extern bank_float g_FakeOutOfWaterMinTime;
|
|
extern bank_float g_FakeOutOfWaterMaxTime;
|
|
extern bank_float g_FakeInWaterMinTime;
|
|
extern bank_float g_FakeInWaterMaxTime;
|
|
extern bank_float g_FakeRevsDecreaseRateBase;
|
|
extern bank_float g_FakeRevsDecreaseRateScale;
|
|
extern u32 g_FakeWaveHitDistanceSq;
|
|
extern f32 g_BankSprayPanDistanceScalar;
|
|
extern f32 g_BankSprayForwardDistanceScalar;
|
|
extern f32 g_LateralSkidSmootherIncrease;
|
|
extern f32 g_LateralSkidSmootherDecrease;
|
|
extern f32 g_MainSkidSmootherIncrease;
|
|
extern f32 g_MainSkidSmootherDecrease;
|
|
|
|
f32 audCarAudioEntity::sm_InnerUpdateFrames = 3.0f;
|
|
f32 audCarAudioEntity::sm_OuterUpdateFrames = 3.0f;
|
|
f32 audCarAudioEntity::sm_InnerCheapUpdateFrames = 6.0f;
|
|
f32 audCarAudioEntity::sm_OuterCheapUpdateFrames = 6.0f;
|
|
f32 audCarAudioEntity::sm_CarFwdSpeedSum = 1.0f;
|
|
f32 audCarAudioEntity::sm_NumActiveCars = 0;
|
|
u32 audCarAudioEntity::sm_LastSportsRevsTime = 0;
|
|
u32 audCarAudioEntity::sm_SportsCarRevsHistoryIndex = 0;
|
|
atRangeArray<audCarAudioEntity::SportsCarRevHistoryEntry, audCarAudioEntity::kSportsCarRevsHistorySize> audCarAudioEntity::sm_SportsCarRevsSoundHistory;
|
|
|
|
BANK_ONLY(atArray<audCarAudioEntity::carPassHistory> audCarAudioEntity::sm_CarPassHistory;)
|
|
BANK_ONLY(Vector3 audCarAudioEntity::sm_VolumeCaptureStartPos; )
|
|
BANK_ONLY(audCarAudioEntity::VolumeCaptureState audCarAudioEntity::sm_VolumeCaptureState = audCarAudioEntity::State_NextVehicle;)
|
|
BANK_ONLY(f32 audCarAudioEntity::sm_VolumeCaptureTimer = 0.0f;)
|
|
BANK_ONLY(s32 audCarAudioEntity::sm_VolumeCaptureVehicleIndex = 0;)
|
|
BANK_ONLY(s32 audCarAudioEntity::sm_VolumeCaptureVehicleStartIndex = 0;)
|
|
BANK_ONLY(f32 audCarAudioEntity::sm_VolumeCaptureIntervalTimer = 0.0f;)
|
|
BANK_ONLY(u32 audCarAudioEntity::sm_VolumeCaptureFramesAtState = 0u;)
|
|
BANK_ONLY(f32 audCarAudioEntity::sm_VolumeCaptureRevs = 0.0f;)
|
|
BANK_ONLY(f32 audCarAudioEntity::sm_VolumeCaptureThrottle = 0.0f;)
|
|
BANK_ONLY(f32 audCarAudioEntity::sm_VolumeCapturePeakLoudness = g_SilenceVolume;)
|
|
BANK_ONLY(f32 audCarAudioEntity::sm_VolumeCapturePeakRMS = g_SilenceVolume;)
|
|
BANK_ONLY(f32 audCarAudioEntity::sm_VolumeCapturePeakAmplitude = g_SilenceVolume;)
|
|
BANK_ONLY(FileHandle audCarAudioEntity::sm_VolumeCaptureFileID = INVALID_FILE_HANDLE;)
|
|
BANK_ONLY(atArray<f32> audCarAudioEntity::sm_VolumeCaptureLoudnessHistory;)
|
|
BANK_ONLY(atArray<f32> audCarAudioEntity::sm_VolumeCaptureRMSHistory;)
|
|
BANK_ONLY(atArray<f32> audCarAudioEntity::sm_VolumeCaptureAmplitudeHistory;)
|
|
BANK_ONLY(fwModelId audCarAudioEntity::sm_VolumeCaptureVehicleRequest;)
|
|
BANK_ONLY(extern f32 g_WaterTurbulenceVolumeTrim;)
|
|
BANK_ONLY(extern f32 g_BankSprayVolumeTrim;)
|
|
extern bool g_TreatAllBoatsAsNPCs;
|
|
|
|
f32 g_RevMaxIncreaseRate = 1.f;
|
|
f32 g_RevMaxDecreaseRate = 10.f;
|
|
f32 g_RevMaxForceStopDecreaseRate = 1.f;
|
|
s32 g_DamageLayerMinPitch = -300;
|
|
s32 g_DamageLayerMaxPitch = 300;
|
|
s32 g_DamagedWheelMinPitch = -200;
|
|
s32 g_DamagedWheelMaxPitch = 600;
|
|
f32 g_HighRevsMisfireSoundProb = 0.3f;
|
|
f32 g_BaseRollOffScalePlayer = 1.0f;
|
|
f32 g_BaseRollOffScaleNPC = 2.0f;
|
|
f32 g_UnderLoadRevsSmootherScalar = 3.0f;
|
|
f32 g_TrunkRadioPositionOffset = 1.6f;
|
|
f32 g_HydraulicSuspensionAngleLoopTriggerThreshold = 0.1f;
|
|
f32 g_HydraulicSuspensionAngleLoopTriggerThresholdRemoteVehicle = 0.01f;
|
|
f32 g_HydraulicSuspensionAngleLoopReTriggerThreshold = 0.08f;
|
|
f32 g_HydraulicSuspensionAngleLoopReTriggerThresholdRemoteVehicle = 0.75f;
|
|
|
|
extern u32 g_MaxVehicleSubmixes;
|
|
extern u32 g_MaxDummyVehicles;
|
|
extern f32 g_GranularQualityCrossfadeSpeed;
|
|
extern f32 g_VehicleReflectionsActivationDist;
|
|
extern f32 g_MaxDummyRangeScale;
|
|
extern f32 g_MaxGranularRangeScale;
|
|
extern f32 g_MaxRealRangeScale;
|
|
extern f32 g_GranularActivationScaleIncreaseRate;
|
|
extern f32 g_GranularActivationScaleDecreaseRate;
|
|
extern f32 g_ActivationScaleIncreaseRate;
|
|
extern f32 g_ActivationScaleDecreaseRate;
|
|
extern f32 g_DummyActivationScaleIncreaseRate;
|
|
extern f32 g_DummyActivationScaleDecreaseRate;
|
|
extern f32 g_MinTimeAtDesiredLOD;
|
|
extern f32 g_MinTimeAtCurrentLOD;
|
|
extern u32 g_NPCRoadNoiseAttackTime;
|
|
extern u32 g_NPCRoadNoiseReleaseTime;
|
|
extern u32 g_SuperDummyRadiusSq;
|
|
extern u32 g_SportsCarRevsEngineSwitchTime;
|
|
extern u32 g_HydraulicsModifiedTimeoutMs;
|
|
extern u8 g_NumHydraulicActivationDelayFrames;
|
|
extern bool g_InteriorEngineExhaustAtListener;
|
|
extern bool g_InteriorEngineExhaustPanned;
|
|
extern bool g_DisablePlayerVehicleDSP;
|
|
extern bool g_DisableNPCVehicleDSP;
|
|
extern u32 g_StuntBoostIntensityTimeout;
|
|
extern u32 g_RocketBoostCooldownTime;
|
|
extern f32 g_IdleMainSmootherRateIncrease;
|
|
extern f32 g_IdleMainSmootherRateDecrease;
|
|
|
|
f32 g_StuntSpeedBoostDecelSmoothing = 100.f;
|
|
u32 g_StuntSpeedBoostDecelSmoothingDuration = 2500;
|
|
|
|
u32 g_MaxGranularEngines = 5;
|
|
|
|
f32 g_ExhaustPopRateThreshold = 1.f;
|
|
f32 audCarAudioEntity::sm_MaxSuspensionStartOffset = 90.f;
|
|
|
|
u32 g_EngineStartDuration = 1000;
|
|
u32 g_EngineStopDuration = 300;
|
|
|
|
f32 g_EngineVolumeTrim = 0.0f;
|
|
f32 g_ExhaustVolumeTrim = 0.0f;
|
|
f32 g_GranularAccelVolumeTrim = 0.0f;
|
|
f32 g_GranularDecelVolumeTrim = 0.0f;
|
|
f32 g_GranularIdleVolumeTrim = 0.0f;
|
|
f32 g_GranularXValueSmoothRate = 1.0f;
|
|
f32 g_GranularEngineRevMultiplier = 1.0f;
|
|
f32 g_NPCVehicleRevsScalar = 1.2f;
|
|
f32 g_OffscreenVisiblityScalar = 0.2f;
|
|
u32 g_EngineSwitchFadeInTime = 1000;
|
|
u32 g_EngineSwitchFadeOutTime = 500;
|
|
f32 g_LODSpeedBias = 0.9f;
|
|
f32 g_LODMinSpeedRatio = 0.05f;
|
|
f32 g_LODMaxSpeedRatio = 0.4f;
|
|
f32 g_MinDamageThrottleCutDuration = 0.05f;
|
|
f32 g_MaxDamageThrottleCutDuration = 0.25f;
|
|
f32 g_ShortDamageCutProbMin = 0.4f;
|
|
f32 g_ShortDamageCutProbMax = 0.7f;
|
|
s32 g_MinTimeBetweenDamageThrottleCutsShort = 50;
|
|
s32 g_MaxTimeBetweenDamageThrottleCutsShort = 350;
|
|
s32 g_MinTimeBetweenDamageThrottleCuts = 2000;
|
|
s32 g_MaxTimeBetweenDamageThrottleCuts = 4000;
|
|
f32 g_GearboxVolumeTrim = 0.0f;
|
|
f32 g_TurboVolumeTrim = 0.0f;
|
|
f32 g_WindNoiseSmootherIncreaseRate = 700.0f;
|
|
f32 g_WindNoiseSmootherDecreaseRate = 10.0f;
|
|
f32 g_HyrdaulicInputBounceLimit = 0.75f;
|
|
f32 g_MaxHydraulicBounceVolumeReduction = 0.5f;
|
|
u32 g_HydraulicsJumpLandSuppressionTime = 300;
|
|
|
|
bool g_LinkExhaustPopsToAudioRevs = true;
|
|
bool g_RevsBoostEffectEnabled = true;
|
|
f32 g_RevsBoostPitchOffset = 150.0f;
|
|
f32 g_RevsBoostRevsScalar = 1.2f;
|
|
f32 g_RevsBoostAngularVelocityLimit = 0.01f;
|
|
f32 g_RevsBoostAngularVelocityLimitSensitivity = 39.0f;
|
|
f32 g_RevsBoostPitchOffsetFadeInTime = 10.0f;
|
|
f32 g_RevsBoostPitchOffsetFadeOutTime = 2.0f;
|
|
f32 g_RevsBoostRevsScaleFadeInTime = 15.0f;
|
|
f32 g_RevsBoostRevsScaleFadeOutTime = 1.0f;
|
|
f32 g_RevsBoostEffectFwdSpeedRatio = 0.80f;
|
|
f32 g_RevsBoostEffectFwdSpeedRatioNPC = 0.70f;
|
|
f32 g_RevsBoostEffectRevRatio = 0.75f;
|
|
|
|
bool g_SportsCarRevsEnabled = true;
|
|
bool g_RevsBoostPitchOffsetOnlyInFinalGear = false;
|
|
|
|
bool g_DisplayClusteredVehicles = false;
|
|
bool g_EnableDamageThrottleCut = true;
|
|
bool g_GranularLimiterEnabled = true;
|
|
bool g_GranularWobblesEnabled = true;
|
|
bool g_GranularDebugRenderingEnabled = false;
|
|
bool g_NonGranularDebugRenderingEnabled = false;
|
|
bool g_GranularIdleDebugRenderingEnabled = false;
|
|
bool g_GranularForceLowQuality = false;
|
|
bool g_GranularForceHighQuality = false;
|
|
bool g_GranularEnableNPCGranularEngines = true;
|
|
bool g_ForceGranularNPCEngines = false;
|
|
bool g_RenderGranularNPCEngines = false;
|
|
bool g_GranularLODEqualPowerCrossfade = false;
|
|
bool g_AllowSynthsOnNetworkVehicles = true;
|
|
|
|
#if __BANK
|
|
bool g_RenderTimeSlicedVehicles = false;
|
|
bool g_EngineVolumeCaptureActive = false;
|
|
bool g_DisableHorns = false;
|
|
bool g_DebugSpecialFlightMode = false;
|
|
bool g_DebugCarPasses = false;
|
|
bool g_ToggleNos = false;
|
|
bool g_ForceEnableBlips = false;
|
|
bool g_DisableThrottleBlips = false;
|
|
bool g_ForceMuteGranularSynths = false;
|
|
bool g_DisableConing = false;
|
|
bool g_MutePlayerVehicle = false;
|
|
bool g_ForceShallowWater = false;
|
|
bool g_DrawVehicleLODQuadrants = false;
|
|
bool g_ForceAutoShutoffEngines = false;
|
|
bool g_SimulateDrowning = false;
|
|
bool g_GranularSkipGrainTogglePressed = false;
|
|
bool g_GranularSkipEveryOtherGrain = false;
|
|
bool g_GranularToneGeneratorEnabled = false;
|
|
bool g_GranularToggleTestTonePressed = false;
|
|
bool g_VehicleAudioAllowEntityFocus = false;
|
|
bool g_ForceRealLodOnFocusEntity = false;
|
|
bool g_SimulatePlayerEnteringVehicle = false;
|
|
bool g_TestForceGameObject = false;
|
|
char g_TestForceGameObjectName[64] = { "BANSHEE" };
|
|
bool g_GranularLoopEditorShiftLeftPressed = false;
|
|
bool g_GranularLoopEditorShiftRightPressed = false;
|
|
bool g_GranularLoopEditorGrowLoopPressed = false;
|
|
bool g_GranularLoopEditorShrinkLoopPressed = false;
|
|
bool g_GranularLoopEditorCreateLoopPressed = false;
|
|
bool g_GranularLoopEditorDeleteLoopPressed = false;
|
|
bool g_GranularLoopEditorExportDataPressed = false;
|
|
bool g_GranularEditorControlRevsThrottle = false;
|
|
bool g_GranularForceRevLimiter = false;
|
|
bool g_SetGranularEngineIdleNative = false;
|
|
bool g_SetGranularExhaustIdleNative = false;
|
|
bool g_DebugDrawTurret = false;
|
|
bool g_DebugDrawTowArm = false;
|
|
bool g_DebugDrawGrappling = false;
|
|
f32 g_GrapSoundAcceleration = 0.f;
|
|
f32 g_GrapIntensity = 0.f;
|
|
s32 g_WeaponAmmoCountOverride = -1;
|
|
bool g_DisplayDamageDebug = false;
|
|
bool g_MuteDamageLayers = false;
|
|
bool g_MuteFanbeltDamage = false;
|
|
bool g_MuteGranularDamage = false;
|
|
bool g_ForceAllCarsAlwaysDamaged = false;
|
|
bool g_OverrideHydraulicSuspensionDamage = false;
|
|
f32 g_OverridenHydraulicSuspensionDamage = 1.f;
|
|
s32 g_GranularInterGrainCrossfadeStyle = (s32)audGranularMix::s_InterGrainCrossfadeStyle;
|
|
s32 g_GranularLoopGrainCrossfadeStyle = (s32)audGranularMix::s_LoopGrainCrossfadeStyle;
|
|
s32 g_GranularLoopLoopCrossfadeStyle = (s32)audGranularMix::s_LoopLoopCrossfadeStyle;
|
|
s32 g_GranularMixCrossfadeStyle = (s32)audGranularMix::s_GranularMixCrossfadeStyle;
|
|
bool g_ShowVehiclesWithWaveSlots = false;
|
|
bool g_ForceSynthsOnAllEngines = false;
|
|
bool g_TestWobble = false;
|
|
u32 g_TestWobbleLength = 50;
|
|
f32 g_TestWobbleLengthVariance = 0.0f;
|
|
f32 g_TestWobbleSpeed = 0.175f;
|
|
f32 g_TestWobbleSpeedVariance = 0.0f;
|
|
f32 g_TestWobblePitch = 0.1f;
|
|
f32 g_TestWobblePitchVariance = 0.0f;
|
|
f32 g_TestWobbleVolume = 0.35f;
|
|
f32 g_TestWobbleVolumeVariance = 0.0f;
|
|
bool g_DrawVehiclesInModShop = false;
|
|
bool g_ForceUpgradeEngine = false;
|
|
f32 g_ForcedEngineUpgradeLevel = 1.0f;
|
|
bool g_ForceUpgradeExhaust = false;
|
|
f32 g_ForcedExhaustUpgradeLevel = 1.0f;
|
|
bool g_ForceUpgradeEngineBay[3] = { false, false, false };
|
|
f32 g_ForcedEngineBayUpgradeLevel[3] = { 1.0f, 1.0f, 1.0f };
|
|
bool g_ForceUpgradeTransmission = false;
|
|
f32 g_ForcedTransmissionUpgradeLevel = 1.0f;
|
|
bool g_ForceUpgradeTurbo = false;
|
|
f32 g_ForcedTurboUpgradeLevel = 1.0f;
|
|
bool g_ForceUpgradeRadio = false;
|
|
f32 g_ForcedRadioUpgradeLevel = 1.0f;
|
|
bool g_ForceDamage = false;
|
|
bool g_ForceWheelDamage = false;
|
|
bool g_TestBackfire = false;
|
|
bool g_TestBackfireBanger = false;
|
|
bool g_DebugDrawVehicleWater = false;
|
|
f32 g_ForcedDamageFactor = 0.0f;
|
|
f32 g_GranularEditorRevs = 0.0f;
|
|
f32 g_GranularEditorThrottle = 0.0f;
|
|
s32 g_ForcePlayerVehicleLOD = AUD_VEHICLE_LOD_UNKNOWN;
|
|
|
|
const char * g_VehicleLODNames[5] = {
|
|
"Real",
|
|
"Dummy",
|
|
"Super Dummy",
|
|
"Disabled",
|
|
"Default",
|
|
};
|
|
|
|
const char * g_GranularPlaybackStyleNames[4] = {
|
|
"Loops And Grains",
|
|
"Loops Only",
|
|
"Grains Only",
|
|
"Dynamic",
|
|
};
|
|
|
|
const char * g_GranularCrossfadeStyleNames[2] = {
|
|
"Linear",
|
|
"Equal Power",
|
|
};
|
|
|
|
const char * g_GranularMixStyleNames[3] = {
|
|
"Accel and Decel",
|
|
"Accel Only",
|
|
"Decel Only",
|
|
};
|
|
|
|
const char * g_GranularRandomisationStyleNames[5] = {
|
|
"Sequential",
|
|
"Random",
|
|
"Walk",
|
|
"Reverse",
|
|
"MixNMatch",
|
|
};
|
|
|
|
f32 g_GranularSlidingWindowSizeHzFraction = 0.035f;
|
|
u32 g_GranularSlidingWindowMinGrains = 5;
|
|
u32 g_GranularSlidingWindowMaxGrains = 30;
|
|
u32 g_GranularMinRepeatRate = 3;
|
|
s32 g_GranularMixStyle = 0;
|
|
s32 g_GranularRandomisationStyle = audGranularSubmix::PlaybackOrderWalk;
|
|
s32 g_GranularIdleRandomisationStyle = audGranularSubmix::PlaybackOrderMax;
|
|
s32 g_GrainPlaybackStyle = audGranularMix::PlaybackStyleMax;
|
|
|
|
bool g_ForceSleighBellsOn = false;
|
|
#endif
|
|
|
|
extern f32 g_ClatterMaxAcceleration;
|
|
extern f32 g_SpinRatioForDebris;
|
|
extern f32 g_SpeedForSpinDebris;
|
|
|
|
extern f32 g_ElectricEngineBoostVolScale;
|
|
extern f32 g_ElectricEngineSpeedVolScale;
|
|
extern f32 g_ElectricEngineRevsOffVolScale;
|
|
extern f32 g_ElectricEngineSpeedLoopSpeedApplyScalar;
|
|
extern f32 g_ElectricEngineSpeedLoopSpeedBias;
|
|
|
|
audCurve audCarAudioEntity::sm_BrakeToBrakeDiscVolumeCurve;
|
|
audCurve audCarAudioEntity::sm_SpeedToBrakeDiscVolumeCurve;
|
|
audCurve audCarAudioEntity::sm_BrakeHoldTimeToStartOffsetCurve;
|
|
audSmoother audCarAudioEntity::sm_PlayerWindNoiseSpeedSmoother;
|
|
SportsCarRevsSettings* audCarAudioEntity::sm_SportsCarRevsSettings = NULL;
|
|
|
|
BANK_ONLY(bool g_AuditionWheelFire = false;);
|
|
BANK_ONLY(extern f32 g_WaveSlotStreamingDelayTime;)
|
|
|
|
audCurve g_EngineLowVolCurve;
|
|
audCurve g_EngineHighVolCurve;
|
|
audCurve g_ExhaustLowVolCurve;
|
|
audCurve g_ExhaustHighVolCurve;
|
|
audCurve g_EngineExhaustPitchCurve;
|
|
audCurve g_IdleVolCurve;
|
|
audCurve g_IdlePitchCurve;
|
|
|
|
// engine curves
|
|
audCurve audCarAudioEntity::sm_SuspensionVolCurve;
|
|
audCurve audCarAudioEntity::sm_SkidFwdSlipToScrapeVol, audCarAudioEntity::sm_LateralSlipToSideVol;
|
|
audCurve g_PlayerThrottleCurve;
|
|
audCurve g_PlayerRevsCurve;
|
|
audCurve g_PedThrottleCurve;
|
|
audCurve g_PedRevsCurve;
|
|
audCurve audCarAudioEntity::sm_EnvironmentalLoudnessThrottleCurve, audCarAudioEntity::sm_EnvironmentalLoudnessRevsCurve;
|
|
audCurve g_RevsSmoothingCurve;
|
|
audCurve g_PlayerAngVelToCarPass;
|
|
|
|
extern bool g_PretendThePlayerIsPissedOff;
|
|
extern bool g_BreakOnVehicleUpdate;
|
|
extern bool g_RenderSlotManager;
|
|
extern bool g_ShowRadioGenres;
|
|
extern bool g_DebugDSPParams;
|
|
extern bool g_DisableEngineExhaustDSP;
|
|
extern bool g_DebugVehicleOpenness;
|
|
extern f32 g_NPCRoadNoiseOuterAngle;
|
|
extern f32 g_NPCRoadNoiseInnerAngle;
|
|
extern f32 g_TransWobbleFreq;
|
|
extern f32 g_TransWobbleFreqVariance;
|
|
extern f32 g_TransWobbleMag;
|
|
extern f32 g_TransWobbleMagVariance;
|
|
extern f32 g_TransWobbleLength;
|
|
extern f32 g_TransWobbleLengthVariance;
|
|
BANK_ONLY(extern bool g_ForceTransWobble;)
|
|
BANK_ONLY(extern bool g_ShowDoorRatios;)
|
|
|
|
#if NA_RADIO_ENABLED
|
|
extern bank_float g_LoudVehicleRadioOffset;
|
|
#endif
|
|
extern f32 g_LowerVehDynamicImpactThreshold;
|
|
extern f32 g_UpperVehDynamicImpactThreshold;
|
|
extern bool g_GranularEnabled;
|
|
extern f32 g_GranularAccelDecelSmoothRate;
|
|
|
|
f32 audCarAudioEntity::sm_TimeToApplyHandbrake = 2.0f; // time in s until the fake handbrake is applied
|
|
|
|
audSoundSet audCarAudioEntity::sm_DamageSoundSet;
|
|
|
|
// m2
|
|
f32 g_DummyRadii[NUM_VEHICLEVOLUMECATEGORY] =
|
|
{
|
|
50.f * 50.f, //VEHICLE_VOLUME_VERY_LOUD,
|
|
45.f * 45.f, //VEHICLE_VOLUME_LOUD,
|
|
43.f * 43.f, //VEHICLE_VOLUME_NORMAL,
|
|
40.f * 40.f, //VEHICLE_VOLUME_QUIET,
|
|
37.f * 37.f, //VEHICLE_VOLUME_VERY_QUIET,
|
|
};
|
|
|
|
audCurve g_RelSpeedToCarByVol;
|
|
audCurve g_DistanceToCarByVol;
|
|
|
|
bool g_ShowEngineExhaust = false;
|
|
|
|
f32 g_BrakeLinearVolumeSmootherRate = 0.5f;
|
|
|
|
extern f32 g_BonnetCamGTOffset;
|
|
extern f32 g_TurboSpinUp;
|
|
extern f32 g_TurboSpinDown;
|
|
extern f32 g_DumpValvePressureThreshold;
|
|
|
|
// in dBs, the volume range of the throttle (vol = 0 - (1-throttle) * range))
|
|
const f32 g_audThrottleVolumeRange = 0.f;
|
|
f32 g_audExhaustThrottleVolumeRange = 1.f;
|
|
|
|
// gear boxes wont crunch unless damage is above this
|
|
f32 g_audVehicleDamageFactoGearBoxCrunch = 0.4f;
|
|
// this probability will be scaled by damage factor
|
|
f32 g_audVehicleGearBoxCrunchProb = 0.65f;
|
|
|
|
f32 g_audEngineSteamSoundVolRange = -2.5f;
|
|
|
|
extern f32 g_ExhaustProximityEffectRange;
|
|
|
|
f32 g_MinCarRollSpeed = 1.0f;
|
|
f32 g_MaxCarRollSpeed = 15.0f;
|
|
f32 g_MinCarRollImpulseMag = 0.1f;
|
|
f32 g_MaxCarRollImpulseMag = 1.0;
|
|
|
|
const f32 g_EnginePowerBand[11] =
|
|
{
|
|
2.f, // reverse, only ever gets to 50%
|
|
0.95f, // full gear for 1st and 2nd
|
|
0.9f,
|
|
0.7f,
|
|
0.60f,
|
|
0.6f,
|
|
0.6f,
|
|
0.6f,
|
|
0.6f,
|
|
0.6f,
|
|
0.6f
|
|
};
|
|
|
|
CompileTimeAssert((MAX_NUM_GEARS + 1) == sizeof(g_EnginePowerBand)/sizeof(g_EnginePowerBand[0]));
|
|
|
|
audCategory *g_PlayerVolumeCategories[5];
|
|
audCategory *g_PedVolumeCategories[5];
|
|
audCategory *g_EngineCategory, *g_EngineLoudCategory, *g_EngineDamageCategory;
|
|
audCategory *g_IgnitionCategory;
|
|
|
|
audCurve g_EnginePowerToDistortion;
|
|
|
|
#if __BANK
|
|
bool g_TreatAsPedCar = false;
|
|
bool g_DebugWindNoise = false;
|
|
bool g_TreatAsDummyCar = false;
|
|
bool g_DisableVolumeCategory = false;
|
|
audSound *g_EngineReferenceLoop = NULL;
|
|
bool g_MuteSuspension = false;
|
|
bool g_ForceNPCHydraulicSounds = false;
|
|
bool g_DebugHydraulicSounds = false;
|
|
bool g_DisableClatter = false;
|
|
bool g_DisplayRidgedSurfaceInfo = false;
|
|
|
|
f32 g_OverriddenThrottle = 0.f;
|
|
f32 g_OverriddenRevs = 0.f;
|
|
bool g_OverrideSim = false;
|
|
bool g_RenderVehicleSlots = false;
|
|
bool g_BlipPlayerThrottle = false;
|
|
bool g_DisableRoadNoise = false;
|
|
bool g_DisableNPCRoadNoise = false;
|
|
bool g_ShowNPCRoadNoiseState = false;
|
|
bool g_AutoReapplyDSPPresets = false;
|
|
bool g_DisplayDirtGlassInfo = false;
|
|
bool g_DrawLinesToRealCars = false;
|
|
bool g_DrawCarsPlayingSportsRevs = false;
|
|
bool g_DrawSportsRevsPassbyDebug = false;
|
|
bool g_ForceAllCarsPlaySportsRevs = false;
|
|
bool g_DrawLinesToVehiclesWithWaveSlots = false;
|
|
bool g_DrawLinesToVehiclesWithSubmixVoices = false;
|
|
bool g_ShowEngineStates = false;
|
|
bool g_DrawSuperDummyRadius = false;
|
|
bool g_ShowFocusVehicle = false;
|
|
|
|
extern bool g_ForceGlassySurface;
|
|
extern bool g_ForceDirtySurface;
|
|
extern f32 g_WheelDirtinessIncreaseSmoothRate;
|
|
extern f32 g_WheelDirtinessDecreaseSmoothRate;
|
|
extern f32 g_WheelGlassinessIncreaseSmoothRate;
|
|
extern f32 g_WheelGlassinessDecreaseSmoothRate;
|
|
extern f32 g_GlassAreaDepletionRate;
|
|
|
|
extern char g_DrivingMaterialName[64];
|
|
extern bool g_DisplayGroundMaterial;
|
|
extern bool g_DebugVehicleSkids;
|
|
#endif
|
|
|
|
extern bool g_DisableBurnoutSkidsInReverse;
|
|
float g_CarVelForPedImpact = 0.2f;
|
|
extern float g_BodyDamageFactorForDebris;
|
|
extern float g_BodyDamageFactorForHydraulicDebris;
|
|
float g_DamageImpactVel = 10.f;
|
|
float g_TrailerBumpVel = 5.f;
|
|
|
|
extern float g_DeformationImpactVel;
|
|
|
|
f32 g_MissionVehicleRevsScaler = 1.3f;
|
|
bool g_ForceRandomBlips = false;
|
|
bank_float g_RandomBlipMaxSpeed = 5.0f;
|
|
bank_float g_MinSqDistForFastBlips = 225.0f;
|
|
|
|
extern f32 g_PlayerHornOffset;
|
|
|
|
extern const u32 g_TemperatureVariableHash = ATSTRINGHASH("temperature", 0x0d649ef0f);
|
|
audSound *g_ExhaustEffectFix = NULL, *g_EngineEffectFix = NULL;
|
|
|
|
static const struct tDamageLayerDescription g_EngineDamageLayers[] = {
|
|
|
|
{ATSTRINGHASH("DAMAGE_RATTLE_AND_SQUEEK", 0xF93244FE), ATSTRINGHASH("DAMAGE_CURVES_RATTLE_AND_SQUEEK_VOL", 0xE50748DC)}, //0 heavy
|
|
{ATSTRINGHASH("DAMAGE_EXTRA_LOOP_2", 0x89E5DB76), ATSTRINGHASH("DAMAGE_CURVES_EXTRA_LOOP_2", 0xAD448DC0)}, // 1 light
|
|
{ATSTRINGHASH("DAMAGE_EXTRA_LOOP_3", 0x7B053DB5), ATSTRINGHASH("DAMAGE_CURVES_EXTRA_LOOP_3", 0xCE9CD070)}, // 2 heavy
|
|
{ATSTRINGHASH("DAMAGE_EXTRA_LOOP_4", 0x642F1009), ATSTRINGHASH("DAMAGE_CURVES_EXTRA_LOOP_4", 0xB4A29C70)}, // 3 light
|
|
{ATSTRINGHASH("DAMAGE_EXTRA_LOOP_5", 0xD7AA76FE), ATSTRINGHASH("DAMAGE_CURVES_EXTRA_LOOP_5", 0xD73AE1A0)}, // 4 heavy
|
|
{ATSTRINGHASH("DAMAGE_EXTRA_LOOP_7", 0xB340AE2B), ATSTRINGHASH("DAMAGE_CURVES_EXTRA_LOOP_7", 0xC2B73899)}, // 5 light
|
|
};
|
|
|
|
static const u32 g_LightDamageLayerIndices[] = {1,3,5};
|
|
static const u32 g_HeavyDamageLayerIndices[] = {0,2,4};
|
|
const u32 g_NumHeavyDamageLayers = (sizeof(g_HeavyDamageLayerIndices)/sizeof(u32));
|
|
const u32 g_NumLightDamageLayers = (sizeof(g_LightDamageLayerIndices)/sizeof(u32));
|
|
const u32 g_NumDamageLayers = (sizeof(g_EngineDamageLayers)/sizeof(g_EngineDamageLayers[0]));
|
|
|
|
audCurve g_EngineDamageCurves[g_NumDamageLayers];
|
|
|
|
#if __WIN32
|
|
#pragma warning(push)
|
|
#pragma warning(disable: 4355) // 'this' used in base member initializer list
|
|
#endif
|
|
|
|
audCarAudioEntity::audCarAudioEntity() : audVehicleAudioEntity()
|
|
{
|
|
m_VehicleLOD = AUD_VEHICLE_LOD_DISABLED;
|
|
m_VehicleType = AUD_VEHICLE_CAR;
|
|
m_DiscBrakeSqueel = NULL;
|
|
m_BrakeReleaseSound = NULL;
|
|
m_ParkingBeep = NULL;
|
|
m_SpecialFlightModeSound = NULL;
|
|
m_StartUpRevsSound = NULL;
|
|
m_InAirRotationSound = NULL;
|
|
m_RevsBlipSound = NULL;
|
|
m_NOSBoostLoop = NULL;
|
|
m_OffRoadRumbleSound = NULL;
|
|
m_BankSpray = NULL;
|
|
m_WooWooSound = NULL;
|
|
m_GliderSound = NULL;
|
|
m_ToyCarEngineLoop = NULL;
|
|
m_SubmarineTransformSound = NULL;
|
|
m_WindFastSound = NULL;
|
|
m_DamageTyreScrapeSound = NULL;
|
|
m_DamageTyreScrapeTurnSound = NULL;
|
|
m_HydraulicSuspensionInputLoop = NULL;
|
|
m_HydraulicSuspensionAngleLoop = NULL;
|
|
m_SportsCarRevsSound = NULL;
|
|
m_OffRoadRumblePulse = NULL;
|
|
m_AdditionalRevsSmoothing = 0.0f;
|
|
|
|
for(u32 i = 0 ; i < g_NumDamageLayersPerCar; i++)
|
|
{
|
|
m_EngineDamageLayers[i] = NULL;
|
|
}
|
|
|
|
for(u32 i = 0; i < NUM_VEH_CWHEELS_MAX; i++)
|
|
{
|
|
m_WheelGrindLoops[i] = NULL;
|
|
m_SuspensionSounds[i] = NULL;
|
|
m_TyreDamageLoops[i] = NULL;
|
|
m_WheelOffRoadSounds[i] = NULL;
|
|
m_WheelOffRoadSoundHashes[i] = g_NullSoundHash;
|
|
}
|
|
}
|
|
|
|
#if __WIN32
|
|
#pragma warning(pop)
|
|
#endif
|
|
|
|
audCarAudioEntity::~audCarAudioEntity()
|
|
{
|
|
ShutdownPrivate();
|
|
}
|
|
|
|
void audCarAudioEntity::Shutdown()
|
|
{
|
|
ShutdownPrivate();
|
|
audVehicleAudioEntity::Shutdown();
|
|
}
|
|
|
|
void audCarAudioEntity::ShutdownPrivate()
|
|
{
|
|
if(m_IsGeneratingReflections)
|
|
{
|
|
g_ReflectionsAudioEntity.RemoveVehicleReflections(this);
|
|
}
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------
|
|
// audCarAudioEntity::UpdateClass
|
|
// -------------------------------------------------------------------------------
|
|
void audCarAudioEntity::UpdateClass()
|
|
{
|
|
f32 averageCarSpeed = sm_NumActiveCars > 0? sm_CarFwdSpeedSum/sm_NumActiveCars : 0.0f;
|
|
g_AudioEngine.GetSoundManager().SetVariableValue(ATSTRINGHASH("Game.Ambience.AverageCarSpeed", 0xB49F8979), averageCarSpeed);
|
|
|
|
sm_CarFwdSpeedSum = 0.0f;
|
|
sm_NumActiveCars = 0;
|
|
|
|
#if __BANK
|
|
if(g_DrawVehicleLODQuadrants)
|
|
{
|
|
Vector3 playerPos = VEC3V_TO_VECTOR3(CGameWorld::FindLocalPlayer()->GetTransform().GetPosition());
|
|
grcDebugDraw::Line(playerPos,playerPos + 10.f *MAT34V_TO_MATRIX34(g_AudioEngine.GetEnvironment().GetVolumeListenerMatrix()).b,Color_red);
|
|
grcDebugDraw::Line(playerPos,playerPos - 10.f *MAT34V_TO_MATRIX34(g_AudioEngine.GetEnvironment().GetVolumeListenerMatrix()).b,Color_red);
|
|
grcDebugDraw::Line(playerPos,playerPos + 10.f *MAT34V_TO_MATRIX34(g_AudioEngine.GetEnvironment().GetVolumeListenerMatrix()).a,Color_red);
|
|
grcDebugDraw::Line(playerPos,playerPos - 10.f *MAT34V_TO_MATRIX34(g_AudioEngine.GetEnvironment().GetVolumeListenerMatrix()).a,Color_red);
|
|
}
|
|
|
|
if(g_EngineVolumeCaptureActive)
|
|
{
|
|
UpdateVolumeCapture();
|
|
}
|
|
else
|
|
{
|
|
if(CFileMgr::IsValidFileHandle(sm_VolumeCaptureFileID))
|
|
{
|
|
CFileMgr::CloseFile(sm_VolumeCaptureFileID);
|
|
sm_VolumeCaptureFileID = INVALID_FILE_HANDLE;
|
|
sm_VolumeCaptureState = State_NextVehicle;
|
|
sm_VolumeCapturePeakLoudness = g_SilenceVolume;
|
|
sm_VolumeCapturePeakRMS = g_SilenceVolume;
|
|
sm_VolumeCapturePeakAmplitude = g_SilenceVolume;
|
|
sm_VolumeCaptureTimer = 0.0f;
|
|
sm_VolumeCaptureFramesAtState = 0;
|
|
sm_VolumeCaptureRevs = 0.0f;
|
|
sm_VolumeCaptureThrottle = 0.0f;
|
|
sm_VolumeCaptureIntervalTimer = 0.0f;
|
|
sm_VolumeCaptureVehicleIndex = sm_VolumeCaptureVehicleStartIndex;
|
|
sm_VolumeCaptureLoudnessHistory.Reset();
|
|
sm_VolumeCaptureRMSHistory.Reset();
|
|
sm_VolumeCaptureAmplitudeHistory.Reset();
|
|
sm_VolumeCaptureVehicleRequest.Invalidate();
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#if __BANK
|
|
// -------------------------------------------------------------------------------
|
|
// Helper function for sorting vehicles by name
|
|
// -------------------------------------------------------------------------------
|
|
s32 QSortVehicleModels(CVehicleModelInfo* const* infoA, CVehicleModelInfo* const* infoB)
|
|
{
|
|
return stricmp((*infoA)->GetModelName(), (*infoB)->GetModelName());
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------
|
|
// Volume capture stuff needed on the update thread
|
|
// -------------------------------------------------------------------------------
|
|
void audCarAudioEntity::UpdateVolumeCaptureUpdateThread()
|
|
{
|
|
if(!fwSceneGraph::IsSceneGraphLocked())
|
|
{
|
|
if(sm_VolumeCaptureVehicleRequest.IsValid())
|
|
{
|
|
if(g_EngineVolumeCaptureActive)
|
|
{
|
|
CVehicle* localVehicle = CGameWorld::FindLocalPlayerVehicle();
|
|
|
|
if(!localVehicle)
|
|
{
|
|
sm_VolumeCaptureStartPos = CGameWorld::FindLocalPlayerCoors();
|
|
}
|
|
|
|
CVehicleFactory::WarpPlayerOutOfCar();
|
|
FindPlayerPed()->SetPosition(sm_VolumeCaptureStartPos, true, true, true);
|
|
|
|
CVehicle* oldVehicle = CVehicleFactory::GetCreatedVehicle();
|
|
|
|
if(oldVehicle)
|
|
{
|
|
CVehicleFactory::GetFactory()->Destroy(oldVehicle);
|
|
}
|
|
|
|
CVehicleFactory::CreateCar(sm_VolumeCaptureVehicleRequest.GetModelIndex());
|
|
CVehicleFactory::WarpPlayerIntoRecentCar();
|
|
}
|
|
|
|
sm_VolumeCaptureVehicleRequest.Invalidate();
|
|
}
|
|
}
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------
|
|
// Update the volume capture system
|
|
// -------------------------------------------------------------------------------
|
|
void audCarAudioEntity::UpdateVolumeCapture()
|
|
{
|
|
static const f32 captureInterval = 0.1f;
|
|
static const f32 captureRevTime = 7.0f;
|
|
static const f32 captureSwitchTime = 12.0f;
|
|
|
|
if(audVerifyf(audDriver::GetMixer()->GetLoudnessMeter() != NULL, "Volume capture requires -audiodesigner"))
|
|
{
|
|
CVehicle* localPlayerVeh = CGameWorld::FindLocalPlayerVehicle();
|
|
const char* vehicleName = NULL;
|
|
|
|
VolumeCaptureState initialState = sm_VolumeCaptureState;
|
|
char tempString[256];
|
|
float xCoord = 0.1f;
|
|
float yCoord = 0.2f;
|
|
|
|
formatf(tempString, "Engine Volume Capture Active");
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
if(localPlayerVeh)
|
|
{
|
|
CarAudioSettings* currentCarSettings = ((audCarAudioEntity*)localPlayerVeh->GetVehicleAudioEntity())->GetCarAudioSettings();
|
|
vehicleName = audNorthAudioEngine::GetMetadataManager().GetObjectNameFromNameTableOffset(currentCarSettings->NameTableOffset);
|
|
formatf(tempString, "Current Vehicle: %s", vehicleName);
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
}
|
|
|
|
yCoord += 0.02f;
|
|
|
|
if(localPlayerVeh)
|
|
{
|
|
formatf(tempString, "Type: %s", ((audCarAudioEntity*)localPlayerVeh->GetVehicleAudioEntity())->IsUsingGranularEngine()? "Granular" : "Non-Granular");
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
}
|
|
|
|
yCoord += 0.02f;
|
|
|
|
switch(sm_VolumeCaptureState)
|
|
{
|
|
case State_NextVehicle:
|
|
{
|
|
formatf(tempString, "State: Selecting Next Vehicle");
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
if(sm_VolumeCaptureFramesAtState == 0)
|
|
{
|
|
if(!CFileMgr::IsValidFileHandle(sm_VolumeCaptureFileID))
|
|
{
|
|
// Try and open a file for the results
|
|
CFileMgr::SetDir("common:/DATA");
|
|
sm_VolumeCaptureFileID = CFileMgr::OpenFileForWriting("VehicleVolumeCapture.csv");
|
|
CFileMgr::SetDir("");
|
|
|
|
if(!audVerifyf(CFileMgr::IsValidFileHandle(sm_VolumeCaptureFileID), "Failed to open VehicleVolumeCapture.csv"))
|
|
{
|
|
g_EngineVolumeCaptureActive = false;
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
char fileOutput[255];
|
|
formatf(fileOutput, "%s,%s,%s, ,%s\n", "Vehicle", "Metric", "Peak", "Data");
|
|
CFileMgr::Write(sm_VolumeCaptureFileID, &fileOutput[0], istrlen(fileOutput));
|
|
audDriver::GetMixer()->GetMasterSubmix()->SetFlag(audMixerSubmix::ComputePeakAmplitude, true);
|
|
sm_VolumeCaptureVehicleIndex = sm_VolumeCaptureVehicleStartIndex;
|
|
}
|
|
}
|
|
|
|
atArray<CVehicleModelInfo*> vehicleTypeArray;
|
|
fwArchetypeDynamicFactory<CVehicleModelInfo>& vehModelInfoStore = CModelInfo::GetVehicleModelInfoStore();
|
|
vehModelInfoStore.GatherPtrs(vehicleTypeArray);
|
|
vehicleTypeArray.QSort(0, -1, QSortVehicleModels);
|
|
u32 numVehicleNames = vehicleTypeArray.GetCount();
|
|
const char* vehicleName = NULL;
|
|
|
|
while(sm_VolumeCaptureVehicleIndex < numVehicleNames)
|
|
{
|
|
vehicleName = vehicleTypeArray[sm_VolumeCaptureVehicleIndex]->GetModelName();
|
|
VehicleType vehicleType = vehicleTypeArray[sm_VolumeCaptureVehicleIndex]->GetVehicleType();
|
|
bool isCar = (vehicleType == VEHICLE_TYPE_CAR || vehicleType == VEHICLE_TYPE_SUBMARINECAR || vehicleType == VEHICLE_TYPE_AMPHIBIOUS_AUTOMOBILE || vehicleType == VEHICLE_TYPE_BIKE || vehicleType == VEHICLE_TYPE_QUADBIKE || vehicleType == VEHICLE_TYPE_DRAFT || vehicleType == VEHICLE_TYPE_SUBMARINECAR || vehicleType == VEHICLE_TYPE_AMPHIBIOUS_QUADBIKE);
|
|
|
|
// We've found a valid car, so use this
|
|
if(isCar && audNorthAudioEngine::GetObject<CarAudioSettings>(vehicleName) != NULL)
|
|
{
|
|
fwModelId modelID = CModelInfo::GetModelIdFromName(vehicleName);
|
|
|
|
if(audVerifyf(modelID.IsValid(), "Invalid modelID!"))
|
|
{
|
|
sm_VolumeCaptureVehicleRequest = modelID;
|
|
}
|
|
else
|
|
{
|
|
g_EngineVolumeCaptureActive = false;
|
|
return;
|
|
}
|
|
|
|
break;
|
|
}
|
|
// Not a valid car, keep searching
|
|
else
|
|
{
|
|
sm_VolumeCaptureVehicleIndex++;
|
|
}
|
|
}
|
|
|
|
if(sm_VolumeCaptureVehicleIndex >= numVehicleNames)
|
|
{
|
|
// Fin
|
|
g_EngineVolumeCaptureActive = false;
|
|
return;
|
|
}
|
|
}
|
|
|
|
camInterface::GetGameplayDirector().GetThirdPersonCamera()->GetControlHelper()->SetLookBehindState(true);
|
|
camInterface::GetGameplayDirector().GetThirdPersonCamera()->GetControlHelper()->IgnoreLookBehindInputThisUpdate();
|
|
|
|
// Give the car time to load the new bank etc. - signalled by the request becoming invalid again
|
|
if(sm_VolumeCaptureTimer > 1.0f && localPlayerVeh && !sm_VolumeCaptureVehicleRequest.IsValid())
|
|
{
|
|
sm_VolumeCaptureState = State_CapturingAccel;
|
|
sm_VolumeCapturePeakLoudness = g_SilenceVolume;
|
|
sm_VolumeCapturePeakRMS = g_SilenceVolume;
|
|
sm_VolumeCapturePeakAmplitude = g_SilenceVolume;
|
|
sm_VolumeCaptureTimer = 0.0f;
|
|
sm_VolumeCaptureFramesAtState = 0;
|
|
sm_VolumeCaptureRevs = 0.0f;
|
|
sm_VolumeCaptureThrottle = 0.0f;
|
|
sm_VolumeCaptureIntervalTimer = 0.0f;
|
|
sm_VolumeCaptureLoudnessHistory.Reset();
|
|
sm_VolumeCaptureRMSHistory.Reset();
|
|
sm_VolumeCaptureAmplitudeHistory.Reset();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case State_CapturingAccel:
|
|
case State_CapturingAccelModded:
|
|
{
|
|
formatf(tempString, "State: Capturing %s", sm_VolumeCaptureState == State_CapturingAccel? "Accel" : "Modded Accel");
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
f32 desiredRevs = sm_VolumeCaptureTimer/captureRevTime;
|
|
|
|
if(desiredRevs > 1.1f)
|
|
{
|
|
sm_VolumeCaptureRevs = 0.0f;
|
|
sm_VolumeCaptureThrottle = 0.0f;
|
|
}
|
|
else
|
|
{
|
|
sm_VolumeCaptureRevs = desiredRevs;
|
|
sm_VolumeCaptureThrottle = 1.0f;
|
|
}
|
|
|
|
formatf(tempString, "Rev Ratio: %f", sm_VolumeCaptureRevs);
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
formatf(tempString, "Throttle: %f", sm_VolumeCaptureThrottle);
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
f32 peakAmplitude = audDriverUtil::ComputeDbVolumeFromLinear(Max(audDriver::GetMixer()->GetMasterSubmix()->GetAndResetPeakAmplitude(0), audDriver::GetMixer()->GetMasterSubmix()->GetAndResetPeakAmplitude(1)));
|
|
f32 loudness = audDriver::GetMixer()->GetLoudnessMeter()->GetLoudness();
|
|
f32 rms = audDriverUtil::ComputeDbVolumeFromLinear(audDriver::GetMixer()->GetMasterSubmix()->GetRMS());
|
|
|
|
if(sm_VolumeCaptureIntervalTimer > captureInterval)
|
|
{
|
|
sm_VolumeCaptureLoudnessHistory.PushAndGrow(loudness);
|
|
sm_VolumeCaptureRMSHistory.PushAndGrow(rms);
|
|
sm_VolumeCaptureAmplitudeHistory.PushAndGrow(peakAmplitude);
|
|
|
|
sm_VolumeCapturePeakLoudness = Max(loudness, sm_VolumeCapturePeakLoudness);
|
|
sm_VolumeCapturePeakRMS = Max(rms, sm_VolumeCapturePeakRMS);
|
|
sm_VolumeCapturePeakAmplitude = Max(peakAmplitude, sm_VolumeCapturePeakAmplitude);
|
|
sm_VolumeCaptureIntervalTimer = 0.0f;
|
|
}
|
|
|
|
static const char *meterNames[] = {"Loudness", "RMS", "Amplitude", "Peak Loudness", "Peak RMS", "Peak Amplitude"};
|
|
const u32 numMeters = sizeof(meterNames)/sizeof(meterNames[0]);
|
|
static audMeterList meterList;
|
|
static f32 meterValues[numMeters];
|
|
|
|
s32 i = 0;
|
|
meterValues[i++] = audDriverUtil::ComputeLinearVolumeFromDb(loudness);
|
|
meterValues[i++] = rms;
|
|
meterValues[i++] = peakAmplitude;
|
|
meterValues[i++] = audDriverUtil::ComputeLinearVolumeFromDb(sm_VolumeCapturePeakLoudness);
|
|
meterValues[i++] = sm_VolumeCapturePeakRMS;
|
|
meterValues[i++] = sm_VolumeCapturePeakAmplitude;
|
|
|
|
meterList.left = 128.0f;
|
|
meterList.bottom = 620.f;
|
|
meterList.width = 400.f;
|
|
meterList.height = 260.f;
|
|
meterList.values = &meterValues[0];
|
|
meterList.names = meterNames;
|
|
meterList.numValues = numMeters;
|
|
audNorthAudioEngine::DrawLevelMeters(&meterList);
|
|
|
|
if(sm_VolumeCaptureTimer > captureSwitchTime)
|
|
{
|
|
// Print our data to the csv file
|
|
char fileOutput[255];
|
|
u32 numOutputItems = (u32)(captureRevTime/captureInterval);
|
|
|
|
// Print loudness
|
|
formatf(fileOutput, "%s%s,Loudness,%.02f, ,", vehicleName, sm_VolumeCaptureState == State_CapturingAccelModded? "_MODDED" : "", sm_VolumeCapturePeakLoudness);
|
|
CFileMgr::Write(sm_VolumeCaptureFileID, &fileOutput[0], istrlen(fileOutput));
|
|
|
|
for(u32 loop = 0; loop < numOutputItems && loop < sm_VolumeCaptureLoudnessHistory.GetCount(); loop++)
|
|
{
|
|
formatf(fileOutput, "%.02f,", sm_VolumeCaptureLoudnessHistory[loop]);
|
|
CFileMgr::Write(sm_VolumeCaptureFileID, &fileOutput[0], istrlen(fileOutput));
|
|
}
|
|
|
|
formatf(fileOutput, "\n");
|
|
CFileMgr::Write(sm_VolumeCaptureFileID, &fileOutput[0], istrlen(fileOutput));
|
|
|
|
// Print RMS
|
|
formatf(fileOutput, ",RMS,%.02f, ,", sm_VolumeCapturePeakRMS);
|
|
CFileMgr::Write(sm_VolumeCaptureFileID, &fileOutput[0], istrlen(fileOutput));
|
|
|
|
for(u32 loop = 0; loop < numOutputItems && loop < sm_VolumeCaptureRMSHistory.GetCount(); loop++)
|
|
{
|
|
formatf(fileOutput, "%.02f,", sm_VolumeCaptureRMSHistory[loop]);
|
|
CFileMgr::Write(sm_VolumeCaptureFileID, &fileOutput[0], istrlen(fileOutput));
|
|
}
|
|
|
|
formatf(fileOutput, "\n");
|
|
CFileMgr::Write(sm_VolumeCaptureFileID, &fileOutput[0], istrlen(fileOutput));
|
|
|
|
// Print Amplitude
|
|
formatf(fileOutput, ",Amplitude,%.02f, ,", sm_VolumeCapturePeakAmplitude);
|
|
CFileMgr::Write(sm_VolumeCaptureFileID, &fileOutput[0], istrlen(fileOutput));
|
|
|
|
for(u32 loop = 0; loop < numOutputItems && loop < sm_VolumeCaptureAmplitudeHistory.GetCount(); loop++)
|
|
{
|
|
formatf(fileOutput, "%.02f,", sm_VolumeCaptureAmplitudeHistory[loop]);
|
|
CFileMgr::Write(sm_VolumeCaptureFileID, &fileOutput[0], istrlen(fileOutput));
|
|
}
|
|
|
|
formatf(fileOutput, "\n\n");
|
|
CFileMgr::Write(sm_VolumeCaptureFileID, &fileOutput[0], istrlen(fileOutput));
|
|
|
|
sm_VolumeCaptureState = sm_VolumeCaptureState == State_CapturingAccel? State_CapturingAccelModded : State_NextVehicle;
|
|
sm_VolumeCapturePeakLoudness = g_SilenceVolume;
|
|
sm_VolumeCapturePeakRMS = g_SilenceVolume;
|
|
sm_VolumeCapturePeakAmplitude = g_SilenceVolume;
|
|
sm_VolumeCaptureTimer = 0.0f;
|
|
sm_VolumeCaptureFramesAtState = 0;
|
|
sm_VolumeCaptureRevs = 0.0f;
|
|
sm_VolumeCaptureThrottle = 0.0f;
|
|
sm_VolumeCaptureIntervalTimer = 0.0f;
|
|
sm_VolumeCaptureLoudnessHistory.Reset();
|
|
sm_VolumeCaptureRMSHistory.Reset();
|
|
sm_VolumeCaptureAmplitudeHistory.Reset();
|
|
|
|
if(sm_VolumeCaptureState == State_NextVehicle)
|
|
{
|
|
sm_VolumeCaptureVehicleIndex++;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
// Don't update these if we've just switched state
|
|
if(initialState == sm_VolumeCaptureState)
|
|
{
|
|
sm_VolumeCaptureFramesAtState++;
|
|
sm_VolumeCaptureTimer += fwTimer::GetTimeStep();
|
|
sm_VolumeCaptureIntervalTimer += fwTimer::GetTimeStep();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
g_EngineVolumeCaptureActive = false;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// -------------------------------------------------------------------------------
|
|
// audCarAudioEntity::InitClass
|
|
// -------------------------------------------------------------------------------
|
|
void audCarAudioEntity::InitClass()
|
|
{
|
|
audVehicleConvertibleRoof::InitClass();
|
|
audVehicleTowTruckArm::InitClass();
|
|
|
|
g_PedVolumeCategories[0] = g_AudioEngine.GetCategoryManager().GetCategoryPtr(ATSTRINGHASH("PED_VEHICLES_VERY_LOUD", 0xD59675EA));
|
|
g_PedVolumeCategories[1] = g_AudioEngine.GetCategoryManager().GetCategoryPtr(ATSTRINGHASH("PED_VEHICLES_LOUD", 0xEA185B02));
|
|
g_PedVolumeCategories[2] = g_AudioEngine.GetCategoryManager().GetCategoryPtr(ATSTRINGHASH("PED_VEHICLES_NORMAL", 0xAC3F546D));
|
|
g_PedVolumeCategories[3] = g_AudioEngine.GetCategoryManager().GetCategoryPtr(ATSTRINGHASH("PED_VEHICLES_QUIET", 0x41ACDDFF));
|
|
g_PedVolumeCategories[4] = g_AudioEngine.GetCategoryManager().GetCategoryPtr(ATSTRINGHASH("PED_VEHICLES_VERY_QUIET", 0xC8B2D787));
|
|
|
|
g_PlayerVolumeCategories[0] = g_AudioEngine.GetCategoryManager().GetCategoryPtr(ATSTRINGHASH("PLAYER_VEHICLES_VERY_LOUD", 0x3AA35DEF));
|
|
g_PlayerVolumeCategories[1] = g_AudioEngine.GetCategoryManager().GetCategoryPtr(ATSTRINGHASH("PLAYER_VEHICLES_LOUD", 0xDCA3CC61));
|
|
g_PlayerVolumeCategories[2] = g_AudioEngine.GetCategoryManager().GetCategoryPtr(ATSTRINGHASH("PLAYER_VEHICLES_NORMAL", 0x1F418253));
|
|
g_PlayerVolumeCategories[3] = g_AudioEngine.GetCategoryManager().GetCategoryPtr(ATSTRINGHASH("PLAYER_VEHICLES_QUIET", 0x933E72C3));
|
|
g_PlayerVolumeCategories[4] = g_AudioEngine.GetCategoryManager().GetCategoryPtr(ATSTRINGHASH("PLAYER_VEHICLES_VERY_QUIET", 0xF05AAEDD));
|
|
|
|
g_EngineCategory = g_AudioEngine.GetCategoryManager().GetCategoryPtr(ATSTRINGHASH("VEHICLES_ENGINES", 0xF7C35252));
|
|
g_EngineLoudCategory = g_EngineCategory; //g_AudioEngine.GetCategoryManager().GetCategoryPtr(ATSTRINGHASH("CARS_ENGINES_LOUD", 0x7366FD5F));
|
|
g_EngineDamageCategory = g_AudioEngine.GetCategoryManager().GetCategoryPtr(ATSTRINGHASH("VEHICLES_ENGINES_DAMAGE", 0x19B73388));
|
|
g_IgnitionCategory = g_AudioEngine.GetCategoryManager().GetCategoryPtr(ATSTRINGHASH("VEHICLES_ENGINES_IGNITION", 0x1365BE95));
|
|
|
|
if(!sm_BrakeToBrakeDiscVolumeCurve.Init(ATSTRINGHASH("BRAKE_TO_BRAKE_DISC_VOLUME", 0xF33BF170)))
|
|
{
|
|
naWarningf("Failed to initialise BRAKE_TO_BRAKE_DISC_VOLUME");
|
|
}
|
|
if(!sm_SpeedToBrakeDiscVolumeCurve.Init(ATSTRINGHASH("SPEED_TO_BRAKE_DISC_VOLUME", 0x67A7E038)))
|
|
{
|
|
naWarningf("Failed to initialise SPEED_TO_BRAKE_DISC_VOLUME");
|
|
}
|
|
if(!sm_BrakeHoldTimeToStartOffsetCurve.Init(ATSTRINGHASH("BRAKE_HOLD_TIME_TO_START_OFFSET", 0xBCBD3464)))
|
|
{
|
|
naWarningf("Failed to initialise BRAKE_HOLD_TIME_TO_START_OFFSET");
|
|
}
|
|
if(!g_EnginePowerToDistortion.Init(ATSTRINGHASH("ENGINE_POWER_TO_DISTORTION", 0x8613F6AD)))
|
|
{
|
|
naWarningf("Failed to initialise ENGINE_POWER_TO_DISTORTION");
|
|
}
|
|
|
|
StaticConditionalWarning(g_IdleVolCurve.Init(ATSTRINGHASH("IDLE_VOLUME", 0xECEC42E2)), "Invalid IdleVolumeCurve");
|
|
StaticConditionalWarning(g_IdlePitchCurve.Init(ATSTRINGHASH("LINEAR_RISE", 0xD0E6F19)), "Invalid IdlePitchCurve");
|
|
StaticConditionalWarning(g_EngineLowVolCurve.Init(ATSTRINGHASH("ENGINE_LOW_VOLUME", 0x26BEE93D)), "Invalid LowEngineVolCurve");
|
|
StaticConditionalWarning(g_EngineHighVolCurve.Init(ATSTRINGHASH("ENGINE_HIGH_VOLUME", 0x5D56EA9B)), "Invalid HighEngineVolCurve");
|
|
StaticConditionalWarning(g_ExhaustLowVolCurve.Init(ATSTRINGHASH("EXHAUST_LOW_VOLUME", 0xF4EC46B2)), "Invalid LowExhaustVolCurve");
|
|
StaticConditionalWarning(g_ExhaustHighVolCurve.Init(ATSTRINGHASH("EXHAUST_HIGH_VOLUME", 0x17DE7D8F)), "Invalid HighExhaustVolCurve");
|
|
StaticConditionalWarning(g_EngineExhaustPitchCurve.Init(ATSTRINGHASH("ENGINE_PITCH_CURVE", 0x8E5FECAE)), "Invalid EnginePitchCurve");
|
|
StaticConditionalWarning(sm_EnvironmentalLoudnessThrottleCurve.Init(ATSTRINGHASH("ENVIRONMENTAL_LOUDNESS_THROTTLE_CURVE", 0x544E1E65)), "EnvironmentalLoudnessThrottleCurve");
|
|
StaticConditionalWarning(sm_EnvironmentalLoudnessRevsCurve.Init(ATSTRINGHASH("ENVIRONMENTAL_LOUDNESS_REVS_CURVE", 0x3E65DB4A)), "Invalid EnvironmentalLoudnessRevsCurve");
|
|
StaticConditionalWarning(sm_SuspensionVolCurve.Init(ATSTRINGHASH("SUSPENSION_COMPRESSION_TO_VOL", 0x2BEC9A45)), "Invalid SuspVolCurve");
|
|
StaticConditionalWarning(sm_SkidFwdSlipToScrapeVol.Init(ATSTRINGHASH("SKID_CURVES_FWD_SLIP_TO_SCRAPE_VOL", 0xB44AEB94)), "Invalid fwd slip to scrape");
|
|
StaticConditionalWarning(sm_LateralSlipToSideVol.Init(ATSTRINGHASH("SKID_CURVES_LATERAL_SLIP_TO_SIDE_VOL", 0xC2308CC3)), "invalid lateral slip to side");
|
|
StaticConditionalWarning(g_PlayerThrottleCurve.Init(ATSTRINGHASH("PLAYER_THROTTLE_CURVE", 0x2E2C2E62)), "Invalid player_throttle_curve");
|
|
StaticConditionalWarning(g_PlayerRevsCurve.Init(ATSTRINGHASH("PLAYER_REVS_CURVE", 0xDDAF5B01)), "Invalid player_revs_curve");
|
|
StaticConditionalWarning(g_PedThrottleCurve.Init(ATSTRINGHASH("PED_THROTTLE_CURVE", 0xEAE4078C)), "Invalid ped throttle_curve");
|
|
StaticConditionalWarning(g_PedRevsCurve.Init(ATSTRINGHASH("PED_REVS_CURVE", 0xEF094EBA)), "Invalid ped_revs_curve");
|
|
StaticConditionalWarning(g_RevsSmoothingCurve.Init(ATSTRINGHASH("REVS_SMOOTHING_RATE", 0x1B4E3DB0)), "invalid revs smoothing rate curve");
|
|
StaticConditionalWarning(g_RelSpeedToCarByVol.Init(ATSTRINGHASH("REL_SPEED_TO_CARBY_VOL", 0xE6D1B0E7)), "Invalid rel speed to carby vol");
|
|
StaticConditionalWarning(g_DistanceToCarByVol.Init(ATSTRINGHASH("DISTANCE_TO_CARBY_VOL", 0x3A34A988)), "Invalid distance to carby vol");
|
|
StaticConditionalWarning(g_PlayerAngVelToCarPass.Init(ATSTRINGHASH("PLAYER_ANG_VEL_TO_CAR_PASS_VOL", 0x427467E0)), "Invalid angvel to carby vol");
|
|
|
|
for(u32 i = 0; i < g_NumDamageLayers; i++)
|
|
{
|
|
g_EngineDamageCurves[i].Init(g_EngineDamageLayers[i].volCurveName);
|
|
}
|
|
|
|
for(u32 i = 0; i < kSportsCarRevsHistorySize; i++)
|
|
{
|
|
sm_SportsCarRevsSoundHistory[i].soundName = 0u;
|
|
sm_SportsCarRevsSoundHistory[i].time = 0u;
|
|
}
|
|
|
|
StaticConditionalWarning(sm_DamageSoundSet.Init(ATSTRINGHASH("VehicleDamage", 0x25E4D820)), "Failed to find VehicleDamage sound set");
|
|
sm_PlayerWindNoiseSpeedSmoother.Init(1.0f/g_WindNoiseSmootherIncreaseRate, 1.0f/g_WindNoiseSmootherDecreaseRate);
|
|
sm_SportsCarRevsSettings = audNorthAudioEngine::GetObject<SportsCarRevsSettings>(ATSTRINGHASH("SPORTS_CAR_REVS_SETTINGS_DEFAULT", 0xF4E580EC));
|
|
|
|
#if __BANK
|
|
sm_VolumeCaptureVehicleRequest.Invalidate();
|
|
#endif
|
|
}
|
|
|
|
void audCarAudioEntity::Reset()
|
|
{
|
|
audVehicleAudioEntity::Reset();
|
|
m_LastHydraulicBounceTime = 0u;
|
|
m_RevsLastFrame = 0.0f;
|
|
m_HydraulicBounceTimer = 0.0f;
|
|
m_SportsCarRevsRequested = false;
|
|
m_SportsCarRevsEnabled = false;
|
|
m_FakeEngineStartupRevs = false;
|
|
m_HydraulicAngleLoopRetriggerValid = true;
|
|
m_IsInAmphibiousBoatMode = false;
|
|
m_LeanRatio = 0.0f;
|
|
m_LastSportsCarRevsTime = 0;
|
|
m_NextDamageThrottleCutTime = 0;
|
|
m_ConsecutiveShortThrottleCuts = 0;
|
|
m_DamageThrottleCutTimer = 0.0f;
|
|
m_MaxSpeedPitchFactor = 0.0f;
|
|
m_MaxSpeedRevsAddition = 0.0f;
|
|
m_ScriptStartupRevsSoundRef = g_NullSoundRef;
|
|
m_DummyLODValid = false;
|
|
m_HasAutoShutOffEngine = false;
|
|
m_IsGeneratingReflections = false;
|
|
m_AutoShutOffTimer = 0.0f;
|
|
m_SportsCarRevsApplyFactor = 0.0f;
|
|
m_IsReversing = false;
|
|
m_WasUpsideDownInAir = false;
|
|
m_HasPlayedInitialJumpStress = false;
|
|
m_HasPlayedInAirJumpStress = true;
|
|
m_HasInitialisedVolumeCones = false;
|
|
m_WasWaitingAtLights = false;
|
|
m_WasDoingBurnout = false;
|
|
m_CarAudioSettings = NULL;
|
|
m_AmphibiousBoatSettings = NULL;
|
|
m_VehicleEngineSettings = NULL;
|
|
m_GranularEngineSettings = NULL;
|
|
m_ElectricEngineSettings = NULL;
|
|
m_DistanceToPlayerLastFrame = 0.f;
|
|
m_DistanceToPlayerDeltaLastFrame = 0.f;
|
|
m_WasInCarByRange = false;
|
|
m_LastCarByTime = 0;
|
|
m_WasSportsCarRevsCancelled = false;
|
|
m_JumpThrottleCutTimer = 0.0f;
|
|
m_OutOfWaterRevsMultiplier = 1.0f;
|
|
m_FakeRevsSmoother.Init(0.0001f, 0.0001f, 0.0f, 1.0f);
|
|
m_RevsSmoother.Init(g_RevMaxIncreaseRate / 1000.f,g_RevMaxDecreaseRate / 1000.f,true);
|
|
m_TyreDamageGrindRatioSmoother.Init(0.1f, 0.05f);
|
|
m_ThrottleSmoother.Init(0.005f,0.005f,-1.0f,1.0f);
|
|
m_RollOffSmoother.Init(1.0f, 0.2f);
|
|
m_BrakeLinearVolumeSmoother.Init(g_BrakeLinearVolumeSmootherRate / 1000.0f, 0.01f);
|
|
m_WasBrakeHeldLastFrame = false;
|
|
m_WasStationaryLastFrame = true;
|
|
m_StartupRevsVolBoostSmoother.Reset();
|
|
m_ReversingExhaustVolSmoother.Init(1.0f);
|
|
m_StartupRevsVolBoostSmoother.Init(0.01f, 0.005f);
|
|
m_NextDoorTime = 0;
|
|
m_LastTimeStationary = 0;
|
|
m_TimeAtCurrentLOD = 1.0f;
|
|
m_IsIndicatorOn = false;
|
|
m_AreExhaustPopsEnabled = true;
|
|
m_HasPlayedStartupSequence = false;
|
|
m_WasPlayingStartupSound = false;
|
|
m_WaterTurbulenceOutOfWaterTimer = 0.0f;
|
|
m_WaterTurbulenceInWaterTimer = 0.0f;
|
|
m_PrevOffRoadRumbleHash = g_NullSoundHash;
|
|
m_EngineDamageFrequencyRatioFluctuator.Init(0.001f, 0.001f, 0.88f, 0.89f, 1.0f, 1.0f, 0.05f, 0.005f, 1.f);
|
|
m_SportsCarRevsTriggerType = REVS_TYPE_MAX;
|
|
|
|
for(u32 i = 0 ; i < g_NumDamageLayersPerCar; i++)
|
|
{
|
|
m_EngineDamageLayerIndex[i] = -1;
|
|
}
|
|
|
|
for(u32 i = 0; i < NUM_VEH_CWHEELS_MAX; i++)
|
|
{
|
|
m_LastCompressionChange[i] = 0.f;
|
|
m_LastBottomOutTime[i] = 0;
|
|
}
|
|
|
|
m_IsTyreCompletelyDead.Reset();
|
|
m_HasBlippedSinceStopping = false;
|
|
m_ForceThrottleBlip = false;
|
|
m_ThrottleBlipTimer = 0;
|
|
m_FakeOutOfWater = false;
|
|
m_FakeOutOfWaterTimer = 0.0f;
|
|
m_FakeRevsHoldTime = 0.0f;
|
|
m_WasHighFakeRevs = false;
|
|
m_TimeAlarmLastArmed = 0;
|
|
#if GTA_REPLAY
|
|
m_ReplayIsInWater = false;
|
|
m_ReplayVehiclePhysicsInWater = false;
|
|
#endif
|
|
}
|
|
|
|
CarAudioSettings *audCarAudioEntity::GetCarAudioSettings()
|
|
{
|
|
bool isSupportedVehicleType = false;
|
|
|
|
if(m_Vehicle)
|
|
{
|
|
if (m_Vehicle->GetVehicleType() == VEHICLE_TYPE_CAR ||
|
|
m_Vehicle->GetVehicleType() == VEHICLE_TYPE_SUBMARINECAR ||
|
|
m_Vehicle->GetVehicleType() == VEHICLE_TYPE_QUADBIKE ||
|
|
m_Vehicle->GetVehicleType() == VEHICLE_TYPE_BIKE ||
|
|
m_Vehicle->GetVehicleType() == VEHICLE_TYPE_BICYCLE ||
|
|
m_Vehicle->GetVehicleType() == VEHICLE_TYPE_AMPHIBIOUS_QUADBIKE ||
|
|
m_Vehicle->GetVehicleType() == VEHICLE_TYPE_AMPHIBIOUS_AUTOMOBILE)
|
|
{
|
|
isSupportedVehicleType = true;
|
|
}
|
|
|
|
audAssertf(isSupportedVehicleType, "Unsupported car vehicle type - %d", m_Vehicle->GetVehicleType());
|
|
}
|
|
|
|
if(!g_AudioEngine.IsAudioEnabled() || !m_Vehicle || !isSupportedVehicleType)
|
|
{
|
|
#if __BANK
|
|
if(!g_AuditionWheelFire)
|
|
{
|
|
return NULL;
|
|
}
|
|
#else
|
|
return NULL;
|
|
#endif
|
|
}
|
|
|
|
if(m_CarAudioSettings) //If we've already set this don't do it again
|
|
{
|
|
return m_CarAudioSettings;
|
|
}
|
|
|
|
CarAudioSettings *settings = NULL;
|
|
|
|
if(m_ForcedGameObject != 0u)
|
|
{
|
|
settings = audNorthAudioEngine::GetObject<CarAudioSettings>(m_ForcedGameObject);
|
|
m_ForcedGameObject = 0u;
|
|
}
|
|
|
|
if(!settings)
|
|
{
|
|
if(m_Vehicle->GetVehicleModelInfo()->GetAudioNameHash() != 0)
|
|
{
|
|
settings = audNorthAudioEngine::GetObject<CarAudioSettings>(m_Vehicle->GetVehicleModelInfo()->GetAudioNameHash());
|
|
}
|
|
|
|
if(!settings)
|
|
{
|
|
settings = audNorthAudioEngine::GetObject<CarAudioSettings>(GetVehicleModelNameHash());
|
|
}
|
|
}
|
|
|
|
if(CSystem::IsThisThreadId(SYS_THREAD_AUDIO))
|
|
{
|
|
audAssertf(settings != NULL, "Couldn't find car audio settings for %s - this vehicle will probably be silent!", GetVehicleModelName());
|
|
}
|
|
|
|
if( settings )
|
|
{
|
|
m_VehicleEngineSettings = audNorthAudioEngine::GetObject<VehicleEngineAudioSettings>(settings->Engine);
|
|
m_ElectricEngineSettings = audNorthAudioEngine::GetObject<ElectricEngineAudioSettings>(settings->ElectricEngine);
|
|
|
|
// Its valid for a bicycle to not have an engine, so don't force one if there isn't one set in RAVE
|
|
if(!m_VehicleEngineSettings && !m_ElectricEngineSettings && m_Vehicle->GetVehicleType() != VEHICLE_TYPE_BICYCLE)
|
|
{
|
|
if (CSystem::IsThisThreadId(SYS_THREAD_AUDIO))
|
|
naDebugf1("Couldn't find engine audio settings for %s", GetVehicleModelName());
|
|
}
|
|
|
|
GranularEngineAudioSettings* primaryEngine = audNorthAudioEngine::GetObject<GranularEngineAudioSettings>(settings->GranularEngine);
|
|
GranularEngineSet* alternativeEngines = audNorthAudioEngine::GetObject<GranularEngineSet>(settings->AlternativeGranularEngines);
|
|
m_GranularEngineSettings = primaryEngine;
|
|
|
|
if(alternativeEngines && alternativeEngines->numGranularEngines > 0 && (!primaryEngine || audEngineUtil::ResolveProbability(settings->AlternativeGranularEngineProbability)))
|
|
{
|
|
f32 totalWeight = 0.0f;
|
|
|
|
for(u32 loop = 0; loop < alternativeEngines->numGranularEngines; loop++)
|
|
{
|
|
totalWeight += alternativeEngines->GranularEngines[loop].Weight;
|
|
}
|
|
|
|
f32 randomWeight = audEngineUtil::GetRandomNumberInRange(0.f, totalWeight);
|
|
|
|
for(u32 loop = 0; loop < alternativeEngines->numGranularEngines; loop++)
|
|
{
|
|
randomWeight -= alternativeEngines->GranularEngines[loop].Weight;
|
|
|
|
if(randomWeight <= 0.f)
|
|
{
|
|
m_GranularEngineSettings = audNorthAudioEngine::GetObject<GranularEngineAudioSettings>(alternativeEngines->GranularEngines[loop].GranularEngine);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
#if __BANK
|
|
if(g_ForceGranularNPCEngines && (!m_GranularEngineSettings || (!m_IsPlayerVehicle && m_GranularEngineSettings->NPCEngineAccel == g_NullSoundHash)))
|
|
{
|
|
const u32 defaultGranularEngineNames[] = {ATSTRINGHASH("BANSHEE_GRANULAR_ENGINE", 0xCC012EBD), ATSTRINGHASH("PENUMBRA_GRANULAR_ENGINE", 0xE9A310B0), ATSTRINGHASH("SULTAN_GRANULAR_ENGINE", 0xC8FA3AB8), ATSTRINGHASH("CHEETAH_GRANULAR_ENGINE", 0x952D6F23)};
|
|
m_GranularEngineSettings = audNorthAudioEngine::GetObject<GranularEngineAudioSettings>(defaultGranularEngineNames[audEngineUtil::GetRandomNumberInRange(0, NELEM(defaultGranularEngineNames) - 1)]);
|
|
}
|
|
#endif
|
|
|
|
// If we're not running an audio designer build, we must obey the publish flag
|
|
if(!PARAM_audiodesigner.Get())
|
|
{
|
|
if(m_GranularEngineSettings)
|
|
{
|
|
if(AUD_GET_TRISTATE_VALUE(m_GranularEngineSettings->Flags, FLAG_ID_GRANULARENGINEAUDIOSETTINGS_PUBLISH) != AUD_TRISTATE_TRUE)
|
|
{
|
|
m_GranularEngineSettings = NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(settings)
|
|
{
|
|
// Turn off auto-shut-off engines for mission vehicles, just incase it messes with any vehicle recordings etc
|
|
if(!m_Vehicle->PopTypeIsMission())
|
|
{
|
|
m_HasAutoShutOffEngine = audEngineUtil::ResolveProbability(settings->StopStartProb/100.0f);
|
|
}
|
|
|
|
BANK_ONLY(m_HasAutoShutOffEngine |= g_ForceAutoShutoffEngines;)
|
|
|
|
m_HasRandomWheelDamage = GetRandomDamageClass() == RANDOM_DAMAGE_ALWAYS && ENTITY_SEED_PROB(GetVehicle()->GetRandomSeed(), 0.1f);
|
|
m_VehicleModelSoundHash = settings->CarModel;
|
|
m_VehicleMakeSoundHash = settings->CarMake;
|
|
m_VehicleCategorySoundHash = settings->CarCategory;
|
|
m_ScannerVehicleSettingsHash = settings->ScannerVehicleSettings;
|
|
m_SportsCarRevsEnabled = (AUD_GET_TRISTATE_VALUE(settings->Flags, FLAG_ID_CARAUDIOSETTINGS_SPORTSCARREVSENABLED) == AUD_TRISTATE_TRUE);
|
|
|
|
#if NA_RADIO_ENABLED
|
|
m_AmbientRadioDisabled = (AUD_GET_TRISTATE_VALUE(settings->Flags, FLAG_ID_CARAUDIOSETTINGS_DISABLEAMBIENTRADIO) == AUD_TRISTATE_TRUE);
|
|
m_RadioType = (RadioType)settings->RadioType;
|
|
m_RadioGenre = (RadioGenre)settings->RadioGenre;
|
|
m_RadioLeakage = (AmbientRadioLeakage)settings->RadioLeakage;
|
|
|
|
// only 30% of cars marked up as bassy loud get bassy loud
|
|
if(m_RadioLeakage == LEAKAGE_BASSY_LOUD)
|
|
{
|
|
if(ENTITY_SEED_PROB(m_Vehicle->GetRandomSeed(), 0.7f))
|
|
{
|
|
m_RadioLeakage = LEAKAGE_BASSY_MEDIUM;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
m_GpsType = settings->GpsType;
|
|
m_GpsVoice = settings->GpsVoice;
|
|
|
|
if(m_VehicleEngineSettings)
|
|
{
|
|
m_Vehicle->m_nVehicleFlags.bHasCoolingFan = (m_VehicleEngineSettings->CoolingFan!=g_NullSoundHash);
|
|
}
|
|
m_VehSirenSounds.Init(settings->SirenSounds);
|
|
|
|
// HL - Hacky fix for new CG Heists pack vehicles, due to smoothing not
|
|
// being configurable on a per-vehicle basis
|
|
switch(GetVehicleModelNameHash())
|
|
{
|
|
case 0x825A9F4C: //GUARDIAN
|
|
case 0x83051506: //TECHNICAL
|
|
case 0x50D4D19F: //TECHNICAL3
|
|
m_AdditionalRevsSmoothing = 1.0f;
|
|
break;
|
|
case 0x9114EADA: //INSURGENT
|
|
case 0x7B7E56F0: //INSURGENT2
|
|
case 0x8D4B7A8A: //INSURGENT3
|
|
m_AdditionalRevsSmoothing = 2.0f;
|
|
break;
|
|
case 0x11AA0E14: //GBURRITO2
|
|
m_AdditionalRevsSmoothing = 6.0f;
|
|
break;
|
|
default:
|
|
m_AdditionalRevsSmoothing = 0.0f;
|
|
break;
|
|
}
|
|
// End hacky fix
|
|
}
|
|
|
|
return settings;
|
|
}
|
|
|
|
bool audCarAudioEntity::AreExhaustPopsEnabled() const
|
|
{
|
|
return m_AreExhaustPopsEnabled BANK_ONLY(&& !g_EngineVolumeCaptureActive);
|
|
}
|
|
|
|
audMetadataRef audCarAudioEntity::GetClatterSound() const
|
|
{
|
|
if(!m_Vehicle->InheritsFromBike() && !m_Vehicle->InheritsFromQuadBike() && !m_Vehicle->InheritsFromAmphibiousQuadBike())
|
|
{
|
|
if(m_CarAudioSettings)
|
|
{
|
|
ClatterType clatterType = (ClatterType)m_CarAudioSettings->ClatterType;
|
|
|
|
if(clatterType == AUD_CLATTER_NONE && m_IsFocusVehicle && !IsToyCar() && !IsGoKart())
|
|
{
|
|
clatterType = AUD_CLATTER_DETAIL;
|
|
}
|
|
|
|
return GetClatterSoundFromType(clatterType);
|
|
}
|
|
}
|
|
|
|
return audVehicleAudioEntity::GetClatterSound();
|
|
}
|
|
|
|
audMetadataRef audCarAudioEntity::GetChassisStressSound() const
|
|
{
|
|
CVehicleVariationInstance& variation = m_Vehicle->GetVariationInstance();
|
|
if(variation.GetMods()[VMT_HORN] != INVALID_MOD)
|
|
{
|
|
const u32 modKitHash = variation.GetKit()->GetStatMods()[variation.GetMods()[VMT_HORN]].GetModifier();
|
|
|
|
// Certain horns enable sleigh bell 'clatter' sounds
|
|
if(modKitHash == ATSTRINGHASH("XM15_HORN_01", 0x354642A) || modKitHash == ATSTRINGHASH("XM15_HORN_02", 0x17D78D30) || modKitHash == ATSTRINGHASH("XM15_HORN_03", 0x216DA05C) BANK_ONLY(||g_ForceSleighBellsOn))
|
|
{
|
|
return g_AudioEngine.GetSoundManager().GetFactory().GetMetadataManager().GetObjectMetadataRefFromHash(ATSTRINGHASH("sleighbells_chassis_stress_detail", 0x68C7D7F0));
|
|
}
|
|
}
|
|
|
|
if(!m_Vehicle->InheritsFromBike() && !m_Vehicle->InheritsFromQuadBike() && !m_Vehicle->InheritsFromAmphibiousQuadBike())
|
|
{
|
|
if(m_CarAudioSettings)
|
|
{
|
|
ClatterType clatterType = (ClatterType)m_CarAudioSettings->ClatterType;
|
|
|
|
if(clatterType == AUD_CLATTER_NONE && m_IsFocusVehicle)
|
|
{
|
|
clatterType = AUD_CLATTER_DETAIL;
|
|
}
|
|
|
|
return GetChassisStressSoundFromType(clatterType);
|
|
}
|
|
}
|
|
|
|
return g_NullSoundRef;
|
|
}
|
|
|
|
f32 audCarAudioEntity::GetChassisStressSensitivityScalar() const
|
|
{
|
|
if(m_CarAudioSettings)
|
|
{
|
|
return m_CarAudioSettings->ChassisStressSensitivityScalar;
|
|
}
|
|
|
|
return 1.0f;
|
|
}
|
|
|
|
f32 audCarAudioEntity::GetClatterSensitivityScalar() const
|
|
{
|
|
if(m_CarAudioSettings)
|
|
{
|
|
return m_CarAudioSettings->ClatterSensitivityScalar;
|
|
}
|
|
|
|
return 1.0f;
|
|
}
|
|
|
|
f32 audCarAudioEntity::GetClatterVolumeBoost() const
|
|
{
|
|
if(m_CarAudioSettings)
|
|
{
|
|
return m_CarAudioSettings->ClatterVolumeBoost * 0.01f;
|
|
}
|
|
|
|
return 0.0f;
|
|
}
|
|
|
|
f32 audCarAudioEntity::GetChassisStressVolumeBoost() const
|
|
{
|
|
if(m_CarAudioSettings)
|
|
{
|
|
return m_CarAudioSettings->ChassisStressVolumeBoost * 0.01f;
|
|
}
|
|
|
|
return 0.0f;
|
|
}
|
|
|
|
void audCarAudioEntity::SetupVolumeCones()
|
|
{
|
|
Vec3V engineConeDir = Vec3V(0.f,1.0f,0.f);
|
|
Vec3V exhaustConeDir = Vec3V(0.f,-1.0f,0.f);
|
|
|
|
bool useExhaustCone = true;
|
|
const Vec3V exPos = m_Vehicle->TransformIntoWorldSpace(m_ExhaustOffsetPos);
|
|
const Vec3V vVehiclePosition = m_Vehicle->GetTransform().GetPosition();
|
|
Vec3V ex2centre = vVehiclePosition - exPos;
|
|
ScalarV dp = Dot(ex2centre, m_Vehicle->GetTransform().GetB());
|
|
|
|
if(IsTrue(IsLessThanOrEqual(dp, ScalarV(V_ZERO))))
|
|
{
|
|
useExhaustCone = false;
|
|
}
|
|
|
|
Vec3V temp = vVehiclePosition - m_Vehicle->TransformIntoWorldSpace(m_EngineOffsetPos);
|
|
dp = Dot(temp, m_Vehicle->GetTransform().GetB());
|
|
|
|
if(IsTrue(IsGreaterThan(dp, ScalarV(V_ZERO))))
|
|
{
|
|
engineConeDir = exhaustConeDir;
|
|
}
|
|
|
|
if(sm_ShouldFlipPlayerCones)
|
|
{
|
|
engineConeDir *= Vec3V(0.0f,-1.f,0.0f);
|
|
exhaustConeDir *= Vec3V(0.0f,-1.f,0.0f);
|
|
}
|
|
|
|
if(m_vehicleEngine.IsGranularEngineActive())
|
|
{
|
|
m_EngineVolumeCone.Init(engineConeDir, m_GranularEngineSettings->EngineMaxConeAttenuation/100.f, 60.f,165.f);
|
|
m_ExhaustVolumeCone.Init(exhaustConeDir, (useExhaustCone?m_GranularEngineSettings->ExhaustMaxConeAttenuation/100.f:0.f), 45.f, 160.f);
|
|
m_HasInitialisedVolumeCones = true;
|
|
}
|
|
else if(m_VehicleEngineSettings)
|
|
{
|
|
m_EngineVolumeCone.Init(engineConeDir, m_VehicleEngineSettings->MaxConeAttenuation/100.f, 60.f,165.f);
|
|
m_ExhaustVolumeCone.Init(exhaustConeDir, (useExhaustCone?m_VehicleEngineSettings->MaxConeAttenuation/100.f:0.f), 45.f, 160.f);
|
|
m_HasInitialisedVolumeCones = true;
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// Get the idle hull slap volume
|
|
// ----------------------------------------------------------------
|
|
f32 audCarAudioEntity::GetIdleHullSlapVolumeLinear(f32 speed) const
|
|
{
|
|
if(m_Vehicle && (m_Vehicle->InheritsFromAmphibiousQuadBike() || m_Vehicle->InheritsFromAmphibiousAutomobile()))
|
|
{
|
|
return m_VehicleSpeedToHullSlapVol.CalculateValue(speed);
|
|
}
|
|
else
|
|
{
|
|
return audVehicleAudioEntity::GetIdleHullSlapVolumeLinear(speed);
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// audCarAudioEntity GetIdleHullSlapSound
|
|
// ----------------------------------------------------------------
|
|
u32 audCarAudioEntity::GetIdleHullSlapSound() const
|
|
{
|
|
if(m_AmphibiousBoatSettings)
|
|
{
|
|
return m_AmphibiousBoatSettings->IdleHullSlapLoop;
|
|
}
|
|
|
|
return audVehicleAudioEntity::GetIdleHullSlapSound();
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// UpdateAmphibiousBoatMode
|
|
// ----------------------------------------------------------------
|
|
void audCarAudioEntity::UpdateAmphibiousBoatMode(audVehicleVariables* vehicleVariables)
|
|
{
|
|
if(m_Vehicle->m_nVehicleFlags.bEngineOn && m_AmphibiousBoatSettings && m_IsInAmphibiousBoatMode)
|
|
{
|
|
Vec3V pos;
|
|
const s32 engineBoneId = m_Vehicle->GetVehicleModelInfo()->GetBoneIndex(VEH_ENGINE);
|
|
|
|
// Using separate water timers for turbulence sounds - the default timers only monitor the big bow VFX
|
|
// at the front of the vehicle, so can report that the boat is not in water even when water VFX is playing visually.
|
|
bool isAnyWaterVFXActive = IsAnyWaterVFXActive();
|
|
|
|
if(isAnyWaterVFXActive)
|
|
{
|
|
m_WaterTurbulenceInWaterTimer += fwTimer::GetTimeStep();
|
|
m_WaterTurbulenceOutOfWaterTimer = 0.f;
|
|
}
|
|
else
|
|
{
|
|
m_WaterTurbulenceOutOfWaterTimer += fwTimer::GetTimeStep();
|
|
m_WaterTurbulenceInWaterTimer = 0.f;
|
|
}
|
|
|
|
f32 volLin = m_WaterTurbulenceVolumeCurve.CalculateValue((vehicleVariables->revs - 0.2f) * 1.25f);
|
|
volLin *= isAnyWaterVFXActive? Clamp(m_WaterTurbulenceInWaterTimer * 3.0f, 0.0f, 1.0f) : 1.0f - Clamp(m_WaterTurbulenceOutOfWaterTimer * 3.0f, 0.0f, 1.0f);
|
|
|
|
// Submersibles use the centre of the sub as the turbulence sound position
|
|
if(volLin > g_SilenceVolumeLin)
|
|
{
|
|
if(engineBoneId !=-1 )
|
|
{
|
|
pos = m_Vehicle->TransformIntoWorldSpace(m_ExhaustOffsetPos);
|
|
}
|
|
else
|
|
{
|
|
pos = m_Vehicle->GetTransform().GetPosition();
|
|
}
|
|
|
|
if(!m_WaterTurbulenceSound)
|
|
{
|
|
audSoundInitParams initParams;
|
|
initParams.AttackTime = m_WasEngineOnLastFrame? sm_LodSwitchFadeTime : 300;
|
|
initParams.EnvironmentGroup = m_Vehicle->GetAudioEnvironmentGroup();
|
|
CreateAndPlaySound_Persistent(m_AmphibiousBoatSettings->WaterTurbulance, &m_WaterTurbulenceSound, &initParams);
|
|
}
|
|
|
|
if(m_WaterTurbulenceSound)
|
|
{
|
|
f32 vol = audDriverUtil::ComputeDbVolumeFromLinear(volLin);
|
|
f32 pitch = m_WaterTurbulencePitchCurve.CalculateValue(vehicleVariables->revs);
|
|
|
|
m_WaterTurbulenceSound->SetRequestedPitch(static_cast<s32>(pitch));
|
|
m_WaterTurbulenceSound->SetRequestedVolume(vol BANK_ONLY(+ g_WaterTurbulenceVolumeTrim));
|
|
m_WaterTurbulenceSound->SetRequestedPosition(pos);
|
|
}
|
|
}
|
|
else if(m_WaterTurbulenceSound)
|
|
{
|
|
m_WaterTurbulenceSound->StopAndForget();
|
|
}
|
|
}
|
|
else if(m_WaterTurbulenceSound)
|
|
{
|
|
m_WaterTurbulenceSound->SetReleaseTime(800);
|
|
m_WaterTurbulenceSound->StopAndForget();
|
|
}
|
|
|
|
f32 boatSprayAngle = 0.0f;
|
|
f32 speedFactor = 0.0f;
|
|
f32 inWaterFactor = 0.0f;
|
|
|
|
speedFactor = CalculateWaterSpeedFactor();
|
|
inWaterFactor = !m_Vehicle->GetIsInWater()?0.f:1.f;
|
|
|
|
if(m_IsFocusVehicle && m_AmphibiousBoatSettings && m_IsInAmphibiousBoatMode)
|
|
{
|
|
const f32 bankVol = m_BankSpraySmoother.CalculateValue(inWaterFactor, fwTimer::GetTimeInMilliseconds());
|
|
|
|
if(bankVol > g_SilenceVolumeLin)
|
|
{
|
|
if(!m_BankSpray)
|
|
{
|
|
audSoundInitParams initParams;
|
|
initParams.UpdateEntity = true;
|
|
initParams.EnvironmentGroup = m_Vehicle->GetAudioEnvironmentGroup();
|
|
CreateSound_PersistentReference(m_AmphibiousBoatSettings->BankSpraySound, &m_BankSpray, &initParams);
|
|
|
|
if(m_BankSpray)
|
|
{
|
|
m_BankSpray->PrepareAndPlay();
|
|
}
|
|
}
|
|
|
|
if(m_BankSpray)
|
|
{
|
|
m_BankSpray->SetRequestedVolume(audDriverUtil::ComputeDbVolumeFromLinear(bankVol) BANK_ONLY(+ g_BankSprayVolumeTrim));
|
|
Vector3 boatRight = VEC3V_TO_VECTOR3(m_Vehicle->GetTransform().GetA());
|
|
Vector3 boatForward = VEC3V_TO_VECTOR3(m_Vehicle->GetTransform().GetB());
|
|
boatSprayAngle = DotProduct(boatRight, g_UnitUp);
|
|
m_BankSpray->FindAndSetVariableValue(ATSTRINGHASH("angle", 0xF3805B5), Abs(boatSprayAngle));
|
|
boatRight.SetZ(0.0f);
|
|
boatForward.SetZ(0.0f);
|
|
|
|
// Pan the sound left and right as the angle changes
|
|
m_BankSpray->SetRequestedPosition(VEC3V_TO_VECTOR3(m_Vehicle->GetTransform().GetPosition()) + (boatForward * g_BankSprayForwardDistanceScalar * ((vehicleVariables->isInFirstPersonCam || vehicleVariables->isInHoodMountedCam) ? 0.0f : 1.0f)) + (boatRight * g_BankSprayPanDistanceScalar * Clamp(boatSprayAngle * 2, -1.0f, 1.0f)));
|
|
}
|
|
}
|
|
else if(m_BankSpray)
|
|
{
|
|
m_BankSpray->StopAndForget();
|
|
}
|
|
}
|
|
else if(m_BankSpray)
|
|
{
|
|
m_BankSpray->StopAndForget();
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// audCarAudioEntity GetLeftWaterSound
|
|
// ----------------------------------------------------------------
|
|
u32 audCarAudioEntity::GetLeftWaterSound() const
|
|
{
|
|
if(m_AmphibiousBoatSettings)
|
|
{
|
|
return m_AmphibiousBoatSettings->LeftWaterSound;
|
|
}
|
|
|
|
return audVehicleAudioEntity::GetLeftWaterSound();
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// audCarAudioEntity GetWaveHitSound
|
|
// ----------------------------------------------------------------
|
|
u32 audCarAudioEntity::GetWaveHitSound() const
|
|
{
|
|
if(m_AmphibiousBoatSettings)
|
|
{
|
|
return m_AmphibiousBoatSettings->WaveHitSound;
|
|
}
|
|
|
|
return audVehicleAudioEntity::GetWaveHitSound();
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------
|
|
// audCarAudioEntity GetWaveHitBigSound
|
|
// ----------------------------------------------------------------
|
|
u32 audCarAudioEntity::GetWaveHitBigSound() const
|
|
{
|
|
if(m_AmphibiousBoatSettings)
|
|
{
|
|
return m_AmphibiousBoatSettings->WaveHitBigAirSound;
|
|
}
|
|
|
|
return audVehicleAudioEntity::GetWaveHitBigSound();
|
|
}
|
|
|
|
void audCarAudioEntity::UpdateParkingBeep(float distance)
|
|
{
|
|
if(HasEntityVariableBlock())
|
|
{
|
|
SetEntityVariable(ATSTRINGHASH("distance", 0xd6ff9582), distance);
|
|
}
|
|
|
|
if(!m_ParkingBeep)
|
|
{
|
|
if(!GetCarAudioSettings())
|
|
{
|
|
return;
|
|
}
|
|
|
|
audSoundInitParams initParams;
|
|
initParams.UpdateEntity = true;
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
initParams.u32ClientVar = AUD_VEHICLE_SOUND_HORN;
|
|
|
|
const Vector3 pos = VEC3V_TO_VECTOR3(m_Vehicle->TransformIntoWorldSpace(m_HornOffsetPos));
|
|
initParams.Position = pos;
|
|
|
|
CreateSound_PersistentReference(GetCarAudioSettings()->ParkingTone, &m_ParkingBeep, &initParams);
|
|
|
|
if(m_ParkingBeep)
|
|
{
|
|
m_ParkingBeep->PrepareAndPlay();
|
|
}
|
|
|
|
}
|
|
}
|
|
void audCarAudioEntity::StopParkingBeepSound()
|
|
{
|
|
if(m_ParkingBeep){
|
|
if(!m_Vehicle->ContainsLocalPlayer())
|
|
{
|
|
//// if we're getting out of the car, ramp it down in volume
|
|
//// if we're totally out of the car, stop playing it, so we don't ever ramp it up again if you get in another one.
|
|
//f32 inCarRatio = 0.0f;
|
|
//audNorthAudioEngine::GetGtaEnvironment()->IsPlayerInVehicle(&inCarRatio);
|
|
//if (inCarRatio==0.0f)
|
|
//{
|
|
// StopAndForgetSounds(m_ParkingBeep);
|
|
// return;
|
|
//}
|
|
//f32 dBVolume = audDriverUtil::ComputeDbVolumeFromLinear(inCarRatio);
|
|
//m_ParkingBeep->SetRequestedVolume(dBVolume);
|
|
m_ParkingBeep->SetReleaseTime(500);
|
|
}
|
|
StopAndForgetSounds(m_ParkingBeep);
|
|
}
|
|
}
|
|
|
|
bool audCarAudioEntity::CanBeDescribedAsACar()
|
|
{
|
|
// Only time it can is if it's a TYPE_CAR, and doesn't have the IAMNOTACAR flag set to true
|
|
if (m_CarAudioSettings)
|
|
{
|
|
if (m_Vehicle && (m_Vehicle->GetVehicleType()==VEHICLE_TYPE_CAR || m_Vehicle->GetVehicleType() == VEHICLE_TYPE_SUBMARINECAR) &&
|
|
!(AUD_GET_TRISTATE_VALUE(m_CarAudioSettings->Flags, FLAG_ID_CARAUDIOSETTINGS_IAMNOTACAR) == AUD_TRISTATE_TRUE))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void audCarAudioEntity::EngineStarted()
|
|
{
|
|
m_EngineStartTime = fwTimer::GetTimeInMilliseconds();
|
|
m_RevsSmoother.CalculateValue(CTransmission::ms_fIdleRevs,m_EngineStartTime);// init revs to idle
|
|
|
|
m_EngineEffectWetSmoother.Reset();
|
|
m_EngineEffectWetSmoother.CalculateValue(0.0f,fwTimer::GetTimeStep());
|
|
}
|
|
|
|
void audCarAudioEntity::SetBoostActive(bool active)
|
|
{
|
|
if(active)
|
|
{
|
|
if(!m_NOSBoostLoop)
|
|
{
|
|
audSoundInitParams initParams;
|
|
initParams.UpdateEntity = true;
|
|
initParams.u32ClientVar = AUD_VEHICLE_SOUND_ENGINE;
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
|
|
audSoundSet newBoostSoundSet;
|
|
|
|
if (m_Vehicle->HasNitrousBoost() && NetworkInterface::IsGameInProgress() && newBoostSoundSet.Init(m_IsPlayerVehicle ? ATSTRINGHASH("DLC_AWXM2018_Mod_Vehicle_Player_Sounds", 0x1D430286) : ATSTRINGHASH("DLC_AWXM2018_Mod_Vehicle_NPC_Sounds", 0x96866E58)))
|
|
{
|
|
CreateAndPlaySound_Persistent(newBoostSoundSet.Find(ATSTRINGHASH("boost_activate", 0xF6D2A804)), &m_NOSBoostLoop, &initParams);
|
|
}
|
|
else
|
|
{
|
|
CreateAndPlaySound(sm_ExtrasSoundSet.Find(ATSTRINGHASH("CarNOSBoostStart", 0xDD67FE00)), &initParams);
|
|
CreateAndPlaySound_Persistent(sm_ExtrasSoundSet.Find(ATSTRINGHASH("CarNOSBoostDuration", 0x150E6407)), &m_NOSBoostLoop, &initParams);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(m_NOSBoostLoop)
|
|
{
|
|
m_NOSBoostLoop->StopAndForget(true);
|
|
}
|
|
}
|
|
#if GTA_REPLAY
|
|
if(CReplayMgr::ShouldRecord())
|
|
{
|
|
CReplayMgr::RecordFx<CPacketSoundNitrousActive>(CPacketSoundNitrousActive(active), m_Vehicle);
|
|
}
|
|
#endif
|
|
|
|
}
|
|
|
|
void audCarAudioEntity::TriggerRoofStuckSound()
|
|
{
|
|
if(IsDisabled())
|
|
{
|
|
return;
|
|
}
|
|
|
|
if(m_CarAudioSettings && m_Vehicle)
|
|
{
|
|
audSoundInitParams initParams;
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
initParams.TrackEntityPosition = true;
|
|
CreateAndPlaySound(m_CarAudioSettings->RoofStuckSound, &initParams);
|
|
}
|
|
}
|
|
|
|
bool audCarAudioEntity::InitVehicleSpecific()
|
|
{
|
|
if(m_Vehicle->GetVehicleType() == VEHICLE_TYPE_BIKE)
|
|
{
|
|
m_EngineDamageLayerIndex[0] = 5;
|
|
m_EngineDamageLayerIndex[1] = -1;
|
|
m_EngineDamageLayerIndex[2] = 2;
|
|
}
|
|
else
|
|
{
|
|
// pick two light damage layers
|
|
m_EngineDamageLayerIndex[0] = g_LightDamageLayerIndices[audEngineUtil::GetRandomNumberInRange(0, g_NumLightDamageLayers-1)];
|
|
do
|
|
{
|
|
m_EngineDamageLayerIndex[1] = g_LightDamageLayerIndices[audEngineUtil::GetRandomNumberInRange(0, g_NumLightDamageLayers-1)];
|
|
}while(m_EngineDamageLayerIndex[0] != m_EngineDamageLayerIndex[1]);
|
|
//and one heavy damage layer
|
|
m_EngineDamageLayerIndex[2] = g_HeavyDamageLayerIndices[audEngineUtil::GetRandomNumberInRange(0,g_NumHeavyDamageLayers-1)];
|
|
}
|
|
|
|
m_CarAudioSettings = GetCarAudioSettings();
|
|
|
|
if(m_CarAudioSettings)
|
|
{
|
|
m_vehicleEngine.Init(this);
|
|
SetEnvironmentGroupSettings(true, audNorthAudioEngine::GetOcclusionManager()->GetMaxOcclusionFullPathDepth());
|
|
SetupVolumeCones();
|
|
|
|
const u32 modelNameHash = GetVehicleModelNameHash();
|
|
|
|
if(modelNameHash == ATSTRINGHASH("RUINER2", 0x381E10BD) ||
|
|
modelNameHash == ATSTRINGHASH("OPPRESSOR", 0x34B82784) ||
|
|
modelNameHash == ATSTRINGHASH("OPPRESSOR2", 0x7B54A9D3) ||
|
|
modelNameHash == ATSTRINGHASH("VIGILANTE", 0xB5EF4C33) ||
|
|
modelNameHash == ATSTRINGHASH("STROMBERG", 0x34DBA661) ||
|
|
modelNameHash == ATSTRINGHASH("TOREADOR", 0x56C8A5EF) ||
|
|
modelNameHash == ATSTRINGHASH("DELUXO", 0x586765FB) ||
|
|
modelNameHash == ATSTRINGHASH("TERBYTE", 0x897AFC65) ||
|
|
modelNameHash == ATSTRINGHASH("SCRAMJET", 0xD9F0503D) ||
|
|
modelNameHash == ATSTRINGHASH("CHERNOBOG", 0xD6BC7523) ||
|
|
modelNameHash == ATSTRINGHASH("TOREADOR", 0x56C8A5EF))
|
|
{
|
|
m_HasMissileLockWarningSystem = true;
|
|
}
|
|
|
|
if(m_Vehicle->InheritsFromAmphibiousAutomobile() || m_Vehicle->InheritsFromAmphibiousQuadBike() || m_Vehicle->InheritsFromSubmarineCar())
|
|
{
|
|
m_BankSpraySmoother.Init(0.0015f, 0.002f);
|
|
BoatAudioSettings* boatAudioSettings = NULL;
|
|
|
|
if(modelNameHash == ATSTRINGHASH("TECHNICAL2", 0x4662BCBB))
|
|
{
|
|
boatAudioSettings = audNorthAudioEngine::GetObject<BoatAudioSettings>(ATSTRINGHASH("TECHNICAL2_BOAT", 0x8EFD0604));
|
|
}
|
|
else if(modelNameHash == ATSTRINGHASH("BLAZER5", 0xA1355F67))
|
|
{
|
|
boatAudioSettings = audNorthAudioEngine::GetObject<BoatAudioSettings>(ATSTRINGHASH("BLAZER5_BOAT", 0xFF2659BD));
|
|
}
|
|
else if(modelNameHash == ATSTRINGHASH("APC", 0x2189D250))
|
|
{
|
|
boatAudioSettings = audNorthAudioEngine::GetObject<BoatAudioSettings>(ATSTRINGHASH("APC_BOAT", 0xF81A98FE));
|
|
}
|
|
else if(modelNameHash == ATSTRINGHASH("STROMBERG", 0x34DBA661))
|
|
{
|
|
boatAudioSettings = audNorthAudioEngine::GetObject<BoatAudioSettings>(ATSTRINGHASH("STROMBERG_SUBMERSIBLE", 0x6E78C824));
|
|
}
|
|
else if (modelNameHash == ATSTRINGHASH("TOREADOR", 0x56C8A5EF))
|
|
{
|
|
boatAudioSettings = audNorthAudioEngine::GetObject<BoatAudioSettings>(ATSTRINGHASH("TOREADOR_SUBMERSIBLE", 0xE0C5A1B0));
|
|
}
|
|
else if (modelNameHash == ATSTRINGHASH("ZHABA", 0x4C8DBA51))
|
|
{
|
|
boatAudioSettings = audNorthAudioEngine::GetObject<BoatAudioSettings>(ATSTRINGHASH("ZHABA_BOAT", 0x15924D7D));
|
|
}
|
|
else if(modelNameHash == ATSTRINGHASH("TOREADOR", 0x56C8A5EF))
|
|
{
|
|
boatAudioSettings = audNorthAudioEngine::GetObject<BoatAudioSettings>(ATSTRINGHASH("STROMBERG_SUBMERSIBLE", 0x6E78C824));
|
|
}
|
|
else
|
|
{
|
|
audAssertf(false, "Unsupported amphibious vehicle %s!", m_Vehicle->GetVehicleModelInfo()->GetModelName());
|
|
}
|
|
|
|
if(boatAudioSettings)
|
|
{
|
|
m_AmphibiousBoatSettings = boatAudioSettings;
|
|
m_WaterTurbulenceVolumeCurve.Init(boatAudioSettings->WaterTurbulanceVol);
|
|
m_VehicleSpeedToHullSlapVol.Init(boatAudioSettings->IdleHullSlapSpeedToVol);
|
|
m_WaterTurbulencePitchCurve.Init(boatAudioSettings->WaterTurbulancePitch);
|
|
|
|
if(AUD_GET_TRISTATE_VALUE(boatAudioSettings->Flags, FLAG_ID_BOATAUDIOSETTINGS_ISSUBMARINE) == AUD_TRISTATE_TRUE)
|
|
{
|
|
InitSubmersible(boatAudioSettings);
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
#if __BANK
|
|
void audCarAudioEntity::UpdateDebug(audVehicleVariables* state)
|
|
{
|
|
if(g_TestForceGameObject && m_IsPlayerVehicle)
|
|
{
|
|
g_TestForceGameObject = false;
|
|
ForceUseGameObject(atHashString(g_TestForceGameObjectName));
|
|
}
|
|
|
|
if(g_SimulatePlayerEnteringVehicle && m_IsPlayerVehicle)
|
|
{
|
|
OnFocusVehicleChanged();
|
|
g_SimulatePlayerEnteringVehicle = false;
|
|
}
|
|
|
|
if(g_RenderGranularNPCEngines)
|
|
{
|
|
if(IsReal())
|
|
{
|
|
Color32 colour;
|
|
|
|
if(m_vehicleEngine.IsGranularEngineActive())
|
|
{
|
|
colour = Color32(0,255,0,128);
|
|
}
|
|
else
|
|
{
|
|
colour = Color32(255,0,0,128);
|
|
}
|
|
|
|
grcDebugDraw::Sphere(VEC3V_TO_VECTOR3(m_Vehicle->GetTransform().GetPosition()), 3.f, colour);
|
|
}
|
|
}
|
|
|
|
if(g_BlipPlayerThrottle && m_IsPlayerVehicle)
|
|
{
|
|
BlipThrottle();
|
|
g_BlipPlayerThrottle = false;
|
|
}
|
|
|
|
if(g_RenderVehicleSlots)
|
|
{
|
|
if(m_EngineWaveSlot)
|
|
{
|
|
if(m_EngineWaveSlot->waveSlot->GetLoadedBankId() < AUD_INVALID_BANK_ID)
|
|
{
|
|
char tempString[32];
|
|
sprintf(tempString, "Throttle:%.02f Revs:%.02f", state->throttle, state->revs );
|
|
grcDebugDraw::Text(VEC3V_TO_VECTOR3(m_Vehicle->GetTransform().GetPosition()), Color32(255,255,255), tempString);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(g_DebugSpecialFlightMode)
|
|
{
|
|
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();
|
|
|
|
f32 xCoord = 0.15f;
|
|
f32 yCoord = 0.15f;
|
|
|
|
char tempString[128];
|
|
formatf(tempString, "throttle: %f", state->throttle);
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
formatf(tempString, "throttleInput: %f", state->throttleInput);
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
formatf(tempString, "rollAngle: %f", rollAngle);
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
formatf(tempString, "pitchAngle: %f", pitchAngle);
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
formatf(tempString, "yawAngle: %f", yawAngle);
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
formatf(tempString, "angularVelocity: %f", angularVelocity);
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
}
|
|
|
|
if(g_RenderTimeSlicedVehicles)
|
|
{
|
|
if(m_Vehicle->GetVehicleAiLod().IsLodFlagSet(CVehicleAILod::AL_LodTimeslicing))
|
|
{
|
|
grcDebugDraw::Sphere(VEC3V_TO_VECTOR3(m_Vehicle->GetTransform().GetPosition()), 3.f, Color32(0,255,0,128));
|
|
}
|
|
}
|
|
|
|
if(g_DisplayDamageDebug)
|
|
{
|
|
if(m_IsPlayerVehicle)
|
|
{
|
|
f32 xCoord = 0.15f;
|
|
f32 yCoord = 0.15f;
|
|
|
|
char tempString[128];
|
|
formatf(tempString, "Revs: %f", state->revs);
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
formatf(tempString, "Rev Ratio: %f", (state->revs - 0.2f) * 1.25f);
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
formatf(tempString, "Engine Damage Factor: %f", state->engineDamageFactor);
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
formatf(tempString, "Body Damage Factor: %f", ComputeEffectiveBodyDamageFactor());
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
for(s32 i = 0; i < m_Vehicle->GetNumWheels(); i++)
|
|
{
|
|
CWheel *wheel = m_Vehicle->GetWheel(i);
|
|
formatf(tempString, "Wheel %d friction damage: %f", i, g_ForceWheelDamage? 1.0f : wheel->GetFrictionDamage());
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
}
|
|
|
|
f32 wheelScrapeTurnVolume = m_DamageTyreScrapeTurnSound != NULL? audDriverUtil::ComputeLinearVolumeFromDb(m_DamageTyreScrapeTurnSound->GetRequestedVolume()) : 0.0f;
|
|
formatf(tempString, "Wheel Scrape Turn Volume: %f", wheelScrapeTurnVolume);
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
f32 wheelScrapeVolume = m_DamageTyreScrapeSound != NULL? audDriverUtil::ComputeLinearVolumeFromDb(m_DamageTyreScrapeSound->GetRequestedVolume()) : 0.0f;
|
|
formatf(tempString, "Wheel Scrape Volume: %f", wheelScrapeVolume);
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
}
|
|
}
|
|
|
|
if(g_DebugCarPasses && m_IsPlayerVehicle)
|
|
{
|
|
f32 xCoord = 0.15f;
|
|
f32 yCoord = 0.15f;
|
|
char tempString[128];
|
|
|
|
if(g_AudioEngine.GetSoundManager().GetVariableAddress(ATSTRINGHASH("Game.Player.Speed", 0x8CE50515)))
|
|
{
|
|
formatf(tempString, "Player Speed: %.02f", *g_AudioEngine.GetSoundManager().GetVariableAddress(ATSTRINGHASH("Game.Player.Speed", 0x8CE50515)));
|
|
grcDebugDraw::Text(Vector2(0.25f, 0.075f), Color32(0,0,255), tempString );
|
|
}
|
|
|
|
for(u32 loop = 0; loop < sm_CarPassHistory.GetCount(); loop++)
|
|
{
|
|
formatf(tempString, "Vehicle: %s", sm_CarPassHistory[loop].vehicleName);
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
formatf(tempString, "Bounding Volume: %.02f", sm_CarPassHistory[loop].boundingVolume);
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
formatf(tempString, "Relative Speed: %.02f", sm_CarPassHistory[loop].relativeSpeed);
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
formatf(tempString, "Trigger Distance: %.02f", sm_CarPassHistory[loop].triggerDistance);
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.04f;
|
|
}
|
|
}
|
|
|
|
if((!g_VehicleAudioAllowEntityFocus && IsPlayerVehicle()) || (g_VehicleAudioAllowEntityFocus && GetVehicle() == CDebugScene::FocusEntities_Get(0)))
|
|
{
|
|
if(g_NonGranularDebugRenderingEnabled || g_EngineVolumeCaptureActive)
|
|
{
|
|
f32 xCoord = 80.0f/1280.0f;
|
|
f32 yCoord = 50.0f/720.0f;
|
|
f32 wavRenderWidth = 1100.0f/1280.0f;
|
|
f32 wavRenderHeight = 50.0f/720.0f;
|
|
|
|
Color32 bgColour = Color32(100,100,100,200);
|
|
Vector2 startPos = Vector2(xCoord, yCoord);
|
|
Vector2 endPos = Vector2(xCoord + wavRenderWidth, yCoord + wavRenderHeight);
|
|
grcDebugDraw::RectAxisAligned(startPos, endPos, bgColour, true);
|
|
|
|
// Draw the current X playback point
|
|
Vector2 v0,v1;
|
|
v0.x = v1.x = xCoord + (m_RevsSmoother.GetLastValue() * wavRenderWidth);
|
|
v0.y = yCoord;
|
|
v1.y = yCoord + wavRenderHeight;
|
|
grcDebugDraw::Line(v0, v1, Color_black, Color_black);
|
|
}
|
|
|
|
if(g_GranularDebugRenderingEnabled || g_NonGranularDebugRenderingEnabled)
|
|
{
|
|
char tempString[128];
|
|
f32 xCoord = 0.7f;
|
|
f32 yCoord = 0.55f;
|
|
|
|
formatf(tempString, "Gear: %d/%d", GetVehicle()->m_Transmission.GetGear(), GetVehicle()->m_Transmission.GetNumGears());
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
formatf(tempString, "Rev Ratio: %f", GetVehicle()->m_Transmission.GetRevRatio());
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
formatf(tempString, "Throttle: %f", GetVehicle()->m_Transmission.GetThrottle());
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
formatf(tempString, "Speed: %f", GetCachedVelocity().Mag());
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
formatf(tempString, "Fwd Speed Ratio: %f", state->fwdSpeedRatio);
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
formatf(tempString, "Max Speed Pitch Factor: %f", m_MaxSpeedPitchFactor);
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
formatf(tempString, "Max Speed Revs Add: %f", m_MaxSpeedRevsAddition);
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
formatf(tempString, "Brake: %f", GetVehicle()->GetBrake());
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
formatf(tempString, "Clutch: %f", GetVehicle()->m_Transmission.GetClutchRatio());
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
formatf(tempString, "Roof Openness: %f", GetEntityVariableValue(ATSTRINGHASH("roofopenness", 0xB146F028)));
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
if(m_Vehicle->GetDriver() && m_Vehicle->GetDriver()->GetPlayerInfo())
|
|
{
|
|
formatf(tempString, "Air Drag Mult: %f", m_Vehicle->GetDriver()->GetPlayerInfo()->m_fForceAirDragMult);
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
}
|
|
|
|
if(m_Vehicle->InheritsFromBike())
|
|
{
|
|
formatf(tempString, "Lean Ratio: %f", m_LeanRatio);
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
}
|
|
|
|
formatf(tempString, "Velocity CR: %f", (GetCachedVelocity().Mag() - GetCachedVelocityLastFrame().Mag()) * fwTimer::GetInvTimeStep());
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
formatf(tempString, "Ang Velocity Mag: %f", GetCachedAngularVelocity().Mag());
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
formatf(tempString, "Ang Velocity X: %f", GetCachedAngularVelocity().GetX());
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
formatf(tempString, "Ang Velocity Y: %f", GetCachedAngularVelocity().GetY());
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
formatf(tempString, "Ang Velocity Z: %f", GetCachedAngularVelocity().GetZ());
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
formatf(tempString, "Material Grip: %f", PGTAMATERIALMGR->GetMtlTyreGrip(m_MainWheelMaterial));
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
formatf(tempString, "Hydraulic Input Rate: %f", m_HydraulicSuspensionInputSmoother.GetLastValue());
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
formatf(tempString, "Hydraulic Angle Rate: %f", m_HydraulicSuspensionAngleSmoother.GetLastValue());
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
formatf(tempString, "Health Factor: %f", 1.0f - ComputeEffectiveBodyDamageFactor());
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
if(m_Vehicle->pHandling->hFlags & HF_HAS_KERS)
|
|
{
|
|
formatf(tempString, "Remaining Kers: %f", m_Vehicle->m_Transmission.GetKERSRemaining()/CTransmission::ms_KERSDurationMax);
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), m_Vehicle->GetKERSActive() ? Color32(0,255,0) : Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
}
|
|
|
|
if(m_Vehicle->HasRocketBoost())
|
|
{
|
|
formatf(tempString, "Remaining Rocket Boost: %f", m_Vehicle->GetRocketBoostRemaining()/m_Vehicle->GetRocketBoostCapacity());
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), m_Vehicle->IsRocketBoosting() ? Color32(0,255,0) : Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(g_DisplayClusteredVehicles)
|
|
{
|
|
if(m_Vehicle->m_nVehicleFlags.bIsInCluster)
|
|
{
|
|
Color32 colour = Color32(255,0,0,120);
|
|
grcDebugDraw::Sphere(VEC3V_TO_VECTOR3(m_Vehicle->GetTransform().GetPosition()), 3.f, colour);
|
|
}
|
|
}
|
|
|
|
if(m_IsPlayerVehicle)
|
|
{
|
|
if(g_TestBackfire)
|
|
{
|
|
m_Vehicle->m_nVehicleFlags.bAudioBackfired = true;
|
|
g_TestBackfire = false;
|
|
}
|
|
|
|
if(g_TestBackfireBanger)
|
|
{
|
|
m_Vehicle->m_nVehicleFlags.bAudioBackfiredBanger = true;
|
|
g_TestBackfireBanger = false;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
bool audCarAudioEntity::IsUsingGranularEngine()
|
|
{
|
|
return m_GranularEngineSettings != NULL;
|
|
}
|
|
|
|
void audCarAudioEntity::UpdateVehicleSpecific(audVehicleVariables& state, audVehicleDSPSettings& dspSettings)
|
|
{
|
|
PF_FUNC(UpdateInternal);
|
|
|
|
sm_CarFwdSpeedSum += state.fwdSpeed;
|
|
sm_NumActiveCars++;
|
|
|
|
if(m_HasAutoShutOffEngine)
|
|
{
|
|
if(!m_WasPlayingStartupSound &&
|
|
m_Vehicle->m_nVehicleFlags.bEngineOn &&
|
|
state.fwdSpeedAbs < 0.1f &&
|
|
!m_Vehicle->IsNetworkClone() &&
|
|
m_Vehicle->m_Transmission.GetRevRatio() <= CTransmission::ms_fIdleRevs &&
|
|
m_Vehicle->m_Transmission.GetThrottle() == 0.0f)
|
|
{
|
|
m_AutoShutOffTimer += fwTimer::GetTimeStep();
|
|
}
|
|
else
|
|
{
|
|
m_AutoShutOffTimer = 0.0f;
|
|
}
|
|
}
|
|
|
|
CPed *localPlayer = CPedFactory::GetFactory()->GetLocalPlayer();
|
|
|
|
if(localPlayer->GetIsInVehicle() && !m_IsPlayerVehicle && DistSquared(localPlayer->GetTransform().GetPosition(), GetPosition()).Getf() < (g_VehicleReflectionsActivationDist * g_VehicleReflectionsActivationDist))
|
|
{
|
|
m_IsGeneratingReflections = g_ReflectionsAudioEntity.AddVehicleReflection(this);
|
|
}
|
|
else if(m_IsGeneratingReflections)
|
|
{
|
|
g_ReflectionsAudioEntity.RemoveVehicleReflections(this);
|
|
m_IsGeneratingReflections = false;
|
|
}
|
|
|
|
if(IsDummy() || IsReal())
|
|
{
|
|
if(IsReal())
|
|
{
|
|
PopulateCarAudioVariables(&state);
|
|
dspSettings.rolloffScale = state.rollOffScale;
|
|
dspSettings.enginePostSubmixAttenuation = state.enginePostSubmixVol;
|
|
dspSettings.exhaustPostSubmixAttenuation = state.exhaustPostSubmixVol;
|
|
dspSettings.AddDSPParameter(atHashString("RPM", 0x5B924509), state.revs);
|
|
dspSettings.AddDSPParameter(atHashString("Throttle", 0xEA0151DC), state.throttle);
|
|
dspSettings.AddDSPParameter(atHashString("ThrottleInput", 0x918028C4), state.throttleInput);
|
|
dspSettings.AddDSPParameter(atHashString("RevLimiter", 0x4F40F76C), state.onRevLimiter ? 1.0f : 0.0f);
|
|
dspSettings.AddDSPParameter(atHashString("IsInTunnel", 0xEBD5E4C3), m_IsPlayerVehicle && g_ReflectionsAudioEntity.AreInteriorReflectionsActive());
|
|
AddCommonDSPParameters(dspSettings);
|
|
|
|
if(!m_Vehicle->m_nVehicleFlags.bEngineOn && m_vehicleEngine.GetState() != audVehicleEngine::AUD_ENGINE_STOPPING)
|
|
{
|
|
// keep the wet mix at 0 so it smooths up whatever happens (even if the car is started with the player inside)
|
|
m_EngineEffectWetSmoother.CalculateValue(0.0f, fwTimer::GetTimeStep());
|
|
}
|
|
|
|
UpdateRevsBoostEffect(&state);
|
|
m_vehicleEngine.Update(&state);
|
|
m_WasEngineOnLastFrame = (m_Vehicle->m_nVehicleFlags.bEngineOn);
|
|
UpdateBrakes(&state);
|
|
UpdateWind(&state);
|
|
UpdateBlips(&state);
|
|
UpdateWooWooSound(&state);
|
|
}
|
|
|
|
UpdateGliding(&state);
|
|
UpdateAmphibiousBoatMode(&state);
|
|
UpdateDamage(&state);
|
|
UpdateOffRoad(&state);
|
|
UpdateSuspension(&state);
|
|
UpdateJump(&state);
|
|
UpdateSpecialFlightMode(&state);
|
|
UpdateToyCar(&state);
|
|
|
|
if(state.fwdSpeedAbs < 0.1f)
|
|
{
|
|
m_LastTimeStationary = state.timeInMs;
|
|
}
|
|
}
|
|
|
|
if(!IsDisabled())
|
|
{
|
|
if(!audNorthAudioEngine::GetMicrophones().IsHeliMicActive())
|
|
{
|
|
UpdateCarPassSounds(&state);
|
|
UpdatePlayerCarSpinSounds(&state);
|
|
}
|
|
|
|
UpdateIndicator();
|
|
m_vehicleEngine.UpdateEngineCooling(&state);
|
|
|
|
if(m_AmphibiousBoatSettings)
|
|
{
|
|
if(IsSubmersible())
|
|
{
|
|
UpdateSubmersible(state, m_AmphibiousBoatSettings);
|
|
}
|
|
else
|
|
{
|
|
StopSubmersibleSounds();
|
|
}
|
|
|
|
u32 transformSoundSet = GetSubmarineCarTransformSoundSet();
|
|
|
|
if(transformSoundSet != 0u)
|
|
{
|
|
if(m_ShouldStopSubTransformSound)
|
|
{
|
|
if(m_SubmarineTransformSound)
|
|
{
|
|
m_SubmarineTransformSound->StopAndForget();
|
|
}
|
|
|
|
m_ShouldStopSubTransformSound = false;
|
|
}
|
|
else if(m_SubmarineTransformSoundHash != 0u)
|
|
{
|
|
audSoundSet soundSet;
|
|
|
|
if(soundSet.Init(transformSoundSet))
|
|
{
|
|
audMetadataRef metadataRef = soundSet.Find(m_SubmarineTransformSoundHash);
|
|
|
|
if(metadataRef != g_NullSoundRef)
|
|
{
|
|
if(m_SubmarineTransformSound)
|
|
{
|
|
m_SubmarineTransformSound->StopAndForget();
|
|
}
|
|
|
|
audSoundInitParams initParams;
|
|
initParams.TrackEntityPosition = true;
|
|
initParams.UpdateEntity = true;
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
CreateAndPlaySound_Persistent(metadataRef, &m_SubmarineTransformSound, &initParams);
|
|
REPLAY_ONLY(CReplayMgr::ReplayRecordSoundPersistant(soundSet.GetNameHash(), m_SubmarineTransformSoundHash, &initParams, m_SubmarineTransformSound, m_Vehicle));
|
|
}
|
|
}
|
|
}
|
|
|
|
m_SubmarineTransformSoundHash = 0u;
|
|
}
|
|
}
|
|
}
|
|
|
|
UpdateSportsCarRevs(&state);
|
|
UpdateHydraulicSuspension();
|
|
|
|
if(CVehicleRecordingMgr::IsPlaybackGoingOnForCar(m_Vehicle)
|
|
&& !CVehicleRecordingMgr::IsPlaybackSwitchedToAiForCar(m_Vehicle))
|
|
{
|
|
if(state.fwdSpeedAbs > 1.0f)
|
|
{
|
|
state.forcedThrottle = 1.0f;
|
|
}
|
|
|
|
if(GetCachedAngularVelocity().Mag2() > (0.5f * 0.5f))
|
|
{
|
|
f32 velocityChange = (GetCachedVelocity().Mag2() - m_CachedVehicleVelocityLastFrame.Mag2()) * fwTimer::GetInvTimeStep();
|
|
|
|
// If we're heavily slowing down, keep the revs on to sound like engine braking
|
|
if(velocityChange < -10.0f && velocityChange > -150.0f)
|
|
{
|
|
state.forcedThrottle = 0.0f;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(m_Vehicle->InheritsFromBike() || m_Vehicle->InheritsFromQuadBike() || (m_Vehicle->InheritsFromAmphibiousQuadBike() && !m_IsInAmphibiousBoatMode))
|
|
{
|
|
f32 desiredLeanRatio = Abs(Clamp(((CBike*)m_Vehicle)->m_fAnimLeanFwd, -1.0f, 1.0f) * Clamp(state.fwdSpeedRatio/0.3f, 0.0f, 1.0f));
|
|
|
|
if(desiredLeanRatio < m_LeanRatio)
|
|
{
|
|
m_LeanRatio = Clamp(m_LeanRatio - fwTimer::GetTimeStep() * 4.0f, 0.0f, 1.0f);
|
|
}
|
|
else
|
|
{
|
|
m_LeanRatio = Clamp(Min(desiredLeanRatio, (m_LeanRatio + (fwTimer::GetTimeStep() * 2.0f))), 0.0f, 1.0f);
|
|
}
|
|
|
|
state.exhaustPostSubmixVol += 1.5f * m_LeanRatio;
|
|
state.enginePostSubmixVol += 1.5f * m_LeanRatio;
|
|
state.granularEnginePitchOffset = Max(state.granularEnginePitchOffset, (s32)(50.0f * m_LeanRatio));
|
|
}
|
|
|
|
m_Vehicle->m_Transmission.ForceThrottle(state.forcedThrottle);
|
|
|
|
if(IsReal())
|
|
{
|
|
if(IsSubmersible())
|
|
{
|
|
m_vehicleEngine.SetGranularPitch(static_cast<s32>(m_SubTurningEnginePitchModifier.CalculateValue(m_SubAngularVelocityMag)));
|
|
}
|
|
else
|
|
{
|
|
m_vehicleEngine.SetGranularPitch(state.granularEnginePitchOffset);
|
|
}
|
|
|
|
|
|
m_vehicleEngine.SetGranularPitch(state.granularEnginePitchOffset);
|
|
}
|
|
|
|
SetEnvironmentGroupSettings(true, audNorthAudioEngine::GetOcclusionManager()->GetMaxOcclusionFullPathDepth());
|
|
|
|
#if __BANK
|
|
if(g_ToggleNos && m_IsPlayerVehicle)
|
|
{
|
|
if(m_NOSBoostLoop)
|
|
{
|
|
SetBoostActive(false);
|
|
}
|
|
else
|
|
{
|
|
SetBoostActive(true);
|
|
}
|
|
|
|
g_ToggleNos = false;
|
|
}
|
|
#endif
|
|
|
|
BANK_ONLY(UpdateDebug(&state);)
|
|
}
|
|
|
|
void audCarAudioEntity::UpdateSpecialFlightMode(audVehicleVariables* state)
|
|
{
|
|
u32 soundsetName = 0u;
|
|
|
|
if (GetVehicleModelNameHash() == ATSTRINGHASH("DELUXO", 0x586765FB))
|
|
{
|
|
soundsetName = ATSTRINGHASH("deluxo_flight_sounds", 0xA6DE1C45);
|
|
}
|
|
else if (GetVehicleModelNameHash() == ATSTRINGHASH("OPPRESSOR2", 0x7B54A9D3))
|
|
{
|
|
soundsetName = m_IsFocusVehicle? ATSTRINGHASH("oppressor2_flight_sounds", 0x3243BC86) : ATSTRINGHASH("oppressor2_npc_flight_sounds", 0x6368F652);
|
|
}
|
|
|
|
if(soundsetName != 0u)
|
|
{
|
|
if(m_Vehicle->GetSpecialFlightModeRatio() > 0.f)
|
|
{
|
|
if(!m_SpecialFlightModeSound)
|
|
{
|
|
audSoundSet soundset;
|
|
const u32 soundFieldName = ATSTRINGHASH("flight_loop", 0x42AF7BEA);
|
|
|
|
if(soundset.Init(soundsetName))
|
|
{
|
|
audSoundInitParams initParams;
|
|
initParams.TrackEntityPosition = true;
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
CreateAndPlaySound_Persistent(soundset.Find(soundFieldName), &m_SpecialFlightModeSound, &initParams);
|
|
}
|
|
}
|
|
|
|
if(m_SpecialFlightModeSound)
|
|
{
|
|
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();
|
|
REPLAY_ONLY(if (CReplayMgr::IsEditModeActive()) { angularVelocity = m_SpecialFlightModeReplayAngularVelocity; })
|
|
|
|
m_SpecialFlightModeSound->FindAndSetVariableValue(ATSTRINGHASH("throttle", 0xEA0151DC), state->throttle);
|
|
m_SpecialFlightModeSound->FindAndSetVariableValue(ATSTRINGHASH("throttleInput", 0x918028C4), state->throttleInput);
|
|
m_SpecialFlightModeSound->FindAndSetVariableValue(ATSTRINGHASH("rollAngle", 0x94FC4D71), rollAngle);
|
|
m_SpecialFlightModeSound->FindAndSetVariableValue(ATSTRINGHASH("pitchAngle", 0x809A226D), pitchAngle);
|
|
m_SpecialFlightModeSound->FindAndSetVariableValue(ATSTRINGHASH("yawAngle", 0x15DE02B1), yawAngle);
|
|
m_SpecialFlightModeSound->FindAndSetVariableValue(ATSTRINGHASH("angularVelocity", 0xC90EACC2), angularVelocity);
|
|
}
|
|
}
|
|
else if(m_SpecialFlightModeSound)
|
|
{
|
|
m_SpecialFlightModeSound->StopAndForget(true);
|
|
}
|
|
}
|
|
}
|
|
|
|
void audCarAudioEntity::UpdateToyCar(audVehicleVariables* state)
|
|
{
|
|
if (IsToyCar())
|
|
{
|
|
f32 throttleInput = Abs(state->throttle);
|
|
|
|
if(!CReplayMgr::IsEditModeActive())
|
|
{
|
|
throttleInput = Max(throttleInput, Abs(state->throttleInput));
|
|
}
|
|
|
|
if (m_Vehicle->IsEngineOn() && (throttleInput > 0 || state->fwdSpeedAbs > 0.1f))
|
|
{
|
|
if (!m_ToyCarEngineLoop)
|
|
{
|
|
audSoundSet soundSet;
|
|
|
|
if (soundSet.Init(ATSTRINGHASH("rcbandito_sounds", 0x7B9D9FE0)))
|
|
{
|
|
audSoundInitParams initParams;
|
|
initParams.TrackEntityPosition = true;
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
initParams.UpdateEntity = true;
|
|
CreateAndPlaySound_Persistent(soundSet.Find(ATSTRINGHASH("motor_loop", 0xF90A7007)), &m_ToyCarEngineLoop, &initParams);
|
|
}
|
|
}
|
|
|
|
if (m_ToyCarEngineLoop)
|
|
{
|
|
const f32 rollAngle = m_Vehicle->GetTransform().GetRoll() * RtoD;
|
|
const f32 pitchAngle = AcosfSafe(Dot(m_Vehicle->GetTransform().GetB(), Vec3V(V_Z_AXIS_WZERO)).Getf()) * RtoD;
|
|
const f32 yawAngle = m_Vehicle->GetTransform().GetHeading() * RtoD;
|
|
|
|
m_ToyCarEngineLoop->FindAndSetVariableValue(ATSTRINGHASH("throttle", 0xEA0151DC), throttleInput);
|
|
m_ToyCarEngineLoop->FindAndSetVariableValue(ATSTRINGHASH("rollAngle", 0x94FC4D71), rollAngle);
|
|
m_ToyCarEngineLoop->FindAndSetVariableValue(ATSTRINGHASH("pitchAngle", 0x809A226D), pitchAngle);
|
|
m_ToyCarEngineLoop->FindAndSetVariableValue(ATSTRINGHASH("yawAngle", 0x15DE02B1), yawAngle);
|
|
m_ToyCarEngineLoop->FindAndSetVariableValue(ATSTRINGHASH("steerAngle", 0x6D2AC1CE), Abs(m_Vehicle->GetSteerAngle()) * RtoD);
|
|
m_ToyCarEngineLoop->FindAndSetVariableValue(ATSTRINGHASH("surfaceHardness", 0x55D4D89C), m_CachedMaterialSettings ? m_CachedMaterialSettings->FootstepMaterialHardness : 0.f);
|
|
}
|
|
}
|
|
else if (m_ToyCarEngineLoop)
|
|
{
|
|
m_ToyCarEngineLoop->StopAndForget(true);
|
|
}
|
|
}
|
|
}
|
|
|
|
void audCarAudioEntity::UpdateJump(audVehicleVariables* state)
|
|
{
|
|
bool isUpsideDownInAir = false;
|
|
|
|
if(m_IsPlayerVehicle || m_Vehicle->IsNetworkClone())
|
|
{
|
|
f32 angleAdjustCreakVolumeLin = 0.0f;
|
|
|
|
if(state->numWheelsTouching == 0 && GetVehicleModelNameHash() != ATSTRINGHASH("OPPRESSOR2", 0x7B54A9D3) && !IsToyCar() && !IsGoKart())
|
|
{
|
|
f32 angVelocityMag = GetCachedAngularVelocity().Mag();
|
|
|
|
if((m_Vehicle->GetVehicleType() == VEHICLE_TYPE_CAR || m_Vehicle->GetVehicleType() == VEHICLE_TYPE_SUBMARINECAR || m_Vehicle->GetVehicleType() == VEHICLE_TYPE_AMPHIBIOUS_AUTOMOBILE) && !m_Vehicle->GetIsInWater())
|
|
{
|
|
if(state->fwdSpeedAbs < 1.0f || state->timeInMs - GetLastTimeOnGround() > 250)
|
|
{
|
|
angleAdjustCreakVolumeLin = Min(Max(Abs(m_InAirRotationalForceX), Abs(m_InAirRotationalForceY)) * Min(angVelocityMag, 1.0f), 1.0f);
|
|
}
|
|
}
|
|
|
|
// Automobile::isInAir isn't safe to call from the audio thread due to the call to HasContactWheels(), but we already know the wheel contact status so
|
|
// just manually check the rest of the conditions
|
|
bool isInAir = !m_Vehicle->GetIsInWater() && !m_Vehicle->GetIsAnyFixedFlagSet() && m_Vehicle->GetVelocity().Mag2() >= 0.005f;
|
|
|
|
if(isInAir)
|
|
{
|
|
if(m_IsPlayerVehicle)
|
|
{
|
|
isUpsideDownInAir = m_Vehicle->IsUpsideDown();
|
|
|
|
if(isUpsideDownInAir != m_WasUpsideDownInAir)
|
|
{
|
|
GetCollisionAudio().TriggerDebrisSounds(1.0f);
|
|
}
|
|
|
|
if((m_Vehicle->GetVehicleType() == VEHICLE_TYPE_CAR || m_Vehicle->GetVehicleType() == VEHICLE_TYPE_SUBMARINECAR || m_Vehicle->GetVehicleType() == VEHICLE_TYPE_AMPHIBIOUS_AUTOMOBILE) && state->timeInMs - GetLastTimeOnGround() > 50 && state->timeInMs - GetLastTimeOnGround() < 100 && !m_HasPlayedInitialJumpStress)
|
|
{
|
|
audSoundInitParams initParams;
|
|
initParams.TrackEntityPosition = true;
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
initParams.Volume = audDriverUtil::ComputeDbVolumeFromLinear((0.6f * Min((angVelocityMag - 1.0f)/4.0f, 1.0f)) + (0.4f * Min(state->fwdSpeedRatio * 2.0f, 1.0f)));
|
|
CreateAndPlaySound(sm_ExtrasSoundSet.Find(ATSTRINGHASH("PlayerCarJumpStartWronk", 0xFB9CB980)), &initParams);
|
|
m_HasPlayedInitialJumpStress = true;
|
|
}
|
|
}
|
|
|
|
if((state->revs > 0.95f && state->throttle > 0.9f) || state->onRevLimiter)
|
|
{
|
|
m_JumpThrottleCutTimer += fwTimer::GetTimeStep();
|
|
}
|
|
else if(m_JumpThrottleCutTimer <= 0.2f)
|
|
{
|
|
m_JumpThrottleCutTimer = 0.0f;
|
|
}
|
|
|
|
if(m_JumpThrottleCutTimer > 0.2f)
|
|
{
|
|
state->forcedThrottle = 0.0f;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_JumpThrottleCutTimer = 0.0f;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// True by default so that it doesn't play if you just jump with the analog stick pressed - you must release and re-press
|
|
m_HasPlayedInAirJumpStress = true;
|
|
m_HasPlayedInitialJumpStress = false;
|
|
m_JumpThrottleCutTimer = 0.0f;
|
|
}
|
|
|
|
if(!m_InAirRotationSound && !m_HasPlayedInAirJumpStress && angleAdjustCreakVolumeLin > g_SilenceVolumeLin && !IsToyCar() && !IsGoKart())
|
|
{
|
|
audSoundInitParams initParams;
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
initParams.TrackEntityPosition = true;
|
|
initParams.u32ClientVar = (u32)AUD_VEHICLE_SOUND_UNKNOWN;
|
|
initParams.UpdateEntity = true;
|
|
initParams.Volume = audDriverUtil::ComputeDbVolumeFromLinear(angleAdjustCreakVolumeLin);
|
|
CreateAndPlaySound_Persistent(sm_ExtrasSoundSet.Find(ATSTRINGHASH("PlayerCarAngleAdjustWronk", 0x9A9AFCEF)), &m_InAirRotationSound, &initParams);
|
|
|
|
if(m_InAirRotationSound)
|
|
{
|
|
m_HasPlayedInAirJumpStress = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(m_InAirRotationSound)
|
|
{
|
|
f32 volumeDB = audDriverUtil::ComputeDbVolumeFromLinear(angleAdjustCreakVolumeLin);
|
|
m_InAirRotationSound->SetRequestedVolume(Max(m_InAirRotationSound->GetRequestedVolume(), volumeDB));
|
|
}
|
|
else if(state->numWheelsTouching == 0 &&
|
|
((Sign(m_InAirRotationalForceX) != Sign(m_InAirRotationalForceXLastFrame) && m_InAirRotationalForceXLastFrame != 0.0f) ||
|
|
(Sign(m_InAirRotationalForceY) != Sign(m_InAirRotationalForceYLastFrame) && m_InAirRotationalForceYLastFrame != 0.0f) ||
|
|
(m_InAirRotationalForceX == 0.0f && m_InAirRotationalForceY == 0.0f)))
|
|
{
|
|
m_HasPlayedInAirJumpStress = false;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_JumpThrottleCutTimer = 0.0f;
|
|
m_HasPlayedInitialJumpStress = false;
|
|
m_HasPlayedInAirJumpStress = true;
|
|
}
|
|
|
|
m_WasUpsideDownInAir = isUpsideDownInAir;
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// audCarAudioEntity UpdateHydraulicSuspension
|
|
// ----------------------------------------------------------------
|
|
void audCarAudioEntity::UpdateHydraulicSuspension()
|
|
{
|
|
bool hydraulicInputLoopValid = false;
|
|
bool hydraulicAngleLoopValid = false;
|
|
|
|
if(!IsDisabled())
|
|
{
|
|
if(m_ShouldTriggerHydraulicBounce)
|
|
{
|
|
TriggerHydraulicBounce(false);
|
|
}
|
|
else if(fwTimer::GetTimeInMilliseconds() - m_LastHydraulicBounceTime > 250)
|
|
{
|
|
if(m_ShouldTriggerHydraulicActivate)
|
|
{
|
|
if(m_HydraulicActivationDelayFrames == 0)
|
|
{
|
|
SetHydraulicSuspensionActive(true);
|
|
}
|
|
}
|
|
else if(m_ShouldTriggerHydraulicDeactivate)
|
|
{
|
|
SetHydraulicSuspensionActive(false);
|
|
}
|
|
}
|
|
|
|
if(m_Vehicle->InheritsFromAutomobile() REPLAY_ONLY(&& !CReplayMgr::IsEditModeActive()))
|
|
{
|
|
const CAutomobile* automobile = static_cast<CAutomobile*>(m_Vehicle);
|
|
|
|
if(automobile->HasHydraulicSuspension())
|
|
{
|
|
const bool useDonkSuspension = m_Vehicle->GetVehicleModelInfo() && m_Vehicle->GetVehicleModelInfo()->GetVehicleFlag( CVehicleModelInfoFlags::FLAG_HAS_LOWRIDER_DONK_HYDRAULICS);
|
|
|
|
if(m_IsPlayerVehicle)
|
|
{
|
|
hydraulicInputLoopValid = UpdateHydraulicSuspensionInputLoop();
|
|
}
|
|
|
|
CalculateHydraulicSuspensionAngle();
|
|
hydraulicAngleLoopValid = UpdateHydraulicSuspensionAngleLoop(useDonkSuspension);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(m_HydraulicActivationDelayFrames > 0)
|
|
{
|
|
m_HydraulicActivationDelayFrames--;
|
|
}
|
|
else
|
|
{
|
|
m_ShouldTriggerHydraulicActivate = false;
|
|
}
|
|
|
|
m_ShouldTriggerHydraulicDeactivate = false;
|
|
m_ShouldTriggerHydraulicBounce = false;
|
|
|
|
if(m_HydraulicSuspensionInputLoop && !hydraulicInputLoopValid)
|
|
{
|
|
m_HydraulicSuspensionInputLoop->StopAndForget();
|
|
}
|
|
|
|
if(m_HydraulicSuspensionAngleLoop && !hydraulicAngleLoopValid)
|
|
{
|
|
m_HydraulicSuspensionAngleLoop->StopAndForget();
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// audCarAudioEntity UpdateHydraulicSuspensionInputLoop
|
|
// ----------------------------------------------------------------
|
|
bool audCarAudioEntity::UpdateHydraulicSuspensionInputLoop()
|
|
{
|
|
bool loopValid = false;
|
|
audSoundSet hydraulicSuspensionSoundSet;
|
|
hydraulicSuspensionSoundSet.Init(GetVehicleHydraulicsSoundSetName());
|
|
|
|
if(hydraulicSuspensionSoundSet.IsInitialised())
|
|
{
|
|
if(m_HydraulicSuspensionInputSmoother.GetLastValue() > 0.f)
|
|
{
|
|
if(!m_HydraulicSuspensionInputLoop)
|
|
{
|
|
const u32 soundName = ATSTRINGHASH("Hydraulic_Suspension_Loop", 0xF27A3105);
|
|
audSoundInitParams initParams;
|
|
initParams.TrackEntityPosition = true;
|
|
initParams.UpdateEntity = true;
|
|
CreateAndPlaySound_Persistent(hydraulicSuspensionSoundSet.Find(soundName), &m_HydraulicSuspensionInputLoop, &initParams);
|
|
|
|
if(m_HydraulicSuspensionInputLoop)
|
|
{
|
|
REPLAY_ONLY(CReplayMgr::ReplayRecordSoundPersistant(hydraulicSuspensionSoundSet.GetNameHash(), soundName, &initParams, m_HydraulicSuspensionInputLoop, m_Vehicle);)
|
|
}
|
|
}
|
|
|
|
if(m_HydraulicSuspensionInputLoop)
|
|
{
|
|
m_HydraulicSuspensionInputLoop->FindAndSetVariableValue(ATSTRINGHASH("MovementRate", 0xE654C106), m_HydraulicSuspensionInputSmoother.GetLastValue());
|
|
}
|
|
|
|
loopValid = true;
|
|
}
|
|
}
|
|
|
|
return loopValid;
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// audCarAudioEntity UpdateHydraulicSuspensionAngleLoop
|
|
// ----------------------------------------------------------------
|
|
bool audCarAudioEntity::UpdateHydraulicSuspensionAngleLoop(bool useDonkSuspension)
|
|
{
|
|
bool loopValid = false;
|
|
audSoundSet hydraulicSuspensionSoundSet;
|
|
hydraulicSuspensionSoundSet.Init(GetVehicleHydraulicsSoundSetName());
|
|
|
|
if(m_HydraulicSuspensionAngleSmoother.GetLastValue() > (m_Vehicle->IsNetworkClone()? g_HydraulicSuspensionAngleLoopTriggerThresholdRemoteVehicle : g_HydraulicSuspensionAngleLoopTriggerThreshold))
|
|
{
|
|
if(m_HydraulicAngleLoopRetriggerValid)
|
|
{
|
|
if(!m_HydraulicSuspensionAngleLoop)
|
|
{
|
|
const u32 soundName = useDonkSuspension? ATSTRINGHASH("Hydraulic_Suspension_Donk_Loop", 0x7B9EE3F6) : ATSTRINGHASH("Hydraulic_Suspension_Angle_Loop", 0x593CF220);
|
|
audMetadataRef soundRef = hydraulicSuspensionSoundSet.Find(soundName);
|
|
|
|
if(soundRef.IsValid())
|
|
{
|
|
audSoundInitParams initParams;
|
|
initParams.TrackEntityPosition = true;
|
|
initParams.UpdateEntity = true;
|
|
CreateAndPlaySound_Persistent(soundRef, &m_HydraulicSuspensionAngleLoop, &initParams);
|
|
|
|
if(m_HydraulicSuspensionAngleLoop)
|
|
{
|
|
REPLAY_ONLY(CReplayMgr::ReplayRecordSoundPersistant(hydraulicSuspensionSoundSet.GetNameHash(), soundName, &initParams, m_HydraulicSuspensionAngleLoop, m_Vehicle);)
|
|
}
|
|
}
|
|
}
|
|
|
|
m_HydraulicAngleLoopRetriggerValid = false;
|
|
}
|
|
|
|
loopValid = true;
|
|
}
|
|
|
|
if(m_HydraulicSuspensionAngleLoop)
|
|
{
|
|
m_HydraulicSuspensionAngleLoop->FindAndSetVariableValue(ATSTRINGHASH("MovementRate", 0xE654C106), m_HydraulicSuspensionAngleSmoother.GetLastValue());
|
|
}
|
|
|
|
if(!m_HydraulicAngleLoopRetriggerValid)
|
|
{
|
|
if(m_HydraulicSuspensionAngleSmoother.GetLastValue() < (m_Vehicle->IsNetworkClone() ? g_HydraulicSuspensionAngleLoopReTriggerThresholdRemoteVehicle : g_HydraulicSuspensionAngleLoopReTriggerThreshold))
|
|
{
|
|
m_HydraulicAngleLoopRetriggerValid = true;
|
|
}
|
|
}
|
|
|
|
return loopValid;
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// Called when the hydraulic suspension is modified
|
|
// ----------------------------------------------------------------
|
|
void audCarAudioEntity::SetHydraulicSuspensionActive(bool hydraulicsActive)
|
|
{
|
|
bool anyWheelTouching = true;
|
|
bool anyWheelLanding = false;
|
|
const bool isUpsideDownOrOnSide = m_Vehicle->IsOnItsSide() || m_Vehicle->IsUpsideDown();
|
|
|
|
// If we're upside down or sideways, just trigger stuff regardless
|
|
if(!isUpsideDownOrOnSide)
|
|
{
|
|
anyWheelTouching = false;
|
|
|
|
for(u32 loop = 0; loop < m_Vehicle->GetNumWheels(); loop++)
|
|
{
|
|
CWheel* wheel = m_Vehicle->GetWheel(loop);
|
|
|
|
if(wheel)
|
|
{
|
|
if(wheel->GetIsTouching())
|
|
{
|
|
anyWheelTouching = true;
|
|
}
|
|
|
|
if(wheel->GetSuspensionHydraulicState() == WHS_BOUNCE_LANDING || wheel->GetSuspensionHydraulicState() == WHS_BOUNCE_LANDING)
|
|
{
|
|
anyWheelLanding = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(anyWheelTouching)
|
|
{
|
|
audSoundSet hydraulicSuspensionSoundSet;
|
|
hydraulicSuspensionSoundSet.Init(GetVehicleHydraulicsSoundSetName());
|
|
|
|
if(!anyWheelLanding)
|
|
{
|
|
if(hydraulicSuspensionSoundSet.IsInitialised())
|
|
{
|
|
const u32 soundName = hydraulicsActive? ATSTRINGHASH("Hydraulic_Suspension_Activate", 0xC9E2ED9E) : ATSTRINGHASH("Hydraulic_Suspension_Deactivate", 0x1D682F39);
|
|
audSoundInitParams initParams;
|
|
initParams.TrackEntityPosition = true;
|
|
initParams.UpdateEntity = true;
|
|
|
|
if(sysThreadType::IsUpdateThread())
|
|
{
|
|
CreateDeferredSound(hydraulicSuspensionSoundSet.Find(soundName), m_Vehicle, &initParams, true);
|
|
}
|
|
else
|
|
{
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
CreateAndPlaySound(hydraulicSuspensionSoundSet.Find(soundName), &initParams);
|
|
}
|
|
|
|
REPLAY_ONLY(CReplayMgr::ReplayRecordSound(hydraulicSuspensionSoundSet.GetNameHash(), soundName, &initParams, m_Vehicle));
|
|
}
|
|
}
|
|
|
|
m_LastHydraulicEngageDisengageTime = m_LastHydraulicSuspensionStateChangeTime = fwTimer::GetTimeInMilliseconds();
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// Trigger a hydraulic bounce on the given number of wheels
|
|
// ----------------------------------------------------------------
|
|
void audCarAudioEntity::TriggerHydraulicBounce(bool smallBounce)
|
|
{
|
|
bool allWheelsTouching = true;
|
|
const bool isUpsideDownOrOnSide = m_Vehicle->IsOnItsSide() || m_Vehicle->IsUpsideDown();
|
|
|
|
// If we're upside down or sideways, just trigger stuff regardless
|
|
if(!isUpsideDownOrOnSide)
|
|
{
|
|
for(u32 loop = 0; loop < m_Vehicle->GetNumWheels(); loop++)
|
|
{
|
|
CWheel* wheel = m_Vehicle->GetWheel(loop);
|
|
|
|
if(wheel && !wheel->GetIsTouching())
|
|
{
|
|
allWheelsTouching = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(allWheelsTouching)
|
|
{
|
|
audSoundSet hydraulicSuspensionSoundSet;
|
|
hydraulicSuspensionSoundSet.Init(GetVehicleHydraulicsSoundSetName());
|
|
|
|
if(hydraulicSuspensionSoundSet.IsInitialised())
|
|
{
|
|
const u32 soundName = smallBounce? ATSTRINGHASH("Hydraulic_Suspension_Bounce_Small", 0x36B0F523) : ATSTRINGHASH("Hydraulic_Suspension_Bounce", 0xFA0677E7);
|
|
audSoundInitParams initParams;
|
|
initParams.TrackEntityPosition = true;
|
|
initParams.UpdateEntity = true;
|
|
|
|
if(sysThreadType::IsUpdateThread())
|
|
{
|
|
CreateDeferredSound(hydraulicSuspensionSoundSet.Find(soundName), m_Vehicle, &initParams, true);
|
|
}
|
|
else
|
|
{
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
CreateAndPlaySound(hydraulicSuspensionSoundSet.Find(soundName), &initParams);
|
|
}
|
|
|
|
REPLAY_ONLY(CReplayMgr::ReplayRecordSound(hydraulicSuspensionSoundSet.GetNameHash(), soundName, &initParams, m_Vehicle));
|
|
m_LastHydraulicBounceTime = fwTimer::GetTimeInMilliseconds();
|
|
m_ShouldTriggerHydraulicActivate = false;
|
|
}
|
|
}
|
|
|
|
m_LastHydraulicSuspensionStateChangeTime = fwTimer::GetTimeInMilliseconds();
|
|
}
|
|
|
|
void audCarAudioEntity::UpdateDamage(audVehicleVariables* state)
|
|
{
|
|
if(m_vehicleEngine.GetState() != audVehicleEngine::AUD_ENGINE_OFF BANK_ONLY(&& !g_MuteDamageLayers))
|
|
{
|
|
for(u32 i = 0; i < g_NumDamageLayersPerCar; i++)
|
|
{
|
|
if(m_EngineDamageLayerIndex[i] != -1)
|
|
{
|
|
s32 pitch = (s32)(g_DamageLayerMinPitch + ((g_DamageLayerMaxPitch - g_DamageLayerMinPitch) * state->revs));
|
|
f32 vol = g_EngineDamageCurves[m_EngineDamageLayerIndex[i]].CalculateValue(state->engineDamageFactor) * audDriverUtil::ComputeLinearVolumeFromDb(state->engineConeAtten + state->engineThrottleAtten);
|
|
UpdateLoopWithLinearVolumeAndPitch(&m_EngineDamageLayers[i], g_EngineDamageLayers[m_EngineDamageLayerIndex[i]].soundHash, vol, pitch, m_EnvironmentGroup, NULL, true, true);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for(u32 loop = 0; loop < g_NumDamageLayersPerCar; loop++)
|
|
{
|
|
if(m_EngineDamageLayers[loop])
|
|
{
|
|
m_EngineDamageLayers[loop]->StopAndForget(true);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(state->engineDamageFactor > 0.5f)
|
|
{
|
|
f32 damageFrequencyRatio = m_EngineDamageFrequencyRatioFluctuator.CalculateValue();
|
|
f32 revRatio = 1.0f - Clamp((((state->revs - 0.2f) * 1.25f)/0.4f), 0.0f, 1.0f);
|
|
|
|
if(revRatio > 0.0f && !m_IsInAmphibiousBoatMode)
|
|
{
|
|
state->granularEnginePitchOffset = (s32)(audDriverUtil::ConvertRatioToPitch(damageFrequencyRatio) * state->engineDamageFactor * revRatio);
|
|
}
|
|
}
|
|
|
|
static const f32 minWheelDamageFactor = 0.1f;
|
|
|
|
if(m_Vehicle->GetNumWheels() >= 4)
|
|
{
|
|
f32 maxWheelDamageVol = 0.0f;
|
|
f32 maxGrindRatio = 0.0f;
|
|
Vector3 soundPosition;
|
|
s32 maxPitch = -1200;
|
|
bool anyWheelsDamaged = false;
|
|
|
|
// Quickly check that any wheels are actually damaged. In most cases they won't be, which saves us the work of
|
|
// querying the wheel positions etc.
|
|
for(s32 i = 0; i < 2; i++)
|
|
{
|
|
CWheel *wheel = m_Vehicle->GetWheel(i);
|
|
|
|
if(m_HasRandomWheelDamage || wheel->GetFrictionDamage() > minWheelDamageFactor BANK_ONLY(|| g_ForceWheelDamage))
|
|
{
|
|
anyWheelsDamaged = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(anyWheelsDamaged)
|
|
{
|
|
Vector3 leftWheelPos, rightWheelPos;
|
|
GetCachedWheelPosition(0, leftWheelPos, *state);
|
|
GetCachedWheelPosition(1, rightWheelPos, *state);
|
|
Vector3 wheelCentre = (leftWheelPos + rightWheelPos) * 0.5f;
|
|
soundPosition = wheelCentre;
|
|
|
|
// High levels of body damage can also cause wheel damage audio, as its pretty hard to properly damage (ie. misalign) the wheels
|
|
f32 bodyDamageFactor = ((GetVehicle()->GetVehicleDamage()->GetBodyHealth() / CVehicleDamage::GetBodyHealthMax()) - 0.7f)/0.5f;
|
|
|
|
for(s32 i = 0; i < 2; i++)
|
|
{
|
|
CWheel *wheel = m_Vehicle->GetWheel(i);
|
|
f32 speedRatio = (wheel->GetIsTouching()?Clamp(Abs(wheel->GetGroundSpeed()) * state->invDriveMaxVelocity, 0.0f,1.0f):0.0f);
|
|
s32 pitch = g_DamagedWheelMinPitch + (s32)((g_DamagedWheelMaxPitch - g_DamagedWheelMinPitch) * Min(speedRatio/0.5f, 1.0f));
|
|
|
|
f32 steeringGrindRatio = 0.0f;
|
|
|
|
if(wheel->GetConfigFlags().IsFlagSet(WCF_STEER))
|
|
{
|
|
f32 steeringAngle = wheel->GetSteeringAngle();
|
|
steeringGrindRatio = Clamp(Abs(steeringAngle*4.0f),0.0f,1.0f);
|
|
maxGrindRatio = Max(maxGrindRatio, steeringGrindRatio);
|
|
}
|
|
|
|
// Wheels are generally completely dead by about 0.3 damage, so max out the volume a little before then
|
|
f32 wheelDamage = wheel->GetFrictionDamage();
|
|
|
|
if(m_HasRandomWheelDamage)
|
|
{
|
|
wheelDamage = Max(wheelDamage, 0.15f);
|
|
}
|
|
|
|
#if __BANK
|
|
if(g_ForceWheelDamage)
|
|
{
|
|
wheelDamage = 1.0f;
|
|
}
|
|
#endif
|
|
|
|
f32 damageRatio = 0.0f;
|
|
|
|
if(wheelDamage > 0.1f)
|
|
{
|
|
damageRatio = Max(Clamp((wheelDamage - 0.1f)/0.1f, 0.f, 1.f), bodyDamageFactor);
|
|
// Scale a bit of the volume quickly at slow speeds, and then apply a more gradual speed fade with a greater range
|
|
f32 vol = damageRatio * ((0.3f * Clamp((speedRatio/0.075f),0.0f,1.0f)) + (0.7f * speedRatio));
|
|
vol *= (0.6f + (0.4f * steeringGrindRatio)); // Louder when turning
|
|
maxWheelDamageVol = Max(vol, maxWheelDamageVol);
|
|
maxPitch = Max(pitch, maxPitch);
|
|
}
|
|
|
|
soundPosition += ((i == 0? leftWheelPos : rightWheelPos) - wheelCentre) * damageRatio;
|
|
}
|
|
|
|
maxGrindRatio = m_TyreDamageGrindRatioSmoother.CalculateValue(maxGrindRatio);
|
|
}
|
|
|
|
if(maxWheelDamageVol > g_SilenceVolumeLin)
|
|
{
|
|
audSoundInitParams initParams;
|
|
initParams.EnvironmentGroup = GetEnvironmentGroup();
|
|
initParams.UpdateEntity = true;
|
|
|
|
if(!m_DamageTyreScrapeTurnSound)
|
|
{
|
|
const audMetadataRef tyreDentTurnRef = GetDamageSoundSet()->Find("Tyre_Scrape_Dent_Turn");
|
|
CreateAndPlaySound_Persistent(tyreDentTurnRef, &m_DamageTyreScrapeTurnSound, &initParams);
|
|
}
|
|
|
|
if(!m_DamageTyreScrapeSound)
|
|
{
|
|
const audMetadataRef tyreDentRef = GetDamageSoundSet()->Find("Tyre_Scrape_Dent");
|
|
CreateAndPlaySound_Persistent(tyreDentRef, &m_DamageTyreScrapeSound, &initParams);
|
|
}
|
|
|
|
if(m_DamageTyreScrapeTurnSound)
|
|
{
|
|
m_DamageTyreScrapeTurnSound->SetRequestedVolume(audDriverUtil::ComputeDbVolumeFromLinear(maxWheelDamageVol * Sinf(maxGrindRatio * (PI * 0.5f))));
|
|
m_DamageTyreScrapeTurnSound->SetRequestedPosition(soundPosition);
|
|
m_DamageTyreScrapeTurnSound->SetRequestedPitch(maxPitch);
|
|
m_DamageTyreScrapeTurnSound->SetRequestedDopplerFactor(0.0f);
|
|
}
|
|
|
|
if(m_DamageTyreScrapeSound)
|
|
{
|
|
m_DamageTyreScrapeSound->SetRequestedVolume(audDriverUtil::ComputeDbVolumeFromLinear(maxWheelDamageVol * Sinf((1.0f - maxGrindRatio) * (PI * 0.5f))));
|
|
m_DamageTyreScrapeSound->SetRequestedPitch(maxPitch);
|
|
m_DamageTyreScrapeSound->SetRequestedPosition(soundPosition);
|
|
m_DamageTyreScrapeSound->SetRequestedDopplerFactor(0.0f);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
StopAndForgetSounds(m_DamageTyreScrapeSound, m_DamageTyreScrapeTurnSound);
|
|
}
|
|
}
|
|
|
|
if(m_IsPlayerVehicle && m_Vehicle->m_nVehicleFlags.bEngineOn BANK_ONLY(&& g_EnableDamageThrottleCut))
|
|
{
|
|
u32 currentTime = g_AudioEngine.GetTimeInMilliseconds();
|
|
|
|
// This should only occur on vehicles that are actually damaged (not 'fake' audio damaged)
|
|
f32 engineDamageFactor = 1.0f - (m_Vehicle->GetVehicleDamage()->GetEngineHealth() / CTransmission::GetEngineHealthMax());
|
|
|
|
#if __BANK
|
|
if(g_ForceDamage && m_IsPlayerVehicle)
|
|
{
|
|
engineDamageFactor = g_ForcedDamageFactor;
|
|
}
|
|
#endif
|
|
|
|
if(currentTime > m_NextDamageThrottleCutTime)
|
|
{
|
|
if(engineDamageFactor > 0.7f && state->gear > 1 && state->throttle == 1.0f)
|
|
{
|
|
f32 throttleCutFactor = (engineDamageFactor - 0.7f)/0.3f;
|
|
|
|
if(state->rawRevs > 0.9f - (0.2f * throttleCutFactor))
|
|
{
|
|
if(m_DamageThrottleCutTimer <= 0.0f)
|
|
{
|
|
if(audEngineUtil::ResolveProbability(g_HighRevsMisfireSoundProb))
|
|
{
|
|
audSoundInitParams initParams;
|
|
initParams.UpdateEntity = true;
|
|
initParams.TrackEntityPosition = true;
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
CreateAndPlaySound(ATSTRINGHASH("DAMAGE_ENGINE_MISFIRE", 0x39395D40), &initParams);
|
|
}
|
|
|
|
m_DamageThrottleCutTimer = audEngineUtil::GetRandomNumberInRange(g_MinDamageThrottleCutDuration, g_MaxDamageThrottleCutDuration);
|
|
|
|
f32 shortCutProbability = g_ShortDamageCutProbMin + ((g_ShortDamageCutProbMax - g_ShortDamageCutProbMin) * throttleCutFactor);
|
|
|
|
if(audEngineUtil::ResolveProbability(shortCutProbability))
|
|
{
|
|
m_NextDamageThrottleCutTime = currentTime + audEngineUtil::GetRandomNumberInRange(g_MinTimeBetweenDamageThrottleCutsShort, g_MaxTimeBetweenDamageThrottleCutsShort);
|
|
m_ConsecutiveShortThrottleCuts++;
|
|
}
|
|
else
|
|
{
|
|
m_NextDamageThrottleCutTime = currentTime + audEngineUtil::GetRandomNumberInRange(g_MinTimeBetweenDamageThrottleCuts, g_MaxTimeBetweenDamageThrottleCuts);
|
|
|
|
if(!m_vehicleEngine.IsMisfiring())
|
|
{
|
|
if(m_ConsecutiveShortThrottleCuts > 2)
|
|
{
|
|
if(audEngineUtil::ResolveProbability(0.05f * m_ConsecutiveShortThrottleCuts))
|
|
{
|
|
audSoundInitParams initParams;
|
|
initParams.UpdateEntity = true;
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
initParams.Predelay = (s32)(m_DamageThrottleCutTimer * 1000.0f);
|
|
initParams.PostSubmixAttenuation = state->exhaustConeAtten;
|
|
initParams.u32ClientVar = AUD_VEHICLE_SOUND_EXHAUST;
|
|
if(CreateAndPlaySound(ATSTRINGHASH("EX_POPS_BACKFIRE", 0x38BEF758), &initParams))
|
|
{
|
|
m_Vehicle->m_nVehicleFlags.bAudioBackfiredBanger = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
m_ConsecutiveShortThrottleCuts = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(m_DamageThrottleCutTimer > 0.0f)
|
|
{
|
|
m_DamageThrottleCutTimer -= fwTimer::GetTimeStep();
|
|
state->forcedThrottle = 0.0f;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_DamageThrottleCutTimer = 0.0f;
|
|
}
|
|
}
|
|
|
|
void audCarAudioEntity::UpdateWind(audVehicleVariables* state)
|
|
{
|
|
if(m_IsPlayerVehicle)
|
|
{
|
|
if(!m_WindFastSound)
|
|
{
|
|
audSoundInitParams initParams;
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
initParams.TrackEntityPosition = true;
|
|
CreateAndPlaySound_Persistent(sm_ExtrasSoundSet.Find(ATSTRINGHASH("SpeedWindSound", 0x1209E974)), &m_WindFastSound, &initParams);
|
|
}
|
|
|
|
if(m_WindFastSound)
|
|
{
|
|
f32 smoothedSpeed = sm_PlayerWindNoiseSpeedSmoother.CalculateValue(Min(state->fwdSpeed, g_AudioEngine.GetEnvironment().GetActualListenerSpeed()), g_AudioEngine.GetSoundManager().GetTimeInMilliseconds(0));
|
|
m_WindFastSound->FindAndSetVariableValue(ATSTRINGHASH("SmoothedSpeed", 0xC5D4E354), smoothedSpeed);
|
|
|
|
f32 cutoff = kVoiceFilterLPFMaxCutoff;
|
|
|
|
if(audNorthAudioEngine::IsRenderingFirstPersonVehicleCam())
|
|
{
|
|
static const float minInteriorViewCutoff = 1000.0f;
|
|
const f32 interiorViewCutoff = minInteriorViewCutoff + ((kVoiceFilterLPFMaxCutoff - minInteriorViewCutoff) * sm_PlayerVehicleOpenness);
|
|
cutoff = Min(cutoff, interiorViewCutoff);
|
|
}
|
|
|
|
#if __BANK
|
|
sm_PlayerWindNoiseSpeedSmoother.SetRates(1.0f/g_WindNoiseSmootherIncreaseRate, 1.0f/g_WindNoiseSmootherDecreaseRate);
|
|
|
|
if(g_DebugWindNoise)
|
|
{
|
|
char tempString[128];
|
|
formatf(tempString, "Fwd Speed: %f", state->fwdSpeed);
|
|
grcDebugDraw::Text(Vector2(0.15f, 0.15f), Color32(255,255,255), tempString);
|
|
|
|
formatf(tempString, "Smoothed Speed: %f", sm_PlayerWindNoiseSpeedSmoother.GetLastValue());
|
|
grcDebugDraw::Text(Vector2(0.15f, 0.17f), Color32(255,255,255), tempString);
|
|
}
|
|
#endif
|
|
|
|
m_WindFastSound->SetRequestedLPFCutoff((u32)cutoff);
|
|
}
|
|
}
|
|
else if(m_WindFastSound)
|
|
{
|
|
m_WindFastSound->StopAndForget();
|
|
}
|
|
}
|
|
|
|
void audCarAudioEntity::BlipThrottle()
|
|
{
|
|
m_ForceThrottleBlip = true;
|
|
}
|
|
|
|
GranularEngineAudioSettings* audCarAudioEntity::GetGranularEngineAudioSettings() const
|
|
{
|
|
if(m_IsPlayerVehicle || g_GranularEnableNPCGranularEngines || g_ForceGranularNPCEngines)
|
|
{
|
|
return m_GranularEngineSettings;
|
|
}
|
|
else
|
|
{
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
void audCarAudioEntity::OnFocusVehicleChanged()
|
|
{
|
|
if(g_GranularEnabled &&
|
|
m_vehicleEngine.HasBeenInitialised() &&
|
|
m_vehicleEngine.GetState() != audVehicleEngine::AUD_ENGINE_STOPPING)
|
|
{
|
|
m_vehicleEngine.QualitySettingChanged();
|
|
}
|
|
|
|
if(!m_IsFocusVehicle && m_ParachuteLoop)
|
|
{
|
|
m_ParachuteLoop->StopAndForget();
|
|
}
|
|
|
|
StopSirenIfBroken();
|
|
|
|
const u32 vehicleModelNameHash = GetVehicleModelNameHash();
|
|
|
|
if(vehicleModelNameHash == ATSTRINGHASH("VOLTIC2", 0x3AF76F4A) || vehicleModelNameHash == ATSTRINGHASH("rcbandito", 0xEEF345EC))
|
|
{
|
|
// Voltic 2 has a special high-quality sized SFX bank, so need to make sure we clear that out when the quality switches
|
|
if(m_vehicleEngine.HasBeenInitialised() && m_vehicleEngine.GetState() != audVehicleEngine::AUD_ENGINE_STOPPING)
|
|
{
|
|
ReapplyDSPEffects();
|
|
FreeWaveSlot(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------
|
|
// audCarAudioEntity::AcquireWaveSlot
|
|
// -------------------------------------------------------------------------------
|
|
bool audCarAudioEntity::AcquireWaveSlot()
|
|
{
|
|
u32 sfxBankLoadSound = 0u;
|
|
m_RequiresSFXBank = false;
|
|
bool useHighQualitySfxBank = false;
|
|
|
|
if(m_IsFocusVehicle)
|
|
{
|
|
u32 vehicleModelNameHash = GetVehicleModelNameHash();
|
|
|
|
if(vehicleModelNameHash == ATSTRINGHASH("VOLTIC2", 0x3AF76F4A))
|
|
{
|
|
sfxBankLoadSound = ATSTRINGHASH("voltic2_bank_load_sound", 0xCA26A3F1);
|
|
useHighQualitySfxBank = true;
|
|
}
|
|
else if (vehicleModelNameHash == ATSTRINGHASH("rcbandito", 0xEEF345EC))
|
|
{
|
|
sfxBankLoadSound = ATSTRINGHASH("rcbandito_bank_load_sound", 0x388C3ED1);
|
|
useHighQualitySfxBank = true;
|
|
}
|
|
else if (vehicleModelNameHash == ATSTRINGHASH("imorgon", 0xBC7C0A00))
|
|
{
|
|
sfxBankLoadSound = ATSTRINGHASH("imorgon_bank_load_sound", 0x78851083);
|
|
}
|
|
else if(m_AmphibiousBoatSettings)
|
|
{
|
|
sfxBankLoadSound = m_AmphibiousBoatSettings->SFXBankSound;
|
|
}
|
|
}
|
|
|
|
if(sfxBankLoadSound != 0u && sfxBankLoadSound != g_NullSoundHash)
|
|
{
|
|
m_RequiresSFXBank = true;
|
|
RequestSFXWaveSlot(sfxBankLoadSound, useHighQualitySfxBank);
|
|
|
|
if(!m_SFXWaveSlot)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_RequiresSFXBank = false;
|
|
}
|
|
|
|
if(m_vehicleEngine.IsGranularEngineActive())
|
|
{
|
|
if(m_vehicleEngine.IsLowQualityGranular())
|
|
{
|
|
RequestWaveSlot(&sm_StandardWaveSlotManager, m_GranularEngineSettings->NPCEngineAccel);
|
|
}
|
|
else
|
|
{
|
|
RequestWaveSlot(&sm_HighQualityWaveSlotManager, m_GranularEngineSettings->EngineAccel);
|
|
}
|
|
}
|
|
else if(m_VehicleEngineSettings)
|
|
{
|
|
RequestWaveSlot(&sm_StandardWaveSlotManager, m_VehicleEngineSettings->IdleEngineSimpleLoop);
|
|
}
|
|
else if(m_ElectricEngineSettings)
|
|
{
|
|
RequestWaveSlot(&sm_StandardWaveSlotManager, m_ElectricEngineSettings->BankLoadSound);
|
|
}
|
|
|
|
if(m_RequiresSFXBank)
|
|
{
|
|
// If we didn't manage to acquire a primary wave slot, release the SFX slot so we don't hog it
|
|
if(m_SFXWaveSlot && !m_EngineWaveSlot)
|
|
{
|
|
audWaveSlotManager::FreeWaveSlot(m_SFXWaveSlot, this);
|
|
}
|
|
|
|
return m_SFXWaveSlot != NULL && m_EngineWaveSlot != NULL;
|
|
}
|
|
else
|
|
{
|
|
return m_EngineWaveSlot != NULL;
|
|
}
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------
|
|
// audCarAudioEntity::GetDesiredLOD
|
|
// -------------------------------------------------------------------------------
|
|
audVehicleLOD audCarAudioEntity::GetDesiredLOD(f32 fwdSpeedRatio, u32 originalDistFromListenerSq, bool visibleBySniper)
|
|
{
|
|
// Artificially increase height offset to give preference to vehicles on the same plane as the listener
|
|
Vector3 distToListener = VEC3V_TO_VECTOR3(m_Vehicle->GetTransform().GetPosition() - g_AudioEngine.GetEnvironment().GetVolumeListenerPosition(audNorthAudioEngine::GetMicrophones().IsTinyRacersMicrophoneActive() ? 1 : 0));
|
|
distToListener.SetZ(distToListener.GetZ() * 2.0f);
|
|
f32 mag2 = visibleBySniper? originalDistFromListenerSq : distToListener.Mag2();
|
|
f32 speedRatioMult = Clamp((fwdSpeedRatio - g_LODMinSpeedRatio)/g_LODMaxSpeedRatio, 0.0f, 1.0f);
|
|
bool movingQuicklyAway = !visibleBySniper && (((s32)m_DistanceFromListener2 - (s32)m_DistanceFromListener2LastFrame) * fwTimer::GetInvTimeStep() > 200.0f);
|
|
m_DummyLODValid = false;
|
|
|
|
if(m_ScriptPriority == AUD_VEHICLE_SCRIPT_PRIORITY_MEDIUM)
|
|
{
|
|
mag2 *= 0.5f;
|
|
speedRatioMult = Clamp(speedRatioMult * 2.0f, 0.0f, 1.0f);
|
|
movingQuicklyAway = false;
|
|
}
|
|
else if(m_ScriptPriority == AUD_VEHICLE_SCRIPT_PRIORITY_HIGH)
|
|
{
|
|
mag2 *= 0.33f;
|
|
speedRatioMult = 1.0f;
|
|
movingQuicklyAway = false;
|
|
}
|
|
|
|
// No driver, no revs, disabled? Car is probably just sat stationary so keep it disabled. Personal vehicles can be turned on remotely at any point, so are an exception.
|
|
if(!m_Vehicle->GetDriver() && (!m_Vehicle->m_nVehicleFlags.bEngineOn && m_vehicleEngine.GetState() == audVehicleEngine::AUD_ENGINE_OFF) && !m_IsFocusVehicle && !m_IsPersonalVehicle)
|
|
{
|
|
return AUD_VEHICLE_LOD_DISABLED;
|
|
}
|
|
else if(m_IsFocusVehicle)
|
|
{
|
|
#if __BANK
|
|
if(g_TreatAsDummyCar)
|
|
{
|
|
return AUD_VEHICLE_LOD_DUMMY;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
return AUD_VEHICLE_LOD_REAL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Dummy cars only care about speed. All we're playing is roadnoise-type sounds for them, which is inaudible when stationary, so no point in having a
|
|
// silent car take up a dummy slot.
|
|
if((m_VehicleLOD <= AUD_VEHICLE_LOD_DUMMY || !movingQuicklyAway) && mag2 < (g_DummyRadii[m_CarAudioSettings->VolumeCategory] * sm_DummyRangeScale[GetVehicleQuadrant()] * speedRatioMult))
|
|
{
|
|
m_DummyLODValid = true;
|
|
}
|
|
|
|
f32 desiredVisibilityScalar = 1.0f;
|
|
|
|
if(m_ScriptPriority < AUD_VEHICLE_SCRIPT_PRIORITY_HIGH)
|
|
{
|
|
spdSphere boundSphere;
|
|
m_Vehicle->GetBoundSphere(boundSphere);
|
|
if(!camInterface::IsSphereVisibleInGameViewport(boundSphere.GetV4()))
|
|
{
|
|
// We're not maxing out the submixes, allow vehicles to stay audible even after going off screen
|
|
if(sm_ActivationRangeScale == g_MaxRealRangeScale &&
|
|
(!m_vehicleEngine.IsGranularEngineActive() || sm_GranularActivationRangeScale == g_MaxGranularRangeScale))
|
|
{
|
|
desiredVisibilityScalar = Max(g_OffscreenVisiblityScalar, m_VisibilitySmoother.GetLastValue());
|
|
}
|
|
else
|
|
{
|
|
desiredVisibilityScalar = g_OffscreenVisiblityScalar;
|
|
}
|
|
}
|
|
}
|
|
|
|
f32 visibilityScalar = m_VisibilitySmoother.CalculateValue(desiredVisibilityScalar, fwTimer::GetTimeStep());
|
|
f32 underLoadScalar = 1.0f;
|
|
|
|
if(m_Vehicle->m_Transmission.IsEngineUnderLoad() && fwdSpeedRatio > 0.01f && m_Vehicle->m_Transmission.GetGear() == 1)
|
|
{
|
|
underLoadScalar *= 1.3f;
|
|
}
|
|
|
|
// Cars playing high-rolloff revs can stay real until they finish
|
|
if(m_SportsCarRevsSound || m_SportsCarRevsApplyFactor > 0.0f || m_SportsCarRevsRequested)
|
|
{
|
|
return AUD_VEHICLE_LOD_REAL;
|
|
}
|
|
// Active cars primarily take speed into account, but also a bit of distance - we still want to hear the idle on very close stationary ones
|
|
else if(mag2 < (g_DummyRadii[m_CarAudioSettings->VolumeCategory] * sm_ActivationRangeScale * sm_GranularActivationRangeScale * underLoadScalar * visibilityScalar * ((1.0f - g_LODSpeedBias) + (g_LODSpeedBias * speedRatioMult))))
|
|
{
|
|
if(movingQuicklyAway && m_VehicleLOD != AUD_VEHICLE_LOD_REAL)
|
|
{
|
|
return m_VehicleLOD;
|
|
}
|
|
else
|
|
{
|
|
return AUD_VEHICLE_LOD_REAL;
|
|
}
|
|
}
|
|
else if(m_DummyLODValid)
|
|
{
|
|
return AUD_VEHICLE_LOD_DUMMY;
|
|
}
|
|
else
|
|
{
|
|
return AUD_VEHICLE_LOD_DISABLED;
|
|
}
|
|
}
|
|
}
|
|
|
|
void audCarAudioEntity::StartEngineSounds(const bool UNUSED_PARAM(fadeIn))
|
|
{
|
|
m_EngineStartTime = fwTimer::GetTimeInMilliseconds();
|
|
m_RevsSmoother.CalculateValue(CTransmission::ms_fIdleRevs,m_EngineStartTime);// init revs to idle
|
|
m_EngineEffectWetSmoother.Reset();
|
|
m_EngineEffectWetSmoother.CalculateValue(0.0f,fwTimer::GetTimeStep());
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------
|
|
// audCarAudioEntity::UpdatePlayerCarSpinSounds
|
|
// -------------------------------------------------------------------------------
|
|
void audCarAudioEntity::UpdatePlayerCarSpinSounds(audVehicleVariables* state)
|
|
{
|
|
// Reusing m_DistanceToPlayerLastFrame/m_LastCarByTime as we don't need them for player vehicle
|
|
if(m_IsPlayerVehicle && m_Vehicle->InheritsFromAutomobile())
|
|
{
|
|
const f32 dp = m_Vehicle->GetTransform().GetRoll();
|
|
|
|
if(state->numWheelsTouchingFactor == 0.0f &&
|
|
Sign(dp) != Sign(m_DistanceToPlayerLastFrame) &&
|
|
state->timeInMs - GetLastTimeOnGround() > 200 &&
|
|
m_CachedVehicleVelocity.Mag2() > (25.0f))
|
|
{
|
|
if(m_LastCarByTime + 250 < state->timeInMs)
|
|
{
|
|
audSoundInitParams initParams;
|
|
initParams.TrackEntityPosition = true;
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
const f32 dpChangeRate = Abs(dp - m_DistanceToPlayerLastFrame) * fwTimer::GetInvTimeStep();
|
|
initParams.Volume = audDriverUtil::ComputeDbVolumeFromLinear(g_PlayerAngVelToCarPass.CalculateValue(dpChangeRate));
|
|
CreateAndPlaySound(sm_ExtrasSoundSet.Find(ATSTRINGHASH("PlayerCarSpin", 0x7E61D83A)), &initParams);
|
|
}
|
|
|
|
m_LastCarByTime = state->timeInMs;
|
|
}
|
|
|
|
m_DistanceToPlayerLastFrame = dp;
|
|
}
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------
|
|
// audCarAudioEntity::TriggerSportsCarRevs
|
|
// -------------------------------------------------------------------------------
|
|
void audCarAudioEntity::TriggerSportsCarRevs(SportCarRevsTriggerType triggerType)
|
|
{
|
|
if(m_VehicleLOD == AUD_VEHICLE_LOD_REAL)
|
|
{
|
|
if(!m_SportsCarRevsSound)
|
|
{
|
|
AllocateVehicleVariableBlock();
|
|
CreateAndPlaySound_Persistent(triggerType == REVS_TYPE_JUNCTION? ATSTRINGHASH("SPORTS_REVS_JUNCTION", 0x7EF46601) : ATSTRINGHASH("SPORTS_REVS_PASSBY", 0xA718080A), &m_SportsCarRevsSound);
|
|
m_LastSportsCarRevsTime = fwTimer::GetTimeInMilliseconds();
|
|
m_SportsCarRevsRequested = false;
|
|
|
|
if(m_GranularEngineSettings)
|
|
{
|
|
sm_SportsCarRevsSoundHistory[sm_SportsCarRevsHistoryIndex].soundName = m_GranularEngineSettings->EngineAccel;
|
|
sm_SportsCarRevsSoundHistory[sm_SportsCarRevsHistoryIndex].time = fwTimer::GetTimeInMilliseconds();
|
|
sm_SportsCarRevsHistoryIndex = (sm_SportsCarRevsHistoryIndex + 1) % kSportsCarRevsHistorySize;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_SportsCarRevsRequested = true;
|
|
}
|
|
|
|
m_WasSportsCarRevsCancelled = false;
|
|
m_SportsCarRevsTriggerType = triggerType;
|
|
}
|
|
|
|
void audCarAudioEntity::UpdateCarPassSounds(audVehicleVariables* state)
|
|
{
|
|
// car by wind sounds
|
|
if((m_Vehicle->GetVehicleType() == VEHICLE_TYPE_CAR || m_Vehicle->GetVehicleType() == VEHICLE_TYPE_SUBMARINECAR || m_Vehicle->GetVehicleType() == VEHICLE_TYPE_AMPHIBIOUS_AUTOMOBILE) && !m_IsPlayerVehicle)
|
|
{
|
|
const CVehicle* playerVeh = CGameWorld::FindLocalPlayerVehicle();
|
|
|
|
if(playerVeh)
|
|
{
|
|
static const f32 passbyAttackTime = 0.1f;
|
|
const Vector3 vPlayerVehPosition = VEC3V_TO_VECTOR3(playerVeh->GetTransform().GetPosition()) + (playerVeh->GetVehicleAudioEntity()->GetCachedVelocity() * passbyAttackTime);
|
|
const Vector3 vVehiclePosition = VEC3V_TO_VECTOR3(m_Vehicle->GetTransform().GetPosition()) + (GetCachedVelocity() * passbyAttackTime);
|
|
const f32 distToPlayer2 = (vPlayerVehPosition-vVehiclePosition).Mag2();
|
|
|
|
if(FPIsFinite(distToPlayer2) && distToPlayer2 <= (15.f * 15.f))
|
|
{
|
|
const f32 distToPlayer = Sqrtf(distToPlayer2);
|
|
const f32 distToPlayerDelta = distToPlayer - m_DistanceToPlayerLastFrame;
|
|
|
|
if(state->timeInMs > m_LastCarByTime + 2000 &&
|
|
m_WasInCarByRange &&
|
|
m_DistanceToPlayerDeltaLastFrame != 0.0f &&
|
|
Abs(vPlayerVehPosition.z-vVehiclePosition.z) < 5.f &&
|
|
Sign(m_DistanceToPlayerDeltaLastFrame) != Sign(distToPlayerDelta))
|
|
{
|
|
const f32 relSpeed = (playerVeh->GetVelocity()-m_Vehicle->GetVelocity()).Mag();
|
|
|
|
// Boost the volume slightly when in high speed mode
|
|
const f32 distanceVol = g_DistanceToCarByVol.CalculateValue(distToPlayer);
|
|
const f32 relVol = audDriverUtil::ComputeDbVolumeFromLinear(g_RelSpeedToCarByVol.CalculateValue(relSpeed) * distanceVol) + (2.0f * sm_HighSpeedSceneApplySmoother.GetLastValue());
|
|
|
|
if(relVol > g_SilenceVolume)
|
|
{
|
|
audSoundInitParams initParams;
|
|
initParams.TrackEntityPosition = true;
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
initParams.Volume = relVol;
|
|
|
|
audSound *sound = NULL;
|
|
CreateSound_LocalReference(sm_ExtrasSoundSet.Find(ATSTRINGHASH("VehiclePassBy", 0xD52094B3)), &sound, &initParams);
|
|
|
|
if(sound)
|
|
{
|
|
const f32 boundingVolume = (m_Vehicle->GetBoundingBoxMax() - m_Vehicle->GetBoundingBoxMin()).Mag();
|
|
sound->FindAndSetVariableValue(ATSTRINGHASH("RELATIVE_SPEED", 0xCA2A352A), relSpeed);
|
|
sound->FindAndSetVariableValue(ATSTRINGHASH("BOUNDING_VOLUME", 0x49613F52), boundingVolume);
|
|
|
|
// only want this playing from listener 1 - the car mic
|
|
sound->SetRequestedListenerMask(1);
|
|
sound->SetRequestedDopplerFactor(0.0f);
|
|
sound->PrepareAndPlay();
|
|
|
|
// enable distance attenuation if we're in a cinematic camera
|
|
const camBaseCamera* renderedCamera = camInterface::GetDominantRenderedCamera();
|
|
if(renderedCamera)
|
|
{
|
|
if(renderedCamera->GetClassId() == camCinematicStuntCamera::GetStaticClassId() ||
|
|
renderedCamera->GetClassId() == camCinematicHeliChaseCamera::GetStaticClassId())
|
|
{
|
|
sound->SetRequestedShouldAttenuateOverDistance(AUD_TRISTATE_TRUE);
|
|
}
|
|
}
|
|
|
|
#if __BANK
|
|
if(g_DebugCarPasses)
|
|
{
|
|
grcDebugDraw::Sphere(vVehiclePosition, 3.f, Color32(255,0,0,128), true, 10);
|
|
|
|
carPassHistory history;
|
|
history.vehicleName = GetVehicleModelName();
|
|
history.boundingVolume = boundingVolume;
|
|
history.relativeSpeed = relSpeed;
|
|
history.triggerDistance = distToPlayer;
|
|
sm_CarPassHistory.PushAndGrow(history);
|
|
|
|
if(sm_CarPassHistory.GetCount() > 6)
|
|
{
|
|
sm_CarPassHistory.Delete(0);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
m_LastCarByTime = state->timeInMs;
|
|
m_DistanceToPlayerDeltaLastFrame = m_DistanceToPlayerLastFrame = 0.f;
|
|
}
|
|
|
|
m_DistanceToPlayerLastFrame = distToPlayer;
|
|
|
|
if(!m_WasInCarByRange)
|
|
{
|
|
m_DistanceToPlayerDeltaLastFrame = 0.0f;
|
|
}
|
|
else
|
|
{
|
|
m_DistanceToPlayerDeltaLastFrame = distToPlayerDelta;
|
|
}
|
|
|
|
m_WasInCarByRange = true;
|
|
}
|
|
else
|
|
{
|
|
m_WasInCarByRange = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// Update offroad noises
|
|
// ----------------------------------------------------------------
|
|
void audCarAudioEntity::UpdateOffRoad(audVehicleVariables* state)
|
|
{
|
|
#if __BANK
|
|
if(g_DisableRoadNoise)
|
|
{
|
|
for(s32 i = 0; i < m_Vehicle->GetNumWheels(); i++)
|
|
{
|
|
if(m_WheelOffRoadSounds[i])
|
|
{
|
|
m_WheelOffRoadSounds[i]->StopAndForget();
|
|
}
|
|
}
|
|
|
|
StopAndForgetSounds(m_OffRoadRumbleSound, m_OffRoadRumblePulse);
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
if(m_IsPlayerVehicle && !IsToyCar() && IsReal() && m_Vehicle)
|
|
{
|
|
CVehicleModelInfo* modelInfo = (CVehicleModelInfo *)(m_Vehicle->GetBaseModelInfo());
|
|
|
|
if(modelInfo)
|
|
{
|
|
for(s32 i = 0; i < m_Vehicle->GetNumWheels(); i++)
|
|
{
|
|
s32 wheelId = m_Vehicle->GetWheel(i)->GetHierarchyId();
|
|
|
|
// Only care about the main four wheels
|
|
if(wheelId >= VEH_WHEEL_FIRST_WHEEL && wheelId < VEH_WHEEL_FIRST_WHEEL + 4 && m_LastMaterialIds[i] != ~0U)
|
|
{
|
|
naAssertf(m_LastMaterialIds[i]<(phMaterialMgr::Id)g_audCollisionMaterials.GetCount(), "out of bounds");
|
|
|
|
if(g_audCollisionMaterials[static_cast<u32>(m_LastMaterialIds[i])])
|
|
{
|
|
u32 offRoadSoundHash = g_audCollisionMaterials[static_cast<u32>(m_LastMaterialIds[i])]->OffRoadSound;
|
|
|
|
if(offRoadSoundHash != g_NullSoundHash && offRoadSoundHash == m_WheelOffRoadSoundHashes[i])
|
|
{
|
|
if(!m_WheelOffRoadSounds[i])
|
|
{
|
|
audSoundInitParams initParams;
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
GetCachedWheelPosition(i, initParams.Position, *state);
|
|
initParams.UpdateEntity = true;
|
|
initParams.u32ClientVar = GetWheelSoundUpdateClientVar(i - VEH_WHEEL_FIRST_WHEEL);
|
|
CreateAndPlaySound_Persistent(offRoadSoundHash, &m_WheelOffRoadSounds[i], &initParams);
|
|
}
|
|
}
|
|
else if(m_WheelOffRoadSounds[i])
|
|
{
|
|
m_WheelOffRoadSounds[i]->StopAndForget();
|
|
}
|
|
|
|
m_WheelOffRoadSoundHashes[i] = offRoadSoundHash;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Only doing this on real cars as material settings will always be tarmac on dummy or lower
|
|
if(IsReal() && !IsToyCar())
|
|
{
|
|
if(m_CachedMaterialSettings && m_CachedMaterialSettings->OffRoadRumbleSound != g_NullSoundHash && state->numWheelsTouching > 0)
|
|
{
|
|
if(m_OffRoadRumbleSound && m_CachedMaterialSettings->OffRoadRumbleSound != m_PrevOffRoadRumbleHash)
|
|
{
|
|
StopAndForgetSounds(m_OffRoadRumbleSound);
|
|
}
|
|
|
|
if(!m_OffRoadRumbleSound)
|
|
{
|
|
audSoundInitParams initParams;
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
initParams.TrackEntityPosition = true;
|
|
initParams.UpdateEntity = true;
|
|
initParams.u32ClientVar = AUD_VEHICLE_SOUND_UNKNOWN;
|
|
initParams.Volume = m_CarAudioSettings->OffRoadRumbleSoundVolume/100.0f;
|
|
CreateAndPlaySound_Persistent(m_CachedMaterialSettings->OffRoadRumbleSound, &m_OffRoadRumbleSound, &initParams);
|
|
m_PrevOffRoadRumbleHash = m_CachedMaterialSettings->OffRoadRumbleSound;
|
|
|
|
if(m_OffRoadRumbleSound && m_IsPlayerVehicle && !m_OffRoadRumblePulse && audNorthAudioEngine::ShouldTriggerPulseHeadset())
|
|
{
|
|
CreateAndPlaySound_Persistent(g_FrontendAudioEntity.GetPulseHeadsetSounds().Find(ATSTRINGHASH("OffRoadRumble", 0x1ADE4D12)), &m_OffRoadRumblePulse);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
StopAndForgetSounds(m_OffRoadRumbleSound);
|
|
}
|
|
|
|
|
|
// Only play rumble pulse while the real rumble is playing on the player vehicle
|
|
if(!m_IsPlayerVehicle || !audNorthAudioEngine::ShouldTriggerPulseHeadset() || !m_OffRoadRumbleSound)
|
|
{
|
|
StopAndForgetSounds(m_OffRoadRumblePulse);
|
|
}
|
|
}
|
|
}
|
|
|
|
void audCarAudioEntity::UpdateSuspension(audVehicleVariables* state)
|
|
{
|
|
f32 cinematicOffsetVol = 0.f;
|
|
|
|
if(m_IsPlayerVehicle || AreHydraulicsActive())
|
|
{
|
|
#if __BANK
|
|
if(g_MuteSuspension)
|
|
{
|
|
for(s32 i = 0; i < m_Vehicle->GetNumWheels(); i++)
|
|
{
|
|
if(m_SuspensionSounds[i])
|
|
{
|
|
m_SuspensionSounds[i]->StopAndForget();
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
#endif
|
|
const u32 currentTime = fwTimer::GetTimeInMilliseconds();
|
|
bool twoWheelLanding = false;
|
|
bool hydraulicsActive = AreHydraulicsActive();
|
|
|
|
// suspension sounds
|
|
for(s32 i = 0; i < m_Vehicle->GetNumWheels(); i++)
|
|
{
|
|
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
|
|
|
|
bool ignoreWheel = false;
|
|
|
|
if(m_Vehicle->m_nVehicleFlags.bIsAsleep ||
|
|
(m_Vehicle->InheritsFromSubmarineCar() && !((CSubmarineCar*)m_Vehicle)->AreWheelsActive()) ||
|
|
((GetVehicleModelNameHash() == ATSTRINGHASH("DELUXO", 0x586765FB) || ATSTRINGHASH("OPPRESSOR2", 0x7B54A9D3)) && m_Vehicle->GetSpecialFlightModeRatio() > 0.f))
|
|
{
|
|
// ignore physics if asleep or the wheel isn't touching anything
|
|
compressionChange = 0.0f;
|
|
ignoreWheel = true;
|
|
}
|
|
|
|
const f32 absCompressionChange = Abs(compressionChange);
|
|
f32 damageFactor = 1.0f - m_Vehicle->GetWheel(i)->GetSuspensionHealth() * SUSPENSION_HEALTH_DEFAULT_INV;
|
|
f32 ratio = (absCompressionChange - m_CarAudioSettings->MinSuspCompThresh) / (m_CarAudioSettings->MaxSuspCompThres - m_CarAudioSettings->MinSuspCompThresh - (damageFactor*2.f));
|
|
|
|
// Exaggerate the suspension travel on rougher surfaces
|
|
if(m_CachedMaterialSettings)
|
|
{
|
|
ratio *= (1.0f + m_CachedMaterialSettings->Roughness);
|
|
}
|
|
|
|
ratio = Clamp(ratio, 0.0f,1.0f);
|
|
|
|
// suspension bottoming out
|
|
CWheel* wheel = m_Vehicle->GetWheel(i);
|
|
|
|
if(wheel)
|
|
{
|
|
u32 hierarchyID = wheel->GetHierarchyId();
|
|
|
|
if(hierarchyID >= VEH_WHEEL_LF && hierarchyID <= VEH_WHEEL_RR)
|
|
{
|
|
if(!ignoreWheel && wheel->GetCompression() + wheel->GetWheelRadiusIncBurst() >= wheel->GetSuspensionLength())
|
|
{
|
|
m_LastBottomOutTime[i] = currentTime;
|
|
|
|
s32 oppositeWheel = m_Vehicle->GetWheel(i)->GetOppositeWheelIndex();
|
|
|
|
if(oppositeWheel >= 0)
|
|
{
|
|
if(currentTime - m_LastBottomOutTime[oppositeWheel] < 100)
|
|
{
|
|
if(currentTime - m_LastTimeInAir < 250 &&
|
|
m_CachedVehicleVelocity.Mag() > 5.0f) // Using velocity rather than state->fwdspeed so spinning the car doesn't affect this
|
|
{
|
|
GetCollisionAudio().TriggerJumpLand(5.f);
|
|
|
|
if(!hydraulicsActive && !IsToyCar())
|
|
{
|
|
GetCollisionAudio().TriggerJumpLandScrape();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// On a 4-wheel vehicle, detect when the player has righted the vehicle after being stationary upside down, and play a clunk then
|
|
if(m_Vehicle->GetNumWheels() == 4)
|
|
{
|
|
if(currentTime - m_LastTimeTwoWheeling < 250 &&
|
|
state->numWheelsTouching == 4)
|
|
{
|
|
s32 frontRearWheel = VEH_INVALID_ID;
|
|
|
|
switch(hierarchyID)
|
|
{
|
|
case VEH_WHEEL_LF:
|
|
frontRearWheel = VEH_WHEEL_LR;
|
|
break;
|
|
case VEH_WHEEL_LR:
|
|
frontRearWheel = VEH_WHEEL_LF;
|
|
break;
|
|
case VEH_WHEEL_RF:
|
|
frontRearWheel = VEH_WHEEL_RR;
|
|
break;
|
|
case VEH_WHEEL_RR:
|
|
frontRearWheel = VEH_WHEEL_RF;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
bool shouldTrigger = true;
|
|
|
|
if(g_ReflectionsAudioEntity.IsStuntTunnelMaterial(GetMainWheelMaterial()))
|
|
{
|
|
if(state->fwdSpeedAbs > 5.f)
|
|
{
|
|
shouldTrigger = false;
|
|
}
|
|
}
|
|
|
|
if(shouldTrigger && frontRearWheel >= 0)
|
|
{
|
|
if(currentTime - m_LastBottomOutTime[frontRearWheel - VEH_WHEEL_FIRST_WHEEL] < 100)
|
|
{
|
|
if(!m_Vehicle->InheritsFromAmphibiousQuadBike() || ((CAmphibiousQuadBike*)m_Vehicle)->IsWheelTransitionFinished())
|
|
{
|
|
GetCollisionAudio().TriggerJumpLand(5.f);
|
|
|
|
if(!hydraulicsActive && !IsToyCar())
|
|
{
|
|
GetCollisionAudio().TriggerJumpLandScrape();
|
|
}
|
|
|
|
twoWheelLanding = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
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(cinematicOffsetVol + audDriverUtil::ComputeDbVolumeFromLinear(sm_SuspensionVolCurve.CalculateValue(ratio)));
|
|
Vector3 pos;
|
|
GetCachedWheelPosition(i, pos, *state);
|
|
m_SuspensionSounds[i]->SetRequestedPosition(pos);
|
|
}
|
|
}
|
|
|
|
if(absCompressionChange > m_CarAudioSettings->MinSuspCompThresh)
|
|
{
|
|
if(!m_SuspensionSounds[i])
|
|
{
|
|
// trigger a suspension sound
|
|
u32 soundHash;
|
|
audSoundInitParams initParams;
|
|
initParams.UpdateEntity = true;
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
GetCachedWheelPosition(i, initParams.Position, *state);
|
|
initParams.Volume = cinematicOffsetVol + audDriverUtil::ComputeDbVolumeFromLinear(sm_SuspensionVolCurve.CalculateValue(ratio));
|
|
|
|
if(hydraulicsActive)
|
|
{
|
|
audSoundSet hydraulicSuspensionSoundSet;
|
|
hydraulicSuspensionSoundSet.Init(GetVehicleHydraulicsSoundSetName());
|
|
|
|
if(hydraulicSuspensionSoundSet.IsInitialised())
|
|
{
|
|
audMetadataRef hydraulicRef = hydraulicSuspensionSoundSet.Find(compressionChange > 0 ? ATSTRINGHASH("Hydraulic_Suspension_Down", 0xBED584C) : ATSTRINGHASH("Hydraulic_Suspension_Up", 0x95B33F3B));
|
|
|
|
if(hydraulicRef != g_NullSoundRef)
|
|
{
|
|
CreateAndPlaySound_Persistent(hydraulicRef, &m_SuspensionSounds[i], &initParams);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(!m_SuspensionSounds[i])
|
|
{
|
|
if(compressionChange > 0)
|
|
{
|
|
soundHash = m_CarAudioSettings->SuspensionDown;
|
|
}
|
|
else
|
|
{
|
|
soundHash = m_CarAudioSettings->SuspensionUp;
|
|
}
|
|
|
|
|
|
CreateAndPlaySound_Persistent(soundHash, &m_SuspensionSounds[i], &initParams);
|
|
}
|
|
}
|
|
|
|
#if GTA_REPLAY
|
|
if(!CReplayMgr::IsEditModeActive())
|
|
#endif
|
|
{
|
|
// For big suspension compression on stairs, trigger a tyre bump
|
|
if(compressionChange > 0 && wheel->GetTyreHealth() > 0.0f && !IsMonsterTruck() && !IsToyCar() && !HydraulicsModifiedRecently())
|
|
{
|
|
if(m_OnStairs || m_WasOnStairs)
|
|
{
|
|
u32 soundName = m_Vehicle->InheritsFromBike() ? ATSTRINGHASH("TyreBumpStairsBike", 0xB0B6D726) : ATSTRINGHASH("TyreBumpStairs", 0x9050DECD);
|
|
audSoundInitParams initParams;
|
|
initParams.UpdateEntity = true;
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
GetCachedWheelPosition(i, initParams.Position, *state);
|
|
CreateAndPlaySound(sm_ExtrasSoundSet.Find(soundName), &initParams);
|
|
|
|
#if GTA_REPLAY
|
|
if(CReplayMgr::ShouldRecord())
|
|
{
|
|
REPLAY_ONLY(CReplayMgr::ReplayRecordSound(sm_ExtrasSoundSet.GetNameHash(), soundName, &initParams, m_Vehicle));
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(twoWheelLanding && !hydraulicsActive && !IsToyCar() && !IsGoKart())
|
|
{
|
|
if(!m_Vehicle->InheritsFromAmphibiousQuadBike() || ((CAmphibiousQuadBike*)m_Vehicle)->IsWheelTransitionFinished())
|
|
{
|
|
// Two wheel landings always get a fair amount of volume so that they play when flipping the car after being upside down
|
|
f32 volumeLin = Max(0.75f, state->fwdSpeedRatio);
|
|
audMetadataRef clatterSoundRef = sm_ClatterSoundSet.Find(ATSTRINGHASH("Detailed", 0xDCE667E1));
|
|
TriggerClatter(clatterSoundRef, volumeLin);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------
|
|
// Convert the car from dummy
|
|
// -------------------------------------------------------------------------------
|
|
void audCarAudioEntity::ConvertFromDummy()
|
|
{
|
|
m_vehicleEngine.ConvertFromDummy();
|
|
m_ThrottleBlipTimer = 0;
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------
|
|
// Convert the car to dummy
|
|
// -------------------------------------------------------------------------------
|
|
void audCarAudioEntity::ConvertToDummy()
|
|
{
|
|
m_vehicleEngine.ConvertToDummy();
|
|
|
|
// These sounds are all updated in UpdateBrakes, which is for real cars only
|
|
StopAndForgetSoundsContinueUpdating(m_DiscBrakeSqueel, m_BrakeReleaseSound, m_WindFastSound, m_OffRoadRumbleSound, m_OffRoadRumblePulse, m_WooWooSound);
|
|
for(u32 loop = 0; loop < NUM_VEH_CWHEELS_MAX; loop++)
|
|
{
|
|
StopAndForgetSoundsContinueUpdating(m_WheelGrindLoops[loop], m_TyreDamageLoops[loop]);
|
|
}
|
|
|
|
if(m_RevsBlipSound)
|
|
{
|
|
m_RevsBlipSound->StopAndForget();
|
|
SetEntityVariable(ATSTRINGHASH("fakethrottle", 0xEB27990), 0.0f);
|
|
SetEntityVariable(ATSTRINGHASH("fakerevs", 0xCEB98BEB), 0.0f);
|
|
SetEntityVariable(ATSTRINGHASH("usefakeengine", 0x91DF7F97), 0.0f);
|
|
}
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------
|
|
// Convert the car to super dummy
|
|
// -------------------------------------------------------------------------------
|
|
void audCarAudioEntity::ConvertToSuperDummy()
|
|
{
|
|
ConvertToDummy();
|
|
StopAndForgetSounds(m_DamageTyreScrapeSound, m_DamageTyreScrapeTurnSound, m_HydraulicSuspensionInputLoop, m_HydraulicSuspensionAngleLoop);
|
|
StopAndForgetSounds(m_WaterTurbulenceSound, m_BankSpray, m_GliderSound, m_SpecialFlightModeSound, m_ToyCarEngineLoop);
|
|
|
|
for(u32 loop = 0; loop < g_NumDamageLayersPerCar; loop++)
|
|
{
|
|
if(m_EngineDamageLayers[loop])
|
|
{
|
|
m_EngineDamageLayers[loop]->StopAndForget(true);
|
|
}
|
|
}
|
|
|
|
for(u32 loop = 0; loop < NUM_VEH_CWHEELS_MAX; loop++)
|
|
{
|
|
StopAndForgetSounds(m_WheelOffRoadSounds[loop], m_SuspensionSounds[loop]);
|
|
m_WheelOffRoadSoundHashes[loop] = g_NullSoundHash;
|
|
}
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------
|
|
// Convert the car to disabled
|
|
// -------------------------------------------------------------------------------
|
|
void audCarAudioEntity::ConvertToDisabled()
|
|
{
|
|
ConvertToSuperDummy();
|
|
|
|
// Stop the engine cooling sounds
|
|
m_vehicleEngine.ConvertToDisabled();
|
|
StopAndForgetSounds(m_SubmarineTransformSound);
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------
|
|
// Populate the car variables struct
|
|
// -------------------------------------------------------------------------------
|
|
void audCarAudioEntity::PopulateCarAudioVariables(audVehicleVariables* state)
|
|
{
|
|
PF_FUNC(PopulateVariables);
|
|
CTransmission* transmission = &m_Vehicle->m_Transmission;
|
|
|
|
if(m_IsInAmphibiousBoatMode && m_Vehicle->GetSecondTransmission())
|
|
{
|
|
transmission = m_Vehicle->GetSecondTransmission();
|
|
}
|
|
|
|
naAssertf(m_Vehicle, "m_vehicle must be valid, about to access a null ptr...");
|
|
f32 revsSmoothIncreaseScalar = 1.0f + (m_CarAudioSettings->AdditionalRevsIncreaseSmoothing * 0.01f);
|
|
f32 revsSmoothDecreaseScalar = 1.0f;
|
|
|
|
u32 timeSinceGearChange = 0u;
|
|
if(m_vehicleEngine.HasBeenInitialised())
|
|
{
|
|
timeSinceGearChange = state->timeInMs - m_vehicleEngine.GetTransmission()->GetLastGearChangeTimeMs();
|
|
}
|
|
|
|
#if __BANK
|
|
if(audNorthAudioEngine::GetMetadataManager().IsRAVEConnected())
|
|
{
|
|
SetupVolumeCones();
|
|
}
|
|
#endif // __BANK
|
|
|
|
state->pitchRatio = 1.0f;
|
|
state->gear = transmission->GetGear();
|
|
state->gasPedal = Abs(transmission->GetThrottle());
|
|
state->clutchRatio = transmission->GetClutchRatio();
|
|
|
|
if(!m_IsFocusVehicle && state->fwdSpeedAbs > 1.0f)
|
|
{
|
|
state->gasPedal = 1.0f;
|
|
}
|
|
|
|
if(m_Vehicle->GetOwnedBy()==ENTITY_OWNEDBY_CUTSCENE && state->fwdSpeedAbs > 0.0f)
|
|
{
|
|
state->gasPedal = 1.0f;
|
|
}
|
|
|
|
#if GTA_REPLAY
|
|
if(CReplayMgr::IsEditModeActive())
|
|
{
|
|
state->rawRevs = m_ReplayRevs;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
if(m_IsInAmphibiousBoatMode)
|
|
{
|
|
if(m_Vehicle->GetDriver() && (!m_Vehicle->GetDriver()->IsPlayer() || g_TreatAllBoatsAsNPCs) && !IsSubmersible() && m_Vehicle->m_nVehicleFlags.bEngineOn)
|
|
{
|
|
// AI controlled boat - fake the revs based on fwd speed
|
|
if(!m_Vehicle->GetIsJetSki() || state->fwdSpeed < 2.5f || m_Vehicle->m_nVehicleFlags.bIsRacing)
|
|
{
|
|
state->rawRevs = Clamp(state->fwdSpeed * 0.1f, 0.2f, 0.85f);
|
|
m_FakeOutOfWaterTimer = 0.0f;
|
|
m_FakeOutOfWater = false;
|
|
}
|
|
else
|
|
{
|
|
f32 fakeRevs = Clamp(state->fwdSpeed * 0.14f, 0.2f, 0.7f);
|
|
f32 baseFakeRevs = Max(fakeRevs - audEngineUtil::GetRandomNumberInRange(g_FakeRevsOffsetBelow * 0.5f, g_FakeRevsOffsetBelow), 0.2f);
|
|
f32 maxFakeRevs = Min(fakeRevs + audEngineUtil::GetRandomNumberInRange(g_FakeRevsOffsetAbove * 0.5f, g_FakeRevsOffsetAbove), 0.8f);
|
|
|
|
f32 fakeRevsTarget = m_WasHighFakeRevs? maxFakeRevs : baseFakeRevs;
|
|
m_FakeRevsSmoother.SetBounds(baseFakeRevs, maxFakeRevs);
|
|
state->rawRevs = m_FakeRevsSmoother.CalculateValue(fakeRevsTarget, state->timeInMs);
|
|
|
|
if(m_WasHighFakeRevs)
|
|
{
|
|
state->gasPedal = 1.0f;
|
|
}
|
|
else
|
|
{
|
|
state->gasPedal = 0.0f;
|
|
}
|
|
|
|
if(state->rawRevs == fakeRevsTarget)
|
|
{
|
|
m_FakeRevsHoldTime -= fwTimer::GetTimeStep();
|
|
|
|
if(m_FakeRevsHoldTime < 0.0f)
|
|
{
|
|
if(m_WasHighFakeRevs)
|
|
{
|
|
m_WasHighFakeRevs = false;
|
|
m_FakeRevsHoldTime = audEngineUtil::GetRandomNumberInRange(g_FakeRevsMinHoldTimeMin, g_FakeRevsMinHoldTimeMax);
|
|
}
|
|
else
|
|
{
|
|
m_WasHighFakeRevs = true;
|
|
m_FakeRevsHoldTime = audEngineUtil::GetRandomNumberInRange(g_FakeRevsMaxHoldTimeMin, g_FakeRevsMaxHoldTimeMax);
|
|
}
|
|
|
|
m_FakeRevsSmoother.SetRates((1.0f/g_FakeRevsIncreaseRateBase) * audEngineUtil::GetRandomNumberInRange(1.0f, g_FakeRevsIncreaseRateScale), (1.0f/g_FakeRevsDecreaseRateBase) * audEngineUtil::GetRandomNumberInRange(1.0f, g_FakeRevsDecreaseRateScale));
|
|
}
|
|
}
|
|
|
|
if(state->fwdSpeed > 5.0f && m_DistanceFromListener2LastFrame > g_FakeWaveHitDistanceSq)
|
|
{
|
|
m_FakeOutOfWaterTimer -= fwTimer::GetTimeStep();
|
|
|
|
if(m_FakeOutOfWaterTimer < 0.0f)
|
|
{
|
|
m_FakeOutOfWater = !m_FakeOutOfWater;
|
|
|
|
if(m_FakeOutOfWater)
|
|
{
|
|
m_FakeOutOfWaterTimer = audEngineUtil::GetRandomNumberInRange(g_FakeOutOfWaterMinTime, g_FakeOutOfWaterMaxTime);
|
|
}
|
|
else
|
|
{
|
|
m_FakeOutOfWaterTimer = audEngineUtil::GetRandomNumberInRange(g_FakeInWaterMinTime, g_FakeInWaterMaxTime);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_FakeOutOfWaterTimer = 0.0f;
|
|
m_FakeOutOfWater = false;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
state->rawRevs = F32_VerifyFinite(transmission->GetRevRatio());
|
|
m_FakeOutOfWaterTimer = 0.0f;
|
|
m_FakeOutOfWater = false;
|
|
}
|
|
|
|
// Don't do this on submarine cars, mutes engine if you beach them on dry land
|
|
if(m_Vehicle->GetDriver() && !m_Vehicle->InheritsFromSubmarineCar())
|
|
{
|
|
f32 filterFactor = 0.2f;
|
|
f32 desiredRevsMultiplier = 1.0f;
|
|
|
|
if(m_OutOfWaterTimer > 0.0f)
|
|
{
|
|
desiredRevsMultiplier = audBoatAudioEntity::sm_BoatAirTimeToRevsMultiplier.CalculateValue(m_OutOfWaterTimer);
|
|
desiredRevsMultiplier *= Min(state->fwdSpeed * 0.5f, 1.0f);
|
|
}
|
|
|
|
m_OutOfWaterRevsMultiplier = (desiredRevsMultiplier * filterFactor) + (m_OutOfWaterRevsMultiplier * (1.0f - filterFactor));
|
|
state->rawRevs *= m_OutOfWaterRevsMultiplier;
|
|
}
|
|
|
|
state->granularEnginePitchOffset = static_cast<s32>(audBoatAudioEntity::sm_BoatAirTimeToPitch.CalculateValue(m_OutOfWaterTimer));
|
|
|
|
REPLAY_ONLY(m_ReplayRevs = state->rawRevs;)
|
|
}
|
|
else
|
|
{
|
|
f32 loadRevsMult = 1.0f;
|
|
f32 desiredRawRevs = 0.0f;
|
|
u32 gearChangeSmoothingTimeMS = m_CarAudioSettings->AdditionalGearChangeSmoothingTime;
|
|
|
|
if(state->gear > 1 && timeSinceGearChange < gearChangeSmoothingTimeMS)
|
|
{
|
|
revsSmoothIncreaseScalar += ((m_CarAudioSettings->AdditionalGearChangeSmoothing * 0.01f) * Max(1.0f - (timeSinceGearChange/(f32)gearChangeSmoothingTimeMS), 0.0f));
|
|
}
|
|
|
|
// Vehicle is under load and moving
|
|
if(transmission->IsEngineUnderLoad() && state->gasPedal > 0.0f && state->fwdSpeedAbs > 0.1f)
|
|
{
|
|
// Scale up the revs - more in lower gears
|
|
f32 gearFactor = Max(1.0f - transmission->GetGear()/4.0f, 0.0f);
|
|
loadRevsMult = 1.0f + (0.25f * Min(state->fwdSpeedRatio/0.02f, 1.0f) * gearFactor);
|
|
desiredRawRevs = Min((F32_VerifyFinite(transmission->GetRevRatio()) * loadRevsMult), 1.0f);
|
|
|
|
// Apply a second revs value directly linked to throttle (but reduced as the gears increase)
|
|
if(m_IsPlayerDrivingVehicle)
|
|
{
|
|
f32 gasPedalGearScalar = 1.0f - ((transmission->GetGear() - 1) * 0.2f);
|
|
gasPedalGearScalar *= transmission->GetClutchRatio();
|
|
|
|
// Take the max of the two values and smooth out the increase a bit to prevent revs jumping too quickly
|
|
desiredRawRevs = Max(state->gasPedal * gasPedalGearScalar, desiredRawRevs);
|
|
}
|
|
|
|
revsSmoothIncreaseScalar += g_UnderLoadRevsSmootherScalar;
|
|
}
|
|
else
|
|
{
|
|
desiredRawRevs = Clamp((F32_VerifyFinite(transmission->GetRevRatio()) + m_MaxSpeedRevsAddition + (0.075f * m_LeanRatio)), CTransmission::ms_fIdleRevs, 1.0f);
|
|
|
|
// When coming out of sports car revs we might be at a totally different rev ratio, so smooth out a bit
|
|
if(!m_IsPlayerVehicle && !m_SportsCarRevsSound && m_SportsCarRevsApplyFactor > 0.0f)
|
|
{
|
|
if(m_WasSportsCarRevsCancelled)
|
|
{
|
|
revsSmoothIncreaseScalar = 2.0f;
|
|
revsSmoothDecreaseScalar = 2.0f;
|
|
}
|
|
else
|
|
{
|
|
revsSmoothIncreaseScalar = 3.0f;
|
|
revsSmoothDecreaseScalar = 3.0f;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(m_Vehicle->IsRocketBoosting())
|
|
{
|
|
state->gasPedal = 1.f;
|
|
desiredRawRevs = 1.f;
|
|
}
|
|
|
|
if(ShouldForceEngineOff())
|
|
{
|
|
state->gasPedal = 0.f;
|
|
desiredRawRevs = 0.f;
|
|
}
|
|
|
|
f32 filterFactor = 1.0f;
|
|
|
|
if(m_Vehicle->GetOwnedBy()==ENTITY_OWNEDBY_CUTSCENE)
|
|
{
|
|
filterFactor = 0.1f;
|
|
}
|
|
else if(state->numWheelsTouchingFactor == 1.0f &&
|
|
desiredRawRevs > m_RevsLastFrame &&
|
|
transmission->GetGear() > 2 &&
|
|
m_RevsLastFrame < 0.98f)
|
|
{
|
|
if(m_Vehicle->GetHandBrake())
|
|
{
|
|
filterFactor = 0.2f;
|
|
}
|
|
else
|
|
{
|
|
filterFactor = 0.1f;
|
|
}
|
|
}
|
|
|
|
state->rawRevs = (m_RevsLastFrame * (1.0f - filterFactor)) + (filterFactor * desiredRawRevs);
|
|
m_RevsLastFrame = state->rawRevs;
|
|
|
|
REPLAY_ONLY(m_ReplayRevs = state->rawRevs;)
|
|
|
|
if(m_CarAudioSettings->EngineType == HYBRID && transmission->GetNumGears() == 1)
|
|
{
|
|
state->rawRevs = 0.2f + (0.8f * state->fwdSpeedRatio);
|
|
}
|
|
|
|
if(!m_IsPlayerVehicle && m_Vehicle->GetDriver() && !m_Vehicle->GetDriver()->IsNetworkPlayer() && state->rawRevs > CTransmission::ms_fIdleRevs && !CVehicleRecordingMgr::IsPlaybackGoingOnForCar(m_Vehicle) && m_Vehicle->GetOwnedBy()!=ENTITY_OWNEDBY_CUTSCENE)
|
|
{
|
|
state->rawRevs = Clamp(state->rawRevs * g_NPCVehicleRevsScalar, 0.0f, 1.0f);
|
|
}
|
|
}
|
|
}
|
|
|
|
#if __BANK
|
|
if(g_EngineVolumeCaptureActive && (sm_VolumeCaptureState == State_CapturingAccel || sm_VolumeCaptureState == State_CapturingAccelModded))
|
|
{
|
|
state->gasPedal = sm_VolumeCaptureThrottle;
|
|
state->rawRevs = sm_VolumeCaptureRevs;
|
|
state->gear = 1;
|
|
}
|
|
#endif
|
|
|
|
f32 entityVariableThrottle = 0.0f;
|
|
f32 entityVariableRevs = 0.0f;
|
|
bool useFakeEngine = false;
|
|
|
|
if(HasEntityVariableBlock())
|
|
{
|
|
entityVariableThrottle = GetEntityVariableValue(ATSTRINGHASH("fakethrottle", 0xEB27990));
|
|
entityVariableRevs = GetEntityVariableValue(ATSTRINGHASH("fakerevs", 0xCEB98BEB));
|
|
|
|
// Reduce this each frame so that that the behaviour gets canceled even if a sound forgets to do so
|
|
f32 fakeEngineFactor = GetEntityVariableValue(ATSTRINGHASH("usefakeengine", 0x91DF7F97));
|
|
SetEntityVariable(ATSTRINGHASH("usefakeengine", 0x91DF7F97), Clamp(fakeEngineFactor - 0.1f, 0.0f, 1.0f));
|
|
useFakeEngine = fakeEngineFactor > 0.1f;
|
|
|
|
if(useFakeEngine && m_WasPlayingStartupSound)
|
|
{
|
|
m_FakeEngineStartupRevs = true;
|
|
}
|
|
}
|
|
|
|
if(useFakeEngine)
|
|
{
|
|
state->gasPedal = entityVariableThrottle;
|
|
state->rawRevs = entityVariableRevs;
|
|
}
|
|
|
|
// Reversing flag (not the same as being in reverse gear) can be used to determine whether the vehicle is
|
|
// intentionally moving backwards, as opposed to going backwards because it did a big drift/spin
|
|
if(state->gear == 0 && state->fwdSpeed < 0.0f && state->numWheelsTouching > 0 && !m_Vehicle->GetHandBrake())
|
|
{
|
|
m_IsReversing = true;
|
|
}
|
|
else if(m_IsReversing && ((state->fwdSpeed >= 0.0f && state->gear > 0) || state->numWheelsTouching == 0))
|
|
{
|
|
m_IsReversing = false;
|
|
}
|
|
|
|
if(m_IsReversing)
|
|
{
|
|
state->rawRevs = Clamp(state->rawRevs, 0.0f, 0.8f);
|
|
}
|
|
|
|
if(m_vehicleEngine.IsAutoShutOffSystemEngaged())
|
|
{
|
|
state->rawRevs = CTransmission::ms_fIdleRevs;
|
|
}
|
|
|
|
if(m_Vehicle->GetVehicleType() == VEHICLE_TYPE_BIKE && !useFakeEngine)
|
|
{
|
|
if(state->gear == 0)
|
|
{
|
|
// don't let bikes rev up in reverse
|
|
state->rawRevs = CTransmission::ms_fIdleRevs;
|
|
state->gasPedal = 0.f;
|
|
}
|
|
}
|
|
#if __BANK
|
|
if(g_OverrideSim && ((m_Vehicle == g_AudioDebugEntity) || (!g_AudioDebugEntity && m_IsPlayerVehicle)))
|
|
{
|
|
state->gasPedal = g_OverriddenThrottle;
|
|
state->rawRevs = g_OverriddenRevs;
|
|
}
|
|
#endif
|
|
|
|
state->engineConeAtten = m_HasInitialisedVolumeCones? m_EngineVolumeCone.ComputeAttenuation(m_Vehicle->GetMatrix()) : 0.0f;
|
|
state->exhaustConeAtten = m_HasInitialisedVolumeCones? m_ExhaustVolumeCone.ComputeAttenuation(m_Vehicle->GetMatrix()) : 0.0f;
|
|
|
|
if(g_RevsBoostEffectEnabled && state->gear == transmission->GetNumGears())
|
|
{
|
|
// Fade out the engine coning as we reach top speed
|
|
state->engineConeAtten *= (1.0f - m_MaxSpeedPitchFactor);
|
|
}
|
|
|
|
#if __BANK
|
|
if(g_DisableConing)
|
|
{
|
|
state->engineConeAtten = 0.0f;
|
|
state->exhaustConeAtten = 0.0f;
|
|
}
|
|
#endif
|
|
|
|
// if in reverse then use the wheel brake force since the brake pedal isnt active
|
|
if(state->gear == 0)
|
|
{
|
|
f32 force = 0.0f;
|
|
|
|
if(m_Vehicle->GetDriver() && !m_Vehicle->GetDriver()->IsBeingJackedFromVehicle())
|
|
{
|
|
for(s32 i = 0; i < m_Vehicle->GetNumWheels(); i++)
|
|
{
|
|
CWheel *wheel = m_Vehicle->GetWheel(i);
|
|
force = Max(force, wheel->GetBrakeForce());
|
|
}
|
|
}
|
|
|
|
state->brakePedal = Clamp(force*2.0f, 0.0f, 1.0f);
|
|
state->speedForBrakes = -1.5f * state->fwdSpeed;
|
|
}
|
|
else
|
|
{
|
|
state->speedForBrakes = state->fwdSpeed;
|
|
state->brakePedal = m_Vehicle->GetBrake();
|
|
}
|
|
if(Abs(state->fwdSpeed) < 0.05f)
|
|
{
|
|
state->speedForBrakes = 0.0f;
|
|
}
|
|
|
|
if(m_Vehicle->m_nVehicleFlags.bIsAsleep)
|
|
{
|
|
// override sim values if physics is sleeping
|
|
state->speedForBrakes = 0.0f;
|
|
}
|
|
|
|
if(IsPlayerDrivingVehicle())
|
|
{
|
|
m_ThrottleSmoother.SetRates(0.005f,0.005f);
|
|
}
|
|
else
|
|
{
|
|
m_ThrottleSmoother.SetRates(0.0025f,0.0025f);
|
|
}
|
|
|
|
// Increase revs a bit for going up hill
|
|
if(!m_IsPlayerVehicle || HasHeavyRoadNoise())
|
|
{
|
|
const f32 currentSlope = m_Vehicle->GetTransform().GetB().GetZf();// Positive = uphill.
|
|
const f32 slopeGasMultiplierForward = 1.0f + (0.2f * Clamp(currentSlope/0.2f, 0.0f, 1.0f)) * Clamp(state->fwdSpeedRatio * 20.0f, 0.0f, 1.0f) * state->numWheelsTouchingFactor;
|
|
state->rawRevs *= slopeGasMultiplierForward;
|
|
}
|
|
|
|
if(m_WasPlayingStartupSound && !m_StartUpRevsSound)
|
|
{
|
|
if(HasEntityVariableBlock())
|
|
{
|
|
SetEntityVariable(ATSTRINGHASH("fakethrottle", 0xEB27990), 0.0f);
|
|
SetEntityVariable(ATSTRINGHASH("fakerevs", 0xCEB98BEB), 0.0f);
|
|
SetEntityVariable(ATSTRINGHASH("usefakeengine", 0x91DF7F97), 0.0f);
|
|
}
|
|
|
|
m_WasPlayingStartupSound = false;
|
|
}
|
|
|
|
if(m_vehicleEngine.GetState() == audVehicleEngine::AUD_ENGINE_STARTING)
|
|
{
|
|
// if the player starts acelerating then interrupt starting behaviour
|
|
if((m_Vehicle->GetThrottle()>0.1f || state->fwdSpeed<-0.1f) && m_IsPlayerVehicle)
|
|
{
|
|
// force the throttle to be 0 so it'll smooth up
|
|
m_ThrottleSmoother.Reset();
|
|
m_ThrottleSmoother.CalculateValue(0.0f, state->timeInMs);
|
|
StopAndForgetSounds(m_StartUpRevsSound);
|
|
}
|
|
else
|
|
{
|
|
if(m_vehicleEngine.IsGranularEngineActive())
|
|
{
|
|
m_RevsSmoother.SetRates(g_RevMaxIncreaseRate / 1000.f,g_RevMaxDecreaseRate / 1000.f);
|
|
|
|
if(!m_StartUpRevsSound && !m_HasPlayedStartupSequence)
|
|
{
|
|
// Don't kick off the fake revs until the real ones have started
|
|
if(m_vehicleEngine.GetGranularEngine()->AreAnySoundsPlaying())
|
|
{
|
|
if(HasEntityVariableBlock())
|
|
{
|
|
SetEntityVariable(ATSTRINGHASH("fakethrottle", 0xEB27990), 0.0f);
|
|
SetEntityVariable(ATSTRINGHASH("fakerevs", 0xCEB98BEB), 0.0f);
|
|
}
|
|
|
|
audMetadataRef startupRevsRef = g_NullSoundRef;
|
|
|
|
if(m_CarAudioSettings->EngineType == COMBUSTION)
|
|
{
|
|
startupRevsRef = g_AudioEngine.GetSoundManager().GetFactory().GetMetadataManager().GetObjectMetadataRefFromHash(m_CarAudioSettings->StartupRevs);
|
|
}
|
|
|
|
// If we have an explicit startup sound, use this instead. Its a one-time use thing though, so forget it immediately afterwards
|
|
if(m_ScriptStartupRevsSoundRef != g_NullSoundRef)
|
|
{
|
|
startupRevsRef = m_ScriptStartupRevsSoundRef;
|
|
m_ScriptStartupRevsSoundRef = g_NullSoundRef;
|
|
}
|
|
|
|
CreateAndPlaySound_Persistent(startupRevsRef, &m_StartUpRevsSound);
|
|
m_HasPlayedStartupSequence = true;
|
|
m_FakeEngineStartupRevs = false;
|
|
|
|
if(m_StartUpRevsSound)
|
|
{
|
|
m_WasPlayingStartupSound = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if(m_CarAudioSettings && m_CarAudioSettings->EngineType != ELECTRIC)
|
|
{
|
|
// seriously smooth revs if we're starting the engine
|
|
m_RevsSmoother.SetRates(1.5f / 1000.f,0.45f / 1000.f);
|
|
|
|
u32 engineOnDuration = fwTimer::GetTimeInMilliseconds() - m_EngineStartTime;
|
|
if(engineOnDuration < 5 || engineOnDuration > (u32)(g_EngineStartDuration/3.0f))
|
|
{
|
|
state->rawRevs = CTransmission::ms_fIdleRevs;
|
|
}
|
|
else
|
|
{
|
|
state->rawRevs = 0.75f;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if(m_vehicleEngine.GetState() == audVehicleEngine::AUD_ENGINE_STOPPING)
|
|
{
|
|
if(ShouldForceEngineOff())
|
|
{
|
|
m_RevsSmoother.SetRates(g_RevMaxIncreaseRate / 1000.f, g_RevMaxForceStopDecreaseRate / 1000.f);
|
|
}
|
|
// seriously smooth revs if we're stopping the engine
|
|
else
|
|
{
|
|
m_RevsSmoother.SetRates(0.3f / 1000.f, 0.3f / 1000.f);
|
|
}
|
|
|
|
state->rawRevs = 0.0f;
|
|
m_HasPlayedStartupSequence = false;
|
|
|
|
// Kill the startup revs immediately if we're just playing fake engine blips. For cars with
|
|
// bespoke startups, keep these playing as it sounds odd to cut them short
|
|
if(m_FakeEngineStartupRevs)
|
|
{
|
|
StopAndForgetSounds(m_StartUpRevsSound);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// hold the revs down until we trigger the backfire sfx/vfx
|
|
if(m_vehicleEngine.IsMisfiring())
|
|
{
|
|
//m_RevsSmoother.SetRates(1.0f / 1000.f,0.7f / 1000.f);
|
|
//state->rawRevs = CTransmission::ms_fIdleRevs;
|
|
state->forcedThrottle = 0.0f;
|
|
}
|
|
else
|
|
{
|
|
revsSmoothDecreaseScalar += (m_CarAudioSettings->AdditionalRevsDecreaseSmoothing * 0.01f);
|
|
revsSmoothDecreaseScalar *= g_RevsSmoothingCurve.CalculateValue(state->rawRevs);
|
|
|
|
// Add extra revs smoothing following a stunt boost
|
|
const u32 time = fwTimer::GetTimeInMilliseconds();
|
|
const f32 stuntBoostRatio = 1.f - Clamp((time - m_LastStuntRaceSpeedBoostTime) / (f32)g_StuntSpeedBoostDecelSmoothingDuration, 0.f, 1.f);
|
|
revsSmoothDecreaseScalar += g_StuntSpeedBoostDecelSmoothing * stuntBoostRatio;
|
|
|
|
// Prevent divide by zero
|
|
if(revsSmoothDecreaseScalar < 1.0f)
|
|
{
|
|
revsSmoothDecreaseScalar = 1.0f;
|
|
}
|
|
|
|
if(state->gear == 0 && m_IsReversing && !m_SportsCarRevsSound)
|
|
{
|
|
m_RevsSmoother.SetRates(0.0002f, g_RevMaxDecreaseRate / (1000.f * revsSmoothDecreaseScalar));
|
|
}
|
|
else
|
|
{
|
|
m_RevsSmoother.SetRates(g_RevMaxIncreaseRate / (1000.f * revsSmoothIncreaseScalar), g_RevMaxDecreaseRate / (1000.f * revsSmoothDecreaseScalar));
|
|
}
|
|
}
|
|
}
|
|
|
|
// If the engine is off, revert to clutch pressed
|
|
if(!m_Vehicle->IsEngineOn())
|
|
{
|
|
state->clutchRatio = 0.1f;
|
|
}
|
|
|
|
// randomly trigger gear box crunch/backfires if car is damaged
|
|
const f32 engineHealth = ComputeEffectiveEngineHealth();
|
|
state->engineDamageFactor = Clamp(1.0f - (engineHealth / CTransmission::GetEngineHealthMax()), 0.0f, 1.0f);
|
|
|
|
s32 timeSinceLimiter = fwTimer::GetTimeInMilliseconds() - GetTimeSinceLastRevLimiter();
|
|
|
|
// url:bugstar:6458027 - Manama2 - Rev limiter pops / vfx are playing as the vehicle revs when modified, before it reaches the top of the rev range
|
|
// For cars with additional revs smoothing, we may hit the limiter quite a long while before the audio revs max out, so we want to delay the limiter
|
|
// so that eg. exhaust pops don't trigger too early
|
|
const bool linkExhaustPopsToAudioRevs = g_LinkExhaustPopsToAudioRevs && m_CarAudioSettings->AdditionalRevsIncreaseSmoothing > 0;
|
|
|
|
// Hitting the limiter starts fiddling with the throttle/pedal controls, which sounds rubbish. Just assume we're on max
|
|
// throttle until it calms down again
|
|
#if __BANK
|
|
if(g_EngineVolumeCaptureActive && (sm_VolumeCaptureState == State_CapturingAccel || sm_VolumeCaptureState == State_CapturingAccelModded))
|
|
{
|
|
state->throttle = m_ThrottleSmoother.CalculateValue(sm_VolumeCaptureThrottle, state->timeInMs);
|
|
state->throttleInput = sm_VolumeCaptureThrottle;
|
|
}
|
|
else
|
|
#endif
|
|
// Stop the rev limiter effect as soon as we change down gears
|
|
if((timeSinceLimiter < 100 && (!linkExhaustPopsToAudioRevs || m_RevsSmoother.GetLastValue() >= 1.f)) && timeSinceGearChange > 100 && !useFakeEngine && m_CarAudioSettings->EngineType != ELECTRIC)
|
|
{
|
|
// Cancel the limiter if we're hitting the brake or in reverse
|
|
if((state->fwdSpeedRatio > 0.05f && (state->brakePedal > 0.0f || m_Vehicle->GetThrottle() == 0.0f)) || state->gear <= 0 || m_IsReversing)
|
|
{
|
|
if(!m_IsReversing)
|
|
{
|
|
state->rawRevs = 1.0f;
|
|
state->throttle = m_ThrottleSmoother.CalculateValue(state->gasPedal, state->timeInMs);
|
|
}
|
|
else
|
|
{
|
|
state->throttle = m_ThrottleSmoother.CalculateValue(Max(state->gasPedal, Abs(m_Vehicle->GetThrottle())), state->timeInMs);
|
|
}
|
|
|
|
state->throttleInput = m_Vehicle->GetThrottle();
|
|
state->onRevLimiter = false;
|
|
}
|
|
else
|
|
{
|
|
m_ThrottleSmoother.Reset();
|
|
state->gasPedal = 1.0f;
|
|
state->throttle = m_ThrottleSmoother.CalculateValue(state->gasPedal, state->timeInMs);
|
|
state->throttleInput = 1.0f;
|
|
state->rawRevs = 1.0f;
|
|
|
|
if(m_DrowningFactor == 0.0f)
|
|
{
|
|
state->onRevLimiter = true;
|
|
}
|
|
else
|
|
{
|
|
state->onRevLimiter = false;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
state->throttle = m_ThrottleSmoother.CalculateValue(state->gasPedal, state->timeInMs);
|
|
state->throttleInput = m_Vehicle->GetThrottle();
|
|
state->onRevLimiter = false;
|
|
}
|
|
|
|
#if GTA_REPLAY
|
|
if(CReplayMgr::IsEditModeActive())
|
|
{
|
|
state->onRevLimiter = m_ReplayRevLimiter;
|
|
state->gasPedal = 1.0f;
|
|
state->throttle = m_ThrottleSmoother.CalculateValue(state->gasPedal, state->timeInMs);
|
|
state->throttleInput = 1.0f;
|
|
}
|
|
#endif
|
|
|
|
state->revs = F32_VerifyFinite(m_RevsSmoother.CalculateValue(state->rawRevs, state->timeInMs));
|
|
if(m_vehicleEngine.GetState() != audVehicleEngine::AUD_ENGINE_STARTING && m_vehicleEngine.GetState() != audVehicleEngine::AUD_ENGINE_STOPPING)
|
|
{
|
|
// clamp revs to idle minimum
|
|
state->revs = Max(CTransmission::ms_fIdleRevs,state->revs);
|
|
}
|
|
|
|
if(m_vehicleEngine.IsGranularEngineActive())
|
|
{
|
|
state->carVolOffset = (m_GranularEngineSettings->MasterVolume/100.f);
|
|
}
|
|
else if(m_VehicleEngineSettings)
|
|
{
|
|
state->carVolOffset = (m_VehicleEngineSettings->MasterVolume/100.f);
|
|
}
|
|
|
|
state->exhaustThrottleAtten = (0.f - ((1.f - state->throttle) * g_audExhaustThrottleVolumeRange));
|
|
state->engineThrottleAtten = (0.f - ((1.f - state->throttle) * g_audThrottleVolumeRange));
|
|
|
|
if(state->revs > g_EnginePowerBand[state->gear])
|
|
{
|
|
state->enginePowerFactor = (g_EnginePowerBand[state->gear] - (state->revs - g_EnginePowerBand[state->gear])) / g_EnginePowerBand[state->gear];
|
|
}
|
|
else
|
|
{
|
|
state->enginePowerFactor = state->revs / g_EnginePowerBand[state->gear];
|
|
}
|
|
|
|
f32 outputCategoryVol = 0.0f;
|
|
f32 environmentalLoudness = 0.0f;
|
|
const f32 wetness = m_EngineEffectWetSmoother.GetLastValue();
|
|
|
|
naAssertf(g_PlayerVolumeCategories[m_CarAudioSettings->VolumeCategory], "Vehicle volume category for player car %s is invalid, about to access a null ptr...", GetVehicleModelName());
|
|
naAssertf(g_PedVolumeCategories[m_CarAudioSettings->VolumeCategory], "Vehicle volume category for ped car %s is invalid, about to access a null ptr...", GetVehicleModelName());
|
|
|
|
// promote the player volume category to loud if its below that
|
|
// NOTE: smaller category IDs are louder (loudest == 0)
|
|
const u32 playerVolCategory = (g_ScriptAudioEntity.IsFlagSet(audScriptAudioFlags::BoostPlayerCarVolume) ? Min((u32)m_CarAudioSettings->VolumeCategory,(u32)VEHICLE_VOLUME_LOUD):m_CarAudioSettings->VolumeCategory);
|
|
state->playerVolCategory = playerVolCategory;
|
|
|
|
#if __BANK
|
|
if(g_DisableVolumeCategory || g_EngineVolumeCaptureActive)
|
|
{
|
|
outputCategoryVol = 0.0f;
|
|
m_EngineEffectWetSmoother.Reset();
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
if(wetness == 0.f)
|
|
{
|
|
// fully dry; use ped volume
|
|
outputCategoryVol = g_PedVolumeCategories[m_CarAudioSettings->VolumeCategory]->GetVolume();
|
|
}
|
|
else if(wetness == 1.f)
|
|
{
|
|
// fully wet; use player volume
|
|
outputCategoryVol = g_PlayerVolumeCategories[playerVolCategory]->GetVolume();
|
|
}
|
|
else
|
|
{
|
|
// fading - interp between
|
|
const f32 outputCategoryVolLinPlayer = audDriverUtil::ComputeLinearVolumeFromDb(g_PlayerVolumeCategories[playerVolCategory]->GetVolume());
|
|
const f32 outputCategoryVolLinPed = audDriverUtil::ComputeLinearVolumeFromDb(g_PedVolumeCategories[m_CarAudioSettings->VolumeCategory]->GetVolume());
|
|
outputCategoryVol = audDriverUtil::ComputeDbVolumeFromLinear(Lerp(wetness, outputCategoryVolLinPed, outputCategoryVolLinPlayer));
|
|
}
|
|
|
|
if(m_IsPlayerVehicle)
|
|
{
|
|
environmentalLoudness = g_PlayerVolumeCategories[playerVolCategory]->GetEnvironmentalLoudness();
|
|
}
|
|
else
|
|
{
|
|
environmentalLoudness = g_PedVolumeCategories[m_CarAudioSettings->VolumeCategory]->GetEnvironmentalLoudness();
|
|
}
|
|
}
|
|
|
|
// environmental loudness gets scaled down by revs and throttle
|
|
environmentalLoudness *= sm_EnvironmentalLoudnessThrottleCurve.CalculateValue(state->throttle);
|
|
environmentalLoudness *= sm_EnvironmentalLoudnessRevsCurve.CalculateValue(state->revs);
|
|
environmentalLoudness = Max(environmentalLoudness, m_SportsCarRevsApplyFactor);
|
|
state->environmentalLoudness = environmentalLoudness;
|
|
|
|
f32 enginePostSubmixVol = outputCategoryVol + state->carVolOffset;
|
|
f32 exhaustPostSubmixVol = outputCategoryVol + state->carVolOffset;
|
|
|
|
// In practice rev ratio always lies between 0.2 and 1.0, so scale up to a 0-1 range
|
|
f32 revRatio = ((state->revs - 0.2f) * 1.25f);
|
|
|
|
// Similarly, clutch ratio actually goes from 0.1 to 1.0, so scale up to a 0-1 range
|
|
f32 clutchRatio = ((state->clutchRatio - 0.1f) * 1.11f);
|
|
|
|
// B*2537551 fix - don't duck exhaust while reversing on certain vehicles. Please make
|
|
// this configurable from metadata for future projects!
|
|
bool duckExahustWhileReversing = true;
|
|
const u32 vehicleModelName = GetVehicleModelNameHash();
|
|
|
|
if(vehicleModelName == ATSTRINGHASH("BUCCANEER2", 0xC397F748) ||
|
|
vehicleModelName == ATSTRINGHASH("CHINO2", 0xAED64A63) ||
|
|
vehicleModelName == ATSTRINGHASH("SLAMVAN", 0x2B7F9DE3) ||
|
|
vehicleModelName == ATSTRINGHASH("BLAZER4", 0xE5BA6858) ||
|
|
vehicleModelName == ATSTRINGHASH("BLAZER5", 0xA1355F67) ||
|
|
vehicleModelName == ATSTRINGHASH("RATLOADER2", 0xDCE1D9F7) ||
|
|
vehicleModelName == ATSTRINGHASH("VOODOO", 0x779B4F2D))
|
|
{
|
|
duckExahustWhileReversing = false;
|
|
}
|
|
|
|
// Doesn't make sense on any bikes as the ped walks them backwards to reverse
|
|
if(m_Vehicle->InheritsFromBike())
|
|
{
|
|
duckExahustWhileReversing = false;
|
|
}
|
|
|
|
f32 reversingExhaustVol = m_ReversingExhaustVolSmoother.CalculateValue(m_IsReversing && duckExahustWhileReversing && state->fwdSpeedAbs > 0.0f? -5.0f : 0.0f);
|
|
|
|
if(m_vehicleEngine.IsGranularEngineActive())
|
|
{
|
|
enginePostSubmixVol += (m_GranularEngineSettings->EngineVolume_PostSubmix * 0.01f);
|
|
exhaustPostSubmixVol += (m_GranularEngineSettings->ExhaustVolume_PostSubmix * 0.01f);
|
|
|
|
enginePostSubmixVol += revRatio * (m_GranularEngineSettings->EngineRevsVolume_PostSubmix * 0.01f);
|
|
exhaustPostSubmixVol += revRatio * (m_GranularEngineSettings->ExhaustRevsVolume_PostSubmix * 0.01f );
|
|
|
|
if(!m_IsReversing)
|
|
{
|
|
// Quickly fade in clutch attenuation effect once player gains speed - don't want it triggering when stationary
|
|
f32 clutchAttenuationApplyFactor = Clamp((state->fwdSpeedRatio - 0.05f) * 25.0f, 0.0f, 1.0f);
|
|
enginePostSubmixVol += state->throttle * (m_GranularEngineSettings->EngineThrottleVolume_PostSubmix * 0.01f);
|
|
enginePostSubmixVol += (m_GranularEngineSettings->EngineClutchAttenuation_PostSubmix * clutchAttenuationApplyFactor * 0.01f) * (1.0f - clutchRatio);
|
|
exhaustPostSubmixVol += state->throttle * (m_GranularEngineSettings->ExhaustThrottleVolume_PostSubmix * 0.01f);
|
|
exhaustPostSubmixVol += (m_GranularEngineSettings->ExhaustClutchAttenuation_PostSubmix * clutchAttenuationApplyFactor * 0.01f) * (1.0f - clutchRatio);
|
|
}
|
|
|
|
exhaustPostSubmixVol += reversingExhaustVol;
|
|
enginePostSubmixVol += (m_GranularEngineSettings->UpgradedEngineVolumeBoost_PostSubmix/100.0f) * GetEngineUpgradeLevel();
|
|
exhaustPostSubmixVol += (m_GranularEngineSettings->UpgradedExhaustVolumeBoost_PostSubmix/100.0f) * GetExhaustUpgradeLevel();
|
|
|
|
f32 engineIdleBoostLin = Lerp(m_vehicleEngine.GetGranularEngine()->GetIdleVolumeScale(), 1.0f, audDriverUtil::ComputeLinearVolumeFromDb((m_GranularEngineSettings->EngineIdleVolume_PostSubmix/100.0f)));
|
|
f32 exhaustIdleBoostLin = Lerp(m_vehicleEngine.GetGranularEngine()->GetIdleVolumeScale(), 1.0f, audDriverUtil::ComputeLinearVolumeFromDb((m_GranularEngineSettings->ExhaustIdleVolume_PostSubmix/100.0f)));
|
|
|
|
enginePostSubmixVol += audDriverUtil::ComputeDbVolumeFromLinear(engineIdleBoostLin);
|
|
exhaustPostSubmixVol += audDriverUtil::ComputeDbVolumeFromLinear(exhaustIdleBoostLin);
|
|
}
|
|
else if(m_VehicleEngineSettings)
|
|
{
|
|
const f32 pedEngineFxComp = m_VehicleEngineSettings->NonPlayerFXComp * 0.01f;
|
|
const f32 playerEngineFxComp = m_VehicleEngineSettings->FXCompensation * 0.01f;
|
|
const f32 revsForCompensation = (m_IsPlayerVehicle?g_PlayerRevsCurve.CalculateValue(state->revs):g_PedRevsCurve.CalculateValue(state->revs));
|
|
const f32 interpolatedFxComp = Lerp(wetness, pedEngineFxComp, playerEngineFxComp);
|
|
const f32 engineFxCompensation = (revsForCompensation * interpolatedFxComp);
|
|
const f32 throttleForCompensation = (m_IsPlayerVehicle?g_PlayerThrottleCurve.CalculateValue(state->throttle):g_PedThrottleCurve.CalculateValue(state->throttle));
|
|
const f32 exhaustFxCompensation = throttleForCompensation * engineFxCompensation;
|
|
|
|
enginePostSubmixVol += engineFxCompensation;
|
|
exhaustPostSubmixVol += exhaustFxCompensation;
|
|
|
|
enginePostSubmixVol += (m_VehicleEngineSettings->UpgradedEngineVolumeBoost_PostSubmix/100.0f) * GetEngineUpgradeLevel();
|
|
exhaustPostSubmixVol += (m_VehicleEngineSettings->UpgradedExhaustVolumeBoost_PostSubmix/100.0f) * GetExhaustUpgradeLevel();
|
|
}
|
|
|
|
#if __BANK
|
|
if(g_MutePlayerVehicle && m_IsPlayerVehicle)
|
|
{
|
|
enginePostSubmixVol = g_SilenceVolume;
|
|
exhaustPostSubmixVol = g_SilenceVolume;
|
|
}
|
|
#endif
|
|
|
|
// Duck exhaust on backfires
|
|
if(m_vehicleEngine.IsExhaustPopActive())
|
|
{
|
|
exhaustPostSubmixVol -= 3.0f;
|
|
}
|
|
|
|
if((m_StartUpRevsSound && useFakeEngine && entityVariableRevs > 0.0f) || m_vehicleEngine.GetStartupSound())
|
|
{
|
|
m_StartupRevsVolBoostSmoother.CalculateValue(revRatio, g_AudioEngine.GetSoundManager().GetTimeInMilliseconds(0));
|
|
}
|
|
else
|
|
{
|
|
m_StartupRevsVolBoostSmoother.CalculateValue(0.0f, g_AudioEngine.GetSoundManager().GetTimeInMilliseconds(0));
|
|
}
|
|
|
|
if(m_GranularEngineSettings)
|
|
{
|
|
enginePostSubmixVol += ((m_GranularEngineSettings->StartupRevsVolumeBoostEngine_PostSubmix * 0.01f) * m_StartupRevsVolBoostSmoother.GetLastValue());
|
|
exhaustPostSubmixVol += ((m_GranularEngineSettings->StartupRevsVolumeBoostExhaust_PostSubmix * 0.01f) * m_StartupRevsVolBoostSmoother.GetLastValue());
|
|
}
|
|
else
|
|
{
|
|
enginePostSubmixVol += 3.0f * m_StartupRevsVolBoostSmoother.GetLastValue();
|
|
exhaustPostSubmixVol += 3.0f * m_StartupRevsVolBoostSmoother.GetLastValue();
|
|
}
|
|
|
|
state->enginePostSubmixVol = enginePostSubmixVol + state->engineConeAtten;
|
|
state->exhaustPostSubmixVol = exhaustPostSubmixVol + state->exhaustConeAtten;
|
|
|
|
state->enginePostSubmixVol += g_EngineVolumeTrim;
|
|
state->exhaustPostSubmixVol += g_ExhaustVolumeTrim;
|
|
|
|
f32 rollOff = m_IsPlayerVehicle? m_CarAudioSettings->MaxRollOffScalePlayer : m_CarAudioSettings->MaxRollOffScaleNPC;
|
|
f32 desiredRollOff = m_IsPlayerVehicle? g_BaseRollOffScalePlayer : g_BaseRollOffScaleNPC + (rollOff * Clamp(revRatio * revRatio * revRatio, 0.0f, 1.0f));
|
|
f32 smoothedRollOff = m_RollOffSmoother.CalculateValue(desiredRollOff);
|
|
|
|
if(sm_SportsCarRevsSettings)
|
|
{
|
|
if(m_SportsCarRevsSound)
|
|
{
|
|
m_SportsCarRevsApplyFactor += fwTimer::GetTimeStep() * sm_SportsCarRevsSettings->AttackTimeScalar;
|
|
}
|
|
else
|
|
{
|
|
m_SportsCarRevsApplyFactor -= fwTimer::GetTimeStep() * sm_SportsCarRevsSettings->ReleaseTimeScalar * (m_WasSportsCarRevsCancelled ? 2.0f : 1.0f);
|
|
}
|
|
|
|
m_SportsCarRevsApplyFactor = Clamp(m_SportsCarRevsApplyFactor, 0.0f, 1.0f);
|
|
state->enginePostSubmixVol += (sm_SportsCarRevsSettings->EngineVolumeBoost * 0.01f * m_SportsCarRevsApplyFactor * state->revs);
|
|
state->exhaustPostSubmixVol += (sm_SportsCarRevsSettings->ExhaustVolumeBoost * 0.01f * m_SportsCarRevsApplyFactor * state->revs);
|
|
|
|
if(m_EnvironmentGroup)
|
|
{
|
|
m_EnvironmentGroup->SetReverbOverrideLarge((u8)(sm_SportsCarRevsSettings->LargeReverbSend * m_SportsCarRevsApplyFactor * state->revs));
|
|
m_EnvironmentGroup->SetReverbOverrideMedium((u8)(sm_SportsCarRevsSettings->MediumReverbSend * m_SportsCarRevsApplyFactor * state->revs));
|
|
m_EnvironmentGroup->SetReverbOverrideSmall((u8)(sm_SportsCarRevsSettings->SmallReverbSend * m_SportsCarRevsApplyFactor * state->revs));
|
|
}
|
|
|
|
state->rollOffScale = smoothedRollOff + (sm_SportsCarRevsSettings->RollOffBoost * m_SportsCarRevsApplyFactor);
|
|
}
|
|
else
|
|
{
|
|
state->rollOffScale = smoothedRollOff;
|
|
}
|
|
|
|
#if GTA_REPLAY
|
|
if(CReplayMgr::ShouldRecord())
|
|
{
|
|
m_ReplayRevLimiter = state->onRevLimiter;
|
|
}
|
|
#endif
|
|
|
|
#if __BANK
|
|
if(m_Vehicle->GetStatus() == STATUS_PLAYER)
|
|
{
|
|
PF_SET(Revs, state->revs);
|
|
PF_SET(RawRevs, state->rawRevs);
|
|
PF_SET(Throttle, state->throttle);
|
|
PF_SET(PowerFactor, state->enginePowerFactor);
|
|
PF_SET(Gear, state->gear);
|
|
}
|
|
|
|
char vehicleDebug[256] = "";
|
|
if(sm_ShouldDisplayEngineDebug )
|
|
{
|
|
if(m_Vehicle->GetStatus()==STATUS_PLAYER)
|
|
{
|
|
CVehicleModelInfo *model = (CVehicleModelInfo*)m_Vehicle->GetBaseModelInfo();
|
|
const f32 engineHealth = ComputeEffectiveEngineHealth();
|
|
sprintf(vehicleDebug, "%s h: %.1f rR:%.3f r:%.3f t:%.3f s:%d g:%d mv:%.2f nw:%d temp: %.2f", model->GetGameName(), engineHealth, state->rawRevs, state->revs, state->throttle, (u32)m_vehicleEngine.GetState(), state->gear, transmission->GetDriveMaxVelocity(), m_Vehicle->GetNumContactWheels(), m_Vehicle->m_EngineTemperature);
|
|
grcDebugDraw::PrintToScreenCoors(vehicleDebug, 5,30);
|
|
sprintf(vehicleDebug, "%f %f %f %f %f %f %f %f", state->engineConeAtten, state->exhaustConeAtten, state->engineThrottleAtten, state->exhaustThrottleAtten, state->carVolOffset, state->enginePowerFactor, state->pitchRatio,(state->revs - state->rawRevs) * fwTimer::GetInvTimeStep());
|
|
grcDebugDraw::PrintToScreenCoors(vehicleDebug, 5, 10);
|
|
}
|
|
|
|
sprintf(vehicleDebug, "bs %f r %f rr %f t %f su %f", state->speedForBrakes, state->revs, state->rawRevs, state->throttle, m_StartupRevsVolBoostSmoother.GetLastValue());
|
|
grcDebugDraw::Text(VEC3V_TO_VECTOR3(m_Vehicle->GetTransform().GetPosition()) + Vector3(0.f,0.f,1.f), Color32(50,50,255), vehicleDebug);
|
|
}
|
|
|
|
if(g_DisableVolumeCategory && m_Vehicle->GetStatus() == STATUS_PLAYER)
|
|
{
|
|
if(CControlMgr::GetKeyboard().GetKeyDown(KEY_0, KEYBOARD_MODE_DEBUG, "engine test loop"))
|
|
{
|
|
if(!g_EngineReferenceLoop)
|
|
{
|
|
audSoundInitParams initParams;
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
CreateAndPlaySound_Persistent(ATSTRINGHASH("ENGINE_REFERENCE_LOOP", 0x68ACCBCB), &g_EngineReferenceLoop, &initParams);
|
|
}
|
|
if(g_EngineReferenceLoop)
|
|
{
|
|
u32 posIdx = (sm_ShouldFlipPlayerCones?AUD_VEHICLE_SOUND_ENGINE:AUD_VEHICLE_SOUND_EXHAUST);
|
|
g_EngineReferenceLoop->SetUpdateEntity(true);
|
|
g_EngineReferenceLoop->SetClientVariable(posIdx);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(g_EngineReferenceLoop)
|
|
{
|
|
g_EngineReferenceLoop->StopAndForget();
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void audCarAudioEntity::SetIsInCarModShop(bool inCarMod)
|
|
{
|
|
if(inCarMod != IsInCarModShop())
|
|
{
|
|
audVehicleAudioEntity::SetIsInCarModShop(inCarMod);
|
|
|
|
// Cancel any startup rev behaviour as we'll be playing revs on the way in/out of the mod shop
|
|
if(m_vehicleEngine.GetState() == audVehicleEngine::AUD_ENGINE_STARTING)
|
|
{
|
|
m_vehicleEngine.ForceEngineState(audVehicleEngine::AUD_ENGINE_ON);
|
|
|
|
if(m_StartUpRevsSound)
|
|
{
|
|
m_StartUpRevsSound->StopAndForget();
|
|
}
|
|
|
|
m_HasPlayedStartupSequence = true;
|
|
m_WasPlayingStartupSound = false;
|
|
m_FakeEngineStartupRevs = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// audCarAudioEntity CalculateIsInWater
|
|
// ----------------------------------------------------------------
|
|
bool audCarAudioEntity::CalculateIsInWater() const
|
|
{
|
|
#if GTA_REPLAY // For replay we set this from CPacketAmphQuadUpdate/CPacketAmphAutoUpdate
|
|
if(CReplayMgr::IsEditModeActive())
|
|
{
|
|
return m_ReplayIsInWater;
|
|
}
|
|
#endif
|
|
if(m_Vehicle->InheritsFromAmphibiousAutomobile())
|
|
{
|
|
CBuoyancyInfo* buoyancyInfo = m_Vehicle->m_Buoyancy.GetBuoyancyInfo(m_Vehicle);
|
|
|
|
if(buoyancyInfo)
|
|
{
|
|
s8 numWaterSampleRows = buoyancyInfo->m_nNumBoatWaterSampleRows;
|
|
s8 lastRowWaterSampleIndex = buoyancyInfo->m_nBoatWaterSampleRowIndices[numWaterSampleRows-1];
|
|
s8 secondLastRowWaterSampleIndex = buoyancyInfo->m_nBoatWaterSampleRowIndices[numWaterSampleRows-2];
|
|
s8 secondLastRowNumWaterSamples = lastRowWaterSampleIndex - secondLastRowWaterSampleIndex;
|
|
s8 entryWaterSampleIndex = secondLastRowWaterSampleIndex + (secondLastRowNumWaterSamples)/2;
|
|
return m_WaterSamples.IsSet(entryWaterSampleIndex);
|
|
}
|
|
}
|
|
|
|
return audVehicleAudioEntity::CalculateIsInWater();
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------
|
|
// Update sports car revs
|
|
// -------------------------------------------------------------------------------
|
|
void audCarAudioEntity::UpdateSportsCarRevs(audVehicleVariables* state)
|
|
{
|
|
if(!sm_SportsCarRevsSettings)
|
|
{
|
|
return;
|
|
}
|
|
|
|
bool sportsCarRevsValid = (m_SportsCarRevsEnabled BANK_ONLY(|| g_ForceAllCarsPlaySportsRevs)) &&
|
|
!camInterface::GetCutsceneDirector().IsCutScenePlaying() &&
|
|
m_Vehicle->GetOwnedBy() != ENTITY_OWNEDBY_CUTSCENE &&
|
|
m_Vehicle->GetOwnedBy() != ENTITY_OWNEDBY_SCRIPT &&
|
|
!m_Vehicle->m_nVehicleFlags.bHasBeenOwnedByPlayer;
|
|
|
|
if(m_SportsCarRevsSound && m_SportsCarRevsTriggerType != REVS_TYPE_DEBUG)
|
|
{
|
|
if(!sportsCarRevsValid ||
|
|
(m_SportsCarRevsTriggerType == REVS_TYPE_JUNCTION && state->fwdSpeedAbs < sm_SportsCarRevsSettings->JunctionStopSpeed) ||
|
|
(m_SportsCarRevsTriggerType == REVS_TYPE_PASSBY && state->fwdSpeedAbs < sm_SportsCarRevsSettings->PassbyStopSpeed))
|
|
{
|
|
StopAndForgetSounds(m_SportsCarRevsSound);
|
|
m_WasSportsCarRevsCancelled = true;
|
|
}
|
|
}
|
|
|
|
if(m_GranularEngineSettings && g_SportsCarRevsEnabled && sportsCarRevsValid)
|
|
{
|
|
f32 distanceFromListenerChangeRate = ((s32)m_DistanceFromListener2 - (s32)m_DistanceFromListener2LastFrame) * fwTimer::GetInvTimeStep();
|
|
bool isApproachingListener = distanceFromListenerChangeRate < 0.0f;
|
|
|
|
bool forceTrigger = false;
|
|
SportCarRevsTriggerType triggerType = REVS_TYPE_MAX;
|
|
m_WasWaitingAtLights |= ((m_Vehicle->GetIntelligence()->GetJunctionCommand() == JUNCTION_COMMAND_WAIT_FOR_LIGHTS || m_Vehicle->GetIntelligence()->GetJunctionCommand() == JUNCTION_COMMAND_GIVE_WAY) && state->fwdSpeedAbs < 0.1f);
|
|
|
|
// If a car is waiting at some lights, trigger revs as it pulls away
|
|
if(m_WasWaitingAtLights && (m_Vehicle->GetIntelligence()->GetJunctionCommand() == JUNCTION_COMMAND_GO || m_Vehicle->GetIntelligence()->GetJunctionCommand() == JUNCTION_COMMAND_NOT_ON_JUNCTION) && state->fwdSpeedAbs > sm_SportsCarRevsSettings->JunctionTriggerSpeed)
|
|
{
|
|
m_WasWaitingAtLights = false;
|
|
|
|
if(m_DistanceFromListener2 > (sm_SportsCarRevsSettings->JunctionMinDistance * sm_SportsCarRevsSettings->JunctionMinDistance) && m_DistanceFromListener2 < (sm_SportsCarRevsSettings->JunctionMaxDistance * sm_SportsCarRevsSettings->JunctionMaxDistance))
|
|
{
|
|
triggerType = REVS_TYPE_JUNCTION;
|
|
}
|
|
}
|
|
|
|
bool isDoingBurnout = static_cast<CAutomobile*>(m_Vehicle)->m_nAutomobileFlags.bBurnoutModeEnabled;
|
|
m_WasDoingBurnout |= isDoingBurnout;
|
|
|
|
if(m_WasDoingBurnout && !isDoingBurnout && state->fwdSpeedAbs > 0.75f && !m_Vehicle->InheritsFromBike())
|
|
{
|
|
forceTrigger = true;
|
|
m_WasDoingBurnout = false;
|
|
triggerType = REVS_TYPE_JUNCTION;
|
|
}
|
|
|
|
// Special case - clustered vehicles can trigger revs even if the player is driving a car
|
|
if(triggerType == REVS_TYPE_MAX && !IsPlayerOnFootOrOnBicycle() && m_Vehicle->m_nVehicleFlags.bIsInCluster)
|
|
{
|
|
if(m_DistanceFromListener2 < sm_SportsCarRevsSettings->ClusterTriggerDistance && m_DistanceFromListener2LastFrame >= (sm_SportsCarRevsSettings->ClusterTriggerDistance * sm_SportsCarRevsSettings->ClusterTriggerDistance) && state->fwdSpeedAbs > sm_SportsCarRevsSettings->ClusterTriggerSpeed)
|
|
{
|
|
triggerType = REVS_TYPE_PASSBY;
|
|
}
|
|
}
|
|
|
|
// If a car passes close by at speed, trigger some revs
|
|
if(triggerType == REVS_TYPE_MAX)
|
|
{
|
|
if(m_Vehicle->GetIntelligence()->GetJunctionCommand() == JUNCTION_COMMAND_NOT_ON_JUNCTION || m_Vehicle->GetIntelligence()->GetJunctionCommand() == JUNCTION_COMMAND_GO)
|
|
{
|
|
// New approach - attempt to predict when the car is due to pass the player and trigger a bit earlier
|
|
if(isApproachingListener)
|
|
{
|
|
if(state->fwdSpeedAbs > sm_SportsCarRevsSettings->PassbyTriggerSpeed)
|
|
{
|
|
if(m_DistanceFromListener2 > (sm_SportsCarRevsSettings->PassbyMinDistance * sm_SportsCarRevsSettings->PassbyMinDistance) &&
|
|
m_DistanceFromListener2 < (sm_SportsCarRevsSettings->PassbyMaxDistance * sm_SportsCarRevsSettings->PassbyMaxDistance))
|
|
{
|
|
CPed* playerPed = FindPlayerPed();
|
|
|
|
if(playerPed)
|
|
{
|
|
Vec3V playerPositionOnLine;
|
|
Vector3 vehiclePos = VEC3V_TO_VECTOR3(m_Vehicle->GetVehiclePosition());
|
|
fwGeom::fwLine positioningLine = fwGeom::fwLine(vehiclePos, vehiclePos + (m_CachedVehicleVelocity * 10.0f * sm_SportsCarRevsSettings->PassbyLookaheadTime));
|
|
ScalarV distanceAlongLine = positioningLine.FindClosestPointOnLineV(playerPed->GetTransform().GetPosition(), playerPositionOnLine);
|
|
|
|
if(IsLessThan(distanceAlongLine, ScalarV(0.1f)).Getb())
|
|
{
|
|
triggerType = REVS_TYPE_PASSBY;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(m_SportsCarRevsRequested)
|
|
{
|
|
TriggerSportsCarRevs(m_SportsCarRevsTriggerType);
|
|
}
|
|
else if(triggerType != REVS_TYPE_MAX)
|
|
{
|
|
if(forceTrigger ||
|
|
(state->timeInMs > sm_LastSportsRevsTime + sm_SportsCarRevsSettings->MinTriggerTime && state->timeInMs - m_LastSportsCarRevsTime > 10000))
|
|
{
|
|
// Special case - clustered vehicles can trigger revs even if the player is driving a car
|
|
if(!m_IsFocusVehicle && !audNorthAudioEngine::GetGtaEnvironment()->AreWeInAnInterior() && (IsPlayerOnFootOrOnBicycle() || m_Vehicle->m_nVehicleFlags.bIsInCluster))
|
|
{
|
|
bool playedRecently = false;
|
|
|
|
if(!forceTrigger)
|
|
{
|
|
for(u32 loop = 0; loop < kSportsCarRevsHistorySize; loop++)
|
|
{
|
|
if(m_GranularEngineSettings &&
|
|
sm_SportsCarRevsSoundHistory[loop].soundName == m_GranularEngineSettings->EngineAccel &&
|
|
fwTimer::GetTimeInMilliseconds() < sm_SportsCarRevsSoundHistory[loop].time + sm_SportsCarRevsSettings->MinRepeatTime)
|
|
{
|
|
playedRecently = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(!playedRecently)
|
|
{
|
|
// Avoid playing sports car revs when in a vehicle as we're low on granular engine and these use 'em up
|
|
TriggerSportsCarRevs(triggerType);
|
|
sm_LastSportsRevsTime = state->timeInMs;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#if __BANK
|
|
if(g_DrawSportsRevsPassbyDebug)
|
|
{
|
|
CPed* playerPed = FindPlayerPed();
|
|
|
|
if(playerPed)
|
|
{
|
|
Vec3V playerPositionOnLine;
|
|
Vector3 vehiclePos = VEC3V_TO_VECTOR3(m_Vehicle->GetVehiclePosition());
|
|
fwGeom::fwLine positioningLine = fwGeom::fwLine(vehiclePos, vehiclePos + (m_CachedVehicleVelocity * 10.0f * sm_SportsCarRevsSettings->PassbyLookaheadTime));
|
|
grcDebugDraw::Line(positioningLine.m_start, positioningLine.m_end, Color32(255,0,0,255), Color32(255,0,0,255));
|
|
grcDebugDraw::Sphere(VEC3V_TO_VECTOR3(playerPositionOnLine), 1.f, Color32(0,255,0,255));
|
|
}
|
|
}
|
|
|
|
if(g_DrawCarsPlayingSportsRevs)
|
|
{
|
|
bool drawDetails = true;
|
|
bool playedRecently = false;
|
|
|
|
for(u32 loop = 0; loop < kSportsCarRevsHistorySize; loop++)
|
|
{
|
|
if(m_GranularEngineSettings &&
|
|
sm_SportsCarRevsSoundHistory[loop].soundName == m_GranularEngineSettings->EngineAccel &&
|
|
fwTimer::GetTimeInMilliseconds() < sm_SportsCarRevsSoundHistory[loop].time + sm_SportsCarRevsSettings->MinRepeatTime)
|
|
{
|
|
playedRecently = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(m_SportsCarRevsSound)
|
|
{
|
|
Color32 colour = Color32(255,0,0,120);
|
|
grcDebugDraw::Sphere(VEC3V_TO_VECTOR3(m_Vehicle->GetTransform().GetPosition()), 3.f, colour);
|
|
grcDebugDraw::Line(VEC3V_TO_VECTOR3(m_Vehicle->GetTransform().GetPosition()), VEC3V_TO_VECTOR3(FindPlayerPed()->GetTransform().GetPosition()), Color32(0,255,0), Color32(0,255,0));
|
|
}
|
|
else if(m_WasDoingBurnout)
|
|
{
|
|
Color32 colour = Color32(255,0,255,120);
|
|
grcDebugDraw::Sphere(VEC3V_TO_VECTOR3(m_Vehicle->GetTransform().GetPosition()), 3.f, colour);
|
|
}
|
|
else if(m_WasWaitingAtLights && !playedRecently)
|
|
{
|
|
Color32 colour = Color32(0,255,0,120);
|
|
grcDebugDraw::Sphere(VEC3V_TO_VECTOR3(m_Vehicle->GetTransform().GetPosition()), 3.f, colour);
|
|
}
|
|
else if(m_CarAudioSettings && AUD_GET_TRISTATE_VALUE(m_CarAudioSettings->Flags, FLAG_ID_CARAUDIOSETTINGS_SPORTSCARREVSENABLED) == AUD_TRISTATE_TRUE)
|
|
{
|
|
Color32 colour = playedRecently? Color32(0,255,255,30) : Color32(0,0,255,60);
|
|
grcDebugDraw::Sphere(VEC3V_TO_VECTOR3(m_Vehicle->GetTransform().GetPosition()), 3.f, colour);
|
|
}
|
|
else
|
|
{
|
|
drawDetails = false;
|
|
}
|
|
|
|
char tempString[256];
|
|
formatf(tempString, "Spd %.02f - Dst %.02f - Dst CR %.02f - JC %d", state->fwdSpeedAbs, sqrt((f32)state->distFromListenerSq), ((f32)m_DistanceFromListener2 - (f32)m_DistanceFromListener2LastFrame) * fwTimer::GetInvTimeStep(), m_Vehicle->GetIntelligence()->GetJunctionCommand());
|
|
grcDebugDraw::Text(GetPosition(), Color32(255,255,255), tempString);
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------
|
|
// Update synth light effect on the front of the Ruiner
|
|
// -------------------------------------------------------------------------------
|
|
void audCarAudioEntity::UpdateWooWooSound(audVehicleVariables* state)
|
|
{
|
|
const u32 modelNameHash = GetVehicleModelNameHash();
|
|
|
|
if(modelNameHash == ATSTRINGHASH("RUINER2", 0x381E10BD))
|
|
{
|
|
if(m_Vehicle->m_nVehicleFlags.bEngineOn && m_IsFocusVehicle && state->revs <= 0.21f && state->fwdSpeedAbs < 0.1f)
|
|
{
|
|
if(!m_WooWooSound)
|
|
{
|
|
audSoundSet soundset;
|
|
const u32 soundsetName = ATSTRINGHASH("DLC_ImportExport_Ruiner2_Sounds", 0xB2AD811);
|
|
const u32 soundName = ATSTRINGHASH("light_woo", 0x8396256B);
|
|
|
|
if(soundset.Init(soundsetName))
|
|
{
|
|
audSoundInitParams initParams;
|
|
initParams.TrackEntityPosition = true;
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
CreateAndPlaySound_Persistent(soundset.Find(soundName), &m_WooWooSound, &initParams);
|
|
}
|
|
}
|
|
}
|
|
else if(m_WooWooSound)
|
|
{
|
|
m_WooWooSound->StopAndForget(true);
|
|
}
|
|
}
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------
|
|
// Update gliding
|
|
// -------------------------------------------------------------------------------
|
|
void audCarAudioEntity::UpdateGliding(audVehicleVariables* state)
|
|
{
|
|
const u32 modelNameHash = GetVehicleModelNameHash();
|
|
|
|
if(modelNameHash == ATSTRINGHASH("OPPRESSOR", 0x34B82784))
|
|
{
|
|
if(m_Vehicle->HasGlider() && m_Vehicle->GetGliderState() == CVehicle::GLIDING && state->numWheelsTouching == 0)
|
|
{
|
|
if(!m_GliderSound)
|
|
{
|
|
audSoundSet soundset;
|
|
const u32 soundsetName = m_IsFocusVehicle? ATSTRINGHASH("DLC_Gunrunning_Oppressor_Sounds", 0xC98DA953) : ATSTRINGHASH("DLC_Gunrunning_Oppressor_NPC_Sounds", 0x23FDA269);
|
|
const u32 soundFieldName = ATSTRINGHASH("glide", 0xF9209D38);
|
|
|
|
if(soundset.Init(soundsetName))
|
|
{
|
|
audSoundInitParams initParams;
|
|
initParams.TrackEntityPosition = true;
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
CreateAndPlaySound_Persistent(soundset.Find(soundFieldName), &m_GliderSound, &initParams);
|
|
REPLAY_ONLY(CReplayMgr::ReplayRecordSoundPersistant(soundsetName, soundFieldName, &initParams, m_GliderSound, GetOwningEntity()));
|
|
}
|
|
}
|
|
}
|
|
|
|
if(m_GliderSound && state->numWheelsTouching > 0)
|
|
{
|
|
m_GliderSound->StopAndForget(true);
|
|
}
|
|
}
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------
|
|
// Update engine blips
|
|
// -------------------------------------------------------------------------------
|
|
void audCarAudioEntity::UpdateBlips(audVehicleVariables* state)
|
|
{
|
|
#if __BANK
|
|
if(g_DisableThrottleBlips)
|
|
{
|
|
if(m_RevsBlipSound)
|
|
{
|
|
m_RevsBlipSound->StopAndForget();
|
|
}
|
|
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
bool areBlipsAllowed = false;
|
|
|
|
if(!m_IsPlayerVehicle && !camInterface::GetCutsceneDirector().IsCutScenePlaying() && !m_StartUpRevsSound)
|
|
{
|
|
bool driverIsValid = false;
|
|
|
|
CPed* driver = m_Vehicle->GetDriver();
|
|
|
|
if(driver && !driver->ShouldBeDead() && !driver->IsNetworkPlayer())
|
|
{
|
|
CPedModelInfo* modelInfo = driver->GetPedModelInfo();
|
|
|
|
if(modelInfo)
|
|
{
|
|
driverIsValid = modelInfo->IsMale();
|
|
}
|
|
}
|
|
|
|
bool vehicleIsValid = m_Vehicle->m_Swankness > 3 && m_CarAudioSettings->VolumeCategory <= VEHICLE_VOLUME_NORMAL && !m_Vehicle->PopTypeIsMission();
|
|
bool speedIsValid = state->fwdSpeedAbs < 0.1f;
|
|
areBlipsAllowed = driverIsValid && vehicleIsValid && speedIsValid;
|
|
}
|
|
|
|
#if __BANK
|
|
areBlipsAllowed |= g_ForceEnableBlips;
|
|
#endif
|
|
|
|
if(areBlipsAllowed)
|
|
{
|
|
if(m_Vehicle->m_nVehicleFlags.bBlipThrottleRandomly || m_ForceThrottleBlip BANK_ONLY(||g_ForceEnableBlips))
|
|
{
|
|
if(m_ThrottleBlipTimer > 3400 || m_ThrottleBlipTimer <= 0)
|
|
{
|
|
m_ThrottleBlipTimer = audEngineUtil::GetRandomNumberInRange(500,3400);
|
|
}
|
|
}
|
|
else if(!m_HasBlippedSinceStopping)
|
|
{
|
|
if(m_Vehicle->IsHornOn())
|
|
{
|
|
if(m_ThrottleBlipTimer > 2000 || m_ThrottleBlipTimer <= 0)
|
|
{
|
|
m_ThrottleBlipTimer = audEngineUtil::GetRandomNumberInRange(1000,2000);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(m_ThrottleBlipTimer > 20000 || m_ThrottleBlipTimer <= 0)
|
|
{
|
|
m_ThrottleBlipTimer = audEngineUtil::GetRandomNumberInRange(10000,20000);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(!m_RevsBlipSound && m_ThrottleBlipTimer > 0)
|
|
{
|
|
m_ThrottleBlipTimer -= fwTimer::GetTimeStepInMilliseconds();
|
|
|
|
if(m_ThrottleBlipTimer <= 0)
|
|
{
|
|
CreateAndPlaySound_Persistent(ATSTRINGHASH("THROTTLE_BLIPS_RND", 0x1CF1A02A), &m_RevsBlipSound);
|
|
m_HasBlippedSinceStopping = true;
|
|
}
|
|
}
|
|
}
|
|
else if(m_RevsBlipSound)
|
|
{
|
|
m_RevsBlipSound->StopAndForget();
|
|
SetEntityVariable(ATSTRINGHASH("fakethrottle", 0xEB27990), 0.0f);
|
|
SetEntityVariable(ATSTRINGHASH("fakerevs", 0xCEB98BEB), 0.0f);
|
|
SetEntityVariable(ATSTRINGHASH("usefakeengine", 0x91DF7F97), 0.0f);
|
|
m_ThrottleBlipTimer = 0;
|
|
}
|
|
|
|
if(state->fwdSpeedAbs > 5.0f)
|
|
{
|
|
m_HasBlippedSinceStopping = false;
|
|
}
|
|
|
|
m_ForceThrottleBlip = false;
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------
|
|
// Check if the engine is upgraded
|
|
// -------------------------------------------------------------------------------
|
|
bool audCarAudioEntity::IsEngineUpgraded() const
|
|
{
|
|
return m_Vehicle->GetVariationInstance().GetModIndex(VMT_ENGINE) != INVALID_MOD BANK_ONLY(|| g_ForceUpgradeEngine || (g_EngineVolumeCaptureActive && sm_VolumeCaptureState == State_CapturingAccelModded));
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------
|
|
// Check if the transmission is upgraded
|
|
// -------------------------------------------------------------------------------
|
|
bool audCarAudioEntity::IsTransmissionUpgraded() const
|
|
{
|
|
return m_Vehicle->GetVariationInstance().GetModIndex(VMT_GEARBOX) != INVALID_MOD BANK_ONLY(|| g_ForceUpgradeTransmission);
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------
|
|
// Check if the exhaust is upgraded
|
|
// -------------------------------------------------------------------------------
|
|
bool audCarAudioEntity::IsExhaustUpgraded() const
|
|
{
|
|
return m_Vehicle->GetVariationInstance().GetModIndex(VMT_EXHAUST) != INVALID_MOD BANK_ONLY(|| g_ForceUpgradeExhaust || (g_EngineVolumeCaptureActive && sm_VolumeCaptureState == State_CapturingAccelModded));
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------
|
|
// Check if the turbo is upgraded
|
|
// -------------------------------------------------------------------------------
|
|
bool audCarAudioEntity::IsTurboUpgraded() const
|
|
{
|
|
return m_Vehicle->GetVariationInstance().GetModIndex(VMT_TURBO) != INVALID_MOD BANK_ONLY(|| g_ForceUpgradeTurbo);
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------
|
|
// Check if the radio is upgraded
|
|
// -------------------------------------------------------------------------------
|
|
bool audCarAudioEntity::IsRadioUpgraded() const
|
|
{
|
|
// CHEBUREK is a special case as it has a speaker item linked to certain livery mods, we designate which using the audio apply factor
|
|
if (GetVehicleModelNameHash() == ATSTRINGHASH("CHEBUREK", 0xC514AAE0) && m_Vehicle->GetVariationInstance().GetModIndex(VMT_LIVERY_MOD) != INVALID_MOD && m_Vehicle->GetVariationInstance().GetAudioApply(VMT_LIVERY_MOD) > 0.f)
|
|
{
|
|
return true;
|
|
}
|
|
else if (GetVehicleModelNameHash() == ATSTRINGHASH("PBUS2", 0x149BD32A))
|
|
{
|
|
return true;
|
|
}
|
|
else if (GetVehicleModelNameHash() == ATSTRINGHASH("CLUB", 0x82E47E85) && m_Vehicle->GetVariationInstance().GetModIndex(VMT_ROOF) != INVALID_MOD && m_Vehicle->GetVariationInstance().GetAudioApply(VMT_ROOF) > 0.f)
|
|
{
|
|
return true;
|
|
}
|
|
else if (m_Vehicle->GetVariationInstance().GetModIndex(VMT_ICE) != INVALID_MOD && !m_Vehicle->HasExpandedMods())
|
|
{
|
|
return true;
|
|
}
|
|
else if (m_Vehicle->GetVariationInstance().GetModIndex(VMT_TRUNK) != INVALID_MOD && m_Vehicle->GetVariationInstance().GetAudioApply(VMT_TRUNK) > 0.f)
|
|
{
|
|
return true;
|
|
}
|
|
else if (GetVehicleModelNameHash() == ATSTRINGHASH("ASBO", 0x42ACA95F) && m_Vehicle->GetVariationInstance().GetModIndex(VMT_CHASSIS) != INVALID_MOD && m_Vehicle->GetVariationInstance().GetAudioApply(VMT_CHASSIS) > 0.f)
|
|
{
|
|
return true;
|
|
}
|
|
#if __BANK
|
|
else if(g_ForceUpgradeRadio)
|
|
{
|
|
return true;
|
|
}
|
|
#endif
|
|
|
|
return false;
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------
|
|
// Get the radio offset position
|
|
// -------------------------------------------------------------------------------
|
|
Vec3V_Out audCarAudioEntity::GetRadioEmitterOffset() const
|
|
{
|
|
if(m_Vehicle && m_Vehicle->GetVariationInstance().GetModIndex(VMT_TRUNK) != INVALID_MOD && m_Vehicle->GetVariationInstance().GetAudioApply(VMT_TRUNK) > 0.f)
|
|
{
|
|
return Negate(Vec3V(V_Y_AXIS_WZERO) * ScalarV(g_TrunkRadioPositionOffset));
|
|
}
|
|
|
|
return Vec3V(V_ZERO);
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// Called when a vehicle mode is altered
|
|
// ----------------------------------------------------------------
|
|
void audCarAudioEntity::OnModChanged(eVehicleModType modSlot, u8 UNUSED_PARAM(modSlotnewModIndex))
|
|
{
|
|
if(modSlot == VMT_ENGINE || (modSlot >= VMT_ENGINEBAY1 && modSlot <= VMT_ENGINEBAY3))
|
|
{
|
|
audSound* engineEffectSubmixSound = GetEngineEffectSubmixSound();
|
|
|
|
if(engineEffectSubmixSound)
|
|
{
|
|
if((m_vehicleEngine.IsGranularEngineActive() && m_GranularEngineSettings && m_GranularEngineSettings->UpgradedEngineSynthDef != m_GranularEngineSettings->EngineSynthDef && m_GranularEngineSettings->UpgradedEngineSynthDef != 0u) ||
|
|
(!m_vehicleEngine.IsGranularEngineActive() && m_VehicleEngineSettings && m_VehicleEngineSettings->UpgradedEngineSynthDef != m_VehicleEngineSettings->EngineSynthDef && m_VehicleEngineSettings->UpgradedEngineSynthDef != 0u))
|
|
{
|
|
m_ResetDSPEffects = true;
|
|
m_ReapplyDSPPresets = true;
|
|
}
|
|
else if((m_vehicleEngine.IsGranularEngineActive() && m_GranularEngineSettings && m_GranularEngineSettings->UpgradedEngineSynthPreset != m_GranularEngineSettings->EngineSynthPreset && m_GranularEngineSettings->UpgradedEngineSynthPreset != 0u) ||
|
|
(!m_vehicleEngine.IsGranularEngineActive() && m_VehicleEngineSettings && m_VehicleEngineSettings->UpgradedEngineSynthPreset != m_VehicleEngineSettings->EngineSynthPreset && m_VehicleEngineSettings->UpgradedEngineSynthPreset != 0u))
|
|
{
|
|
m_ReapplyDSPPresets = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(modSlot == VMT_EXHAUST || (modSlot >= VMT_ENGINEBAY1 && modSlot <= VMT_ENGINEBAY3))
|
|
{
|
|
audSound* exhaustEffectSubmixSound = GetExhaustEffectSubmixSound();
|
|
|
|
if(exhaustEffectSubmixSound)
|
|
{
|
|
if((m_vehicleEngine.IsGranularEngineActive() && m_GranularEngineSettings && m_GranularEngineSettings->UpgradedExhaustSynthDef != m_GranularEngineSettings->ExhaustSynthDef && m_GranularEngineSettings->UpgradedExhaustSynthDef != 0u) ||
|
|
(!m_vehicleEngine.IsGranularEngineActive() && m_VehicleEngineSettings && m_VehicleEngineSettings->UpgradedExhaustSynthDef != m_VehicleEngineSettings->ExhaustSynthDef && m_VehicleEngineSettings->UpgradedExhaustSynthDef != 0u))
|
|
{
|
|
m_ResetDSPEffects = true;
|
|
m_ReapplyDSPPresets = true;
|
|
}
|
|
else if((m_vehicleEngine.IsGranularEngineActive() && m_GranularEngineSettings && m_GranularEngineSettings->UpgradedExhaustSynthPreset != m_GranularEngineSettings->ExhaustSynthPreset && m_GranularEngineSettings->UpgradedExhaustSynthPreset != 0u) ||
|
|
(!m_vehicleEngine.IsGranularEngineActive() && m_VehicleEngineSettings && m_VehicleEngineSettings->UpgradedExhaustSynthPreset != m_VehicleEngineSettings->ExhaustSynthPreset && m_VehicleEngineSettings->UpgradedExhaustSynthPreset != 0u))
|
|
{
|
|
m_ReapplyDSPPresets = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------
|
|
// Get the engine submix synth def
|
|
// -------------------------------------------------------------------------------
|
|
u32 audCarAudioEntity::GetEngineSubmixSynth() const
|
|
{
|
|
if(ShouldUseDSPEffects())
|
|
{
|
|
if(g_GranularEnabled && m_GranularEngineSettings)
|
|
{
|
|
if(IsEngineUpgraded() && m_GranularEngineSettings->UpgradedEngineSynthDef != 0u)
|
|
{
|
|
return m_GranularEngineSettings->UpgradedEngineSynthDef;
|
|
}
|
|
else
|
|
{
|
|
return m_GranularEngineSettings->EngineSynthDef;
|
|
}
|
|
}
|
|
else if(m_VehicleEngineSettings)
|
|
{
|
|
if(IsEngineUpgraded() && m_VehicleEngineSettings->UpgradedEngineSynthDef != 0u)
|
|
{
|
|
return m_VehicleEngineSettings->UpgradedEngineSynthDef;
|
|
}
|
|
else
|
|
{
|
|
return m_VehicleEngineSettings->EngineSynthDef;
|
|
}
|
|
}
|
|
}
|
|
|
|
return audVehicleAudioEntity::GetEngineSubmixSynth();
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------
|
|
// Get the engine submix synth preset
|
|
// -------------------------------------------------------------------------------
|
|
u32 audCarAudioEntity::GetEngineSubmixSynthPreset() const
|
|
{
|
|
if(ShouldUseDSPEffects())
|
|
{
|
|
if(g_GranularEnabled && m_GranularEngineSettings)
|
|
{
|
|
if(IsEngineUpgraded() && m_GranularEngineSettings->UpgradedEngineSynthPreset != 0u)
|
|
{
|
|
return m_GranularEngineSettings->UpgradedEngineSynthPreset;
|
|
}
|
|
else
|
|
{
|
|
return m_GranularEngineSettings->EngineSynthPreset;
|
|
}
|
|
}
|
|
else if(m_VehicleEngineSettings)
|
|
{
|
|
if(IsEngineUpgraded() && m_VehicleEngineSettings->UpgradedEngineSynthPreset != 0u)
|
|
{
|
|
return m_VehicleEngineSettings->UpgradedEngineSynthPreset;
|
|
}
|
|
else
|
|
{
|
|
return m_VehicleEngineSettings->EngineSynthPreset;
|
|
}
|
|
}
|
|
}
|
|
|
|
return audVehicleAudioEntity::GetEngineSubmixSynthPreset();
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------
|
|
// Get the exhaust submix synth def
|
|
// -------------------------------------------------------------------------------
|
|
u32 audCarAudioEntity::GetExhaustSubmixSynth() const
|
|
{
|
|
if(ShouldUseDSPEffects())
|
|
{
|
|
if(g_GranularEnabled && m_GranularEngineSettings)
|
|
{
|
|
if(IsExhaustUpgraded() && m_GranularEngineSettings->UpgradedExhaustSynthDef != 0u)
|
|
{
|
|
return m_GranularEngineSettings->UpgradedExhaustSynthDef;
|
|
}
|
|
else
|
|
{
|
|
return m_GranularEngineSettings->ExhaustSynthDef;
|
|
}
|
|
}
|
|
else if(m_VehicleEngineSettings)
|
|
{
|
|
if(IsExhaustUpgraded() && m_VehicleEngineSettings->UpgradedExhaustSynthDef != 0u)
|
|
{
|
|
return m_VehicleEngineSettings->UpgradedExhaustSynthDef;
|
|
}
|
|
else
|
|
{
|
|
return m_VehicleEngineSettings->ExhaustSynthDef;
|
|
}
|
|
}
|
|
}
|
|
|
|
return audVehicleAudioEntity::GetExhaustSubmixSynth();
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------
|
|
// Get the exhaust submix synth preset
|
|
// -------------------------------------------------------------------------------
|
|
u32 audCarAudioEntity::GetExhaustSubmixSynthPreset() const
|
|
{
|
|
if(ShouldUseDSPEffects())
|
|
{
|
|
if(g_GranularEnabled && m_GranularEngineSettings)
|
|
{
|
|
if(IsExhaustUpgraded() && m_GranularEngineSettings->UpgradedExhaustSynthPreset != 0u)
|
|
{
|
|
return m_GranularEngineSettings->UpgradedExhaustSynthPreset;
|
|
}
|
|
else
|
|
{
|
|
return m_GranularEngineSettings->ExhaustSynthPreset;
|
|
}
|
|
}
|
|
else if(m_VehicleEngineSettings)
|
|
{
|
|
if(IsExhaustUpgraded() && m_VehicleEngineSettings->UpgradedExhaustSynthPreset != 0u)
|
|
{
|
|
return m_VehicleEngineSettings->UpgradedExhaustSynthPreset;
|
|
}
|
|
else
|
|
{
|
|
return m_VehicleEngineSettings->ExhaustSynthPreset;
|
|
}
|
|
}
|
|
}
|
|
|
|
return audVehicleAudioEntity::GetExhaustSubmixSynthPreset();
|
|
}
|
|
|
|
|
|
// -------------------------------------------------------------------------------
|
|
// Get the engine submix voice
|
|
// -------------------------------------------------------------------------------
|
|
u32 audCarAudioEntity::GetEngineSubmixVoice() const
|
|
{
|
|
if(g_GranularEnabled && m_GranularEngineSettings)
|
|
{
|
|
return m_GranularEngineSettings->EngineSubmixVoice;
|
|
}
|
|
else if(m_VehicleEngineSettings)
|
|
{
|
|
return m_VehicleEngineSettings->EngineSubmixVoice;
|
|
}
|
|
|
|
return audVehicleAudioEntity::GetEngineSubmixVoice();
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------
|
|
// Get the exhaust submix voice
|
|
// -------------------------------------------------------------------------------
|
|
u32 audCarAudioEntity::GetExhaustSubmixVoice() const
|
|
{
|
|
if(g_GranularEnabled && m_GranularEngineSettings)
|
|
{
|
|
return m_GranularEngineSettings->ExhaustSubmixVoice;
|
|
}
|
|
else if(m_VehicleEngineSettings)
|
|
{
|
|
return m_VehicleEngineSettings->ExhaustSubmixVoice;
|
|
}
|
|
|
|
return audVehicleAudioEntity::GetExhaustSubmixVoice();
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------
|
|
// Get the exhaust proximity effect volume boost
|
|
// -------------------------------------------------------------------------------
|
|
f32 audCarAudioEntity::GetExhaustProximityVolumeBoost() const
|
|
{
|
|
if(m_GranularEngineSettings)
|
|
{
|
|
return m_GranularEngineSettings->ExhaustProximityVolume_PostSubmix * 0.01f;
|
|
}
|
|
|
|
return audVehicleAudioEntity::GetExhaustProximityVolumeBoost();
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// audCarAudioEntity GetCabinToneSound
|
|
// ----------------------------------------------------------------
|
|
u32 audCarAudioEntity::GetCabinToneSound() const
|
|
{
|
|
if(m_CarAudioSettings)
|
|
{
|
|
return m_CarAudioSettings->CabinToneLoop;
|
|
}
|
|
|
|
return audVehicleAudioEntity::GetCabinToneSound();
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------
|
|
// The revs boost effect slowly scales up revs and pitch to give the impression that the
|
|
// vehicle is constantly accelerating even once it is going at max speed
|
|
// -------------------------------------------------------------------------------
|
|
void audCarAudioEntity::UpdateRevsBoostEffect(audVehicleVariables* state)
|
|
{
|
|
bool suggestChangeUp = false;
|
|
|
|
if(g_RevsBoostEffectEnabled && !m_IsInAmphibiousBoatMode)
|
|
{
|
|
u32 timeSinceGearChange = state->timeInMs - m_vehicleEngine.GetTransmission()->GetLastGearChangeTimeMs();
|
|
|
|
// If we're going above the speed and rev limits, start bringing in the effect
|
|
if(state->fwdSpeedRatio > (m_IsPlayerVehicle? g_RevsBoostEffectFwdSpeedRatio : g_RevsBoostEffectFwdSpeedRatioNPC) &&
|
|
state->rawRevs > g_RevsBoostEffectRevRatio &&
|
|
state->numWheelsTouchingFactor == 1.0f &&
|
|
state->throttle == 1.0f &&
|
|
timeSinceGearChange > 2000)
|
|
{
|
|
// Kill the effect once the vehicle starts deviating from a set angular velocity. This means that cornering/weaving
|
|
// will drop the revs, allowing them to start climbing again. The limit gets stricter as we approach the top of the pitch range
|
|
f32 currentAngularVelocityLimit = g_RevsBoostAngularVelocityLimit + ((g_RevsBoostAngularVelocityLimit * g_RevsBoostAngularVelocityLimitSensitivity) * (1.0f - m_MaxSpeedPitchFactor));
|
|
|
|
// More sensitive on NPC vehicles
|
|
if(!m_IsPlayerVehicle)
|
|
{
|
|
currentAngularVelocityLimit *= 10.0f;
|
|
}
|
|
|
|
if(g_RevsBoostAngularVelocityLimit > 0.0f && Abs(GetCachedAngularVelocity().GetZ()) > currentAngularVelocityLimit)
|
|
{
|
|
// Separate decrease rates for angular velocity changes incase we want to fade the effect quicker
|
|
m_MaxSpeedRevsAddition -= (g_RevsBoostRevsScalar - 1.0f) * (fwTimer::GetTimeStep()/g_RevsBoostRevsScaleFadeOutTime);
|
|
m_MaxSpeedPitchFactor -= (fwTimer::GetTimeStep()/g_RevsBoostPitchOffsetFadeOutTime);
|
|
}
|
|
else
|
|
{
|
|
// Revs increase first
|
|
if(state->rawRevs < 1.0f)
|
|
{
|
|
m_MaxSpeedRevsAddition += (g_RevsBoostRevsScalar - 1.0f) * (fwTimer::GetTimeStep() / (g_RevsBoostRevsScaleFadeInTime * (m_IsPlayerVehicle? 1.0f : 2.0f)));
|
|
}
|
|
else
|
|
{
|
|
m_MaxSpeedRevsAddition -= (g_RevsBoostRevsScalar - 1.0f) * (fwTimer::GetTimeStep() / (g_RevsBoostRevsScaleFadeInTime * (m_IsPlayerVehicle? 1.0f : 2.0f) * 2.0f));
|
|
}
|
|
|
|
// Once revs are fully increased, bring in the pitch scale
|
|
if(state->rawRevs >= 0.98f )
|
|
{
|
|
suggestChangeUp = true;
|
|
|
|
// Only in top gear
|
|
if(!g_RevsBoostPitchOffsetOnlyInFinalGear || state->gear == m_Vehicle->m_Transmission.GetNumGears())
|
|
{
|
|
m_MaxSpeedPitchFactor += (fwTimer::GetTimeStep() / g_RevsBoostPitchOffsetFadeInTime) * (m_IsPlayerVehicle? 1.0f : 2.0f);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_MaxSpeedRevsAddition -= (g_RevsBoostRevsScalar - 1.0f) * (fwTimer::GetTimeStep()/g_RevsBoostRevsScaleFadeOutTime);
|
|
m_MaxSpeedPitchFactor -= (fwTimer::GetTimeStep()/g_RevsBoostPitchOffsetFadeOutTime);
|
|
}
|
|
|
|
m_MaxSpeedPitchFactor = Clamp(m_MaxSpeedPitchFactor, 0.0f, 1.0f);
|
|
m_MaxSpeedRevsAddition = Max(m_MaxSpeedRevsAddition, 0.0f);
|
|
|
|
f32 pitchAdditionFactor = m_MaxSpeedPitchFactor;
|
|
state->granularEnginePitchOffset = (s32)(g_RevsBoostPitchOffset * pitchAdditionFactor);
|
|
}
|
|
|
|
m_Vehicle->m_Transmission.AudioSuggestChangeUp(suggestChangeUp);
|
|
}
|
|
|
|
bool audCarAudioEntity::IsKickstarted() const
|
|
{
|
|
return m_CarAudioSettings && AUD_GET_TRISTATE_VALUE(m_CarAudioSettings->Flags, FLAG_ID_CARAUDIOSETTINGS_ISKICKSTARTED) == AUD_TRISTATE_TRUE;
|
|
}
|
|
|
|
bool audCarAudioEntity::HasCBRadio() const
|
|
{
|
|
return m_CarAudioSettings && AUD_GET_TRISTATE_VALUE(m_CarAudioSettings->Flags, FLAG_ID_CARAUDIOSETTINGS_HASCBRADIO) == AUD_TRISTATE_TRUE;
|
|
}
|
|
|
|
bool audCarAudioEntity::IsDamageModel() const
|
|
{
|
|
return GetRandomDamageClass() == RANDOM_DAMAGE_ALWAYS;
|
|
}
|
|
|
|
bool audCarAudioEntity::IsToyCar() const
|
|
{
|
|
return m_CarAudioSettings && AUD_GET_TRISTATE_VALUE(m_CarAudioSettings->Flags, FLAG_ID_CARAUDIOSETTINGS_ISTOYCAR) == AUD_TRISTATE_TRUE;
|
|
}
|
|
|
|
bool audCarAudioEntity::IsGoKart() const
|
|
{
|
|
return GetVehicleModelNameHash() == ATSTRINGHASH("Veto", 0xCCE5C8FA) || GetVehicleModelNameHash() == ATSTRINGHASH("Veto2", 0xA703E4A9);
|
|
}
|
|
|
|
bool audCarAudioEntity::IsGolfKart() const
|
|
{
|
|
const u32 modelNameHash = GetVehicleModelNameHash();
|
|
return modelNameHash == ATSTRINGHASH("Caddy", 0x44623884) || modelNameHash == ATSTRINGHASH("Caddy2", 0xDFF0594C) || modelNameHash == ATSTRINGHASH("Caddy3", 0xD227BDBB);
|
|
}
|
|
|
|
bool audCarAudioEntity::AreTyreChirpsEnabled() const
|
|
{
|
|
return m_CarAudioSettings && AUD_GET_TRISTATE_VALUE(m_CarAudioSettings->Flags, FLAG_ID_CARAUDIOSETTINGS_TYRECHIRPSENABLED) == AUD_TRISTATE_TRUE;
|
|
}
|
|
|
|
bool audCarAudioEntity::HasReverseWarning() const
|
|
{
|
|
return m_CarAudioSettings && AUD_GET_TRISTATE_VALUE(m_CarAudioSettings->Flags, FLAG_ID_CARAUDIOSETTINGS_REVERSEWARNING) == AUD_TRISTATE_TRUE;
|
|
}
|
|
|
|
bool audCarAudioEntity::HasDoorOpenWarning() const
|
|
{
|
|
return m_CarAudioSettings && AUD_GET_TRISTATE_VALUE(m_CarAudioSettings->Flags, FLAG_ID_CARAUDIOSETTINGS_DOOROPENWARNING) != AUD_TRISTATE_FALSE;
|
|
}
|
|
|
|
bool audCarAudioEntity::HasHeavyRoadNoise() const
|
|
{
|
|
return m_CarAudioSettings && AUD_GET_TRISTATE_VALUE(m_CarAudioSettings->Flags, FLAG_ID_CARAUDIOSETTINGS_HEAVYROADNOISE) == AUD_TRISTATE_TRUE;
|
|
}
|
|
|
|
bool audCarAudioEntity::CanCauseControllerRumble() const
|
|
{
|
|
// B*2136772 GTAV fix - disabling this, it got forgotten about and only set up on a solitary vehicle, making it look like a bug rather than an intentional feature
|
|
// TODO: Reinstate for future projects and actually make use of it
|
|
return false;
|
|
//return m_CarAudioSettings && AUD_GET_TRISTATE_VALUE(m_CarAudioSettings->Flags, FLAG_ID_CARAUDIOSETTINGS_CAUSECONTROLLERRUMBLE) == AUD_TRISTATE_TRUE;
|
|
}
|
|
|
|
bool audCarAudioEntity::HasAlarm()
|
|
{
|
|
const CarAudioSettings* settings = GetCarAudioSettings();
|
|
if(settings)
|
|
{
|
|
return (AUD_GET_TRISTATE_VALUE(settings->Flags, FLAG_ID_CARAUDIOSETTINGS_HASALARM) == AUD_TRISTATE_TRUE);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
RandomDamageClass audCarAudioEntity::GetRandomDamageClass() const
|
|
{
|
|
if(m_CarAudioSettings)
|
|
{
|
|
return (RandomDamageClass) m_CarAudioSettings->RandomDamage;
|
|
}
|
|
|
|
return audVehicleAudioEntity::GetRandomDamageClass();
|
|
}
|
|
|
|
void audCarAudioEntity::TriggerBrakeRelease(f32 brakeHoldTime, bool isHandbrake)
|
|
{
|
|
if(IsDisabled())
|
|
{
|
|
return;
|
|
}
|
|
|
|
if(brakeHoldTime > 0.25f && !audNorthAudioEngine::GetGtaEnvironment()->AreWeInAnInterior())
|
|
{
|
|
f32 startOffset = sm_BrakeHoldTimeToStartOffsetCurve.CalculateValue(brakeHoldTime);
|
|
audSoundInitParams initParams;
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
initParams.TrackEntityPosition = true;
|
|
initParams.StartOffset = (s32)startOffset;
|
|
initParams.IsStartOffsetPercentage = true;
|
|
CreateAndPlaySound(sm_ExtrasSoundSet.Find(isHandbrake?ATSTRINGHASH("BigRig_HandbrakeRelease", 0x2F52453A):ATSTRINGHASH("BigRig_BrakeRelease", 0xFE7CB891)), &initParams);
|
|
}
|
|
}
|
|
|
|
void audCarAudioEntity::UpdateBrakes(audVehicleVariables* state)
|
|
{
|
|
PF_FUNC(UpdateBrakes);
|
|
|
|
f32 scrapeVolLin = 0.0f;
|
|
for(s32 i = 0; i < m_Vehicle->GetNumWheels(); i++)
|
|
{
|
|
CWheel *wheel = m_Vehicle->GetWheel(i);
|
|
|
|
// check how damaged the wheel is and play metal grind sounds
|
|
// for a front wheel check the angle of the wheel and compare with steering angle to grind more
|
|
f32 speedRatio = (wheel->GetIsTouching()?Clamp(Abs(wheel->GetGroundSpeed()) * state->invDriveMaxVelocity, 0.0f,1.0f):0.0f);
|
|
|
|
f32 steeringGrindRatio = 0.5f;
|
|
|
|
if(wheel->GetConfigFlags().IsFlagSet(WCF_STEER))
|
|
{
|
|
// dot with the right vector
|
|
//f32 bentAngle = offset.x;
|
|
|
|
f32 steeringAngle = wheel->GetSteeringAngle();
|
|
steeringGrindRatio = Clamp(Abs(steeringAngle*4.0f),0.0f,1.0f);
|
|
|
|
}
|
|
|
|
// Wheels are generally completely dead by about 0.3 damage, so max out the volume a little before then
|
|
f32 damageRatio = Clamp((wheel->GetFrictionDamage() - 0.1f)/0.25f, 0.f, 1.f);
|
|
f32 vol = damageRatio * Clamp((speedRatio*2.f),0.0f,1.0f) * audDriverUtil::ComputeLinearVolumeFromDb(Lerp(steeringGrindRatio, -15.0f, 0.0f));
|
|
scrapeVolLin = Max(vol, scrapeVolLin);
|
|
|
|
if(m_vehicleEngine.GetState() != audVehicleEngine::AUD_ENGINE_OFF)
|
|
{
|
|
bool needToSetupSound = (m_WheelGrindLoops[i] == NULL);
|
|
// We position wheel loops manually so disable automatic tracking
|
|
UpdateLoopWithLinearVolumeAndPitch(&m_WheelGrindLoops[i], ATSTRINGHASH("DAMAGE_WHEEL_GRIND", 0x50040B5D), vol, i*50, m_EnvironmentGroup, NULL, true, false, 1.f, false);
|
|
if(m_WheelGrindLoops[i] && needToSetupSound)
|
|
{
|
|
Vector3 pos;
|
|
GetCachedWheelPosition(i, pos, *state);
|
|
m_WheelGrindLoops[i]->SetRequestedPosition(pos);
|
|
m_WheelGrindLoops[i]->SetClientVariable(GetWheelSoundUpdateClientVar(i));
|
|
m_WheelGrindLoops[i]->SetUpdateEntity(true);
|
|
}
|
|
}
|
|
|
|
// tyre damage
|
|
const f32 tyreHealth = wheel->GetTyreHealth() * TYRE_HEALTH_DEFAULT_INV;
|
|
u32 hashToPlay = g_NullSoundHash;
|
|
f32 tyreDamageVol = 0.f;
|
|
bool inWater = wheel->GetDynamicFlags().IsFlagSet(WF_INSHALLOWWATER) || wheel->GetDynamicFlags().IsFlagSet(WF_INDEEPWATER) BANK_ONLY(|| g_ForceShallowWater);
|
|
|
|
if(!m_Vehicle->m_nVehicleFlags.bIsAsleep && wheel->GetIsFlat() && m_Vehicle->GetWheel(i)->GetIsTouching() && !inWater)
|
|
{
|
|
if(tyreHealth > 0.f)
|
|
{
|
|
tyreDamageVol = Min(1.f, speedRatio * 2.f);
|
|
// still have some tyre
|
|
hashToPlay = ATSTRINGHASH("FLAT_TYRE", 0x5741B3C5);
|
|
}
|
|
else
|
|
{
|
|
// no tyre left. Speed is greatly reduced, so scale back the speed ratio when calculating volume
|
|
tyreDamageVol = Clamp(Max(state->fwdSpeedRatio, speedRatio)/0.2f, 0.0f, 1.0f);
|
|
hashToPlay = ATSTRINGHASH("WHEEL_RIM", 0x6A8F09B3);
|
|
|
|
// catch the case where we were playing rubber and we're now down to the rim
|
|
if(!m_IsTyreCompletelyDead.IsSet(i))
|
|
{
|
|
if(m_TyreDamageLoops[i])
|
|
{
|
|
m_TyreDamageLoops[i]->StopAndForget();
|
|
}
|
|
|
|
m_IsTyreCompletelyDead.Set(i);
|
|
}
|
|
|
|
VfxGroup_e vfxGroup = PGTAMATERIALMGR->GetMtlVfxGroup(m_Vehicle->GetWheel(i)->GetMaterialId());
|
|
VfxWheelInfo_s* pVfxWheelInfo = g_vfxWheel.GetInfo(VFXTYRESTATE_BURST_DRY, vfxGroup);
|
|
|
|
if(pVfxWheelInfo)
|
|
{
|
|
CVfxVehicleInfo* pVfxVehicleInfo = g_vfxVehicleInfoMgr.GetInfo(m_Vehicle);
|
|
|
|
if(pVfxVehicleInfo)
|
|
{
|
|
atHashWithStringNotFinal ptFxHashName;
|
|
|
|
if (pVfxVehicleInfo->GetWheelGenericPtFxSet()==2)
|
|
{
|
|
ptFxHashName = pVfxWheelInfo->ptFxWheelFric2HashName;
|
|
}
|
|
else
|
|
{
|
|
ptFxHashName = pVfxWheelInfo->ptFxWheelFric1HashName;
|
|
}
|
|
|
|
if(ptFxHashName.GetHash() != ATSTRINGHASH("rim_fric_hard", 0x9F6F204C))
|
|
{
|
|
tyreDamageVol = 0.f;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(!m_TyreDamageLoops[i])
|
|
{
|
|
if(tyreDamageVol > g_SilenceVolumeLin)
|
|
{
|
|
audSoundInitParams initParams;
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
CreateSound_PersistentReference(hashToPlay, &m_TyreDamageLoops[i], &initParams);
|
|
if(m_TyreDamageLoops[i])
|
|
{
|
|
Vector3 pos;
|
|
GetCachedWheelPosition(i, pos, *state);
|
|
m_TyreDamageLoops[i]->SetUpdateEntity(true);
|
|
m_TyreDamageLoops[i]->SetRequestedPosition(pos);
|
|
m_TyreDamageLoops[i]->SetClientVariable(GetWheelSoundUpdateClientVar(i));
|
|
m_TyreDamageLoops[i]->PrepareAndPlay();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if(m_TyreDamageLoops[i])
|
|
{
|
|
if(tyreDamageVol < g_SilenceVolumeLin)
|
|
{
|
|
m_TyreDamageLoops[i]->StopAndForget();
|
|
}
|
|
else
|
|
{
|
|
const f32 pitch = 760.f * state->wheelSpeedRatio;
|
|
m_TyreDamageLoops[i]->SetRequestedPitch((s32)pitch);
|
|
m_TyreDamageLoops[i]->SetRequestedVolume(audDriverUtil::ComputeDbVolumeFromLinear(tyreDamageVol));
|
|
}
|
|
}
|
|
}
|
|
|
|
m_BrakeLinearVolumeSmoother.SetRates(g_BrakeLinearVolumeSmootherRate / 1000.0f, 0.01f);
|
|
f32 minSuspensionHealth = SUSPENSION_HEALTH_DEFAULT;
|
|
for(s32 i = 0 ; i < m_Vehicle->GetNumWheels(); i++)
|
|
{
|
|
minSuspensionHealth = Min(m_Vehicle->GetVehicleDamage()->GetSuspensionHealth(i), minSuspensionHealth);
|
|
}
|
|
const f32 suspensionDamageFactor = Max(m_ScriptBodyDamageFactor, 1.0f - minSuspensionHealth / SUSPENSION_HEALTH_DEFAULT);
|
|
f32 volLin = 0.0f;
|
|
|
|
if(m_vehicleEngine.GetState() != audVehicleEngine::AUD_ENGINE_OFF && !m_Vehicle->m_nVehicleFlags.bIsBeingTowed && !m_IsInAmphibiousBoatMode)
|
|
{
|
|
volLin = m_CarAudioSettings->BrakeSqueekFactor * sm_BrakeToBrakeDiscVolumeCurve.CalculateValue(state->brakePedal) * sm_SpeedToBrakeDiscVolumeCurve.CalculateValue(state->speedForBrakes) * audDriverUtil::ComputeLinearVolumeFromDb(state->carVolOffset + ((1.f - suspensionDamageFactor) * -4.f));
|
|
// if there is a wheel knackered then also apply some brake disc squeal while the wheel is rotating
|
|
volLin = Max(volLin, scrapeVolLin*0.4f);
|
|
}
|
|
|
|
f32 volLinSmoothed = m_BrakeLinearVolumeSmoother.CalculateValue(volLin, state->timeInMs);
|
|
bool hasBigRigBrakes = AUD_GET_TRISTATE_VALUE(m_CarAudioSettings->Flags, FLAG_ID_CARAUDIOSETTINGS_BIGRIGBRAKES) == AUD_TRISTATE_TRUE;
|
|
UpdateLoopWithLinearVolumeAndPitch(&m_DiscBrakeSqueel,(hasBigRigBrakes?ATSTRINGHASH("BIG_RIG_DISC_BRAKE", 0xF67F84FA):ATSTRINGHASH("DISC_BRAKE_SQUEEL_LOOP", 0x8F09D5E0)), volLinSmoothed, 0, m_EnvironmentGroup, NULL, true, false);
|
|
|
|
if(m_vehicleEngine.GetState() != audVehicleEngine::AUD_ENGINE_OFF)
|
|
{
|
|
if(hasBigRigBrakes)
|
|
{
|
|
// if vehicle is stationary then charge up brakes (pseudo-handbrake)
|
|
if(state->fwdSpeed < 0.1f && m_Vehicle->m_nVehicleFlags.bEngineOn)
|
|
{
|
|
if(m_WasStationaryLastFrame)
|
|
{
|
|
m_TimeStationary += fwTimer::GetTimeStep();
|
|
}
|
|
else
|
|
{
|
|
m_TimeStationary = 0.0f;
|
|
}
|
|
|
|
m_WasStationaryLastFrame = true;
|
|
}
|
|
else
|
|
{
|
|
// dont trigger the release if the engine turns off
|
|
if(m_WasStationaryLastFrame && m_TimeStationary >= sm_TimeToApplyHandbrake && m_Vehicle->GetThrottle() > 0.1f)
|
|
{
|
|
TriggerBrakeRelease(m_TimeStationary - sm_TimeToApplyHandbrake, true);
|
|
}
|
|
|
|
m_WasStationaryLastFrame = false;
|
|
|
|
}
|
|
|
|
f32 brakePedal = state->brakePedal;
|
|
|
|
if(GetVehicleModelNameHash() == ATSTRINGHASH("CHERNOBOG", 0xD6BC7523) && m_Vehicle->GetOutriggerDeployRatio() > 0.f)
|
|
{
|
|
brakePedal = 0.f;
|
|
}
|
|
|
|
if(brakePedal > 0.1f)
|
|
{
|
|
if(m_WasBrakeHeldLastFrame)
|
|
{
|
|
m_BrakeHoldTime += fwTimer::GetTimeStep();
|
|
}
|
|
else
|
|
{
|
|
m_BrakeHoldTime = 0.f;
|
|
}
|
|
m_WasBrakeHeldLastFrame = true;
|
|
}
|
|
else
|
|
{
|
|
if(m_WasBrakeHeldLastFrame)
|
|
{
|
|
TriggerBrakeRelease(m_BrakeHoldTime, false);
|
|
}
|
|
|
|
m_WasBrakeHeldLastFrame = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void audCarAudioEntity::TriggerHandbrakeSound()
|
|
{
|
|
if(IsDisabled())
|
|
{
|
|
return;
|
|
}
|
|
|
|
if(m_vehicleEngine.WasEngineOnLastFrame() && m_CarAudioSettings)
|
|
{
|
|
audSoundInitParams initParams;
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
initParams.TrackEntityPosition = true;
|
|
CreateAndPlaySound(m_CarAudioSettings->Handbrake, &initParams);
|
|
|
|
REPLAY_ONLY(CReplayMgr::ReplayRecordSound(m_CarAudioSettings->Handbrake, &initParams, m_Vehicle));
|
|
}
|
|
}
|
|
|
|
void audCarAudioEntity::UpdateIndicator()
|
|
{
|
|
if(m_HasIndicatorRequest)
|
|
{
|
|
const bool isOn = m_IsIndicatorRequestedOn;
|
|
if(m_CarAudioSettings)
|
|
{
|
|
u32 hash = 0;
|
|
if(m_IsIndicatorOn && !isOn)
|
|
{
|
|
// trigger off
|
|
hash = m_CarAudioSettings->IndicatorOff;
|
|
}
|
|
else if(!m_IsIndicatorOn && isOn)
|
|
{
|
|
// trigger on
|
|
hash = m_CarAudioSettings->IndicatorOn;
|
|
}
|
|
if(hash!=0)
|
|
{
|
|
audSoundInitParams initParams;
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
initParams.TrackEntityPosition = true;
|
|
|
|
f32 vol;
|
|
u32 cutoff;
|
|
GetInteriorSoundOcclusion(vol,cutoff);
|
|
initParams.Volume = Max(vol, -6.f);
|
|
|
|
CreateAndPlaySound(hash, &initParams);
|
|
}
|
|
}
|
|
m_IsIndicatorOn = isOn;
|
|
m_HasIndicatorRequest = false;
|
|
}
|
|
}
|
|
|
|
bool audCarAudioEntity::DoesHornHaveTail() const
|
|
{
|
|
// HL - Hacky fix here to support new horns for the BTYPE vehicle:
|
|
// The BTYPE's default claxon-style horn uses an on-stop sound to play a tail, hence we don't want to use the
|
|
// standard horn release time value as it cuts it off.
|
|
const u32 vehicleModelNameHash = GetVehicleModelNameHash();
|
|
|
|
if(vehicleModelNameHash == ATSTRINGHASH("BTYPE", 0x6FF6914) || vehicleModelNameHash == ATSTRINGHASH("BTYPE3", 0xDC19D101))
|
|
{
|
|
CVehicleVariationInstance& variation = m_Vehicle->GetVariationInstance();
|
|
|
|
if(variation.GetMods()[VMT_HORN] == INVALID_MOD)
|
|
{
|
|
// No mod - must be using the default horn
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
u32 modeKitHash = variation.GetKit()->GetStatMods()[variation.GetMods()[VMT_HORN]].GetModifier();
|
|
|
|
if(modeKitHash == 0)
|
|
{
|
|
// No mod - must be using the default horn
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
// End hacky fix
|
|
|
|
return false;
|
|
}
|
|
|
|
u32 audCarAudioEntity::GetVehicleHornSoundHash(bool ignoreMods)
|
|
{
|
|
u32 vehicleHornHash = 0;
|
|
if(m_Vehicle && GetCarAudioSettings())
|
|
{
|
|
u32 hornSoundsHash = GetCarAudioSettings()->HornSounds;
|
|
|
|
// HL - Hacky fix here to support new horns for the BTYPE vehicle:
|
|
// The new horn assets are bundled in with the vehicle engine bank, so we need to duplicate them in both the NPC and
|
|
// player banks so that cars can still honk even if the player isn't driving them. This means that we need to play a
|
|
// different sound depending on whether or not this is a player vehicle.
|
|
const u32 vehicleModelNameHash = GetVehicleModelNameHash();
|
|
|
|
if(vehicleModelNameHash == ATSTRINGHASH("BTYPE", 0x6FF6914))
|
|
{
|
|
if(m_IsPlayerVehicle)
|
|
{
|
|
hornSoundsHash = ATSTRINGHASH("HORN_LIST_BTYPE", 0x329FE267);
|
|
}
|
|
else
|
|
{
|
|
hornSoundsHash = ATSTRINGHASH("HORN_LIST_BTYPE_NPC", 0x5A5E45C6);
|
|
}
|
|
}
|
|
else if(vehicleModelNameHash == ATSTRINGHASH("BTYPE3", 0xDC19D101))
|
|
{
|
|
if(m_IsPlayerVehicle)
|
|
{
|
|
hornSoundsHash = ATSTRINGHASH("HORN_LIST_BTYPE3", 0x28435C95);
|
|
}
|
|
else
|
|
{
|
|
hornSoundsHash = ATSTRINGHASH("HORN_LIST_BTYPE3_NPC", 0xE6E47A37);
|
|
}
|
|
}
|
|
// End hacky fix
|
|
|
|
SoundHashList* hornSounds = g_AudioEngine.GetSoundManager().GetFactory().GetMetadataManager().GetObject<SoundHashList>(hornSoundsHash);
|
|
if(naVerifyf(hornSounds, "Vehicle has no horn Sounds."))
|
|
{
|
|
if( m_HornSoundIndex == -1)
|
|
{
|
|
m_HornSoundIndex = static_cast<s16>(hornSounds->CurrentSoundIdx);
|
|
naAssertf(m_HornSoundIndex != -1, "Fail getting the horn index, please contact audio team.");
|
|
hornSounds->CurrentSoundIdx = (hornSounds->CurrentSoundIdx + 1) % hornSounds->numSoundHashes;
|
|
}
|
|
if(naVerifyf(m_HornSoundIndex < hornSounds->numSoundHashes,"Wrong horn index."))
|
|
{
|
|
vehicleHornHash = hornSounds->SoundHashes[m_HornSoundIndex].SoundHash;
|
|
}
|
|
|
|
}
|
|
if(!ignoreMods)
|
|
{
|
|
CVehicleVariationInstance& variation = m_Vehicle->GetVariationInstance();
|
|
if(variation.GetMods()[VMT_HORN] != INVALID_MOD)
|
|
{
|
|
u32 modKitHash = variation.GetKit()->GetStatMods()[variation.GetMods()[VMT_HORN]].GetModifier();
|
|
if( modKitHash != 0)
|
|
{
|
|
vehicleHornHash = modKitHash;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return vehicleHornHash;
|
|
}
|
|
|
|
void audCarAudioEntity::BlipHorn()
|
|
{
|
|
if(m_CarAudioSettings)
|
|
{
|
|
audEnvelopeSound *envelopeSound;
|
|
audSoundInitParams initParams;
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
const Vector3 pos = VEC3V_TO_VECTOR3(m_Vehicle->TransformIntoWorldSpace(m_HornOffsetPos));
|
|
initParams.Position = pos;
|
|
CreateSound_LocalReference(ATSTRINGHASH("UTIL_ENVELOPE", 0xF4983BA1),(audSound**)&envelopeSound, &initParams);
|
|
if(envelopeSound)
|
|
{
|
|
envelopeSound->SetRequestedEnvelope(30, 0,100,100,50);
|
|
envelopeSound->SetChildSoundReference(GetVehicleHornSoundHash());
|
|
envelopeSound->SetClientVariable((u32)AUD_VEHICLE_SOUND_HORN);
|
|
envelopeSound->SetUpdateEntity(true);
|
|
envelopeSound->PrepareAndPlay(NULL, false, 100);
|
|
}
|
|
}
|
|
}
|
|
|
|
void audCarAudioEntity::TriggerDoorOpenSound(eHierarchyId doorId)
|
|
{
|
|
if(IsDisabled())
|
|
{
|
|
return;
|
|
}
|
|
|
|
if(m_CarAudioSettings)
|
|
{
|
|
u32 hash = g_NullSoundHash;
|
|
|
|
// Zhaba boot/door correspond to the small flaps on the side of the vehicle
|
|
if (GetVehicleModelNameHash() == ATSTRINGHASH("ZHABA", 0x4C8DBA51) && (doorId == VEH_BONNET || doorId == VEH_BOOT))
|
|
{
|
|
hash = m_CarAudioSettings->BootOpenSound;
|
|
}
|
|
else if(doorId == VEH_BONNET)
|
|
{
|
|
hash = ATSTRINGHASH("VEHICLES_EXTRAS_DAMAGED_HOOD_OPEN", 0x34DA9EFC);
|
|
}
|
|
else if(doorId == VEH_BOOT)
|
|
{
|
|
hash = m_CarAudioSettings->BootOpenSound;
|
|
}
|
|
else
|
|
{
|
|
hash = m_CarAudioSettings->DoorOpenSound;
|
|
}
|
|
TriggerDoorSound(hash, doorId);
|
|
}
|
|
}
|
|
|
|
void audCarAudioEntity::TriggerDoorCloseSound(eHierarchyId doorId, const bool isBroken)
|
|
{
|
|
if(IsDisabled())
|
|
{
|
|
return;
|
|
}
|
|
|
|
// 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_CarAudioSettings)
|
|
{
|
|
u32 hash = g_NullSoundHash;
|
|
|
|
// Zhaba boot/door correspond to the small flaps on the side of the vehicle
|
|
if (GetVehicleModelNameHash() == ATSTRINGHASH("ZHABA", 0x4C8DBA51) && (doorId == VEH_BONNET || doorId == VEH_BOOT))
|
|
{
|
|
hash = m_CarAudioSettings->BootCloseSound;
|
|
}
|
|
else if(doorId == VEH_BOOT || doorId == VEH_BONNET)
|
|
{
|
|
if(isBroken)
|
|
{
|
|
if(fwTimer::GetTimeInMilliseconds() < m_NextDoorTime)
|
|
{
|
|
return;
|
|
}
|
|
m_NextDoorTime = fwTimer::GetTimeInMilliseconds() + audEngineUtil::GetRandomNumberInRange(100,300);
|
|
hash = ATSTRINGHASH("VEHICLES_EXTRAS_DAMAGED_HOOD_SHUT", 0x209CA2D3);
|
|
}
|
|
else
|
|
{
|
|
hash = m_CarAudioSettings->BootCloseSound;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hash = m_CarAudioSettings->DoorCloseSound;
|
|
}
|
|
|
|
TriggerDoorSound(hash, doorId, volumeOffset);
|
|
}
|
|
}
|
|
|
|
void audCarAudioEntity::OnPlayerOpenDoor()
|
|
{
|
|
const u32 now = g_AudioEngine.GetSoundManager().GetTimeInMilliseconds(0);
|
|
if(m_PlayerVehicleAlarmBehaviour &&
|
|
now > m_TimeAlarmLastArmed + 5000 &&
|
|
m_Vehicle &&
|
|
m_Vehicle->m_Swankness >= 3 &&
|
|
m_Vehicle->GetHealth() > 250.f &&
|
|
!m_Vehicle->IsEngineOn() &&
|
|
m_Vehicle->GetNumberOfPassenger() == 0 &&
|
|
m_Vehicle->GetDriver() == NULL &&
|
|
m_VehicleType == AUD_VEHICLE_CAR)
|
|
{
|
|
m_PlayerVehicleAlarmBehaviour = false;
|
|
m_TimeAlarmLastArmed = now;
|
|
audSoundInitParams initParams;
|
|
initParams.TrackEntityPosition = true;
|
|
initParams.EnvironmentGroup = m_EnvironmentGroup;
|
|
CreateAndPlaySound(sm_ExtrasSoundSet.Find(ATSTRINGHASH("Alarm_Disarm", 0x95DE98C6)), &initParams);
|
|
|
|
REPLAY_ONLY(CReplayMgr::ReplayRecordSound(sm_ExtrasSoundSet.GetNameHash(), ATSTRINGHASH("Alarm_Disarm", 0x95DE98C6), &initParams, m_Vehicle));
|
|
}
|
|
}
|
|
|
|
void audCarAudioEntity::TriggerDoorFullyOpenSound(eHierarchyId doorId)
|
|
{
|
|
if(IsDisabled())
|
|
{
|
|
return;
|
|
}
|
|
|
|
if(m_CarAudioSettings)
|
|
{
|
|
if(GetVehicleModelNameHash() != ATSTRINGHASH("Draugur", 0xD235A4A6))
|
|
{
|
|
TriggerDoorSound(ATSTRINGHASH("VEHICLES_EXTRAS_DOOR_LIMIT", 0xE4126EED), doorId);
|
|
}
|
|
}
|
|
}
|
|
|
|
u32 audCarAudioEntity::GetJumpLandingSound(bool interiorView) const
|
|
{
|
|
if(m_CarAudioSettings)
|
|
{
|
|
if(interiorView && m_CarAudioSettings->JumpLandSoundInterior != g_NullSoundHash)
|
|
{
|
|
return m_CarAudioSettings->JumpLandSoundInterior;
|
|
}
|
|
else
|
|
{
|
|
return m_CarAudioSettings->JumpLandSound;
|
|
}
|
|
}
|
|
|
|
return audVehicleAudioEntity::GetJumpLandingSound(interiorView);
|
|
}
|
|
|
|
u32 audCarAudioEntity::GetVehicleRainSound(bool interiorView) const
|
|
{
|
|
if(m_CarAudioSettings)
|
|
{
|
|
if(interiorView)
|
|
{
|
|
return m_CarAudioSettings->VehicleRainSoundInterior;
|
|
}
|
|
else
|
|
{
|
|
return m_CarAudioSettings->VehicleRainSound;
|
|
}
|
|
}
|
|
|
|
return audVehicleAudioEntity::GetVehicleRainSound(interiorView);
|
|
}
|
|
|
|
u32 audCarAudioEntity::GetTowTruckSoundSet() const
|
|
{
|
|
if(m_CarAudioSettings)
|
|
{
|
|
return m_CarAudioSettings->TowTruckSounds;
|
|
}
|
|
|
|
return audVehicleAudioEntity::GetTowTruckSoundSet();
|
|
}
|
|
|
|
u32 audCarAudioEntity::GetDamagedJumpLandingSound(bool interiorView) const
|
|
{
|
|
if(m_CarAudioSettings)
|
|
{
|
|
if(interiorView && m_CarAudioSettings->DamagedJumpLandSoundInterior != g_NullSoundHash)
|
|
{
|
|
return m_CarAudioSettings->DamagedJumpLandSoundInterior;
|
|
}
|
|
else
|
|
{
|
|
return m_CarAudioSettings->DamagedJumpLandSound;
|
|
}
|
|
}
|
|
|
|
return audVehicleAudioEntity::GetDamagedJumpLandingSound(interiorView);
|
|
}
|
|
|
|
u32 audCarAudioEntity::GetNPCRoadNoiseSound() const
|
|
{
|
|
if(m_CarAudioSettings)
|
|
{
|
|
if(m_Vehicle->GetIntelligence()->IsOnHighway())
|
|
{
|
|
return m_CarAudioSettings->NPCRoadNoiseHighway;
|
|
}
|
|
else
|
|
{
|
|
return m_CarAudioSettings->NPCRoadNoise;
|
|
}
|
|
}
|
|
|
|
return audVehicleAudioEntity::GetNPCRoadNoiseSound();
|
|
}
|
|
|
|
u32 audCarAudioEntity::GetReverseWarningSound() const
|
|
{
|
|
if(m_CarAudioSettings)
|
|
{
|
|
return m_CarAudioSettings->ReverseWarningSound;
|
|
}
|
|
|
|
return audVehicleAudioEntity::GetReverseWarningSound();
|
|
}
|
|
|
|
u32 audCarAudioEntity::GetForkliftSoundSet() const
|
|
{
|
|
if(m_CarAudioSettings)
|
|
{
|
|
return m_CarAudioSettings->ForkliftSounds;
|
|
}
|
|
|
|
return audVehicleAudioEntity::GetForkliftSoundSet();
|
|
}
|
|
|
|
u32 audCarAudioEntity::GetDiggerSoundSet() const
|
|
{
|
|
if(m_CarAudioSettings)
|
|
{
|
|
return m_CarAudioSettings->DiggerSounds;
|
|
}
|
|
|
|
return audVehicleAudioEntity::GetDiggerSoundSet();
|
|
}
|
|
|
|
u32 audCarAudioEntity::GetConvertibleRoofSoundSet() const
|
|
{
|
|
if(m_CarAudioSettings)
|
|
{
|
|
return m_CarAudioSettings->ConvertibleRoofSoundSet;
|
|
}
|
|
|
|
return audVehicleAudioEntity::GetConvertibleRoofSoundSet();
|
|
}
|
|
|
|
u32 audCarAudioEntity::GetConvertibleRoofInteriorSoundSet() const
|
|
{
|
|
if(m_CarAudioSettings)
|
|
{
|
|
return m_CarAudioSettings->ConvertibleRoofInteriorSoundSet;
|
|
}
|
|
|
|
return audVehicleAudioEntity::GetConvertibleRoofInteriorSoundSet();
|
|
}
|
|
|
|
u32 audCarAudioEntity::GetTurretSoundSet() const
|
|
{
|
|
if(m_CarAudioSettings)
|
|
{
|
|
return m_CarAudioSettings->TurretSounds;
|
|
}
|
|
|
|
return audVehicleAudioEntity::GetTurretSoundSet();
|
|
}
|
|
|
|
|
|
u32 audCarAudioEntity::GetWindNoiseSound() const
|
|
{
|
|
if(m_CarAudioSettings)
|
|
{
|
|
return m_CarAudioSettings->WindNoise;
|
|
}
|
|
|
|
return audVehicleAudioEntity::GetWindNoiseSound();
|
|
}
|
|
|
|
u32 audCarAudioEntity::GetEngineIgnitionLoopSound() const
|
|
{
|
|
if(m_VehicleEngineSettings)
|
|
{
|
|
return m_VehicleEngineSettings->Ignition;
|
|
}
|
|
|
|
return audVehicleAudioEntity::GetEngineIgnitionLoopSound();
|
|
}
|
|
|
|
u32 audCarAudioEntity::GetEngineShutdownSound() const
|
|
{
|
|
if(m_VehicleEngineSettings)
|
|
{
|
|
return m_VehicleEngineSettings->EngineShutdown;
|
|
}
|
|
|
|
return audVehicleAudioEntity::GetEngineShutdownSound();
|
|
}
|
|
|
|
u32 audCarAudioEntity::GetVehicleShutdownSound() const
|
|
{
|
|
if(m_CarAudioSettings)
|
|
{
|
|
return m_CarAudioSettings->CarSpecificShutdownSound;
|
|
}
|
|
|
|
return audVehicleAudioEntity::GetVehicleShutdownSound();
|
|
}
|
|
|
|
u32 audCarAudioEntity::GetEngineStartupSound() const
|
|
{
|
|
if(m_VehicleEngineSettings)
|
|
{
|
|
return m_VehicleEngineSettings->EngineStartUp;
|
|
}
|
|
else if(m_ElectricEngineSettings)
|
|
{
|
|
return m_ElectricEngineSettings->EngineStartUp;
|
|
}
|
|
|
|
return audVehicleAudioEntity::GetEngineStartupSound();
|
|
}
|
|
|
|
bool audCarAudioEntity::IsElectricOrHybrid() const
|
|
{
|
|
if(m_CarAudioSettings)
|
|
{
|
|
if(m_CarAudioSettings->EngineType == ELECTRIC || m_CarAudioSettings->EngineType == HYBRID)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
VehicleCollisionSettings* audCarAudioEntity::GetVehicleCollisionSettings() const
|
|
{
|
|
if(m_CarAudioSettings)
|
|
{
|
|
return audNorthAudioEngine::GetObject<VehicleCollisionSettings>(m_CarAudioSettings->VehicleCollisions);
|
|
}
|
|
|
|
return audVehicleAudioEntity::GetVehicleCollisionSettings();
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// Compute the ignition hold time
|
|
// ----------------------------------------------------------------
|
|
f32 audCarAudioEntity::ComputeIgnitionHoldTime(bool isStartingThisTime)
|
|
{
|
|
bool isStartingFirstTime = (isStartingThisTime && m_Vehicle->m_failedEngineStartAttempts == 0);
|
|
f32 maxHold = (isStartingFirstTime?sm_StartingIgnitionMaxHold:sm_IgnitionMaxHold);
|
|
f32 minHold = (isStartingFirstTime?sm_StartingIgnitionMinHold:sm_IgnitionMinHold);
|
|
f32 timeFactor = 1.f;
|
|
|
|
// Electric engines just click on immediately
|
|
if(m_CarAudioSettings && m_CarAudioSettings->EngineType == ELECTRIC)
|
|
{
|
|
m_IgnitionHoldTime = 0.0f;
|
|
}
|
|
else
|
|
{
|
|
if(!isStartingFirstTime && (m_Vehicle->GetStatus() == STATUS_WRECKED || m_Vehicle->m_Transmission.GetEngineHealth() <= ENGINE_DAMAGE_ONFIRE || !CTaskMotionInAutomobile::IsVehicleDrivable(*m_Vehicle)))
|
|
{
|
|
// its not going to start so try for longer
|
|
timeFactor = 2.5f;
|
|
}
|
|
else if(HasHeavyRoadNoise())
|
|
{
|
|
timeFactor = 1.5f;
|
|
}
|
|
// Don't like hard coding the sound name here, but we've got non-granular trucks that aren't set to have heavy road noise so this is the simplest way to identify them
|
|
else if(!m_vehicleEngine.IsGranularEngineActive() && m_VehicleEngineSettings && m_VehicleEngineSettings->Ignition == ATSTRINGHASH("IGNITION_TRUCK", 0xFBF1D8BA))
|
|
{
|
|
timeFactor = 1.5f;
|
|
}
|
|
|
|
if(m_Vehicle->m_nVehicleFlags.bCarNeedsToBeHotwired)
|
|
{
|
|
// Doing a little ignition at the end of the hotwire anim, need to keep it short to fit with the visuals
|
|
maxHold = minHold;
|
|
}
|
|
|
|
m_IgnitionHoldTime = audEngineUtil::GetRandomNumberInRange(minHold * timeFactor, maxHold * timeFactor);
|
|
}
|
|
|
|
return m_IgnitionHoldTime;
|
|
}
|
|
|
|
VehicleVolumeCategory audCarAudioEntity::GetVehicleVolumeCategory()
|
|
{
|
|
if (m_CarAudioSettings)
|
|
{
|
|
return (VehicleVolumeCategory) m_CarAudioSettings->VolumeCategory;
|
|
}
|
|
|
|
return VEHICLE_VOLUME_NORMAL;
|
|
}
|
|
|
|
f32 audCarAudioEntity::GetVehicleModelRadioVolume() const
|
|
{
|
|
if(m_CarAudioSettings)
|
|
{
|
|
return m_CarAudioSettings->AmbientRadioVol;
|
|
}
|
|
|
|
return 0.0f;
|
|
}
|
|
|
|
f32 audCarAudioEntity::GetControllerRumbleIntensity() const
|
|
{
|
|
// For now - just full intensity while the startup sound is playing. May want to customize this with a curve or something
|
|
if(m_IsPlayerVehicle && CanCauseControllerRumble() && m_vehicleEngine.GetStartupSound() != NULL)
|
|
{
|
|
return 1.0f;
|
|
}
|
|
|
|
return audVehicleAudioEntity::GetControllerRumbleIntensity();
|
|
}
|
|
|
|
f32 audCarAudioEntity::GetEngineSwitchFadeTimeScalar() const
|
|
{
|
|
if(!m_IsPlayerVehicle)
|
|
{
|
|
// If we're low on vehicles, we can be a bit more lazy with our fade time - the lack of vehicles makes the sharper
|
|
// cuts in/out more obvious, so this improves the sound of the transitions
|
|
if(m_Vehicle->GetOwnedBy() != ENTITY_OWNEDBY_CUTSCENE &&
|
|
m_Vehicle->GetOwnedBy() != ENTITY_OWNEDBY_SCRIPT)
|
|
{
|
|
if(sm_ActivationRangeScale == g_MaxRealRangeScale &&
|
|
(!m_vehicleEngine.IsGranularEngineActive() || sm_GranularActivationRangeScale == g_MaxGranularRangeScale))
|
|
{
|
|
return 2.0f;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 1.0f;
|
|
}
|
|
|
|
f32 audCarAudioEntity::GetInteriorViewEngineOpenness() const
|
|
{
|
|
if(m_CarAudioSettings)
|
|
{
|
|
return m_CarAudioSettings->InteriorViewEngineOpenness;
|
|
}
|
|
|
|
return audVehicleAudioEntity::GetInteriorViewEngineOpenness();
|
|
}
|
|
|
|
f32 audCarAudioEntity::GetMinOpenness() const
|
|
{
|
|
f32 openness = 0.f;
|
|
if(m_CarAudioSettings)
|
|
{
|
|
openness = m_CarAudioSettings->Openness;
|
|
}
|
|
//CVehicleVariationInstance& variation = m_Vehicle->GetVariationInstance();
|
|
//if(variation.GetMods()[VMT_ROOF] != 255)
|
|
//{
|
|
// if(variation.GetKit()->GetStatMods()[variation.GetMods()[VMT_HORN]].GetModifier() != 0)
|
|
// {
|
|
// hornSound = variation.GetKit()->GetStatMods()[variation.GetMods()[VMT_HORN]].GetModifier();
|
|
// }
|
|
//}
|
|
return openness;
|
|
}
|
|
void audCarAudioEntity::Fix()
|
|
{
|
|
audVehicleAudioEntity::Fix();
|
|
|
|
// also fix all car tyres
|
|
m_IsTyreCompletelyDead.Reset();
|
|
}
|
|
|
|
f32 audCarAudioEntity::GetSkidVolumeScale() const
|
|
{
|
|
if(m_CarAudioSettings && AUD_GET_TRISTATE_VALUE(m_CarAudioSettings->Flags, FLAG_ID_CARAUDIOSETTINGS_DISABLESKIDS) == AUD_TRISTATE_TRUE)
|
|
{
|
|
return 0.f;
|
|
}
|
|
return 1.f;
|
|
}
|
|
|
|
AmbientRadioLeakage audCarAudioEntity::GetPositionalPlayerRadioLeakage() const
|
|
{
|
|
return GetAmbientRadioLeakage();
|
|
}
|
|
|
|
bool audCarAudioEntity::IsSubmersible() const
|
|
{
|
|
if(m_Vehicle->InheritsFromSubmarineCar() && m_IsInAmphibiousBoatMode)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return audVehicleAudioEntity::IsSubmersible();
|
|
}
|
|
|
|
bool audCarAudioEntity::IsPlayingStartupSequence() const
|
|
{
|
|
if(m_StartUpRevsSound)
|
|
{
|
|
const u32 playTimeMs = m_StartUpRevsSound->GetCurrentPlayTime(g_AudioEngine.GetSoundManager().GetTimeInMilliseconds(0));
|
|
static u32 s_StartupSequenceTime = 500;
|
|
if(playTimeMs <= s_StartupSequenceTime)
|
|
{
|
|
// Only count the first 0.5s of the sequence
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
else if(m_HasPlayedStartupSequence)
|
|
{
|
|
return false;
|
|
}
|
|
// We'll be in a starting state before we've played the sequence, so need to treat that as 'playing startup sequence'
|
|
return (m_vehicleEngine.IsGranularEngineActive() && m_vehicleEngine.GetState() == audVehicleEngine::AUD_ENGINE_STARTING);
|
|
}
|
|
|
|
#if __BANK
|
|
void GranularLoopEditorShiftLeft()
|
|
{
|
|
g_GranularLoopEditorShiftLeftPressed = true;
|
|
}
|
|
|
|
void GranularLoopEditorShiftRight()
|
|
{
|
|
g_GranularLoopEditorShiftRightPressed = true;
|
|
}
|
|
|
|
void GranularLoopEditorGrowLoopPressed()
|
|
{
|
|
g_GranularLoopEditorGrowLoopPressed = true;
|
|
}
|
|
|
|
void GranularLoopEditorShrinkLoopPressed()
|
|
{
|
|
g_GranularLoopEditorShrinkLoopPressed = true;
|
|
}
|
|
|
|
void GranularLoopEditorCreateLoopPressed()
|
|
{
|
|
g_GranularLoopEditorCreateLoopPressed = true;
|
|
}
|
|
|
|
void GranularLoopEditorDeleteLoopPressed()
|
|
{
|
|
g_GranularLoopEditorDeleteLoopPressed = true;
|
|
}
|
|
|
|
void GranularLoopEditorExportLoopData()
|
|
{
|
|
g_GranularLoopEditorExportDataPressed = true;
|
|
}
|
|
|
|
void TriggerMobilePreRing()
|
|
{
|
|
g_ScriptAudioEntity.PlayMobilePreRing(ATSTRINGHASH("MOBILE_PRERING", 0x80DC9690), 1.0f);
|
|
}
|
|
|
|
void TestStuntRaceBoost()
|
|
{
|
|
CVehicle* vehicle = FindPlayerVehicle();
|
|
|
|
if(vehicle)
|
|
{
|
|
vehicle->GetVehicleAudioEntity()->TriggerStuntRaceSpeedBoost();
|
|
}
|
|
}
|
|
|
|
void OverrideVehicleWeaponAmmoCount()
|
|
{
|
|
CVehicle* vehicle = FindPlayerVehicle();
|
|
|
|
if(vehicle && vehicle->GetVehicleWeaponMgr())
|
|
{
|
|
for(u32 i = 0; i < MAX_NUM_VEHICLE_WEAPONS; i++)
|
|
{
|
|
vehicle->SetRestrictedAmmoCount(i, g_WeaponAmmoCountOverride);
|
|
}
|
|
}
|
|
}
|
|
|
|
void TestStuntRaceSlowdown()
|
|
{
|
|
CVehicle* vehicle = FindPlayerVehicle();
|
|
|
|
if(vehicle)
|
|
{
|
|
vehicle->GetVehicleAudioEntity()->TriggerStuntRaceSlowDown();
|
|
}
|
|
}
|
|
|
|
void TestSportsRevs()
|
|
{
|
|
if(FindPlayerVehicle())
|
|
{
|
|
audVehicleAudioEntity* vehicleAudioEntity = FindPlayerVehicle()->GetVehicleAudioEntity();
|
|
|
|
if(vehicleAudioEntity && vehicleAudioEntity->GetAudioVehicleType() == AUD_VEHICLE_CAR)
|
|
{
|
|
((audCarAudioEntity*)vehicleAudioEntity)->TriggerSportsCarRevs(audCarAudioEntity::REVS_TYPE_DEBUG);
|
|
}
|
|
}
|
|
}
|
|
|
|
void StartAutomatedVolumeCapture()
|
|
{
|
|
g_EngineVolumeCaptureActive = true;
|
|
}
|
|
|
|
void StopAutomatedVolumeCapture()
|
|
{
|
|
g_EngineVolumeCaptureActive = false;
|
|
}
|
|
|
|
void GranularToggleSkipEveryOtherGrain()
|
|
{
|
|
g_GranularSkipGrainTogglePressed = true;
|
|
g_GranularSkipEveryOtherGrain = !g_GranularSkipEveryOtherGrain;
|
|
}
|
|
|
|
void GranularToggleTestTone()
|
|
{
|
|
g_GranularToggleTestTonePressed = true;
|
|
g_GranularToneGeneratorEnabled = !g_GranularToneGeneratorEnabled;
|
|
}
|
|
|
|
void audCarAudioEntity::AddWidgets(bkBank &bank)
|
|
{
|
|
bank.PushGroup("Vehicles", false);
|
|
bank.AddToggle("Debug Special Flight Mode", &g_DebugSpecialFlightMode);
|
|
bank.AddToggle("Disable Horns", &g_DisableHorns);
|
|
bank.AddToggle("Simulate Drowning", &g_SimulateDrowning);
|
|
bank.AddToggle("Test Force Game Object", &g_TestForceGameObject);
|
|
bank.AddText("Test Force Game Object Name", &g_TestForceGameObjectName[0], sizeof(g_TestForceGameObjectName), false);
|
|
bank.AddToggle("Force Auto Shutoff Engines", &g_ForceAutoShutoffEngines);
|
|
bank.AddToggle("Audition Wheel Fire", &g_AuditionWheelFire);
|
|
bank.AddToggle("Render vehicle slots", &g_RenderVehicleSlots);
|
|
bank.AddToggle("Breakpoint debug vehicle update", &g_BreakOnVehicleUpdate);
|
|
bank.AddToggle("Show Genre Info", &g_ShowRadioGenres);
|
|
bank.AddToggle("Debug Vehicle Openness", &g_DebugVehicleOpenness);
|
|
bank.AddToggle("Debug Draw Vehicle Water", &g_DebugDrawVehicleWater);
|
|
#if NA_RADIO_ENABLED
|
|
bank.AddSlider("g_LoudVehicleRadioOffset", &g_LoudVehicleRadioOffset, 0.f, 12.f, 0.1f);
|
|
#endif
|
|
|
|
bank.AddSlider("Player Horn Offset", &g_PlayerHornOffset, 0.f, 12.f, 0.1f);
|
|
bank.AddSlider("CheapDistance", &sm_CheapDistance, 0.0f, 40.0f, 1.0f);
|
|
bank.AddButton("Trigger Mobile PreRing", CFA(TriggerMobilePreRing));
|
|
|
|
bank.PushGroup("Collisions");
|
|
bank.AddSlider("Clatter Max Acceleration", &g_ClatterMaxAcceleration, 0.0f, 200.f, 1.0f);
|
|
bank.AddSlider("Car Velocity for Ped Impact", &g_CarVelForPedImpact, 0.f, 10.f, 0.1f);
|
|
bank.AddSlider("Damage Impact Velocity", &g_DamageImpactVel, 0.f, 50.f, 1.f);
|
|
bank.AddSlider("Deformation Impact Velocity", &g_DeformationImpactVel, 0.f, 50.f, 1.f);
|
|
bank.AddSlider("Trailer Bump Velocity", &g_TrailerBumpVel, 0.f, 50.f, 1.f);
|
|
bank.AddSlider("LowDynamicImpacts", &g_LowerVehDynamicImpactThreshold, -100.f, 6.f, 0.1f);
|
|
bank.AddSlider("HighDynamicImpacts", &g_UpperVehDynamicImpactThreshold, -100.f, 6.f, 0.1f);
|
|
bank.PopGroup();
|
|
|
|
bank.PushGroup("Gadgets");
|
|
bank.AddToggle("Enable Turret Debug", &g_DebugDrawTurret);
|
|
bank.AddToggle("Enable Tow Arm Debug", &g_DebugDrawTowArm);
|
|
bank.AddToggle("Enable Grappling Hook Debug", &g_DebugDrawGrappling);
|
|
bank.AddSlider("Grap - soundAcceleration", &g_GrapSoundAcceleration, 0.f, 70.f, 0.1f);
|
|
bank.AddSlider("Grap - Intensity", &g_GrapIntensity, -1.f, 1.f, 0.1f);
|
|
bank.AddSlider("Vehicle Weapon Ammo Count", &g_WeaponAmmoCountOverride, -1, 100, 1);
|
|
bank.AddButton("Override Vehicle Weapon Ammo Count", CFA(OverrideVehicleWeaponAmmoCount));
|
|
bank.PopGroup();
|
|
|
|
bank.PushGroup("Stunt Races");
|
|
bank.AddSlider("Boost Intensity Timeout Ms", &g_StuntBoostIntensityTimeout, 0, 15000, 10);
|
|
bank.AddButton("Trigger Stunt Race Boost", CFA(TestStuntRaceBoost));
|
|
bank.AddButton("Trigger Stunt Race Slow Down", CFA(TestStuntRaceSlowdown));
|
|
bank.AddSlider("Speed Boost Decel Smoothing Duration", &g_StuntSpeedBoostDecelSmoothingDuration, 0, 60000, 100);
|
|
bank.AddSlider("Speed Boost Decel Smoothing", &g_StuntSpeedBoostDecelSmoothing, 0.f, 500.f, 1.f);
|
|
bank.PopGroup();
|
|
|
|
bank.PushGroup("Damage");
|
|
bank.AddToggle("Display Damage Debug", &g_DisplayDamageDebug);
|
|
bank.AddToggle("Force Engine Damage", &g_ForceDamage);
|
|
bank.AddToggle("Force Wheel Damage", &g_ForceWheelDamage);
|
|
bank.AddSlider("Forced Engine Damage Factor", &g_ForcedDamageFactor, 0.0f, 1.0f, 0.01f);
|
|
bank.AddToggle("Set All Cars Always Damaged", &g_ForceAllCarsAlwaysDamaged);
|
|
bank.AddToggle("Mute Damage Layers", &g_MuteDamageLayers);
|
|
bank.AddToggle("Mute Fanbelt Damage", &g_MuteFanbeltDamage);
|
|
bank.AddToggle("Mute Granular Damage", &g_MuteGranularDamage);
|
|
bank.AddSlider("Engine Volume Trim", &g_EngineVolumeTrim, -100.0f, 100.f, 0.1f);
|
|
bank.AddSlider("Exhaust Volume Trim", &g_ExhaustVolumeTrim, -100.0f, 100.f, 0.1f);
|
|
bank.AddSlider("Damage Layer Min Pitch", &g_DamageLayerMinPitch, -2000, 2000, 10);
|
|
bank.AddSlider("Damage Layer Max Pitch", &g_DamageLayerMaxPitch, -2000, 2000, 10);
|
|
bank.AddSlider("Body Damage Factor For Debris", &g_BodyDamageFactorForDebris, 0.f, 1.f, 0.01f);
|
|
bank.AddSlider("Body Damage Factor For Hydraulic Debris", &g_BodyDamageFactorForHydraulicDebris, 0.f, 1.f, 0.01f);
|
|
bank.AddSlider("Damaged Wheel Min Pitch", &g_DamagedWheelMinPitch, -2000, 2000, 10);
|
|
bank.AddSlider("Damaged Wheel Max Pitch", &g_DamagedWheelMaxPitch, -2000, 2000, 10);
|
|
bank.AddToggle("Enable Damage Throttle Cut", &g_EnableDamageThrottleCut);
|
|
bank.AddSlider("High Revs Misfire Sound Prob", &g_HighRevsMisfireSoundProb, 0.0f, 1.0f, 0.01f);
|
|
bank.AddSlider("Min Throttle Cut Duration", &g_MinDamageThrottleCutDuration, 0.0f, 10.f, 0.01f);
|
|
bank.AddSlider("Max Throttle Cut Duration", &g_MaxDamageThrottleCutDuration, 0.0f, 10.f, 0.01f);
|
|
bank.AddSlider("Short Throttle Cut Prob Min", &g_ShortDamageCutProbMin, 0.0f, 1.0f, 0.01f);
|
|
bank.AddSlider("Short Throttle Cut Prob Max", &g_ShortDamageCutProbMax, 0.0f, 1.0f, 0.01f);
|
|
bank.AddSlider("Min Time Between Short Throttle Cuts", &g_MinTimeBetweenDamageThrottleCutsShort, 0, 60000, 10);
|
|
bank.AddSlider("Max Time Between Short Throttle Cuts", &g_MaxTimeBetweenDamageThrottleCutsShort, 0, 60000, 10);
|
|
bank.AddSlider("Min Time Between Long Throttle Cuts", &g_MinTimeBetweenDamageThrottleCuts, 0, 60000, 10);
|
|
bank.AddSlider("Max Time Between Long Throttle Cuts", &g_MaxTimeBetweenDamageThrottleCuts, 0, 60000, 10);
|
|
bank.PopGroup();
|
|
|
|
bank.PushGroup("Car Mods");
|
|
bank.AddToggle("Draw Vehicles In Mod Shop", &g_DrawVehiclesInModShop);
|
|
bank.AddToggle("Upgrade Engine", &g_ForceUpgradeEngine);
|
|
bank.AddSlider("Engine Bay Upgrade Level", &g_ForcedEngineUpgradeLevel, 0.0f, 1.0f, 0.1f);
|
|
bank.AddToggle("Upgrade Exhaust", &g_ForceUpgradeExhaust);
|
|
bank.AddSlider("Engine Bay Upgrade Level", &g_ForcedExhaustUpgradeLevel, 0.0f, 1.0f, 0.1f);
|
|
bank.AddToggle("Upgrade Transmission", &g_ForceUpgradeTransmission);
|
|
bank.AddSlider("Transmission Upgrade Level", &g_ForcedTransmissionUpgradeLevel, 0.0f, 1.0f, 0.1f);
|
|
bank.AddToggle("Upgrade Turbo", &g_ForceUpgradeTurbo);
|
|
bank.AddSlider("Turbo Upgrade Level", &g_ForcedTurboUpgradeLevel, 0.0f, 1.0f, 0.1f);
|
|
bank.AddToggle("Upgrade Radio", &g_ForceUpgradeRadio);
|
|
bank.AddSlider("Radio Upgrade Level", &g_ForcedRadioUpgradeLevel, 0.0f, 1.0f, 0.1f);
|
|
bank.AddToggle("Upgrade Engine Bay Slot 0", &g_ForceUpgradeEngineBay[0]);
|
|
bank.AddSlider("Engine Bay Slot 0 Upgrade Level", &g_ForcedEngineBayUpgradeLevel[0], 0.0f, 1.0f, 0.1f);
|
|
bank.AddToggle("Upgrade Engine Bay Slot 1", &g_ForceUpgradeEngineBay[1]);
|
|
bank.AddSlider("Engine Bay Slot 1 Upgrade Level", &g_ForcedEngineBayUpgradeLevel[1], 0.0f, 1.0f, 0.1f);
|
|
bank.AddToggle("Upgrade Engine Bay Slot 2", &g_ForceUpgradeEngineBay[2]);
|
|
bank.AddSlider("Engine Bay Slot 2 Upgrade Level", &g_ForcedEngineBayUpgradeLevel[2], 0.0f, 1.0f, 0.1f);
|
|
bank.AddSlider("Trunk Radio Offset Position", &g_TrunkRadioPositionOffset, 0.0f, 10.0f, 0.1f);
|
|
bank.PopGroup();
|
|
|
|
bank.PushGroup("Revs Boost Effect");
|
|
bank.AddToggle("Revs Boost Enabled", &g_RevsBoostEffectEnabled);
|
|
bank.AddToggle("Enable Debug Rendering", &g_GranularDebugRenderingEnabled);
|
|
bank.AddSlider("Max Pitch Offset", &g_RevsBoostPitchOffset, 0.0f, 2400.0f, 1.0f);
|
|
bank.AddSlider("Max Revs Scalar", &g_RevsBoostRevsScalar, 0.0f, 10.0f, 0.01f);
|
|
bank.AddSlider("Pitch Offset Fade In Time", &g_RevsBoostPitchOffsetFadeInTime, 0.0f, 100.0f, 1.0f);
|
|
bank.AddSlider("Pitch Offset Fade Out Time", &g_RevsBoostPitchOffsetFadeOutTime, 0.0f, 100.0f, 1.0f);
|
|
bank.AddSlider("Revs Scale Fade In Time", &g_RevsBoostRevsScaleFadeInTime, 0.0f, 100.0f, 1.0f);
|
|
bank.AddSlider("Revs Scale Fade Out Time", &g_RevsBoostRevsScaleFadeOutTime, 0.0f, 100.0f, 1.0f);
|
|
bank.AddSlider("Min Fwd Speed Ratio", &g_RevsBoostEffectFwdSpeedRatio, 0.0f, 1.0f, 0.001f);
|
|
bank.AddSlider("Min Rev Ratio", &g_RevsBoostEffectRevRatio, 0.0f, 1.0f, 0.001f);
|
|
bank.AddSlider("Angular Velocity Limit", &g_RevsBoostAngularVelocityLimit, 0.0f, 50.0f, 0.01f);
|
|
bank.AddSlider("Angular Velocity Limit Sensitivity", &g_RevsBoostAngularVelocityLimitSensitivity, 0.0f, 50.0f, 0.01f);
|
|
bank.AddToggle("Pitch Shift Only in Final Gear", &g_RevsBoostPitchOffsetOnlyInFinalGear);
|
|
bank.PopGroup();
|
|
|
|
bank.PushGroup("Vehicle Occlusion");
|
|
bank.AddSlider("InnerUpdateFrames", &sm_InnerUpdateFrames, 0.0f, 10.0f, 1.0f);
|
|
bank.AddSlider("OuterUpdateFrames", &sm_OuterUpdateFrames, 0.0f, 10.0f, 1.0f);
|
|
bank.AddSlider("InnerCheapUpdateFrames", &sm_InnerCheapUpdateFrames, 0.0f, 10.0f, 1.0f);
|
|
bank.AddSlider("OuterCheapUpdateFrames", &sm_OuterCheapUpdateFrames, 0.0f, 10.0f, 1.0f);
|
|
bank.PopGroup();
|
|
|
|
bank.PushGroup("Surfaces and Road Noise");
|
|
bank.AddToggle("DebugVehicleSkids", &g_DebugVehicleSkids);
|
|
bank.AddText("Player ground material", &g_DrivingMaterialName[0], sizeof(g_DrivingMaterialName));
|
|
bank.AddToggle("Display ground material", &g_DisplayGroundMaterial);
|
|
bank.AddSlider("Spin Ratio For Debris", &g_SpinRatioForDebris, 0.000001f, 10.f, 0.001f);
|
|
bank.AddSlider("Speed For Spin Debris", &g_SpeedForSpinDebris, 0.f, 10.f, 0.1f);
|
|
bank.AddToggle("Disable Road Noise", &g_DisableRoadNoise);
|
|
bank.AddToggle("Disable NPC Road Noise", &g_DisableNPCRoadNoise);
|
|
bank.AddToggle("Show NPC Road Noise State", &g_ShowNPCRoadNoiseState);
|
|
bank.AddSlider("NPC Road Noise Inner Angle", &g_NPCRoadNoiseInnerAngle, 0.0f, 180.0f, 1.0f);
|
|
bank.AddSlider("NPC Road Noise Outer Angle", &g_NPCRoadNoiseOuterAngle, 0.0f, 180.0f, 1.0f);
|
|
bank.AddToggle("Force Shallow Water", &g_ForceShallowWater);
|
|
bank.AddToggle("Display Ridged Surface Info", &g_DisplayRidgedSurfaceInfo);
|
|
bank.AddToggle("Disable Clatter", &g_DisableClatter);
|
|
bank.AddToggle("Display Dirt/Glass", &g_DisplayDirtGlassInfo);
|
|
bank.AddToggle("Force Glassy Surface", &g_ForceGlassySurface);
|
|
bank.AddToggle("Force Dirty Surface", &g_ForceDirtySurface);
|
|
bank.AddToggle("Disable Burnout Skids in Reverse", &g_DisableBurnoutSkidsInReverse);
|
|
bank.AddSlider("Wheel Dirtiness Increase Smooth Rate", &g_WheelDirtinessIncreaseSmoothRate, 0.0f, 1.0f, 0.001f);
|
|
bank.AddSlider("Wheel Dirtiness Decrease Smooth Rate", &g_WheelDirtinessDecreaseSmoothRate, 0.0f, 1.0f, 0.001f);
|
|
bank.AddSlider("Wheel Glassiness Increase Smooth Rate", &g_WheelGlassinessIncreaseSmoothRate, 0.0f, 1.0f, 0.001f);
|
|
bank.AddSlider("Wheel Glassiness Decrease Smooth Rate", &g_WheelGlassinessDecreaseSmoothRate, 0.0f, 1.0f, 0.001f);
|
|
bank.AddSlider("Glass Area Depletion Rate", &g_GlassAreaDepletionRate, 0.0f, 1.0f, 0.001f);
|
|
bank.AddSlider("Main Skid Smoother Increase", &g_MainSkidSmootherIncrease, 0.0f, 100.0f, 0.001f);
|
|
bank.AddSlider("Main Skid Smoother Decrease", &g_MainSkidSmootherDecrease, 0.0f, 100.0f, 0.001f);
|
|
bank.AddSlider("Lateral Skid Smoother Increase", &g_LateralSkidSmootherIncrease, 0.0f, 100.0f, 0.001f);
|
|
bank.AddSlider("Lateral Skid Smoother Decrease", &g_LateralSkidSmootherDecrease, 0.0f, 100.0f, 0.001f);
|
|
bank.PopGroup();
|
|
|
|
bank.PushGroup("Wind and SFX");
|
|
bank.AddToggle("Debug Passbys", &g_DebugCarPasses);
|
|
bank.AddToggle("Debug Wind Noise", &g_DebugWindNoise);
|
|
bank.AddSlider("Wind Noise Increase Smoothing", &g_WindNoiseSmootherIncreaseRate, 0.0f, 1000000.0f, 10.0f);
|
|
bank.AddSlider("Wind Noise Decrease Smoothing", &g_WindNoiseSmootherDecreaseRate, 0.0f, 1000000.0f, 10.0f);
|
|
bank.PopGroup();
|
|
|
|
bank.PushGroup("Sports Car Revs", false);
|
|
bank.AddToggle("Sports Car Revs Enabled", &g_SportsCarRevsEnabled);
|
|
bank.AddToggle("Draw Cars Playing Sports Revs", &g_DrawCarsPlayingSportsRevs);
|
|
bank.AddToggle("Draw Sports Car Passbys", &g_DrawSportsRevsPassbyDebug);
|
|
bank.AddToggle("Force Sports Revs on All Cars", &g_ForceAllCarsPlaySportsRevs);
|
|
bank.AddButton("Trigger Sports Revs", CFA(TestSportsRevs));
|
|
bank.AddSlider("Engine Switch Attack Time", &g_SportsCarRevsEngineSwitchTime, 0, 10000, 10);
|
|
bank.PopGroup();
|
|
|
|
bank.PushGroup("Vehicle LODs", false);
|
|
bank.AddToggle("Display Vehicle LODs", &g_ShowEngineStates);
|
|
bank.AddToggle("Display Super Dummy Radius", &g_DrawSuperDummyRadius);
|
|
bank.AddToggle("Display Focus Vehicle", &g_ShowFocusVehicle);
|
|
bank.AddToggle("Show Vehicles with Wave Slots", &g_ShowVehiclesWithWaveSlots);
|
|
bank.AddToggle("Render slot manager", &g_RenderSlotManager);
|
|
bank.AddToggle("Debug Draw DSP Effects", &g_DebugDSPParams);
|
|
bank.AddToggle("Draw Lines to Real Cars", &g_DrawLinesToRealCars);
|
|
bank.AddToggle("Draw Lines to Vehicles with Wave Slots", &g_DrawLinesToVehiclesWithWaveSlots);
|
|
bank.AddToggle("Draw Lines to Vehicles with DSP Effects", &g_DrawLinesToVehiclesWithSubmixVoices);
|
|
bank.AddCombo("Force Player Vehicle LOD", &g_ForcePlayerVehicleLOD, 5, &g_VehicleLODNames[0], 0, NullCB, "" );
|
|
bank.AddSlider("Max Dummy Range Scale", &g_MaxDummyRangeScale, 0.0f, 100.0f, 1.0f);
|
|
bank.AddSlider("Max Granular Range Scale", &g_MaxGranularRangeScale, 0.0f, 100.0f, 1.0f);
|
|
bank.AddSlider("Max Real Range Scale", &g_MaxRealRangeScale, 0.0f, 100.0f, 1.0f);
|
|
bank.AddSlider("Real Scale Increase Rate", &g_ActivationScaleIncreaseRate, 0.0f, 100.0f, 0.1f);
|
|
bank.AddSlider("Real Scale Decrease Rate", &g_ActivationScaleDecreaseRate, 0.0f, 100.0f, 0.1f);
|
|
bank.AddSlider("Granular Scale Increase Rate", &g_GranularActivationScaleIncreaseRate, 0.0f, 100.0f, 0.1f);
|
|
bank.AddSlider("Granular Scale Decrease Rate", &g_GranularActivationScaleDecreaseRate, 0.0f, 100.0f, 0.1f);
|
|
bank.AddSlider("Dummy Scale Increase Rate", &g_DummyActivationScaleIncreaseRate, 0.0f, 100.0f, 0.1f);
|
|
bank.AddSlider("Dummy Scale Decrease Rate", &g_DummyActivationScaleDecreaseRate, 0.0f, 100.0f, 0.1f);
|
|
bank.AddSlider("Off Screen Visibility Scalar", &g_OffscreenVisiblityScalar, 0.0f, 10.0f, 0.01f);
|
|
bank.AddSlider("Engine Switch Fade In Time", &g_EngineSwitchFadeInTime, 0, 10000, 10);
|
|
bank.AddSlider("Engine Switch Fade Out Time", &g_EngineSwitchFadeOutTime, 0, 10000, 10);
|
|
bank.AddSlider("NPC Road Noise Attack Time", &g_NPCRoadNoiseAttackTime, 0, 10000, 10);
|
|
bank.AddSlider("NPC Road Noise Release Time", &g_NPCRoadNoiseReleaseTime, 0, 10000, 10);
|
|
bank.AddSlider("Min Time At Desired LOD", &g_MinTimeAtDesiredLOD, 0.0f, 10.0f, 0.01f);
|
|
bank.AddSlider("Min Time At Current LOD", &g_MinTimeAtCurrentLOD, 0.0f, 10.0f, 0.01f);
|
|
bank.AddSlider("LOD Speed Bias", &g_LODSpeedBias, 0.0f, 1.0f, 0.01f);
|
|
bank.AddSlider("LOD Min Speed Ratio", &g_LODMinSpeedRatio, 0.0f, 1.0f, 0.01f);
|
|
bank.AddSlider("LOD Max Speed Ratio", &g_LODMaxSpeedRatio, 0.0f, 1.0f, 0.01f);
|
|
bank.AddToggle("Show Time Sliced Vehicles", &g_RenderTimeSlicedVehicles);
|
|
bank.PopGroup();
|
|
|
|
bank.PushGroup("Engines",false);
|
|
bank.PushGroup("Mixing",false);
|
|
bank.AddToggle("EngineMixMode", &g_DisableVolumeCategory);
|
|
bank.AddToggle("TreatAsPedCar", &g_TreatAsPedCar);
|
|
bank.AddToggle("TreatAsDummyCar", &g_TreatAsDummyCar);
|
|
bank.AddToggle("Enable Debug Focusing", &g_VehicleAudioAllowEntityFocus);
|
|
bank.AddToggle("Force Real LOD on Focus Vehicle", &g_ForceRealLodOnFocusEntity);
|
|
bank.PopGroup();
|
|
|
|
bank.PushGroup("Transmission",false);
|
|
bank.AddToggle("Force Wobble", &g_ForceTransWobble);
|
|
bank.AddSlider("Wobble Frequency", &g_TransWobbleFreq, 0.0f, 200.0f, 1.0f);
|
|
bank.AddSlider("Wobble Frequency Variance", &g_TransWobbleFreqVariance, 0.0f, 200.0f, 1.0f);
|
|
bank.AddSlider("Wobble Magnitude", &g_TransWobbleMag, 0.0f, 1.0f, 0.01f);
|
|
bank.AddSlider("Wobble Magnitude Variance", &g_TransWobbleMagVariance, 0.0f, 1.0f, 0.01f);
|
|
bank.AddSlider("Wobble Length", &g_TransWobbleLength, 0.0f, 100.0f, 0.1f);
|
|
bank.AddSlider("Wobble Length Variance", &g_TransWobbleLengthVariance, 0.0f, 100.0f, 0.1f);
|
|
bank.PopGroup();
|
|
|
|
bank.PushGroup("DSP Effects",false);
|
|
bank.AddToggle("Debug Draw", &g_DebugDSPParams);
|
|
bank.AddToggle("Mute DSP Effects", &g_DisableEngineExhaustDSP);
|
|
bank.AddToggle("Disable Player DSP Effects", &g_DisablePlayerVehicleDSP);
|
|
bank.AddToggle("Disable NPC DSP Effects", &g_DisableNPCVehicleDSP);
|
|
bank.AddToggle("Auto Re-apply DSP Presets", &g_AutoReapplyDSPPresets);
|
|
bank.AddToggle("Allow Synths on Network Vehicles", &g_AllowSynthsOnNetworkVehicles);
|
|
bank.AddToggle("Force Synths On All Engines", &g_ForceSynthsOnAllEngines);
|
|
bank.PopGroup();
|
|
|
|
bank.PushGroup("Electric Engines",false);
|
|
bank.AddSlider("Speed Volume Scale", &g_ElectricEngineSpeedVolScale, 0.0f, 1.0f, 0.1f);
|
|
bank.AddSlider("Speed Loop Speed Bias", &g_ElectricEngineSpeedLoopSpeedBias, 0.0f, 1.0f, 0.01f);
|
|
bank.AddSlider("Speed Loop Speed Scalar", &g_ElectricEngineSpeedLoopSpeedApplyScalar, 0.0f, 10.0f, 0.1f);
|
|
bank.AddSlider("Boost Volume Scale", &g_ElectricEngineBoostVolScale, 0.0f, 1.0f, 0.1f);
|
|
bank.AddSlider("Revs Off Volume Scale", &g_ElectricEngineRevsOffVolScale, 0.0f, 1.0f, 0.1f);
|
|
bank.PopGroup();
|
|
|
|
bank.PushGroup("Volume Controls",false);
|
|
bank.AddSlider("Engine Volume Trim", &g_EngineVolumeTrim, -100.0f, 100.f, 0.1f);
|
|
bank.AddSlider("Exhaust Volume Trim", &g_ExhaustVolumeTrim, -100.0f, 100.f, 0.1f);
|
|
bank.AddSlider("Gearbox Volume Trim", &g_GearboxVolumeTrim, -100.0f, 100.f, 0.1f);
|
|
bank.AddSlider("Turbo Volume Trim", &g_TurboVolumeTrim, -100.0f, 100.f, 0.1f);
|
|
bank.AddSlider("Granular Accel Volume Trim", &g_GranularAccelVolumeTrim, -100.0f, 100.f, 0.1f);
|
|
bank.AddSlider("Granular Decel Volume Trim", &g_GranularDecelVolumeTrim, -100.0f, 100.f, 0.1f);
|
|
bank.AddSlider("Granular Idle Volume Trim", &g_GranularIdleVolumeTrim, -100.0f, 100.f, 0.1f);
|
|
bank.AddToggle("Disable Coning", &g_DisableConing);
|
|
bank.AddSlider("Base Rolloff Scale Player", &g_BaseRollOffScalePlayer, 0.0f, 100.0f, 0.1f);
|
|
bank.AddSlider("Base Rolloff Scale NPC", &g_BaseRollOffScaleNPC, 0.0f, 100.0f, 0.1f);
|
|
bank.AddButton("Start Automated Volume Capture", CFA(StartAutomatedVolumeCapture));
|
|
bank.AddButton("Stop Automated Volume Capture", CFA(StopAutomatedVolumeCapture));
|
|
bank.AddSlider("Volume Capture Start Index", &audCarAudioEntity::sm_VolumeCaptureVehicleStartIndex, 0, 300, 1);
|
|
bank.PopGroup();
|
|
|
|
bank.PushGroup("Wobbles",false);
|
|
bank.AddToggle("Test Wobble", &g_TestWobble);
|
|
bank.AddSlider("Length", &g_TestWobbleLength, 1, 10000, 1);
|
|
bank.AddSlider("Length Variance", &g_TestWobbleLengthVariance, 0.0f, 100.f, 0.1f);
|
|
bank.AddSlider("Speed", &g_TestWobbleSpeed, 0.0f, 10.f, 0.1f);
|
|
bank.AddSlider("Speed Variance", &g_TestWobbleSpeedVariance, 0.0f, 100.f, 0.1f);
|
|
bank.AddSlider("Pitch", &g_TestWobblePitch, 0.0f, 10.f, 0.1f);
|
|
bank.AddSlider("Pitch Variance", &g_TestWobblePitchVariance, 0.0f, 10.f, 0.1f);
|
|
bank.AddSlider("Volume", &g_TestWobbleVolume, 0.0f, 10.f, 0.1f);
|
|
bank.AddSlider("Volume Variance", &g_TestWobbleVolumeVariance, 0.0f, 100.f, 0.1f);
|
|
bank.PopGroup();
|
|
|
|
bank.PushGroup("Granular Controls ",false);
|
|
bank.AddSlider("Granular X Value Smooth Rate", &g_GranularXValueSmoothRate, 0.0f, 1.0f, 0.01f);
|
|
bank.AddSlider("Granular Sliding Window Size Hz Fraction", &g_GranularSlidingWindowSizeHzFraction, 0.0f, 1.0f, 0.001f);
|
|
bank.AddSlider("Granular Sliding Window Min Grains", &g_GranularSlidingWindowMinGrains, 0, 30, 1);
|
|
bank.AddSlider("Granular Sliding Window Max Grains", &g_GranularSlidingWindowMaxGrains, 0, 30, 1);
|
|
bank.AddSlider("Granular Min Repeat Rate", &g_GranularMinRepeatRate, 0, 10, 1);
|
|
bank.AddSlider("Default Granular Change Rate for Loops", &audGranularMix::s_DefaultGranularChangeRateForLoops, 0.0f, 100.0f, 0.1f);
|
|
bank.AddSlider("Granular Physics Revs Multiplier", &g_GranularEngineRevMultiplier, 0.5f, 2.0f, 0.01f);
|
|
bank.AddCombo("Grain Playback Style", &g_GrainPlaybackStyle, 4, &g_GranularPlaybackStyleNames[0], 0, NullCB, "" );
|
|
bank.AddCombo("Grain Mix Style", &g_GranularMixStyle, 3, &g_GranularMixStyleNames[0], 0, NullCB, "" );
|
|
bank.AddCombo("Accel-Decel Crossfade Style", &g_GranularMixCrossfadeStyle, 2, &g_GranularCrossfadeStyleNames[0], 0, NullCB, "" );
|
|
bank.AddCombo("Inter-Grain Crossfade Style", &g_GranularInterGrainCrossfadeStyle, 2, &g_GranularCrossfadeStyleNames[0], 0, NullCB, "" );
|
|
bank.AddCombo("Loop-Grain Crossfade Style", &g_GranularLoopGrainCrossfadeStyle, 2, &g_GranularCrossfadeStyleNames[0], 0, NullCB, "" );
|
|
bank.AddCombo("Loop-Loop Crossfade Style", &g_GranularLoopLoopCrossfadeStyle, 2, &g_GranularCrossfadeStyleNames[0], 0, NullCB, "" );
|
|
bank.AddCombo("Grain Randomisation Style", &g_GranularRandomisationStyle, 5, &g_GranularRandomisationStyleNames[0], 0, NullCB, "" );
|
|
bank.AddCombo("Idle Grain Randomisation Style", &g_GranularIdleRandomisationStyle, 5, &g_GranularRandomisationStyleNames[0], 0, NullCB, "" );
|
|
bank.AddSlider("Idle to Main Smooth Rate (Increase)", &g_IdleMainSmootherRateIncrease, 0.0f, 1.0f, 0.01f);
|
|
bank.AddSlider("Idle to Main Smooth Rate (Decrease)", &g_IdleMainSmootherRateDecrease, 0.0f, 1.0f, 0.01f);
|
|
bank.AddSlider("Granular Loop Below Bias", &audGranularMix::s_GranularLoopBelowBias, 0.0f, 5.0f, 0.1f);
|
|
bank.AddSlider("Granular Loop To Grain Smooth Rate", &audGranularMix::s_GranularLoopToGrainChangeRate, 0.0f, 1.0f, 0.01f);
|
|
bank.AddSlider("Granular Grain To Loop Smooth Rate", &audGranularMix::s_GranularGrainToLoopChangeRate, 0.0f, 1.0f, 0.01f);
|
|
bank.AddSlider("Granular Accel/Decel Smooth Rate", &g_GranularAccelDecelSmoothRate, 0.0f, 1.0f, 0.01f);
|
|
bank.AddToggle("Enable Granular Limiter", &g_GranularLimiterEnabled);
|
|
bank.AddToggle("Force Granular Limiter", &g_GranularForceRevLimiter);
|
|
bank.AddToggle("Enable Granular Wobbles", &g_GranularWobblesEnabled);
|
|
bank.AddToggle("Force Granular Low Quality", &g_GranularForceLowQuality);
|
|
bank.AddToggle("Force Granular High Quality", &g_GranularForceHighQuality);
|
|
bank.AddToggle("Simulate Player Leaving/Entering Vehicle", &g_SimulatePlayerEnteringVehicle);
|
|
bank.AddSlider("Granular Quality Change Crossfade Speed", &g_GranularQualityCrossfadeSpeed, 0.0f, 10.0f, 0.01f);
|
|
bank.AddToggle("Enable Granular NPC Engines", &g_GranularEnableNPCGranularEngines);
|
|
bank.AddToggle("Force Granular NPC Engines", &g_ForceGranularNPCEngines);
|
|
bank.AddToggle("Render Granular NPC Engines", &g_RenderGranularNPCEngines);
|
|
bank.AddToggle("Granular LOD Switch Equal Power X-Fade", &g_GranularLODEqualPowerCrossfade);
|
|
bank.AddToggle("Mute Granular Synths", &g_ForceMuteGranularSynths);
|
|
bank.AddSlider("Granular Loop Randomisation Granular CR", &audGranularMix::s_LoopRandomisationGranularChangeRate, 0.0f, 50.0f, 0.1f);
|
|
bank.AddToggle("Granular Mid-Loop Randomisation Enabled", &audGranularSubmix::s_GranularMidLoopRandomisationEnabled);
|
|
bank.AddToggle("Enable Granular Loop Peak Normalisation", &audGranularMix::s_GranularPeakNormaliseLoops);
|
|
bank.AddButton("Toggle Granular Test Tone", CFA(GranularToggleTestTone));
|
|
bank.AddButton("Skip Every Other Grain", CFA(GranularToggleSkipEveryOtherGrain));
|
|
bank.AddToggle("Force Granular Starvation", &audGranularSubmix::s_ForceGranularSubmixStarvation);
|
|
bank.AddToggle("Set Granular Engine Idle Native", &g_SetGranularEngineIdleNative);
|
|
bank.AddToggle("Set Granular Exhaust Idle Native", &g_SetGranularExhaustIdleNative);
|
|
bank.PopGroup();
|
|
|
|
bank.PushGroup("Debug Rendering",false);
|
|
bank.AddToggle("Enable Granular Debug Rendering", &g_GranularDebugRenderingEnabled);
|
|
bank.AddToggle("Enable Granular Idle Debug Rendering", &g_GranularIdleDebugRenderingEnabled);
|
|
bank.AddToggle("Enable Non-Granular Debug Rendering", &g_NonGranularDebugRenderingEnabled);
|
|
#if __PS3
|
|
bank.AddToggle("Draw Granular Vram Loaders", &audGranularMix::s_DebugDrawVramGrainLoaders);
|
|
bank.AddToggle("Draw Loop Vram Loaders", &audGranularMix::s_DebugDrawVramLoopLoaders);
|
|
#endif
|
|
bank.PopGroup();
|
|
|
|
bank.PushGroup("Granular Loop Editing",false);
|
|
bank.AddToggle("Enable Granular Debug Rendering", &g_GranularDebugRenderingEnabled);
|
|
bank.AddToggle("Loop Editor Active", &audGrainPlayer::s_LoopEditorActive);
|
|
bank.AddSlider("Loop Editor Mix Index", &audGrainPlayer::s_LoopEditorMixIndex, 0, 10, 1);
|
|
bank.AddSlider("Loop Editor Loop Index", &audGrainPlayer::s_LoopEditorLoopIndex, 0, 10, 1);
|
|
bank.AddButton("Shift Loop Left", CFA(GranularLoopEditorShiftLeft));
|
|
bank.AddButton("Shift Loop Right", CFA(GranularLoopEditorShiftRight));
|
|
bank.AddSlider("Shift Amount", &audGrainPlayer::s_LoopEditorShiftAmount, 1, 100, 1);
|
|
bank.AddButton("Grow Loop", CFA(GranularLoopEditorGrowLoopPressed));
|
|
bank.AddButton("Shrink Loop", CFA(GranularLoopEditorShrinkLoopPressed));
|
|
bank.AddButton("Create New Loop", CFA(GranularLoopEditorCreateLoopPressed));
|
|
bank.AddButton("Delete Selected Loop", CFA(GranularLoopEditorDeleteLoopPressed));
|
|
bank.AddButton("Export Loop Data", CFA(GranularLoopEditorExportLoopData));
|
|
bank.AddToggle("Force Rev/Throttle Values", &g_GranularEditorControlRevsThrottle);
|
|
bank.AddSlider("Revs", &g_GranularEditorRevs, 0.0f, 1.0f, 0.01f);
|
|
bank.AddSlider("Throttle", &g_GranularEditorThrottle, 0.0f, 1.0f, 0.01f);
|
|
bank.PopGroup();
|
|
|
|
bank.PushGroup("Misc Options",false);
|
|
bank.AddToggle("Link Exhaust Pops to Audio Revs", &g_LinkExhaustPopsToAudioRevs);
|
|
bank.AddSlider("Rocket Boost Cooldown Time", &g_RocketBoostCooldownTime, 0, 60000, 100);
|
|
bank.AddToggle("Show Engine/Exhaust", &g_ShowEngineExhaust);
|
|
bank.AddToggle("Position Interior Engine/Exhaust at Listener", &g_InteriorEngineExhaustAtListener);
|
|
bank.AddToggle("Interior Engine/Exhaust Panned", &g_InteriorEngineExhaustPanned);
|
|
bank.AddToggle("Mute Player Vehicle", &g_MutePlayerVehicle);
|
|
bank.AddSlider("NPC Revs Scalar", &g_NPCVehicleRevsScalar, 0.0f, 10.0f, 0.01f);
|
|
bank.AddSlider("Engine Start Duration", &g_EngineStartDuration, 0, 10000, 1);
|
|
bank.AddSlider("Engine Stop Duration", &g_EngineStopDuration, 0, 10000, 1);
|
|
bank.AddSlider("Revs Increase Rate", &g_RevMaxIncreaseRate, 0.1f, 1000.f, 1.f);
|
|
bank.AddSlider("Revs Force Stop Decrease Rate", &g_RevMaxForceStopDecreaseRate, 0.1f, 1000.f, 1.f);
|
|
bank.AddSlider("Revs Decrease Rate", &g_RevMaxDecreaseRate, 0.1f, 1000.f, 1.f);
|
|
bank.AddSlider("Under Load Revs Smoothing", &g_UnderLoadRevsSmootherScalar, 0.1f, 100.f, 0.1f);
|
|
bank.AddSlider("Frequency Smoothing Rate", &sm_FrequencySmoothingRate, -1.f, 100.f, 0.1f);
|
|
bank.AddToggle("Display engine debug text", &sm_ShouldDisplayEngineDebug);
|
|
bank.AddToggle("Flip player volume cones", &sm_ShouldFlipPlayerCones);
|
|
bank.AddSlider("BrakeLinearVolumeSmoothRate", &g_BrakeLinearVolumeSmootherRate, 0.1f, 10.0f, 0.1f);
|
|
bank.AddSlider("BonnetCamGTOffset", &g_BonnetCamGTOffset, 0.0f, 12.0f, 0.1f);
|
|
bank.AddSlider("TurboSpinUp", &g_TurboSpinUp, 0.0f, 10.f, 0.1f);
|
|
bank.AddSlider("TurboSpinDown", &g_TurboSpinDown, 0.0f, 10.f, 0.1f);
|
|
bank.AddSlider("DumpValvePressureThresh", &g_DumpValvePressureThreshold, 0.0f, 1.0f, 0.1f);
|
|
bank.AddSlider("ExhaustThrottleAtten", &g_audExhaustThrottleVolumeRange, 0.0f, 100.f, 0.1f);
|
|
bank.AddSlider("ExhaustProximityAffectRange", &g_ExhaustProximityEffectRange, 1.0f, 50.f, 0.1f);
|
|
bank.AddToggle("Override Sim", &g_OverrideSim);
|
|
bank.AddSlider("OverriddenThrottle", &g_OverriddenThrottle, 0.f, 1.f, 0.001f);
|
|
bank.AddSlider("OverriddenRevs", &g_OverriddenRevs, 0.f, 1.f, 0.001f);
|
|
bank.AddSlider("Mission Vehicle Revs Scalar", &g_MissionVehicleRevsScaler, 0.f, 3.f, 0.1f);
|
|
bank.AddToggle("ForceRandomBlips", &g_ForceRandomBlips);
|
|
bank.AddSlider("g_RandomBlipMaxSpeed", &g_RandomBlipMaxSpeed, 0.0f, 20.0f, 0.01f);
|
|
bank.AddSlider("g_MinSqDistForFastBlips", &g_MinSqDistForFastBlips, 0.0f, 10000.0f, 1.0f);
|
|
bank.AddSlider("ExhaustPopsThresh", &g_ExhaustPopRateThreshold, 0.01f, 100.f, 0.1f);
|
|
bank.AddSlider("Starting Ignition Max Hold", &audVehicleAudioEntity::sm_StartingIgnitionMaxHold, 0.0f, 10.f, 0.01f);
|
|
bank.AddSlider("Starting Ignition Min Hold", &audVehicleAudioEntity::sm_StartingIgnitionMinHold, 0.0f, 10.f, 0.01f);
|
|
bank.AddToggle("BlipPlayerThrottle", &g_BlipPlayerThrottle);
|
|
bank.AddToggle("Force Throttle Blips", &g_ForceEnableBlips);
|
|
bank.AddToggle("Disable Throttle Blips", &g_DisableThrottleBlips);
|
|
bank.AddToggle("Toggle NOS Boost", &g_ToggleNos);
|
|
bank.AddToggle("Test Backfire", &g_TestBackfire);
|
|
bank.AddToggle("Test Backfire Banger", &g_TestBackfireBanger);
|
|
bank.AddToggle("Show Clustered Vehicles", &g_DisplayClusteredVehicles);
|
|
bank.AddSlider("Min Ignition Time", &sm_IgnitionMinHold, 0.01f, 2.f, 0.01f);
|
|
bank.AddSlider("Max Ignition Time", &sm_IgnitionMaxHold, 0.01f, 5.f, 0.01f);
|
|
bank.PopGroup();
|
|
bank.PopGroup();
|
|
|
|
bank.PushGroup("Suspension",false);
|
|
bank.AddSlider("MinSuspensionStartOffset", &sm_MaxSuspensionStartOffset, 0.f,100.f,1.f);
|
|
bank.AddToggle("Mute Suspension", &g_MuteSuspension);
|
|
bank.AddSlider("Hydraulics Modified Timeout Ms", &g_HydraulicsModifiedTimeoutMs, 0,10000,10);
|
|
bank.AddSlider("Hydraulics Activation Delay Frames", &g_NumHydraulicActivationDelayFrames, 0,50,1);
|
|
bank.AddToggle("Force NPC Hydraulics", &g_ForceNPCHydraulicSounds);
|
|
bank.AddToggle("Print Hydraulic Impact Info", &g_DebugHydraulicSounds);
|
|
bank.AddToggle("Override Hydraulic Suspension Health", &g_OverrideHydraulicSuspensionDamage);
|
|
bank.AddSlider("Hydraulic Suspension Health", &g_OverridenHydraulicSuspensionDamage, 0.f,1.f,0.01f);
|
|
bank.AddSlider("Hydraulic Jump Land Suppression Time", &g_HydraulicsJumpLandSuppressionTime, 0,5000,10);
|
|
bank.AddSlider("Suspension Loop Threshold", &g_HydraulicSuspensionAngleLoopTriggerThreshold, 0.f,10.f,0.01f);
|
|
bank.AddSlider("Suspension Loop Threshold Remote", &g_HydraulicSuspensionAngleLoopTriggerThresholdRemoteVehicle, 0.f,10.f,0.01f);
|
|
bank.AddSlider("Suspension ReTrigger Threshold", &g_HydraulicSuspensionAngleLoopReTriggerThreshold, 0.f,100.f,0.01f);
|
|
bank.AddSlider("Suspension ReTrigger Threshold Remote", &g_HydraulicSuspensionAngleLoopReTriggerThresholdRemoteVehicle, 0.f,100.f,0.01f);
|
|
bank.PopGroup();
|
|
|
|
bank.PushGroup("Openness",false);
|
|
bank.AddSlider("Door Cone Inner Angle Scaling", &sm_DoorConeInnerAngleScaling, 0.0f, 1.0f, 0.1f);
|
|
bank.AddSlider("Door Cone Outer Angle", &sm_DoorConeOuterAngle, 0.0f, 360.0f, 1.0f);
|
|
bank.AddToggle("Show Door Ratios", &g_ShowDoorRatios);
|
|
bank.PopGroup();
|
|
|
|
bank.PushGroup("Rolling cars",false);
|
|
bank.AddSlider("g_MinCarRollImpulseMag", &g_MinCarRollImpulseMag, 0.0f, 100.0f, 0.01f);
|
|
bank.AddSlider("g_MaxCarRollImpulseMag", &g_MaxCarRollImpulseMag, 0.0f, 100.0f, 0.01f);
|
|
bank.AddSlider("g_MinCarRollSpeed", &g_MinCarRollSpeed, 0.0f, 100.0f, 0.01f);
|
|
bank.AddSlider("g_MaxCarRollSpeed", &g_MaxCarRollSpeed, 0.0f, 100.0f, 0.01f);
|
|
bank.PopGroup();
|
|
|
|
bank.PushGroup("Optimisation Tests", false);
|
|
bank.AddSlider("Max Real Vehicles", &g_MaxVehicleSubmixes, 0, 100, 1);
|
|
bank.AddSlider("Max Dummy Vehicles", &g_MaxDummyVehicles, 0, 100, 1);
|
|
bank.AddToggle("Draw Vehicle LOD Quadrants", &g_DrawVehicleLODQuadrants);
|
|
bank.AddSlider("Slow Streaming Test Delay Time", &g_WaveSlotStreamingDelayTime, 0.0f, 20.0f, 0.1f);
|
|
bank.PopGroup();
|
|
|
|
audVehicleCollisionAudio::AddWidgets(bank);
|
|
|
|
|
|
bank.PopGroup();
|
|
}
|
|
#endif
|
|
|
|
|