How to Create Custom Items and "item_speed" for Half-Life

In this tutorial I will give explanation on how to create new "items" for Half-Life 1 mods. As added extra I will give the code for item_speed. this is a custom item I coded for my mod FlatLine Arena that upon activation gives you a boost of extra speed.

This tutorial will give you the basic steps you need to create a generic item in Gold Source engine. You need some knowledge in C++ in order to pull this off. The tutorial is not intended to be "copy-paste" (but it is pretty much that).

We're going to work on the server side of the Half-Life 1 code.

Take a note that I will not be held impressible for any bad things that might happen to your mod's code if you follow this tutorial. Make sure to backup your code often...

What are we going to need?

  1. Microsoft Visual Studio C++ 2010 Well, any version of the Visual Studio will do, as long as you have the compatible Half-Life SDK to go with it.

Important Note: This is not a tutorial on setting up your SDK or Visual Studio. I am with the presumption that you already have the SDK, you know how to compile it and you actually have a working build for your mod.

  1. Half-Life SDK 2.3 and above, preferably compatible with Microsoft Visual Studio C++ 2010 and above.

  2. Notepad++ I prefer to do the code modification is this tool. You can use any other tool including the native

  3. Half-Life + Your mod

Ok let us start.

I must apologize, this tutorial will have no pictures, just code snippets. Well, what do you expect? Screenshots from the C++ code?

Below I will outline the steps needed to code a generic item and then I will give the code for my "Extra Speed" item for my mod "FlatLine Arena" (Well most of it anyway, I have extra options, messages, effects and sounds - but let's keep it clear and simple).

I will try to keep it simple, but at the end of this you should be able to create your own custom items and you will have a working item that upon acquisition and pressing the "+speedpack" key will allow you to move a lot faster in all directions (including swimming and flying, assuming you have flight in your mod).

So what is an item?

Well that's easy it is a pick up, that you can activate to use or a pickup that gives you a boost of stats when obtained.

Examples? Really - longjump module, battery pack, health kit, keay card, antidote etc.

So what do you need to create custom items:

Creating Half-Life 1 Items in 6 Steps (List of actions, not code...)

  1. Code that will be the effect for the item, let us say you have an awesome code that can make you player fly, invisible, or give him extra HP, armor or DMG (in my example I will give the player more speed). :)

  2. In the server side "items.cpp" you need to define your new item routines.

  3. Again the server side, in "weapons.h", look for "#define item_*" and define your item. Make sure to pick unique number sine you will get errors if there is a conflict.

  4. In "weapons.ccp" you need to precache your new item, or the game will crash the time you try to spawn/obtain your item, and you do not wish that right? (Or maybe you do?)

You know you can create item that crash the game if that is the objective... for example when a player uses impulse 101, but I prefer different medicine.. like spawning a Gargantua or a black hole when using the cheat code...

  1. You can add the item to the impulse command in "player.cpp" you need to look for "case 101:" and add the item name there.

  2. Create an entry in the .fgd file for mappers to place in maps. I will also explain how to do that. I might do a tutorial on how to create custom .fgd file for your mod later on as well. 

That's pretty much everything you need to do in order to create a new item. Compile and profit.

Bonus: You can add extra effects, sounds etc. You can make the item to take HEV battery etc. Tt is up to you. There are endless possibilities and only the sjy is the limit.

That said the code part starts here. The tutorial is pretty much copy-paste, but I hope you will learn something from it.

We'll work only on the server side of the SDK code.

  1. This needs to be added in "player.h" in the public section of "class CBasePlayer : public CBaseMonster" below this:

char m_szTeamName[TEAM_NAME_LENGTH];

add this:

// Napoleon was here

void ExtraSpeed( ); // Faster than a speeding bullet!

BOOL m_fExtraSpeed; // Yeah I do have the item...

BOOL m_fExtraSpeedKeyDown; // Yeah I see you're pressing the speed key

