Module dpmod: Change committed

havoc at icculus.org havoc at icculus.org
Sun Jun 8 04:02:58 EDT 2003


Commiter   : havoc
CVSROOT    : /cvs/cvsroot/twilight
Module     : dpmod
Commit time: 2003-06-08 08:02:58 UTC

Log message:

changed how weapon firing works again (the W_ShotsToFire function returns how many shots to fire this frame, moves a bit more of the work to the individual weapon code)
modified the weapons (I don't even remember what changes I made, sorry)
added lightning gun back
and...  the long awaited return of the plasma wave cannon; never before seen in a public release

Modified files:
     qc/item_weapons.qc qc/m_enforcer.qc qc/plasma.qc qc/progs.src
     qc/w_common.qc qc/w_dbshotgun.qc qc/w_defs.qc qc/w_frame.qc
     qc/w_grapple.qc qc/w_grenade.qc qc/w_nailgun.qc qc/w_pistol.qc
     qc/w_plasmarifle.qc qc/w_rocket.qc qc/w_shotgun.qc
     qc/w_supernailgun.qc

Added files:
     qc/w_lightning.qc qc/w_plasmawave.qc

------=MIME.f0c2e1fdd8d2eda5591b03a0d358dafc
Content-Type: text/plain; name="dpmod.20030608.080258.havoc.diff"
Content-Disposition: attachment; filename="dpmod.20030608.080258.havoc.diff"
Content-Transfer-Encoding: 8bit

Index: dpmod/qc/item_weapons.qc
diff -u dpmod/qc/item_weapons.qc:1.3 dpmod/qc/item_weapons.qc:1.4
--- dpmod/qc/item_weapons.qc:1.3	Tue Mar 11 14:27:11 2003
+++ dpmod/qc/item_weapons.qc	Sun Jun  8 04:02:48 2003
@@ -181,6 +181,6 @@
 
 /*QUAKED weapon_lightning (0 .5 .8) (-16 -16 0) (16 16 32)
 */
-//void() weapon_lightning       = {weapon_spawnhandler("progs/g_light.mdl" , IT_WEAPON8 | IT_WEAPON9 | IT_WEAPON10,   0,   0,   0,  20,   0, "You got the Plasma Gun!\n");};
-void() weapon_lightning       = {weapon_spawnhandler("progs/g_light.mdl" , IT_WEAPON8 | IT_WEAPON9,   0,   0,   0,  50,   0, "You got the Plasma Gun!\n");};
+void() weapon_lightning       = {weapon_spawnhandler("progs/g_light.mdl" , IT_WEAPON8 | IT_WEAPON9 | IT_WEAPON10,   0,   0,   0,  20,   0, "You got the Plasma Gun!\n");};
+//void() weapon_lightning       = {weapon_spawnhandler("progs/g_light.mdl" , IT_WEAPON8 | IT_WEAPON9,   0,   0,   0,  50,   0, "You got the Plasma Gun!\n");};
 
Index: dpmod/qc/m_enforcer.qc
diff -u dpmod/qc/m_enforcer.qc:1.2 dpmod/qc/m_enforcer.qc:1.3
--- dpmod/qc/m_enforcer.qc:1.2	Fri Nov 15 07:59:54 2002
+++ dpmod/qc/m_enforcer.qc	Sun Jun  8 04:02:48 2003
@@ -8,7 +8,7 @@
 
 $cd id1/models/enforcer
 $origin 0 -6 24
-$base base		
+$base base
 $skin skin
 
 $frame stand1 stand2 stand3 stand4 stand5 stand6 stand7
@@ -74,7 +74,8 @@
 
 	shotdir = normalize(hit - shotorg);
 	w_muzzleflash(shotorg, 2);
-	FirePlasma(self, shotorg, shotdir, DMG_ENFORCER_PLASMA, DMG_ENFORCER_PLASMA, v_right * 100, self.deathtype, Obituary_Generic);
+	sound (self, CHAN_WEAPON, "plasma/plasma.wav", 1, ATTN_NORM);
+	FirePlasma(self, shotorg, shotdir * 5000, DMG_ENFORCER_PLASMA, DMG_ENFORCER_PLASMA, self.deathtype, Obituary_Generic);
 };
 
 void(vector hit) enforcer_rocket =
Index: dpmod/qc/plasma.qc
diff -u dpmod/qc/plasma.qc:1.3 dpmod/qc/plasma.qc:1.4
--- dpmod/qc/plasma.qc:1.3	Fri Nov 15 07:59:54 2002
+++ dpmod/qc/plasma.qc	Sun Jun  8 04:02:48 2003
@@ -40,12 +40,12 @@
 		remove(self);
 };
 
-void(entity own, vector org, vector dir, float damg, float damg2, vector casingdir, string dethtype, void(entity t, entity a, string m, float dtyp) obitfunc) FirePlasma =
+void(entity own, vector org, vector vel, float damg, float damg2, string dethtype, void(entity t, entity a, string m, float dtyp) obitfunc) FirePlasma =
 {
 	local   vector  a;
 
 	//sound (own, CHAN_WEAPON, "plasma/plasma.wav", 1, ATTN_NORM);
-	sound (own, CHAN_WEAPON, "weapons/rocket1i.wav", 1, ATTN_NORM);
+	//sound (own, CHAN_WEAPON, "weapons/rocket1i.wav", 1, ATTN_NORM);
 
 	fightdone = time + 1; // delay stuff until fighting is over
 
@@ -58,7 +58,7 @@
 	setsize(newmis, '0 0 0', '0 0 0');
 	setorigin(newmis, org);
 	newmis.effects = EF_LOWPRECISION;
-	newmis.velocity = dir * 5000;// + self.velocity;
+	newmis.velocity = vel;// + self.velocity;
 	newmis.dmg = damg;
 	newmis.dmg2 = damg2;
 	if (self.items & IT_QUAD)
@@ -75,3 +75,105 @@
 	newmis.think = plasma_think;
 	newmis.nextthink = time + 0.1;
 };
+
+void() plasmaball_touch =
+{
+	local   vector  v;
+	if (other == self.owner)
+		return;
+	if (pointcontents(self.origin) == CONTENT_SKY)
+	{
+		remove(self);
+		return;
+	}
+	if (other.solid != SOLID_BSP)
+		return;
+	v = normalize(self.velocity);
+	T_Damage(other, self, self.owner, self.dmg, self.dmg, self.deathtype, DT_PLASMA, self.origin, v * self.dmg, self.obitfunc1);
+	T_RadiusDamage(self, self.owner, self.dmg, self.dmg2, other, self.deathtype, DT_PLASMA, self.obitfunc1);
+	sound(self, CHAN_WEAPON, "plasma/plasexpl.wav", 1, ATTN_NORM);
+	effect(self.origin - v * 16, "progs/plasmashot.spr32", 10, 5, 30);
+	te_plasmaburn(self.origin - v);
+	remove(self);
+};
+
+/*
+void() plasmaball_burn =
+{
+	local entity head;
+	head = findradius(self.origin, self.dmg2);
+};
+*/
+
+void() plasmaball_think =
+{
+	local float damage, step, steps;
+	local vector backup;
+	self.nextthink = time;
+	if (time > self.cnt)
+	{
+		self.cnt = time + 0.1;
+		self.frame = self.frame + 1;
+		if (self.frame >= 10)
+			self.frame = 0;
+	}
+	damage = self.dmg * (time - self.count2) * 5;
+	if (damage >= 10)
+	{
+		self.count2 = time;
+		steps = ceil(damage / 50);
+		damage = damage / steps;
+		backup = self.origin;
+		step = 0;
+		while (step < steps)
+		{
+			step = step + 1;
+			self.origin = (backup - self.dest) * (step / steps) + self.dest;
+			//plasmaball_burn();
+			T_RadiusDamage(self, self.owner, damage, self.dmg2, self.owner, self.deathtype, DT_PLASMA, self.obitfunc1);
+		}
+		// the above loop leaves self.origin restored to what it should be
+	}
+	if (time > self.count)
+		remove(self);
+};
+
+void(entity own, vector org, vector vel, float damg, float damg2, string dethtype, void(entity t, entity a, string m, float dtyp) obitfunc) FirePlasmaBall =
+{
+	local   vector  a;
+
+	//sound (own, CHAN_WEAPON, "plasma/plasma.wav", 1, ATTN_NORM);
+	//sound (own, CHAN_WEAPON, "weapons/rocket1i.wav", 1, ATTN_NORM);
+
+	fightdone = time + 1; // delay stuff until fighting is over
+
+	newmis = spawn();
+	newmis.classname = "plasmaball";
+	newmis.owner = own;
+	newmis.solid = SOLID_TRIGGER;
+	newmis.movetype = MOVETYPE_FLY;
+	setmodel(newmis, "progs/plasmashot.spr32");
+	setsize(newmis, '0 0 0', '0 0 0');
+	setorigin(newmis, org);
+	newmis.effects = EF_LOWPRECISION;
+	newmis.velocity = vel;// + self.velocity;
+	newmis.dmg = damg;
+	newmis.dmg2 = damg2;
+	if (self.items & IT_QUAD)
+	{
+		newmis.dmg = newmis.dmg * 4;
+		newmis.effects = newmis.effects | EF_BLUE;
+	}
+	newmis.deathtype = dethtype;
+	newmis.obitfunc1 = obitfunc;
+//	newmis.frame = random() * 9.999;
+//	newmis.frame = floor(newmis.frame);
+	newmis.count = time + 50;
+	newmis.count2 = time;
+	newmis.dest = self.origin;
+	newmis.touch = plasmaball_touch;
+	newmis.think = plasmaball_think;
+	newmis.nextthink = time + 0.1;
+};
+
+
Index: dpmod/qc/progs.src
diff -u dpmod/qc/progs.src:1.4 dpmod/qc/progs.src:1.5
--- dpmod/qc/progs.src:1.4	Thu Feb 20 03:58:51 2003
+++ dpmod/qc/progs.src	Sun Jun  8 04:02:48 2003
@@ -90,9 +90,11 @@
 w_supernailgun.qc // 5
 w_grenade.qc // 6
 w_rocket.qc // 7
