Move git root from Client/ to src/ to track all source code: - Client: Game client source (moved to Client/Client/) - Server: Game server source - GameTools: Development tools - CryptoSource: Encryption utilities - database: Database scripts - Script: Game scripts - rylCoder_16.02.2008_src: Legacy coder tools - GMFont, Game: Additional resources 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
938 lines
22 KiB
C++
938 lines
22 KiB
C++
// SectorSoundMap.cpp: implementation of the CSectorSoundMap class.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#include "SectorSoundMap.h"
|
|
#include "AmbienceStruct.h"
|
|
#include "SceneManager.h"
|
|
#include "DirectSound.h"
|
|
#include "SoundBuffer.h"
|
|
#include "StreamBuffer.h"
|
|
#include <windows.h>
|
|
#include <vector>
|
|
#include <algorithm>
|
|
#include <set>
|
|
#include <string>
|
|
#include <exception>
|
|
#include "BaseDataDefine.h"
|
|
|
|
#define MAXSECTOR_X 30 //내가 임시로 정해놓았음.
|
|
#define MAXSECTOR_Y 30 //이 값이 부족하면 나중에 늘려줄 것.
|
|
|
|
typedef CSectorSoundMap::AMBIENCELIST AMBIENCELIST;
|
|
typedef CSectorSoundMap::AMBIENCELIST::iterator AMBIENCE_ITERATOR;
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
//
|
|
|
|
const char * FindSoundFileInList( float, WAVEFILELIST & );
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
//
|
|
|
|
struct SScheduleSound
|
|
{
|
|
float fTime;
|
|
tString strFilename;
|
|
SAmbience * pAmbience;
|
|
|
|
|
|
SScheduleSound()
|
|
: fTime( 0 ), strFilename(), pAmbience( NULL )
|
|
{}
|
|
|
|
SScheduleSound( float time, tString & filename, SAmbience * pAmb )
|
|
: fTime( time ), strFilename( filename ), pAmbience( pAmb )
|
|
{}
|
|
|
|
bool operator<( const SScheduleSound & rhs ) const
|
|
{
|
|
return fTime < rhs.fTime;
|
|
}
|
|
bool operator>( const SScheduleSound & rhs ) const
|
|
{
|
|
return fTime > rhs.fTime;
|
|
}
|
|
};
|
|
|
|
struct SSoundList
|
|
{
|
|
CSectorSoundMap::AMBIENCELIST ambienceList;
|
|
CSectorSoundMap::SCHEDULESOUNDLIST scheduleSoundList;
|
|
};
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Construction/Destruction
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
void CheckSectorIndex( int & sectorX, int & sectorY )
|
|
{
|
|
if( sectorX >= MAXSECTOR_X || sectorY >= MAXSECTOR_Y )
|
|
{
|
|
if( sectorX >= MAXSECTOR_X )
|
|
sectorX = MAXSECTOR_X - 1;
|
|
if( sectorY >= MAXSECTOR_Y )
|
|
sectorY = MAXSECTOR_Y - 1;
|
|
}
|
|
|
|
if( sectorX < 0 )
|
|
sectorX = 0;
|
|
if( sectorY < 0 )
|
|
sectorY = 0;
|
|
}
|
|
|
|
CSectorSoundMap::CSectorSoundMap( HWND hWnd, DWORD dwFlag )
|
|
: m_pSoundAssets( new SOUNDASSETS )
|
|
, m_aaSoundList( new SSoundList*[MAXSECTOR_X] )
|
|
, m_iCurrentScheduleSound( 0 )
|
|
, m_DSound( CDirectSound::GetInstance() )
|
|
, m_pSoundBuffers( new SOUNDBUFFERS )
|
|
, m_iCurrentSectorX( 0 )
|
|
, m_iCurrentSectorY( 0 )
|
|
, m_nEvent( 0 )
|
|
, m_arrEvent( new HANDLE[m_nEvent] )
|
|
, m_arrEventIndexes( new int[m_nEvent] )
|
|
, m_fPickedX( 0.0f )
|
|
, m_fPickedY( 0.0f )
|
|
, m_fPickedZ( 0.0f )
|
|
{
|
|
if( m_DSound.GetDS() == NULL )
|
|
m_DSound.Create( hWnd, dwFlag );
|
|
|
|
for( int i = 0; i < MAXSECTOR_X; i++ )
|
|
{
|
|
m_aaSoundList[i] = new SSoundList[MAXSECTOR_Y];
|
|
}
|
|
m_DSound.SetRolloff( 3.0f );
|
|
}
|
|
|
|
CSectorSoundMap::CSectorSoundMap( IDirectSound8 * pDSound )
|
|
: m_pSoundAssets( new SOUNDASSETS )
|
|
, m_aaSoundList( new SSoundList*[MAXSECTOR_X] )
|
|
, m_iCurrentScheduleSound( 0 )
|
|
, m_DSound( CDirectSound::GetInstance() )
|
|
, m_pSoundBuffers( new SOUNDBUFFERS )
|
|
, m_iCurrentSectorX( 0 )
|
|
, m_iCurrentSectorY( 0 )
|
|
, m_nEvent( 0 )
|
|
, m_arrEvent( new HANDLE[m_nEvent] )
|
|
, m_arrEventIndexes( new int[m_nEvent] )
|
|
, m_fPickedX( 0.0f )
|
|
, m_fPickedY( 0.0f )
|
|
, m_fPickedZ( 0.0f )
|
|
{
|
|
m_DSound.Create( pDSound );
|
|
|
|
for( int i = 0; i < MAXSECTOR_X; i++ )
|
|
{
|
|
m_aaSoundList[i] = new SSoundList[MAXSECTOR_Y];
|
|
}
|
|
}
|
|
|
|
|
|
|
|
CSectorSoundMap & CSectorSoundMap::GetInstance( HWND hWnd, DWORD dwFlag )
|
|
{
|
|
static CSectorSoundMap instance( hWnd, dwFlag );
|
|
return instance;
|
|
}
|
|
|
|
/*
|
|
CSectorSoundMap & CSectorSoundMap::GetInstance( IDirectSound8 * pDSound )
|
|
{
|
|
static CSectorSoundMap instance( pDSound );
|
|
return instance;
|
|
}
|
|
*/
|
|
|
|
IDirectSound8 * CSectorSoundMap::GetDS()
|
|
{
|
|
return m_DSound.GetDS();
|
|
}
|
|
|
|
CSectorSoundMap::~CSectorSoundMap()
|
|
{
|
|
Destroy();
|
|
|
|
delete m_pSoundAssets;
|
|
for( int i = 0; i < MAXSECTOR_X; i++ )
|
|
{
|
|
delete [] m_aaSoundList[i];
|
|
}
|
|
delete [] m_aaSoundList;
|
|
delete m_pSoundBuffers;
|
|
delete [] m_arrEvent;
|
|
delete [] m_arrEventIndexes;
|
|
}
|
|
|
|
|
|
static void Error( const char * szMsg, ... )
|
|
{
|
|
va_list varg;
|
|
va_start( varg, szMsg );
|
|
|
|
char szBuffer[256];
|
|
|
|
vsprintf( szBuffer, szMsg, varg );
|
|
|
|
MessageBox( NULL, szBuffer, "Error!!", MB_OK );
|
|
}
|
|
|
|
|
|
void CSectorSoundMap::Create( const char * szFilename )
|
|
{
|
|
char szBuffer[256];
|
|
|
|
Destroy();
|
|
|
|
FILE * fp = fopen( szFilename, "rb" );
|
|
|
|
if( fp == NULL )
|
|
{
|
|
Error( "Cannot open file : %s", szFilename );
|
|
return;
|
|
}
|
|
|
|
|
|
//SoundAsset들을 로드
|
|
int AssetSize = 0, nWaveFile = 0;
|
|
fread( &AssetSize, sizeof( int ), 1, fp ); //Asset의 개수
|
|
|
|
for( int i = 0; i < AssetSize; i++ )
|
|
{
|
|
m_pSoundAssets->push_back( SSoundAsset() );
|
|
SSoundAsset & rAsset = m_pSoundAssets->back();
|
|
|
|
int nameLen = 0;
|
|
fread( &nameLen, sizeof( int ), 1, fp ); //Asset Name의 글자 수
|
|
fread( szBuffer, sizeof( char ), nameLen, fp ); //Asset Name 로드
|
|
szBuffer[ nameLen ] = '\0';
|
|
rAsset.m_Name = szBuffer;
|
|
|
|
fread( &rAsset.m_eTrigger, sizeof( SSoundAsset::eTrigger ), 1, fp );
|
|
fread( &rAsset.m_b3DSound, sizeof( bool ), 1, fp );
|
|
|
|
fread( &nWaveFile, sizeof( int ), 1, fp ); //WaveFile의 개수
|
|
|
|
for( int j = 0; j < nWaveFile; j++ )
|
|
{
|
|
rAsset.m_pWaveFileList->push_back( WAVEFILE( 0.0f, "" ) );
|
|
WAVEFILE & rWaveFile = rAsset.m_pWaveFileList->back();
|
|
|
|
float tempFloat = 0.0f;
|
|
fread( &tempFloat, sizeof( float ), 1, fp );
|
|
rWaveFile.first = tempFloat;
|
|
|
|
int stringLen = 0;
|
|
fread( &stringLen, sizeof( int ), 1, fp ); //WaveFile의 글자 수
|
|
fread( szBuffer, sizeof( char ), stringLen, fp );
|
|
szBuffer[ stringLen ] = '\0';
|
|
|
|
rWaveFile.second = szBuffer;
|
|
}
|
|
}
|
|
|
|
|
|
//ambience들을 로드
|
|
int nAmbiences = 0;
|
|
fread( &nAmbiences, sizeof( int ), 1, fp );
|
|
|
|
int loadCount = 0;
|
|
|
|
for( int n = 0; n < nAmbiences; n++ )
|
|
{
|
|
SAmbience tempAmbience;
|
|
|
|
fread( &tempAmbience.m_SoundAssetID, sizeof( int ), 1, fp );
|
|
fread( &tempAmbience.m_fPosX, sizeof( float ), 1, fp );
|
|
fread( &tempAmbience.m_fPosY, sizeof( float ), 1, fp );
|
|
fread( &tempAmbience.m_fPosZ, sizeof( float ), 1, fp );
|
|
fread( &tempAmbience.m_fMinDistance, sizeof( float ), 1, fp );
|
|
fread( &tempAmbience.m_fMaxDistance, sizeof( float ), 1, fp );
|
|
|
|
AddAmbience( tempAmbience, false );
|
|
|
|
loadCount++;
|
|
}
|
|
|
|
assert( nAmbiences == loadCount );
|
|
|
|
ResetSectorSound( m_iCurrentSectorX, m_iCurrentSectorY );
|
|
|
|
fclose( fp );
|
|
}
|
|
|
|
void CSectorSoundMap::Save( const char * szFilename )
|
|
{
|
|
FILE * fp = fopen( szFilename, "wb" );
|
|
|
|
if( fp == NULL )
|
|
{
|
|
Error( "Cannot open file : %s", szFilename );
|
|
return;
|
|
}
|
|
|
|
//SoundAsset들 저장
|
|
int size = m_pSoundAssets->size(); //Asset의 개수
|
|
fwrite( &size, sizeof( int ), 1, fp );
|
|
|
|
for( SOUNDASSETS::iterator i = m_pSoundAssets->begin(); i != m_pSoundAssets->end(); i++ )
|
|
{
|
|
int nameLen = i->m_Name.size();
|
|
fwrite( &nameLen, sizeof( int ), 1, fp ); //Asset Name의 글자 수
|
|
fwrite( i->m_Name.c_str(), sizeof( char ), nameLen, fp ); //Asset Name 저장
|
|
fwrite( &i->m_eTrigger, sizeof( SSoundAsset::eTrigger ), 1, fp );
|
|
fwrite( &i->m_b3DSound, sizeof( bool ), 1, fp );
|
|
|
|
size = i->m_pWaveFileList->size();
|
|
fwrite( &size, sizeof( int ), 1, fp ); //WaveFile의 개수
|
|
|
|
for( WAVEFILELIST::iterator i2 = i->m_pWaveFileList->begin();
|
|
i2 != i->m_pWaveFileList->end(); i2++ )
|
|
{
|
|
float fTime = i2->first;
|
|
fwrite( &fTime, sizeof( float ), 1, fp );
|
|
int stringLen = i2->second.size();
|
|
fwrite( &stringLen, sizeof( int ), 1, fp ); //WaveFile의 글자 수
|
|
fwrite( i2->second.c_str(), sizeof( char ), stringLen, fp );
|
|
}
|
|
}
|
|
|
|
int nAmbiences = GetWholeSectorAmbienceNum();
|
|
fwrite( &nAmbiences, sizeof( int ), 1, fp ); //ambience들의 총합
|
|
|
|
int saveCount = 0;
|
|
|
|
//Ambience들을 저장
|
|
for( int sx = 0; sx < MAXSECTOR_X; sx++ )
|
|
{
|
|
for( int sy = 0; sy < MAXSECTOR_Y; sy++ )
|
|
{
|
|
AMBIENCELIST & ambList = m_aaSoundList[sx][sy].ambienceList;
|
|
|
|
for( AMBIENCELIST::iterator it = ambList.begin(); it != ambList.end(); it++ )
|
|
{
|
|
SAmbience & ambience = *it;
|
|
fwrite( &ambience.m_SoundAssetID, sizeof( int ), 1, fp );
|
|
fwrite( &ambience.m_fPosX, sizeof( float ), 1, fp );
|
|
fwrite( &ambience.m_fPosY, sizeof( float ), 1, fp );
|
|
fwrite( &ambience.m_fPosZ, sizeof( float ), 1, fp );
|
|
fwrite( &ambience.m_fMinDistance, sizeof( float ), 1, fp );
|
|
fwrite( &ambience.m_fMaxDistance, sizeof( float ), 1, fp );
|
|
|
|
saveCount++;
|
|
}
|
|
}
|
|
}
|
|
|
|
assert( nAmbiences == saveCount );
|
|
|
|
fclose( fp );
|
|
}
|
|
|
|
void CSectorSoundMap::DestroyAllSoundBuffers()
|
|
{
|
|
for( SOUNDBUFFERS::iterator i = m_pSoundBuffers->begin(); i != m_pSoundBuffers->end(); i++ )
|
|
{
|
|
delete *i;
|
|
}
|
|
m_pSoundBuffers->clear();
|
|
}
|
|
|
|
void CSectorSoundMap::Destroy()
|
|
{
|
|
m_pSoundAssets->clear();
|
|
|
|
for( int sx = 0; sx < MAXSECTOR_X; sx++ )
|
|
{
|
|
for( int sy = 0; sy < MAXSECTOR_Y; sy++ )
|
|
{
|
|
m_aaSoundList[sx][sy].ambienceList.clear();
|
|
m_aaSoundList[sx][sy].scheduleSoundList.clear();
|
|
}
|
|
}
|
|
|
|
DestroyAllSoundBuffers();
|
|
|
|
m_iCurrentSectorX = m_iCurrentSectorY = 0;
|
|
|
|
m_iCurrentScheduleSound = 0;
|
|
}
|
|
|
|
|
|
void CSectorSoundMap::AppendSoundAsset( SSoundAsset & Asset )
|
|
{
|
|
m_pSoundAssets->push_back( Asset );
|
|
}
|
|
|
|
void CSectorSoundMap::GetSoundAsset( int index, SSoundAsset & Asset )
|
|
{
|
|
try
|
|
{
|
|
Asset = m_pSoundAssets->at( index );
|
|
}
|
|
catch ( exception & e )
|
|
{
|
|
MessageBox( NULL, e.what(), "Error!!", MB_OK );
|
|
}
|
|
}
|
|
|
|
void CSectorSoundMap::SetSoundAsset( int index, SSoundAsset & Asset )
|
|
{
|
|
try
|
|
{
|
|
SSoundAsset & Selected = m_pSoundAssets->at( index );
|
|
Selected = Asset;
|
|
|
|
RebuildScheduleSound( m_aaSoundList[ m_iCurrentSectorX ][ m_iCurrentSectorY ] );
|
|
}
|
|
catch ( exception & e )
|
|
{
|
|
MessageBox( NULL, e.what(), "Error!!", MB_OK );
|
|
}
|
|
}
|
|
|
|
void CSectorSoundMap::DeleteSoundAsset( int index )
|
|
{
|
|
int curIndex = 0;
|
|
|
|
for( SOUNDASSETS::iterator i = m_pSoundAssets->begin(); i != m_pSoundAssets->end(); )
|
|
{
|
|
if( curIndex++ == index )
|
|
{
|
|
i = m_pSoundAssets->erase( i );
|
|
continue;
|
|
}
|
|
i++;
|
|
}
|
|
}
|
|
|
|
int CSectorSoundMap::GetSoundAssetCount()
|
|
{
|
|
return m_pSoundAssets->size();
|
|
}
|
|
|
|
|
|
int CSectorSoundMap::GetAmbienceCount( int SectorX, int SectorY )
|
|
{
|
|
if( SectorX >= MAXSECTOR_X || SectorY >= MAXSECTOR_Y )
|
|
return 0;
|
|
|
|
if( SectorX < 0 || SectorY < 0 )
|
|
return 0;
|
|
|
|
SSoundList & SoundList = m_aaSoundList[SectorX][SectorY];
|
|
CheckSectorIndex( SectorX, SectorY );
|
|
return SoundList.ambienceList.size();
|
|
}
|
|
|
|
SAmbience * CSectorSoundMap::GetAmbience( int SectorX, int SectorY, int index )
|
|
{
|
|
SSoundList & SoundList = m_aaSoundList[SectorX][SectorY];
|
|
CheckSectorIndex( SectorX, SectorY );
|
|
|
|
AMBIENCELIST & ambList = SoundList.ambienceList;
|
|
int index2 = 0;
|
|
|
|
for( AMBIENCELIST::iterator i = ambList.begin(); i != ambList.end(); i++, index2++ )
|
|
{
|
|
if( index == index2 )
|
|
return &(*i);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
//x, y, z좌표에 가장 가까운 ambience를 구한다.
|
|
|
|
AMBIENCE_ITERATOR GetClosestAmbience( AMBIENCELIST & ambList, float x, float y, float z )
|
|
{
|
|
float fLen = 10.0f;
|
|
AMBIENCE_ITERATOR it_amb = ambList.end();
|
|
|
|
for( AMBIENCELIST::iterator i = ambList.begin(); i != ambList.end(); i++ )
|
|
{
|
|
vector3 tempVector( x - i->m_fPosX, y - i->m_fPosY, z - i->m_fPosZ );
|
|
|
|
float length = tempVector.GetLens();
|
|
if( fLen >= length )
|
|
{
|
|
fLen = length;
|
|
it_amb = i;
|
|
}
|
|
}
|
|
return it_amb;
|
|
}
|
|
|
|
SAmbience * CSectorSoundMap::GetAmbience( float x, float y, float z )
|
|
{
|
|
int indexX = (int)(x/SECTORSIZE);
|
|
int indexY = (int)(z/SECTORSIZE);
|
|
|
|
CheckSectorIndex( indexX, indexY );
|
|
|
|
AMBIENCELIST & ambList = m_aaSoundList[ indexX ][ indexY ].ambienceList;
|
|
|
|
AMBIENCE_ITERATOR it = GetClosestAmbience( ambList, x, y, z );
|
|
if( it == ambList.end() )
|
|
return NULL;
|
|
|
|
return &(*it);
|
|
}
|
|
|
|
|
|
void CSectorSoundMap::PickAmbience( float x, float y, float z )
|
|
{
|
|
m_fPickedX = x;
|
|
m_fPickedY = y;
|
|
m_fPickedZ = z;
|
|
}
|
|
|
|
|
|
void CSectorSoundMap::AddAmbience( SAmbience & ambience, bool bReset )
|
|
{
|
|
try {
|
|
|
|
if( ambience.m_fPosX == 0.0f && ambience.m_fPosZ == 0.0f )
|
|
return;
|
|
|
|
int SectorX = ambience.m_fPosX / SECTORSIZE;
|
|
int SectorY = ambience.m_fPosZ / SECTORSIZE;
|
|
|
|
//섹터별 Ambience 리스트에 먼저 저장을 한다.
|
|
SSoundList & SoundList = m_aaSoundList[SectorX][SectorY];
|
|
SoundList.ambienceList.push_back( ambience );
|
|
SAmbience & addedAmbience = SoundList.ambienceList.back();
|
|
|
|
//시간에 따라 변경되는 사운드는 fTime으로 정렬해서 들어가도록 삽입한다.
|
|
SCHEDULESOUNDLIST & scSoundList = SoundList.scheduleSoundList;
|
|
|
|
SSoundAsset & soundAsset = m_pSoundAssets->at( ambience.m_SoundAssetID );
|
|
|
|
for( WAVEFILELIST::iterator i = soundAsset.m_pWaveFileList->begin(); i != soundAsset.m_pWaveFileList->end(); i++ )
|
|
{
|
|
scSoundList.push_back( SScheduleSound( i->first, i->second, &addedAmbience ) );
|
|
}
|
|
|
|
sort( scSoundList.begin(), scSoundList.end() );
|
|
|
|
//현재 섹터의 Ambience일 경우 사운드들을 새로 세팅한다.
|
|
if( SectorX == m_iCurrentSectorX && SectorY == m_iCurrentSectorY )
|
|
{
|
|
if( bReset )
|
|
ResetSectorSound( SectorX, SectorY );
|
|
return;
|
|
}
|
|
|
|
}
|
|
catch ( exception & e )
|
|
{
|
|
MessageBox( NULL, e.what(), "Error!!", MB_OK );
|
|
}
|
|
}
|
|
|
|
void CSectorSoundMap::MoveAmbience( float destX, float destY, float destZ )
|
|
{
|
|
int indexX = (int)(m_fPickedX/SECTORSIZE);
|
|
int indexY = (int)(m_fPickedZ/SECTORSIZE);
|
|
int destSectorX = (int)(destX/SECTORSIZE);
|
|
int destSectorY = (int)(destZ/SECTORSIZE);
|
|
|
|
if( indexX != destSectorX || indexY != destSectorY ) //다른 섹터로 옮겨질 경우
|
|
{
|
|
SAmbience Amb = *GetAmbience( m_fPickedX, m_fPickedY, m_fPickedZ );
|
|
DeleteAmbience( m_fPickedX, m_fPickedY, m_fPickedZ );
|
|
Amb.m_fPosX = destX;
|
|
Amb.m_fPosY = destY;
|
|
Amb.m_fPosZ = destZ;
|
|
AddAmbience( Amb );
|
|
return;
|
|
}
|
|
|
|
CheckSectorIndex( indexX, indexY );
|
|
|
|
AMBIENCELIST & ambList = m_aaSoundList[ indexX ][ indexY ].ambienceList;
|
|
|
|
AMBIENCE_ITERATOR it = GetClosestAmbience( ambList, m_fPickedX, m_fPickedY, m_fPickedZ );
|
|
|
|
if( it != ambList.end() )
|
|
{
|
|
it->m_fPosX = destX;
|
|
it->m_fPosY = destY;
|
|
it->m_fPosZ = destZ;
|
|
|
|
m_fPickedX = destX;
|
|
m_fPickedY = destY;
|
|
m_fPickedZ = destZ;
|
|
}
|
|
RebuildScheduleSound( m_aaSoundList[ indexX ][ indexY ] );
|
|
|
|
//현재 섹터의 Ambience일 경우 사운드들을 새로 세팅한다.
|
|
if( indexX == m_iCurrentSectorX && indexY == m_iCurrentSectorY )
|
|
{
|
|
// ResetSectorSound( indexX, indexY );
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
long CSectorSoundMap::DeleteAmbience( float x, float y, float z )
|
|
{
|
|
int indexX=(int)(x/SECTORSIZE);
|
|
int indexY=(int)(z/SECTORSIZE);
|
|
long objID = -1;
|
|
|
|
try {
|
|
CheckSectorIndex( indexX, indexY );
|
|
|
|
AMBIENCELIST & ambList = m_aaSoundList[ indexX ][ indexY ].ambienceList;
|
|
|
|
AMBIENCE_ITERATOR it = GetClosestAmbience( ambList, x, y, z );
|
|
|
|
if( it != ambList.end() )
|
|
{
|
|
if( it->iSoundBufferIndex >= 0 && it->iSoundBufferIndex < m_pSoundBuffers->size() )
|
|
{
|
|
CSoundBuffer * pSoundBuffer = m_pSoundBuffers->at( it->iSoundBufferIndex );
|
|
pSoundBuffer->Destroy();
|
|
}
|
|
objID = it->lObjectSceneID;
|
|
ambList.erase( it );
|
|
}
|
|
RebuildScheduleSound( m_aaSoundList[ indexX ][ indexY ] );
|
|
|
|
//현재 섹터의 Ambience일 경우 사운드들을 새로 세팅한다.
|
|
if( indexX == m_iCurrentSectorX && indexY == m_iCurrentSectorY )
|
|
{
|
|
ResetSectorSound( indexX, indexY );
|
|
}
|
|
}
|
|
catch ( exception & e )
|
|
{
|
|
MessageBox( NULL, e.what(), "Error!!", MB_OK );
|
|
}
|
|
return objID;
|
|
}
|
|
|
|
void CSectorSoundMap::RebuildScheduleSound( SSoundList & SoundList )
|
|
{
|
|
try {
|
|
|
|
SoundList.scheduleSoundList.clear();
|
|
|
|
for( AMBIENCELIST::iterator i = SoundList.ambienceList.begin(); i != SoundList.ambienceList.end(); i++ )
|
|
{
|
|
SSoundAsset & soundAsset = m_pSoundAssets->at( i->m_SoundAssetID );
|
|
|
|
for( WAVEFILELIST::iterator j = soundAsset.m_pWaveFileList->begin(); j != soundAsset.m_pWaveFileList->end(); j++ )
|
|
{
|
|
SoundList.scheduleSoundList.push_back( SScheduleSound( j->first, j->second, &(*i) ) );
|
|
}
|
|
}
|
|
sort( SoundList.scheduleSoundList.begin(), SoundList.scheduleSoundList.end() );
|
|
m_iCurrentScheduleSound = 0;
|
|
|
|
}
|
|
catch ( exception & e )
|
|
{
|
|
MessageBox( NULL, e.what(), "Error!!", MB_OK );
|
|
}
|
|
}
|
|
|
|
//매 프레임마다 검사를 하며 사운드 변화를 처리
|
|
void CSectorSoundMap::UpdateListener( float dirX, float dirY, float dirZ, float upX, float upY, float upZ, float x, float y, float z )
|
|
{
|
|
static bool bUpdate = true;
|
|
|
|
if( !bUpdate )
|
|
return;
|
|
|
|
try {
|
|
|
|
if( (fabs(dirX) <= 0.0000001f) && (fabs(dirY) <= 0.0000001f) && (fabs(dirZ) <= 0.0000001f))
|
|
{
|
|
dirX = 0.0f;
|
|
dirY = 0.0f;
|
|
dirZ = 1.0f;
|
|
|
|
}
|
|
|
|
if( (fabs(upX) <= 0.0000001f) && (fabs(upY) <= 0.0000001f) && (fabs(upZ) <= 0.0000001f))
|
|
{
|
|
upX = 0.0f;
|
|
upY = 1.0f;
|
|
upZ = 0.0f;
|
|
|
|
}
|
|
|
|
static float old_dirX, old_dirY, old_dirZ, old_x, old_y, old_z;
|
|
static float oldWeatherTime = 0.0f;
|
|
|
|
HandleStreamEvents();
|
|
|
|
if( old_dirX != dirX || old_dirY != dirY || old_dirZ != dirZ )
|
|
{
|
|
m_DSound.Set3DOrientation( dirX, dirY, dirZ, upX, upY, upZ );
|
|
old_dirX = dirX;
|
|
old_dirY = dirY;
|
|
old_dirZ = dirZ;
|
|
}
|
|
|
|
if( old_x != x || old_y != y || old_z != z )
|
|
{
|
|
m_DSound.SetPosition( x, y, z );
|
|
old_x = x;
|
|
old_y = y;
|
|
old_z = z;
|
|
}
|
|
|
|
int SectorX = x / SECTORSIZE;
|
|
int SectorY = z / SECTORSIZE;
|
|
|
|
//섹터가 바뀌었을 때에는 사운드들을 새로 세팅한다.
|
|
if( SectorX != m_iCurrentSectorX || SectorY != m_iCurrentSectorY )
|
|
{
|
|
ResetSectorSound( SectorX, SectorY );
|
|
return;
|
|
}
|
|
|
|
float CurrentTime = CSceneManager::GetWeatherTime();
|
|
|
|
if( oldWeatherTime > CurrentTime )
|
|
m_iCurrentScheduleSound = 0;
|
|
oldWeatherTime = CurrentTime;
|
|
|
|
SCHEDULESOUNDLIST & scSoundList = m_aaSoundList[ m_iCurrentSectorX ][ m_iCurrentSectorY ].scheduleSoundList;
|
|
|
|
if( m_iCurrentScheduleSound >= scSoundList.size() || m_iCurrentScheduleSound < 0 )
|
|
return;
|
|
|
|
//현재 시간이 현재 가리키고 있는 스케쥴 사운드의 시간을 지났으면
|
|
while( true )
|
|
{
|
|
if( m_iCurrentScheduleSound >= scSoundList.size() || m_iCurrentScheduleSound < 0 )
|
|
break;
|
|
|
|
if( CurrentTime <= scSoundList[ m_iCurrentScheduleSound ].fTime )
|
|
break;
|
|
|
|
//그 스케쥴 사운드에 따라 사운드 화일을 교체한다.
|
|
SScheduleSound & sc = scSoundList[ m_iCurrentScheduleSound ];
|
|
SSoundAsset & sndAsset = m_pSoundAssets->at( sc.pAmbience->m_SoundAssetID );
|
|
|
|
if( sndAsset.m_iSndBufIndex < 0 || sndAsset.m_iSndBufIndex >= m_pSoundBuffers->size() )
|
|
{
|
|
m_pSoundBuffers->push_back( new CStreamBuffer );
|
|
sndAsset.m_iSndBufIndex = m_pSoundBuffers->size() - 1;
|
|
}
|
|
|
|
if( sndAsset.m_iSndBufIndex >= 0 && sndAsset.m_iSndBufIndex < m_pSoundBuffers->size() )
|
|
{
|
|
CSoundBuffer * pBuf = m_pSoundBuffers->at( sndAsset.m_iSndBufIndex );
|
|
|
|
string strFilename = SOUNDFILEPATH;
|
|
strFilename += sc.strFilename.c_str();
|
|
|
|
if( !pBuf->IsSameFile( strFilename.c_str() ) )
|
|
{
|
|
|
|
pBuf->Create( m_DSound.GetDS(), strFilename.c_str(), sndAsset.m_b3DSound, 30 );
|
|
}
|
|
|
|
int index = pBuf->Play( true );
|
|
pBuf->SetPosition( index, sc.pAmbience->m_fPosX, sc.pAmbience->m_fPosY, sc.pAmbience->m_fPosZ );
|
|
pBuf->SetDistance( index, sc.pAmbience->m_fMinDistance, sc.pAmbience->m_fMaxDistance );
|
|
sc.pAmbience->iSoundBufferIndex = index;
|
|
ResetEventArray();
|
|
}
|
|
|
|
m_iCurrentScheduleSound++;
|
|
}
|
|
}
|
|
catch ( exception & e )
|
|
{
|
|
MessageBox( NULL, e.what(), "Error!!", MB_OK );
|
|
MessageBox( NULL, "Ambience 사운드가 Off됩니다.", "Warning", MB_OK );
|
|
bUpdate = false;
|
|
}
|
|
}
|
|
|
|
void CSectorSoundMap::ResetSectorSound( int sectorX, int sectorY )
|
|
{
|
|
try {
|
|
|
|
CheckSectorIndex( sectorX, sectorY );
|
|
|
|
float CurrentTime = CSceneManager::GetWeatherTime();
|
|
|
|
SSoundList & Sound = m_aaSoundList[sectorX][sectorY];
|
|
|
|
for( int i = 0; i < m_pSoundAssets->size(); i++ )
|
|
{
|
|
SSoundAsset & sndAsset = m_pSoundAssets->at( i );
|
|
sndAsset.m_iSndBufIndex = -1;
|
|
}
|
|
|
|
DestroyAllSoundBuffers();
|
|
|
|
|
|
|
|
for( AMBIENCELIST::iterator j = Sound.ambienceList.begin();
|
|
j != Sound.ambienceList.end();
|
|
j++ )
|
|
{
|
|
SSoundAsset & sndAsset = m_pSoundAssets->at( j->m_SoundAssetID );
|
|
|
|
if( sndAsset.m_iSndBufIndex >= 0 && sndAsset.m_iSndBufIndex < m_pSoundBuffers->size() )
|
|
{
|
|
CSoundBuffer * pBuf = m_pSoundBuffers->at( sndAsset.m_iSndBufIndex );
|
|
int index = pBuf->Play( true );
|
|
pBuf->SetPosition( index, j->m_fPosX, j->m_fPosY, j->m_fPosZ );
|
|
pBuf->SetDistance( index, j->m_fMinDistance, j->m_fMaxDistance );
|
|
|
|
j->iSoundBufferIndex = index;
|
|
}
|
|
else
|
|
{
|
|
const char * szSoundFile = FindSoundFileInList( CurrentTime, *sndAsset.m_pWaveFileList );
|
|
if( szSoundFile == NULL )
|
|
{
|
|
j++;
|
|
continue;
|
|
}
|
|
|
|
string strFilename = SOUNDFILEPATH;
|
|
strFilename += szSoundFile;
|
|
CSoundBuffer * pBuf = new CStreamBuffer;
|
|
m_pSoundBuffers->push_back( pBuf );
|
|
sndAsset.m_iSndBufIndex = m_pSoundBuffers->size() - 1;
|
|
pBuf->Create( m_DSound.GetDS(), strFilename.c_str(), sndAsset.m_b3DSound, 30 );
|
|
int index = pBuf->Play( true );
|
|
pBuf->SetPosition( index, j->m_fPosX, j->m_fPosY, j->m_fPosZ );
|
|
pBuf->SetDistance( index, j->m_fMinDistance, j->m_fMaxDistance );
|
|
|
|
j->iSoundBufferIndex = index;
|
|
|
|
}
|
|
}
|
|
|
|
for( m_iCurrentScheduleSound = 0;
|
|
m_iCurrentScheduleSound < Sound.scheduleSoundList.size();
|
|
m_iCurrentScheduleSound++ )
|
|
{
|
|
if( Sound.scheduleSoundList[ m_iCurrentScheduleSound ].fTime > CurrentTime )
|
|
break;
|
|
}
|
|
m_iCurrentSectorX = sectorX;
|
|
m_iCurrentSectorY = sectorY;
|
|
|
|
ResetEventArray();
|
|
|
|
}
|
|
catch ( exception & e )
|
|
{
|
|
MessageBox( NULL, e.what(), "Error!!", MB_OK );
|
|
}
|
|
}
|
|
|
|
//fTime에 맞는 사운드 화일을 찾아냄
|
|
const char * FindSoundFileInList( float fTime, WAVEFILELIST & SoundFileList )
|
|
{
|
|
WAVEFILELIST::iterator i = SoundFileList.end();
|
|
|
|
do
|
|
{
|
|
i--;
|
|
if( i->first < fTime )
|
|
return i->second.c_str();
|
|
} while( i != SoundFileList.begin() );
|
|
|
|
if( i == SoundFileList.begin() )
|
|
{
|
|
if( SoundFileList.size() >= 1 )
|
|
return SoundFileList.back().second.c_str();
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
int CSectorSoundMap::GetWholeSectorAmbienceNum()
|
|
{
|
|
int totalSize = 0;
|
|
|
|
for( int sx = 0; sx < MAXSECTOR_X; sx++ )
|
|
{
|
|
for( int sy = 0; sy < MAXSECTOR_Y; sy++ )
|
|
{
|
|
totalSize += m_aaSoundList[sx][sy].ambienceList.size();
|
|
}
|
|
}
|
|
return totalSize;
|
|
}
|
|
|
|
void CSectorSoundMap::ResetEventArray()
|
|
{
|
|
try {
|
|
|
|
vector< int > tempArr;
|
|
|
|
for( int i = 0; i < m_pSoundBuffers->size(); i++ )
|
|
{
|
|
CSoundBuffer * pBuffer = m_pSoundBuffers->at( i );
|
|
|
|
if( pBuffer->GetEventNotify() != 0 )
|
|
tempArr.push_back( i );
|
|
}
|
|
|
|
m_nEvent = tempArr.size();
|
|
int arrSize = m_nEvent > 0 ? m_nEvent : 1;
|
|
|
|
delete [] m_arrEvent;
|
|
delete [] m_arrEventIndexes;
|
|
m_arrEvent = new HANDLE[ arrSize ];
|
|
m_arrEventIndexes = new int[ arrSize ];
|
|
|
|
for( i = 0; i < m_nEvent; i++ )
|
|
{
|
|
m_arrEventIndexes[i] = tempArr[i];
|
|
CSoundBuffer * pBuffer = m_pSoundBuffers->at( tempArr[i] );
|
|
m_arrEvent[i] = pBuffer->GetEventNotify();
|
|
}
|
|
|
|
}
|
|
catch ( exception & e )
|
|
{
|
|
MessageBox( NULL, e.what(), "Error!!", MB_OK );
|
|
}
|
|
}
|
|
|
|
void CSectorSoundMap::HandleStreamEvents()
|
|
{
|
|
try
|
|
{
|
|
|
|
if( m_nEvent <= 0 )
|
|
return;
|
|
|
|
DWORD dwResult = MsgWaitForMultipleObjects( m_nEvent, m_arrEvent, FALSE, 0, QS_ALLEVENTS );
|
|
|
|
if( dwResult >= WAIT_OBJECT_0 + 0 && dwResult < WAIT_OBJECT_0 + m_nEvent )
|
|
{
|
|
int index = dwResult - WAIT_OBJECT_0;
|
|
|
|
if( index >= 0 && index < m_pSoundBuffers->size() )
|
|
{
|
|
CSoundBuffer * pBuffer = m_pSoundBuffers->at( index );
|
|
|
|
pBuffer->HandleNotification();
|
|
}
|
|
}
|
|
}
|
|
catch ( exception & e )
|
|
{
|
|
MessageBox( NULL, e.what(), "Error!!", MB_OK );
|
|
}
|
|
}
|
|
|