raze/source/games/blood/src/asound.cpp

151 lines
4.6 KiB
C++
Raw Normal View History

2019-09-19 22:42:45 +00:00
//-------------------------------------------------------------------------
/*
Copyright (C) 2010-2019 EDuke32 developers and contributors
Copyright (C) 2019 Nuke.YKT
This file is part of NBlood.
NBlood is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License version 2
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
//-------------------------------------------------------------------------
#include "ns.h" // Must come before everything else!
2019-09-19 22:42:45 +00:00
#include "build.h"
#include "blood.h"
#include "raze_sound.h"
2019-09-19 22:42:45 +00:00
BEGIN_BLD_NS
enum {kMaxAmbChannel = 64 };
2019-09-19 22:42:45 +00:00
struct AMB_CHANNEL
{
FSoundID soundID;
int distance;
int check;
2019-09-19 22:42:45 +00:00
};
AMB_CHANNEL ambChannels[kMaxAmbChannel];
int nAmbChannels = 0;
void ambProcess(void)
{
if (!SoundEnabled())
2019-09-19 22:42:45 +00:00
return;
2021-08-26 19:43:41 +00:00
BloodStatIterator it(kStatAmbience);
while (DBloodActor* actor = it.Next())
2019-09-19 22:42:45 +00:00
{
2021-08-26 19:43:41 +00:00
spritetype *pSprite = &actor->s();
2019-09-19 22:42:45 +00:00
if (pSprite->owner < 0 || pSprite->owner >= kMaxAmbChannel)
continue;
2021-08-26 19:43:41 +00:00
if (actor->hasX())
2019-09-19 22:42:45 +00:00
{
2021-08-26 19:43:41 +00:00
XSPRITE *pXSprite = &actor->x();
2019-09-19 22:42:45 +00:00
if (pXSprite->state)
{
int dx = pSprite->pos.X-gMe->pSprite->pos.X;
2019-09-19 22:42:45 +00:00
int dy = pSprite->y-gMe->pSprite->y;
int dz = pSprite->z-gMe->pSprite->z;
dx >>= 4;
dy >>= 4;
dz >>= 8;
int nDist = ksqrt(dx*dx+dy*dy+dz*dz);
int vs = MulScale(pXSprite->data4, pXSprite->busy, 16);
ambChannels[pSprite->owner].distance += ClipRange(scale(nDist, pXSprite->data1, pXSprite->data2, vs, 0), 0, vs);
2019-09-19 22:42:45 +00:00
}
}
}
AMB_CHANNEL *pChannel = ambChannels;
for (int i = 0; i < nAmbChannels; i++, pChannel++)
{
if (soundEngine->IsSourcePlayingSomething(SOURCE_Ambient, pChannel, CHAN_BODY, -1))
2019-09-19 22:42:45 +00:00
{
if (pChannel->distance > 0)
{
soundEngine->ChangeSoundVolume(SOURCE_Ambient, pChannel, CHAN_BODY, pChannel->distance / 255.f);
}
else
{
// Stop the sound if it cannot be heard so that it doesn't occupy a physical channel.
soundEngine->StopSound(SOURCE_Ambient, pChannel, CHAN_BODY);
}
2019-09-19 22:42:45 +00:00
}
else if (pChannel->distance > 0)
{
FVector3 pt{};
soundEngine->StartSound(SOURCE_Ambient, pChannel, &pt, CHAN_BODY, CHANF_LOOP|CHANF_TRANSIENT, pChannel->soundID, pChannel->distance / 255.f, ATTN_NONE);
}
pChannel->distance = 0;
2019-09-19 22:42:45 +00:00
}
}
void ambKillAll(void)
{
AMB_CHANNEL *pChannel = ambChannels;
for (int i = 0; i < nAmbChannels; i++, pChannel++)
{
soundEngine->StopSound(SOURCE_Ambient, pChannel, CHAN_BODY);
pChannel->soundID = 0;
2019-09-19 22:42:45 +00:00
}
nAmbChannels = 0;
}
void ambInit(void)
{
ambKillAll();
memset(ambChannels, 0, sizeof(ambChannels));
2021-08-26 19:43:41 +00:00
BloodStatIterator it(kStatAmbience);
while (DBloodActor* actor = it.Next())
2020-10-15 15:15:45 +00:00
{
2021-08-26 19:43:41 +00:00
spritetype* pSprite = &actor->s();
if (!actor->hasX()) continue;
2021-08-26 19:43:41 +00:00
XSPRITE* pXSprite = &actor->x();
if (pXSprite->data1 >= pXSprite->data2) continue;
int i; AMB_CHANNEL *pChannel = ambChannels;
for (i = 0; i < nAmbChannels; i++, pChannel++)
if (pXSprite->data3 == pChannel->check) break;
if (i == nAmbChannels) {
if (i >= kMaxAmbChannel) {
2021-08-26 19:43:41 +00:00
pSprite->owner = -1;
continue;
}
int nSFX = pXSprite->data3;
auto snd = soundEngine->FindSoundByResID(nSFX);
if (!snd) {
//I_Error("Missing sound #%d used in ambient sound generator %d\n", nSFX);
viewSetSystemMessage("Missing sound #%d used in ambient sound generator #%d\n", nSFX, actor->GetIndex());
2021-08-26 19:43:41 +00:00
actPostSprite(actor, kStatDecoration);
continue;
}
pChannel->soundID = FSoundID(snd);
pChannel->check = nSFX;
pChannel->distance = 0;
nAmbChannels++;
2019-09-19 22:42:45 +00:00
}
2021-08-26 19:43:41 +00:00
pSprite->owner = i;
2019-09-19 22:42:45 +00:00
}
}
END_BLD_NS