-w_plasmarifle.qc // 8
-w_grapple.qc // 9
-w_fake10.qc // 10
+w_lightning.qc // 8
+w_plasmarifle.qc // 9
+w_plasmawave.qc // 10
+
+w_grapple.qc // +button5
 
 w_info.qc   // must be after the weapons themselves
 
Index: dpmod/qc/w_common.qc
diff -u dpmod/qc/w_common.qc:1.2 dpmod/qc/w_common.qc:1.3
--- dpmod/qc/w_common.qc:1.2	Fri Sep 20 01:59:12 2002
+++ dpmod/qc/w_common.qc	Sun Jun  8 04:02:48 2003
@@ -1,11 +1,12 @@
 
-float   stopfiring; // set by uniquefunc when out of ammo or whatever
 .float  wload;
 .float  wloadtime;
 
+void() grapple_precache;
 void() common_precache =
 {
 	precache_model("progs/muzzleflash.spr32");
+	grapple_precache();
 };
 
 void(vector muzzleorg, float kickback) w_muzzleflash =
@@ -67,50 +68,38 @@
 	return findtrajectory_velocity;
 };
 
-.float notfiring;
-
-void(string firingsound, float nextshotdelay, void() uniquefunc) W_GenericRapidFireCode =
+void() W_Hostile =
 {
-	if (time < self.attack_finished) // still busy with the last shot
-		return;
-
-	stopfiring = FALSE;
-	fightdone = time + 1; // delay stuff until fighting is over
-
-	// not firing yet, set base time to avoid double shots
-	if (self.notfiring)
-		self.attack_finished = time;
-	self.notfiring = FALSE;
-
 	// wake up monsters
 	self.show_hostile = time + 1;
 	weaponwakeup(self.origin, self);
+	fightdone = time + 1; // delay stuff until fighting is over
 	SuperDamageSound();
-	if (firingsound != "")
-		sound (self, CHAN_WEAPON, firingsound, 1, ATTN_NORM);
-
-	while (time >= self.attack_finished && !stopfiring)
-	{
-		self.attack_finished = self.attack_finished + nextshotdelay;
-		uniquefunc();
-	}
 };
 
-void(string firingsound, float nextshotdelay, void() uniquefunc) W_GenericSlowFireCode =
+.float firing;
+.float oldfiring;
+float(float nextshotdelay) W_ShotsToFire =
 {
-	if (time < self.attack_finished) // still busy with the last shot
-		return;
-	
-	// wake up monsters
-	self.show_hostile = time + 1;
-	weaponwakeup(self.origin, self);
-	fightdone = time + 1; // delay stuff until fighting is over
-	SuperDamageSound();
-	if (firingsound != "")
-		sound (self, CHAN_WEAPON, firingsound, 1, ATTN_NORM);
+	local float shotcount;
+
+	self.firing = TRUE;
+
+	// check if still busy with the previous shot
+	if (time < self.attack_finished)
+		return 0;
 
-	self.attack_finished = time + nextshotdelay;
-	uniquefunc();
+	// if not firing yet, set base time to avoid double shots
+	if (!self.oldfiring)
+		self.attack_finished = time;
+
+	shotcount = 0;
+	while (time >= self.attack_finished)
+	{
+		self.attack_finished = self.attack_finished + nextshotdelay;
+		shotcount = shotcount + 1;
+	}
+	return shotcount;
 };
 
 float(float haveammo) W_CheckNoAmmo =
Index: dpmod/qc/w_dbshotgun.qc
diff -u dpmod/qc/w_dbshotgun.qc:1.8 dpmod/qc/w_dbshotgun.qc:1.9
--- dpmod/qc/w_dbshotgun.qc:1.8	Wed Apr  9 23:24:30 2003
+++ dpmod/qc/w_dbshotgun.qc	Sun Jun  8 04:02:48 2003
@@ -74,7 +74,10 @@
 float DBSHOTGUNBUCKSHOT = 50;
 float DBSHOTGUNEXPLOSIVESLUG = 50;
 
-.float shotgunmode, shotgunshells;
+.float shotgunshells;
+
+/*
+.float shotgunmode;
 void(void(entity t, entity a, string m, float dtyp) obitfunc, float spreadboost, float explosive) W_DBShotgunFireShell =
 {
 	local vector v;
@@ -91,11 +94,13 @@
 		shotorg = shotorg + v_right;
 	}
 	self.wload = self.wload - 1;
+*/
 	/*
 	if (self.shotgunmode)
 		self.currentammo = self.ammo_xshells = self.ammo_xshells - 1;
 	else
 	*/
+/*
 		self.currentammo = self.ammo_shells = self.ammo_shells - 1;
 	self.wfiretime = time;
 	w_muzzleflash(v, 4);
@@ -130,6 +135,7 @@
 	while (self.wload > 0)
 		W_DBShotgunFireShell(Obituary_DBShotgunDouble_Explosive, 0, TRUE);
 };
+*/
 
 void(void(entity t, entity a, string m, float dtyp) obitfunc, float spreadboost, float explosive) W_DBShotgunGatlingFireShell =
 {
@@ -155,7 +161,7 @@
 	*/
 		self.currentammo = self.ammo_shells = self.ammo_shells - 1;
 	self.wfiretime = time;
-	w_muzzleflash(v, 4);
+	w_muzzleflash(v, 2);
 	if (explosive)
 		FireBullets(self, self, 1, 1, 0, 0, DBSHOTGUNEXPLOSIVESLUG * damagescale, 80, shotdir * 5000, spreadboost, "SHOTGUNEXPLOSIVESLUG", DT_SHOTGUN, obitfunc);
 	else
@@ -165,15 +171,15 @@
 	}
 	shotorg = v;
 };
-
-void() W_DBShotgunGatlingFireCode_Buckshot =
-{
-	W_DBShotgunGatlingFireShell(Obituary_DBShotgunSingle_Buckshot, 0, FALSE);
-};
 
-void() W_DBShotgunGatlingFireCode_Explosive =
+void(float fireexplosive) W_DBShotgunGatlingFireCode =
 {
-	W_DBShotgunGatlingFireShell(Obituary_DBShotgunSingle_Explosive, 0, TRUE);
+	W_Hostile();
+	sound(self, CHAN_WEAPON, "weapons/shotgn2.wav", 1, ATTN_NORM);
+	if (fireexplosive)
+		W_DBShotgunGatlingFireShell(Obituary_DBShotgunSingle_Explosive, 0, TRUE);
+	else
+		W_DBShotgunGatlingFireShell(Obituary_DBShotgunSingle_Buckshot, 0, FALSE);
 };
 
 
@@ -227,13 +233,10 @@
 			if (self.shotgunshells & 2) ejectcasing (v + v_right * -1, '0 0 0', 30, ang, '0 0 0', 150, 1);
 			self.shotgunshells = 0;
 		}
+		if (self.button0 || self.button3)
 		if (self.ammo_shells > 0)
-		{
-			if (self.button0)
-				W_GenericSlowFireCode("weapons/shotgn2.wav", 0.2, W_DBShotgunGatlingFireCode_Buckshot);
-			else if (self.button3)
-				W_GenericSlowFireCode("weapons/shotgn2.wav", 0.2, W_DBShotgunGatlingFireCode_Explosive);
-		}
+		if (W_ShotsToFire(0.2))
+			W_DBShotgunGatlingFireCode(self.button3);
 	}
 
 	/*
Index: dpmod/qc/w_defs.qc
diff -u dpmod/qc/w_defs.qc:1.2 dpmod/qc/w_defs.qc:1.3
--- dpmod/qc/w_defs.qc:1.2	Fri Sep 20 01:59:12 2002
+++ dpmod/qc/w_defs.qc	Sun Jun  8 04:02:48 2003
@@ -25,8 +25,8 @@
 float   stopfiring; // used by W_GenericRapidFireCode system
 
 vector  shotorg, shotdir;
-void(string firingsound, float nextshotdelay, void() uniquefunc) W_GenericRapidFireCode;
-void(string firingsound, float nextshotdelay, void() uniquefunc) W_GenericSlowFireCode;
+void() W_Hostile;
+float(float nextshotdelay) W_ShotsToFire;
 float(float minrange, float preferredrange, float baserating) genericweaponrating;
 
 float(float w, float request) setweapon;
Index: dpmod/qc/w_frame.qc
diff -u dpmod/qc/w_frame.qc:1.4 dpmod/qc/w_frame.qc:1.5
--- dpmod/qc/w_frame.qc:1.4	Thu Feb 20 03:44:12 2003
+++ dpmod/qc/w_frame.qc	Sun Jun  8 04:02:48 2003
@@ -9,6 +9,8 @@
 Called every frame so impulse events can be handled as well as possible
 ============
 */
