Files
GTASource/game/audio/dynamicmixmodules.cpp

250 lines
5.9 KiB
C++
Raw Permalink Normal View History

2025-02-23 17:40:52 +08:00
#include "dynamicmixmodules.h"
#include "dynamicmixer.h"
#include "scriptaudioentity.h"
#include "vehiclecollisionaudio.h"
#include "vehicles/vehicle.h"
#include "scene/world/GameWorld.h"
#include "debugaudio.h"
AUDIO_DYNAMICMIXING_OPTIMISATIONS()
// Helper functions ----------------------------------------------------------------
static f32 GetPlayerVehVelocity()
{
CVehicle* playerVeh = CGameWorld::FindLocalPlayerVehicle();
if(playerVeh)
{
return playerVeh->GetVelocity().Mag();
}
return 0.f;
}
static f32 GetPlayerVehAirtime()
{
CVehicle* playerVeh = CGameWorld::FindLocalPlayerVehicle();
if(playerVeh)
{
audVehicleAudioEntity * vehAudio = playerVeh->GetVehicleAudioEntity();
if(vehAudio)
{
return (f32)(fwTimer::GetTimeInMilliseconds() - vehAudio->GetLastTimeOnGround());
}
}
return 0.f;
}
static f32 GetPlayerVehUpsideDown()
{
CVehicle* playerVeh = CGameWorld::FindLocalPlayerVehicle();
if(playerVeh)
{
if(playerVeh->GetVehicleType() == VEHICLE_TYPE_CAR &&
(playerVeh->IsUpsideDown()))
{
return 1.f;
}
}
return 0.f;
}
// Scene Variable Mix Module -------------------------------------------------------------------------------
void audSceneVariableMixModule::Init(audDynMixModule * module)
{
module->SetModuleCurve(module->m_SceneVariableSettings->InputOutputCurve);
Update(module);
}
void audSceneVariableMixModule::Update(audDynMixModule * module)
{
const SceneVariableModuleSettings * settings = module->m_SceneVariableSettings;
f32 inputValue = 0.f;
switch(settings->Input)
{
case INPUT_PLAYER_VEH_VELOCITY:
{
inputValue = GetPlayerVehVelocity();
}
break;
case INPUT_PLAYER_VEH_AIRTIME:
{
inputValue = GetPlayerVehAirtime();
}
break;
case INPUT_PLAYER_VEH_ROLL:
{
inputValue = GetPlayerVehUpsideDown();
}
break;
default:
break;
}
f32 outputValue = module->GetModuleCurve()->CalculateRescaledValue(0.f, 1.f, settings->ScaleMin, settings->ScaleMax, inputValue);
module->GetScene()->SetVariableValue(settings->SceneVariable, outputValue);
}
void audSceneVariableMixModule::Shutdown(audDynMixModule * UNUSED_PARAM(module))
{
}
// Vehicle collision mix module ----------------------------------------------------------
void audVehicleCollisionMixModule::Init(audDynMixModule * UNUSED_PARAM(module))
{
}
void audVehicleCollisionMixModule::Update(audDynMixModule * UNUSED_PARAM(module))
{
}
void audVehicleCollisionMixModule::Shutdown(audDynMixModule * UNUSED_PARAM(module))
{
}
void audVehicleCollisionMixModule::Process(audDynMixModule * module, audVehicleCollisionAudio * collisionAudio)
{
audVehicleCollisionContext * playContext = collisionAudio->GetCollisionContextList().GetEvents();
bool vehicleOnLeftSide = false, buildingOnLeftSide = false;
bool vehicleOnRightSide = false, buildingOnRightSide = false;
while(playContext)
{
if(playContext->GetTypeFlag(AUD_VEH_COLLISION_LEFTSIDE) && playContext->otherEntity->GetIsTypeBuilding())
{
buildingOnLeftSide = true;
}
if(playContext->GetTypeFlag(AUD_VEH_COLLISION_RIGHTSIDE) && playContext->otherEntity->GetIsTypeBuilding())
{
buildingOnRightSide = true;
}
if(playContext->GetTypeFlag(AUD_VEH_COLLISION_LEFTSIDE) && playContext->otherEntity->GetIsTypeVehicle())
{
vehicleOnLeftSide = true;
}
if(playContext->GetTypeFlag(AUD_VEH_COLLISION_RIGHTSIDE) && playContext->otherEntity->GetIsTypeVehicle())
{
vehicleOnRightSide = true;
}
}
switch(module->m_VehicleCollisionModuleSettings->Input)
{
case VEH_VEH_SIDES:
if(vehicleOnLeftSide && vehicleOnRightSide)
{
//We're sandwiched between two vehicles
//Assert(0);
}
break;
case VEH_BUILDING_SIDES:
if((buildingOnRightSide && vehicleOnLeftSide) || (buildingOnLeftSide && vehicleOnRightSide))
{
//We're being squashed into a building wheeeeeeee
//Assert(0);
}
}
}
// Scene Transition Mix Module -------------------------------------------------------------------------------------------------
void audSceneTransitionMixModule::Init(audDynMixModule * UNUSED_PARAM(module))
{
}
void audSceneTransitionMixModule::Update(audDynMixModule * module)
{
const SceneTransitionModuleSettings * settings = module->m_SceneTransitionSettings;
f32 inputValue = 0.f;
switch(settings->Input)
{
case INPUT_PLAYER_VEH_VELOCITY:
{
inputValue = GetPlayerVehVelocity();
}
break;
case INPUT_PLAYER_VEH_AIRTIME:
{
inputValue = GetPlayerVehAirtime();
}
break;
case INPUT_PLAYER_VEH_ROLL:
{
inputValue = GetPlayerVehUpsideDown();
}
break;
default:
break;
}
}
void audSceneTransitionMixModule::Shutdown(audDynMixModule * UNUSED_PARAM(module))
{
}
// audDynamicMixModuleInterface -------------------------------------------------------
audDynamicMixModuleInterface::audDynamicMixModuleInterface()
{
sysMemSet(&m_VehiclePostCollisionMods[0], 0, sizeof(m_VehiclePostCollisionMods));
}
void audDynamicMixModuleInterface::AddVehicleCollisionModule(audDynMixModule * module)
{
for(int i=0; i < k_max_mods; i++)
{
if(!m_VehiclePostCollisionMods[i])
{
m_VehiclePostCollisionMods[i] = module;
return;
}
}
naAssertf(0, "Ran out of room in m_VehiclePostCollisionMods");
}
void audDynamicMixModuleInterface::RemoveVehicleCollisionModule(audDynMixModule * module)
{
for(int i=0; i < k_max_mods; i++)
{
if(m_VehiclePostCollisionMods[i] == module)
{
m_VehiclePostCollisionMods[i] = NULL;
}
}
naAssertf(0, "Couldn't find module %s to remove from m_VehiclePostCollisionMods", module->GetModuleName());
}
void audDynamicMixModuleInterface::ProcessVehiclePostCollision(audVehicleCollisionAudio * collisionAudio)
{
for(int i=0; i < k_max_mods; i++)
{
if(m_VehiclePostCollisionMods[i])
{
audVehicleAudioEntity * vehicleAudio = collisionAudio->GetParent();
if(!m_VehiclePostCollisionMods[i]->GetMixGroup() ||
m_VehiclePostCollisionMods[i]->GetMixGroup()->GetIndex() == vehicleAudio->GetEnvironmentGroup()->GetMixGroupIndex())
{
audVehicleCollisionMixModule::Process(m_VehiclePostCollisionMods[i], collisionAudio);
}
}
}
}