⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 soundfx.cpp

📁 Blood 2全套源码
💻 CPP
字号:
// ----------------------------------------------------------------------- //
//
// MODULE  : SoundFX.cpp
//
// PURPOSE : A start/stoppable ambient sound object.
//
// CREATED : 09/11/98
//
// ----------------------------------------------------------------------- //

#include <stdio.h>
#include "cpp_server_de.h"
#include "SoundFX.h"
#include "ClientServerShared.h"
#include "ObjectUtilities.h"
#include <mbstring.h>
#include "SoundTypes.h"


BEGIN_CLASS(SoundFX)
    ADD_BOOLPROP(StartOn, DTRUE)                
	ADD_STRINGPROP(RampUpSound, "")
	ADD_STRINGPROP(RampDownSound, "")
	ADD_STRINGPROP(Sound, "")
	ADD_LONGINTPROP(Priority, 0.0f)
	ADD_REALPROP_FLAG(OuterRadius, 500.0f, PF_RADIUS)
	ADD_REALPROP_FLAG(InnerRadius, 100.0f, PF_RADIUS)
	ADD_LONGINTPROP(Volume, 100.0f)
	ADD_BOOLPROP(Ambient, 1)
	ADD_BOOLPROP(FileStream, 0)
END_CLASS_DEFAULT(SoundFX, B2BaseClass, NULL, NULL)


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	
//
//	PURPOSE:	Constructor
//
// ----------------------------------------------------------------------- //

SoundFX::SoundFX() : B2BaseClass(OT_NORMAL)
{
	m_bStartOn				= DTRUE;
	m_byState				= SNDFX_OFF;

	m_hstrRampUpSound		= DNULL;
	m_hstrSound				= DNULL;
	m_hstrRampDownSound		= DNULL;

	m_hsndSound				= DNULL;

	m_fOuterRadius			= 0.0f;
	m_fInnerRadius			= 0.0f;
	m_nVolume				= 0;
	m_bAmbient				= DFALSE;
	m_bFileStream			= DFALSE;
	m_nPriority				= SOUNDPRIORITY_MISC_LOW;
}

// ----------------------------------------------------------------------- //
//
//	ROUTINE:	SoundFX::~SoundFX()	
//
//	PURPOSE:	Destructor
//
// ----------------------------------------------------------------------- //

