Created By: Kryten
eMail: kryten@inside3d.com
Difficulty Scale: Easy


Here I will show you how to make a good Sniper Rifle. The Sniper Rifle will fire one bullet
causing a random ammount of damage from 50 and 140. Follow these simple steps to make the Sniper
Rifle.

Open the weapons.qc and find this line:

void(float shotcount, vector dir, vector spread) FireBullets =

Change that line to this:

void(float shotcount, vector dir, vector spread, float damage) FireBullets =

That will allow you to modify how much damage each bullet does. The shotgun fires 6 bullets, each
doing 4 damage. The sniper rifle will fire one doing a random ammount of damage. The next thing
you need to do is modify everything that calls FireBullets. This is an explample, most will look
something like this (not all!):

	FireBullets (6, dir, '0.04 0.04 0');

You want to add to them so they will work with the changed FireBullets, so just add a ", 0"
before the ");". The above example will look like this:

	FireBullets (6, dir, '0.04 0.04 0', 0);

DO NOT make every FireBullets call look like that! They are different for a reason, just add what
I told you to. There are two calls in the weapons.qc, and one in the soldier.qc. You may have
more if you have added more weapons, or monsters. Compile the code now to make sure you get them
all, if you get an error then you must have forgotten one.

Now you want to go into the FireBullets function, it should look like this:

void(float shotcount, vector dir, vector spread, float damage) FireBullets =
{
	local	vector direction;
	local	vector	src;
	
	makevectors(self.v_angle);

	src = self.origin + v_forward*10;
	src_z = self.absmin_z + self.size_z * 0.7;

	ClearMultiDamage ();
	while (shotcount > 0)
	{
		direction = dir + crandom()*spread_x*v_right + crandom()*spread_y*v_up;

		traceline (src, src + direction*2048, FALSE, self);
		if (trace_fraction != 1.0)
			TraceAttack (4, direction);

		shotcount = shotcount - 1;
	}
	ApplyMultiDamage ();
};

The TraceAttack call sets the damage to 4, you don't want that for the sniper rifle, you want to
have a random damage thats much higher then 4. so you want to add these lines:

	if (!damage) //if damage set to 0
		damage = 4; //set to 4

Above this line:

	ClearMultiDamage ();

Now change the 4 in TraceAttack to damage. Now below the FireBullets function you want to add
this new function:

/*
================
W_FireSniper
================
*/
void() W_FireSniper =
{
	local vector dir;
	local float damage;

	damage = 50 + random()*50 + random()*20 + random()*20; //up to 140, never less than 50

	sound (self, CHAN_WEAPON, "weapons/rocket1i.wav", 1, ATTN_NORM);	

	self.punchangle_x = -2;
	
	self.currentammo = self.ammo_shells = self.ammo_shells - 10; //set to whatever you want
	dir = aim (self, 100000);
	FireBullets (1, dir, '0 0 0', damage);
};

This W_FireSniper function is based on the W_FireShotgun function. However the W_FireSniper
function will do a random ammount of damage between 50 and 140, enough to kill a human and many
monsters. Now go all the way down to W_SetCurrentAmmo. After these lines:

	else if (self.weapon == IT_LIGHTNING)
	{
		self.currentammo = self.ammo_cells;
		self.weaponmodel = "progs/v_light.mdl";
		self.weaponframe = 0;
		self.items = self.items | IT_CELLS;
	}

You want to add these lines:

	else if (self.weapon == IT_SNIPER)
	{
		self.currentammo = self.ammo_shells;
		self.weaponmodel = "progs/v_shot.mdl";
		self.weaponframe = 0;
		self.items = self.items | IT_SHELLS;
	}

At the top of W_CheckNoAmmo you want to add this:

	if (self.weapon == IT_SNIPER && self.currentammo >= 10)
		return TRUE;

Now at the bottom of W_Attack add:

	else if (self.weapon == IT_SNIPER)
	{
		player_shot1 ();
		W_FireSniper ();
		self.attack_finished = time + 2.5;
		centerprint (self,"Reloading!!\n\n\n\n\n\n\n");
	}

You are almost done with the weapons.qc. You want to be able to select the weapon so go down to
the W_ChangeWeapon function. There you should find these lines:

	else if (self.impulse == 3)
	{
		fl = IT_SUPER_SHOTGUN;
		if (self.ammo_shells < 2)
			am = 1;
	}		

You want to change them to:

	else if (self.impulse == 3)
	{
		if (self.weapon != IT_SUPER_SHOTGUN)
		{
			fl = IT_SUPER_SHOTGUN;
			if (self.ammo_shells < 2)
				am = 1;
		}
		else
		{
			fl = IT_SNIPER;
			if (self.ammo_shells < 10)
				am = 1;
		}
	}		

Now when you press 3 twice you will get the Sniper Rifle! One final step in the weapons.qc. At
the top of the W_WeaponFrame add this:

	if (time > self.reload && time < self.reload + 1)
		centerprint (self,"Sniper Rifle is Ready!\n\n\n\n\n\n\n\n\n\n");

That will tell the player when he can use the Sniper Rifle again. Ok now open then defs.qc and
go down until you find:

// items
float	IT_AXE					= 4096;

Now you should have a whole bunch of IT_ things. Some are weapons, some are other items. Now
above the above lines add this line:

.float reload;

Then change:

float	IT_EXTRA_WEAPON			= 128;

To:

float	IT_SNIPER			= 128;

If you already have a weapon using bit 128 then DO NOT use that one, check and see if you have
something using bit 8388608, if not then use that one. Now we need to pick up the sniper rifle,
but how? I will show you how to make it come with the Super Shotgun. Open the items.qc and go
down to weapon_touch. There find:

	else if (self.classname == "weapon_supershotgun")
	{
		if (leave && (other.items & IT_SUPER_SHOTGUN) )
			return;
		hadammo = other.ammo_rockets;			
		new = IT_SUPER_SHOTGUN;
		other.ammo_shells = other.ammo_shells + 5;
	}

Add this line just before the "}":

		other.items = other.items | IT_SNIPER;

Now compile and enjoy!