Source Engine Single Player Mod Setup

12 minute read

This is a walkthrough of how to setup a basic single player mod for the Source Engine.

At the end of this tutorial you will have a functioning single player mod that will behave just like Half-Life 2 Episode 2.

What to Do If You Run into Issues

If you run into a problem the fastest way is to ask a question on the Steam Source SDK Forums, Reddit, or the Source Engine Discord. But do be sure to search first, often someone else has already had the same problem and solved it!

You can email me directly but I respond the fastest to posts on the Source SDK forums since Steam puts the alert in my face.

Video Version of This Tutorial

Don’t feel like reading or need a visual aid? Check out the video!

NOTE: There are some differences now between this video and the written version, the video is from 2015 and since then I’ve updated/improved the documentation

Things You Will Need to Download

Required

If you are new to git there are a ton of great tutorials out there on it

  • Visual Studio 2013 Community Edition (scroll down to 2013, click Download, and sign in with your Microsoft account), yes you can just use the compiler but this tutorial was made with VS2013 CE in mind.

See Building Without Visual Studio on the VDC for a tutorial on that

  • Multibyte MFC Library, install AFTER VS 2013 is installed

  • Install Source SDK Base 2013 Single Player on Steam

Prompt Steam to Install or find it in the Tools section

Once installed right click and choose properties then go to the betas tab and choose “upcoming”

image-center

Optional

  • Microsoft Speech SDK 5.1 if you are wanting to do anything that isn’t directly gameplay related such as shaders (the everything.sln requires it for compiling), just pick SpeechSDK51.exe

Setting up the Work Directory

Create the directory you want your mods source files to live in while you are working on it. Personally I like to have a “working” directory that houses all of my projects, so in my case it is going to be D:/working/myfirstmod

Make sure there are no spaces in your directory name, having spaces will cause issues!

Now in your new directory create another called “code”, this is where we will be storing the code portion of your mod. So go ahead and either unzip your copy of Source SDK 2013 from GitHub or if you are using git control clone into this directory.

Open up your copy of the source code and you will notice two directories, sp and mp, being named after single player and multiplayer respectively. We do not need the multiplayer version so go ahead and select that directory and delete it.

Setting up the Mod Directory

Navigate to your primary Steam directory, where steam.exe lives, and go into steamapps and then sourcemods. If you installed Steam with all the defaults on your default C drive it is probably: C:\Program Files (x86)\Steam\steamapps\sourcemods.

In this directory go ahead and make a directory that is the same name as your mod and enter it.

Make sure there are no spaces in your directory name, having spaces will cause issues!

In here make the following directories:

  • bin
  • cfg
  • maps
  • materials
  • models
  • resource
  • scripts
  • sound

Setting up Microsoft Speech SDK (SAPI)

If you are not using this (as in you do not need to compile the “everything” project) then skip this section, otherwise read on.

Run the SpeechSDK51.exe that you downloaded earlier. It should unzip contents into a directory of your choice. One of the contents it unzips is Microsoft SDK 5.1.msi. Running this with the default settings should create a directory called Microsoft Speech SDK 5.1 in your Program Files (x86) directory. Copy that directory and it’s contents into \sp\src\utils of your mods source code directory and rename it to sapi51.

In sp\src\utils\sapi51\Include open up the sphelper.h file in an editor of your choice, the following changes need to be made to it:

Line 769:

const size_t ulLenVendorPreferred = wcslen(pszVendorPreferred); // no size_t

Line 1418:

static long CoMemCopyWFEX(const WAVEFORMATEX * pSrc, WAVEFORMATEX ** ppCoMemWFEX) // missing long

Line 2368:

const WCHAR * PropertyStringValue() const
   {
       // Search for the first NULL and return pointer to the char past it.
       SPDBG_ASSERT(eEventId == SPEI_PROPERTY_STRING_CHANGE);
       const WCHAR * psz = (const WCHAR *)lParam; // moved this from for init
       for (; *psz; psz++) {}
       return psz + 1;
   }

Line 2560:

SPPHONEID* pphoneId = (SPPHONEID*)((WCHAR *)dsPhoneId); // improper casting

Line 2634:

pphoneId += wcslen((const wchar_t *)pphoneId) + 1; // improper casting

Setting up the Codebase and Compiling it

Navigate to your spc/src directory.

Run creategameprojects.bat and you will see it makes a games.sln, this is the solution file and is used for organizing the project. Go ahead and open it up in Visual Studio 2013 CE.

Right click Solution 'games' (8 projects) in the Solution Explorer and choose Properties

image-center

On the left side of the properties menu click on Configuration under Configuration Properties and then click Configuration Manager... in the upper right.