SoundFX::~SoundFX()
{
	CServerDE* pServerDE = GetServerDE();
	if (!pServerDE) return;

	if (m_hstrRampUpSound)
	{
		pServerDE->FreeString(m_hstrRampUpSound);
	}

	if (m_hstrRampDownSound)
	{
		pServerDE->FreeString(m_hstrRampDownSound);
	}

	if (m_hstrRampDownSound)
	{
		pServerDE->FreeString(m_hstrRampDownSound);
	}

	if (m_hstrSound)
	{
		pServerDE->FreeString(m_hstrSound);
	}

	if (m_hsndSound)
		pServerDE->KillSound(m_hsndSound);
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	EngineMessageFn
//
//	PURPOSE:	Handle engine messages
//
// ----------------------------------------------------------------------- //

DDWORD SoundFX::EngineMessageFn(DDWORD messageID, void *pData, DFLOAT fData)
{
	switch(messageID)
	{
		case MID_PRECREATE:
		{
			DDWORD dwRet = B2BaseClass::EngineMessageFn(messageID, pData, fData);

			if (fData == PRECREATE_WORLDFILE || fData == PRECREATE_STRINGPROP)
			{
				ReadProp((ObjectCreateStruct*)pData);
			}

			PostPropRead((ObjectCreateStruct*)pData);

			return dwRet;
		}
		break;
    
		case MID_INITIALUPDATE:
		{
			if (fData != INITIALUPDATE_SAVEGAME)
			{
				InitialUpdate((DVector *)pData);
			}
			CacheFiles();
			break;
		}

		case MID_UPDATE:
		{
    		if (!Update()) 
            {
		    	CServerDE* pServerDE = BaseClass::GetServerDE();
			    if (pServerDE) 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:	SoundFX::ObjectMessageFn
//
//	PURPOSE:	Handle object-to-object messages
//
// ----------------------------------------------------------------------- //
DDWORD SoundFX::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:	SoundFX::HandleTrigger()
//
//	PURPOSE:	Called when triggered.
//
// ----------------------------------------------------------------------- //
void SoundFX::HandleTrigger( HOBJECT hSender, HMESSAGEREAD hRead )
{
	HSTRING hMsg = g_pServerDE->ReadFromMessageHString(hRead);
	char *pszMessage = g_pServerDE->GetStringData( hMsg );

    if ( _mbsicmp((const unsigned char*)pszMessage, (const unsigned char*)"TOGGLE") == 0)
    {
		if (m_byState != SNDFX_OFF)
		{
			m_byState = SNDFX_RAMPDOWN;
		}
		else
		{
			m_byState = SNDFX_RAMPUP;
		}

		UpdateSound();
    } 
    else if ( _mbsicmp((const unsigned char*)pszMessage, (const unsigned char*)"ON") == 0 || _mbsicmp((const unsigned char*)pszMessage, (const unsigned char*)"TRIGGER") == 0 )
    {
		if (m_byState == SNDFX_OFF)
		{
			m_byState = SNDFX_RAMPUP;
		}

		UpdateSound();
    }            
    else if ( _mbsicmp((const unsigned char*)pszMessage, (const unsigned char*)"OFF") == 0)
    {
		if (m_byState != SNDFX_OFF)
		{
			m_byState = SNDFX_RAMPDOWN;
		}

		UpdateSound();
    }        
    
	g_pServerDE->FreeString( hMsg );
}



// ----------------------------------------------------------------------- //
//
//	ROUTINE:	SoundFX::ReadProp
//
//	PURPOSE:	Set property value
//
// ----------------------------------------------------------------------- //
DBOOL SoundFX::ReadProp(ObjectCreateStruct *)
{
	CServerDE* pServerDE = GetServerDE();
	if (!pServerDE) return DFALSE;

	GenericProp genProp;

	if (pServerDE->GetPropGeneric("StartOn", &genProp) == LT_OK)
		m_bStartOn = genProp.m_Bool;

	if (pServerDE->GetPropGeneric("RampUpSound", &genProp) == DE_OK)
	{
		if (genProp.m_String[0])
			 m_hstrRampUpSound = pServerDE->CreateString(genProp.m_String);
	}

	if (pServerDE->GetPropGeneric("RampDownSound", &genProp) == DE_OK)
	{
		if (genProp.m_String[0])
			 m_hstrRampDownSound = pServerDE->CreateString(genProp.m_String);
	}

	if (pServerDE->GetPropGeneric("Sound", &genProp) == DE_OK)
	{
		if (genProp.m_String[0])
			 m_hstrSound = pServerDE->CreateString(genProp.m_String);
	}

	if (pServerDE->GetPropGeneric("Priority", &genProp) == LT_OK)
		m_nPriority = (unsigned char) genProp.m_Long;
	
	if (pServerDE->GetPropGeneric("OuterRadius", &genProp) == LT_OK)
		m_fOuterRadius = genProp.m_Float;
	
	if (pServerDE->GetPropGeneric("InnerRadius", &genProp) == LT_OK)
		m_fInnerRadius = genProp.m_Float;
	
	if (pServerDE->GetPropGeneric("Volume", &genProp) == LT_OK)
		m_nVolume = (DBYTE) genProp.m_Long;
	
	if (pServerDE->GetPropGeneric("Ambient", &genProp) == LT_OK)
		m_bAmbient = genProp.m_Bool;

	if (pServerDE->GetPropGeneric("FileStream", &genProp) == LT_OK)
		m_bFileStream = genProp.m_Bool;

	return DTRUE;
}

      
// ----------------------------------------------------------------------- //
//
//	ROUTINE:	PostPropRead()
//
//	PURPOSE:	Update properties
//
// ----------------------------------------------------------------------- //

void SoundFX::PostPropRead(ObjectCreateStruct *pStruct)
{
	if (!pStruct) return;

    // Set the Update!

	pStruct->m_NextUpdate = m_bStartOn ? 0.01f : 0.0f;
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	InitialUpdate()
//
//	PURPOSE:	Handle initial update
//
// ----------------------------------------------------------------------- //

DBOOL SoundFX::InitialUpdate(DVector *pMovement)
{
	CServerDE* pServerDE = GetServerDE();
	if (!pServerDE) return DFALSE;

	// Mark this object as savable
	DDWORD dwFlags = g_pServerDE->GetObjectUserFlags(m_hObject);
	dwFlags |= USRFLG_SAVEABLE;
	g_pServerDE->SetObjectUserFlags(m_hObject, dwFlags);

	if (m_bStartOn)
	{
		m_byState = SNDFX_ON;
		UpdateSound();
	}


	pServerDE->SetNextUpdate(m_hObject, 0);

	return DTRUE;
}



// ----------------------------------------------------------------------- //
//
//	ROUTINE:	SoundFX::Update
//
//	PURPOSE:
//
// ----------------------------------------------------------------------- //
DBOOL SoundFX::Update()
{
	CServerDE* pServerDE = GetServerDE();
	if (!pServerDE) return DFALSE;

	pServerDE->SetNextUpdate(m_hObject, 0);

	if (m_byState == SNDFX_RAMPUP)
	{
		m_byState = SNDFX_ON;
		UpdateSound();
	}
	else if (m_byState == SNDFX_RAMPDOWN)
	{
		m_byState = SNDFX_OFF;
		UpdateSound();
	}
	else if (m_byState == SNDFX_ON)
	{
		m_byState = SNDFX_RAMPDOWN;
		UpdateSound();
	}

	return DTRUE;
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	SoundFX::UpdateSound
//
//	PURPOSE:	Plays the requested sound file.
//
// ----------------------------------------------------------------------- //

void SoundFX::UpdateSound()
{
	CServerDE* pServerDE = GetServerDE();
	if (!pServerDE) return;


	// Kill the current sound
	if (m_hsndSound) 
	{
		pServerDE->KillSound(m_hsndSound);
		m_hsndSound = DNULL;
	}

	char *pSoundFile = DNULL;

	switch (m_byState)
	{
		case SNDFX_OFF: return;
		case SNDFX_RAMPUP:
			{
				if (m_hstrRampUpSound)
				{
					pSoundFile = pServerDE->GetStringData(m_hstrRampUpSound);
				}
				else
				{
					m_byState = SNDFX_ON;
					if (m_hstrSound)
						pSoundFile = pServerDE->GetStringData(m_hstrSound);
				}
			}
			break;

		case SNDFX_RAMPDOWN:
			{
				if (m_hstrRampDownSound)
				{
					pSoundFile = pServerDE->GetStringData(m_hstrRampDownSound);
				}
				else
				{
					m_byState = SNDFX_OFF;
					return;
				}
			}
			break;

		case SNDFX_ON:
			{
				if (m_hstrSound)
					pSoundFile = pServerDE->GetStringData(m_hstrSound);
			}
			break;
	}


	// Play the sound...
	if (pSoundFile)
	{
		PlaySoundInfo playSoundInfo;
		
		PLAYSOUNDINFO_INIT( playSoundInfo );
		
		playSoundInfo.m_dwFlags = PLAYSOUND_GETHANDLE | PLAYSOUND_TIME;
		if (m_byState == SNDFX_ON && m_bAmbient)		// Loop the on sound only
		{
			playSoundInfo.m_dwFlags |= PLAYSOUND_LOOP;
		}

		_mbscpy( (unsigned char*)playSoundInfo.m_szSoundName, (const unsigned char*)pSoundFile );
		playSoundInfo.m_nPriority = m_nPriority;
		playSoundInfo.m_fOuterRadius = m_fOuterRadius;
		playSoundInfo.m_fInnerRadius = m_fInnerRadius;
		if( m_nVolume < 100 )
		{
			playSoundInfo.m_nVolume = m_nVolume;
			playSoundInfo.m_dwFlags |= PLAYSOUND_CTRL_VOL;
		}
		
		pServerDE->GetObjectPos( m_hObject, &playSoundInfo.m_vPosition );
		if( m_bAmbient )
		{
			playSoundInfo.m_dwFlags |= PLAYSOUND_AMBIENT;
		}
		else
		{
			playSoundInfo.m_dwFlags |= PLAYSOUND_3D | PLAYSOUND_REVERB;
		}

		if( m_bFileStream )
		{
			playSoundInfo.m_dwFlags |= PLAYSOUND_FILESTREAM | PLAYSOUND_TIMESYNC;
		}

 		pServerDE->PlaySound( &playSoundInfo );
		m_hsndSound = playSoundInfo.m_hSound;

		// Set next update to play the next sound..
		if (m_hsndSound && (m_byState == SNDFX_RAMPUP || m_byState == SNDFX_RAMPDOWN) || (m_byState == SNDFX_ON && !m_bAmbient))
		{
			DFLOAT fDuration = 0.0f;
			DRESULT res;
			res = pServerDE->GetSoundDuration(playSoundInfo.m_hSound, &fDuration);
			if (res == LT_OK)
			{
				pServerDE->SetNextUpdate(m_hObject, fDuration);
			}
		}
	}
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	SoundFX::Save
//
//	PURPOSE:	Save the object
//
// ----------------------------------------------------------------------- //

void SoundFX::Save(HMESSAGEWRITE hWrite, DDWORD dwSaveFlags)
{
	CServerDE* pServerDE = GetServerDE();
	if (!pServerDE || !hWrite) return;

	pServerDE->WriteToMessageByte(hWrite, m_byState);
	pServerDE->WriteToMessageHString(hWrite, m_hstrRampUpSound);
	pServerDE->WriteToMessageHString(hWrite, m_hstrRampDownSound);
	pServerDE->WriteToMessageHString(hWrite, m_hstrSound);

	pServerDE->WriteToMessageFloat(hWrite, m_fOuterRadius);
	pServerDE->WriteToMessageFloat(hWrite, m_fInnerRadius);
	pServerDE->WriteToMessageByte(hWrite, m_nVolume);
	pServerDE->WriteToMessageByte(hWrite, m_bAmbient);
	pServerDE->WriteToMessageByte(hWrite, m_bFileStream);
	pServerDE->WriteToMessageByte(hWrite, m_nPriority);
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	SoundFX::Load
//
//	PURPOSE:	Load the object
//
// ----------------------------------------------------------------------- //

void SoundFX::Load(HMESSAGEREAD hRead, DDWORD dwLoadFlags)
{
	CServerDE* pServerDE = GetServerDE();
	if (!pServerDE || !hRead) return;

	m_byState			= pServerDE->ReadFromMessageByte(hRead);
	m_hstrRampUpSound	= pServerDE->ReadFromMessageHString(hRead);
	m_hstrRampDownSound	= pServerDE->ReadFromMessageHString(hRead);
	m_hstrSound			= pServerDE->ReadFromMessageHString(hRead);

	m_fOuterRadius		= pServerDE->ReadFromMessageFloat(hRead);
	m_fInnerRadius		= pServerDE->ReadFromMessageFloat(hRead);
	m_nVolume			= pServerDE->ReadFromMessageByte(hRead);
	m_bAmbient			= pServerDE->ReadFromMessageByte(hRead);
	m_bFileStream		= pServerDE->ReadFromMessageByte(hRead);
	m_nPriority			= pServerDE->ReadFromMessageByte(hRead);

	// Start the sound playing..
	m_hsndSound = DNULL;

	UpdateSound();

	pServerDE->SetNextUpdate( m_hObject, 0.0f );
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	SoundFX::CacheFiles
//
//	PURPOSE:	Cache resources used by the object
//
// ----------------------------------------------------------------------- //

void SoundFX::CacheFiles()
{
	CServerDE* pServerDE = GetServerDE();
	if (!pServerDE) return;

	// {MD 9/23/98}
	if(!(pServerDE->GetServerFlags() & SS_CACHING))
		return;

	char* pFile = DNULL;

	if (m_hstrRampUpSound)
	{
		pFile = g_pServerDE->GetStringData(m_hstrRampUpSound);
		if (pFile)
		{
			 g_pServerDE->CacheFile(FT_SOUND ,pFile);
		}
	}

	if (m_hstrRampDownSound)
	{
		pFile = g_pServerDE->GetStringData(m_hstrRampDownSound);
		if (pFile)
		{
			 g_pServerDE->CacheFile(FT_SOUND ,pFile);
		}
	}

	if (m_hstrSound)
	{
		pFile = g_pServerDE->GetStringData(m_hstrSound);
		if (pFile)
		{
			 g_pServerDE->CacheFile(FT_SOUND ,pFile);
		}
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -