Semi or Burst fire

For help, see the VDC Editing Help and Wikipedia cleanup process. Also, remember to check for any notes left by the tagger at this article's talk page.
This is a simple tutorial about adding semi-auto or burst fire mode to a weapon.
The weapon_pistol.cpp will be used as the basis of this tutorial. The extra lines to add are marked in bold.
First define a constant that will hold the maximum number of bullets to be fired with one trigger pull (mouse click). (Set it to 1 for semi-auto, to 3 for a 3 shot burst, etc.)
#define PISTOL_ACCURACY_SHOT_PENALTY_TIME 0.2f // Applied amount of time each shot adds to the time we must recover from #define PISTOL_ACCURACY_MAXIMUM_PENALTY_TIME 1.5f // Maximum penalty to deal out #define MAXBURST 1
At the declaration of the pistol class, add the following lines. (You can copy-paste these sections over the original part if you would like to.)
private: CNetworkVar( float, m_flSoonestPrimaryAttack ); CNetworkVar( float, m_flLastAttackTime ); CNetworkVar( float, m_flAccuracyPenalty ); CNetworkVar( int, m_nNumShotsFired ); CNetworkVar( int, m_iSemi );
private: CWeaponPistol( const CWeaponPistol & ); };
IMPLEMENT_NETWORKCLASS_ALIASED( WeaponPistol, DT_WeaponPistol ) BEGIN_NETWORK_TABLE( CWeaponPistol, DT_WeaponPistol ) #ifdef CLIENT_DLL RecvPropTime( RECVINFO( m_flSoonestPrimaryAttack ) ), RecvPropTime( RECVINFO( m_flLastAttackTime ) ), RecvPropFloat( RECVINFO( m_flAccuracyPenalty ) ), RecvPropInt( RECVINFO( m_nNumShotsFired ) ), RecvPropInt( RECVINFO( m_iSemi ) ), #else SendPropTime( SENDINFO( m_flSoonestPrimaryAttack ) ), SendPropTime( SENDINFO( m_flLastAttackTime ) ), SendPropFloat( SENDINFO( m_flAccuracyPenalty ) ), SendPropInt( SENDINFO( m_nNumShotsFired ) ), SendPropInt( SENDINFO( m_iSemi ) ), #endif END_NETWORK_TABLE()
BEGIN_PREDICTION_DATA( CWeaponPistol ) DEFINE_PRED_FIELD( m_iSemi, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ), END_PREDICTION_DATA()
This will create the m_iSemi variable that will hold the MAXBURST constant.
The code above has something to do with client side prediction, to ease the server load. The important part is that it works.
Set up the new variable in the constructor with this line:
CWeaponPistol::CWeaponPistol( void ) { m_flSoonestPrimaryAttack = gpGlobals->curtime; m_flAccuracyPenalty = 0.0f; m_fMinRange1 = 24; m_fMaxRange1 = 1500; m_fMinRange2 = 24; m_fMaxRange2 = 200; m_bFiresUnderwater = true; m_iSemi=MAXBURST; }
Time to add the actual code. Look up the ItemPostFrame procedure and add these lines:
CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); if ( !(pOwner->m_nButtons & IN_ATTACK) ) m_iSemi = MAXBURST;
This sets the m_iSemi variable to the MAXBURST constant.
To finish up the modification, add these bold lines into the PrimaryAttack procedure:
if (m_iSemi<=0) return; m_iSemi--; BaseClass::PrimaryAttack();
This will deduct each shot fired from the maximum number of allowed shots as long as the trigger is pushed in, and will cease when the gun has fired the defined number of bullets. The player would need to release the trigger and push it again for an other shot/burst.