+.float notfiringcountdown;
+void() w_frame_grapple;
 void() W_WeaponFrame =
 {
 	local vector v;
@@ -64,8 +66,12 @@
 	if (self.viewzoom == 0)
 		self.viewzoom = 1;
 
+	w_frame_grapple();
+
 	// weapon animation, firing, etc
 	setweapon(self.weapon, WR_SETUP);
+	self.oldfiring = self.firing;
+	self.firing = FALSE;
 	self.weaponframecode();
 	setweapon(self.weapon, WR_SETUP);
 
Index: dpmod/qc/w_grapple.qc
diff -u dpmod/qc/w_grapple.qc:1.3 dpmod/qc/w_grapple.qc:1.4
--- dpmod/qc/w_grapple.qc:1.3	Fri Nov 15 07:59:54 2002
+++ dpmod/qc/w_grapple.qc	Sun Jun  8 04:02:48 2003
@@ -57,7 +57,8 @@
 		self.effects = self.effects | EF_BLUE;
 	else
 		self.effects = self.effects - (self.effects & EF_BLUE);
-	if (self.enemy.solid == SOLID_NOT || self.owner.deadflag || (self.owner.button0 == 0 && self.owner.weapon == IT_WEAPON9 && self.owner.switchweapon == IT_WEAPON9))
+	if (self.enemy.solid == SOLID_NOT || self.owner.deadflag || self.owner.button5 == 0)
+	//if (self.enemy.solid == SOLID_NOT || self.owner.deadflag || (self.owner.button0 == 0 && self.owner.weapon == IT_WEAPON10 && self.owner.switchweapon == IT_WEAPON10))
 	{
 		grapplereturn();
 		return;
@@ -142,37 +143,92 @@
 {
 	self.nextthink = time + 0.05;
 	traceline(self.owner.origin + '0 0 16', self.origin, TRUE, self);
-	if (trace_fraction < 1 || time > self.cnt || !self.owner.button0)
+	if (trace_fraction < 1 || time > self.cnt || !self.owner.button5)
+	//if (trace_fraction < 1 || time > self.cnt || !self.owner.button0)
 		grapplereturn();
 };
 
+void() grapplebit_think =
+{
+	if (self.owner.modelindex == 0)
+	{
+		remove(self);
+		return;
+	}
+	if (self.owner.owner.modelindex == 0)
+	{
+		remove(self);
+		return;
+	}
+	self.nextthink = time;
+	setorigin(self, self.owner.owner.origin + self.count * (self.owner.origin - self.owner.owner.origin));
+};
+
 void(entity own, vector org, vector dir) FireGrapple =
 {
+	local entity grapplebolt, bit;
+	local float c;
 	w_muzzleflash(org, 3);
-	own.grapple = newmis = spawn();
-	newmis.classname = "grapple";
-	newmis.owner = own;
-	newmis.movetype = MOVETYPE_FLYMISSILE;
-	newmis.solid = SOLID_BBOX;
-	newmis.touch = grappleflytouch;
-	setorigin(newmis, org);
-	setmodel(newmis, "progs/star.mdl");
-	setsize(newmis, '0 0 0', '0 0 0');
-	newmis.angles = vectoangles(dir);
-	newmis.velocity = dir * 1500;
-	newmis.think = grappleflythink;
-	newmis.nextthink = time;
-	newmis.cnt = time + 3;
-	sound(newmis, CHAN_BODY, "weapons/chain1.wav", 1, ATTN_NORM);
+	own.grapple = grapplebolt = spawn();
+	grapplebolt.classname = "grapple";
+	grapplebolt.owner = own;
+	grapplebolt.movetype = MOVETYPE_FLYMISSILE;
+	grapplebolt.solid = SOLID_BBOX;
+	grapplebolt.touch = grappleflytouch;
+	setorigin(grapplebolt, org);
+	setmodel(grapplebolt, "progs/star.mdl");
+	setsize(grapplebolt, '0 0 0', '0 0 0');
+	grapplebolt.angles = vectoangles(dir);
+	grapplebolt.velocity = dir * 1500;
+	grapplebolt.think = grappleflythink;
+	grapplebolt.nextthink = time;
+	grapplebolt.cnt = time + 3;
+	sound(grapplebolt, CHAN_BODY, "weapons/chain1.wav", 1, ATTN_NORM);
+	c = 0;
+	while (c < 1)
+	{
+		c = c + 0.25;
+		if (c >= 1)
+			break;
+		bit = spawn();
+		bit.owner = grapplebolt;
+		bit.think = grapplebit_think;
+		bit.nextthink = time;
+		bit.count = c;
+		setmodel(bit, "progs/bit.mdl");
+	}
 };
 
 void() W_GrappleFireCode =
 {
+	W_Hostile();
+	sound(self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
 	self.wfiretime = time;
 	w_muzzleflash(shotorg, 1);
 	FireGrapple(self, shotorg, shotdir);
 };
 
+void() grapple_precache =
+{
+	precache_model("progs/star.mdl");
+	precache_model("progs/bit.mdl");
+	precache_sound("weapons/sgun1.wav");
+	precache_sound("player/axhit2.wav");
+	precache_sound("weapons/chain1.wav");
+	precache_sound("weapons/chain2.wav");
+	precache_sound("weapons/chain3.wav");
+	precache_sound("weapons/bounce2.wav");
+};
+
+void() w_frame_grapple =
+{
+	if (self.button5) // fire
+	if (!self.grapple)
+	if (W_ShotsToFire(0.5))
+		W_GrappleFireCode();
+};
+
+/*
 void() w_grappledrop1;
 void() w_grappledrop2;
 void() w_grappleraise1;
@@ -185,7 +241,8 @@
 	if (self.button0) // fire
 	{
 		if (!self.grapple)
-			W_GenericSlowFireCode("weapons/sgun1.wav", 0.5, W_GrappleFireCode);
+		if (W_ShotsToFire(0.5))
+			W_GrappleFireCode();
 	}
 	// else if (self.button3)
 		// FIXME: add chainsaw
@@ -202,7 +259,7 @@
 	havoc_shotanimupdate(self.weaponframe);
 };
 
-void() weapon9_precache =
+void() weapon10_precache =
 {
 	precache_model("progs/v_dpshot.mdl");
 	precache_model("progs/star.mdl");
@@ -215,11 +272,12 @@
 };
 
 float() w_grapplerating = {return genericweaponrating(0, 500, 50);};
-void() w_grapplesetup = {wset(IT_WEAPON9, 0, 0, VWEP_GENERIC, "progs/v_dpshot.mdl");};
-float(float request) setweapon9 = {return weapongeneric(IT_WEAPON9, TRUE, request, w_grapplesetup, w_grapple, w_grappleraise1, w_directaim, w_grapplerating, "Grapple");};
+void() w_grapplesetup = {wset(IT_WEAPON10, 0, 0, VWEP_GENERIC, "progs/v_dpshot.mdl");};
+float(float request) setweapon10 = {return weapongeneric(IT_WEAPON10, TRUE, request, w_grapplesetup, w_grapple, w_grappleraise1, w_directaim, w_grapplerating, "Grapple");};
 
 void() w_grappleraise1 = {wraise(8, w_grappleraise2, 0.1);};
 void() w_grappleraise2 = {wraise(7, w_grapple, 0.1);};
 
 void() w_grappledrop1 = {wdrop(7, w_grappledrop2, 0.1);};
 void() w_grappledrop2 = {wdropped(8, 0.1);};
+*/
Index: dpmod/qc/w_grenade.qc
diff -u dpmod/qc/w_grenade.qc:1.7 dpmod/qc/w_grenade.qc:1.8
--- dpmod/qc/w_grenade.qc:1.7	Wed Apr  9 23:24:30 2003
+++ dpmod/qc/w_grenade.qc	Sun Jun  8 04:02:48 2003
@@ -63,9 +63,11 @@
 
 void() W_GrenadeFirePipebomb =
 {
+	W_Hostile();
+	sound(self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
 	self.wfiretime = time;
 	self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
-	w_muzzleflash(shotorg, 3);
+	w_muzzleflash(shotorg, 5);
 	LaunchGrenade(shotorg, shotdir * 1000 + v_up * 200, self, 150 * damagescale, 120, GRENADE_DETONATABLE | GRENADE_DETONATEONCREATURE, 60, "PIPEBOMB", Obituary_Grenade);
 };
 
@@ -109,7 +111,10 @@
 			if (self.activemines < 20)
 			{
 				if (self.ammo_rockets >= 1)
-					W_GenericSlowFireCode("weapons/grenade.wav", 0.3, W_GrenadeFirePipebomb);
+				{
+					if (W_ShotsToFire(0.6))
+						W_GrenadeFirePipebomb();
+				}
 				else
 					self.switchweapon = W_BestWeapon(TRUE);
 			}
Index: dpmod/qc/w_lightning.qc
diff -u /dev/null dpmod/qc/w_lightning.qc:1.1
--- /dev/null	Sun Jun  8 04:02:58 2003
+++ dpmod/qc/w_lightning.qc	Sun Jun  8 04:02:48 2003
@@ -0,0 +1,195 @@
+
+void(entity targ, entity attacker, string dmsg, float dtype) Obituary_Lightning =
+{
+	if (dtype == DTYPE_PLAYER)
+	{
+		deathstring1 = targ.netname;
+		deathstring2 = " was sizzled by ";
+		deathstring3 = attacker.netname;
+		deathstring4 = "";
+	}
+	else
+		Obituary_Fallback(targ, attacker, dmsg, dtype);
+};
+
+void(entity targ, entity attacker, string dmsg, float dtype) Obituary_LightningExplode =
+{
+	if (dtype == DTYPE_PLAYER)
+	{
+		deathstring1 = targ.netname;
+		deathstring2 = " was destroyed by ";
+		deathstring3 = attacker.netname;
+		deathstring4 = "'s lightning gun explosion";
+	}
+	else if (dtype == DTYPE_SUICIDE)
+	{
+		deathstring1 = targ.netname;
+		deathstring2 = " blow dries his hair in the water";
+		deathstring3 = "";
+		deathstring4 = "";
+	}
+	else
+		Obituary_Fallback(targ, attacker, dmsg, dtype);
+};
+
+void(entity targ, entity attacker, string dmsg, float dtype) Obituary_LightningSuperBeam =
+{
+	if (dtype == DTYPE_PLAYER)
+	{
+		deathstring1 = targ.netname;
+		deathstring2 = " was shocked by ";
+		deathstring3 = attacker.netname;
+		deathstring4 = "'s super lightning";
+	}
+	else if (dtype == DTYPE_SUICIDE)
+	{
+		deathstring1 = targ.netname;
+		deathstring2 = " forgot to run from the super lightning";
+		deathstring3 = "";
+		deathstring4 = "";
+	}
+	else
+		Obituary_Fallback(targ, attacker, dmsg, dtype);
+};
+
+void(entity targ, entity attacker, string dmsg, float dtype) Obituary_LightningSuperBeamDirectHit =
+{
+	if (dtype == DTYPE_PLAYER)
+	{
+		deathstring1 = targ.netname;
+		deathstring2 = " was incinerated by ";
+		deathstring3 = attacker.netname;
+		deathstring4 = "'s super lightning";
+	}
+	else
+		Obituary_Fallback(targ, attacker, dmsg, dtype);
+};
+
+.entity lightningchain;
+.float lightningsolidbackup;
+.vector lightninghitpoint;
+vector(entity inflictor, entity attacker, vector start, vector end, float hdamage, float bdamage, string dmsg, float dtype, void(entity targ2, entity attacker2, string dmsg2, float dtype2) obitfunc) W_BeamDamage =
+{
+	local entity lightningchainhead, e;
+	local float c;
+	local vector force;
+	force = (normalize(end - start) + '0 0 0.25') * 2 * bdamage;
+
+	// find entities in the beam
+	c = 0;
+	lightningchainhead = world;
+	// need to change self to SOLID_BBOX to do weapon traces (able to hit a corpse)
+	self.lightningsolidbackup = self.solid;
+	self.solid = SOLID_BBOX;
+	while (c < 10)
+	{
+		c = c + 1;
+		traceline(start, end, FALSE, self);
+		if (trace_fraction == 1)
+			break;
+		if (trace_ent.solid == SOLID_BSP)
+			break;
+		// make entity non-solid so the beam can continue
+		trace_ent.lightningsolidbackup = trace_ent.solid;
+		trace_ent.solid = SOLID_NOT;
+		trace_ent.lightninghitpoint = trace_endpos;
+		// add entity to chain
+		trace_ent.lightningchain = lightningchainhead;
+		lightningchainhead = trace_ent;
+	}
+	// restore their .solid
+	self.solid = self.lightningsolidbackup;
+	e = lightningchainhead;
+	while (e != world)
+	{
+		e.solid = e.lightningsolidbackup;
+		e = e.lightningchain;
+	}
+	end = trace_endpos;
+
+	// now damage them
+	e = lightningchainhead;
+	while (e != world)
+	{
+		T_Damage(e, inflictor, attacker, hdamage, bdamage, dmsg, dtype, trace_endpos, force, obitfunc);
+		e = e.lightningchain;
+	}
+	return end;
+};
+
+void(float cells) W_LightningFireCode =
+{
+	if (cells > self.ammo_cells)
+		cells = self.ammo_cells;
+	self.wfiretime = time;
+	self.currentammo = self.ammo_cells = self.ammo_cells - cells;
+	self.wframe = self.wframe + 1;
+	if (self.wframe >= 3)
+		self.wframe = 1;
+	W_BeamDamage(self, self, shotorg, shotorg + shotdir * 100000, cells * 30 * damagescale, cells * 15 * damagescale, "LIGHTNING", DT_LIGHTNING, Obituary_Lightning);
+
+	traceline(shotorg, shotorg + shotdir * 100000, TRUE, self);
+	te_lightning2(self, shotorg, trace_endpos);
+};
+
+void() w_lightningdrop1;
+void() w_lightningdrop2;
+void() w_lightningraise1;
+void() w_lightningraise2;
+.float oldbutton0;
+void() w_lightning =
+{
+	if (widle(w_lightningdrop1))
+		return;
+
+	if (self.button0)
+	{
+		if (self.ammo_cells > 0)
+		{
+			if (!self.oldbutton0)
+				sound(self, CHAN_AUTO, "weapons/lstart.wav", 1, ATTN_NORM);
+			if (time >= self.wfiretime + 0.1)
+			{
+				self.wfiretime = time;
+				W_Hostile();
+				sound(self, CHAN_WEAPON, "weapons/lhit.wav", 1, ATTN_NORM);
+			}
+			self.wload = W_ShotsToFire(1/20);
+			if (self.wload > 0)
+				W_LightningFireCode(self.wload / 2);
+		}
+	}
+	/*
+	else if (self.button3)
+	{
+		//if (self.button3)
+		//if (self.ammo_rockets >= 1)
+		//	W_GenericSlowFireCode("weapons/grenade.wav", 0.5, W_SuperNailgunMineFireCode);
+	}
+	*/
+	self.oldbutton0 = self.button0;
+
+	if ((time - self.wfiretime) < 0.15)
+		self.weaponframe = self.wframe;
+	else
+		self.weaponframe = 0;
+
+	havoc_lightanimupdate(self.weaponframe);
+};
+
+void() weapon8_precache =
+{
+	precache_model("progs/v_dplight.mdl");
+	precache_sound("weapons/lhit.wav");
+	precache_sound("weapons/lstart.wav");
+};
+
+void() w_lightningraise1 = {wraise(6, w_lightningraise2, 0.1);};
+void() w_lightningraise2 = {wraise( 5, w_lightning, 0.1);};
+
+void() w_lightningdrop1 = {wdrop( 5, w_lightningdrop2, 0.1);};
+void() w_lightningdrop2 = {wdropped(6, 0.1);};
+
+float() w_lightningrating = {return genericweaponrating(0, 1000, 300);};
+void() w_lightningsetup = {wset(IT_WEAPON8, IT_CELLS, self.ammo_cells, VWEP_LIGHTNING, "progs/v_dplight.mdl");};
+float(float request) setweapon8 = {return weapongeneric(IT_WEAPON8, self.ammo_cells >= 1, request, w_lightningsetup, w_lightning, w_lightningraise1, w_directaim, w_lightningrating, "Thunderbolt");};
Index: dpmod/qc/w_nailgun.qc
diff -u dpmod/qc/w_nailgun.qc:1.6 dpmod/qc/w_nailgun.qc:1.7
--- dpmod/qc/w_nailgun.qc:1.6	Wed Apr  9 23:24:30 2003
+++ dpmod/qc/w_nailgun.qc	Sun Jun  8 04:02:48 2003
@@ -12,36 +12,39 @@
 		Obituary_Fallback(targ, attacker, dmsg, dtype);
 };
 
-void() W_NailgunFireCode =
+void(float shots) W_NailgunFireCode =
 {
 	local vector v, casingdir, ang;
-	if (self.ammo_nails < 1) {stopfiring = TRUE;return;}
-	self.wfiretime = time;
-	self.currentammo = self.ammo_nails = self.ammo_nails - 1;
-	self.wframe = self.wframe + 1;
-	if (self.wframe >= 9)
-		self.wframe = 1;
-	self.wfiretime = time;
-	self.punchangle_x = -2;
+	W_Hostile();
+	sound(self, CHAN_WEAPON, "weapons/rocket1i.wav", 1, ATTN_NORM);
+	while (shots > 0 && self.ammo_nails >= 1)
+	{
+		shots = shots - 1;
+		self.wfiretime = time;
+		self.currentammo = self.ammo_nails = self.ammo_nails - 1;
+		self.wframe = self.wframe + 1;
+		if (self.wframe >= 9)
+			self.wframe = 1;
+		self.wfiretime = time;
+		self.punchangle_x = -2;
+
+		v = shotorg;
+		ang = self.v_angle;ang_x = 0 - ang_x;
+		if (self.wframe & 1)
+		{
+			shotorg = shotorg + v_right * 2;
+			ejectcasing(shotorg, v_right * 200 + v_up * 50, 50, ang, '0 250 0', 100, 0);
+		}
+		else
+		{
+			shotorg = shotorg - v_right * 2;
+			ejectcasing(shotorg, v_right * -200 + v_up * 50, 50, ang, '0 -250 0', 100, 0);
+		}
 
-	v = shotorg;
-	ang = self.v_angle;ang_x = 0 - ang_x;
-	if (self.wframe & 1)
-	{
-		shotorg = shotorg + v_right * 2;
-		ejectcasing(shotorg, v_right * 200 + v_up * 50, 50, ang, '0 250 0', 100, 0);
+		w_muzzleflash(shotorg, 1);
+		FireBullets(self, self, 4, 1, 15 * damagescale, 15 * damagescale, 0, 0, shotdir * 7000, 0.025, "NAILGUN", DT_NAIL, Obituary_Nailgun);
+		shotorg = v;
 	}
-	else
-	{
-		shotorg = shotorg - v_right * 2;
-		ejectcasing(shotorg, v_right * -200 + v_up * 50, 50, ang, '0 -250 0', 100, 0);
-	}
-
-	w_muzzleflash(shotorg, 1);
-	FireBullets(self, self, 4, 1, 15 * damagescale, 15 * damagescale, 0, 0, shotdir * 7000, 0.025, "NAILGUN", DT_NAIL, Obituary_Nailgun);
-	shotorg = v;
-
-	if (self.ammo_nails < 1) {stopfiring = TRUE;return;}
 };
 
 void(entity targ, entity attacker, string dmsg, float dtype) Obituary_NailgunMine =
@@ -75,9 +78,11 @@
 
 void() W_NailgunGrenadeFireCode =
 {
+	W_Hostile();
+	sound(self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
 	self.wfiretime = time;
 	self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
-	w_muzzleflash(shotorg, 3);
+	w_muzzleflash(shotorg, 1);
 	//LaunchGrenade(shotorg, shotdir * 1000 + v_up * 200, self, 80 * damagescale, 300, GRENADE_IMPACT, 2.5, "NAILGUNGRENADE", Obituary_NailgunGrenade);
 	LaunchMine(shotorg, shotdir * 1000 + v_up * 200, self, 200 * damagescale, 70, 20 * damagescale, 10 * damagescale, MINE_LASERTRIP, 60, "LASERTRIPMINE", Obituary_NailgunMine);
 };
@@ -95,14 +100,18 @@
 	if (self.button0)
 	{
 		if (self.ammo_nails >= 1)
-			W_GenericRapidFireCode("weapons/rocket1i.wav", 0.1, W_NailgunFireCode);
+		{
+			self.wload = W_ShotsToFire(0.1);
+			if (self.wload)
+				W_NailgunFireCode(self.wload);
+		}
 	}
 	else
 	{
-		self.notfiring = TRUE;
 		if (self.button3)
 		if (self.ammo_rockets >= 1)
-			W_GenericSlowFireCode("weapons/grenade.wav", 0.8, W_NailgunGrenadeFireCode);
+		if (W_ShotsToFire(0.8))
+			W_NailgunGrenadeFireCode();
 	}
 
 	if ((time - self.wfiretime) < 0.15)
Index: dpmod/qc/w_pistol.qc
diff -u dpmod/qc/w_pistol.qc:1.7 dpmod/qc/w_pistol.qc:1.8
--- dpmod/qc/w_pistol.qc:1.7	Wed Apr  9 23:24:30 2003
+++ dpmod/qc/w_pistol.qc	Sun Jun  8 04:02:48 2003
@@ -15,6 +15,8 @@
 void() W_PistolFireCode =
 {
 	local vector ang;
+	W_Hostile();
+	sound(self, CHAN_WEAPON, "weapons/rocket1i.wav", 1, ATTN_NORM);
 	self.wfiretime = time;
 	w_muzzleflash(shotorg, 1);
 	ang = self.v_angle;ang_x = 0 - ang_x;
@@ -32,7 +34,8 @@
 		return;
 
 	if (self.button0)
-		W_GenericSlowFireCode("weapons/rocket1i.wav", 0.4, W_PistolFireCode);
+	if (W_ShotsToFire(0.4))
+		W_PistolFireCode();
 
 	if (self.wfiretime)
 	{
Index: dpmod/qc/w_plasmarifle.qc
diff -u dpmod/qc/w_plasmarifle.qc:1.8 dpmod/qc/w_plasmarifle.qc:1.9
--- dpmod/qc/w_plasmarifle.qc:1.8	Sun Mar 16 01:01:00 2003
+++ dpmod/qc/w_plasmarifle.qc	Sun Jun  8 04:02:48 2003
@@ -21,123 +21,58 @@
 		Obituary_Fallback(targ, attacker, dmsg, dtype);
 };
 
-/*
-void() W_PlasmaRifleFire5 =
-{
-	self.wfiretime = time;
-	self.currentammo = self.ammo_cells = self.ammo_cells - 5;
-	FirePlasma(self, shotorg, shotdir, 600 * damagescale, 300, '0 0 0', "PLASMARIFLE", Obituary_PlasmaRifle);
-};
-
-void() W_PlasmaRifleFire1 =
-{
-	self.wfiretime = time;
-	self.currentammo = self.ammo_cells = self.ammo_cells - 1;
-	FirePlasma(self, shotorg, shotdir, 120 * damagescale, 60, '0 0 0', "PLASMARIFLE", Obituary_PlasmaRifle);
-};
-*/
-
-/*
-void(float a, float d, float r) W_PlasmaRifleFireShot =
-{
-	local vector v;
-	if (self.ammo_cells <= 0)
-		return;
-	if (a > self.ammo_cells)
-		a = self.ammo_cells;
-	self.wfiretime = time;
-	self.currentammo = self.ammo_cells = self.ammo_cells - a;
-	self.wburst = self.wburst - a;
-	if (self.plasmabarrel == 0)
-	{
-		self.plasmabarrel = 1;
-		v = v_up * 2;
-	}
-	else if (self.plasmabarrel == 1)
-	{
-		self.plasmabarrel = 2;
-		v = v_right * 1.4 + v_up * -1.4;
-	}
-	else
-	{
-		self.plasmabarrel = 0;
-		v = v_right * -1.4 + v_up * -1.4;
-	}
-	FirePlasma(self, shotorg + v, shotdir + v * 0.005, a * d * damagescale, r, '0 0 0', "PLASMARIFLE", Obituary_PlasmaRifle);
-};
-
-void() W_PlasmaRifleFireRapid =
-{
-	if (self.ammo_cells <= 0)
-	{
-		stopfiring = TRUE;
-		return;
-	}
-	W_PlasmaRifleFireShot(1, 30, 60);
-};
-
-void() W_PlasmaRifleFireBlast =
-{
-	W_PlasmaRifleFireShot(2, 25, 120);
-	W_PlasmaRifleFireShot(2, 25, 120);
-	W_PlasmaRifleFireShot(2, 25, 120);
-};
-
-void() W_PlasmaRifleFireBlast2 =
-{
-	local float d, r;
-	local vector v;
-	self.wfiretime = time;
-	d = 50;
-	r = 120;
-	v = v_up    *  2                ;FirePlasma(self, shotorg + v, shotdir + v * 0.005, d * damagescale, r, '0 0 0', "PLASMARIFLE", Obituary_PlasmaRifle);
-	v = v_right *  1.4 + v_up * -1.4;FirePlasma(self, shotorg + v, shotdir + v * 0.005, d * damagescale, r, '0 0 0', "PLASMARIFLE", Obituary_PlasmaRifle);
-	v = v_right * -1.4 + v_up * -1.4;FirePlasma(self, shotorg + v, shotdir + v * 0.005, d * damagescale, r, '0 0 0', "PLASMARIFLE", Obituary_PlasmaRifle);
-};
-*/
-
 .float plasmabarrel;
-void() W_PlasmaRifleFireRapid2 =
+void(float shots, float cellspershot, float damagepercell, float r) W_PlasmaRifleFire =
 {
-	local float d, r;
 	local vector v;
-	self.currentammo = self.ammo_cells = self.ammo_cells - 1;
-	self.wfiretime = time;
-	if (self.plasmabarrel == 0)
-	{
-		self.plasmabarrel = 1;
-		v = v_up * 2;
-	}
-	else if (self.plasmabarrel == 1)
-	{
-		self.plasmabarrel = 2;
-		v = v_right * 1.4 + v_up * -1.4;
-	}
-	else
-	{
-		self.plasmabarrel = 0;
-		v = v_right * -1.4 + v_up * -1.4;
+	local float cells;
+	W_Hostile();
+	sound(self, CHAN_WEAPON, "plasma/plasma.wav", 1, ATTN_NORM);
+	while (shots > 0)
+	{
+		shots = shots - 1;
+		cells = cellspershot;
+		if (cells > self.ammo_cells)
+			cells = self.ammo_cells;
+		if (cells <= 0)
+			return;
+		self.currentammo = self.ammo_cells = self.ammo_cells - cells;
+		self.wfiretime = time;
+		if (self.plasmabarrel == 0)
+		{
+			self.plasmabarrel = 1;
+			v = v_up * 2;
+		}
+		else if (self.plasmabarrel == 1)
+		{
+			self.plasmabarrel = 2;
+			v = v_right * 1.4 + v_up * -1.4;
+		}
+		else
+		{
+			self.plasmabarrel = 0;
+			v = v_right * -1.4 + v_up * -1.4;
+		}
+		FirePlasma(self, shotorg + v, (shotdir + v * 0.005) * 5000, damagepercell * cells * damagescale, r, "PLASMARIFLE", Obituary_PlasmaRifle);
 	}
-	d = 30;
-	r = 60;
-	FirePlasma(self, shotorg + v, shotdir + v * 0.005, d * damagescale, r, '0 0 0', "PLASMARIFLE", Obituary_PlasmaRifle);
-	if (self.ammo_cells <= 0)
-		stopfiring = TRUE;
 };
 
 .float woverload;
+/*
 void() W_PlasmaRifleFireOverload2 =
 {
 	local float d, r;
 	local vector v;
+	W_Hostile();
+	sound(self, CHAN_WEAPON, "plasma/plasma.wav", 1, ATTN_NORM);
 	self.wfiretime = time;
-	d = self.woverload * 10;
+	d = self.woverload * 20;
 	r = 120;
-	v = v_up    *  2                    ;FirePlasma(self, shotorg + v, shotdir + v * 0.005, d * damagescale, r, '0 0 0', "PLASMARIFLE", Obituary_PlasmaRifle);
-	v = v_right *  1.414 + v_up * -1.414;FirePlasma(self, shotorg + v, shotdir + v * 0.005, d * damagescale, r, '0 0 0', "PLASMARIFLE", Obituary_PlasmaRifle);
-	v = v_right * -1.414 + v_up * -1.414;FirePlasma(self, shotorg + v, shotdir + v * 0.005, d * damagescale, r, '0 0 0', "PLASMARIFLE", Obituary_PlasmaRifle);
-	self.woverload = 0;
+	v = v_up    *  2                    ;FirePlasma(self, shotorg + v, (shotdir + v * 0.005) * 10000, d * damagescale, r, "PLASMARIFLE", Obituary_PlasmaRifle);
+	v = v_right *  1.414 + v_up * -1.414;FirePlasma(self, shotorg + v, (shotdir + v * 0.005) * 10000, d * damagescale, r, "PLASMARIFLE", Obituary_PlasmaRifle);
+	v = v_right * -1.414 + v_up * -1.414;FirePlasma(self, shotorg + v, (shotdir + v * 0.005) * 10000, d * damagescale, r, "PLASMARIFLE", Obituary_PlasmaRifle);
 };
+*/
 
 void() w_plasmarifledrop1;
 void() w_plasmarifledrop2;
@@ -145,179 +80,29 @@
 void() w_plasmarifleraise2;
 void() w_plasmarifle =
 {
-	/*
-	if (time > self.attack_finished)
-	{
-		if (self.button0)
-		{
-			if (self.ammo_cells >= 1)
-			if (self.wburst < 5)
-			{
-				if (self.wburst < 1)
-				{
-					self.wburst = 1;
-					// FIXME: need a prep sound
-					sound(self, CHAN_WEAPON, "plasma/plasexpl.wav", 1, ATTN_NORM);
-				}
-				self.wburst = self.wburst + frametime * 4;
-				if (self.wburst >= 5)
-				{
-					self.wburst = 5;
-					// FIXME: need a full charge reached sound
-					sound(self, CHAN_WEAPON, "plasma/plasexpl.wav", 1, ATTN_NORM);
-				}
-			}
-		}
-		else
-		{
-			// discharge sound
-			if (self.ammo_cells >= 1)
-			if (self.wburst)
-			{
-				// FIXME: need a high power fire sound (and a new low power one)
-				if (self.wburst >= 5)
-					W_GenericSlowFireCode("plasma/plasma.wav", 2, W_PlasmaRifleFire5);
-				else
-					W_GenericSlowFireCode("plasma/plasma.wav", 0.7, W_PlasmaRifleFire1);
-			}
-			self.wburst = 0;
-			if (!self.button3)
-			if (widle(w_plasmarifledrop1))
-				return;
-		}
-	}
-	*/
-
-	/*
-	if (time > self.attack_finished)
-	{
-		if (self.button0)
-		{
-			if (self.wburst)
-				self.wload = self.wload + frametime * 2;
-			else
-				self.wload = 2;
-			while (self.wload >= 1 && self.ammo_cells >= 1 && self.wburst < 5)
-			{
-				// FIXME: need a proper charge sound
-				//if (!self.wburst)
-				//	sound(self, CHAN_WEAPON, "weapons/plasmarifle/charge.wav", 1, ATTN_NORM);
-				//	sound(self, CHAN_WEAPON, "plasma/plasma.wav", 1, ATTN_NORM);
-				sound(self, CHAN_WEAPON, "plasma/plasexpl.wav", 1, ATTN_NORM);
-				self.wburst = self.wburst + 1;
-				self.currentammo = self.ammo_cells = self.ammo_cells - 1;
-				self.wload = self.wload - 1;
-			}
-		}
-		else
-		{
-			if (self.button0)
-			{
-				// fire
-				// FIXME: need a proper fire sound
-				//sound(self, CHAN_WEAPON, "weapons/plasmarifle/fire.wav", 1, ATTN_NORM);
-				sound(self, CHAN_WEAPON, "plasma/plasma.wav", 1, ATTN_NORM);
-				W_GenericSlowFireCode("", 0.7, W_PlasmaRifleFire);
-				self.wburst = 0;
-			}
-			else if (self.wload)
-			{
-				// discharge without firing (wasted ammo)
-				// FIXME: need a proper discharge sound
-				//sound(self, CHAN_WEAPON, "weapons/plasmarifle/discharge.wav", 1, ATTN_NORM);
-				sound(self, CHAN_WEAPON, "plasma/plasexpl.wav", 1, ATTN_NORM);
-			}
-			else if (widle(w_plasmarifledrop1))
-				return;
-			self.wload = 0;
-		}
-	}
-	*/
-
-	/*
-	if (time >= self.attack_finished)
-	{
-		if (self.ammo_cells > 0 && self.wburst > 0 && (self.button0 || self.button3))
-		{
-			// fire higher powered shots if zoomed
-			// (but they use ammo faster, so the burst runs out sooner)
-			self.wload = 1;
-			if (self.button3)
-				self.wload = 3;
-			if (self.wload > self.wburst)
-				self.wload = self.wburst;
-			W_GenericSlowFireCode("plasma/plasma.wav", 0.1 * self.wload, W_PlasmaRifleFire);
-		}
-		else if (self.ammo_cells > 0 && self.wburst < 9)
-		{
-			self.wburst = 9;
-			self.attack_finished = time + 0.4;
-		}
-		else if (widle(w_plasmarifledrop1))
-			return;
-	}
-	*/
-
-	/*
-	if (self.button0 && self.ammo_cells > 0)
-		W_GenericRapidFireCode("plasma/plasma.wav", 0.1, W_PlasmaRifleFireRapid);
-	else
-	{
-		self.notfiring = TRUE;
-		if (self.button3 && self.ammo_cells > 0)
-			W_GenericSlowFireCode("plasma/plasma.wav", 0.8, W_PlasmaRifleFireBlast);
-		else if (time >= self.attack_finished)
-			if (widle(w_plasmarifledrop1))
-				return;
-	}
-	*/
-	/*
-	if (self.button3)
-	{
-		if (self.wburst < 9)
-		if (time > self.attack_finished)
-		{
-			self.wburst = self.wburst + 3;
-			self.currentammo = self.ammo_cells = self.ammo_cells - 1;
-			self.attack_finished = time + 0.1;
-			if (self.wburst > 9)
-				self.wburst = 9;
-			sound(self, CHAN_WEAPON, "plasma/plasexpl.wav", 1, ATTN_NORM);
-		}
-	}
-	else if (self.button0)
+	// FIXME: need overload fire sound (second overload sound)
+	if (self.woverload > 0)
 	{
-		if (self.wburst <= 0)
-		if (time > self.attack_finished)
+		if (W_ShotsToFire(1))
 		{
-			self.wburst = self.wburst + 3;
-			self.currentammo = self.ammo_cells = self.ammo_cells - 1;
-			self.attack_finished = time + 0.1;
-			if (self.wburst > 9)
-				self.wburst = 9;
-			//sound(self, CHAN_WEAPON, "plasma/plasexpl.wav", 1, ATTN_NORM);
+			W_PlasmaRifleFire(3, self.woverload / 3, 30, 120);
+			self.woverload = 0;
 		}
-		if (self.wburst > 0)
-			W_GenericSlowFireCode("plasma/plasma.wav", 0.1, W_PlasmaRifleFireRapid2);
 	}
-	else
+	else if (self.button0 && self.ammo_cells > 0)
 	{
+		self.wload = W_ShotsToFire(0.05);
+		if (self.wload > 0)
+			W_PlasmaRifleFire(self.wload, 1, 30, 60);
 	}
-	*/
-	// FIXME: need overload fire sound (second overload sound)
-	if (self.woverload > 0)
-		W_GenericSlowFireCode("plasma/plasma.wav", 1, W_PlasmaRifleFireOverload2);
-	else if (self.button0 && self.ammo_cells > 0)
-		W_GenericRapidFireCode("plasma/plasma.wav", 0.1, W_PlasmaRifleFireRapid2);
 	else if (time >= self.attack_finished)
 	{
-		self.notfiring = TRUE;
 		if (self.button3 && self.ammo_cells > 0)
 		{
 			self.woverload = 12;
-			if (self.woverload > self.ammo_cells)
-				self.woverload = self.ammo_cells;
-			self.currentammo = self.ammo_cells = self.ammo_cells - self.woverload;
+			//if (self.woverload > self.ammo_cells)
+			//	self.woverload = self.ammo_cells;
+			//self.currentammo = self.ammo_cells = self.ammo_cells - self.woverload;
 			self.attack_finished = time + 0.2;
 			// FIXME: need overload charge sound (first overload sound)
 			sound(self, CHAN_WEAPON, "plasma/plasexpl.wav", 1, ATTN_NORM);
@@ -338,18 +123,19 @@
 	havoc_shotanimupdate(self.weaponframe);
 };
 
-void() weapon8_precache =
+void() weapon9_precache =
 {
 	precache_model("progs/v_dpshot.mdl");
 	precache_model("progs/s_bubble.spr");
 	precache_model("progs/plasmashot.spr32");
+	//precache_sound("weapons/rocket1i.wav");
 	precache_sound("plasma/plasma.wav");
 	precache_sound("plasma/plasexpl.wav");
 };
 
 float() w_plasmariflerating = {return genericweaponrating(0, 1500, 200);};
-void() w_plasmariflesetup = {wset(IT_WEAPON8, IT_CELLS, self.ammo_cells, VWEP_SHOTGUN, "progs/v_dpshot.mdl");};
-float(float request) setweapon8 = {return weapongeneric(IT_WEAPON8, self.ammo_cells >= 1, request, w_plasmariflesetup, w_plasmarifle, w_plasmarifleraise1, w_directaim, w_plasmariflerating, "PlasmaRifle");};
+void() w_plasmariflesetup = {wset(IT_WEAPON9, IT_CELLS, self.ammo_cells, VWEP_SHOTGUN, "progs/v_dpshot.mdl");};
+float(float request) setweapon9 = {return weapongeneric(IT_WEAPON9, self.ammo_cells >= 1, request, w_plasmariflesetup, w_plasmarifle, w_plasmarifleraise1, w_directaim, w_plasmariflerating, "PlasmaRifle");};
 
 void() w_plasmarifleraise1 = {wraise(8, w_plasmarifleraise2, 0.1);};
 void() w_plasmarifleraise2 = {self.wburst = 9;wraise(7, w_plasmarifle, 0.1);};
Index: dpmod/qc/w_plasmawave.qc
diff -u /dev/null dpmod/qc/w_plasmawave.qc:1.1
--- /dev/null	Sun Jun  8 04:02:58 2003
+++ dpmod/qc/w_plasmawave.qc	Sun Jun  8 04:02:48 2003
@@ -0,0 +1,160 @@
+
+void(entity targ, entity attacker, string dmsg, float dtype) Obituary_PlasmaWaveShot =
+{
+	if (dtype == DTYPE_PLAYER)
+	{
+		deathstring1 = targ.netname;
+		deathstring2 = " was incinerated by ";
+		deathstring3 = attacker.netname;
+		deathstring4 = "'s plasma inferno";
+		if (targ.bodyhealth < 1)
+			deathstring2 = " was obliterated by ";
+	}
+	else if (dtype == DTYPE_SUICIDE)
+	{
+		deathstring1 = targ.netname;
+		deathstring2 = " became crispy";
+		deathstring3 = "";
+		deathstring4 = "";
+	}
+	else
+		Obituary_Fallback(targ, attacker, dmsg, dtype);
+};
+
+void(entity targ, entity attacker, string dmsg, float dtype) Obituary_PlasmaWaveOverload =
+{
+	if (dtype == DTYPE_PLAYER)
+	{
+		deathstring1 = targ.netname;
+		deathstring2 = " surfed ";
+		deathstring3 = attacker.netname;
+		deathstring4 = "'s plasma wave";
+		if (targ.bodyhealth < 1)
+			deathstring2 = " wiped out in ";
+	}
+	else if (dtype == DTYPE_SUICIDE)
+	{
+		deathstring1 = targ.netname;
+		deathstring2 = " became crispy";
+		deathstring3 = "";
+		deathstring4 = "";
+	}
+	else
+		Obituary_Fallback(targ, attacker, dmsg, dtype);
+};
+
+void() W_PlasmaWaveFireShot =
+{
+	local float cells;
+	W_Hostile();
+	sound(self, CHAN_WEAPON, "plasma/plasma.wav", 1, ATTN_NORM);
+	cells = self.ammo_cells;
+	if (cells > 10)
+		cells = 10;
+	self.wfiretime = time;
+	self.currentammo = self.ammo_cells = self.ammo_cells - cells;
+	FirePlasmaBall(self, shotorg, shotdir * 1000, cells * 20 * damagescale, 120, "PLASMAWAVE", Obituary_PlasmaWaveShot);
+};
+
+void() W_PlasmaWaveFireWave =
+{
+	/*
+	local float cells;
+	W_Hostile();
+	sound(self, CHAN_WEAPON, "plasma/plasma.wav", 1, ATTN_NORM);
+	cells = self.ammo_cells;
+	if (cells > 50)
+		cells = 50;
+	self.wfiretime = time;
+	self.currentammo = self.ammo_cells = self.ammo_cells - cells;
+	FirePlasmaBall(self, shotorg, shotdir * 1000, cells * 15 * damagescale, 300, "PLASMAWAVE", Obituary_PlasmaWaveShot);
+	*/
+	local float cells, shots, damage;
+	local vector ang;
+	W_Hostile();
+	sound(self, CHAN_WEAPON, "plasma/plasma.wav", 1, ATTN_NORM);
+	cells = self.ammo_cells;
+	if (cells > 50)
+		cells = 50;
+	self.wfiretime = time;
+	self.currentammo = self.ammo_cells = self.ammo_cells - cells;
+	//cells = cells + 60;
+	shots = ceil(cells / 5);
+	if (shots > 12)
+		shots = 12;
+	damage = cells * 20 * damagescale / shots;
+	ang = self.v_angle - (shots * '0 3 0');
+	while (shots > 0)
+	{
+		shots = shots - 1;
+		makevectors(ang);
+		FirePlasmaBall(self, shotorg, v_forward * 1000, damage, 120, "PLASMAWAVE", Obituary_PlasmaWaveOverload);
+		ang = ang + '0 6 0';
+	}
+};
+
+.float woverload;
+void() w_plasmawavedrop1;
+void() w_plasmawavedrop2;
+void() w_plasmawaveraise1;
+void() w_plasmawaveraise2;
+void() w_plasmawave =
+{
+	// FIXME: need overload fire sound (second overload sound)
+	if (self.woverload > 0)
+	{
+		if (W_ShotsToFire(1))
+		{
+			self.woverload = 0;
+			W_PlasmaWaveFireWave();
+		}
+	}
+	else if (self.button0 && self.ammo_cells > 0)
+	{
+		if (W_ShotsToFire(0.5))
+			W_PlasmaWaveFireShot();
+	}
+	else if (time >= self.attack_finished)
+	{
+		if (self.button3 && self.ammo_cells > 0)
+		{
+			self.woverload = 1;
+			self.attack_finished = time + 0.5;
+			// FIXME: need overload charge sound (first overload sound)
+			sound(self, CHAN_WEAPON, "plasma/plasexpl.wav", 1, ATTN_NORM);
+		}
+		else if (widle(w_plasmawavedrop1))
+			return;
+	}
+
+	if (self.wfiretime)
+	{
+		self.weaponframe = floor((time - self.wfiretime) * 10 + 1);
+		if (self.weaponframe >= 3)
+			self.weaponframe = self.wfiretime = 0;
+	}
+	else
+		self.weaponframe = 0;
+
+	havoc_shotanimupdate(self.weaponframe);
+};
+
+void() weapon10_precache =
+{
+	precache_model("progs/v_dpshot.mdl");
+	precache_model("progs/s_bubble.spr");
+	precache_model("progs/plasmashot.spr32");
+	precache_sound("weapons/rocket1i.wav");
+	//precache_sound("plasma/plasma.wav");
+	precache_sound("plasma/plasexpl.wav");
+};
+
+float() w_plasmawaverating = {return genericweaponrating(0, 1500, 200);};
+void() w_plasmawavesetup = {wset(IT_WEAPON10, IT_CELLS, self.ammo_cells, VWEP_LIGHTNING, "progs/v_dplight.mdl");};
+float(float request) setweapon10 = {return weapongeneric(IT_WEAPON10, self.ammo_cells >= 1, request, w_plasmawavesetup, w_plasmawave, w_plasmawaveraise1, w_directaim, w_plasmawaverating, "Plasma Wave Cannon");};
+
+void() w_plasmawaveraise1 = {wraise(3, w_plasmawaveraise2, 0.1);};
+void() w_plasmawaveraise2 = {self.wburst = 4;wraise(7, w_plasmawave, 0.1);};
+
+void() w_plasmawavedrop1 = {wdrop(3, w_plasmawavedrop2, 0.1);};
+void() w_plasmawavedrop2 = {wdropped(4, 0.1);};
Index: dpmod/qc/w_rocket.qc
diff -u dpmod/qc/w_rocket.qc:1.7 dpmod/qc/w_rocket.qc:1.8
--- dpmod/qc/w_rocket.qc:1.7	Tue Mar 11 14:18:26 2003
+++ dpmod/qc/w_rocket.qc	Sun Jun  8 04:02:48 2003
@@ -92,88 +92,38 @@
 		Obituary_Fallback(targ, attacker, dmsg, dtype);
 }
 
-void() W_RocketFire =
-{
-	local vector v;
-	self.wfiretime = time;
-	self.flags = self.flags - (self.flags & FL_ONGROUND);
-	self.velocity = self.velocity - shotdir * 150;
-	self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
-	if (self.wload)
-		v = v_right * 3;
-	else
-		v = v_right * -3;
-	w_muzzleflash(shotorg + v, 2);
-	LaunchMissile(shotorg + v, shotdir * 5000, self, 120 * damagescale, 100, "ROCKET", Obituary_Rocket);
-	self.wload = !self.wload;
-};
-
-void() W_RocketFireDual =
-{
-	local vector v;
-	self.wfiretime = time;
-	self.flags = self.flags - (self.flags & FL_ONGROUND);
-	self.velocity = self.velocity - shotdir * 150;
-	self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
-	v = v_right * 3;
-	w_muzzleflash(shotorg + v, 5);
-	LaunchMissile(shotorg + v, (shotdir + v * 0.005) * 5000, self, 120 * damagescale, 100, "ROCKET", Obituary_Rocket);
-	if (self.ammo_rockets < 1)
-		return;
-	self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
-	v = v_right * -3;
-	w_muzzleflash(shotorg + v, 5);
-	LaunchMissile(shotorg + v, (shotdir + v * 0.005) * 5000, self, 120 * damagescale, 100, "ROCKET", Obituary_Rocket);
-};
-
-void() W_RocketFireTriple =
-{
-	self.wfiretime = time;
-	self.flags = self.flags - (self.flags & FL_ONGROUND);
-	self.velocity = self.velocity - shotdir * 450;
-	self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
-	w_muzzleflash(shotorg, 10);
-	LaunchMissile(shotorg, shotdir * 5000, self, 150 * damagescale, 200, "ROCKET", Obituary_Rocket);
-	if (self.ammo_rockets < 1)
-		return;
-	self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
-	w_muzzleflash(shotorg + v_right * 8, 10);
-	LaunchMissile(shotorg + v_right * 8, (shotdir + v_right * 0.025) * 5000, self, 150 * damagescale, 200, "ROCKET", Obituary_Rocket);
-	if (self.ammo_rockets < 1)
-		return;
-	self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
-	w_muzzleflash(shotorg - v_right * 8, 10);
-	LaunchMissile(shotorg - v_right * 8, (shotdir - v_right * 0.025) * 5000, self, 150 * damagescale, 200, "ROCKET", Obituary_Rocket);
-};
-
 void() W_RocketFireSingle =
 {
+	W_Hostile();
+	sound(self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
 	self.wfiretime = time;
 	self.flags = self.flags - (self.flags & FL_ONGROUND);
 	self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
-	w_muzzleflash(shotorg, 4);
+	w_muzzleflash(shotorg, 2);
 	LaunchMissile(shotorg, shotdir * 5000, self, 120 * damagescale, 100, "ROCKET", Obituary_Rocket);
 };
 
 void() W_RocketFireTripleSpiral =
 {
+	W_Hostile();
+	sound(self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
 	self.wfiretime = time;
 	self.flags = self.flags - (self.flags & FL_ONGROUND);
 	self.velocity = self.velocity - shotdir * 450;
 	self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
-	w_muzzleflash(shotorg, 15);
+	w_muzzleflash(shotorg, 4);
 	LaunchMissile(shotorg, shotdir * 3000, self, 120 * damagescale, 100, "ROCKET", Obituary_Rocket);
 	spiralmissile_orbitentity = newmis;
 	if (self.ammo_rockets < 1)
 		return;
 	self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
-	w_muzzleflash(shotorg + v_right * 8, 10);
-	LaunchSpiralMissile(shotorg, shotdir, self, 80 * damagescale, 100, "ROCKET", Obituary_Rocket, -12);
+	w_muzzleflash(shotorg + v_right * 8, 4);
+	LaunchSpiralMissile(shotorg, shotdir, self, 120 * damagescale, 100, "ROCKET", Obituary_Rocket, -12);
 	if (self.ammo_rockets < 1)
 		return;
 	self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
-	w_muzzleflash(shotorg - v_right * 8, 10);
-	LaunchSpiralMissile(shotorg, shotdir, self, 80 * damagescale, 100, "ROCKET", Obituary_Rocket, 12);
+	w_muzzleflash(shotorg - v_right * 8, 4);
+	LaunchSpiralMissile(shotorg, shotdir, self, 120 * damagescale, 100, "ROCKET", Obituary_Rocket, 12);
 };
 
 void() w_rocketdrop1;
@@ -186,24 +136,15 @@
 		return;
 
 	if (self.button3)
-		W_GenericSlowFireCode("weapons/sgun1.wav", 1.2, W_RocketFireDual);
-	//	W_GenericSlowFireCode("weapons/sgun1.wav", 1, W_RocketFireTripleSpiral);
-	/*
 	{
-		if (self.button0)
-			W_GenericSlowFireCode("weapons/sgun1.wav", 1.2, W_RocketFireTriple);
-		else
-			self.wburst = 1;
+		if (W_ShotsToFire(1.2))
+			W_RocketFireTripleSpiral();
 	}
-	else if (self.wburst)
+	else if (self.button0)
 	{
-		self.wburst = 0;
-		W_GenericSlowFireCode("weapons/sgun1.wav", 1.2, W_RocketFireTripleSpiral);
+		if (W_ShotsToFire(0.6))
+			W_RocketFireSingle();
 	}
-	*/
-	else if (self.button0)
-		W_GenericSlowFireCode("weapons/sgun1.wav", 0.6, W_RocketFire);
-	//	W_GenericSlowFireCode("weapons/sgun1.wav", 0.8, W_RocketFireSingle);
 
 	if (self.wfiretime)
 	{
Index: dpmod/qc/w_shotgun.qc
diff -u dpmod/qc/w_shotgun.qc:1.7 dpmod/qc/w_shotgun.qc:1.8
--- dpmod/qc/w_shotgun.qc:1.7	Wed Apr  9 23:24:30 2003
+++ dpmod/qc/w_shotgun.qc	Sun Jun  8 04:02:48 2003
@@ -16,22 +16,20 @@
 float SHOTGUNEXPLOSIVESLUG = 50;
 
 .float shotgunmode;
-void() W_SingleShotgunFireCode_Buckshot =
+void(float fireexplosive) W_SingleShotgunFireCode =
 {
+	W_Hostile();
+	sound(self, CHAN_WEAPON, "weapons/shotgn2.wav", 1, ATTN_NORM);
 	self.wfiretime = time;
 	self.currentammo = self.ammo_shells = self.ammo_shells - 1;
 	w_muzzleflash(shotorg, 2);
-	FireBullets(self, self, 1, 5, SHOTGUNBUCKSHOT * 0.1 * damagescale, SHOTGUNBUCKSHOT * 0.1 * damagescale, 0, 0, shotdir * 6000, 0.05, "SHOTGUN", DT_SHOTGUN, Obituary_Shotgun);
-	FireBullets(self, self, 0, 5, SHOTGUNBUCKSHOT * 0.1 * damagescale, SHOTGUNBUCKSHOT * 0.1 * damagescale, 0, 0, shotdir * 6000, 0.05, "SHOTGUN", DT_SHOTGUN, Obituary_Shotgun);
-	self.wload = -1;
-};
-
-void() W_SingleShotgunFireCode_Explosive =
-{
-	self.wfiretime = time;
-	self.currentammo = self.ammo_shells = self.ammo_shells - 1;
-	w_muzzleflash(shotorg, 2);
-	FireBullets(self, self, 1, 1, SHOTGUNEXPLOSIVESLUG * 0.2 * damagescale, SHOTGUNEXPLOSIVESLUG * 0.2 * damagescale, SHOTGUNEXPLOSIVESLUG * 0.8 * damagescale, 80, shotdir * 5000, 0, "SHOTGUNEXPLOSIVESLUG", DT_SHOTGUN, Obituary_Shotgun);
+	if (fireexplosive)
+		FireBullets(self, self, 1, 1, SHOTGUNEXPLOSIVESLUG * 0.2 * damagescale, SHOTGUNEXPLOSIVESLUG * 0.2 * damagescale, SHOTGUNEXPLOSIVESLUG * 0.8 * damagescale, 80, shotdir * 5000, 0, "SHOTGUNEXPLOSIVESLUG", DT_SHOTGUN, Obituary_Shotgun);
+	else
+	{
+		FireBullets(self, self, 1, 5, SHOTGUNBUCKSHOT * 0.1 * damagescale, SHOTGUNBUCKSHOT * 0.1 * damagescale, 0, 0, shotdir * 6000, 0.05, "SHOTGUN", DT_SHOTGUN, Obituary_Shotgun);
+		FireBullets(self, self, 0, 5, SHOTGUNBUCKSHOT * 0.1 * damagescale, SHOTGUNBUCKSHOT * 0.1 * damagescale, 0, 0, shotdir * 6000, 0.05, "SHOTGUN", DT_SHOTGUN, Obituary_Shotgun);
+	}
 	self.wload = -1;
 };
 
@@ -62,15 +60,11 @@
 	if (self.wload > self.ammo_shells)
 		self.wload = self.ammo_shells;
 
-	if (self.button0)
-	{
-		if (self.wload >= 1) // is it loaded?
-			W_GenericSlowFireCode("weapons/shotgn2.wav", 0.3, W_SingleShotgunFireCode_Buckshot);
-	}
-	else if (self.button3)
+	if (self.button0 || self.button3)
 	{
 		if (self.wload >= 1) // is it loaded?
-			W_GenericSlowFireCode("weapons/shotgn2.wav", 0.3, W_SingleShotgunFireCode_Explosive);
+		if (W_ShotsToFire(0.3))
+			W_SingleShotgunFireCode(self.button3);
 	}
 
 	if (self.wload < 1 && time > self.attack_finished)
Index: dpmod/qc/w_supernailgun.qc
diff -u dpmod/qc/w_supernailgun.qc:1.6 dpmod/qc/w_supernailgun.qc:1.7
--- dpmod/qc/w_supernailgun.qc:1.6	Wed Apr  9 23:24:30 2003
+++ dpmod/qc/w_supernailgun.qc	Sun Jun  8 04:02:48 2003
@@ -12,24 +12,28 @@
 		Obituary_Fallback(targ, attacker, dmsg, dtype);
 };
 
-void() W_SuperNailgunFireCode =
+void(float shots) W_SuperNailgunFireCode =
 {
 	local vector v, ang;
-	self.currentammo = self.ammo_nails = self.ammo_nails - 1;
-	self.wframe = self.wframe + 0.5; // 10fps animation
-	if (self.wframe >= 9)
-		self.wframe = 1;
-	self.wfiretime = time;
-
+	W_Hostile();
+	sound(self, CHAN_WEAPON, "weapons/spike2.wav", 1, ATTN_NORM);
 	v = shotorg;
-	shotorg = shotorg + v_up * 2;
-	w_muzzleflash(shotorg, 1);
-	ang = self.v_angle;ang_x = 0 - ang_x;
-	ejectcasing(shotorg, v_right * 200 + v_up * 50, 50, ang, '0 50 0', 100, 0);
-	FireBullets(self, self, 4, 1, 15 * damagescale, 15 * damagescale, 0, 0, shotdir * 7000, 0.05, "SUPERNAILGUN", DT_NAIL, Obituary_SuperNailgun);
+	while (shots > 0 && self.ammo_nails >= 1)
+	{
+		shots = shots - 1;
+		self.currentammo = self.ammo_nails = self.ammo_nails - 1;
+		self.wframe = self.wframe + 0.5; // 10fps animation
+		if (self.wframe >= 9)
+			self.wframe = 1;
+		self.wfiretime = time;
+
+		shotorg = shotorg + v_up * 2;
+		w_muzzleflash(shotorg, 1);
+		ang = self.v_angle;ang_x = 0 - ang_x;
+		ejectcasing(shotorg, v_right * 200 + v_up * 50, 50, ang, '0 50 0', 100, 0);
+		FireBullets(self, self, 4, 1, 15 * damagescale, 15 * damagescale, 0, 0, shotdir * 7000, 0.05, "SUPERNAILGUN", DT_NAIL, Obituary_SuperNailgun);
+	}
 	shotorg = v;
-
-	if (self.ammo_nails < 1) {stopfiring = TRUE;return;}
 };
 
 void(entity targ, entity attacker, string dmsg, float dtype) Obituary_ProximityMine =
@@ -71,6 +75,8 @@
 void() W_SuperNailgunMineFireCode =
 {
 	local float a;
+	W_Hostile();
+	sound(self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
 	self.wfiretime = time;
 	a = 3;
 	if (a > self.ammo_rockets)
@@ -92,14 +98,18 @@
 	if (self.button0)
 	{
 		if (self.ammo_nails >= 1)
-			W_GenericRapidFireCode("weapons/spike2.wav", 0.05, W_SuperNailgunFireCode);
+		{
+			self.wload = W_ShotsToFire(0.05);
+			if (self.wload > 0)
+				W_SuperNailgunFireCode(self.wload);
+		}
 	}
 	else
 	{
-		self.notfiring = TRUE;
 		if (self.button3)
 		if (self.ammo_rockets >= 1)
-			W_GenericSlowFireCode("weapons/grenade.wav", 0.5, W_SuperNailgunMineFireCode);
+		if (W_ShotsToFire(0.5))
+			W_SuperNailgunMineFireCode();
 	}
 
 	if ((time - self.wfiretime) < 0.15)


More information about the twilight-commits mailing list