Posted by: Persuter
Date posted: Mar 17 2003 User Rating: 4 out of 5.0 | Number of views: 10579 Number of comments: 10 | Description: both client and server side detailed |
(Disclaimer: I know this works for SDK 2.2, I don't know about SDK 2.3. It should work, but please email me at persuter@planethalflife.com if you find differently.)
This tutorial's aim is not to particularly explain HOW to program a weapon; that will be different for each weapon. Instead, this tutorial will provide a checklist for all the little niggling details that are required before your server-side and client-side weapon code can work in Half-Life.
For this tutorial, I will create an example gun, called, usefully enough, CExampleGun. You will see that there are many different names for it. I will highlight my added code with bold face.
We'll start off by explaining the stuff you need to do on the server side:
Go to func_break.cpp, around line 62, you will add your weapon to the list of things a breakable can spawn.
| | | const char *CBreakable::pSpawnObjects[] =
{
NULL, // 0
"item_battery", // 1
"item_healthkit", // 2
"weapon_9mmhandgun",// 3
"ammo_9mmclip", // 4
"weapon_9mmAR", // 5
"ammo_9mmAR", // 6
"ammo_ARgrenades", // 7
"weapon_shotgun", // 8
"ammo_buckshot", // 9
"weapon_crossbow", // 10
"ammo_crossbow", // 11
"weapon_357", // 12
"ammo_357", // 13
"weapon_rpg", // 14
"ammo_rpgclip", // 15
"ammo_gaussclip", // 16
"weapon_handgrenade",// 17
"weapon_tripmine", // 18
"weapon_satchel", // 19
"weapon_snark", // 20
"weapon_hornetgun", // 21
"weapon_example", // 22
}; |
Next, go to weapons.cpp, and around line 340, add a UTIL_PrecacheOtherWeapon for your weapon.
| | | // glock
UTIL_PrecacheOtherWeapon( "weapon_9mmhandgun" );
UTIL_PrecacheOther( "ammo_9mmclip" );
// mp5
UTIL_PrecacheOtherWeapon( "weapon_9mmAR" );
UTIL_PrecacheOther( "ammo_9mmAR" );
UTIL_PrecacheOther( "ammo_ARgrenades" );
// example weapon
UTIL_PrecacheOtherWeapon( "weapon_example" );
|
Next, go to line 89 in weapons.h, and add your weapon's define name.
| | | #define WEAPON_TRIPMINE 13
#define WEAPON_SATCHEL 14
#define WEAPON_SNARK 15
#define WEAPON_EXAMPLE 16 |
You may also, though it is not necessary, add defines for your weapon's weight, default ammo, max ammo, and so forth below that. In general, this is something you want to do for most weapons, but since it's dependent on each weapon (some weapons don't have ammo at all, for example), I'm not going to go through all the possibilities here.
Next, go to the very bottom of weapons.h, and add your weapon's class. It should look something like this.
| | | class CExampleGun : public CBasePlayerWeapon
{
public:
void Spawn( void );
void Precache( void );
int iItemSlot( void ) { return 4; }
int GetItemInfo(ItemInfo *p);
void PrimaryAttack( void );
void SecondaryAttack( void );
BOOL Deploy( void );
void WeaponIdle( void );
int AddToPlayer( CBasePlayer* );
virtual BOOL UseDecrement( void )
{ #if defined( CLIENT_WEAPONS )
return TRUE;
#else
return FALSE;
#endif
}
private:
unsigned short m_usExampleFire;
}; |
All of those functions and the unsigned short are necessary. Other functions and variables will probably be necessary for any particular weapon, but obviously we cannot go through that here. You will have to change iItemSlot's return value to whatever HUD slot you want it in. In this case, we have put it in the fourth slot, where the egon, gauss, rocket launcher, and so forth go.
Next, we create a file called example.cpp (name it something else for your own weapon). Most of the functions you'll have to figure out, but your cpp file should start out with something like the following. Check how the other weapons are done to finish it off.
| | | #include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "monsters.h"
#include "weapons.h"
#include "nodes.h"
#include "player.h"
LINK_ENTITY_TO_CLASS( weapon_example, CExampleGun );
void CExampleGun::Spawn( )
{
pev->classname = MAKE_STRING("weapon_example"); // hack to allow for old names
Precache( );
SET_MODEL(ENT(pev), "models/w_9mmAR.mdl"); // This should be your own weapon model
m_iId = WEAPON_EXAMPLE;
m_iDefaultAmmo = 50; // this could be replaced with EXAMPLE_DEFAULT_GIVE if you had defined it
FallInit();// get ready to fall down.
}
void CExampleGun::Precache( void )
{
// Again, you must replace these precache models and sounds with your own models and sounds
PRECACHE_MODEL("models/v_9mmAR.mdl");
PRECACHE_MODEL("models/w_9mmAR.mdl");
PRECACHE_MODEL("models/p_9mmAR.mdl");
PRECACHE_SOUND("items/9mmclip1.wav");
PRECACHE_SOUND("items/clipinsert1.wav");
PRECACHE_SOUND("items/cliprelease1.wav");
PRECACHE_SOUND ("weapons/hks1.wav");
PRECACHE_SOUND ("weapons/hks2.wav"); PRECACHE_SOUND ("weapons/hks3.wav");
// this is to hook your client-side event
m_usExampleFire = PRECACHE_EVENT( 1, "events/example.sc" );
}
int CExampleGun::GetItemInfo(ItemInfo *p)
{
p->pszName = STRING(pev->classname);
p->pszAmmo1 = "9mm";
p->iMaxAmmo1 = 200;
p->iMaxClip = -1; // means that there is no clip
p->iSlot = 3;
p->iPosition = 4;
p->iFlags = 0;
p->iId = m_iId = WEAPON_EXAMPLE;
p->iWeight = MP5_WEIGHT; // weight is for autoswitching, so it doesn't really matter much
p->pszAmmo2 = NULL; // no secondary ammo
p->iMaxAmmo2 = -1;
return 1;
}
int CExampleGun::AddToPlayer( CBasePlayer *pPlayer )
{
if ( CBasePlayerWeapon::AddToPlayer( pPlayer ) )
{
MESSAGE_BEGIN( MSG_ONE, gmsgWeapPickup, NULL, pPlayer->pev );
WRITE_BYTE( m_iId );
MESSAGE_END();
return TRUE;
}
return FALSE;
} |
One note: p->iSlot MUST be one less than whatever you put in iItemSlot. If it isn't, your weapon will not display in the HUD.
OK, that's the server-side done. We now turn our attention to the client-side.
First, go into FileView (in the left window), and in the Source Files folder you will see a folder marked hl. Right-click that folder, click \"Add Files To Folder\", and find example.cpp (it should be in the dlls directory of your source code). Double-click on example.cpp. Your weapon code is now included in the client-side.
Open ev_hldm.cpp (it's also in the hl folder) and go down to about line 67, and add the following line (the function can be called anything):
| | | void EV_EgonStop( struct event_args_s *args );
void EV_HornetGunFire( struct event_args_s *args );
void EV_TripmineFire( struct event_args_s *args );
void EV_SnarkFire( struct event_args_s *args );
void EV_ExampleFire( struct event_args_s *args ); |
Now go down in the file and you'll see the definitions of all these functions. Add your own in there. Again, check how the other weapons are done to have an idea about how to write yours.
Now, open up hl_weapons.cpp. Go to line 64, and add the following line:
| | | CHandGrenade g_HandGren;
CSatchel g_Satchel;
CTripmine g_Tripmine;
CSqueak g_Snark;
CExampleGun g_ExampleGun |
Now go down to line 637, same file, and add the following line:
| | | HUD_PrepEntity( &g_HandGren , &player );
HUD_PrepEntity( &g_Satchel , &player );
HUD_PrepEntity( &g_Tripmine , &player );
HUD_PrepEntity( &g_Snark , &player );
HUD_PrepEntity( &g_ExampleGun , &player ); |
Finally, go down to line 761, same file, and add the following lines:
| | | case WEAPON_TRIPMINE:
pWeapon = &g_Tripmine;
break;
case WEAPON_SNARK:
pWeapon = &g_Snark;
break;
case WEAPON_EXAMPLE:
pWeapon = &g_ExampleGun;
break;
|
Now go to hl_events.cpp, in the hl folder, go to line 40, and add the following line:
| | | void EV_EgonStop( struct event_args_s *args );
void EV_HornetGunFire( struct event_args_s *args );
void EV_TripmineFire( struct event_args_s *args );
void EV_SnarkFire( struct event_args_s *args );
void EV_ExampleFire( struct event_args_s *args ); |
(Yes, that's the same as the declaration you made in ev_hldm.cpp.)
Now go down to line 88, same file, and add the following line:
| | | gEngfuncs.pfnHookEvent( "events/egon_stop.sc", EV_EgonStop );
gEngfuncs.pfnHookEvent( "events/firehornet.sc", EV_HornetGunFire );
gEngfuncs.pfnHookEvent( "events/tripfire.sc", EV_TripmineFire );
gEngfuncs.pfnHookEvent( "events/snarkfire.sc", EV_SnarkFire );
gEngfuncs.pfnHookEvent( "events/example.sc", EV_ExampleFire ); |
Note that the sc file mentioned above must be the same you used in PRECACHE_EVENT in the shared weapons code.
OK, now just comes some file housekeeping. First, go into your mod's directory. Go into the events directory (if there isn't one, create one), and create a new file called example.sc. It can be totally empty, it just needs to be there. Next, go into the sprites directory and create a new text file called weapon_example.txt. I'm not wholly sure about EXACTLY how this file works, so I'll just give you an example one. There are tutorials elsewhere on the web about what exactly it is. This is just the sprite text file for the MP5, I use it for testing.
| | | // mp5
12 // number of sprites
weapon 320 320hud1 0 120 80 20
weapon_s 320 320hud1 0 140 80 20
ammo 320 320hud2 0 16 18 18
ammo2 320 320hud2 36 16 18 18
crosshair 320 crosshairs 0 48 24 24
autoaim 320 crosshairs 48 72 24 24
weapon 640 640hud1 0 135 170 45
weapon_s 640 640hud4 0 135 170 45
ammo 640 640hud7 0 72 24 24
ammo2 640 640hud7 48 72 24 24
crosshair 640 crosshairs 0 48 24 24
autoaim 640 crosshairs 48 72 24 24 |
OK, you should be done! For simplicity, I'm going to repeat this tutorial in the following checklist so once you get used to doing these things, you can simply go through the checklist. It's in kind of a funky order, and the line numbers are slightly different, but it should work fine (this is the actual checklist I use).
| | | HL dll:
func_break.cpp line 62
Add weapon entity name to breakables list
weapons.cpp line 341
Add weapon entity name to PrecacheOtherWeapon list
weapons.h line 82
Add weapon define name and any other defines you want
weapons.h end
Create weapon class declaration.
example.cpp
Program weapon.
CL dll:
Add HL directory weapon file to hl folder in project.
ev_hldm.cpp line 67
Add client-side event to list
ev_hldm.cpp line 740 (approx)
Code client-side event
hl/hl_weapons.cpp line 756
Add weapon in switch statement
line 630
Add weapon to HUD_PrepEntity
line 66
Add global variable
hl/hl_events.cpp line 82
Add hookevent
line 41
Add client-side event to list (again)
Go into <mod name>/events and add event file.
Go into <mod name>/sprites and add weapon_<weapon name>.txt | |
|
User Comments
Showing comments 1-10
I think this tutorial misses the parts about ammo and inflicting damage... But its real nice, there are a lot of questions in forums about this. I'll link to this page more often :)Edited by [NL]Mox on Jan 05 2004, 05:49:05
|
|
I did not put in how to create new types of ammo, true, but that's because not everyone wants to do that. (Indeed, it's oftentimes irrelevant what with the obsession with tactical mods today. :D) As for inflicting damage, I'm assuming you mean the Primary Attack and Secondary Attack function. I deliberately didn't include that, nor most of the actual weapon source code, because this is a tutorial about the rest of what needs to be done, not the actual programming of the weapon.
P.S. This article works fine for 2.3.Edited by Persuter on Feb 09 2004, 10:52:26
|
|
I think it would be very useful to others if you went over using ammo and inflicting damage.
but it is a very good tutorial gj.Edited by Bryan on Mar 12 2004, 11:31:55
|
|
|
(Indeed, it's oftentimes irrelevant what with the obsession with tactical mods today. :D) I would've thought you would know better than to encourage more CS clones! |
|
|
Well in all seriousness there's no reason to add new types of ammo these days. |
|
|
if you want a tutorial that does take that up i an tutorial visit www.wired-mod.tk |
|
|
Not to rain on your parade but there is no such article on your site. |
|
I´ve tried to do somethin similar to this in my MOD, I tried to make the weapon fires right and left guns ( it´s twohanded) if you press right or left mousebutton, even when it worked (copy-paste of MP5´s code) I cannot make the muzzleflash appears in the right gun, and the shells ejected are only the ones from the right gun, and appears in the middle of the screen!!!
what´s the problem then? |
|
|
EDIT:FixedEdited by cossack13 on Oct 26 2006, 07:13:33
|
|
|
Errr...cossack, do as I, learn a bit more C++ before going any far in MOD creation, believe me, you must do it. The tutorial works fine if you take a deeper look to it; the errors you receive are self explanatory ( missing declarations of functions and classes, etc. not sure at a 100% ), this tutorial helped me to fix my MOD´s weapons. :D |
|
You must register to post a comment. If you have already registered, you must login.
|
296 Approved Articless
5 Pending Articles
3940 Registered Members
0 People Online (16 guests)
|
|