// End Speed code

  1. This need to be added in : "player.cpp". Normally I would add those right above the routines for DeadHev, still anywhere in player.cpp will do.

//=========================================================

// ExtraSpeed routines (used for item)

//=========================================================

// Napoleon was here

// Entry for the extra speed item

void CBasePlayer::ExtraSpeed( )

{

if(!m_fExtraSpeed) //if we don't have extraspeed return

return;

if(m_fExtraSpeedKeyDown) // are we pressing the speed key?

{

if ( !FBitSet(pev->flags, FL_ONGROUND) ) // are we on the ground?

{

pev->movetype = MOVETYPE_WALK; // move!

return;

}

if( pev->button & IN_FORWARD ) // are we moving forward?

{

pev->movetype = MOVETYPE_FLY; // hack!

UTIL_MakeVectors( pev->v_angle + pev->punchangle );

Vector New_Position = pev->origin + gpGlobals->v_forward * 500; // how far forward?

pev->velocity = New_Position- pev->origin;

return;

}

if( pev->button & IN_BACK ) // are we moving back?

{

pev->movetype = MOVETYPE_FLY; // hack!

UTIL_MakeVectors( pev->v_angle + pev->punchangle );

Vector New_Position = pev->origin - gpGlobals->v_forward * 500; // how far back?

pev->velocity = New_Position- pev->origin;

return;

}

if( pev->button & IN_MOVERIGHT ) // are we moving right?

{

pev->movetype = MOVETYPE_FLY; // hack!

UTIL_MakeVectors( pev->v_angle + pev->punchangle );

Vector New_Position = pev->origin + gpGlobals->v_right * 500; // how far right?

pev->velocity = New_Position- pev->origin;

return;

}

if( pev->button & IN_MOVELEFT ) // are we moving left?

{ pev->movetype = MOVETYPE_FLY; // hack!

UTIL_MakeVectors( pev->v_angle + pev->punchangle );

Vector New_Position = pev->origin - gpGlobals->v_right * 500; // how far left?

pev->velocity = New_Position- pev->origin;

return;

}

}

}

// End Extra speed

Note you can experiment with the speed, I find it best at 500.

  1. Now go to void CBasePlayer::PreThink(void) (again in player.cpp) and add the below code between:

UTIL_MakeVectors(pev->v_angle); // is this still used?

and

ItemPreFrame( );

Add this code:

// Napoleon was here

// extra speed entry :P

ExtraSpeed(); // Faster than a speeding bullet!

// End speed entry

Now why did I added this here? To get the player speeding when the "+speedpack" button is pressed. "+speedpack" button? Yeah, we will define it in a second. Still before that...

  1. One last thing to do in player.cpp we want to make sure they don not keep the speedpack when they die.

look for:

// this client isn't going to be thinking for a while, so reset the sound until they respawn

and above it add:

// Napoleon was here

// fatser than a speeding bullet

m_fExtraSpeed = FALSE; // you died so no speed bonus for you when respawning (unless you get the item again)

// end speed

  1. Now on the topic of the speed button... OK, now open client.cpp so we can add the "+speedpack" command. Search for:

GetClassPtr((CBasePlayer *)pev)->SelectLastItem();

and below it add this:

// Napoleon was here

// faster than a speeding bullet

// you need to bind "+speedpack" to a key for this to work

else if (FStrEq(pcmd, "+speedpack" ))

{

//We are holding the key set this.

GetClassPtr((CBasePlayer *)pev)->m_fExtraSpeedKeyDown = TRUE;

}

// you don't need to bind this

else if (FStrEq(pcmd, "-speedpack" ))

{

//We are not holding the key un-set this.

GetClassPtr((CBasePlayer *)pev)->m_fExtraSpeedKeyDown = FALSE;

}

// end speeding bullet

  1. OK, now we have the awesome move code and we have the command for the speedpack activation, yet we are missing the item. Let us create it.

