This tutorial was originally written by AssKicka at solidground@planetquake.com.

Included here are personal notes made to deal with areas that were difficult to follow in the original tutorial due to for example differing version numbers.

To get around the problem of differing numbers included the source code necessary to determine the where the changes need to be made will be included as well as a rough line number

This version assumes that the following versions are being used: Note Related sprites and models from solid ground 2.0 are here

1. Adding weapon and ammo definitions.

Adding a flag
file - bg_public.h
line - 303
typedef enum {
   .
   .
   .
   WP_FLAME_THROWER, //tute10.1
   .
   .
   .
} weapon_t;   

Adding a method of death flag
file - bg_public.h
line - 574
// means of death
typedef enum {
   .
   .
   .
   MOD_FLAME_THROWER, //tute10.2
   .
   .
   .
} meansOfDeath_t;   

Adding the method of death string
file - g_active.c
line - 268
note - the order does not matter because it is strings being passed or values already predefined
// these are just for logging, the client prints its own messages
char	*modNames[] = {
   .
   .
   .
	"MOD_FLAME_THROWER", //tute10.3
   .	
   .
   .   
};   

Adding the inventory and model indexes
file - inv.h
line - anywhere in the file
#define INVENTORY_FLAMETHROWER 35 //tute10.4
#define MODELINDEX_FLAMETHROWER 36 //tute10.4

Defining the flamethrower
file - bg_misc.c
line - near the other weapon definitions which look very similar
//tute10.5
/*
 *QUAKED weapon_flamethrower (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
 */
{
   "weapon_flamethrower",
   "sound/misc/w_pkup.wav",

   {"models/weapons2/flamethrower/flamethrower.md3", 0, 0, 0},
   
   /* icon */     "icons/iconw_flame",   
   /* pickup */   "Flame Thrower", 20,IT_WEAPON,WP_FLAME_THROWER,   
   /* precache */ "",
   /* sounds */   ""
},


Defining the flamethrower ammo
file - bg_misc.c
line - near the other ammo definitions which look very similar

//tute10.6
/*
 *QUAKED ammo_flame (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
 */
{
   "ammo_flame",
   "sound/misc/am_pkup.wav",

   {"models/powerups/ammo/bfgam.md3", 0, 0, 0},
      
   /* icon */      "icons/icona_bfg",
   /* pickup */    "Flame Ammo",50,IT_AMMO,WP_FLAME_THROWER,
   /* precache */  "",
   /* sounds */    ""   
},


2. Setting the rate of fire

file - bg_pmove.c
line - anywhere as long as it does not replace the guantlet as a the default
/*
==============
PM_Weapon

Generates weapon events and modifes the weapon counter
==============
*/
static void PM_Weapon( void ) {
   .
   .
   .
   switch( pm->ps->weapon ) 
   {
	default:
	case WP_GAUNTLET:
		addTime = 400;
		break;
      	case WP_FLAME_THROWER: //tute10.7
		addTime = 40;
	.
	.
	.
   }	
   .
   .
   .
}

3. Spawn the player with the flamethrower

file - g_client.c
line - as long as it is after the definition for the machinegun
note - this replaces the machine gun as the starting weapon, so the player does not spawn with a machine gun
/*
===========
ClientSpawn

Called every time a client is placed fresh in the world:
after the first ClientBegin, and after each respawn
Initializes all non-persistant parts of playerState
============
*/
void ClientSpawn(gentity_t *ent) {
   .
   .
   .
   client->ps.stats[STAT_WEAPONS] = ( 1 << WP_MACHINEGUN );
	
   if ( g_gametype.integer == GT_TEAM ) 
   {
      client->ps.ammo[WP_MACHINEGUN] = 50;
   }
   else
   {
      client->ps.ammo[WP_MACHINEGUN] = 100;
   }
   
   //tute10.8
   //Spawn player with flame thrower
   client->ps.stats[STAT_WEAPONS] = ( 1 << WP_FLAME_THROWER );
   client->ps.ammo[WP_FLAME_THROWER] = 999;    
   .
   .
   .
}   

Register the starting weapon
file - g_items.c
line - 776
/*
==============
ClearRegisteredItems
==============
*/
void ClearRegisteredItems( void ) {
   memset( itemRegistered, 0, sizeof( itemRegistered ) );

   // players always start with the base weapon
   RegisterItem( BG_FindItemForWeapon( WP_MACHINEGUN ) );
   RegisterItem( BG_FindItemForWeapon( WP_GAUNTLET ) );
   
   RegisterItem( BG_FindItemForWeapon( WP_FLAME_THROWER) );  //tute10.9
   .
   .
   .
}      

