The purpose of this article is to help you add the code for new weapons to your Half-Life 2 mod. However difficult it may seem, I can assure you that the process is simple and straightforward once you understand how the existing weapons work.
Note that this article only covers the coding aspect; new sounds, models, etc. for your new weapon are beyond the scope of what I will cover.
Single-Player Weapons Background
Weapons fall under a special class of entities known as network entities. This means that they exist as two objects, one instance on the server and one instance on the client. As such, both the server code and the client code need a class declaration for each weapon. The easiest way to see how the system is set up is to take an example and follow it through the SDK, so for the rest of the article we will use the Pistol as our example weapon.
Let's start by taking a look at the Pistol weapon code on the server. It is located in weapon_pistol.cpp, under the "HL2 DLL" project folder. The first thing you'll notice is that both the class declaration and the implementation are in the same file. This is because there isn't any other object in the game that relies on the Pistol weapon declaration, and thus it can be put directly above the implementation.
The second thing you'll notice is that CWeaponPistol is derived from a class named CBaseHLCombatWeapon. This is a base class of all the single-player Half-Life 2 weapons on the server. While the details of this inheritance structure are beyond the scope of this article, every new single-player weapon you create should derive from CBaseHLCombatWeapon at some point in its inheritance hierarchy. It should then override the methods it needs. Examining the current weapon code will give you a good idea of what is usually overridden, and for what purpose.
For most of the single-player weapons, all the prediction and networking code you need is handled by the base class implementation. In other words, it's already written for you. Only the weapons that require special client-side effects (such as the stun-gun and physics cannon) require additional coding. Take a look at the aforementioned examples to see exactly what a weapon would do to create special client-side effects.
For the weapons you will usually be creating, there is a special file called c_weapon__stubs_hl2.cpp. A macro named STUB_WEAPON_CLASS creates a basic client-side class declaration for your weapon that does nothing but serve as the instantiable object on the client.
Adding a Single-Player Weapon
Now that you know a little about the structure of single-player weapons, how about adding one of your own? For this article we'll just copy the Pistol code verbatim, and give it a different name.
Create a new CPP file for your weapon. Name is weapon_<newname>.cpp, where <newname> is the name of your weapon. I used "killer" in place of <newname>, although you can use whatever in want in place of "killer." You can place the file anywhere, although the best place is probably with the rest of the weapon code (src dlls hl2_dll).
Open the Pistol code file (weapon_pistol.cpp) and copy all the code to your new file.
In your new file, change all instances of weapon_pistol to weapon_killer. Change all instances of CWeaponPistol to CWeaponKiller. There will be a bunch of #define statements that use the word PISTOL. Change them to use KILLER instead - don't forget to change where they're referenced in the file as well. Lastly, change the console variable declared at the top of the file (of type ConVar) to use "killer" as well, and change all references to this variable.
Your work on the server side is done. Now open up your client project, and go to the file c_weapon__stubs_hl2.cpp. Add your weapon to the list of stubs, following a similar format as the rest of them.
That's it! All the necessary changes to the code for your new weapon have been made. The final step involves creating a script file for your new weapon that contains resource information. Open up the folder <modname>\scripts and locate the file weapon_pistol.txt. Copy the file and name the new copy weapon_killer.txt. Open the file for editing. From here you can edit certain properties of your weapon. The most important change for the weapon to function properly in-game is for you to set up the bucket and position correctly. I left the bucket the same, and changed the position to 2 (since the Pistol and 357 Magnum occupy positions 0 and 1, respectively).
And you're done. Load up your mod in Half-Life 2 and open a test map. Type give weapon_killer in the console. You should receive your new weapon! Typing impulse 101 at this point won't work because we haven't set up the gun to be given during that command, however you can do an impulse 101 followed by the give weapon_killer command to play around with the weapon for a while.
After the weapon has been added to your code, all that remains are the appropriate modifications to weapon models, sounds, and other such resources.