2020-06-02 11:46:59 +00:00
|
|
|
#include <engine/demo.h>
|
2014-10-10 17:10:57 +00:00
|
|
|
#include <engine/engine.h>
|
|
|
|
#include <engine/sound.h>
|
|
|
|
|
2014-10-13 10:10:56 +00:00
|
|
|
#include <game/client/components/camera.h>
|
2014-10-12 14:12:13 +00:00
|
|
|
#include <game/client/components/maplayers.h> // envelope
|
2014-10-10 17:10:57 +00:00
|
|
|
#include <game/client/components/sounds.h>
|
|
|
|
|
|
|
|
#include "mapsounds.h"
|
|
|
|
|
|
|
|
CMapSounds::CMapSounds()
|
|
|
|
{
|
|
|
|
m_Count = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CMapSounds::OnMapLoad()
|
|
|
|
{
|
|
|
|
IMap *pMap = Kernel()->RequestInterface<IMap>();
|
|
|
|
|
2014-10-18 13:21:13 +00:00
|
|
|
Clear();
|
2014-10-11 11:38:08 +00:00
|
|
|
|
|
|
|
// load samples
|
|
|
|
int Start;
|
|
|
|
pMap->GetType(MAPITEMTYPE_SOUND, &Start, &m_Count);
|
|
|
|
|
|
|
|
// load new samples
|
|
|
|
for(int i = 0; i < m_Count; i++)
|
|
|
|
{
|
|
|
|
m_aSounds[i] = 0;
|
|
|
|
|
2020-09-26 19:41:58 +00:00
|
|
|
CMapItemSound *pSound = (CMapItemSound *)pMap->GetItem(Start + i, 0, 0);
|
2014-10-11 11:38:08 +00:00
|
|
|
if(pSound->m_External)
|
|
|
|
{
|
|
|
|
char Buf[256];
|
|
|
|
char *pName = (char *)pMap->GetData(pSound->m_SoundName);
|
2014-10-27 15:23:53 +00:00
|
|
|
str_format(Buf, sizeof(Buf), "mapres/%s.opus", pName);
|
|
|
|
m_aSounds[i] = Sound()->LoadOpus(Buf);
|
2014-10-11 11:38:08 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-10-11 12:50:16 +00:00
|
|
|
void *pData = pMap->GetData(pSound->m_SoundData);
|
2014-10-27 15:23:53 +00:00
|
|
|
m_aSounds[i] = Sound()->LoadOpusFromMem(pData, pSound->m_SoundDataSize);
|
2014-10-11 12:50:16 +00:00
|
|
|
pMap->UnloadData(pSound->m_SoundData);
|
2014-10-11 11:38:08 +00:00
|
|
|
}
|
|
|
|
}
|
2014-10-10 17:10:57 +00:00
|
|
|
|
|
|
|
// enqueue sound sources
|
2014-10-12 14:12:13 +00:00
|
|
|
m_lSourceQueue.clear();
|
2014-10-10 17:10:57 +00:00
|
|
|
for(int g = 0; g < Layers()->NumGroups(); g++)
|
|
|
|
{
|
|
|
|
CMapItemGroup *pGroup = Layers()->GetGroup(g);
|
|
|
|
|
|
|
|
if(!pGroup)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
for(int l = 0; l < pGroup->m_NumLayers; l++)
|
|
|
|
{
|
2020-09-26 19:41:58 +00:00
|
|
|
CMapItemLayer *pLayer = Layers()->GetLayer(pGroup->m_StartLayer + l);
|
2014-10-10 17:10:57 +00:00
|
|
|
|
|
|
|
if(!pLayer)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if(pLayer->m_Type == LAYERTYPE_SOUNDS)
|
|
|
|
{
|
|
|
|
CMapItemLayerSounds *pSoundLayer = (CMapItemLayerSounds *)pLayer;
|
2014-10-11 11:38:08 +00:00
|
|
|
|
2014-11-27 15:18:15 +00:00
|
|
|
if(pSoundLayer->m_Version < 1 || pSoundLayer->m_Version > CMapItemLayerSounds::CURRENT_VERSION)
|
|
|
|
continue;
|
|
|
|
|
2014-10-11 11:38:08 +00:00
|
|
|
if(pSoundLayer->m_Sound == -1)
|
|
|
|
continue;
|
|
|
|
|
2014-10-10 17:10:57 +00:00
|
|
|
CSoundSource *pSources = (CSoundSource *)Layers()->Map()->GetDataSwapped(pSoundLayer->m_Data);
|
|
|
|
|
|
|
|
if(!pSources)
|
|
|
|
continue;
|
|
|
|
|
2020-09-26 19:41:58 +00:00
|
|
|
for(int i = 0; i < pSoundLayer->m_NumSources; i++)
|
|
|
|
{
|
2014-10-18 13:21:13 +00:00
|
|
|
CSourceQueueEntry source;
|
|
|
|
source.m_Sound = pSoundLayer->m_Sound;
|
|
|
|
source.m_pSource = &pSources[i];
|
2020-09-26 19:41:58 +00:00
|
|
|
source.m_HighDetail = pLayer->m_Flags & LAYERFLAG_DETAIL;
|
2014-10-18 13:21:13 +00:00
|
|
|
|
|
|
|
if(!source.m_pSource || source.m_Sound == -1)
|
|
|
|
continue;
|
|
|
|
|
2014-11-25 20:01:31 +00:00
|
|
|
m_lSourceQueue.add(source);
|
|
|
|
}
|
2014-10-10 17:10:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CMapSounds::OnRender()
|
|
|
|
{
|
|
|
|
if(Client()->State() != IClient::STATE_ONLINE && Client()->State() != IClient::STATE_DEMOPLAYBACK)
|
|
|
|
return;
|
|
|
|
|
2020-06-02 11:46:59 +00:00
|
|
|
bool DemoPlayerPaused = Client()->State() == IClient::STATE_DEMOPLAYBACK && DemoPlayer()->BaseInfo()->m_Paused;
|
|
|
|
|
2014-10-10 17:10:57 +00:00
|
|
|
// enqueue sounds
|
2014-10-12 14:12:13 +00:00
|
|
|
for(int i = 0; i < m_lSourceQueue.size(); i++)
|
2014-10-10 17:10:57 +00:00
|
|
|
{
|
2014-10-12 14:12:13 +00:00
|
|
|
CSourceQueueEntry *pSource = &m_lSourceQueue[i];
|
2014-10-10 17:10:57 +00:00
|
|
|
|
2014-10-18 13:21:13 +00:00
|
|
|
static float s_Time = 0.0f;
|
2014-10-31 15:10:09 +00:00
|
|
|
if(m_pClient->m_Snap.m_pGameInfoObj) // && !(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED))
|
2014-10-10 17:10:57 +00:00
|
|
|
{
|
2020-09-26 19:41:58 +00:00
|
|
|
s_Time = mix((Client()->PrevGameTick(g_Config.m_ClDummy) - m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick) / (float)Client()->GameTickSpeed(),
|
|
|
|
(Client()->GameTick(g_Config.m_ClDummy) - m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick) / (float)Client()->GameTickSpeed(),
|
|
|
|
Client()->IntraGameTick(g_Config.m_ClDummy));
|
2014-10-10 17:10:57 +00:00
|
|
|
}
|
2020-09-26 19:41:58 +00:00
|
|
|
float Offset = s_Time - pSource->m_pSource->m_TimeDelay;
|
2020-06-02 11:46:59 +00:00
|
|
|
if(!DemoPlayerPaused && Offset >= 0.0f && g_Config.m_SndEnable && (g_Config.m_GfxHighDetail || !pSource->m_HighDetail))
|
2014-10-10 17:10:57 +00:00
|
|
|
{
|
2014-10-18 13:21:13 +00:00
|
|
|
if(pSource->m_Voice.IsValid())
|
|
|
|
{
|
|
|
|
// currently playing, set offset
|
2017-03-21 10:24:44 +00:00
|
|
|
Sound()->SetVoiceTimeOffset(pSource->m_Voice, Offset);
|
2014-10-18 13:21:13 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// need to enqueue
|
|
|
|
int Flags = 0;
|
2020-09-26 19:41:58 +00:00
|
|
|
if(pSource->m_pSource->m_Loop)
|
|
|
|
Flags |= ISound::FLAG_LOOP;
|
|
|
|
if(!pSource->m_pSource->m_Pan)
|
|
|
|
Flags |= ISound::FLAG_NO_PANNING;
|
2014-10-12 14:12:13 +00:00
|
|
|
|
2014-10-23 13:53:23 +00:00
|
|
|
pSource->m_Voice = m_pClient->m_pSounds->PlaySampleAt(CSounds::CHN_MAPSOUND, m_aSounds[pSource->m_Sound], 1.0f, vec2(fx2f(pSource->m_pSource->m_Position.x), fx2f(pSource->m_pSource->m_Position.y)), Flags);
|
2017-03-21 10:24:44 +00:00
|
|
|
Sound()->SetVoiceTimeOffset(pSource->m_Voice, Offset);
|
2020-09-26 19:41:58 +00:00
|
|
|
Sound()->SetVoiceFalloff(pSource->m_Voice, pSource->m_pSource->m_Falloff / 255.0f);
|
2014-11-29 13:29:40 +00:00
|
|
|
switch(pSource->m_pSource->m_Shape.m_Type)
|
|
|
|
{
|
|
|
|
case CSoundShape::SHAPE_CIRCLE:
|
2020-09-26 19:41:58 +00:00
|
|
|
{
|
|
|
|
Sound()->SetVoiceCircle(pSource->m_Voice, pSource->m_pSource->m_Shape.m_Circle.m_Radius);
|
|
|
|
break;
|
|
|
|
}
|
2014-11-29 13:29:40 +00:00
|
|
|
|
|
|
|
case CSoundShape::SHAPE_RECTANGLE:
|
2020-09-26 19:41:58 +00:00
|
|
|
{
|
|
|
|
Sound()->SetVoiceRectangle(pSource->m_Voice, fx2f(pSource->m_pSource->m_Shape.m_Rectangle.m_Width), fx2f(pSource->m_pSource->m_Shape.m_Rectangle.m_Height));
|
|
|
|
break;
|
|
|
|
}
|
2014-11-29 13:29:40 +00:00
|
|
|
};
|
2014-10-18 13:21:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// stop voice
|
|
|
|
Sound()->StopVoice(pSource->m_Voice);
|
|
|
|
pSource->m_Voice = ISound::CVoiceHandle();
|
2014-10-12 14:12:13 +00:00
|
|
|
}
|
|
|
|
}
|
2014-10-10 17:50:39 +00:00
|
|
|
|
2014-10-13 10:10:56 +00:00
|
|
|
vec2 Center = m_pClient->m_pCamera->m_Center;
|
|
|
|
for(int g = 0; g < Layers()->NumGroups(); g++)
|
2014-10-12 14:12:13 +00:00
|
|
|
{
|
2014-10-13 10:10:56 +00:00
|
|
|
CMapItemGroup *pGroup = Layers()->GetGroup(g);
|
2014-10-12 14:12:13 +00:00
|
|
|
|
2014-10-13 10:10:56 +00:00
|
|
|
if(!pGroup)
|
2014-10-12 14:12:13 +00:00
|
|
|
continue;
|
|
|
|
|
2014-10-13 10:10:56 +00:00
|
|
|
for(int l = 0; l < pGroup->m_NumLayers; l++)
|
2014-10-12 14:12:13 +00:00
|
|
|
{
|
2020-09-26 19:41:58 +00:00
|
|
|
CMapItemLayer *pLayer = Layers()->GetLayer(pGroup->m_StartLayer + l);
|
2014-10-12 14:12:13 +00:00
|
|
|
|
2014-10-13 10:10:56 +00:00
|
|
|
if(!pLayer)
|
|
|
|
continue;
|
2014-10-12 14:43:33 +00:00
|
|
|
|
2014-10-13 10:10:56 +00:00
|
|
|
if(pLayer->m_Type == LAYERTYPE_SOUNDS)
|
|
|
|
{
|
|
|
|
CMapItemLayerSounds *pSoundLayer = (CMapItemLayerSounds *)pLayer;
|
2015-07-09 00:08:14 +00:00
|
|
|
|
2014-11-27 15:18:15 +00:00
|
|
|
if(pSoundLayer->m_Version < 1 || pSoundLayer->m_Version > CMapItemLayerSounds::CURRENT_VERSION)
|
|
|
|
continue;
|
2014-10-12 14:43:33 +00:00
|
|
|
|
2014-10-13 10:10:56 +00:00
|
|
|
CSoundSource *pSources = (CSoundSource *)Layers()->Map()->GetDataSwapped(pSoundLayer->m_Data);
|
|
|
|
|
|
|
|
if(!pSources)
|
|
|
|
continue;
|
|
|
|
|
2020-09-26 19:41:58 +00:00
|
|
|
for(int s = 0; s < pSoundLayer->m_NumSources; s++)
|
|
|
|
{
|
2014-10-18 13:21:13 +00:00
|
|
|
for(int i = 0; i < m_lSourceQueue.size(); i++)
|
2014-10-13 10:10:56 +00:00
|
|
|
{
|
2014-10-18 13:21:13 +00:00
|
|
|
CSourceQueueEntry *pVoice = &m_lSourceQueue[i];
|
2014-10-13 10:10:56 +00:00
|
|
|
|
|
|
|
if(pVoice->m_pSource != &pSources[s])
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if(!pVoice->m_Voice.IsValid())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
float OffsetX = 0, OffsetY = 0;
|
|
|
|
|
|
|
|
if(pVoice->m_pSource->m_PosEnv >= 0)
|
|
|
|
{
|
|
|
|
float aChannels[4];
|
2020-09-26 19:41:58 +00:00
|
|
|
CMapLayers::EnvelopeEval(pVoice->m_pSource->m_PosEnvOffset / 1000.0f, pVoice->m_pSource->m_PosEnv, aChannels, m_pClient->m_pMapLayersBackGround);
|
2014-10-13 10:10:56 +00:00
|
|
|
OffsetX = aChannels[0];
|
|
|
|
OffsetY = aChannels[1];
|
|
|
|
}
|
|
|
|
|
2020-09-26 19:41:58 +00:00
|
|
|
float x = fx2f(pVoice->m_pSource->m_Position.x) + OffsetX;
|
|
|
|
float y = fx2f(pVoice->m_pSource->m_Position.y) + OffsetY;
|
2014-10-13 10:10:56 +00:00
|
|
|
|
2020-09-26 19:41:58 +00:00
|
|
|
x += Center.x * (1.0f - pGroup->m_ParallaxX / 100.0f);
|
|
|
|
y += Center.y * (1.0f - pGroup->m_ParallaxY / 100.0f);
|
2014-10-13 10:10:56 +00:00
|
|
|
|
2020-09-26 19:41:58 +00:00
|
|
|
x -= pGroup->m_OffsetX;
|
|
|
|
y -= pGroup->m_OffsetY;
|
2014-10-13 10:10:56 +00:00
|
|
|
|
|
|
|
Sound()->SetVoiceLocation(pVoice->m_Voice, x, y);
|
|
|
|
|
|
|
|
if(pVoice->m_pSource->m_SoundEnv >= 0)
|
|
|
|
{
|
|
|
|
float aChannels[4];
|
2020-09-26 19:41:58 +00:00
|
|
|
CMapLayers::EnvelopeEval(pVoice->m_pSource->m_SoundEnvOffset / 1000.0f, pVoice->m_pSource->m_SoundEnv, aChannels, m_pClient->m_pMapLayersBackGround);
|
2014-10-13 10:10:56 +00:00
|
|
|
float Volume = clamp(aChannels[0], 0.0f, 1.0f);
|
|
|
|
|
|
|
|
Sound()->SetVoiceVolume(pVoice->m_Voice, Volume);
|
|
|
|
}
|
2015-07-09 00:08:14 +00:00
|
|
|
}
|
|
|
|
}
|
2014-10-13 10:10:56 +00:00
|
|
|
}
|
2014-10-12 14:43:33 +00:00
|
|
|
}
|
2014-10-10 17:10:57 +00:00
|
|
|
}
|
2014-10-18 13:21:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CMapSounds::Clear()
|
|
|
|
{
|
|
|
|
// unload all samples
|
|
|
|
for(int i = 0; i < m_Count; i++)
|
|
|
|
{
|
|
|
|
Sound()->UnloadSample(m_aSounds[i]);
|
|
|
|
m_aSounds[i] = -1;
|
|
|
|
}
|
|
|
|
m_Count = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CMapSounds::OnStateChange(int NewState, int OldState)
|
|
|
|
{
|
|
|
|
if(NewState < IClient::STATE_ONLINE)
|
|
|
|
Clear();
|
2014-10-23 13:53:23 +00:00
|
|
|
}
|