image-center

In the Configuration Manager under Active solution configuration: choose Release from the drop down.

image-center

Click close and then OK to exit out of both the configuration manager and the properties menus.

In the menu bar at the top click Build then click Rebuild Solution (or press ctrl+Alt+F7) and wait for the build to finish.

image-center

If everything was setup properly you will get a nice output that tells you that there were 8 successes, 0 fails, and 0 skips.

image-center

Getting the Binaries

Your mod needs both a client.dll and server.dll to run properly which is why we compiled the code earlier. Compiling the code gives us binaries for the engine to use.

In your source code directory, sp\src, navigate to game and you will see three directories: client, server, and shared. To begin let’s get the client.dll. Go into the client directory followed by the Release_mod_episodic directory. In here you will find a lot of .obj files but the one we are looking for is a .dll, so either search using *.dll or sort by type. Copy the client.dll once you have found it into your mods bin directory. Do exactly the same for server.

image-center

Once you are done your bin directory should contain both client and server .dll files.

We can also automate this process using what is known as a post build event.

In Visual Studio right click Client (Episodic) in the Solution Explorer and select properties just like we did earlier with the solution.

On the left side look for Build Events and expand that and choose Post-Build Event

image-center

Click on Command Line and then the drop down arrow to the right and choose <Edit...>

image-center

image-center

A window titled Command Line will open up, inside of it is the batch script that will run after it is done compiling. If you look closely you will see it has the line

copy "$(TargetDir)$(TargetFileName)" "..\..\..\game\mod_episodic\bin\.\$(TargetFileName)"

This line of the script is saying “Copy the dll into a directory. That directory is 3 levels up from where you are now (..\..\..\) and then down into game\mod_episodic\bin\. and the copied file is still going to have the same name as the original, $(TargetFileName).

We of course want the dll’s going into our mods bin directory so let’s change this. To start select the entire script and copy it into a different editor like Notepad++.

Select the text ..\..\..\game\mod_episodic\bin and press CTRL+H to bring up the Find Replace feature of Notepad++, if you are using a different text editor it most likely has the exact same function with a different hoteky.

image-center

We now want to replace all instances of ..\..\..\game\mod_episodic\bin with our mods bin directory. In my case that is C:\Program Files (x86)\Steam\steamapps\sourcemods\myfirstmod\bin and then press Replace All.

image-center

image-center

If your directory path contains spaces in it such as C:\Program Files (x86)\Steam\steamapps\sourcemods\myfirstmod\bin it must be wrapped in double quotes!

Select all of your modified script and copy it back into the Visual Studio Command Line window and press OK to close the window. Press OK again to apply and close the Properties Page of Client (Episodic).

You now need to do the exact same thing for Server (Episodic) but the good news is you can just reuse the same exact script you modified.

Now if you do a rebuild you will see it puts the dlls into your mods bin directory!

NOTE: dlls are only copied when a successful build happens, so if you do not make any changes to server then the dll will not be copied for example.

Original Script Modified Script

Gameinfo.txt Setup

The gameinfo.txt is a very important part of any Source Engine mod and game. This file tells the engine and Steam not only what your mod is called but what files to mount.

The following are examples of some gameinfo.txt’s from Valve’s games:

Half-Life 2 Half-Life 2 EP2 Portal 2 Team Fortress 2

In your mod directory create a file called gameinfo.txt and copy the following into it:

