commit
36ecf74ee7
399
src/audio/AudioCollision.cpp
Normal file
399
src/audio/AudioCollision.cpp
Normal file
@ -0,0 +1,399 @@
|
|||||||
|
#include "common.h"
|
||||||
|
#include "patcher.h"
|
||||||
|
#include "DMAudio.h"
|
||||||
|
#include "Entity.h"
|
||||||
|
#include "AudioCollision.h"
|
||||||
|
#include "AudioManager.h"
|
||||||
|
#include "AudioSamples.h"
|
||||||
|
#include "SurfaceTable.h"
|
||||||
|
#include "sampman.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
cAudioCollisionManager::AddCollisionToRequestedQueue()
|
||||||
|
{
|
||||||
|
int32 collisionsIndex;
|
||||||
|
int32 i;
|
||||||
|
|
||||||
|
|
||||||
|
if (m_bCollisionsInQueue < NUMAUDIOCOLLISIONS)
|
||||||
|
collisionsIndex = m_bCollisionsInQueue++;
|
||||||
|
else {
|
||||||
|
collisionsIndex = m_bIndicesTable[NUMAUDIOCOLLISIONS - 1];
|
||||||
|
if (m_sQueue.m_fDistance >= m_asCollisions1[collisionsIndex].m_fDistance) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_asCollisions1[collisionsIndex] = m_sQueue;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
if(collisionsIndex) {
|
||||||
|
while(m_asCollisions1[m_bIndicesTable[i]].m_fDistance <= m_asCollisions1[collisionsIndex].m_fDistance) {
|
||||||
|
if(++i >= collisionsIndex) {
|
||||||
|
m_bIndicesTable[i] = collisionsIndex;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
memmove(&m_bIndicesTable[i + 1], &m_bIndicesTable[i], NUMAUDIOCOLLISIONS - 1 - i);
|
||||||
|
}
|
||||||
|
m_bIndicesTable[i] = collisionsIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
float
|
||||||
|
cAudioManager::GetCollisionLoopingRatio(uint32 a, uint32 b, float c) const
|
||||||
|
{
|
||||||
|
return GetCollisionRatio(c, 0.0f, 0.02f, 0.02f);
|
||||||
|
}
|
||||||
|
|
||||||
|
float
|
||||||
|
cAudioManager::GetCollisionOneShotRatio(int32 a, float b) const
|
||||||
|
{
|
||||||
|
float result;
|
||||||
|
|
||||||
|
switch(a) {
|
||||||
|
case SURFACE_DEFAULT:
|
||||||
|
case SURFACE_TARMAC:
|
||||||
|
case SURFACE_PAVEMENT:
|
||||||
|
case SURFACE_STONE:
|
||||||
|
case SURFACE_BOLLARD: result = GetCollisionRatio(b, 10.f, 60.f, 50.f); break;
|
||||||
|
case SURFACE_GRASS:
|
||||||
|
case SURFACE_LOOSE30: result = GetCollisionRatio(b, 0.f, 2.f, 2.f); break;
|
||||||
|
case SURFACE_DIRT: result = GetCollisionRatio(b, 0.f, 2.f, 2.f); break;
|
||||||
|
case SURFACE_DIRTTRACK: result = GetCollisionRatio(b, 0.f, 2.f, 2.f); break;
|
||||||
|
case SURFACE_METAL6: result = GetCollisionRatio(b, 6.f, 50.f, 44.f); break;
|
||||||
|
case SURFACE_GLASS: result = GetCollisionRatio(b, 0.1f, 10.f, 9.9f); break;
|
||||||
|
case SURFACE_SCAFFOLD:
|
||||||
|
case SURFACE_STEEL: result = GetCollisionRatio(b, 30.f, 130.f, 100.f); break;
|
||||||
|
case SURFACE_METAL_DOOR: result = GetCollisionRatio(b, 20.f, 100.f, 80.f); break;
|
||||||
|
case SURFACE_BILLBOARD: result = GetCollisionRatio(b, 0.f, 4.f, 4.f); break;
|
||||||
|
case SURFACE_METAL_POLE:
|
||||||
|
case SURFACE_GATE: result = GetCollisionRatio(b, 1.f, 10.f, 9.f); break;
|
||||||
|
case SURFACE_STREET_LIGHT: result = GetCollisionRatio(b, 1.f, 10.f, 9.f); break;
|
||||||
|
case SURFACE_METAL14: result = GetCollisionRatio(b, 1.f, 15.f, 14.f); break;
|
||||||
|
case SURFACE_METAL15: result = GetCollisionRatio(b, 8.f, 50.f, 42.f); break;
|
||||||
|
case SURFACE_METAL_FENCE: result = GetCollisionRatio(b, 0.1f, 10.f, 9.9f); break;
|
||||||
|
case SURFACE_FLESH: result = GetCollisionRatio(b, 0.f, 20.f, 20.f); break;
|
||||||
|
case SURFACE_SAND: result = GetCollisionRatio(b, 0.f, 10.f, 10.f); break;
|
||||||
|
case SURFACE_PUDDLE: result = GetCollisionRatio(b, 0.f, 10.f, 10.f); break;
|
||||||
|
case SURFACE_WOOD: result = GetCollisionRatio(b, 1.f, 4.f, 3.f); break;
|
||||||
|
case SURFACE_WOOD_BOX: result = GetCollisionRatio(b, 0.1f, 5.f, 4.9f); break;
|
||||||
|
case SURFACE_WOOD_PLANK: result = GetCollisionRatio(b, 0.1f, 40.f, 39.9f); break;
|
||||||
|
case SURFACE_TIRE:
|
||||||
|
case SURFACE_RUBBER29: result = GetCollisionRatio(b, 0.f, 10.f, 10.f); break;
|
||||||
|
case SURFACE_HARD24: result = GetCollisionRatio(b, 0.1f, 4.f, 3.9f); break;
|
||||||
|
case SURFACE_HEDGE: result = GetCollisionRatio(b, 0.f, 0.5f, 0.5f); break;
|
||||||
|
case SURFACE_METAL27: result = GetCollisionRatio(b, 4.f, 40.f, 36.f); break;
|
||||||
|
case SURFACE_METAL28: result = GetCollisionRatio(b, 0.f, 5.f, 5.f); break;
|
||||||
|
default: result = 0.f; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
float
|
||||||
|
cAudioManager::GetCollisionRatio(float a, float b, float c, float d) const
|
||||||
|
{
|
||||||
|
float e;
|
||||||
|
e = a;
|
||||||
|
if(a <= b) return 0.0f;
|
||||||
|
if(c <= a) e = c;
|
||||||
|
return (e - b) / d;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32
|
||||||
|
cAudioManager::SetLoopingCollisionRequestedSfxFreqAndGetVol(cAudioCollision *audioCollision)
|
||||||
|
{
|
||||||
|
uint8 surface1 = audioCollision->m_bSurface1;
|
||||||
|
uint8 surface2 = audioCollision->m_bSurface2;
|
||||||
|
int32 vol;
|
||||||
|
float ratio;
|
||||||
|
|
||||||
|
if(surface1 == SURFACE_GRASS || surface2 == SURFACE_GRASS || surface1 == SURFACE_HEDGE ||
|
||||||
|
surface2 == SURFACE_HEDGE) {
|
||||||
|
ratio = GetCollisionRatio(audioCollision->m_fIntensity2, 0.0001f, 0.09f, 0.0899f);
|
||||||
|
m_sQueueSample.m_nSampleIndex = SFX_RAIN;
|
||||||
|
m_sQueueSample.m_nFrequency = 13000.f * ratio + 35000;
|
||||||
|
vol = 50.f * ratio;
|
||||||
|
} else {
|
||||||
|
if(surface1 == SURFACE_PUDDLE || surface2 == SURFACE_PUDDLE) {
|
||||||
|
ratio = GetCollisionRatio(audioCollision->m_fIntensity2, 0.0001f, 0.09f, 0.0899f);
|
||||||
|
m_sQueueSample.m_nSampleIndex = SFX_BOAT_WATER_LOOP;
|
||||||
|
m_sQueueSample.m_nFrequency = 6050.f * ratio + 16000;
|
||||||
|
vol = 30.f * ratio;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if(surface1 == SURFACE_DIRT || surface2 == SURFACE_DIRT || surface1 == SURFACE_DIRTTRACK ||
|
||||||
|
surface2 == SURFACE_DIRTTRACK || surface1 == SURFACE_SAND || surface2 == SURFACE_SAND) {
|
||||||
|
ratio = GetCollisionRatio(audioCollision->m_fIntensity2, 0.0001f, 0.09f, 0.0899f);
|
||||||
|
m_sQueueSample.m_nSampleIndex = SFX_GRAVEL_SKID;
|
||||||
|
m_sQueueSample.m_nFrequency = 6000.f * ratio + 10000;
|
||||||
|
vol = 50.f * ratio;
|
||||||
|
} else {
|
||||||
|
if(surface1 == SURFACE_FLESH || surface2 == SURFACE_FLESH) { return 0; }
|
||||||
|
ratio = GetCollisionRatio(audioCollision->m_fIntensity2, 0.0001f, 0.09f, 0.0899f);
|
||||||
|
m_sQueueSample.m_nSampleIndex = SFX_SCRAPE_CAR_1;
|
||||||
|
m_sQueueSample.m_nFrequency = 10000.f * ratio + 10000;
|
||||||
|
vol = 40.f * ratio;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(audioCollision->m_nBaseVolume < 2) vol = audioCollision->m_nBaseVolume * vol / 2;
|
||||||
|
return vol;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cAudioManager::SetUpLoopingCollisionSound(cAudioCollision *col, uint8 counter)
|
||||||
|
{
|
||||||
|
if(col->m_fIntensity2 > 0.0016f) {
|
||||||
|
uint8 emittingVol = SetLoopingCollisionRequestedSfxFreqAndGetVol(col);
|
||||||
|
if(emittingVol) {
|
||||||
|
m_sQueueSample.m_fDistance = Sqrt(col->m_fDistance);
|
||||||
|
m_sQueueSample.m_bVolume = ComputeVolume(emittingVol, 60.f, m_sQueueSample.m_fDistance);
|
||||||
|
if(m_sQueueSample.m_bVolume) {
|
||||||
|
m_sQueueSample.m_counter = counter;
|
||||||
|
m_sQueueSample.m_vecPos = col->m_vecPosition;
|
||||||
|
m_sQueueSample.m_bBankIndex = 0;
|
||||||
|
m_sQueueSample.m_bIsDistant = 0;
|
||||||
|
m_sQueueSample.field_16 = 7;
|
||||||
|
m_sQueueSample.m_nLoopCount = 0;
|
||||||
|
m_sQueueSample.m_bEmittingVolume = emittingVol;
|
||||||
|
m_sQueueSample.m_nLoopStart =
|
||||||
|
SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);
|
||||||
|
m_sQueueSample.m_nLoopEnd =
|
||||||
|
SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);
|
||||||
|
m_sQueueSample.field_48 = 4.0f;
|
||||||
|
m_sQueueSample.m_fSoundIntensity = 60.0f;
|
||||||
|
m_sQueueSample.field_56 = 0;
|
||||||
|
m_sQueueSample.field_76 = 5;
|
||||||
|
m_sQueueSample.m_bReverbFlag = 1;
|
||||||
|
m_sQueueSample.m_bRequireReflection = 0;
|
||||||
|
AddSampleToRequestedQueue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cAudioManager::SetUpOneShotCollisionSound(cAudioCollision *col)
|
||||||
|
{
|
||||||
|
static const int32 gOneShotCol[] = {
|
||||||
|
SFX_COL_TARMAC_1, SFX_COL_TARMAC_1, SFX_COL_GRASS_1,
|
||||||
|
SFX_COL_GRAVEL_1, SFX_COL_MUD_1, SFX_COL_TARMAC_1,
|
||||||
|
SFX_COL_CAR_1, SFX_COL_GRASS_1, SFX_COL_SCAFFOLD_POLE_1,
|
||||||
|
SFX_COL_GARAGE_DOOR_1, SFX_COL_CAR_PANEL_1, SFX_COL_THICK_METAL_PLATE_1,
|
||||||
|
SFX_COL_SCAFFOLD_POLE_1, SFX_COL_LAMP_POST_1, SFX_COL_HYDRANT_1,
|
||||||
|
SFX_COL_HYDRANT_1, SFX_COL_METAL_CHAIN_FENCE_1, SFX_COL_PED_1,
|
||||||
|
SFX_COL_SAND_1, SFX_SPLASH_1, SFX_COL_WOOD_CRATES_1,
|
||||||
|
SFX_COL_WOOD_BENCH_1, SFX_COL_WOOD_SOLID_1, SFX_COL_GRASS_1,
|
||||||
|
SFX_COL_GRASS_1, SFX_COL_VEG_1, SFX_COL_TARMAC_1,
|
||||||
|
SFX_COL_CONTAINER_1, SFX_COL_NEWS_VENDOR_1, SFX_TYRE_BUMP,
|
||||||
|
SFX_COL_CARDBOARD_1, SFX_COL_TARMAC_1, SFX_COL_GATE};
|
||||||
|
|
||||||
|
int16 s1;
|
||||||
|
int16 s2;
|
||||||
|
|
||||||
|
int32 emittingVol;
|
||||||
|
float ratio;
|
||||||
|
|
||||||
|
static uint16 counter = 28;
|
||||||
|
|
||||||
|
for(int32 i = 0; i < 2; i++) {
|
||||||
|
if(i) {
|
||||||
|
s1 = col->m_bSurface2;
|
||||||
|
s2 = col->m_bSurface1;
|
||||||
|
} else {
|
||||||
|
s1 = col->m_bSurface1;
|
||||||
|
s2 = col->m_bSurface2;
|
||||||
|
}
|
||||||
|
ratio = GetCollisionOneShotRatio(s1, col->m_fIntensity1);
|
||||||
|
if(s1 == SURFACE_METAL6 && s2 == SURFACE_FLESH) ratio = 0.25f * ratio;
|
||||||
|
if(s1 == SURFACE_METAL6 && ratio < 0.6f) {
|
||||||
|
s1 = SURFACE_BILLBOARD;
|
||||||
|
ratio = min(1.f, 2.f * ratio);
|
||||||
|
}
|
||||||
|
emittingVol = 40.f * ratio;
|
||||||
|
if(emittingVol) {
|
||||||
|
m_sQueueSample.m_fDistance = Sqrt(col->m_fDistance);
|
||||||
|
m_sQueueSample.m_bVolume = ComputeVolume(emittingVol, 60.f, m_sQueueSample.m_fDistance);
|
||||||
|
if(m_sQueueSample.m_bVolume) {
|
||||||
|
m_sQueueSample.m_nSampleIndex = gOneShotCol[s1];
|
||||||
|
switch(m_sQueueSample.m_nSampleIndex) {
|
||||||
|
case SFX_COL_TARMAC_1:
|
||||||
|
m_sQueueSample.m_nSampleIndex += m_anRandomTable[3] % 5;
|
||||||
|
break;
|
||||||
|
case SFX_COL_CAR_PANEL_1:
|
||||||
|
m_sQueueSample.m_nSampleIndex += m_anRandomTable[0] % 6;
|
||||||
|
break;
|
||||||
|
case SFX_COL_LAMP_POST_1:
|
||||||
|
m_sQueueSample.m_nSampleIndex += m_anRandomTable[1] % 2;
|
||||||
|
break;
|
||||||
|
case SFX_COL_METAL_CHAIN_FENCE_1:
|
||||||
|
m_sQueueSample.m_nSampleIndex += m_anRandomTable[3] % 4;
|
||||||
|
break;
|
||||||
|
case SFX_COL_PED_1:
|
||||||
|
m_sQueueSample.m_nSampleIndex += m_anRandomTable[4] % 5;
|
||||||
|
break;
|
||||||
|
case SFX_COL_WOOD_CRATES_1:
|
||||||
|
m_sQueueSample.m_nSampleIndex += m_anRandomTable[4] % 4;
|
||||||
|
break;
|
||||||
|
case SFX_COL_WOOD_BENCH_1:
|
||||||
|
m_sQueueSample.m_nSampleIndex += m_anRandomTable[1] % 4;
|
||||||
|
break;
|
||||||
|
case SFX_COL_VEG_1:
|
||||||
|
m_sQueueSample.m_nSampleIndex += m_anRandomTable[2] % 5;
|
||||||
|
break;
|
||||||
|
case SFX_COL_NEWS_VENDOR_1:
|
||||||
|
m_sQueueSample.m_nSampleIndex += m_anRandomTable[2] % 3;
|
||||||
|
break;
|
||||||
|
case SFX_COL_CAR_1:
|
||||||
|
m_sQueueSample.m_nSampleIndex += m_anRandomTable[1] % 5;
|
||||||
|
break;
|
||||||
|
case SFX_COL_CARDBOARD_1:
|
||||||
|
m_sQueueSample.m_nSampleIndex += m_anRandomTable[3] % 2;
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
switch(s1) {
|
||||||
|
case SURFACE_GLASS: m_sQueueSample.m_nFrequency = 13500; break;
|
||||||
|
case SURFACE_METAL15: m_sQueueSample.m_nFrequency = 8819; break;
|
||||||
|
case SURFACE_PUDDLE:
|
||||||
|
m_sQueueSample.m_nFrequency =
|
||||||
|
2 * SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);
|
||||||
|
break;
|
||||||
|
case SURFACE_TIRE: m_sQueueSample.m_nFrequency = 6000; break;
|
||||||
|
case SURFACE_HARD24: m_sQueueSample.m_nFrequency = 8000; break;
|
||||||
|
default:
|
||||||
|
m_sQueueSample.m_nFrequency =
|
||||||
|
SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16);
|
||||||
|
m_sQueueSample.m_counter = counter++;
|
||||||
|
if(counter >= 255) counter = 28;
|
||||||
|
m_sQueueSample.m_vecPos = col->m_vecPosition;
|
||||||
|
m_sQueueSample.m_bBankIndex = 0;
|
||||||
|
m_sQueueSample.m_bIsDistant = 0;
|
||||||
|
m_sQueueSample.field_16 = 11;
|
||||||
|
m_sQueueSample.m_nLoopCount = 1;
|
||||||
|
m_sQueueSample.m_bEmittingVolume = emittingVol;
|
||||||
|
m_sQueueSample.m_nLoopStart = 0;
|
||||||
|
m_sQueueSample.m_nLoopEnd = -1;
|
||||||
|
m_sQueueSample.field_48 = 4.0f;
|
||||||
|
m_sQueueSample.m_fSoundIntensity = 60.0f;
|
||||||
|
m_sQueueSample.field_56 = 1;
|
||||||
|
m_sQueueSample.m_bReverbFlag = 1;
|
||||||
|
m_sQueueSample.m_bRequireReflection = 0;
|
||||||
|
AddSampleToRequestedQueue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cAudioManager::ServiceCollisions()
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
bool someArr1[NUMAUDIOCOLLISIONS];
|
||||||
|
bool someArr2[NUMAUDIOCOLLISIONS];
|
||||||
|
|
||||||
|
m_sQueueSample.m_nEntityIndex = m_nCollisionEntity;
|
||||||
|
|
||||||
|
for (int i = 0; i < NUMAUDIOCOLLISIONS; i++)
|
||||||
|
someArr1[i] = someArr2[i] = false;
|
||||||
|
|
||||||
|
for (i = 0; i < m_sCollisionManager.m_bCollisionsInQueue; i++) {
|
||||||
|
for (j = 0; j < NUMAUDIOCOLLISIONS; j++) {
|
||||||
|
int index = m_sCollisionManager.m_bIndicesTable[i];
|
||||||
|
if ((m_sCollisionManager.m_asCollisions1[index].m_pEntity1 == m_sCollisionManager.m_asCollisions2[j].m_pEntity1)
|
||||||
|
&& (m_sCollisionManager.m_asCollisions1[index].m_pEntity2 == m_sCollisionManager.m_asCollisions2[j].m_pEntity2)
|
||||||
|
&& (m_sCollisionManager.m_asCollisions1[index].m_bSurface1 == m_sCollisionManager.m_asCollisions2[j].m_bSurface1)
|
||||||
|
&& (m_sCollisionManager.m_asCollisions1[index].m_bSurface2 == m_sCollisionManager.m_asCollisions2[j].m_bSurface2)
|
||||||
|
) {
|
||||||
|
someArr1[index] = true;
|
||||||
|
someArr2[j] = true;
|
||||||
|
m_sCollisionManager.m_asCollisions1[index].m_nBaseVolume = ++m_sCollisionManager.m_asCollisions2[j].m_nBaseVolume;
|
||||||
|
SetUpLoopingCollisionSound(&m_sCollisionManager.m_asCollisions1[index], j);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < NUMAUDIOCOLLISIONS; i++) {
|
||||||
|
if (!someArr2[i]) {
|
||||||
|
m_sCollisionManager.m_asCollisions2[i].m_pEntity1 = nil;
|
||||||
|
m_sCollisionManager.m_asCollisions2[i].m_pEntity2 = nil;
|
||||||
|
m_sCollisionManager.m_asCollisions2[i].m_bSurface1 = 0;
|
||||||
|
m_sCollisionManager.m_asCollisions2[i].m_bSurface2 = 0;
|
||||||
|
m_sCollisionManager.m_asCollisions2[i].m_fIntensity2 = 0.0f;
|
||||||
|
m_sCollisionManager.m_asCollisions2[i].m_fIntensity1 = 0.0f;
|
||||||
|
m_sCollisionManager.m_asCollisions2[i].m_vecPosition = CVector(0.0f, 0.0f, 0.0f);
|
||||||
|
m_sCollisionManager.m_asCollisions2[i].m_fDistance = 0.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < m_sCollisionManager.m_bCollisionsInQueue; i++) {
|
||||||
|
int index = m_sCollisionManager.m_bIndicesTable[i];
|
||||||
|
if (!someArr1[index]) {
|
||||||
|
for (j = 0; j < NUMAUDIOCOLLISIONS; j++) {
|
||||||
|
if (someArr2[j]) {
|
||||||
|
m_sCollisionManager.m_asCollisions2[j].m_nBaseVolume = 1;
|
||||||
|
m_sCollisionManager.m_asCollisions2[j].m_pEntity1 = m_sCollisionManager.m_asCollisions1[index].m_pEntity1;
|
||||||
|
m_sCollisionManager.m_asCollisions2[j].m_pEntity2 = m_sCollisionManager.m_asCollisions1[index].m_pEntity2;
|
||||||
|
m_sCollisionManager.m_asCollisions2[j].m_bSurface1 = m_sCollisionManager.m_asCollisions1[index].m_bSurface1;
|
||||||
|
m_sCollisionManager.m_asCollisions2[j].m_bSurface2 = m_sCollisionManager.m_asCollisions1[index].m_bSurface2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SetUpOneShotCollisionSound(&m_sCollisionManager.m_asCollisions1[index]);
|
||||||
|
SetUpLoopingCollisionSound(&m_sCollisionManager.m_asCollisions1[index], j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < NUMAUDIOCOLLISIONS; i++)
|
||||||
|
m_sCollisionManager.m_bIndicesTable[i] = NUMAUDIOCOLLISIONS;
|
||||||
|
m_sCollisionManager.m_bCollisionsInQueue = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cAudioManager::ReportCollision(CEntity *entity1, CEntity *entity2, uint8 surface1, uint8 surface2, float collisionPower,
|
||||||
|
float velocity)
|
||||||
|
{
|
||||||
|
float dist;
|
||||||
|
CVector v1;
|
||||||
|
CVector v2;
|
||||||
|
|
||||||
|
if(!m_bIsInitialised || m_nCollisionEntity < 0 || m_bUserPause ||
|
||||||
|
(velocity < 0.0016f && collisionPower < 0.01f))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(entity1->IsBuilding()) {
|
||||||
|
v1 = v2 = entity2->GetPosition();
|
||||||
|
} else if(entity2->IsBuilding()) {
|
||||||
|
v1 = v2 = entity1->GetPosition();
|
||||||
|
} else {
|
||||||
|
v1 = entity1->GetPosition();
|
||||||
|
v2 = entity2->GetPosition();
|
||||||
|
}
|
||||||
|
CVector pos = (v1 + v2) * 0.5f;
|
||||||
|
dist = GetDistanceSquared(&pos);
|
||||||
|
if(dist < SQR(60.f)) {
|
||||||
|
m_sCollisionManager.m_sQueue.m_pEntity1 = entity1;
|
||||||
|
m_sCollisionManager.m_sQueue.m_pEntity2 = entity2;
|
||||||
|
m_sCollisionManager.m_sQueue.m_bSurface1 = surface1;
|
||||||
|
m_sCollisionManager.m_sQueue.m_bSurface2 = surface2;
|
||||||
|
m_sCollisionManager.m_sQueue.m_fIntensity1 = collisionPower;
|
||||||
|
m_sCollisionManager.m_sQueue.m_fIntensity2 = velocity;
|
||||||
|
m_sCollisionManager.m_sQueue.m_vecPosition = pos;
|
||||||
|
m_sCollisionManager.m_sQueue.m_fDistance = dist;
|
||||||
|
m_sCollisionManager.AddCollisionToRequestedQueue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
STARTPATCHES
|
||||||
|
InjectHook(0x5685E0, &cAudioCollisionManager::AddCollisionToRequestedQueue, PATCH_JUMP);
|
||||||
|
InjectHook(0x569060, &cAudioManager::GetCollisionOneShotRatio, PATCH_JUMP);
|
||||||
|
InjectHook(0x5693B0, &cAudioManager::GetCollisionRatio, PATCH_JUMP);
|
||||||
|
InjectHook(0x568410, &cAudioManager::ReportCollision, PATCH_JUMP);
|
||||||
|
InjectHook(0x5686D0, &cAudioManager::ServiceCollisions, PATCH_JUMP);
|
||||||
|
InjectHook(0x568E20, &cAudioManager::SetLoopingCollisionRequestedSfxFreqAndGetVol, PATCH_JUMP);
|
||||||
|
InjectHook(0x568D30, &cAudioManager::SetUpLoopingCollisionSound, PATCH_JUMP);
|
||||||
|
InjectHook(0x5689D0, &cAudioManager::SetUpOneShotCollisionSound, PATCH_JUMP);
|
||||||
|
ENDPATCHES
|
36
src/audio/AudioCollision.h
Normal file
36
src/audio/AudioCollision.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define NUMAUDIOCOLLISIONS 10
|
||||||
|
|
||||||
|
class cAudioCollision
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CEntity *m_pEntity1;
|
||||||
|
CEntity *m_pEntity2;
|
||||||
|
uint8 m_bSurface1;
|
||||||
|
uint8 m_bSurface2;
|
||||||
|
float m_fIntensity1;
|
||||||
|
float m_fIntensity2;
|
||||||
|
CVector m_vecPosition;
|
||||||
|
float m_fDistance;
|
||||||
|
int32 m_nBaseVolume;
|
||||||
|
|
||||||
|
// no methods
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(cAudioCollision) == 40, "cAudioCollision: error");
|
||||||
|
|
||||||
|
class cAudioCollisionManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
cAudioCollision m_asCollisions1[NUMAUDIOCOLLISIONS];
|
||||||
|
cAudioCollision m_asCollisions2[NUMAUDIOCOLLISIONS];
|
||||||
|
uint8 m_bIndicesTable[NUMAUDIOCOLLISIONS];
|
||||||
|
uint8 m_bCollisionsInQueue;
|
||||||
|
cAudioCollision m_sQueue;
|
||||||
|
|
||||||
|
// reversed all methods
|
||||||
|
void AddCollisionToRequestedQueue(); /// ok
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(cAudioCollisionManager) == 852, "cAudioCollisionManager: error");
|
File diff suppressed because it is too large
Load Diff
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include "DMAudio.h"
|
#include "DMAudio.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "AudioCollision.h"
|
||||||
|
#include "PoliceRadio.h"
|
||||||
|
|
||||||
enum eScriptSounds : int16
|
enum eScriptSounds : int16
|
||||||
{
|
{
|
||||||
@ -182,25 +184,6 @@ public:
|
|||||||
|
|
||||||
static_assert(sizeof(tSound) == 92, "tSound: error");
|
static_assert(sizeof(tSound) == 92, "tSound: error");
|
||||||
|
|
||||||
enum eAudioType : int32
|
|
||||||
{
|
|
||||||
AUDIOTYPE_PHYSICAL = 0,
|
|
||||||
AUDIOTYPE_EXPLOSION = 1,
|
|
||||||
AUDIOTYPE_FIRE = 2,
|
|
||||||
AUDIOTYPE_WEATHER = 3,
|
|
||||||
AUDIOTYPE_CRANE = 4,
|
|
||||||
AUDIOTYPE_SCRIPTOBJECT = 5,
|
|
||||||
AUDIOTYPE_BRIDGE = 6,
|
|
||||||
AUDIOTYPE_COLLISION = 7,
|
|
||||||
AUDIOTYPE_FRONTEND = 8,
|
|
||||||
AUDIOTYPE_PROJECTILE = 9,
|
|
||||||
AUDIOTYPE_GARAGE = 10,
|
|
||||||
AUDIOTYPE_FIREHYDRANT = 11,
|
|
||||||
AUDIOTYPE_WATERCANNON = 12,
|
|
||||||
AUDIOTYPE_POLICERADIO = 13,
|
|
||||||
TOTAL_AUDIO_TYPES = 14,
|
|
||||||
};
|
|
||||||
|
|
||||||
class CPhysical;
|
class CPhysical;
|
||||||
class CAutomobile;
|
class CAutomobile;
|
||||||
|
|
||||||
@ -256,42 +239,6 @@ static_assert(sizeof(cPedComments) == 1164, "cPedComments: error");
|
|||||||
|
|
||||||
class CEntity;
|
class CEntity;
|
||||||
|
|
||||||
class cAudioCollision
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CEntity *m_pEntity1;
|
|
||||||
CEntity *m_pEntity2;
|
|
||||||
uint8 m_bSurface1;
|
|
||||||
uint8 m_bSurface2;
|
|
||||||
uint8 field_10;
|
|
||||||
uint8 field_11;
|
|
||||||
float m_fIntensity1;
|
|
||||||
float m_fIntensity2;
|
|
||||||
CVector m_vecPosition;
|
|
||||||
float m_fDistance;
|
|
||||||
int32 m_nBaseVolume;
|
|
||||||
|
|
||||||
// no methods
|
|
||||||
};
|
|
||||||
|
|
||||||
static_assert(sizeof(cAudioCollision) == 40, "cAudioCollision: error");
|
|
||||||
|
|
||||||
class cAudioCollisionManager
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
cAudioCollision m_asCollisions1[10];
|
|
||||||
cAudioCollision m_asCollisions2[10];
|
|
||||||
uint8 m_bIndicesTable[10];
|
|
||||||
uint8 m_bCollisionsInQueue;
|
|
||||||
uint8 gap_811;
|
|
||||||
cAudioCollision m_sQueue;
|
|
||||||
|
|
||||||
// reversed all methods
|
|
||||||
void AddCollisionToRequestedQueue(); /// ok
|
|
||||||
};
|
|
||||||
|
|
||||||
static_assert(sizeof(cAudioCollisionManager) == 852, "cAudioCollisionManager: error");
|
|
||||||
|
|
||||||
class cMissionAudio
|
class cMissionAudio
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -320,24 +267,6 @@ class CPed;
|
|||||||
class cPedParams;
|
class cPedParams;
|
||||||
class cTransmission;
|
class cTransmission;
|
||||||
|
|
||||||
class cAudioScriptObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
int16 AudioId;
|
|
||||||
char _pad0[2];
|
|
||||||
CVector Posn;
|
|
||||||
int32 AudioEntity;
|
|
||||||
|
|
||||||
void Reset(); /// ok
|
|
||||||
|
|
||||||
static void *operator new(size_t);
|
|
||||||
static void *operator new(size_t, int);
|
|
||||||
static void operator delete(void *, size_t);
|
|
||||||
static void operator delete(void *, int);
|
|
||||||
};
|
|
||||||
|
|
||||||
static_assert(sizeof(cAudioScriptObject) == 20, "cAudioScriptObject: error");
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
/*
|
/*
|
||||||
REFLECTION_YMAX = 0, top
|
REFLECTION_YMAX = 0, top
|
||||||
@ -355,23 +284,6 @@ enum {
|
|||||||
MAX_REFLECTIONS,
|
MAX_REFLECTIONS,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum AudioEntityHandle {
|
|
||||||
AEHANDLE_NONE = -5,
|
|
||||||
AEHANDLE_ERROR_NOAUDIOSYS = -4,
|
|
||||||
AEHANDLE_ERROR_NOFREESLOT = -3,
|
|
||||||
AEHANDLE_ERROR_NOENTITY = -2,
|
|
||||||
AEHANDLE_ERROR_BADAUDIOTYPE = -1,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct cAMCrime {
|
|
||||||
int32 type;
|
|
||||||
CVector position;
|
|
||||||
uint16 timer;
|
|
||||||
uint16 gap;
|
|
||||||
};
|
|
||||||
|
|
||||||
static_assert(sizeof(cAMCrime) == 20, "cAMCrime: error ");
|
|
||||||
|
|
||||||
class cAudioManager
|
class cAudioManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -407,12 +319,7 @@ public:
|
|||||||
int32 m_nFireAudioEntity;
|
int32 m_nFireAudioEntity;
|
||||||
int32 m_nWaterCannonEntity;
|
int32 m_nWaterCannonEntity;
|
||||||
int32 m_nPoliceChannelEntity;
|
int32 m_nPoliceChannelEntity;
|
||||||
int32 crimesSamples[60];
|
cPoliceRadioQueue m_sPoliceRadioQueue;
|
||||||
uint8 policeChannelTimer;
|
|
||||||
uint8 policeChannelTimerSeconds;
|
|
||||||
uint8 policeChannelCounterSeconds;
|
|
||||||
uint8 gap30;
|
|
||||||
cAMCrime crimes[10];
|
|
||||||
int32 m_nFrontEndEntity;
|
int32 m_nFrontEndEntity;
|
||||||
int32 m_nCollisionEntity;
|
int32 m_nCollisionEntity;
|
||||||
cAudioCollisionManager m_sCollisionManager;
|
cAudioCollisionManager m_sCollisionManager;
|
||||||
@ -546,7 +453,7 @@ public:
|
|||||||
float GetDistanceSquared(CVector *v) const; /// ok
|
float GetDistanceSquared(CVector *v) const; /// ok
|
||||||
int32 GetJumboTaxiFreq() const; /// ok
|
int32 GetJumboTaxiFreq() const; /// ok
|
||||||
bool GetMissionAudioLoadingStatus() const; /// ok
|
bool GetMissionAudioLoadingStatus() const; /// ok
|
||||||
char GetMissionScriptPoliceAudioPlayingStatus() const; /// ok
|
int8 GetMissionScriptPoliceAudioPlayingStatus() const; /// ok
|
||||||
uint8 GetNum3DProvidersAvailable() const;
|
uint8 GetNum3DProvidersAvailable() const;
|
||||||
int32 GetPedCommentSfx(CPed *ped, int32 sound);
|
int32 GetPedCommentSfx(CPed *ped, int32 sound);
|
||||||
void GetPhrase(uint32 *phrase, uint32 *prevPhrase, uint32 sample, uint32 maxOffset) const;
|
void GetPhrase(uint32 *phrase, uint32 *prevPhrase, uint32 sample, uint32 maxOffset) const;
|
||||||
@ -658,7 +565,7 @@ public:
|
|||||||
void ResetTimers(uint32 time); /// ok
|
void ResetTimers(uint32 time); /// ok
|
||||||
|
|
||||||
void Service(); /// ok
|
void Service(); /// ok
|
||||||
void ServiceCollisions(); // todo
|
void ServiceCollisions(); /// ok
|
||||||
void ServicePoliceRadio(); /// ok
|
void ServicePoliceRadio(); /// ok
|
||||||
void ServicePoliceRadioChannel(int32 wantedLevel); /// ok
|
void ServicePoliceRadioChannel(int32 wantedLevel); /// ok
|
||||||
void ServiceSoundEffects(); /// ok
|
void ServiceSoundEffects(); /// ok
|
||||||
@ -696,8 +603,13 @@ public:
|
|||||||
|
|
||||||
// only used in pc
|
// only used in pc
|
||||||
void AdjustSamplesVolume(); /// ok
|
void AdjustSamplesVolume(); /// ok
|
||||||
int32 ComputeEmittingVolume(uint8 emittingVolume, float intensity,
|
uint8 ComputeEmittingVolume(uint8 emittingVolume, float intensity,
|
||||||
float dist); /// ok
|
float dist); /// ok
|
||||||
|
public:
|
||||||
|
static const int channels = ARRAY_SIZE(cAudioManager::m_asActiveSamples);
|
||||||
|
static const int policeChannel = channels + 1;
|
||||||
|
static const int allChannels = channels + 2;
|
||||||
|
static const int maxVolume = 127;
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(sizeof(cAudioManager) == 19220, "cAudioManager: error");
|
static_assert(sizeof(cAudioManager) == 19220, "cAudioManager: error");
|
||||||
|
@ -1,7 +1,48 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "patcher.h"
|
||||||
#include "AudioScriptObject.h"
|
#include "AudioScriptObject.h"
|
||||||
|
#include "Pools.h"
|
||||||
|
|
||||||
void PlayOneShotScriptObject(uint8 id, CVector const &pos)
|
void
|
||||||
|
cAudioScriptObject::Reset()
|
||||||
{
|
{
|
||||||
((void (__cdecl *)(uint8, CVector const &))0x57C5F0)(id, pos);
|
AudioId = 125;
|
||||||
}
|
Posn = CVector(0.0f, 0.0f, 0.0f);
|
||||||
|
AudioEntity = AEHANDLE_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
cAudioScriptObject::operator new(size_t sz)
|
||||||
|
{
|
||||||
|
return CPools::GetAudioScriptObjectPool()->New();
|
||||||
|
}
|
||||||
|
void *
|
||||||
|
cAudioScriptObject::operator new(size_t sz, int handle)
|
||||||
|
{
|
||||||
|
return CPools::GetAudioScriptObjectPool()->New(handle);
|
||||||
|
}
|
||||||
|
void
|
||||||
|
cAudioScriptObject::operator delete(void *p, size_t sz)
|
||||||
|
{
|
||||||
|
CPools::GetAudioScriptObjectPool()->Delete((cAudioScriptObject *)p);
|
||||||
|
}
|
||||||
|
void
|
||||||
|
cAudioScriptObject::operator delete(void *p, int handle)
|
||||||
|
{
|
||||||
|
CPools::GetAudioScriptObjectPool()->Delete((cAudioScriptObject *)p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PlayOneShotScriptObject(uint8 id, CVector const &pos)
|
||||||
|
{
|
||||||
|
cAudioScriptObject *audioScriptObject = new cAudioScriptObject();
|
||||||
|
audioScriptObject->Posn = pos;
|
||||||
|
audioScriptObject->AudioId = id;
|
||||||
|
audioScriptObject->AudioEntity = AEHANDLE_NONE;
|
||||||
|
DMAudio.CreateOneShotScriptObject(audioScriptObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
STARTPATCHES
|
||||||
|
InjectHook(0x57C430, &cAudioScriptObject::Reset, PATCH_JUMP);
|
||||||
|
InjectHook(0x57C5F0, &PlayOneShotScriptObject, PATCH_JUMP);
|
||||||
|
ENDPATCHES
|
@ -128,4 +128,21 @@ enum
|
|||||||
_SCRSOUND_BULLET_SHELL_HIT_GROUND_2 = 123,
|
_SCRSOUND_BULLET_SHELL_HIT_GROUND_2 = 123,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class cAudioScriptObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int16 AudioId;
|
||||||
|
CVector Posn;
|
||||||
|
int32 AudioEntity;
|
||||||
|
|
||||||
|
void Reset(); /// ok
|
||||||
|
|
||||||
|
static void* operator new(size_t);
|
||||||
|
static void* operator new(size_t, int);
|
||||||
|
static void operator delete(void*, size_t);
|
||||||
|
static void operator delete(void*, int);
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(cAudioScriptObject) == 20, "cAudioScriptObject: error");
|
||||||
|
|
||||||
extern void PlayOneShotScriptObject(uint8 id, CVector const &pos);
|
extern void PlayOneShotScriptObject(uint8 id, CVector const &pos);
|
@ -3,6 +3,7 @@
|
|||||||
#include "DMAudio.h"
|
#include "DMAudio.h"
|
||||||
#include "MusicManager.h"
|
#include "MusicManager.h"
|
||||||
#include "AudioManager.h"
|
#include "AudioManager.h"
|
||||||
|
#include "AudioScriptObject.h"
|
||||||
#include "sampman.h"
|
#include "sampman.h"
|
||||||
|
|
||||||
cDMAudio &DMAudio = *(cDMAudio*)0x95CDBE;
|
cDMAudio &DMAudio = *(cDMAudio*)0x95CDBE;
|
||||||
|
786
src/audio/PoliceRadio.cpp
Normal file
786
src/audio/PoliceRadio.cpp
Normal file
@ -0,0 +1,786 @@
|
|||||||
|
#include "common.h"
|
||||||
|
#include "patcher.h"
|
||||||
|
#include "DMAudio.h"
|
||||||
|
#include "AudioManager.h"
|
||||||
|
#include "AudioSamples.h"
|
||||||
|
#include "MusicManager.h"
|
||||||
|
#include "PoliceRadio.h"
|
||||||
|
#include "PlayerPed.h"
|
||||||
|
#include "sampman.h"
|
||||||
|
#include "Zones.h"
|
||||||
|
#include "Vehicle.h"
|
||||||
|
#include "World.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct tPoliceRadioZone {
|
||||||
|
char m_aName[8];
|
||||||
|
uint32 m_nSampleIndex;
|
||||||
|
int32 field_12;
|
||||||
|
};
|
||||||
|
|
||||||
|
tPoliceRadioZone (&ZoneSfx)[NUMAUDIOZONES] = *(tPoliceRadioZone(*)[NUMAUDIOZONES])*(uintptr*)0x880240;
|
||||||
|
char *SubZo2Label = (char*)0x6E9918;
|
||||||
|
char *SubZo3Label = (char*)0x6E9870;
|
||||||
|
|
||||||
|
int32 &g_nMissionAudioSfx = *(int32*)0x60ED84;
|
||||||
|
int8 &g_nMissionAudioPlayingStatus = *(int8*)0x60ED88;
|
||||||
|
uint8 &gSpecialSuspectLastSeenReport = *(uint8*)0x95CD4D;
|
||||||
|
uint32 (&gMinTimeToNextReport)[NUM_CRIME_TYPES] = *(uint32(*)[NUM_CRIME_TYPES])*(uintptr*)0x8E2828;
|
||||||
|
|
||||||
|
void
|
||||||
|
cAudioManager::InitialisePoliceRadioZones()
|
||||||
|
{
|
||||||
|
for (int32 i = 0; i < NUMAUDIOZONES; i++)
|
||||||
|
memset(ZoneSfx[i].m_aName, 0, 8);
|
||||||
|
|
||||||
|
#define SETZONESFX(i, name, sample) \
|
||||||
|
strcpy(ZoneSfx[i].m_aName, name); \
|
||||||
|
ZoneSfx[i].m_nSampleIndex = sample;
|
||||||
|
|
||||||
|
SETZONESFX(0, "HOSPI_2", SFX_POLICE_RADIO_ROCKFORD);
|
||||||
|
SETZONESFX(1, "CONSTRU", SFX_POLICE_RADIO_FORT_STAUNTON);
|
||||||
|
SETZONESFX(2, "STADIUM", SFX_POLICE_RADIO_ASPATRIA);
|
||||||
|
SETZONESFX(3, "YAKUSA", SFX_POLICE_RADIO_TORRINGTON);
|
||||||
|
SETZONESFX(4, "SHOPING", SFX_POLICE_RADIO_BEDFORD_POINT);
|
||||||
|
SETZONESFX(5, "COM_EAS", SFX_POLICE_RADIO_NEWPORT);
|
||||||
|
SETZONESFX(6, "PARK", SFX_POLICE_RADIO_BELLEVILLE_PARK);
|
||||||
|
SETZONESFX(7, "UNIVERS", SFX_POLICE_RADIO_LIBERTY_CAMPUS);
|
||||||
|
SETZONESFX(8, "BIG_DAM", SFX_POLICE_RADIO_COCHRANE_DAM);
|
||||||
|
SETZONESFX(9, "SUB_IND", SFX_POLICE_RADIO_PIKE_CREEK);
|
||||||
|
SETZONESFX(10, "SWANKS", SFX_POLICE_RADIO_CEDAR_GROVE);
|
||||||
|
SETZONESFX(11, "PROJECT", SFX_POLICE_RADIO_WICHITA_GARDENS);
|
||||||
|
SETZONESFX(12, "AIRPORT", SFX_POLICE_RADIO_FRANCIS_INTERNATIONAL_AIRPORT);
|
||||||
|
SETZONESFX(13, "PORT_W", SFX_POLICE_RADIO_CALLAHAN_POINT);
|
||||||
|
SETZONESFX(14, "PORT_S", SFX_POLICE_RADIO_ATLANTIC_QUAYS);
|
||||||
|
SETZONESFX(15, "PORT_E", SFX_POLICE_RADIO_PORTLAND_HARBOUR);
|
||||||
|
SETZONESFX(16, "PORT_I", SFX_POLICE_RADIO_TRENTON);
|
||||||
|
SETZONESFX(17, "CHINA", SFX_POLICE_RADIO_CHINATOWN);
|
||||||
|
SETZONESFX(18, "REDLIGH", SFX_POLICE_RADIO_RED_LIGHT_DISTRICT);
|
||||||
|
SETZONESFX(19, "TOWERS", SFX_POLICE_RADIO_HEPBURN_HEIGHTS);
|
||||||
|
SETZONESFX(20, "LITTLEI", SFX_POLICE_RADIO_SAINT_MARKS);
|
||||||
|
SETZONESFX(21, "HARWOOD", SFX_POLICE_RADIO_HARWOOD);
|
||||||
|
SETZONESFX(22, "EASTBAY", SFX_POLICE_RADIO_PORTLAND_BEACH);
|
||||||
|
SETZONESFX(23, "S_VIEW", SFX_POLICE_RADIO_PORTLAND_STRAIGHTS);
|
||||||
|
SETZONESFX(24, "CITYZON", SFX_POLICE_RADIO_LIBERTY_CITY);
|
||||||
|
SETZONESFX(25, "IND_ZON", SFX_POLICE_RADIO_PORTLAND);
|
||||||
|
SETZONESFX(26, "COM_ZON", SFX_POLICE_RADIO_STAUNTON_ISLAND);
|
||||||
|
SETZONESFX(27, "SUB_ZON", SFX_POLICE_RADIO_SHORESIDE_VALE);
|
||||||
|
SETZONESFX(28, "SUB_ZO2", SFX_POLICE_RADIO_SHORESIDE_VALE);
|
||||||
|
SETZONESFX(29, "SUB_ZO3", SFX_POLICE_RADIO_SHORESIDE_VALE);
|
||||||
|
SETZONESFX(30, "A", SFX_POLICE_RADIO_ROCKFORD);
|
||||||
|
SETZONESFX(31, "A", SFX_POLICE_RADIO_ROCKFORD);
|
||||||
|
SETZONESFX(32, "A", SFX_POLICE_RADIO_ROCKFORD);
|
||||||
|
SETZONESFX(33, "A", SFX_POLICE_RADIO_ROCKFORD);
|
||||||
|
SETZONESFX(34, "A", SFX_POLICE_RADIO_ROCKFORD);
|
||||||
|
|
||||||
|
#undef SETZONESFX
|
||||||
|
|
||||||
|
strcpy(SubZo2Label, "SUB_ZO2");
|
||||||
|
strcpy(SubZo3Label, "SUB_ZO3");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cAudioManager::InitialisePoliceRadio()
|
||||||
|
{
|
||||||
|
m_sPoliceRadioQueue.policeChannelTimer = 0;
|
||||||
|
m_sPoliceRadioQueue.policeChannelTimerSeconds = 0;
|
||||||
|
m_sPoliceRadioQueue.policeChannelCounterSeconds = 0;
|
||||||
|
for (int32 i = 0; i < ARRAY_SIZE(m_sPoliceRadioQueue.crimes); i++)
|
||||||
|
m_sPoliceRadioQueue.crimes[i].type = 0;
|
||||||
|
|
||||||
|
SampleManager.SetChannelReverbFlag(policeChannel, 0);
|
||||||
|
gSpecialSuspectLastSeenReport = false;
|
||||||
|
for (int32 i = 0; i < ARRAY_SIZE(gMinTimeToNextReport); i++)
|
||||||
|
gMinTimeToNextReport[i] = m_nTimeOfRecentCrime;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cAudioManager::ResetPoliceRadio()
|
||||||
|
{
|
||||||
|
if (!m_bIsInitialised) return;
|
||||||
|
if (SampleManager.GetChannelUsedFlag(policeChannel)) SampleManager.StopChannel(policeChannel);
|
||||||
|
InitialisePoliceRadio();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cAudioManager::SetMissionScriptPoliceAudio(int32 sfx) const
|
||||||
|
{
|
||||||
|
if (!m_bIsInitialised) return;
|
||||||
|
if (g_nMissionAudioPlayingStatus != 1) {
|
||||||
|
g_nMissionAudioPlayingStatus = 0;
|
||||||
|
g_nMissionAudioSfx = sfx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int8
|
||||||
|
cAudioManager::GetMissionScriptPoliceAudioPlayingStatus() const
|
||||||
|
{
|
||||||
|
return g_nMissionAudioPlayingStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cAudioManager::DoPoliceRadioCrackle()
|
||||||
|
{
|
||||||
|
m_sQueueSample.m_nEntityIndex = m_nPoliceChannelEntity;
|
||||||
|
m_sQueueSample.m_counter = 0;
|
||||||
|
m_sQueueSample.m_nSampleIndex = SFX_POLICE_RADIO_CRACKLE;
|
||||||
|
m_sQueueSample.m_bBankIndex = 0;
|
||||||
|
m_sQueueSample.m_bIsDistant = 1;
|
||||||
|
m_sQueueSample.field_16 = 10;
|
||||||
|
m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_POLICE_RADIO_CRACKLE);
|
||||||
|
m_sQueueSample.m_bVolume = m_anRandomTable[2] % 20 + 15;
|
||||||
|
m_sQueueSample.m_nLoopCount = 0;
|
||||||
|
m_sQueueSample.m_bEmittingVolume = m_sQueueSample.m_bVolume;
|
||||||
|
m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(SFX_POLICE_RADIO_CRACKLE);
|
||||||
|
m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(SFX_POLICE_RADIO_CRACKLE);
|
||||||
|
m_sQueueSample.field_56 = 0;
|
||||||
|
m_sQueueSample.m_bReverbFlag = 0;
|
||||||
|
m_sQueueSample.m_bOffset = 63;
|
||||||
|
m_sQueueSample.field_76 = 3;
|
||||||
|
m_sQueueSample.m_bRequireReflection = 0;
|
||||||
|
AddSampleToRequestedQueue();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cAudioManager::ServicePoliceRadio()
|
||||||
|
{
|
||||||
|
int32 wantedLevel = 0; // bug?;
|
||||||
|
static uint32 nLastSeen = 300;
|
||||||
|
|
||||||
|
if (!m_bIsInitialised) return;
|
||||||
|
|
||||||
|
if (!m_bUserPause) {
|
||||||
|
bool crimeReport = SetupCrimeReport();
|
||||||
|
wantedLevel = FindPlayerPed()->m_pWanted->m_nWantedLevel;
|
||||||
|
if (!crimeReport) {
|
||||||
|
if (wantedLevel) {
|
||||||
|
if (nLastSeen) {
|
||||||
|
--nLastSeen;
|
||||||
|
} else {
|
||||||
|
nLastSeen = m_anRandomTable[1] % 1000 + 2000;
|
||||||
|
SetupSuspectLastSeenReport();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ServicePoliceRadioChannel(wantedLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cAudioManager::ServicePoliceRadioChannel(int32 wantedLevel)
|
||||||
|
{
|
||||||
|
bool processed = false;
|
||||||
|
uint32 sample;
|
||||||
|
int32 freq;
|
||||||
|
|
||||||
|
static int cWait = 0;
|
||||||
|
static bool bChannelOpen = false;
|
||||||
|
static uint8 bMissionAudioPhysicalPlayingStatus = 0;
|
||||||
|
static int32 PoliceChannelFreq = 5500;
|
||||||
|
|
||||||
|
if (!m_bIsInitialised) return;
|
||||||
|
|
||||||
|
if (m_bUserPause) {
|
||||||
|
if (SampleManager.GetChannelUsedFlag(policeChannel)) SampleManager.StopChannel(policeChannel);
|
||||||
|
if (g_nMissionAudioSfx != TOTAL_AUDIO_SAMPLES && bMissionAudioPhysicalPlayingStatus == 1 &&
|
||||||
|
SampleManager.IsStreamPlaying(1)) {
|
||||||
|
SampleManager.PauseStream(1, 1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (m_bPreviousUserPause && g_nMissionAudioSfx != TOTAL_AUDIO_SAMPLES &&
|
||||||
|
bMissionAudioPhysicalPlayingStatus == 1) {
|
||||||
|
SampleManager.PauseStream(0, 1);
|
||||||
|
}
|
||||||
|
if (m_sPoliceRadioQueue.policeChannelTimer == 0) bChannelOpen = false;
|
||||||
|
if (cWait) {
|
||||||
|
--cWait;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (g_nMissionAudioSfx != TOTAL_AUDIO_SAMPLES && !bChannelOpen) {
|
||||||
|
if (g_nMissionAudioPlayingStatus) {
|
||||||
|
if (g_nMissionAudioPlayingStatus == 1 && !bMissionAudioPhysicalPlayingStatus &&
|
||||||
|
SampleManager.IsStreamPlaying(1)) {
|
||||||
|
bMissionAudioPhysicalPlayingStatus = 1;
|
||||||
|
}
|
||||||
|
if (bMissionAudioPhysicalPlayingStatus == 1) {
|
||||||
|
if (SampleManager.IsStreamPlaying(1)) {
|
||||||
|
DoPoliceRadioCrackle();
|
||||||
|
} else {
|
||||||
|
bMissionAudioPhysicalPlayingStatus = 2;
|
||||||
|
g_nMissionAudioPlayingStatus = 2;
|
||||||
|
g_nMissionAudioSfx = TOTAL_AUDIO_SAMPLES;
|
||||||
|
cWait = 30;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if (!SampleManager.GetChannelUsedFlag(policeChannel)) {
|
||||||
|
SampleManager.PreloadStreamedFile(g_nMissionAudioSfx, 1);
|
||||||
|
SampleManager.SetStreamedVolumeAndPan(maxVolume, 63, 1, 1);
|
||||||
|
SampleManager.StartPreloadedStreamedFile(1);
|
||||||
|
g_nMissionAudioPlayingStatus = 1;
|
||||||
|
bMissionAudioPhysicalPlayingStatus = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bChannelOpen) DoPoliceRadioCrackle();
|
||||||
|
if ((g_nMissionAudioSfx == TOTAL_AUDIO_SAMPLES || g_nMissionAudioPlayingStatus != 1) &&
|
||||||
|
!SampleManager.GetChannelUsedFlag(policeChannel) && m_sPoliceRadioQueue.policeChannelTimer) {
|
||||||
|
if (m_sPoliceRadioQueue.policeChannelTimer) {
|
||||||
|
sample = m_sPoliceRadioQueue.crimesSamples[m_sPoliceRadioQueue.policeChannelCounterSeconds];
|
||||||
|
m_sPoliceRadioQueue.policeChannelTimer--;
|
||||||
|
m_sPoliceRadioQueue.policeChannelCounterSeconds = (m_sPoliceRadioQueue.policeChannelCounterSeconds + 1) % 60;
|
||||||
|
} else {
|
||||||
|
sample = TOTAL_AUDIO_SAMPLES;
|
||||||
|
}
|
||||||
|
if (!wantedLevel) {
|
||||||
|
if (gSpecialSuspectLastSeenReport) {
|
||||||
|
gSpecialSuspectLastSeenReport = 0;
|
||||||
|
} else if (((sample >= SFX_POLICE_RADIO_MESSAGE_NOISE_1) && (sample <= SFX_POLICE_RADIO_MESSAGE_NOISE_3)) || sample == TOTAL_AUDIO_SAMPLES) {
|
||||||
|
bChannelOpen = false;
|
||||||
|
processed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sample == TOTAL_AUDIO_SAMPLES) {
|
||||||
|
if (!processed) cWait = 30;
|
||||||
|
} else {
|
||||||
|
SampleManager.InitialiseChannel(policeChannel, sample, 0);
|
||||||
|
switch (sample) {
|
||||||
|
case SFX_POLICE_RADIO_MESSAGE_NOISE_1:
|
||||||
|
case SFX_POLICE_RADIO_MESSAGE_NOISE_2:
|
||||||
|
case SFX_POLICE_RADIO_MESSAGE_NOISE_3:
|
||||||
|
freq = m_anRandomTable[4] % 2000 + 10025;
|
||||||
|
bChannelOpen = bChannelOpen == false;
|
||||||
|
break;
|
||||||
|
default: freq = SampleManager.GetSampleBaseFrequency(sample); break;
|
||||||
|
}
|
||||||
|
PoliceChannelFreq = freq;
|
||||||
|
SampleManager.SetChannelFrequency(policeChannel, freq);
|
||||||
|
SampleManager.SetChannelVolume(policeChannel, 100);
|
||||||
|
SampleManager.SetChannelPan(policeChannel, 63);
|
||||||
|
SampleManager.SetChannelLoopCount(policeChannel, 1);
|
||||||
|
SampleManager.SetChannelLoopPoints(policeChannel, 0, -1);
|
||||||
|
SampleManager.StartChannel(policeChannel);
|
||||||
|
}
|
||||||
|
if (processed) ResetPoliceRadio();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
cAudioManager::SetupCrimeReport()
|
||||||
|
{
|
||||||
|
int16 audioZoneId;
|
||||||
|
CZone *zone;
|
||||||
|
float rangeX;
|
||||||
|
float rangeY;
|
||||||
|
float halfX;
|
||||||
|
float halfY;
|
||||||
|
float quarterX;
|
||||||
|
float quarterY;
|
||||||
|
int i;
|
||||||
|
int32 sampleIndex;
|
||||||
|
bool processed = false;
|
||||||
|
|
||||||
|
if (MusicManager.m_nMusicMode == MUSICMODE_CUTSCENE) return false;
|
||||||
|
|
||||||
|
if (60 - m_sPoliceRadioQueue.policeChannelTimer <= 9) {
|
||||||
|
AgeCrimes();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(m_sPoliceRadioQueue.crimes); i++) {
|
||||||
|
if (m_sPoliceRadioQueue.crimes[i].type != CRIME_NONE)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == ARRAY_SIZE(m_sPoliceRadioQueue.crimes)) return false;
|
||||||
|
audioZoneId = CTheZones::FindAudioZone(&m_sPoliceRadioQueue.crimes[i].position);
|
||||||
|
if (audioZoneId >= 0 && audioZoneId < NUMAUDIOZONES) {
|
||||||
|
zone = &CTheZones::ZoneArray[CTheZones::AudioZoneArray[audioZoneId]];
|
||||||
|
for (int j = 0; j < NUMAUDIOZONES; j++) {
|
||||||
|
if (strcmp(zone->name, ZoneSfx[j].m_aName) == 0) {
|
||||||
|
sampleIndex = ZoneSfx[j].m_nSampleIndex;
|
||||||
|
m_sPoliceRadioQueue.Add(m_anRandomTable[4] % 3 + SFX_POLICE_RADIO_MESSAGE_NOISE_1);
|
||||||
|
m_sPoliceRadioQueue.Add(m_anRandomTable[0] % 3 + SFX_WEVE_GOT);
|
||||||
|
m_sPoliceRadioQueue.Add(m_anRandomTable[1] % 2 + SFX_A_10_1);
|
||||||
|
switch (m_sPoliceRadioQueue.crimes[i].type) {
|
||||||
|
case CRIME_PED_BURNED: m_sPoliceRadioQueue.crimes[i].type = CRIME_HIT_PED; break;
|
||||||
|
case CRIME_COP_BURNED: m_sPoliceRadioQueue.crimes[i].type = CRIME_HIT_COP; break;
|
||||||
|
case CRIME_VEHICLE_BURNED: m_sPoliceRadioQueue.crimes[i].type = CRIME_STEAL_CAR; break;
|
||||||
|
case CRIME_DESTROYED_CESSNA: m_sPoliceRadioQueue.crimes[i].type = CRIME_SHOOT_HELI; break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
m_sPoliceRadioQueue.Add(m_sPoliceRadioQueue.crimes[i].type + SFX_CRIME_1 - 1);
|
||||||
|
m_sPoliceRadioQueue.Add(SFX_IN);
|
||||||
|
if (sampleIndex == SFX_POLICE_RADIO_SHORESIDE_VALE &&
|
||||||
|
(strcmp(zone->name, SubZo2Label) == 0 || strcmp(zone->name, SubZo3Label) == 0)) {
|
||||||
|
m_sPoliceRadioQueue.Add(SFX_NORTH);
|
||||||
|
m_sPoliceRadioQueue.Add(SFX_EAST);
|
||||||
|
} else {
|
||||||
|
rangeX = zone->maxx - zone->minx;
|
||||||
|
rangeY = zone->maxy - zone->miny;
|
||||||
|
halfX = 0.5f * rangeX + zone->minx;
|
||||||
|
halfY = 0.5f * rangeY + zone->miny;
|
||||||
|
quarterX = 0.25f * rangeX;
|
||||||
|
quarterY = 0.25f * rangeY;
|
||||||
|
|
||||||
|
if (m_sPoliceRadioQueue.crimes[i].position.y > halfY + quarterY) {
|
||||||
|
m_sPoliceRadioQueue.Add(SFX_NORTH);
|
||||||
|
processed = true;
|
||||||
|
} else if (m_sPoliceRadioQueue.crimes[i].position.y < halfY - quarterY) {
|
||||||
|
m_sPoliceRadioQueue.Add(SFX_SOUTH);
|
||||||
|
processed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_sPoliceRadioQueue.crimes[i].position.x > halfX + quarterX)
|
||||||
|
m_sPoliceRadioQueue.Add(SFX_EAST);
|
||||||
|
else if (m_sPoliceRadioQueue.crimes[i].position.x < halfX - quarterX)
|
||||||
|
m_sPoliceRadioQueue.Add(SFX_WEST);
|
||||||
|
else if (!processed)
|
||||||
|
m_sPoliceRadioQueue.Add(SFX_CENTRAL);
|
||||||
|
|
||||||
|
m_sPoliceRadioQueue.Add(sampleIndex);
|
||||||
|
m_sPoliceRadioQueue.Add(m_anRandomTable[2] % 3 + SFX_POLICE_RADIO_MESSAGE_NOISE_1);
|
||||||
|
m_sPoliceRadioQueue.Add(TOTAL_AUDIO_SAMPLES);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_sPoliceRadioQueue.crimes[i].type = CRIME_NONE;
|
||||||
|
AgeCrimes();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cAudioManager::SetupSuspectLastSeenReport()
|
||||||
|
{
|
||||||
|
CVehicle *veh;
|
||||||
|
uint8 color1;
|
||||||
|
int32 main_color;
|
||||||
|
int32 sample;
|
||||||
|
|
||||||
|
int32 color_pre_modifier;
|
||||||
|
int32 color_post_modifier;
|
||||||
|
|
||||||
|
const int32 gCarColourTable[][3] = {
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_BLACK, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_WHITE, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_RED, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_PURPLE, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_YELLOW, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_BRIGHT, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_LIGHT, SFX_POLICE_RADIO_BLUE, SFX_POLICE_RADIO_GREY},
|
||||||
|
#ifdef FIX_BUGS
|
||||||
|
{SFX_POLICE_RADIO_LIGHT, SFX_POLICE_RADIO_RED, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_RED, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_RED, TOTAL_AUDIO_SAMPLES},
|
||||||
|
#else
|
||||||
|
{SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
|
||||||
|
#endif
|
||||||
|
{SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_RED, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_RED, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_RED, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_RED, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_RED, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_RED, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_RED, TOTAL_AUDIO_SAMPLES},
|
||||||
|
#ifdef FIX_BUGS
|
||||||
|
{SFX_POLICE_RADIO_LIGHT, SFX_POLICE_RADIO_RED, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_ORANGE, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_ORANGE, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_ORANGE, TOTAL_AUDIO_SAMPLES},
|
||||||
|
#else
|
||||||
|
{SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
|
||||||
|
#endif
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_ORANGE, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_ORANGE, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_ORANGE, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_ORANGE, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_ORANGE, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_ORANGE, TOTAL_AUDIO_SAMPLES},
|
||||||
|
#ifdef FIX_BUGS
|
||||||
|
{SFX_POLICE_RADIO_LIGHT, SFX_POLICE_RADIO_ORANGE, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_YELLOW, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_YELLOW, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_YELLOW, TOTAL_AUDIO_SAMPLES},
|
||||||
|
#else
|
||||||
|
{SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
|
||||||
|
#endif
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_YELLOW, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_YELLOW, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_YELLOW, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_YELLOW, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_YELLOW, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_YELLOW, TOTAL_AUDIO_SAMPLES},
|
||||||
|
#ifdef FIX_BUGS
|
||||||
|
{SFX_POLICE_RADIO_LIGHT, SFX_POLICE_RADIO_YELLOW, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_GREEN, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_GREEN, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_GREEN, TOTAL_AUDIO_SAMPLES},
|
||||||
|
#else
|
||||||
|
{SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
|
||||||
|
#endif
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_GREEN, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_GREEN, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_GREEN, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_GREEN, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_GREEN, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_GREEN, TOTAL_AUDIO_SAMPLES},
|
||||||
|
#ifdef FIX_BUGS
|
||||||
|
{SFX_POLICE_RADIO_LIGHT, SFX_POLICE_RADIO_GREEN, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
|
||||||
|
#else
|
||||||
|
{SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
|
||||||
|
#endif
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
|
||||||
|
#ifdef FIX_BUGS
|
||||||
|
{SFX_POLICE_RADIO_LIGHT, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_PURPLE, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_PURPLE, SFX_POLICE_RADIO_BLUE},
|
||||||
|
{SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_PURPLE, TOTAL_AUDIO_SAMPLES},
|
||||||
|
#else
|
||||||
|
{SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
|
||||||
|
#endif
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_PURPLE, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_PURPLE, TOTAL_AUDIO_SAMPLES},
|
||||||
|
#ifdef FIX_BUGS
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_PURPLE, SFX_POLICE_RADIO_GREY},
|
||||||
|
#else
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_PURPLE, TOTAL_AUDIO_SAMPLES},
|
||||||
|
#endif
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_PURPLE, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_PURPLE, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_PURPLE, TOTAL_AUDIO_SAMPLES},
|
||||||
|
#ifdef FIX_BUGS
|
||||||
|
{SFX_POLICE_RADIO_LIGHT, SFX_POLICE_RADIO_PURPLE, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_SILVER, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_SILVER, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_SILVER, TOTAL_AUDIO_SAMPLES},
|
||||||
|
#else
|
||||||
|
{SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
|
||||||
|
#endif
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_SILVER, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_SILVER, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_SILVER, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_SILVER, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_SILVER, TOTAL_AUDIO_SAMPLES},
|
||||||
|
#ifdef FIX_BUGS
|
||||||
|
{SFX_POLICE_RADIO_LIGHT, SFX_POLICE_RADIO_SILVER, TOTAL_AUDIO_SAMPLES},
|
||||||
|
#else
|
||||||
|
{TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_SILVER, TOTAL_AUDIO_SAMPLES},
|
||||||
|
#endif
|
||||||
|
{SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
|
||||||
|
{SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (MusicManager.m_nMusicMode != MUSICMODE_CUTSCENE) {
|
||||||
|
veh = FindPlayerVehicle();
|
||||||
|
if (veh != nil) {
|
||||||
|
if (60 - m_sPoliceRadioQueue.policeChannelTimer > 9) {
|
||||||
|
color1 = veh->m_currentColour1;
|
||||||
|
if (color1 >= ARRAY_SIZE(gCarColourTable)) {
|
||||||
|
debug("\n *** UNKNOWN CAR COLOUR %d *** ", color1);
|
||||||
|
} else {
|
||||||
|
main_color = gCarColourTable[color1][1];
|
||||||
|
color_pre_modifier = gCarColourTable[color1][0];
|
||||||
|
color_post_modifier = gCarColourTable[color1][2];
|
||||||
|
switch (veh->m_modelIndex) {
|
||||||
|
#ifdef FIX_BUGS
|
||||||
|
case MI_COLUMB:
|
||||||
|
main_color = SFX_POLICE_RADIO_BLUE;
|
||||||
|
color_pre_modifier = color_post_modifier = TOTAL_AUDIO_SAMPLES;
|
||||||
|
#endif
|
||||||
|
case MI_LANDSTAL:
|
||||||
|
case MI_BLISTA: sample = SFX_POLICE_RADIO_CRUISER; break;
|
||||||
|
#ifdef FIX_BUGS
|
||||||
|
case MI_YARDIE:
|
||||||
|
color_pre_modifier = TOTAL_AUDIO_SAMPLES;
|
||||||
|
main_color = SFX_POLICE_RADIO_RED;
|
||||||
|
color_post_modifier = SFX_POLICE_RADIO_YELLOW;
|
||||||
|
sample = SFX_POLICE_RADIO_CONVERTIBLE; break;
|
||||||
|
case MI_DIABLOS:
|
||||||
|
main_color = SFX_POLICE_RADIO_BLACK;
|
||||||
|
#endif
|
||||||
|
case MI_IDAHO:
|
||||||
|
case MI_STALLION: sample = SFX_POLICE_RADIO_CONVERTIBLE; break;
|
||||||
|
#ifdef FIX_BUGS
|
||||||
|
case MI_YAKUZA:
|
||||||
|
color_pre_modifier = TOTAL_AUDIO_SAMPLES;
|
||||||
|
main_color = SFX_POLICE_RADIO_SILVER;
|
||||||
|
color_post_modifier = SFX_POLICE_RADIO_RED;
|
||||||
|
#endif
|
||||||
|
case MI_STINGER:
|
||||||
|
case MI_INFERNUS:
|
||||||
|
case MI_CHEETAH:
|
||||||
|
case MI_BANSHEE: sample = SFX_POLICE_RADIO_SPORTS_CAR; break;
|
||||||
|
#ifdef FIX_BUGS
|
||||||
|
case MI_MAFIA:
|
||||||
|
color_pre_modifier = color_post_modifier = TOTAL_AUDIO_SAMPLES;
|
||||||
|
main_color = SFX_POLICE_RADIO_GREY;
|
||||||
|
case MI_KURUMA:
|
||||||
|
#endif
|
||||||
|
case MI_PEREN:
|
||||||
|
case MI_SENTINEL:
|
||||||
|
case MI_FBICAR: sample = SFX_POLICE_RADIO_SALOON; break;
|
||||||
|
case MI_PATRIOT:
|
||||||
|
case MI_BOBCAT: sample = SFX_POLICE_RADIO_PICKUP; break;
|
||||||
|
case MI_FIRETRUCK: sample = SFX_POLICE_RADIO_FIRE_TRUCK; break;
|
||||||
|
#ifdef FIX_BUGS
|
||||||
|
case MI_LINERUN:
|
||||||
|
case MI_FLATBED:
|
||||||
|
#endif
|
||||||
|
case MI_TRASH:
|
||||||
|
case MI_BARRACKS: sample = SFX_POLICE_RADIO_TRUCK; break;
|
||||||
|
case MI_STRETCH: sample = SFX_POLICE_RADIO_LIMO; break;
|
||||||
|
#ifdef FIX_BUGS
|
||||||
|
case MI_CORPSE:
|
||||||
|
#endif
|
||||||
|
case MI_MANANA:
|
||||||
|
case MI_ESPERANT: sample = SFX_POLICE_RADIO_2_DOOR; break;
|
||||||
|
#ifdef FIX_BUGS
|
||||||
|
case MI_HOODS:
|
||||||
|
color_pre_modifier = TOTAL_AUDIO_SAMPLES;
|
||||||
|
main_color = SFX_POLICE_RADIO_BLUE;
|
||||||
|
color_post_modifier = SFX_POLICE_RADIO_GREEN;
|
||||||
|
case MI_BELLYUP:
|
||||||
|
case MI_YANKEE:
|
||||||
|
case MI_TOYZ:
|
||||||
|
case MI_MRWONGS:
|
||||||
|
case MI_PANLANT:
|
||||||
|
#endif
|
||||||
|
case MI_PONY:
|
||||||
|
case MI_MULE:
|
||||||
|
case MI_MOONBEAM:
|
||||||
|
case MI_ENFORCER:
|
||||||
|
case MI_SECURICA:
|
||||||
|
case MI_RUMPO: sample = SFX_POLICE_RADIO_VAN; break;
|
||||||
|
case MI_AMBULAN: sample = SFX_POLICE_RADIO_AMBULANCE; break;
|
||||||
|
case MI_TAXI:
|
||||||
|
case MI_CABBIE:
|
||||||
|
case MI_BORGNINE: sample = SFX_POLICE_RADIO_TAXI; break;
|
||||||
|
case MI_MRWHOOP:
|
||||||
|
sample = SFX_POLICE_RADIO_ICE_CREAM_VAN;
|
||||||
|
break;
|
||||||
|
case MI_BFINJECT: sample = SFX_POLICE_RADIO_BUGGY; break;
|
||||||
|
case MI_POLICE: sample = SFX_POLICE_RADIO_POLICE_CAR; break;
|
||||||
|
#ifdef FIX_BUGS
|
||||||
|
case MI_SPEEDER:
|
||||||
|
case MI_REEFER:
|
||||||
|
case MI_GHOST:
|
||||||
|
#endif
|
||||||
|
case MI_PREDATOR: sample = SFX_POLICE_RADIO_BOAT; break;
|
||||||
|
case MI_BUS:
|
||||||
|
case MI_COACH: sample = SFX_POLICE_RADIO_BUS; break;
|
||||||
|
case MI_RHINO:
|
||||||
|
sample = SFX_POLICE_RADIO_TANK;
|
||||||
|
main_color = TOTAL_AUDIO_SAMPLES;
|
||||||
|
color_post_modifier = TOTAL_AUDIO_SAMPLES;
|
||||||
|
break;
|
||||||
|
case MI_TRAIN:
|
||||||
|
sample = SFX_POLICE_RADIO_SUBWAY_CAR;
|
||||||
|
main_color = TOTAL_AUDIO_SAMPLES;
|
||||||
|
color_post_modifier = TOTAL_AUDIO_SAMPLES;
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
debug("\n *** UNKNOWN CAR MODEL INDEX %d *** ", veh->m_modelIndex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_sPoliceRadioQueue.Add(m_anRandomTable[4] % 3 + SFX_POLICE_RADIO_MESSAGE_NOISE_1);
|
||||||
|
m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_SUSPECT);
|
||||||
|
if (m_anRandomTable[3] % 2)
|
||||||
|
m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_LAST_SEEN);
|
||||||
|
#ifdef FIX_BUGS
|
||||||
|
if (main_color == SFX_POLICE_RADIO_ORANGE && color_pre_modifier == TOTAL_AUDIO_SAMPLES)
|
||||||
|
#else
|
||||||
|
if (main_color == SFX_POLICE_RADIO_ORANGE)
|
||||||
|
#endif
|
||||||
|
m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_IN_AN);
|
||||||
|
else
|
||||||
|
m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_IN_A);
|
||||||
|
if (color_pre_modifier != TOTAL_AUDIO_SAMPLES)
|
||||||
|
m_sPoliceRadioQueue.Add(color_pre_modifier);
|
||||||
|
if (main_color != TOTAL_AUDIO_SAMPLES)
|
||||||
|
m_sPoliceRadioQueue.Add(main_color);
|
||||||
|
if (color_post_modifier != TOTAL_AUDIO_SAMPLES)
|
||||||
|
m_sPoliceRadioQueue.Add(color_post_modifier);
|
||||||
|
m_sPoliceRadioQueue.Add(sample);
|
||||||
|
m_sPoliceRadioQueue.Add(m_anRandomTable[0] % 3 + SFX_POLICE_RADIO_MESSAGE_NOISE_1);
|
||||||
|
m_sPoliceRadioQueue.Add(TOTAL_AUDIO_SAMPLES);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (60 - m_sPoliceRadioQueue.policeChannelTimer > 4) {
|
||||||
|
m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_MESSAGE_NOISE_1);
|
||||||
|
m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_SUSPECT);
|
||||||
|
m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_ON_FOOT);
|
||||||
|
m_sPoliceRadioQueue.Add(m_anRandomTable[0] % 3 + SFX_POLICE_RADIO_MESSAGE_NOISE_1);
|
||||||
|
m_sPoliceRadioQueue.Add(TOTAL_AUDIO_SAMPLES);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
cAudioManager::ReportCrime(int32 type, const CVector *pos)
|
||||||
|
{
|
||||||
|
int32 lastCrime = ARRAY_SIZE(m_sPoliceRadioQueue.crimes);
|
||||||
|
if (m_bIsInitialised && MusicManager.m_nMusicMode != MUSICMODE_CUTSCENE && FindPlayerPed()->m_pWanted->m_nWantedLevel > 0 &&
|
||||||
|
(type > CRIME_NONE || type < NUM_CRIME_TYPES) && m_nTimeOfRecentCrime >= gMinTimeToNextReport[type]) {
|
||||||
|
for (int32 i = 0; i < ARRAY_SIZE(m_sPoliceRadioQueue.crimes); i++) {
|
||||||
|
if (m_sPoliceRadioQueue.crimes[i].type) {
|
||||||
|
if (m_sPoliceRadioQueue.crimes[i].type == type) {
|
||||||
|
m_sPoliceRadioQueue.crimes[i].position = *pos;
|
||||||
|
m_sPoliceRadioQueue.crimes[i].timer = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
lastCrime = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastCrime < ARRAY_SIZE(m_sPoliceRadioQueue.crimes)) {
|
||||||
|
m_sPoliceRadioQueue.crimes[lastCrime].type = type;
|
||||||
|
m_sPoliceRadioQueue.crimes[lastCrime].position = *pos;
|
||||||
|
m_sPoliceRadioQueue.crimes[lastCrime].timer = 0;
|
||||||
|
gMinTimeToNextReport[type] = m_nTimeOfRecentCrime + 500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cAudioManager::PlaySuspectLastSeen(float x, float y, float z)
|
||||||
|
{
|
||||||
|
int16 audioZone;
|
||||||
|
CZone *zone;
|
||||||
|
float rangeX;
|
||||||
|
float rangeY;
|
||||||
|
float halfX;
|
||||||
|
float halfY;
|
||||||
|
float quarterX;
|
||||||
|
float quarterY;
|
||||||
|
int32 sample;
|
||||||
|
bool processed = false;
|
||||||
|
CVector vec = CVector(x, y, z);
|
||||||
|
|
||||||
|
if (!m_bIsInitialised) return;
|
||||||
|
|
||||||
|
if (MusicManager.m_nMusicMode != MUSICMODE_CUTSCENE && 60 - m_sPoliceRadioQueue.policeChannelTimer > 9) {
|
||||||
|
audioZone = CTheZones::FindAudioZone(&vec);
|
||||||
|
if (audioZone >= 0 && audioZone < NUMAUDIOZONES) {
|
||||||
|
zone = &CTheZones::ZoneArray[CTheZones::AudioZoneArray[audioZone]];
|
||||||
|
for (int i = 0; i < NUMAUDIOZONES; i++) {
|
||||||
|
if (strcmp(zone->name, ZoneSfx[i].m_aName) == 0) {
|
||||||
|
sample = ZoneSfx[i].m_nSampleIndex;
|
||||||
|
m_sPoliceRadioQueue.Add(m_anRandomTable[4] % 3 + SFX_POLICE_RADIO_MESSAGE_NOISE_1);
|
||||||
|
m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_SUSPECT);
|
||||||
|
m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_LAST_SEEN);
|
||||||
|
m_sPoliceRadioQueue.Add(SFX_IN);
|
||||||
|
if (sample == SFX_POLICE_RADIO_SHORESIDE_VALE &&
|
||||||
|
(strcmp(zone->name, SubZo2Label) == 0 ||
|
||||||
|
strcmp(zone->name, SubZo3Label) == 0)) {
|
||||||
|
m_sPoliceRadioQueue.Add(SFX_NORTH);
|
||||||
|
m_sPoliceRadioQueue.Add(SFX_EAST);
|
||||||
|
} else {
|
||||||
|
rangeX = zone->maxx - zone->minx;
|
||||||
|
rangeY = zone->maxy - zone->miny;
|
||||||
|
halfX = 0.5f * rangeX + zone->minx;
|
||||||
|
halfY = 0.5f * rangeY + zone->miny;
|
||||||
|
quarterX = 0.25f * rangeX;
|
||||||
|
quarterY = 0.25f * rangeY;
|
||||||
|
|
||||||
|
if (vec.y > halfY + quarterY) {
|
||||||
|
m_sPoliceRadioQueue.Add(SFX_NORTH);
|
||||||
|
processed = true;
|
||||||
|
} else if (vec.y < halfY - quarterY) {
|
||||||
|
m_sPoliceRadioQueue.Add(SFX_SOUTH);
|
||||||
|
processed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vec.x > halfX + quarterX)
|
||||||
|
m_sPoliceRadioQueue.Add(SFX_EAST);
|
||||||
|
else if (vec.x < halfX - quarterX)
|
||||||
|
m_sPoliceRadioQueue.Add(SFX_WEST);
|
||||||
|
else if (!processed)
|
||||||
|
m_sPoliceRadioQueue.Add(SFX_CENTRAL);
|
||||||
|
}
|
||||||
|
m_sPoliceRadioQueue.Add(sample);
|
||||||
|
m_sPoliceRadioQueue.Add(m_anRandomTable[2] % 3 + SFX_POLICE_RADIO_MESSAGE_NOISE_1);
|
||||||
|
m_sPoliceRadioQueue.Add(TOTAL_AUDIO_SAMPLES);
|
||||||
|
gSpecialSuspectLastSeenReport = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cAudioManager::AgeCrimes()
|
||||||
|
{
|
||||||
|
for (uint8 i = 0; i < ARRAY_SIZE(m_sPoliceRadioQueue.crimes); i++) {
|
||||||
|
if (m_sPoliceRadioQueue.crimes[i].type != CRIME_NONE) {
|
||||||
|
if (++m_sPoliceRadioQueue.crimes[i].timer > 1500) m_sPoliceRadioQueue.crimes[i].type = CRIME_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
STARTPATCHES
|
||||||
|
InjectHook(0x580AF0, &cAudioManager::AgeCrimes, PATCH_JUMP);
|
||||||
|
InjectHook(0x57F060, &cAudioManager::DoPoliceRadioCrackle, PATCH_JUMP);
|
||||||
|
InjectHook(0x57F050, &cAudioManager::GetMissionScriptPoliceAudioPlayingStatus, PATCH_JUMP);
|
||||||
|
InjectHook(0x57EEC0, &cAudioManager::InitialisePoliceRadio, PATCH_JUMP);
|
||||||
|
InjectHook(0x57EAC0, &cAudioManager::InitialisePoliceRadioZones, PATCH_JUMP);
|
||||||
|
InjectHook(0x580500, &cAudioManager::PlaySuspectLastSeen, PATCH_JUMP);
|
||||||
|
InjectHook(0x5803D0, &cAudioManager::ReportCrime, PATCH_JUMP);
|
||||||
|
InjectHook(0x57EFF0, &cAudioManager::ResetPoliceRadio, PATCH_JUMP);
|
||||||
|
InjectHook(0x57F110, &cAudioManager::ServicePoliceRadio, PATCH_JUMP);
|
||||||
|
InjectHook(0x57F1B0, &cAudioManager::ServicePoliceRadioChannel, PATCH_JUMP);
|
||||||
|
InjectHook(0x57F020, &cAudioManager::SetMissionScriptPoliceAudio, PATCH_JUMP);
|
||||||
|
InjectHook(0x57F5B0, &cAudioManager::SetupCrimeReport, PATCH_JUMP);
|
||||||
|
InjectHook(0x57FCC0, &cAudioManager::SetupSuspectLastSeenReport, PATCH_JUMP);
|
||||||
|
ENDPATCHES
|
44
src/audio/PoliceRadio.h
Normal file
44
src/audio/PoliceRadio.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
struct cAMCrime {
|
||||||
|
int32 type;
|
||||||
|
CVector position;
|
||||||
|
uint16 timer;
|
||||||
|
|
||||||
|
cAMCrime()
|
||||||
|
{
|
||||||
|
type = CRIME_NONE;
|
||||||
|
position = CVector(0.0f, 0.0f, 0.0f);
|
||||||
|
timer = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(cAMCrime) == 20, "cAMCrime: error ");
|
||||||
|
|
||||||
|
class cPoliceRadioQueue
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int32 crimesSamples[60];
|
||||||
|
uint8 policeChannelTimer;
|
||||||
|
uint8 policeChannelTimerSeconds;
|
||||||
|
uint8 policeChannelCounterSeconds;
|
||||||
|
cAMCrime crimes[10];
|
||||||
|
|
||||||
|
cPoliceRadioQueue()
|
||||||
|
{
|
||||||
|
policeChannelTimerSeconds = 0;
|
||||||
|
policeChannelCounterSeconds = 0;
|
||||||
|
policeChannelTimer = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Add(uint32 sample)
|
||||||
|
{
|
||||||
|
if (policeChannelTimer != 60) {
|
||||||
|
crimesSamples[policeChannelTimerSeconds] = sample;
|
||||||
|
policeChannelTimer++;
|
||||||
|
policeChannelTimerSeconds = (policeChannelTimerSeconds + 1) % 60;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(cPoliceRadioQueue) == 444, "cPoliceRadioQueue: error ");
|
@ -225,4 +225,31 @@ enum eStreamedSounds
|
|||||||
STREAMED_SOUND_MISSION_CAT1 = 195,
|
STREAMED_SOUND_MISSION_CAT1 = 195,
|
||||||
TOTAL_STREAMED_SOUNDS = 196,
|
TOTAL_STREAMED_SOUNDS = 196,
|
||||||
NO_STREAMED_SOUND = 197,
|
NO_STREAMED_SOUND = 197,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum AudioEntityHandle {
|
||||||
|
AEHANDLE_NONE = -5,
|
||||||
|
AEHANDLE_ERROR_NOAUDIOSYS = -4,
|
||||||
|
AEHANDLE_ERROR_NOFREESLOT = -3,
|
||||||
|
AEHANDLE_ERROR_NOENTITY = -2,
|
||||||
|
AEHANDLE_ERROR_BADAUDIOTYPE = -1,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum eAudioType : int32
|
||||||
|
{
|
||||||
|
AUDIOTYPE_PHYSICAL = 0,
|
||||||
|
AUDIOTYPE_EXPLOSION = 1,
|
||||||
|
AUDIOTYPE_FIRE = 2,
|
||||||
|
AUDIOTYPE_WEATHER = 3,
|
||||||
|
AUDIOTYPE_CRANE = 4,
|
||||||
|
AUDIOTYPE_SCRIPTOBJECT = 5,
|
||||||
|
AUDIOTYPE_BRIDGE = 6,
|
||||||
|
AUDIOTYPE_COLLISION = 7,
|
||||||
|
AUDIOTYPE_FRONTEND = 8,
|
||||||
|
AUDIOTYPE_PROJECTILE = 9,
|
||||||
|
AUDIOTYPE_GARAGE = 10,
|
||||||
|
AUDIOTYPE_FIREHYDRANT = 11,
|
||||||
|
AUDIOTYPE_WATERCANNON = 12,
|
||||||
|
AUDIOTYPE_POLICERADIO = 13,
|
||||||
|
TOTAL_AUDIO_TYPES = 14,
|
||||||
|
};
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
#include "PlayerPed.h"
|
#include "PlayerPed.h"
|
||||||
#include "Automobile.h"
|
#include "Automobile.h"
|
||||||
#include "DummyPed.h"
|
#include "DummyPed.h"
|
||||||
#include "AudioManager.h"
|
#include "AudioScriptObject.h"
|
||||||
|
|
||||||
typedef CPool<CPtrNode> CCPtrNodePool;
|
typedef CPool<CPtrNode> CCPtrNodePool;
|
||||||
typedef CPool<CEntryInfoNode> CEntryInfoNodePool;
|
typedef CPool<CEntryInfoNode> CEntryInfoNodePool;
|
||||||
@ -18,7 +18,7 @@ typedef CPool<CBuilding> CBuildingPool;
|
|||||||
typedef CPool<CTreadable> CTreadablePool;
|
typedef CPool<CTreadable> CTreadablePool;
|
||||||
typedef CPool<CObject, CCutsceneHead> CObjectPool;
|
typedef CPool<CObject, CCutsceneHead> CObjectPool;
|
||||||
typedef CPool<CDummy, CDummyPed> CDummyPool;
|
typedef CPool<CDummy, CDummyPed> CDummyPool;
|
||||||
typedef CPool<cAudioScriptObject, cAudioScriptObject> CAudioScriptObjectPool;
|
typedef CPool<cAudioScriptObject> CAudioScriptObjectPool;
|
||||||
|
|
||||||
class CPools
|
class CPools
|
||||||
{
|
{
|
||||||
|
@ -22,6 +22,7 @@ enum eCrimeType
|
|||||||
CRIME_COP_BURNED,
|
CRIME_COP_BURNED,
|
||||||
CRIME_VEHICLE_BURNED,
|
CRIME_VEHICLE_BURNED,
|
||||||
CRIME_DESTROYED_CESSNA,
|
CRIME_DESTROYED_CESSNA,
|
||||||
|
NUM_CRIME_TYPES
|
||||||
};
|
};
|
||||||
|
|
||||||
class CCrimeBeingQd
|
class CCrimeBeingQd
|
||||||
|
Loading…
Reference in New Issue
Block a user