4. Prevent the flamethrower from being dropped

file - g_combat.c
line - 72
note
- not really needed but is included for educational purposes.
- The first part makes sure other weapons are dropped while the player is changing weapons, i.e. the player picks up the BFG and dies while the weapon is being activated.
-The second parts says if the weapon is bigger than a machine gun and the weapon is not a grappling hook and it's also not a flame thrower and the ammo for this item is more than 0 then drop the weapon.
/*
=================
TossClientItems

Toss the weapon and powerups for the killed player
=================
*/
void TossClientItems( gentity_t *self ) {
   .
   .
   .
   //tute10.11
   if ( weapon == WP_MACHINEGUN || weapon == WP_GRAPPLING_HOOK || weapon == WP_FLAME_THROWER) 
   {
      if ( self->client->ps.weaponstate == WEAPON_DROPPING ) 
      {
         weapon = self->client->pers.cmd.weapon;
      }
      .
      .
      .
   }
   
   //tute10.11
   if ( weapon > WP_MACHINEGUN && weapon != WP_GRAPPLING_HOOK && weapon != WP_FLAME_THROWER && self->client->ps.ammo[ weapon ] ) 
   {
	// find the item type for this weapon
	item = BG_FindItemForWeapon( weapon );

	// spawn the item
	Drop_Item( self, item, 0 );
   }
   .
   .
   .
}      

5. Adding the flamethower fire functions

file - g_weapons.c
line - 840
/*
===============
FireWeapon
===============
*/
void FireWeapon( gentity_t *ent ) {
   .
   .
   .
   // fire the specific weapon
   switch( ent->s.weapon ) {
      .
      .
      .
      case WP_FLAME_THROWER :
         Weapon_fire_flame( ent );
         break;
      .
      .
      .
   }
   .
   .
   .
}   

file - g_weapons.c
line -
note -
An entity "m" of type gentity_t is created and then the "fire_flame" function is called.

The "fire_flame" function is passed the the calling entity (ent), the starting point (muzzle) and the direction (forward).

The "fire_flame" function will spawn a new entity in the world and all the new entities information will be passed back to "m".

The damage/splashDamage is multiplied by the quad factor. damage and splashDamage are examples of the information passed back from the "fire_flame" function.
/*
=======================================================================
FLAME_THROWER
=======================================================================
*/
void Weapon_fire_flame (gentity_t *ent ) 
{
   gentity_t *m;

   m                = fire_flame(ent, muzzle, forward);
   m->damage       *= s_quadFactor;
   m->splashDamage *= s_quadFactor;
}   

file - g_missle.c
line - near the fire_plasma function
//*tute10.14
=================
fire_flame
=================
*/
gentity_t *fire_flame (gentity_t *self, vec3_t start, vec3_t dir) 
{
   gentity_t*bolt;

   VectorNormalize (dir);

   bolt = G_Spawn();
   bolt->classname = "flame";
   bolt->nextthink = level.time + 1500;
   bolt->think = G_ExplodeMissile;
   bolt->s.eType = ET_MISSILE;
   bolt->r.svFlags = SVF_USE_CURRENT_ORIGIN;
   bolt->s.weapon = WP_FLAME_THROWER;
   bolt->r.ownerNum = self->s.number;
   bolt->parent = self;
   bolt->damage = 30;
   bolt->splashDamage = 25;
   bolt->splashRadius = 45;
   bolt->methodOfDeath = MOD_FLAME_THROWER;
   bolt->splashMethodOfDeath = MOD_PLASMA_SPLASH;
   bolt->clipmask = MASK_SHOT;
   bolt->s.pos.trType = TR_LINEAR;
   bolt->s.pos.trTime = level.time - MISSILE_PRESTEP_TIME;// move a bit on the very first frame

   VectorCopy( start, bolt->s.pos.trBase );
   VectorScale( dir, 300, bolt->s.pos.trDelta );
   SnapVector( bolt->s.pos.trDelta );// save net bandwidth
   VectorCopy (start, bolt->r.currentOrigin);

   return bolt;
}

file -
line -
   
   
      

6. Adding special effects and gfx for the flamethrower

file -
line -
   
   
      

7. Adding adding weapon 11 to the menu

file -
line -
   
   
      



Recompile cgame, game and ui.



Disclaimer:
This is a personal page published by the author. The ideas and information expressed on it have not been approved or authorised by Monash University either explicitly or impliedly. In no event shall Monash University be liable for any damages whatsoever resulting from any action arising in connection with the use of this information or its publication, including any action for infringement of copyright or defamation.