Programming/creating vgui soundscape maker: Difference between revisions

From Valve Developer Community
Jump to navigation Jump to search
m (minor edit)
m (fixed Vector vec = g_SoundscapePositions[i]; being after if (g_bUsingVector[i] == false || vec == vec3_origin))
 
(17 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 Panel In Game.png|thumb|alt=Soundscape panel in game|Soundscape panel in game]]
 
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++
Have read and/or understand:
* [[VGUI Documentation]]
* [[VGUI2: Creating a panel]]


==The main vgui panels==
==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 in the same file find:
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 &paramsIn )''' 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>
<source lang=cpp>
void C_SoundscapeSystem::StartNewSoundscape( KeyValues *pSoundscape )
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>
</source>
and just above that add:
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>
<source lang=cpp>
extern bool g_IsPlayingSoundscape;
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>
</source>
then at the very top of the function add
Now you need to find:
<source lang=cpp>
<source lang=cpp>
if (g_IsPlayingSoundscape)
if ( !pWaveName )
return;
return;
</source>
</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 305: Line 416:
bool IsBeingRestored() const
bool IsBeingRestored() const
</source>
</source>
in the .h file you just added the class to. and if you find it then make the '''private''' be '''public'''.
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:
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.
==How to use panel==
This will teach you on how to create soundscapes using the soundscape maker panel.
So The soundscape panel has 4 sections.<br>
* The Soundscapes section. This section contains the list of soundscapes for this file.
* The soundscape data section. This section has all the data for a specific soundscape for this file.
* The random soundscape data section. This section has all the random waves that can play for a "playrandom" section for a specific soundscape.
* The data section. this section contains all the data for the specific soundscape and/or current soundscape data like: '''the soundscape name, the soundscape dsp, a soundscape data's volume''' and more.


TODO: add more and add stuff to vgui_soundscape_maker files
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

English (en)Translate (Translate)

This tutorial will show you how to make a vgui soundscape maker panel that allows you to modify, create, and play soundscapes in game.

All panels for vgui soundscape maker in game
All panels for vgui soundscape maker in game

Requirements

The main vgui panel

Before you start the tutorial you need to copy and paste both these files into your src/game/client/ directory


Note.pngNote:The vgui_soundscape_maker.cpp will have some errors but they will be fixed later when the c_soundscape.cpp and .h files get changed.

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 &paramsIn ) 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 &params );

	// 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 &params );	
	// "playrandom"
	void ProcessPlayRandom( KeyValues *pPlayRandom, const subsoundscapeparams_t &params );
	// "playsoundscape"
	void ProcessPlaySoundscape( KeyValues *pPlaySoundscape, subsoundscapeparams_t &params );
	// "soundmixer"
	void ProcessSoundMixer( KeyValues *pSoundMixer, subsoundscapeparams_t &params );
	// "dsp_volume"
	void ProcessDSPVolume( KeyValues *pKey, subsoundscapeparams_t &params );

	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: