Created By: Triften Chmil
eMail: tlccod@c2i2.com
ICQ UIN: 2651988
Difficulty Scale: Medium


Introduction
This tutorial will tell you how to change the regular wussy nailgun into a weapon of mass destruction. Instead of regular nails, you will have time-delay explosive nails (a la Ghost in the Shell). 1.5 seconds after the last one hits, everyone with a nail sticking out of the will go critical and make a BIG mess.


Step 1
First, open weapons.qc and go down to launch_spike. It'll look like this:
/*
===============
launch_spike

Used for both the player and the ogre (From QTest? Now, that's a bit outdated, eh?)
===============
*/
Above this we will create a new function, W_FireDarts. We have to create a new function or else the scraggs will be certain death. Just cut and paste this or whatever:

void(float ox) W_FireDarts =// the ox makes the nails come out of each barrel
{
	local vector dir;
	local entity dart; //our dart entity

	if (self.ammo_nails >= 2 && self.weapon == IT_SUPER_NAILGUN)
	{
		W_FireSuperSpikes (); //fire spikes and not darts if you are using the super nailgun
		return;
	}

	self.punchangle_x = -4;//the kickback
	
	self.currentammo = self.ammo_nails = self.ammo_nails - 1;
	sound (self, CHAN_WEAPON, "weapons/rocket1i.wav", 1, ATTN_NORM);
	self.attack_finished = time + 0.2;
	dir = aim (self, 1000);
	dart = spawn ();//creat the dart
	dart.owner = self;//you are the owner
	dart.movetype = MOVETYPE_FLYMISSILE;//It doesn't bounce
	dart.solid = SOLID_BBOX;//it doesn't share space with other items

	dart.angles = vectoangles(dir);
	
	dart.touch = dart_touch;//when touched call dart_touch
	dart.classname = "spike";
	dart.think = SUB_Remove;   //After 6 seconds of uneventful flight,
	dart.nextthink = time + 6; //remove the dart
	setmodel (dart, "progs/spike.mdl");
	setsize (dart, VEC_ORIGIN, VEC_ORIGIN);		
	setorigin (dart, self.origin + '0 0 16' + v_right*ox);

	dart.velocity = dir * 700; //the dart's speed
};


Step 2
Above this we will have to define the various touch and think functions Here goes:
void() dart_touch =
{
local float rand;
	if (other == self.owner)
		return; //If it hits you, do nothing

	if (other.solid == SOLID_TRIGGER)
		return;	// trigger field, do nothing

	if (pointcontents(self.origin) == CONTENT_SKY)
	{
		remove(self);
		return;
	}

// hit something that bleeds
	if (other.takedamage)
	{
		spawn_touchblood (4);
		T_Damage (other, self, self.owner, 4); //Low damage
		self.velocity = (self.velocity * 0);    //Set's the spike up so it sticks
		self.avelocity = VEC_ORIGIN;            //to an enemy
		self.enemy = other;
		dart_wait = time + 1.5; //the time delay for detonation
		self.think = dart_stick;        //In a tenth second
		self.nextthink = (time + 0.10); //go to dart_stick
		self.touch = dart_fuse;         //now when touched call dart_fuse

	}
	else //otherwise the dart hits a wall...
	{
		WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
		WriteByte (MSG_BROADCAST, TE_SPIKE);
		WriteCoord (MSG_BROADCAST, self.origin_x);
		WriteCoord (MSG_BROADCAST, self.origin_y);
		WriteCoord (MSG_BROADCAST, self.origin_z);
		remove(self);
	}
};

Above this we define dart_fuse and dart_stick

void() dart_fuse = //this is our touch function { if (time > dart_wait) //if touching something and 1.5 seconds pass, then.. { // T_RadiusDamage (self, self.owner, 120, world); //You can chose to do radius dmg T_Damage (other, other, self.owner, 400); //or dmg only to the poor sap with WriteByte (MSG_BROADCAST, SVC_TEMPENTITY); //the dart. WriteByte (MSG_BROADCAST, TE_EXPLOSION); //Then the dart becomes an explosion WriteCoord (MSG_BROADCAST, self.origin_x); WriteCoord (MSG_BROADCAST, self.origin_y); WriteCoord (MSG_BROADCAST, self.origin_z); BecomeExplosion (); remove(self); //The dart exploded, therefore we remove it } }; void() dart_stick = //our think function { if ( ((self.enemy != world) && (self.enemy.health > 1)) ) //if the dart is on a live enemy then.. { self.origin = self.enemy.origin; //it stays on the enemy and if ( (self.velocity == VEC_ORIGIN) ) //moves with the enemy { self.avelocity = VEC_ORIGIN; } } else //if the enemy dies then.. { WriteByte (MSG_BROADCAST, SVC_TEMPENTITY); //explode harmlessly WriteByte (MSG_BROADCAST, TE_EXPLOSION); //or you could make it do damage, WriteCoord (MSG_BROADCAST, self.origin_x); //doesn't matter. WriteCoord (MSG_BROADCAST, self.origin_y); WriteCoord (MSG_BROADCAST, self.origin_z); BecomeExplosion (); } self.nextthink = (time + 0.10); //after another .1 sec check this function again };



Step 3
Finally we mention functions ahead of time to define later and add one thing to player.qc. Add this above dart_fuse:
void() s_explode1;
void() BecomeExplosion;
float dart_wait;
void() W_FireSuperSpikes;
Open player.qc and find this:

void() player_nail1   =[$nailatt1, player_nail2  ] 
{
	self.effects = self.effects | EF_MUZZLEFLASH;

	if (!self.button0)
		{player_run ();return;}
	self.weaponframe = self.weaponframe + 1;
	if (self.weaponframe == 9)
		self.weaponframe = 1;
	SuperDamageSound();
	W_FireSpikes (4);
	self.attack_finished = time + 0.2;
};
void() player_nail2   =[$nailatt2, player_nail1  ]
{
	self.effects = self.effects | EF_MUZZLEFLASH;

	if (!self.button0)
		{player_run ();return;}
	self.weaponframe = self.weaponframe + 1;
	if (self.weaponframe == 9)
		self.weaponframe = 1;
	SuperDamageSound();
	W_FireSpikes (-4);
	self.attack_finished = time + 0.2;
};
Change both of the W_FireSpikes to W_FireDarts. Leave the 4 and -4 alone.


Step 4
Compile and run in with guns a-blazin'!