This needs to be added in "items.cpp" (at the very bottom).

// Napoleon was here

// ExtraSpeed item code goes below :)

class CItemExtraSpeed : public CItem

{

void Spawn( void )

{

Precache( );

//the mdl we see on the ground; make sure o precache it... or the game will crash

SET_MODEL(ENT(pev), "models/w_longjump.mdl"); // feel free to change the model

CItem::Spawn( );

}

void Precache( void )

{

//precache it here, else the game crash

PRECACHE_MODEL ("models/w_longjump.mdl"); // feel free to change the model

}

BOOL MyTouch( CBasePlayer *pPlayer )

{

if ( pPlayer->m_fExtraSpeed )

{

return FALSE; //don't let us pick up a pack if we have one; you don't need to be that fast...

}

pPlayer->m_fExtraSpeed = TRUE;// player now has extra speed

// Go tell the world the good news (well tell the player)

MESSAGE_BEGIN( MSG_ONE, gmsgItemPickup, NULL, pPlayer->pev );

WRITE_STRING( STRING(pev->classname) ); //i dunno why but this should be here

MESSAGE_END();

return TRUE;

}

};

//bind the class to entity

LINK_ENTITY_TO_CLASS( item_speed, CItemExtraSpeed ); // we use this for placement on maps

// End Extra speed

  1. So now we are almost done. Few more touching moves.

We need to precahe the item, to include it in impulse 101 (the first one is mandatory, else expect crashes, the second one is to get the extra speed item) we need to #define item_speed in "weapons.h". Do not forget to define that the player starts with no super speed :P

go to "weapons.h", look for:

#define ITEM_BATTERY 4

and below that add the following:

// Napoleon was here

#define ITEM_SPEED 5 // entry for the speed item

// End speed item

Note: Make sure to place the appropriate number for the item (I am assuming you have no extra items defined, if you do you need to change the value).

Go to "weapons.ccp", in "void W_Precache(void)", look for;

// common world objects

and below the entry for "item_longjump" add your item:

// Napoleon was here

// if you don't precache it here the game will crash when you try to get the item

UTIL_PrecacheOther( "item_speed" ); // Faster than a speeding bullet

// end speed item

Now you would like to add the new item to the impulse 101 cheat right? (admit it... you love cheating!)

Go back to "player.cpp", look for "case 101:" and "GiveNamedItem( "item_longjump" );" and add the following below:

// Napoleon was here

// and you do like cheating

GiveNamedItem( "item_speed" ); // faster than a speeding bullet

// end speed item

Again in "player.cpp" look for " " and below it add:

// Napoleon was here

m_fExtraSpeed = FALSE; // no speedpack on spawn

// end extraspeed

  1. Go and compile the server and the client dlls. There should be no errors upon comoile. If there are.. you will need to troubleshoot them. After the compile, fire your mod amd try your new speed item.

sv_cheats 1 ; restart ; impule 101 or give item_speed Don't forget you need to bind a key to "+speedpack" to get the boost of speed when you have the item and you press the button :)

  1. Now about the .fgd file. Open the file with Notepad++ and add this at the bottom of the file:

@PointClass size(-16 -16 0, 16 16 36) base(Weapon, Targetx) studio("models/w_longjump.mdl") = item_speed : "SpeedPack Module" []

Change the model, if you added different model.

  1. For extra points you can also add:
  • Announcer sounds when picked up.
  • Sprites for extra effects and when picked up (for that you need knowledge on how to send messages).
  • You can make it to use HEV battery and to make sound when used.

The possibilities are endless. Still I will leave that for you.

Feel free to use in your mod and give me a feedback if you like it. If you use my code, please give credit when credit is due. :)

Have fun and happy coding. :)

You can watch a video of the item in action here:


Speedpack - Mod DB

If you don’t like something – MOD it!

Napoleon was here at some undisclosed time in 2021…