Programming/creating vgui soundscape maker: Difference between revisions
WadDelz0949 (talk | contribs) m (WadDelz0949 moved page Category:Programming/creating vgui soundscape maker to Programming/creating vgui soundscape maker: fixup the directory) |
WadDelz0949 (talk | contribs) m (fixed Vector vec = g_SoundscapePositions[i]; being after if (g_bUsingVector[i] == false || vec == vec3_origin)) |
||
(19 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
This tutorial will show you how to make a vgui soundscape maker panel that allows you to modify and play soundscapes in game. | {{LanguageBar|title=Creating VGUI Soundscape Maker}} | ||
[[File:Soundscape | |||
This tutorial will show you how to make a vgui soundscape maker panel that allows you to modify, create, and play soundscapes in game. | |||
[[File:Vgui Soundscape maker panel in game.png|thumb|alt=All panels for vgui soundscape maker in game|All panels for vgui soundscape maker in game]] | |||
==Requirements== | ==Requirements== | ||
* A mod running on [[Source SDK 2013]] | * A mod running on [[Source SDK 2013]] | ||
* Knowledge of C++ | * Knowledge of C++ | ||
==The main vgui | ==The main vgui panel== | ||
Before you start the tutorial you need to copy and paste both these files into your '''src/game/client/''' directory | Before you start the tutorial you need to copy and paste both these files into your '''src/game/client/''' directory | ||
Line 46: | Line 47: | ||
g_SoundscapeMaker->Destroy(); | g_SoundscapeMaker->Destroy(); | ||
</source> | </source> | ||
<br> | |||
Now go to '''public\tier1\KeyValues.h''' and find: | Now go to '''public\tier1\KeyValues.h''' and find: | ||
<source lang=cpp> | <source lang=cpp> | ||
Line 57: | Line 58: | ||
KeyValues( KeyValues& ); // prevent copy constructor being used | KeyValues( KeyValues& ); // prevent copy constructor being used | ||
</source> | </source> | ||
<br> | |||
Now go to '''public\vgui_controls\TextEntry.h''' and find: | |||
<source lang=cpp> | |||
virtual void GetTextRange( char *buf, int from, int numchars ); // copy a portion of the text to the buffer and add zero-termination | |||
private: | |||
CUtlVector<wchar_t> m_TextStream; // the text in the text window is stored in this buffer | |||
</source> | |||
(should be around line 318) and make that be: | |||
<source lang=cpp> | |||
virtual void GetTextRange( char *buf, int from, int numchars ); // copy a portion of the text to the buffer and add zero-termination | |||
public: | |||
CUtlVector<wchar_t> m_TextStream; // the text in the text window is stored in this buffer | |||
</source> | |||
<br> | |||
Now go to '''client/c_soundscape.cpp''' and copy: | Now go to '''client/c_soundscape.cpp''' and copy: | ||
<source lang=cpp> | <source lang=cpp> | ||
#include "c_soundscape.h" | #include "c_soundscape.h" | ||
extern bool g_IsPlayingSoundscape; | |||
extern bool g_bSSMHack; | |||
//debug stuff | |||
void SoundscapePrint(Color color, const char* msg, ...); | |||
void SoundscapeAddLine(Color color, float speed, float width, bool accending); | |||
int SoundscapeGetLineNum(); | |||
</source> | </source> | ||
to be under | to be under | ||
Line 65: | Line 92: | ||
#include "tier0/icommandline.h" | #include "tier0/icommandline.h" | ||
</source> | </source> | ||
Then. find the function: '''void Soundscape_Update( audioparams_t &audio )''' and at the very top of the function and before '''g_SoundscapeSystem.UpdateAudioParams( audio );''' add: | |||
<source lang=cpp> | |||
if (g_IsPlayingSoundscape) | |||
return; | |||
</source> | |||
now find the function: '''void C_SoundscapeSystem::StartNewSoundscape( KeyValues *pSoundscape )''' and at the very top of it and before '''int i;''' add: | |||
<source lang=cpp> | |||
if (g_IsPlayingSoundscape && !g_bSSMHack) | |||
return; | |||
</source> | |||
Now find '''StartSubSoundscape( pSoundscapeKeys, subParams );''' inside '''void C_SoundscapeSystem::ProcessPlaySoundscape( KeyValues *pPlaySoundscape, subsoundscapeparams_t ¶msIn )''' and under it add | |||
<source lang=cpp> | |||
if (g_IsPlayingSoundscape) | |||
SoundscapePrint(Color(100, 255, 0, 255), "Playing Sub Soundscape: \"%s\"\n\n", pSoundscapeName); | |||
</source> | |||
Now find '''if ( soundSlot < 0 )''' in the function '''int C_SoundscapeSystem::AddLoopingSound( const char *pSoundName, bool isAmbient, float volume, soundlevel_t soundlevel, int pitch, const Vector &position )''' and above it add: | |||
<source lang=cpp> | |||
if (g_IsPlayingSoundscape) | |||
{ | |||
//get index | |||
int index = Clamp<int>(SoundscapeGetLineNum(), 0, 6); | |||
//color for looping sounds | |||
static Color LoopingSoundColors[] = { | |||
Color(255, 100, 0, 255), | |||
Color(255, 255, 0, 255), | |||
Color(255, 0, 100, 255), | |||
Color(0, 255, 0, 255), | |||
Color(0, 255, 255, 255), | |||
Color(255, 0, 0, 255), | |||
Color(0, 100, 255, 255), | |||
}; | |||
SoundscapePrint(LoopingSoundColors[index], "Fading looping sound \"%s\" in. Volume = %f, Pitch = %d\nPosition = {%.2f %.2f %.2f}\n\n", pSoundName, volume, pitch, position.x, position.y, position.z); | |||
//sound widths | |||
static float LoopingSoundsIn[] = { | |||
0.4f, | |||
0.5f, | |||
0.6f, | |||
0.7f, | |||
0.8f, | |||
0.9f, | |||
1.0f, | |||
}; | |||
//add to graph | |||
SoundscapeAddLine(LoopingSoundColors[index], 3 / soundscape_fadetime.GetFloat(), LoopingSoundsIn[index], true); | |||
} | |||
</source> | |||
Now find '''m_randomSounds[i].nextPlayTime = gameTime + RandomInterval( m_randomSounds[i].time );''' inside '''C_SoundscapeSystem::UpdateRandomSounds( float gameTime )''' and under it add: | |||
<source lang=cpp> | |||
if (g_IsPlayingSoundscape) | |||
SoundscapePrint(Color(100, 255, 255, 255), "Playing next random sound for RandomSound index \"%d\" In \"%f\" Seconds\n\n", i, m_randomSounds[i].nextPlayTime - gameTime); | |||
</source> | |||
Now find '''m_randomSounds[index].nextPlayTime = gpGlobals->curtime + 0.5 * RandomInterval( sound.time );''' inside '''int C_SoundscapeSystem::AddRandomSound( const randomsound_t &sound )''' and under it add: | |||
<source lang=cpp> | |||
if (g_IsPlayingSoundscape) | |||
SoundscapePrint(Color(100, 255, 255, 255), "Adding random sounds to soundscape system.\nNumber of sounds = \"%d\" For index \"%d\"\n\n", sound.waveCount, index); | |||
</source> | |||
Now you need to find: | |||
<source lang=cpp> | |||
if ( !pWaveName ) | |||
return; | |||
</source> | |||
inside '''void C_SoundscapeSystem::PlayRandomSound''' and under it add: | |||
<source lang=cpp> | |||
int pitch = (int)RandomInterval(sound.pitch); | |||
float volume = sound.masterVolume * RandomInterval(sound.volume); | |||
if (sound.isRandom) | |||
{ | |||
sound.position = GenerateRandomSoundPosition(); | |||
} | |||
if (g_IsPlayingSoundscape) | |||
SoundscapePrint(Color(100, 255, 255, 255), "Playing Random sound \"%s\", Volume = %f, Pitch = %d\nPosition = {%.2f, %.2f, %.2f}\n", pWaveName, volume, pitch, sound.position.x, sound.position.y, sound.position.z); | |||
</source> | |||
Then, in that same function find: | |||
<source lang=cpp> | |||
ep.m_flVolume = sound.masterVolume * RandomInterval( sound.volume ); | |||
ep.m_SoundLevel = (soundlevel_t)(int)RandomInterval( sound.soundlevel ); | |||
ep.m_nPitch = (int)RandomInterval( sound.pitch ); | |||
if ( sound.isRandom ) | |||
{ | |||
sound.position = GenerateRandomSoundPosition(); | |||
} | |||
ep.m_pOrigin = &sound.position; | |||
</source> | |||
And replace that with | |||
<source lang=cpp> | |||
ep.m_flVolume = volume; | |||
ep.m_SoundLevel = (soundlevel_t)(int)RandomInterval( sound.soundlevel ); | |||
ep.m_nPitch = pitch; | |||
ep.m_pOrigin = &sound.position; | |||
</source> | |||
<br> | |||
Then in the same file move | Then in the same file move | ||
<source lang=cpp> | <source lang=cpp> | ||
Line 84: | Line 208: | ||
#pragma once | #pragma once | ||
</source> | </source> | ||
from '''c_soundscapes.cpp''' into the file '''client/c_soundscapes.h'''<br> | |||
and finally move: | and finally move: | ||
<source lang=cpp> | <source lang=cpp> | ||
Line 283: | Line 407: | ||
</source> | </source> | ||
from '''c_soundscape.cpp''' to under the code you added in the '''c_soundscape.h''' file. | from '''c_soundscape.cpp''' to under the code you added in the '''c_soundscape.h''' file. | ||
Then under | before anything else you need to look for | ||
<source lang=cpp> | |||
void ProcessDSPVolume(KeyValues* pKey, subsoundscapeparams_t& params); | |||
private: | |||
bool IsBeingRestored() const | |||
</source> | |||
in the .h file you just added the class to. and if you find it then make the '''private''' be '''public'''.<br> | |||
Then under the class definition add: | |||
<source lang=cpp> | <source lang=cpp> | ||
extern C_SoundscapeSystem g_SoundscapeSystem; | extern C_SoundscapeSystem g_SoundscapeSystem; | ||
</source> | |||
<br> | |||
Now go to '''shared/hl2/hl2_usermessages.cpp''' and inside the file find: | |||
<source lang=cpp> | |||
usermessages->Register( "AchievementEvent", -1 ); | |||
usermessages->Register( "UpdateJalopyRadar", -1 ); | |||
</source> | |||
(should be around line 47) and under it add | |||
<source lang=cpp> | |||
usermessages->Register("SoundscapeMaker_Recieve", -1); | |||
</source> | |||
Now for the final part. you need to go to '''server/player.cpp''' and just above: | |||
<source lang=cpp> | |||
//----------------------------------------------------------------------------- | |||
// Purpose: | |||
//----------------------------------------------------------------------------- | |||
void CBasePlayer::PostThink() | |||
</source> | |||
(should be around line 4590) add: | |||
<source lang=cpp> | |||
bool g_bInSoundscapePositionEditor = false; | |||
int g_SoundscapePositionNumber = 0; | |||
//color based on g_SoundscapePositionNumber | |||
Color g_SoundscapeColors[] = { | |||
Color(255, 0, 0, 50), | |||
Color(200, 200, 0, 50), | |||
Color(200, 0, 255, 50), | |||
Color(0, 0, 255, 50), | |||
Color(0, 255, 0, 50), | |||
Color(200, 100, 0, 50), | |||
Color(0, 0, 0, 50), | |||
Color(0, 100, 250, 50), | |||
}; | |||
//vector positions | |||
Vector g_SoundscapePositions[] = { | |||
vec3_origin, | |||
vec3_origin, | |||
vec3_origin, | |||
vec3_origin, | |||
vec3_origin, | |||
vec3_origin, | |||
vec3_origin, | |||
vec3_origin, | |||
}; | |||
bool g_bUsingVector[] = { | |||
false, | |||
false, | |||
false, | |||
false, | |||
false, | |||
false, | |||
false, | |||
false, | |||
}; | |||
#define MAX_SOUNDSCAPES 8 | |||
//hidden commands | |||
CON_COMMAND_F(__ss_maker_start, "", FCVAR_HIDDEN) | |||
{ | |||
g_bInSoundscapePositionEditor = true; | |||
g_SoundscapePositionNumber = atoi(args.Arg(1)); | |||
} | |||
CON_COMMAND_F(__ss_maker_set, "", FCVAR_HIDDEN) | |||
{ | |||
int index = Clamp<int>(atoi(args.Arg(1)), 0, MAX_SOUNDSCAPES - 1); | |||
g_SoundscapePositions[index] = Vector(atof(args.Arg(2)), atof(args.Arg(3)), atof(args.Arg(4))); | |||
g_bUsingVector[index] = atoi(args.Arg(5)) == 0 ? false : true; | |||
} | |||
ConVar __ss_draw("__ss_draw", "0", FCVAR_HIDDEN); | |||
CON_COMMAND_F(__ss_maker_stop, "", FCVAR_HIDDEN) | |||
{ | |||
g_bInSoundscapePositionEditor = false; | |||
if (!__ss_draw.GetBool()) | |||
g_bUsingVector[g_SoundscapePositionNumber] = false; | |||
} | |||
</source> | |||
Then finally at the top of the '''CBasePlayer::PostThink''' function add: | |||
<source lang=cpp> | |||
if (g_bInSoundscapePositionEditor) | |||
{ | |||
do { | |||
//get endpos for player's eye position + forward 150 | |||
//eye position | |||
Vector EyePos = EyePosition(); | |||
EyePos.z = EyePos.z - 10; | |||
//forward direction | |||
Vector ForwardDir; | |||
AngleVectors(EyeAngles(), &ForwardDir); | |||
//get endpos | |||
Vector EndPos = EyePos + (ForwardDir * 75); | |||
int index = Clamp<int>(g_SoundscapePositionNumber, 0, MAX_SOUNDSCAPES - 1); | |||
//draw overlay line | |||
Color& c = g_SoundscapeColors[index]; | |||
NDebugOverlay::Line(EyePos, EndPos, c.r(), c.b(), c.g(), false, NDEBUG_PERSIST_TILL_NEXT_SERVER); | |||
//set vector at position | |||
g_SoundscapePositions[index] = EndPos; | |||
g_bUsingVector[index] = true; | |||
//check for primary attack | |||
if (m_afButtonPressed & IN_USE) | |||
{ | |||
g_bInSoundscapePositionEditor = false; | |||
//write message for client | |||
CReliableBroadcastRecipientFilter filter; | |||
UserMessageBegin(filter, "SoundscapeMaker_Recieve"); | |||
WRITE_BYTE(g_SoundscapePositionNumber); | |||
WRITE_VEC3COORD(g_SoundscapePositions[g_SoundscapePositionNumber]); | |||
MessageEnd(); | |||
break; | |||
} | |||
if (m_afButtonPressed & IN_RELOAD) | |||
{ | |||
g_bInSoundscapePositionEditor = false; | |||
g_bUsingVector[index] = false; | |||
//write that we canceled the thing | |||
CReliableBroadcastRecipientFilter filter; | |||
UserMessageBegin(filter, "SoundscapeMaker_Recieve"); | |||
WRITE_BYTE(255); | |||
WRITE_VEC3COORD(vec3_invalid); | |||
MessageEnd(); | |||
break; | |||
} | |||
} while (false); | |||
} | |||
//draw all the positions | |||
if (g_bInSoundscapePositionEditor || __ss_draw.GetBool()) | |||
{ | |||
//now draw all the positions | |||
for (int i = 0; i < MAX_SOUNDSCAPES; i++) | |||
{ | |||
Vector vec = g_SoundscapePositions[i]; | |||
//check for invalid vector | |||
if (g_bUsingVector[i] == false || vec == vec3_origin) | |||
continue; | |||
//get box stuff | |||
Color& c = g_SoundscapeColors[i]; | |||
//draw all the items | |||
NDebugOverlay::Box(vec, Vector(-10, -10, -10), Vector(10, 10, 10), c.r(), c.b(), c.g(), c.a(), NDEBUG_PERSIST_TILL_NEXT_SERVER); | |||
//move vec up 3 | |||
vec.z = vec.z + 3; | |||
NDebugOverlay::Text(vec, CFmtStr("Origin: %f %f %f", vec.x, vec.y, vec.z), false, NDEBUG_PERSIST_TILL_NEXT_SERVER); | |||
//move vec down 6 | |||
vec.z = vec.z - 6; | |||
NDebugOverlay::Text(vec, CFmtStr("Position: %d", i), false, NDEBUG_PERSIST_TILL_NEXT_SERVER); | |||
} | |||
} | |||
</source> | </source> | ||
Now the panel should be all done. to open the panel in game use the '''modbase_soundscape_panel''' command and the panel should show. | Now the panel should be all done. to open the panel in game use the '''modbase_soundscape_panel''' command and the panel should show. | ||
For information on how to use the vgui panel head over to: | |||
* [[How_to_use_vgui_soundscape_maker|How to use the vgui soundscape maker]] |
Latest revision as of 03:22, 12 June 2025


This tutorial will show you how to make a vgui soundscape maker panel that allows you to modify, create, and play soundscapes in game.
Requirements
- A mod running on Source SDK 2013
- Knowledge of C++
The main vgui panel
Before you start the tutorial you need to copy and paste both these files into your src/game/client/ directory

Once that is done you are almost all done. The next thing you are going to want to do is go over to client/vgui_int.cpp and at the top of the file and under
#include <vgui_controls/Controls.h>
add
#include "vgui_soundscape_maker.h"
Then in the same file find:
void VGui_CreateGlobalPanels( void )
{
VPANEL gameToolParent = enginevgui->GetPanel( PANEL_CLIENTDLL_TOOLS );
VPANEL toolParent = enginevgui->GetPanel( PANEL_TOOLS );
and under that add
g_SoundscapeMaker->Create(toolParent);
Now find
void VGui_Shutdown()
{
And under it add:
g_SoundscapeMaker->Destroy();
Now go to public\tier1\KeyValues.h and find:
private:
KeyValues( KeyValues& ); // prevent copy constructor being used
(should be around line 258) and make that be:
public:
KeyValues( KeyValues& ); // prevent copy constructor being used
Now go to public\vgui_controls\TextEntry.h and find:
virtual void GetTextRange( char *buf, int from, int numchars ); // copy a portion of the text to the buffer and add zero-termination
private:
CUtlVector<wchar_t> m_TextStream; // the text in the text window is stored in this buffer
(should be around line 318) and make that be:
virtual void GetTextRange( char *buf, int from, int numchars ); // copy a portion of the text to the buffer and add zero-termination
public:
CUtlVector<wchar_t> m_TextStream; // the text in the text window is stored in this buffer
Now go to client/c_soundscape.cpp and copy:
#include "c_soundscape.h"
extern bool g_IsPlayingSoundscape;
extern bool g_bSSMHack;
//debug stuff
void SoundscapePrint(Color color, const char* msg, ...);
void SoundscapeAddLine(Color color, float speed, float width, bool accending);
int SoundscapeGetLineNum();
to be under
#include "tier0/icommandline.h"
Then. find the function: void Soundscape_Update( audioparams_t &audio ) and at the very top of the function and before g_SoundscapeSystem.UpdateAudioParams( audio ); add:
if (g_IsPlayingSoundscape)
return;
now find the function: void C_SoundscapeSystem::StartNewSoundscape( KeyValues *pSoundscape ) and at the very top of it and before int i; add:
if (g_IsPlayingSoundscape && !g_bSSMHack)
return;
Now find StartSubSoundscape( pSoundscapeKeys, subParams ); inside void C_SoundscapeSystem::ProcessPlaySoundscape( KeyValues *pPlaySoundscape, subsoundscapeparams_t ¶msIn ) and under it add
if (g_IsPlayingSoundscape)
SoundscapePrint(Color(100, 255, 0, 255), "Playing Sub Soundscape: \"%s\"\n\n", pSoundscapeName);
Now find if ( soundSlot < 0 ) in the function int C_SoundscapeSystem::AddLoopingSound( const char *pSoundName, bool isAmbient, float volume, soundlevel_t soundlevel, int pitch, const Vector &position ) and above it add:
if (g_IsPlayingSoundscape)
{
//get index
int index = Clamp<int>(SoundscapeGetLineNum(), 0, 6);
//color for looping sounds
static Color LoopingSoundColors[] = {
Color(255, 100, 0, 255),
Color(255, 255, 0, 255),
Color(255, 0, 100, 255),
Color(0, 255, 0, 255),
Color(0, 255, 255, 255),
Color(255, 0, 0, 255),
Color(0, 100, 255, 255),
};
SoundscapePrint(LoopingSoundColors[index], "Fading looping sound \"%s\" in. Volume = %f, Pitch = %d\nPosition = {%.2f %.2f %.2f}\n\n", pSoundName, volume, pitch, position.x, position.y, position.z);
//sound widths
static float LoopingSoundsIn[] = {
0.4f,
0.5f,
0.6f,
0.7f,
0.8f,
0.9f,
1.0f,
};
//add to graph
SoundscapeAddLine(LoopingSoundColors[index], 3 / soundscape_fadetime.GetFloat(), LoopingSoundsIn[index], true);
}
Now find m_randomSounds[i].nextPlayTime = gameTime + RandomInterval( m_randomSounds[i].time ); inside C_SoundscapeSystem::UpdateRandomSounds( float gameTime ) and under it add:
if (g_IsPlayingSoundscape)
SoundscapePrint(Color(100, 255, 255, 255), "Playing next random sound for RandomSound index \"%d\" In \"%f\" Seconds\n\n", i, m_randomSounds[i].nextPlayTime - gameTime);
Now find m_randomSounds[index].nextPlayTime = gpGlobals->curtime + 0.5 * RandomInterval( sound.time ); inside int C_SoundscapeSystem::AddRandomSound( const randomsound_t &sound ) and under it add:
if (g_IsPlayingSoundscape)
SoundscapePrint(Color(100, 255, 255, 255), "Adding random sounds to soundscape system.\nNumber of sounds = \"%d\" For index \"%d\"\n\n", sound.waveCount, index);
Now you need to find:
if ( !pWaveName )
return;
inside void C_SoundscapeSystem::PlayRandomSound and under it add:
int pitch = (int)RandomInterval(sound.pitch);
float volume = sound.masterVolume * RandomInterval(sound.volume);
if (sound.isRandom)
{
sound.position = GenerateRandomSoundPosition();
}
if (g_IsPlayingSoundscape)
SoundscapePrint(Color(100, 255, 255, 255), "Playing Random sound \"%s\", Volume = %f, Pitch = %d\nPosition = {%.2f, %.2f, %.2f}\n", pWaveName, volume, pitch, sound.position.x, sound.position.y, sound.position.z);
Then, in that same function find:
ep.m_flVolume = sound.masterVolume * RandomInterval( sound.volume );
ep.m_SoundLevel = (soundlevel_t)(int)RandomInterval( sound.soundlevel );
ep.m_nPitch = (int)RandomInterval( sound.pitch );
if ( sound.isRandom )
{
sound.position = GenerateRandomSoundPosition();
}
ep.m_pOrigin = &sound.position;
And replace that with
ep.m_flVolume = volume;
ep.m_SoundLevel = (soundlevel_t)(int)RandomInterval( sound.soundlevel );
ep.m_nPitch = pitch;
ep.m_pOrigin = &sound.position;
Then in the same file move
struct loopingsound_t
{
Vector position; // position (if !isAmbient)
const char *pWaveName; // name of the wave file
float volumeTarget; // target volume level (fading towards this)
float volumeCurrent; // current volume level
soundlevel_t soundlevel; // sound level (if !isAmbient)
int pitch; // pitch shift
int id; // Used to fade out sounds that don't belong to the most current setting
bool isAmbient; // Ambient sounds have no spatialization - they play from everywhere
};
to be under
#ifdef _WIN32
#pragma once
from c_soundscapes.cpp into the file client/c_soundscapes.h
and finally move:
struct randomsound_t
{
Vector position;
float nextPlayTime; // time to play a sound from the set
interval_t time;
interval_t volume;
interval_t pitch;
interval_t soundlevel;
float masterVolume;
int waveCount;
bool isAmbient;
bool isRandom;
KeyValues *pWaves;
void Init()
{
memset( this, 0, sizeof(*this) );
}
};
struct subsoundscapeparams_t
{
int recurseLevel; // test for infinite loops in the script / circular refs
float masterVolume;
int startingPosition;
int positionOverride; // forces all sounds to this position
int ambientPositionOverride; // forces all ambient sounds to this position
bool allowDSP;
bool wroteSoundMixer;
bool wroteDSPVolume;
};
class C_SoundscapeSystem : public CBaseGameSystemPerFrame
{
public:
virtual char const *Name() { return "C_SoundScapeSystem"; }
C_SoundscapeSystem()
{
m_nRestoreFrame = -1;
}
~C_SoundscapeSystem() {}
void OnStopAllSounds()
{
m_params.ent.Set( NULL );
m_params.soundscapeIndex = -1;
m_loopingSounds.Purge();
m_randomSounds.Purge();
}
// IClientSystem hooks, not needed
virtual void LevelInitPreEntity()
{
Shutdown();
Init();
TouchSoundFiles();
}
virtual void LevelInitPostEntity()
{
if ( !m_pSoundMixerVar )
{
m_pSoundMixerVar = (ConVar *)cvar->FindVar( "snd_soundmixer" );
}
if ( !m_pDSPVolumeVar )
{
m_pDSPVolumeVar = (ConVar *)cvar->FindVar( "dsp_volume" );
}
}
// The level is shutdown in two parts
virtual void LevelShutdownPreEntity() {}
// Entities are deleted / released here...
virtual void LevelShutdownPostEntity()
{
OnStopAllSounds();
}
virtual void OnSave() {}
virtual void OnRestore()
{
m_nRestoreFrame = gpGlobals->framecount;
}
virtual void SafeRemoveIfDesired() {}
// Called before rendering
virtual void PreRender() { }
// Called after rendering
virtual void PostRender() { }
// IClientSystem hooks used
virtual bool Init();
virtual void Shutdown();
// Gets called each frame
virtual void Update( float frametime );
void PrintDebugInfo()
{
Msg( "\n------- CLIENT SOUNDSCAPES -------\n" );
for ( int i=0; i < m_soundscapes.Count(); i++ )
{
Msg( "- %d: %s\n", i, m_soundscapes[i]->GetName() );
}
if ( m_forcedSoundscapeIndex )
{
Msg( "- PLAYING DEBUG SOUNDSCAPE: %d [%s]\n", m_forcedSoundscapeIndex, SoundscapeNameByIndex(m_forcedSoundscapeIndex) );
}
Msg( "- CURRENT SOUNDSCAPE: %d [%s]\n", m_params.soundscapeIndex.Get(), SoundscapeNameByIndex(m_params.soundscapeIndex) );
Msg( "----------------------------------\n\n" );
}
// local functions
void UpdateAudioParams( audioparams_t &audio );
void GetAudioParams( audioparams_t &out ) const { out = m_params; }
int GetCurrentSoundscape()
{
if ( m_forcedSoundscapeIndex >= 0 )
return m_forcedSoundscapeIndex;
return m_params.soundscapeIndex;
}
void DevReportSoundscapeName( int index );
void UpdateLoopingSounds( float frametime );
int AddLoopingAmbient( const char *pSoundName, float volume, int pitch );
void UpdateLoopingSound( loopingsound_t &loopSound );
void StopLoopingSound( loopingsound_t &loopSound );
int AddLoopingSound( const char *pSoundName, bool isAmbient, float volume,
soundlevel_t soundLevel, int pitch, const Vector &position );
int AddRandomSound( const randomsound_t &sound );
void PlayRandomSound( randomsound_t &sound );
void UpdateRandomSounds( float gameClock );
Vector GenerateRandomSoundPosition();
void ForceSoundscape( const char *pSoundscapeName, float radius );
int FindSoundscapeByName( const char *pSoundscapeName );
const char *SoundscapeNameByIndex( int index );
KeyValues *SoundscapeByIndex( int index );
// main-level soundscape processing, called on new soundscape
void StartNewSoundscape( KeyValues *pSoundscape );
void StartSubSoundscape( KeyValues *pSoundscape, subsoundscapeparams_t ¶ms );
// root level soundscape keys
// add a process for each new command here
// "dsp"
void ProcessDSP( KeyValues *pDSP );
// "dsp_player"
void ProcessDSPPlayer( KeyValues *pDSPPlayer );
// "playlooping"
void ProcessPlayLooping( KeyValues *pPlayLooping, const subsoundscapeparams_t ¶ms );
// "playrandom"
void ProcessPlayRandom( KeyValues *pPlayRandom, const subsoundscapeparams_t ¶ms );
// "playsoundscape"
void ProcessPlaySoundscape( KeyValues *pPlaySoundscape, subsoundscapeparams_t ¶ms );
// "soundmixer"
void ProcessSoundMixer( KeyValues *pSoundMixer, subsoundscapeparams_t ¶ms );
// "dsp_volume"
void ProcessDSPVolume( KeyValues *pKey, subsoundscapeparams_t ¶ms );
bool IsBeingRestored() const
{
return gpGlobals->framecount == m_nRestoreFrame ? true : false;
}
void AddSoundScapeFile( const char *filename );
void TouchPlayLooping( KeyValues *pAmbient );
void TouchPlayRandom( KeyValues *pPlayRandom );
void TouchWaveFiles( KeyValues *pSoundScape );
void TouchSoundFile( char const *wavefile );
void TouchSoundFiles();
int m_nRestoreFrame;
CUtlVector< KeyValues * > m_SoundscapeScripts; // The whole script file in memory
CUtlVector<KeyValues *> m_soundscapes; // Lookup by index of each root section
audioparams_t m_params; // current player audio params
CUtlVector<loopingsound_t> m_loopingSounds; // list of currently playing sounds
CUtlVector<randomsound_t> m_randomSounds; // list of random sound commands
float m_nextRandomTime; // next time to play a random sound
int m_loopingSoundId; // marks when the sound was issued
int m_forcedSoundscapeIndex;// >= 0 if this a "forced" soundscape? i.e. debug mode?
float m_forcedSoundscapeRadius;// distance to spatialized sounds
static ConVar *m_pDSPVolumeVar;
static ConVar *m_pSoundMixerVar;
};
from c_soundscape.cpp to under the code you added in the c_soundscape.h file. before anything else you need to look for
void ProcessDSPVolume(KeyValues* pKey, subsoundscapeparams_t& params);
private:
bool IsBeingRestored() const
in the .h file you just added the class to. and if you find it then make the private be public.
Then under the class definition add:
extern C_SoundscapeSystem g_SoundscapeSystem;
Now go to shared/hl2/hl2_usermessages.cpp and inside the file find:
usermessages->Register( "AchievementEvent", -1 );
usermessages->Register( "UpdateJalopyRadar", -1 );
(should be around line 47) and under it add
usermessages->Register("SoundscapeMaker_Recieve", -1);
Now for the final part. you need to go to server/player.cpp and just above:
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBasePlayer::PostThink()
(should be around line 4590) add:
bool g_bInSoundscapePositionEditor = false;
int g_SoundscapePositionNumber = 0;
//color based on g_SoundscapePositionNumber
Color g_SoundscapeColors[] = {
Color(255, 0, 0, 50),
Color(200, 200, 0, 50),
Color(200, 0, 255, 50),
Color(0, 0, 255, 50),
Color(0, 255, 0, 50),
Color(200, 100, 0, 50),
Color(0, 0, 0, 50),
Color(0, 100, 250, 50),
};
//vector positions
Vector g_SoundscapePositions[] = {
vec3_origin,
vec3_origin,
vec3_origin,
vec3_origin,
vec3_origin,
vec3_origin,
vec3_origin,
vec3_origin,
};
bool g_bUsingVector[] = {
false,
false,
false,
false,
false,
false,
false,
false,
};
#define MAX_SOUNDSCAPES 8
//hidden commands
CON_COMMAND_F(__ss_maker_start, "", FCVAR_HIDDEN)
{
g_bInSoundscapePositionEditor = true;
g_SoundscapePositionNumber = atoi(args.Arg(1));
}
CON_COMMAND_F(__ss_maker_set, "", FCVAR_HIDDEN)
{
int index = Clamp<int>(atoi(args.Arg(1)), 0, MAX_SOUNDSCAPES - 1);
g_SoundscapePositions[index] = Vector(atof(args.Arg(2)), atof(args.Arg(3)), atof(args.Arg(4)));
g_bUsingVector[index] = atoi(args.Arg(5)) == 0 ? false : true;
}
ConVar __ss_draw("__ss_draw", "0", FCVAR_HIDDEN);
CON_COMMAND_F(__ss_maker_stop, "", FCVAR_HIDDEN)
{
g_bInSoundscapePositionEditor = false;
if (!__ss_draw.GetBool())
g_bUsingVector[g_SoundscapePositionNumber] = false;
}
Then finally at the top of the CBasePlayer::PostThink function add:
if (g_bInSoundscapePositionEditor)
{
do {
//get endpos for player's eye position + forward 150
//eye position
Vector EyePos = EyePosition();
EyePos.z = EyePos.z - 10;
//forward direction
Vector ForwardDir;
AngleVectors(EyeAngles(), &ForwardDir);
//get endpos
Vector EndPos = EyePos + (ForwardDir * 75);
int index = Clamp<int>(g_SoundscapePositionNumber, 0, MAX_SOUNDSCAPES - 1);
//draw overlay line
Color& c = g_SoundscapeColors[index];
NDebugOverlay::Line(EyePos, EndPos, c.r(), c.b(), c.g(), false, NDEBUG_PERSIST_TILL_NEXT_SERVER);
//set vector at position
g_SoundscapePositions[index] = EndPos;
g_bUsingVector[index] = true;
//check for primary attack
if (m_afButtonPressed & IN_USE)
{
g_bInSoundscapePositionEditor = false;
//write message for client
CReliableBroadcastRecipientFilter filter;
UserMessageBegin(filter, "SoundscapeMaker_Recieve");
WRITE_BYTE(g_SoundscapePositionNumber);
WRITE_VEC3COORD(g_SoundscapePositions[g_SoundscapePositionNumber]);
MessageEnd();
break;
}
if (m_afButtonPressed & IN_RELOAD)
{
g_bInSoundscapePositionEditor = false;
g_bUsingVector[index] = false;
//write that we canceled the thing
CReliableBroadcastRecipientFilter filter;
UserMessageBegin(filter, "SoundscapeMaker_Recieve");
WRITE_BYTE(255);
WRITE_VEC3COORD(vec3_invalid);
MessageEnd();
break;
}
} while (false);
}
//draw all the positions
if (g_bInSoundscapePositionEditor || __ss_draw.GetBool())
{
//now draw all the positions
for (int i = 0; i < MAX_SOUNDSCAPES; i++)
{
Vector vec = g_SoundscapePositions[i];
//check for invalid vector
if (g_bUsingVector[i] == false || vec == vec3_origin)
continue;
//get box stuff
Color& c = g_SoundscapeColors[i];
//draw all the items
NDebugOverlay::Box(vec, Vector(-10, -10, -10), Vector(10, 10, 10), c.r(), c.b(), c.g(), c.a(), NDEBUG_PERSIST_TILL_NEXT_SERVER);
//move vec up 3
vec.z = vec.z + 3;
NDebugOverlay::Text(vec, CFmtStr("Origin: %f %f %f", vec.x, vec.y, vec.z), false, NDEBUG_PERSIST_TILL_NEXT_SERVER);
//move vec down 6
vec.z = vec.z - 6;
NDebugOverlay::Text(vec, CFmtStr("Position: %d", i), false, NDEBUG_PERSIST_TILL_NEXT_SERVER);
}
}
Now the panel should be all done. to open the panel in game use the modbase_soundscape_panel command and the panel should show.
For information on how to use the vgui panel head over to: