Snarkpit Articles


First of all I would like to thank Wil5on for his help with the code, you taught me some valuable stuff and couldn't have done it with out ya smiley

Now, this tutorial if for all the coding n00bs out there, like me who have trouble finding working tutorials. In this tutorial will will have a look at how to override that unbalanced mp5 grenade and replace it with a zoom feature. Then will will have a look at how to tweak the mp5's accuracy and range to better suit its shiny new zoom feature. To do this tutorial, we need the half-life sdk 2.3 or the spirit of half-life source or equivalent and a c++ editor/compiler, would you like some links? No problem.

C++ Compiler/Editor :: Spirit of Half-life 1.2 Source :: Half-life SDK 2.3

Before we begin, we need to back up our source code and dlls (as you always should when coding). Once you do that we can begin.

Note: Code will be written in red.

Much better. Now for this tutorial we will be working on the server side. Server means we are working with the hl.dll, spirit.dll etc, client means we are working with the client.dll. Now we need to open up a file called mp5.cpp Scroll down till we get to mp5's secondary attack info. It looks like this...


void CMP5::SecondaryAttack( void )
{
// don't fire underwater
if (m_pPlayer->pev->waterlevel == 3 && m_pPlayer->pev->watertype > CONTENT_FLYFIELD)
{

PlayEmptySound( );
m_flNextPrimaryAttack = 0.15;
return;
}

if (m_pPlayer->m_rgAmmo[m_iSecondaryAmmoType] == 0)
{
PlayEmptySound( );
return;
}

m_pPlayer->m_iWeaponVolume = NORMAL_GUN_VOLUME;
m_pPlayer->m_iWeaponFlash = BRIGHT_GUN_FLASH;

m_pPlayer->m_iExtraSoundTypes = bits_SOUND_DANGER;
m_pPlayer->m_flStopExtraSoundTime = UTIL_WeaponTimeBase() + 0.2;

m_pPlayer->m_rgAmmo[m_iSecondaryAmmoType]--;

// player "shoot" animation
m_pPlayer->SetAnimation( PLAYER_ATTACK1 );

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

// we don't add in player velocity anymore.
CGrenade::ShootContact( m_pPlayer->pev,
m_pPlayer->pev->origin + m_pPlayer->pev->view_ofs + gpGlobals->v_forward * 16,
gpGlobals->v_forward * 800 );

int flags;
#if defined( CLIENT_WEAPONS )
flags = FEV_NOTHOST;
#else
flags = 0;
#endif

PLAYBACK_EVENT( flags, m_pPlayer->edict(), m_usMP52 );

m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 1;
m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 1;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 5;// idle pretty soon after shooting.

if (!m_pPlayer->m_rgAmmo[m_iSecondaryAmmoType])
// HEV suit - indicate out of ammo condition
m_pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0);
}


It will look different depending on the source code that you use but the first line should be the same in all source code. We don't want the mp5 grenade function anymore, so we want to get rid of it, but we still need some secondary attack. This is where the zoom comes in. Now what we want to do is replace this code with different code that you will see in a few short seconds, if you keep reading. So highlight the following code (in this tutorial), copy it and paste it over the existing code (what you have):


void CMP5::SecondaryAttack( void )
{
if ( m_pPlayer->pev->fov != 0 )
{
m_pPlayer->pev->fov = m_pPlayer->m_iFOV = 0; // 0 means reset to default fov
m_fInZoom = 0;
}
else if ( m_pPlayer->pev->fov != 20 )
{
m_pPlayer->pev->fov = m_pPlayer->m_iFOV = 20;
m_fInZoom = 1;
}

SetNextThink( 0.1 );
m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 1.0;

}


Also in mp5.cpp we need to add some code that makes the weapon zoom out when we reload. Find the line void CMP5::Reload( void ) and under the opening brace which is under that line, paste in:


if ( m_pPlayer->pev->fov != 0 )
{
SecondaryAttack();
}


Believe it or not, you have just done most of the hard work. But where not done yet. C++ is complex, in the code it refers to other bits of code and other files all the time. Think of it like mapping, the sound, textures, models, sprites and so on are not all contained in the .bsp file. They are else where, so now if you like, we will add some more code. Open up weapons.h. Now this is a big file so it may take a little time to find the lines of code we want. You can use the search feature if you want, but it doesn't always help. We are looking for this line of code, which is near the middle in the bottom half, in my source code:


class CMP5 : public CBasePlayerWeapon
{
public:
void Spawn( void );
void Precache( void );
int iItemSlot( void ) { return 3; }
int GetItemInfo(ItemInfo *p);
int AddToPlayer( CBasePlayer *pPlayer );

void PrimaryAttack( void );
void SecondaryAttack( void );
int SecondaryAmmoIndex( void );
BOOL Deploy( void );
void Reload( void );
void WeaponIdle( void );
float m_flNextAnimTime;
int m_iShell;

virtual BOOL UseDecrement( void )
{
#if defined( CLIENT_WEAPONS )
return TRUE;
#else
return FALSE;
#endif
}

private:
unsigned short m_usMP5;
unsigned short m_usMP52;
};


We only need to add one line of code inside here, we are not deleting anything. Under int m_iShell; add in int m_fInZoom; // don't save this. So now the code should look something like this, depending on your source code:


class CMP5 : public CBasePlayerWeapon
{
public:
void Spawn( void );
void Precache( void );
int iItemSlot( void ) { return 3; }
int GetItemInfo(ItemInfo *p);
int AddToPlayer( CBasePlayer *pPlayer );

void PrimaryAttack( void );
void SecondaryAttack( void );
int SecondaryAmmoIndex( void );
BOOL Deploy( void );
void Reload( void );
void WeaponIdle( void );
float m_flNextAnimTime;
int m_iShell;
int m_fInZoom; // don't save this

virtual BOOL UseDecrement( void )
{
#if defined( CLIENT_WEAPONS )
return TRUE;
#else
return FALSE;
#endif
}

private:
unsigned short m_usMP5;
unsigned short m_usMP52;
};


That tiny amount of code has made out whole zoom feature work. We have somewhat recycled so far. We are using the crossbows zoom feature on the mp5. A bit like using a model more than once in a map. You can now compile the hl.dll and the client.dll or whatever it is for you. To do this open the hl.dsp on the client side and cl_dll.dsp on the server side. If you are using the program linked at the top you can click on build> build client.dll/hl.dll in the menus. After the first time you compile I recommend you use rebuild all instead of build. It will spit out the two dll's somewhere inside a newly created file in your source code something like "releasehl" or whatever.

You now should have a working zoom feature on your mp5. But one thing you may be thinking, "I cant see the scope on top of the gun", well lol to you sir. You need to add a scope to it, its called modeling. Now as I promised before, we will tweak your weapon a little bit, if you want. Go back to the mp5.cpp on the client side. But this time we are looking for this line: void CMP5::PrimaryAttack() which should be above the code we where working on before. Now inside this function is where the weapon accuracy and range is stored. Look for this line inside that function, just a little bit down. We want this one:


// optimized multiplayer. Widened to make it easier to hit a moving player
vecDir = m_pPlayer->FireBulletsPlayer( 1, vecSrc, vecAiming, VECTOR_CONE_1DEGREES, 4500, BULLET_PLAYER_MP5, 2, 0, m_pPlayer->pev,
m_pPlayer->random_seed );


and this one :


// single player spread,br> vecDir = m_pPlayer->FireBulletsPlayer( 1, vecSrc, vecAiming, VECTOR_CONE_1DEGREES, 4500, BULLET_PLAYER_MP5, 2, 0, m_pPlayer->pev,
m_pPlayer->random_seed );


The first one is for multiplayer. Yess valve has made it so that the some weapons, including the mp5, have different accuracy and range in multiplayer than single player. Now this will look the tiniest bit different to yours because I have already modified it. Anyways here is where the weapon accuracy is stored:


VECTOR_CONE_1DEGREES


and the weapon's range in units (mapping):


4500


Feel free to tweak the latter value freely, however the first one has preset values that must be used. Meaning that 1DEGREES represents a value. Here are all the possible values you can have:


VECTOR_CONE_1DEGREES
VECTOR_CONE_2DEGREES
VECTOR_CONE_3DEGREES
VECTOR_CONE_4DEGREES
VECTOR_CONE_5DEGREES
VECTOR_CONE_6DEGREES
VECTOR_CONE_7DEGREES
VECTOR_CONE_8DEGREES
VECTOR_CONE_9DEGREES
VECTOR_CONE_10DEGREEs
VECTOR_CONE_15DEGREES
VECTOR_CONE_20DEGREES


The smaller the value the greater the accuracy. Remember if you change the values you must recompile your code, both server AND client side because they refer to each other, remember that. The server and client side both use the mp5.cpp and the weapons.h. Now to improve our code, we need to add something to make the mp5 zoom out when we swap weapons. To do this, simply add:


void CMP5::Holster( int skiplocal /* = 0 */ )
{
if ( m_fInZoom )
{
SecondaryAttack( );
}
}



Next open up weapons.h and search for this class class CMP5 : public CBasePlayerWeapon and inside that class look for the line int m_fInZoom; // don't save this paste the following code after that void Holster( int skiplocal = 0 );. So that section should now look something like this:


int m_iShell;
int m_fInZoom; // don't save this
void Holster( int skiplocal = 0 );

virtual BOOL UseDecrement( void )
{


And that's about it. If any of the links are broken please send me an email to aarondakilla@gmail.com.



Post ReplyView Topic
Discussion
0 starsPosted by Vortiguantian on Fri Aug 7th 2009 at 1:50pm

Why not just delete the original grenade launcher .wav (that would be glauncher.wav and glauncher2.wav I belive)in half-life 1's .pak file?
[author]
Posted by Le Chief on Fri Aug 7th 2009 at 12:38pm

Good points. smiley

I have to admit, when I wrote this tutorial I was n00by and used the Spirit Of Half-Life code instead of the proper Half-Life source code. Truth is the Spirit Of Half-Life code is a massive mess and real buggy!

As for the grenade sound, I didn't notice it, nice find. I should probably update the tutorial but it's been so long since I've opened the Half-Life code I've forgotten alot of stuff.

0 starsPosted by Dragos on Fri Aug 7th 2009 at 12:08pm

Great tutorial! smiley Everything is working perfectly except one little mistake you made in the code.

This line:

SetNextThink( 0.1 );

Should be replaced with this one:

pev->nextthink = gpGlobals->time + 0.1;

Because SetNextThink is not used in original HL SDK. It's a Spirit of Half-Life command.

By the way there is another little bug in-game, when you switch between normal and the zoom mode you can hear the grenade launch sound.

Sorry for my poor English. smiley
Post ReplyView Topic