Semi or Burst fire: Difference between revisions

From Valve Developer Community
Jump to navigation Jump to search
mNo edit summary
(Cleaned up the article a bit. Defined exactly what needs to be done to finish the cleanup.)
Line 1: Line 1:
{{template:cleanup}}
{{template:cleanup}}
{{template:pov}}


This is a simple tutorial about adding semi-auto or burst fire mode to a weapon.


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 added extra lines are marked bold.
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 holds the maximum number of bullets to be fired with 1 trigger pull (mouse click). In semi-auto, you would add 1. For a 3 shot burst add 3 etc.
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_SHOT_PENALTY_TIME 0.2f // Applied amount of time each shot adds to the time we must recover from
Line 12: Line 12:




Now look up this part in the code at the declaration of the pistol class. Then add the bold lines. You can copy-paste it over the original part if you would like to.
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:
  private:
Line 48: Line 48:
  END_PREDICTION_DATA()
  END_PREDICTION_DATA()


This created the m_iSemi variable. The code above has something to do with client side prediction, to ease the server load. The important part is that it works.
This will create the ''m_iSemi'' variable that will hold the ''MAXBURST'' constant.


Now set up our new variable in the constructor:
The code above has something to do with client side prediction, to ease the server load. The important part is that it works.
 
{{todo|Find out what it does.}}
 
Set up the new variable in the constructor with this line:
   
   
  CWeaponPistol::CWeaponPistol( void )
  CWeaponPistol::CWeaponPistol( void )
Line 64: Line 68:
  }
  }


Here comes the tricky part. Look up the ''ItemPostFrame'' procedure and add these lines:
Time to add the actual code. Look up the ''ItemPostFrame'' procedure and add these lines:
   
   
  '''CBasePlayer *pOwner = ToBasePlayer( GetOwner() );'''
  '''CBasePlayer *pOwner = ToBasePlayer( GetOwner() );'''
Line 70: Line 74:
  '''{m_iSemi = MAXBURST;} '''
  '''{m_iSemi = MAXBURST;} '''


This sets the m_iSemi variable to the pre-defined constant. The logic check is funny with only the ELSE part having code. This works, but feel free to make it more elegant.
This sets the ''m_iSemi'' variable to the ''MAXBURST'' constant.
To finish up the modification, add the bold lines into the ''PrimaryAttack'' procedure:
 
{{todo|The logic check is funny with only the ELSE part having code. Make this more elegant.}}
 
To finish up the modification, add these bold lines into the ''PrimaryAttack'' procedure:
 
  '''if (m_iSemi<=0)'''
  '''if (m_iSemi<=0)'''
  '''{ return; }'''
  '''{ return; }'''
Line 77: Line 85:
  BaseClass::PrimaryAttack();
  BaseClass::PrimaryAttack();


Now this will deduct each shot fired from the maximum number of allowed shots as long as you push the button. If the gun fired the definded number of bullets, the gun will cease to fire. You would need to release the trigger and push it again for an other shot/burst. Case finnished.
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.
HINT: To make a gun selective fire you would need to set up an extra bool variable (like m_bSemi) and trigger it with something (like 2nd fire). Then replace the  '''m_iSemi--;''' line with this '''if ( m_bSemi ) {m_iSemi--;}'''.
 
{{todo|Write a section on selective fire. To make a gun selective fire, one would need to set up an extra bool variable (like ''m_bSemi'') and trigger it with something (like alt fire), and then replace the  '''m_iSemi--;''' line with this: '''if ( m_bSemi ) {m_iSemi--;}'''.}}

Revision as of 05:31, 19 August 2006

Broom icon.png
This article or section needs to be cleaned up to conform to a higher standard of quality.
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.

Todo: Find out what it does.

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  ){}else 
{m_iSemi = MAXBURST;} 

This sets the m_iSemi variable to the MAXBURST constant.

Todo: The logic check is funny with only the ELSE part having code. Make this more elegant.

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.

Todo: Write a section on selective fire. To make a gun selective fire, one would need to set up an extra bool variable (like m_bSemi) and trigger it with something (like alt fire), and then replace the m_iSemi--; line with this: if ( m_bSemi ) {m_iSemi--;}.