📄 randomsoundfx.cpp
字号:
// ----------------------------------------------------------------------- //
//
// MODULE : RandomSoundFX.cpp
//
// PURPOSE : Random sounds
//
// CREATED : 08/23/98
//
// ----------------------------------------------------------------------- //
#include <stdio.h>
#include "cpp_server_de.h"
#include "generic_msg_de.h"
#include "RandomSoundFX.h"
#include "ObjectUtilities.h"
#include "SharedDefs.h"
#include <mbstring.h>
#include "SoundTypes.h"
BEGIN_CLASS(RandomSoundFX)
ADD_BOOLPROP(InitiallyOn, DTRUE)
ADD_BOOLPROP(PositionalSound, DTRUE) // Sound should be positional, not localized
ADD_BOOLPROP(SequentialPlay, DFALSE) // Sounds should be played in sequence.
ADD_BOOLPROP(LoopSequence, DFALSE) // Loop sequential playing
ADD_REALPROP(PosRangeRadius, 0.0f) // Sound should be positional, placed withing this radius
ADD_REALPROP_FLAG(SoundRadius, 1000.0f, PF_RADIUS)
ADD_LONGINTPROP(Volume, 100)
ADD_BOOLPROP(Ambient, 1)
ADD_REALPROP(MinWaitTime, 60.0f)
ADD_REALPROP(MaxWaitTime, 60.0f)
ADD_STRINGPROP(SoundFile1, "")
ADD_STRINGPROP(SoundFile2, "")
ADD_STRINGPROP(SoundFile3, "")
ADD_STRINGPROP(SoundFile4, "")
ADD_STRINGPROP(SoundFile5, "")
ADD_STRINGPROP(SoundFile6, "")
ADD_STRINGPROP(SoundFile7, "")
ADD_STRINGPROP(SoundFile8, "")
ADD_STRINGPROP(SoundFile9, "")
ADD_STRINGPROP(SoundFile10, "")
END_CLASS_DEFAULT(RandomSoundFX, B2BaseClass, NULL, NULL)
// ----------------------------------------------------------------------- //
//
// ROUTINE:
//
// PURPOSE: Constructor
//
// ----------------------------------------------------------------------- //
RandomSoundFX::RandomSoundFX() : B2BaseClass()
{
m_bOn = DTRUE;
m_bPositional = DFALSE;
m_bSequentialPlay = DFALSE;
m_bLoopSequence = DFALSE;
m_fPosRangeRadius = 0.0f;
m_fSoundRadius = 1000.0f;
m_nVolume = 100;
m_fMinWaitTime = 60.0f;
m_fMaxWaitTime = 60.0f;
m_nNumSounds = 0;
m_nCurrentSound = 0;
for (int i=0; i < RS_NUMSOUNDS; i++)
m_hstrSoundFile[i] = DNULL;
m_hsndSound = DNULL;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: RandomSoundFX::~RandomSoundFX()
//
// PURPOSE: Destructor
//
// ----------------------------------------------------------------------- //
RandomSoundFX::~RandomSoundFX()
{
if (!g_pServerDE) return;
for (int i=0; i < RS_NUMSOUNDS; i++)
{
if (m_hstrSoundFile[i])
{
g_pServerDE->FreeString(m_hstrSoundFile[i]);
}
}
if (m_hsndSound)
g_pServerDE->KillSound(m_hsndSound);
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: RandomSoundFX::EngineMessageFn
//
// PURPOSE: Handle engine messages
//
// ----------------------------------------------------------------------- //
DDWORD RandomSoundFX::EngineMessageFn(DDWORD messageID, void *pData, DFLOAT fData)
{
if (!g_pServerDE) return 0;
switch(messageID)
{
case MID_PRECREATE:
{
if (fData == PRECREATE_WORLDFILE || fData == PRECREATE_STRINGPROP)
{
ReadProp((ObjectCreateStruct*)pData);
}
break;
}
break;
case MID_INITIALUPDATE:
{
if (fData != INITIALUPDATE_SAVEGAME)
{
InitialUpdate((DVector *)pData);
}
CacheFiles();
}
break;
case MID_UPDATE:
{
if (!Update())
{
g_pServerDE->RemoveObject(m_hObject);
}
}
break;
case MID_SAVEOBJECT:
{
Save((HMESSAGEWRITE)pData, (DDWORD)fData);
}
break;
case MID_LOADOBJECT:
{
Load((HMESSAGEREAD)pData, (DDWORD)fData);
}
break;
default : break;
}
return B2BaseClass::EngineMessageFn(messageID, pData, fData);
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: RandomSoundFX::ObjectMessageFn
//
// PURPOSE: Handle object-to-object messages
//
// ----------------------------------------------------------------------- //
DDWORD RandomSoundFX::ObjectMessageFn(HOBJECT hSender, DDWORD messageID, HMESSAGEREAD hRead)
{
switch(messageID)
{
case MID_TRIGGER:
{
HandleTrigger(hSender, hRead);
break;
}
default : break;
}
return B2BaseClass::ObjectMessageFn (hSender, messageID, hRead);
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: RandomSoundFX::HandleTrigger()
//
// PURPOSE: Called when triggered.
//
// ----------------------------------------------------------------------- //
void RandomSoundFX::HandleTrigger( HOBJECT hSender, HMESSAGEREAD hRead )
{
HSTRING hMsg = g_pServerDE->ReadFromMessageHString(hRead);
char *pszMessage = g_pServerDE->GetStringData( hMsg );
if ( _mbsncmp((const unsigned char*)pszMessage, (const unsigned char*)"TOGGLE", 6) == 0)
{
// Toggle the flag
m_bOn = !m_bOn;
}
else if ( _mbsncmp((const unsigned char*)pszMessage, (const unsigned char*)"ON", 2) == 0)
{
m_bOn = DTRUE;
}
else if ( _mbsncmp((const unsigned char*)pszMessage, (const unsigned char*)"OFF", 3) == 0)
{
m_bOn = DFALSE;
}
g_pServerDE->FreeString( hMsg );
// If toggled on, reset the sequence
if (m_bOn && m_bSequentialPlay)
{
m_nCurrentSound = 0;
}
// Set the next update to play a sound immediately if activated
DFLOAT fNextUpdate = m_bOn ? 0.1f : 0.0f;
g_pServerDE->FreeString(hMsg);
g_pServerDE->SetNextUpdate(m_hObject, fNextUpdate);
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: RandomSoundFX::ReadProp
//
// PURPOSE: Set property value
//
// ----------------------------------------------------------------------- //
DBOOL RandomSoundFX::ReadProp(ObjectCreateStruct *)
{
CServerDE* pServerDE = GetServerDE();
if (!pServerDE) return DFALSE;
GenericProp genProp;
if (pServerDE->GetPropGeneric("InitiallyOn", &genProp) == DE_OK)
m_bOn = genProp.m_Bool;
if (pServerDE->GetPropGeneric("PositionalSound", &genProp) == DE_OK)
m_bPositional = genProp.m_Bool;
if (pServerDE->GetPropGeneric("SequentialPlay", &genProp) == DE_OK)
m_bSequentialPlay = genProp.m_Bool;
if (pServerDE->GetPropGeneric("LoopSequence", &genProp) == DE_OK)
m_bLoopSequence = genProp.m_Bool;
if (pServerDE->GetPropGeneric("PosRangeRadius", &genProp) == DE_OK)
m_fPosRangeRadius = genProp.m_Float;
if (pServerDE->GetPropGeneric("SoundRadius", &genProp) == DE_OK)
m_fSoundRadius = genProp.m_Float;
if (pServerDE->GetPropGeneric("Volume", &genProp) == DE_OK)
{
m_nVolume = (DBYTE)genProp.m_Long;
CLIPLOWHIGH(m_nVolume, 0, 100);
}
if (pServerDE->GetPropGeneric("MinWaitTime", &genProp) == DE_OK)
m_fMinWaitTime = genProp.m_Float;
if (pServerDE->GetPropGeneric("MaxWaitTime", &genProp) == DE_OK)
m_fMaxWaitTime = genProp.m_Float;
for (int i=0; i < RS_NUMSOUNDS; i++)
{
char name[30];
sprintf(name, "SoundFile%d", i + 1);
if (pServerDE->GetPropGeneric(name, &genProp) == DE_OK)
{
if (genProp.m_String[0])
m_hstrSoundFile[i] = pServerDE->CreateString(genProp.m_String);
else
break;
m_nNumSounds++;
}
}
return DTRUE;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: InitialUpdate()
//
// PURPOSE: Handle initial update
//
// ----------------------------------------------------------------------- //
DBOOL RandomSoundFX::InitialUpdate(DVector *pMovement)
{
if (!g_pServerDE) return DFALSE;
if (m_bOn)
{
DFLOAT fNextUpdate = g_pServerDE->Random(m_fMinWaitTime, m_fMaxWaitTime);
g_pServerDE->SetNextUpdate(m_hObject, fNextUpdate);
}
return DTRUE;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: RandomSoundFX::Update
//
// PURPOSE: Play a sound
//
// ----------------------------------------------------------------------- //
DBOOL RandomSoundFX::Update()
{
if (!g_pServerDE) return DFALSE;
// Kill the current sound
if (m_hsndSound)
{
g_pServerDE->KillSound(m_hsndSound);
m_hsndSound = DNULL;
}
// Get a sound..
if (m_nNumSounds < 1) return DFALSE;
char *pSound = DNULL;
int n;
if (!m_bSequentialPlay)
n = g_pServerDE->IntRandom(0, m_nNumSounds - 1);
else
n = m_nCurrentSound;
if (m_hstrSoundFile[n])
pSound = g_pServerDE->GetStringData(m_hstrSoundFile[n]);
if (!pSound) return DFALSE;
/* if (!m_bPositional)
{
g_pServerDE->PlaySoundLocal(pSound, SOUNDTYPE_MISC, SOUNDPRIORITY_LOW);
}
else
{
DVector vPos;
g_pServerDE->GetObjectPos(m_hObject, &vPos);
vPos.x += g_pServerDE->Random(-m_fPosRangeRadius, m_fPosRangeRadius);
vPos.z += g_pServerDE->Random(-m_fPosRangeRadius, m_fPosRangeRadius);
PlaySoundFromPos(&vPos,
pSound,
m_fSoundRadius,
SOUNDTYPE_MISC,
SOUNDPRIORITY_LOW,
DFALSE,
DFALSE,
DFALSE,
m_nVolume);
}
*/
DVector vPos;
g_pServerDE->GetObjectPos(m_hObject, &vPos);
vPos.x += g_pServerDE->Random(-m_fPosRangeRadius, m_fPosRangeRadius);
vPos.z += g_pServerDE->Random(-m_fPosRangeRadius, m_fPosRangeRadius);
PlaySoundInfo playSoundInfo;
PLAYSOUNDINFO_INIT( playSoundInfo );
playSoundInfo.m_dwFlags = PLAYSOUND_GETHANDLE | PLAYSOUND_TIME;
_mbscpy((unsigned char*)playSoundInfo.m_szSoundName, (const unsigned char*)pSound );
playSoundInfo.m_nPriority = SOUNDPRIORITY_MISC_LOW;
playSoundInfo.m_fOuterRadius = m_fSoundRadius;
playSoundInfo.m_fInnerRadius = m_fSoundRadius * 0.5f;
if( m_nVolume < 100 )
{
playSoundInfo.m_nVolume = m_nVolume;
playSoundInfo.m_dwFlags |= PLAYSOUND_CTRL_VOL;
}
VEC_COPY(playSoundInfo.m_vPosition, vPos);
if( !m_bPositional )
{
playSoundInfo.m_dwFlags |= PLAYSOUND_AMBIENT;
}
else
{
playSoundInfo.m_dwFlags |= PLAYSOUND_3D | PLAYSOUND_REVERB;
}
g_pServerDE->PlaySound( &playSoundInfo );
m_hsndSound = playSoundInfo.m_hSound;
if (m_bSequentialPlay)
{
m_nCurrentSound++;
if (m_nCurrentSound == m_nNumSounds)
{
m_nCurrentSound = 0;
// If not looping, turn off
if (!m_bLoopSequence)
{
m_bOn = DFALSE;
}
}
}
// Set the next sound play time, unless no longer on
if (m_bOn)
{
DFLOAT fNextUpdate = g_pServerDE->Random(m_fMinWaitTime, m_fMaxWaitTime);
g_pServerDE->SetNextUpdate(m_hObject, fNextUpdate);
}
return DTRUE;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: RandomSoundFX::Save
//
// PURPOSE: Save the object
//
// ----------------------------------------------------------------------- //
void RandomSoundFX::Save(HMESSAGEWRITE hWrite, DDWORD dwSaveFlags)
{
CServerDE* pServerDE = GetServerDE();
if (!pServerDE || !hWrite) return;
// Only need to save the data that changes (all the data in the
// special fx message is saved/loaded for us)...
pServerDE->WriteToMessageByte(hWrite, m_bOn);
pServerDE->WriteToMessageByte(hWrite, m_bPositional);
pServerDE->WriteToMessageByte(hWrite, m_bSequentialPlay);
pServerDE->WriteToMessageByte(hWrite, m_bLoopSequence);
pServerDE->WriteToMessageFloat(hWrite, m_fPosRangeRadius);
pServerDE->WriteToMessageFloat(hWrite, m_fSoundRadius);
pServerDE->WriteToMessageFloat(hWrite, m_fMinWaitTime);
pServerDE->WriteToMessageFloat(hWrite, m_fMaxWaitTime);
pServerDE->WriteToMessageByte(hWrite, m_nVolume);
pServerDE->WriteToMessageByte(hWrite, m_nNumSounds);
pServerDE->WriteToMessageByte(hWrite, m_nCurrentSound);
for (int i=0; i < RS_NUMSOUNDS; i++)
{
pServerDE->WriteToMessageHString(hWrite, m_hstrSoundFile[i]);
}
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: RandomSoundFX::Load
//
// PURPOSE: Load the object
//
// ----------------------------------------------------------------------- //
void RandomSoundFX::Load(HMESSAGEREAD hRead, DDWORD dwLoadFlags)
{
CServerDE* pServerDE = GetServerDE();
if (!pServerDE || !hRead) return;
m_bOn = (DBOOL) pServerDE->ReadFromMessageByte(hRead);
m_bPositional = (DBOOL) pServerDE->ReadFromMessageByte(hRead);
m_bSequentialPlay = (DBOOL) pServerDE->ReadFromMessageByte(hRead);
m_bLoopSequence = (DBOOL) pServerDE->ReadFromMessageByte(hRead);
m_fPosRangeRadius = pServerDE->ReadFromMessageFloat(hRead);
m_fSoundRadius = pServerDE->ReadFromMessageFloat(hRead);
m_fMinWaitTime = pServerDE->ReadFromMessageFloat(hRead);
m_fMaxWaitTime = pServerDE->ReadFromMessageFloat(hRead);
m_nVolume = pServerDE->ReadFromMessageByte(hRead);
m_nNumSounds = pServerDE->ReadFromMessageByte(hRead);
m_nCurrentSound = pServerDE->ReadFromMessageByte(hRead);
for (int i=0; i < RS_NUMSOUNDS; i++)
{
m_hstrSoundFile[i] = pServerDE->ReadFromMessageHString(hRead);
}
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: RandomSoundFX::CacheFiles
//
// PURPOSE: Cache resources used by the object
//
// ----------------------------------------------------------------------- //
void RandomSoundFX::CacheFiles()
{
CServerDE* pServerDE = GetServerDE();
if (!pServerDE) return;
// {MD 9/23/98}
if(!(pServerDE->GetServerFlags() & SS_CACHING))
return;
char* pFile = DNULL;
for (int i = 0; i < RS_NUMSOUNDS; i++)
if (m_hstrSoundFile[i])
{
pFile = g_pServerDE->GetStringData(m_hstrSoundFile[i]);
g_pServerDE->CacheFile(FT_SOUND, pFile);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -