
Sound parts are a new type of parts which you can use to directly add sounds via keyframes INTO the SFX! This is pretty helpful to reach a perfect "mixing" and timing of multiple(or single) sounds inside inside a SFX. If you are taking things serious and if you are working on good quality SFX, you'll need proper sounds! And those sounds can be used to give the perfect feeling in your game.
ATTENTION:
There is no guarantee that those source changes work 100% on your server files and i will NOT provide any support on how to add those. You are responsible on your own to add the given code properly according to the guides posted!
Without the source changes of the corresponding Features, those Features will NOT work for you!
Open your ..\_Common\sfxbase.h
Take a look at the following enum:
enum SFXPARTTYPE {
SFXPARTTYPE_BILL = 1,
SFXPARTTYPE_PARTICLE = 2,
SFXPARTTYPE_MESH = 3,
SFXPARTTYPE_CUSTOMMESH = 4
};
REPLACE it with this:
enum SFXPARTTYPE {
SFXPARTTYPE_BILL = 1,
SFXPARTTYPE_PARTICLE = 2,
SFXPARTTYPE_MESH = 3,
SFXPARTTYPE_CUSTOMMESH = 4,
#ifdef __LNB_SFX_PART_SOUNDS
SFXPARTTYPE_SOUND = 5, // Add this new type for sound parts
#endif //__LNB_SFX_PART_SOUNDS
};
Now look for the following:
class CSfxBase
Add the following ABOVE it:
#ifdef __LNB_SFX_PART_SOUNDS
class CSfxPartSound: public CSfxPart {
public:
CSfxPartSound();
~CSfxPartSound() {
}
// Override base class methods(actually not too sure if we need to overwrite them all, but just in case..)
virtual void Load(CResFile& file);
virtual void Load2(CResFile& file);
virtual void Load3(CResFile& file) {
};
virtual void OldLoad(CResFile& file);
#ifndef __WORLDSERVER
virtual void Render(D3DXVECTOR3 vPos, WORD nFrame, FLOAT fAngle, D3DXVECTOR3 vScale = D3DXVECTOR3(1.0f, 1.0f, 1.0f));
#endif
virtual void Render2(D3DXVECTOR3 vPos, WORD nFrame, D3DXVECTOR3 fAngle, D3DXVECTOR3 vScale = D3DXVECTOR3(1.0f, 1.0f, 1.0f));
private:
WORD m_lastPlayedFrame;
};
#endif //__LNB_SFX_PART_SOUNDS
Next, open your ..\_Common\sfxbase.cpp
Look for the following:
CSfxPart::CSfxPart() {
Ensure to add the following ABOVE it:
#ifdef __LNB_SFX_PART_SOUNDS
static std::map<std::string, DWORD> g_playingSounds;
static const DWORD SOUND_COOLDOWN_MS = 100; // Minimum time between sound replays(ms.)
#endif//__LNB_SFX_PART_SOUNDS
Now look for CSfxPart* CSfxBase::AddPart(SFXPARTTYPE nType) {
and scroll down until you see the following:
case SFXPARTTYPE_CUSTOMMESH:
{
pSfxPart = new CSfxPartCustomMesh;
break;
}
Place this UNDER it:
#ifdef __LNB_SFX_PART_SOUNDS
case SFXPARTTYPE_SOUND:
{
pSfxPart = new CSfxPartSound;
break;
}
#endif //__LNB_SFX_PART_SOUNDS
Next, jump to BOOL CSfxModel::Render(LPDIRECT3DDEVICE9 pd3dDevice, const D3DXMATRIX* pmWorld) {
and look for this:
case SFXPARTTYPE_CUSTOMMESH:
{
CSfxMng::m_pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
CSfxMng::m_pd3dDevice->SetFVF(D3DFVF_D3DSFXVERTEX);
pPart->Render(m_vPos, m_nCurFrame, m_vRotate.y, m_vScale);
CSfxMng::m_pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
}
break;
Place this UNDER it:
#ifdef __LNB_SFX_PART_SOUNDS
case SFXPARTTYPE_SOUND:
{
CSfxPartSound* pSoundPart = static_cast<CSfxPartSound*>(pPart);
if(pSoundPart)
{
pSoundPart->Render(m_vPos, m_nCurFrame, m_vRotate.y, m_vScale);
}
else
{
//You can remove this but for debugging purposes, you should keep this for your first try after implementing sound parts
g_WndMng.PutString("Failed to cast to CSfxPartSound :c");
}
}
break;
#endif //__LNB_SFX_PART_SOUNDS
Now scroll down to the very end of the sfxbase.cpp!
Then add this:
#ifdef __LNB_SFX_PART_SOUNDS
//Followed the same pattern of the already existing official weird SFX stuff...
CSfxPartSound::CSfxPartSound() {
m_nType = SFXPARTTYPE_SOUND;
m_lastPlayedFrame = 0xFFFF;
}
void CSfxPartSound::Load(CResFile& file) {
int i;
char strTemp[255];
int nStrLen;
file.Read(&nStrLen, sizeof(int));
file.Read(strTemp, nStrLen); strTemp[nStrLen] = 0;
m_strName = strTemp;
m_strTex = strTemp;
//Not needed but lets keep those for compability ensurance
m_nTexFrame = 1;
m_nTexLoop = 1;
m_bUseing = TRUE;
file.Read(&m_nBillType, sizeof(SFXPARTBILLTYPE));
file.Read(&m_nAlphaType, sizeof(SFXPARTALPHATYPE));
int nKey;
file.Read(&nKey, sizeof(int));
for(i = 0; i < nKey; i++) {
WORD nFrame;
file.Read(&nFrame, sizeof(WORD));
AddKeyFrame(nFrame);
SfxKeyFrame Key;
file.Read(&(Key.vPos), sizeof(D3DXVECTOR3));
file.Read(&(Key.vPosRotate), sizeof(D3DXVECTOR3));
file.Read(&(Key.vScale), sizeof(D3DXVECTOR3));
file.Read(&(Key.vRotate), sizeof(D3DXVECTOR3));
file.Read(&(Key.nAlpha), sizeof(int));
AdjustKeyFrame(nFrame, Key);
}
}
void CSfxPartSound::Load2(CResFile& file) {
int i;
char strTemp[255];
int nStrLen;
file.Read(&nStrLen, sizeof(int));
file.Read(strTemp, nStrLen); strTemp[nStrLen] = 0;
m_strName = strTemp;
file.Read(&nStrLen, sizeof(int));
file.Read(strTemp, nStrLen); strTemp[nStrLen] = 0;
m_strTex = strTemp;
//Not needed but lets keep those for compability ensurance
file.Read(&m_nTexFrame, sizeof(WORD));
file.Read(&m_nTexLoop, sizeof(WORD));
file.Read(&m_bUseing, sizeof(BOOL));
file.Read(&m_nBillType, sizeof(SFXPARTBILLTYPE));
file.Read(&m_nAlphaType, sizeof(SFXPARTALPHATYPE));
int nKey;
file.Read(&nKey, sizeof(int));
for(i = 0; i < nKey; i++) {
WORD nFrame;
file.Read(&nFrame, sizeof(WORD));
AddKeyFrame(nFrame);
SfxKeyFrame Key;
file.Read(&(Key.vPos), sizeof(D3DXVECTOR3));
file.Read(&(Key.vPosRotate), sizeof(D3DXVECTOR3));
file.Read(&(Key.vScale), sizeof(D3DXVECTOR3));
file.Read(&(Key.vRotate), sizeof(D3DXVECTOR3));
file.Read(&(Key.nAlpha), sizeof(int));
AdjustKeyFrame(nFrame, Key);
}
}
void CSfxPartSound::OldLoad(CResFile& file) {
int i;
char strTemp[255];
int nStrLen;
file.Read(&nStrLen, sizeof(int));
file.Read(strTemp, nStrLen); strTemp[nStrLen] = 0;
m_strName = strTemp;
m_strTex = strTemp;
//Not needed but lets keep those for compability ensurance
m_nTexFrame = 1;
m_nTexLoop = 1;
m_bUseing = TRUE;
file.Read(&m_nBillType, sizeof(SFXPARTBILLTYPE));
file.Read(&m_nAlphaType, sizeof(SFXPARTALPHATYPE));
int nKey;
file.Read(&nKey, sizeof(int));
for(i = 0; i < nKey; i++) {
WORD nFrame;
file.Read(&nFrame, sizeof(WORD));
AddKeyFrame(nFrame);
SfxKeyFrame Key;
file.Read(&(Key.vPos), sizeof(D3DXVECTOR3));
file.Read(&(Key.vScale), sizeof(D3DXVECTOR3));
file.Read(&(Key.vRotate), sizeof(D3DXVECTOR3));
file.Read(&(Key.nAlpha), sizeof(int));
Key.vPosRotate = D3DXVECTOR3(0, 0, 0);
AdjustKeyFrame(nFrame, Key);
}
}
#ifndef __WORLDSERVER
void CSfxPartSound::Render(D3DXVECTOR3 vPos, WORD nFrame, FLOAT fAngle, D3DXVECTOR3 vScale) {
// If not set to "visible" inside the SFX itself, we dont play the sound
if(!m_bUseing)
return;
if(m_lastPlayedFrame == nFrame)
return;
CString dbgStr;
//For debugging. Keep it for possible later purposes, or just delete it
//dbgStr.Format("Total keyframes: %d, Current frame: %d", m_apKeyFrames.GetSize(), nFrame);
//g_WndMng.PutString(dbgStr);
for(int i = 0; i < m_apKeyFrames.GetSize(); i++) {
SfxKeyFrame* key = (SfxKeyFrame*)m_apKeyFrames[i];
if(key && key->nFrame == nFrame) {
if(!m_strTex.empty()) {
DWORD currentTime = GetTickCount();
std::string soundName = m_strTex.c_str();
// Check if this sound is already playing and within cooldown period(100 ms. that we set before, feel free to change..)
if(g_playingSounds.find(soundName) != g_playingSounds.end()) {
DWORD lastPlayedTime = g_playingSounds[soundName];
if(currentTime - lastPlayedTime < SOUND_COOLDOWN_MS) {
// Sound is still in cooldown, dont play it again to prevent distortion
return;
}
}
// We wanna limit the size of the map to prevent memory leaks
// Maybe not the best way but it works
if(g_playingSounds.size() > 100) {
// Clear thoes old entries
g_playingSounds.clear();
}
// FInally play the sound
PLAYSND(soundName.c_str(), &vPos);
g_playingSounds[soundName] = currentTime;
m_lastPlayedFrame = nFrame;
}
break;
}
}
}
#endif
void CSfxPartSound::Render2(D3DXVECTOR3 vPos, WORD nFrame, D3DXVECTOR3 fAngle, D3DXVECTOR3 vScale) {
#ifndef __WORLDSERVER
Render(vPos, nFrame, fAngle.y, vScale);
#endif
}
#endif //__LNB_SFX_PART_SOUNDS
Do no forget to add the following to your versioncommon/servercommon:
#define __LNB_SFX_PART_SOUNDS //Newly implemented custom parts which support playing sound keyframes made in AToolsX!
That's it! Your Neuz should now properly play sound parts and their content!
Make sure to compile your Neuz and try it - enjoy!
Last updated