"GameInfo"
{
	game 		"My First Episodic Mod"
	title 		"HALF-LIFE'"
	title2		""
	supportsvr	1

	type		singleplayer_only

	FileSystem
	{
		SteamAppId				243730		// This sets the app ID in Steam
		
		//
		// The code that loads this file automatically does a few things here:
		//
		// 1. For each "Game" search path, it adds a "GameBin" path, in <dir>\bin
		// 2. For each "Game" search path, it adds another "Game" path in front of it with _<langage> at the end.
		//    For example: c:\hl2\cstrike on a french machine would get a c:\hl2\cstrike_french path added to it.
		// 3. For the first "Game" search path, it adds a search path called "MOD".
		// 4. For the first "Game" search path, it adds a search path called "DEFAULT_WRITE_PATH".
		//

		//
		// Search paths are relative to the base directory, which is where hl2.exe is found.
		//
		// |gameinfo_path| points at the directory where gameinfo.txt is.
		// We always want to mount that directory relative to gameinfo.txt, so
		// people can mount stuff in c:\mymod, and the main game resources are in
		// someplace like c:\program files\valve\steam\steamapps\half-life 2.
		//
		SearchPaths
		{
			// First, mount all user customizations.  This will search for VPKs and subdirectories
			// and mount them in alphabetical order.  The easiest way to distribute a mod is to
			// pack up the custom content into a VPK.  To "install" a mod, just drop it in this
			// directory.
			//
			// Note that this directory is scanned only when the game is booted.
            game+mod            |gameinfo_path|custom/*

			// Now search loose files.  We'll set the directory containing the gameinfo.txt file
			// as the first "mod" search path (after any user customizations).  This is also the one
			// that's used when writing to the "mod" path.
			mod+mod_write+default_write_path    |gameinfo_path|.
            game+game_write     |gameinfo_path|.

			gamebin				|gameinfo_path|bin

			// We search VPK files before ordinary directories, because most files will be found in
			// VPK and we can avoid making thousands of file system calls to attempt to open files
			// in directories where they don't exist.  (Searching a VPK is much faster than making an operating
			// system call.)
			game_lv				hl2/hl2_lv.vpk
			game+mod			|all_source_engine_paths|ep2/ep2_english.vpk	// EP2 that comes with SDK 2013 SP
			game+mod			|all_source_engine_paths|ep2/ep2_pak.vpk	
			
			game				|all_source_engine_paths|episodic/ep1_english.vpk	// EP1 that comes with SDK 2013 SP
			game				|all_source_engine_paths|episodic/ep1_pak.vpk
			
			game				|all_source_engine_paths|hl2/hl2_english.vpk	// Base HL2 that comes with SDK 2103 SP
			game				|all_source_engine_paths|hl2/hl2_pak.vpk
			game				|all_source_engine_paths|hl2/hl2_textures.vpk
			game				|all_source_engine_paths|hl2/hl2_sound_vo_english.vpk
			game				|all_source_engine_paths|hl2/hl2_sound_misc.vpk
			game				|all_source_engine_paths|hl2/hl2_misc.vpk

            // If you wanted to mount other games here such as Portal or Counter-Strike Source this is where you would do it
            // Example:
            // game             |all_source_engine_paths|cstrike/cstrike_pak.vpk


			platform			|all_source_engine_paths|platform/platform_misc.vpk

			// Last, mount in shared HL2 loose files
			game				|all_source_engine_paths|episodic
			game				|all_source_engine_paths|hl2
			platform			|all_source_engine_paths|platform
		}
	}
}

Be sure to change the values for game and title to match your mods name!

The CFG Directory

The CFG directory is where you will keep all of your config files for the game. A .cfg file is simply a file that contains commands that will get run when executed.

The .cfg files you should have in your directory:

  • modsettings.cfg, runs when the mod starts up
  • game.cfg, runs on every map load
  • skill.cfg, contains the console variables for various settings for NPC’s and weapons
  • skill_manifest.cfg, this is used to run multiple skill.cfg files
  • config_default.cfg, the default keybinds
  • chapter#.cfg, ran when the player picks that chapter # from the main menu. Normally it’s to load the proper map.

Examples:

Half-Life 2’s skill.cfg Half-Life 2 EP2 skill_episodic.cfg skill_manifest.cfg Half-Life 2 chapter1.cfg config_default.cfg

Valve and other mod teams do various things with cfg’s since they are convient places to store settings that can be applied easily or change. Poke around for some ideas!

The Other Directories

Quick run down on what these other directories are used for, will go into more detail on some of these in later tutorials.

  • Maps, you store your map files in here including the .bsp, .nav, and other files you might have added support for such as descriptions like Counter-Strike: Source
  • Models/Materials/Sound, these are pretty straight forward the corresponding files go in here and you should try to keep them organized in subdirectories
  • Resource, contains fonts, close caption text, icons, cursors, and other UI elements
  • Scripts, holds script files for things like soundscapes, weapon scripts, chapter titles, prop_data, sentences, HUD layout, vehicles and a lot more. Definitely dig through the HL2 scripts directory to get an idea

Opt into the Source SDK 2013 Singleplayer Beta

For compatibility reasons with older 2013 based mods, 2013 singelplayer has a beta branch called upcoming that you need to opt into.

Start by right clicking Source SDK 2013 Singleplayer and selecting properties.

image-center

Select the beta tab.

image-center

Click the drop down and choose upcoming.

image-center

You should notice it now queues up an update, wait for that to finish downloading.

You’re Done!

Restart Steam and you should see your mod show up in the Games section now! Launch your mod and you will end up on the main menu.

NOTE: You will notice the water is missing it’s texture for the default Half-Life 2 EP2 background when you load in. This is an issue with the map being loaded out of a vpk. If you unpack the map from the vpk into your maps folder and launch the game it will be fixed.

If you have feedback feel free to shoot me an email and if you want to buy me a coffee on Ko-fi it would be really appreciated!