Module dpmod: Change committed

havoc at icculus.org havoc at icculus.org
Sat Aug 9 12:20:39 EDT 2003


Commiter   : havoc
CVSROOT    : /cvs/cvsroot/twilight
Module     : dpmod
Commit time: 2003-08-09 16:20:39 UTC

Log message:

cleaned up some weapon code related to havocbot aiming (each weapon aims itself now)
cleaned up some damage scaling code (fixing the bugs that made monsters too tough)
added WR_SWITCH request to clean up a little code

Modified files:
     qc/client.qc qc/damage.qc qc/dpextensions.qc qc/havocbot.qc
     qc/impulse_main.qc qc/inventory.qc qc/item_backpacks.qc
     qc/m_enforcer.qc qc/m_ogre.qc qc/m_soldier.qc
     qc/mode_management.qc qc/plasma.qc qc/playermovement.qc
     qc/rocket.qc qc/t_damage.qc qc/w_common.qc qc/w_dbshotgun.qc
     qc/w_defs.qc qc/w_grenade.qc qc/w_info.qc qc/w_lightning.qc
     qc/w_nailgun.qc qc/w_pistol.qc qc/w_plasmarifle.qc
     qc/w_plasmawave.qc qc/w_rocket.qc qc/w_shotgun.qc
     qc/w_supernailgun.qc qc/world.qc

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

Index: dpmod/qc/client.qc
diff -u dpmod/qc/client.qc:1.11 dpmod/qc/client.qc:1.12
--- dpmod/qc/client.qc:1.11	Sun Jul 27 03:01:18 2003
+++ dpmod/qc/client.qc	Sat Aug  9 12:20:28 2003
@@ -136,15 +136,45 @@
 
 void() SetNewParms =
 {
-	parm1 = IT_WEAPON1 | IT_WEAPON2 | IT_WEAPON10; // | IT_WEAPON3 | IT_WEAPON4 | IT_WEAPON5 | IT_WEAPON6 | IT_WEAPON7 | IT_WEAPON8 | IT_WEAPON9 | IT_WEAPON10;
-	parm2 = HEALTHMAX; // health
-	parm3 = 0; // armorvalue
-	parm4 = STARTSP_AMMO_SHELLS;
-	parm5 = STARTSP_AMMO_NAILS;
-	parm6 = STARTSP_AMMO_ROCKETS;
-	parm7 = STARTSP_AMMO_CELLS;
-	parm8 = STARTSP_WEAPON; // selected weapon
-	parm9 = 0; // armortype * 100
+	if (deathmatch == DM_FRAGFEST || deathmatch == DM_ELIM)
+	{
+		parm1 = IT_WEAPON1 | IT_WEAPON2 | IT_WEAPON3 | IT_WEAPON4 | IT_WEAPON5 | IT_WEAPON6 | IT_WEAPON7 | IT_WEAPON8 | IT_WEAPON9 | IT_WEAPON10; //STARTPARMSELIM_ITEMS;
+		parm2 = STARTPARMSELIM_HEALTH;
+		parm3 = STARTPARMSELIM_ARMORVALUE;
+		parm4 = STARTPARMSELIM_AMMO_SHELLS;
+		parm5 = STARTPARMSELIM_AMMO_NAILS;
+		parm6 = STARTPARMSELIM_AMMO_ROCKETS;
+		parm7 = STARTPARMSELIM_AMMO_CELLS;
+		parm8 = 0; // weapon
+		parm9 = STARTPARMSELIM_ARMORTYPE * 100;
+		parm10 = STARTPARMSELIM_MAXHEALTH;
+	}
+	else if (deathmatch)
+	{
+		parm1 = IT_WEAPON1 | IT_WEAPON2; //STARTPARMSDM_ITEMS;
+		parm2 = STARTPARMSDM_HEALTH;
+		parm3 = STARTPARMSDM_ARMORVALUE;
+		parm4 = STARTPARMSDM_AMMO_SHELLS;
+		parm5 = STARTPARMSDM_AMMO_NAILS;
+		parm6 = STARTPARMSDM_AMMO_ROCKETS;
+		parm7 = STARTPARMSDM_AMMO_CELLS;
+		parm8 = 0; // weapon
+		parm9 = STARTPARMSDM_ARMORTYPE * 100;
+		parm10 = STARTPARMSDM_MAXHEALTH;
+	}
+	else
+	{
+		parm1 = IT_WEAPON1 | IT_WEAPON2; //STARTPARMSSP_ITEMS;
+		parm2 = STARTPARMSSP_HEALTH;
+		parm3 = STARTPARMSSP_ARMORVALUE;
+		parm4 = STARTPARMSSP_AMMO_SHELLS;
+		parm5 = STARTPARMSSP_AMMO_NAILS;
+		parm6 = STARTPARMSSP_AMMO_ROCKETS;
+		parm7 = STARTPARMSSP_AMMO_CELLS;
+		parm8 = 0; // weapon
+		parm9 = STARTPARMSSP_ARMORTYPE * 100;
+		parm10 = STARTPARMSSP_MAXHEALTH;
+	}
 };
 
 void() SetChangeParms =
@@ -167,59 +197,29 @@
 	parm7 = Inventory_Quantity(self, "cells");
 	parm8 = self.weapon;
 	parm9 = self.armortype * 100;
+	parm10 = self.max_health;
 };
 
 void() DecodeLevelParms =
 {
-	if ((deathmatch == DM_FRAGFEST) || (deathmatch == DM_ELIM))
-	{
-		self.items = IT_WEAPON1 | IT_WEAPON2 | IT_WEAPON3 | IT_WEAPON4 | IT_WEAPON5 | IT_WEAPON6 | IT_WEAPON7 | IT_WEAPON8 | IT_WEAPON9 | IT_WEAPON10 | IT_ARMOR3;
-		self.health = self.max_health = HEALTHMAX; // start at max, not above it
-		if (deathmatch == DM_ELIM)
-			self.health = self.max_health = HEALTHELIMINATION;
-		self.armortype = 0.8;
-		self.armorvalue = 200;
-		// this gets clipped down to whatever the limits are
-		Inventory_SetQuantity(self, "shells", 9999999);
-		Inventory_SetQuantity(self, "nails", 9999999);
-		Inventory_SetQuantity(self, "rockets", 9999999);
-		Inventory_SetQuantity(self, "cells", 9999999);
-		Inventory_SetQuantity(self, "xshells", 9999999);
-		self.weapon = W_BestWeapon(TRUE);
-	}
-	else if (deathmatch)
-	{
-		self.items = IT_WEAPON1 | IT_WEAPON2 | IT_WEAPON9 | IT_WEAPON10 | IT_ARMOR1; // | IT_WEAPON3 | IT_WEAPON4 | IT_WEAPON5 | IT_WEAPON6 | IT_WEAPON7 | IT_WEAPON8 | IT_WEAPON9 | IT_WEAPON10;
-		self.health = HEALTHSTART; // health
-		self.max_health = HEALTHMAX;
-		self.armorvalue = 50;
-		self.armortype = 0.3;
-		Inventory_SetQuantity(self, "shells", STARTDM_AMMO_SHELLS);
-		Inventory_SetQuantity(self, "nails", STARTDM_AMMO_NAILS);
-		Inventory_SetQuantity(self, "rockets", STARTDM_AMMO_ROCKETS);
-		Inventory_SetQuantity(self, "cells", STARTDM_AMMO_CELLS);
-		Inventory_SetQuantity(self, "xshells", STARTDM_AMMO_XSHELLS);
-		self.weapon = W_BestWeapon(TRUE);
-	}
-	else // singleplayer or coop
-	{
-		// if a bot, or on start map, reset equipment
-		if (self.isbot || world.model == "maps/start.bsp")
-			SetNewParms();
-		self.max_health = HEALTHMAX;
-		self.items = parm1;
-		self.health = parm2;
-		if (self.health < 1)
-			self.health = 1;
-		self.armorvalue = parm3;
-		Inventory_SetQuantity(self, "shells", parm4);
-		Inventory_SetQuantity(self, "nails", parm5);
-		Inventory_SetQuantity(self, "rockets", parm6);
-		Inventory_SetQuantity(self, "cells", parm7);
-		self.weapon = parm8;
-		self.armortype = parm9 / 100;
-		Inventory_SetQuantity(self, "xshells", parm10);
-	}
+	// reset equipment in some cases
+	if (deathmatch || self.isbot || world.model == "maps/start.bsp")
+		SetNewParms();
+	self.items = parm1;
+	self.health = parm2;
+	self.armorvalue = parm3;
+	Inventory_SetQuantity(self, "shells", parm4);
+	Inventory_SetQuantity(self, "nails", parm5);
+	Inventory_SetQuantity(self, "rockets", parm6);
+	Inventory_SetQuantity(self, "cells", parm7);
+	self.weapon = parm8;
+	self.armortype = parm9 / 100;
+	self.max_health = parm10;
+	// safety checks
+	if (self.health < 1)
+		self.health = 1;
+	if (self.max_health < 1)
+		self.max_health = 100;
 	self.bodyhealth = self.health + 100;
 	if ((self.items & self.weapon) == 0)
 		self.weapon = W_BestWeapon(TRUE);
@@ -853,7 +853,6 @@
 		Inventory_SetQuantity(self, "nails", 0);
 		Inventory_SetQuantity(self, "rockets", 0);
 		Inventory_SetQuantity(self, "cells", 0);
-		Inventory_SetQuantity(self, "xshells", 0);
 		self.items = 0;
 		self.think = SUB_Null;
 		self.nextthink = 0;
@@ -1168,7 +1167,6 @@
 		Inventory_SetQuantity(self, "nails", AMMOMAX_NAILS);
 		Inventory_SetQuantity(self, "rockets", AMMOMAX_ROCKETS);
 		Inventory_SetQuantity(self, "cells", AMMOMAX_CELLS);
-		Inventory_SetQuantity(self, "xshells", AMMOMAX_XSHELLS);
 	}
 
 	if (intermission_running)
Index: dpmod/qc/damage.qc
diff -u dpmod/qc/damage.qc:1.4 dpmod/qc/damage.qc:1.5
--- dpmod/qc/damage.qc:1.4	Wed Jun 11 05:07:37 2003
+++ dpmod/qc/damage.qc	Sat Aug  9 12:20:28 2003
@@ -3,40 +3,54 @@
 .float  ammo_nails;
 .float  ammo_rockets;
 .float  ammo_cells;
-.float  ammo_xshells;
 
 float   AMMOMAX_SHELLS          =  100;
 float   AMMOMAX_NAILS           =  200;
 float   AMMOMAX_ROCKETS         =  100;
 float   AMMOMAX_CELLS           =  200;
-float   AMMOMAX_XSHELLS         =  100;
 
-float   STARTDM_AMMO_SHELLS      =    20;
-float   STARTDM_AMMO_NAILS       =    0;
-float   STARTDM_AMMO_ROCKETS     =    0;
-float   STARTDM_AMMO_CELLS       =    0;
-float   STARTDM_AMMO_XSHELLS     =    0;
-
-float   STARTSP_AMMO_SHELLS      =    20;
-float   STARTSP_AMMO_NAILS       =    0;
-float   STARTSP_AMMO_ROCKETS     =    0;
-float   STARTSP_AMMO_CELLS       =    0;
-float   STARTSP_AMMO_XSHELLS     =    0;
-float   STARTSP_WEAPON           = IT_WEAPON2;
+// LordHavoc: since constants can't have math in them, the ITEMS are inlined in client.qc :(
+float   STARTPARMSDM_AMMO_SHELLS     =   20;
+float   STARTPARMSDM_AMMO_NAILS      =    0;
+float   STARTPARMSDM_AMMO_ROCKETS    =    0;
+float   STARTPARMSDM_AMMO_CELLS      =    0;
+//float   STARTPARMSDM_ITEMS           = IT_WEAPON1 | IT_WEAPON2;
+float   STARTPARMSDM_HEALTH          =  125;
+float   STARTPARMSDM_MAXHEALTH       =  100;
+float   STARTPARMSDM_ARMORVALUE      =    0;
+float   STARTPARMSDM_ARMORTYPE       =    0;
 
+float   STARTPARMSSP_AMMO_SHELLS     =   20;
+float   STARTPARMSSP_AMMO_NAILS      =    0;
+float   STARTPARMSSP_AMMO_ROCKETS    =    0;
+float   STARTPARMSSP_AMMO_CELLS      =    0;
+//float   STARTPARMSSP_ITEMS           = IT_WEAPON1 | IT_WEAPON2;
+float   STARTPARMSSP_HEALTH          =  100;
+float   STARTPARMSSP_MAXHEALTH       =  100;
+float   STARTPARMSSP_ARMORVALUE      =    0;
+float   STARTPARMSSP_ARMORTYPE       =    0;
+
+float   STARTPARMSELIM_AMMO_SHELLS   =  100;
+float   STARTPARMSELIM_AMMO_NAILS    =  200;
+float   STARTPARMSELIM_AMMO_ROCKETS  =  100;
+float   STARTPARMSELIM_AMMO_CELLS    =  200;
+//float   STARTPARMSELIM_ITEMS         = IT_WEAPON1 | IT_WEAPON2 | IT_WEAPON3 | IT_WEAPON4 | IT_WEAPON5 | IT_WEAPON6 | IT_WEAPON7 | IT_WEAPON8 | IT_WEAPON9 | IT_WEAPON10;
+float   STARTPARMSELIM_HEALTH        =  400;
+float   STARTPARMSELIM_MAXHEALTH     =  400;
+float   STARTPARMSELIM_ARMORVALUE    =    0;
+float   STARTPARMSELIM_ARMORTYPE     =    0;
+
 // ammo given by collecting weapons when already at weapon's fill-up limit
 float   AMMOWEAPONOVERFLOW              =    0; // false, thus it will give normal ammo
 float   AMMOWEAPONOVERFLOW_SHELLS       =    3;
 float   AMMOWEAPONOVERFLOW_NAILS        =    5;
 float   AMMOWEAPONOVERFLOW_ROCKETS      =    1;
 float   AMMOWEAPONOVERFLOW_CELLS        =    5;
-float   AMMOWEAPONOVERFLOW_XSHELLS      =    3;
 
 float   AMMO_SHELLS                     =   20; // double if big box
 float   AMMO_NAILS                      =   25; // double if big box
 float   AMMO_ROCKETS                    =    5; // double if big box
 float   AMMO_CELLS                      =   14; // double if big box
-float   AMMO_XSHELLS                    =   20; // double if big box
 
 float   AMMO_GRUNT_PISTOL_ROUNDS        =    5;
 float   AMMO_GRUNT_SHOTGUN_SHELLS       =    2;
Index: dpmod/qc/dpextensions.qc
diff -u dpmod/qc/dpextensions.qc:1.12 dpmod/qc/dpextensions.qc:1.13
--- dpmod/qc/dpextensions.qc:1.12	Wed Jul 30 20:42:56 2003
+++ dpmod/qc/dpextensions.qc	Sat Aug  9 12:20:28 2003
@@ -1,70 +1,15 @@
 
 //DarkPlaces supported extension list, draft version 1.04
 
-//DP_GFX_SKINFILES
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//description:
-//alias models (mdl, md2, md3) can have .skin files to replace conventional texture naming, these have a naming format such as:
-//progs/test.md3_0.skin
-//progs/test.md3_1.skin
-//...
-//
-//these files contain replace commands (replace meshname shadername), example:
-//replace "helmet" "progs/test/helmet1.tga" // this is a mesh shader replacement
-//replace "teamstripes" "progs/test/redstripes.tga"
-//replace "visor" "common/nodraw" // this makes the visor mesh invisible
-////it is not possible to rename tags using this format
-//
-//Or the Quake3 syntax (100% compatible withe Quake3's .skin files):
-//helmet,progs/test/helmet1.tga // this is a mesh shader replacement
-//teamstripes,progs/test/redstripes.tga
-//visor,common/nodraw // this makes the visor mesh invisible
-//tag_camera, // this defines that the first tag in the model is called tag_camera
-//tag_test, // this defines that the second tag in the model is called tag_test
-//
-//any names that are not replaced are automatically show up as a grey checkerboard to indicate the error status, and "common/nodraw" is a special case that is invisible.
-//this feature is intended to allow multiple skin sets on md3 models (which otherwise only have one skin set).
-//other commands might be added someday but it is not expected.
-
-//DP_GFX_QUAKE3MODELTAGS
-//idea: id Software
-//darkplaces implementation: LordHavoc
-//field definitions:
-.entity tag_entity; // entity this is attached to (call setattachment to set this)
-.float tag_index; // which tag on that entity (0 is relative to the entity, > 0 is an index into the tags on the model if it has any) (call setattachment to set this)
-//builtin definitions:
-void(entity e, entity tagentity, string tagname) setattachment = #443; // attachs e to a tag on tagentity (note: use "" to attach to entity origin/angles instead of a tag)
-//description:
-//allows entities to be visually attached to model tags (which follow animations perfectly) on other entities, for example attaching a weapon to a player's hand, or upper body attached to lower body, allowing it to change angles and frame separately (note: origin and angles are relative to the tag, use '0 0 0' for both if you want it to follow exactly, this is similar to viewmodelforclient's behavior).
-//note 2: if the tag is not found, it defaults to "" (attach to origin/angles of entity)
-//note 3: attaching to world turns off attachment
-//note 4: the entity that this is attached to must be visible for this to work
-
-//DP_QC_BOTCLIENT
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//builtin definitions:
-// FIXME: these need numbers assigned, and they need to be added to the engine!
-//entity() spawnclient = #; // like spawn but for client slots (also calls relevant connect/spawn functions), returns world if no clients available
-//void(entity e) removeclient = #; // like remove but for client slots (also calls relevant disconnect functions)
-//description:
-//functions to allow bots to use client slots with no hacks, some notes:
-.string netname; //controls name on scoreboard (so be sure to set it for a bot)
-.float frags; //controls score on scoreboard (this is expected)
-.float clientcolors; //controls coloring on scoreboard (this determines player colors exactly like the "color" command, except for using a single number that contains pants and shirt colors (pants + shirt * 16, 0-255 potentially), so be sure to set it for a bot)
-//note also that these fields can be set on a real client to change the relevant settings.
-//see also DP_SV_SETCOLOR extension for another way to manipulate clientcolors (made obsolete by this extension).
-
-//unassigned stuff:  (need to write up specs but haven't yet)
-.vector punchvector; // DP_SV_PUNCHVECTOR
-.float  ping; // DP_SV_PING
-
 //checkextension function
 //idea: expected by almost everyone
 //darkplaces implementation: LordHavoc
 float(string s) checkextension = #99;
-//description: check if (cvar("pr_checkextension")) before calling this, this is the only guarenteed extension to be present in the extension system, it allows you to check if an extension is available, by name, to check for an extension use code like this:
+//description:
+//check if (cvar("pr_checkextension")) before calling this, this is the only
+//guarenteed extension to be present in the extension system, it allows you
+//to check if an extension is available, by name, to check for an extension
+//use code like this:
 //// (it is recommended this code be placed in worldspawn or a worldspawn called function somewhere)
 //if (cvar("pr_checkextension"))
 //if (checkextension("DP_SV_SETCOLOR"))
@@ -297,6 +242,46 @@
 game/gfx/conchars.tga
 */
 
+//DP_GFX_QUAKE3MODELTAGS
+//idea: id Software
+//darkplaces implementation: LordHavoc
+//field definitions:
+.entity tag_entity; // entity this is attached to (call setattachment to set this)
+.float tag_index; // which tag on that entity (0 is relative to the entity, > 0 is an index into the tags on the model if it has any) (call setattachment to set this)
+//builtin definitions:
+void(entity e, entity tagentity, string tagname) setattachment = #443; // attachs e to a tag on tagentity (note: use "" to attach to entity origin/angles instead of a tag)
+//description:
+//allows entities to be visually attached to model tags (which follow animations perfectly) on other entities, for example attaching a weapon to a player's hand, or upper body attached to lower body, allowing it to change angles and frame separately (note: origin and angles are relative to the tag, use '0 0 0' for both if you want it to follow exactly, this is similar to viewmodelforclient's behavior).
+//note 2: if the tag is not found, it defaults to "" (attach to origin/angles of entity)
+//note 3: attaching to world turns off attachment
+//note 4: the entity that this is attached to must be visible for this to work
+
+//DP_GFX_SKINFILES
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//description:
+//alias models (mdl, md2, md3) can have .skin files to replace conventional texture naming, these have a naming format such as:
+//progs/test.md3_0.skin
+//progs/test.md3_1.skin
+//...
+//
+//these files contain replace commands (replace meshname shadername), example:
+//replace "helmet" "progs/test/helmet1.tga" // this is a mesh shader replacement
+//replace "teamstripes" "progs/test/redstripes.tga"
+//replace "visor" "common/nodraw" // this makes the visor mesh invisible
+////it is not possible to rename tags using this format
+//
+//Or the Quake3 syntax (100% compatible withe Quake3's .skin files):
+//helmet,progs/test/helmet1.tga // this is a mesh shader replacement
+//teamstripes,progs/test/redstripes.tga
+//visor,common/nodraw // this makes the visor mesh invisible
+//tag_camera, // this defines that the first tag in the model is called tag_camera
+//tag_test, // this defines that the second tag in the model is called tag_test
+//
+//any names that are not replaced are automatically show up as a grey checkerboard to indicate the error status, and "common/nodraw" is a special case that is invisible.
+//this feature is intended to allow multiple skin sets on md3 models (which otherwise only have one skin set).
+//other commands might be added someday but it is not expected.
+
 //DP_HALFLIFE_MAP
 //idea: LordHavoc
 //darkplaces implementation: LordHavoc
@@ -842,7 +827,7 @@
 //idea: KrimZon
 //darkplaces implementation: KrimZon, LordHavoc
 //engine-called QC prototypes:
-//void(string s) SV_ParseCommand;
+//void(string s) SV_ParseClientCommand;
 //builtin definitions:
 void(entity e, string s) clientcommand = #440;
 float(string s) tokenize = #441;
@@ -872,5 +857,25 @@
 //sv_stepheight (default 18)
 //description:
 //sv_jumpstep allows stepping up onto stairs while airborn, sv_stepheight controls how high a single step can be.
+
+// UNFINISHED section
+//DP_QC_BOTCLIENT
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//builtin definitions:
+// FIXME: these need numbers assigned, and they need to be added to the engine!
+//entity() spawnclient = #; // like spawn but for client slots (also calls relevant connect/spawn functions), returns world if no clients available
+//void(entity e) removeclient = #; // like remove but for client slots (also calls relevant disconnect functions)
+//description:
+//functions to allow bots to use client slots with no hacks, some notes:
+.string netname; //controls name on scoreboard (so be sure to set it for a bot)
+.float frags; //controls score on scoreboard (this is expected)
+.float clientcolors; //controls coloring on scoreboard (this determines player colors exactly like the "color" command, except for using a single number that contains pants and shirt colors (pants + shirt * 16, 0-255 potentially), so be sure to set it for a bot)
+//note also that these fields can be set on a real client to change the relevant settings.
+//see also DP_SV_SETCOLOR extension for another way to manipulate clientcolors (made obsolete by this extension).
+
+//unassigned stuff:  (need to write up specs but haven't yet)
+.vector punchvector; // DP_SV_PUNCHVECTOR
+.float  ping; // DP_SV_PING
 
 
Index: dpmod/qc/havocbot.qc
diff -u dpmod/qc/havocbot.qc:1.6 dpmod/qc/havocbot.qc:1.7
--- dpmod/qc/havocbot.qc:1.6	Wed Apr  9 23:24:30 2003
+++ dpmod/qc/havocbot.qc	Sat Aug  9 12:20:28 2003
@@ -1099,11 +1099,8 @@
 	while (head)
 	{
 		if (head.takedamage == DAMAGE_AIM)
-		if (head != self)
-		if (!head.deadflag)
 		if (head.health < besthealth)
-		if (head.classname != "player" || !coop)
-		if (head.team != self.team || self.team == 0 || teamplay == 0)
+		if (w_shouldattack(head))
 		{
 			traceline(self.origin + self.view_ofs, (head.absmin + head.absmax) * 0.5, FALSE, self);
 			if (trace_ent == head || trace_fraction >= 1)
@@ -1125,15 +1122,12 @@
 .float nextaim;
 void() havocbot_aim =
 {
-	local float aimlatency;
 	local vector selfvel, enemyvel;
 	local string s;
 	if (time < self.nextaim)
 		return;
 	self.nextaim = time + 0.1;
-	aimlatency = (4 - skill) * 0.1 + random() * 0.05;
-	self.ping = self.ping + (aimlatency - self.ping) * frametime * 3;
-	aimlatency = self.ping;
+	self.ping = self.ping + (((4 - skill) * 0.1 + random() * 0.05) - self.ping) * frametime * 3;
 	if (self.enemy != world)
 	{
 		selfvel = self.velocity;
@@ -1142,13 +1136,14 @@
 		enemyvel = self.enemy.velocity;
 		if (!self.enemy.waterlevel)
 			enemyvel_z = 0;
-		lag_additem(time + aimlatency, 0, 0, self.enemy, self.origin, selfvel, self.enemy.origin, enemyvel);
+		lag_additem(time + self.ping, 0, 0, self.enemy, self.origin, selfvel, self.enemy.origin, enemyvel);
 	}
 	else
-		lag_additem(time + aimlatency, 0, 0, world, '0 0 0', '0 0 0', '0 0 0', '0 0 0');
+		lag_additem(time + self.ping, 0, 0, world, '0 0 0', '0 0 0', '0 0 0', '0 0 0');
 };
 
 .entity aimtarg;
+.float aimlatency;
 .vector aimselforigin;
 .vector aimselfvelocity;
 .vector aimtargorigin;
@@ -1156,17 +1151,19 @@
 void(float t, float f1, float f2, entity e1, vector v1, vector v2, vector v3, vector v4) havocbot_lagfunc =
 {
 	self.aimtarg = e1;
+	self.aimlatency = self.ping; // FIXME?  Shouldn't this be in the lag item?
 	self.aimselforigin = v1;
 	self.aimselfvelocity = v2;
 	self.aimtargorigin = v3;
 	self.aimtargvelocity = v4;
 };
 
+/*
 .float painintensity;
 void() havocbot_doaim =
 {
 	local vector ang, angdiff, originalangdiff, selfvel, selforigin, targvel, targorigin, v, aimdir;
-	local float angdistance, fire, aimlatency, latency, shotleadspeed, pain;
+	local float angdistance, fire, latency, shotleadspeed, pain;
 	local entity targ, saveenemy;
 	//local string s;
 
@@ -1181,7 +1178,10 @@
 	}
 	if (targ != world)
 	if (targ.takedamage)
+	if (self.weapon == self.switchweapon)
+	if (self.wstate == WS_ACTIVE)
 	{
+*/
 		/*
 		if (time > self.weaponchangetimeout || !setweapon(self.weapon, WR_SELECTABLE))
 		{
@@ -1189,62 +1189,63 @@
 			self.switchweapon = W_BestWeaponForTarget(targ); //W_BestWeapon(TRUE);
 		}
 		*/
-		selforigin = self.aimselforigin + self.aimselfvelocity * aimlatency;
-		targorigin = self.aimtargorigin + self.aimtargvelocity * aimlatency;
-		if (self.weapon == IT_WEAPON6) shotleadspeed = 600;
-		else if (self.weapon == IT_WEAPON7) shotleadspeed = 5000;
-		else if (self.weapon == IT_WEAPON8) shotleadspeed = 5000;
-		else shotleadspeed = 5000;
+/*
+		selforigin = self.aimselforigin + self.aimselfvelocity * self.aimlatency;
+		targorigin = self.aimtargorigin + self.aimtargvelocity * self.aimlatency;
+		shotleadspeed = setweapon(self.weapon, WR_SHOTLEADSPEED);
 		latency = vlen(targorigin - selforigin) / shotleadspeed;
-		v = targorigin + self.aimtargvelocity * latency - self.aimselfvelocity * latency;
+		v = targorigin + self.aimtargvelocity * latency;
+		// this extra line compensates for momentum
+		//v = v - self.aimselfvelocity * latency;
 		tracebox(self.aimtargorigin, targ.mins, targ.maxs, v, FALSE, targ);
 		aimdir = trace_endpos - self.origin - '0 0 16';
-		if (self.weapon == self.switchweapon && self.wstate == WS_ACTIVE)
+		saveenemy = self.enemy;
+		self.enemy = targ;
+		weaponaimtarget = trace_endpos;
+*/
+		/*
+		bprint("havocbot_doaim(");
+		s = etos(self.aimtarg);
+		bprint(s);
+		bprint(", ");
+		s = vtos(self.aimselforigin);
+		bprint(s);
+		bprint(", ");
+		s = vtos(self.aimselfvelocity);
+		bprint(s);
+		bprint(", ");
+		s = vtos(self.aimtargorigin);
+		bprint(s);
+		bprint(", ");
+		s = vtos(self.aimtargvelocity);
+		bprint(s);
+		bprint(")\nselforigin ");
+		s = vtos(selforigin);
+		bprint(s);
+		bprint(", targorigin ");
+		s = vtos(targorigin);
+		bprint(s);
+		bprint(", aimdir ");
+		s = vtos(aimdir);
+		bprint(s);
+		bprint(")\n");
+		*/
+/*
+		if (setweapon(self.weapon, WR_AIM))
 		{
-			saveenemy = self.enemy;
-			self.enemy = targ;
-			weaponaimtarget = trace_endpos;
+			if ((cvar("temp1") & 512) == 0)
+				self.button0 = 1;
+*/
 			/*
-			bprint("havocbot_doaim(");
-			s = etos(self.aimtarg);
-			bprint(s);
-			bprint(", ");
-			s = vtos(self.aimselforigin);
-			bprint(s);
-			bprint(", ");
-			s = vtos(self.aimselfvelocity);
-			bprint(s);
-			bprint(", ");
-			s = vtos(self.aimtargorigin);
-			bprint(s);
-			bprint(", ");
-			s = vtos(self.aimtargvelocity);
+			bprint("weaponaimdir ");
+			s = vtos(weaponaimdir);
 			bprint(s);
-			bprint(")\nselforigin ");
-			s = vtos(selforigin);
-			bprint(s);
-			bprint(", targorigin ");
-			s = vtos(targorigin);
-			bprint(s);
-			bprint(", aimdir ");
-			s = vtos(aimdir);
-			bprint(s);
-			bprint(")\n");
+			bprint("\n");
 			*/
-			if (setweapon(self.weapon, WR_AIM))
-			{
-				if ((cvar("temp1") & 512) == 0)
-					self.button0 = 1;
-				/*
-				bprint("weaponaimdir ");
-				s = vtos(weaponaimdir);
-				bprint(s);
-				bprint("\n");
-				*/
-				aimdir = weaponaimdir;
-			}
-			self.enemy = saveenemy;
+/*
+			aimdir = weaponaimdir;
 		}
+		self.enemy = saveenemy;
 	}
 
 	// LordHavoc: todo: deceleration aiming simulation
@@ -1301,6 +1302,7 @@
 	// compute model angles
 	self.angles = self.v_angle_y * '0 1 0';
 };
+*/
 
 .float  respawntime;
 .float nextgoalcheck;
@@ -1330,7 +1332,9 @@
 	havocbot_chooseweapon();
 	havocbot_aim();
 	lag_update();
-	havocbot_doaim();
+	//havocbot_doaim();
+	if (!self.aimtarg)
+		w_aimdir(self.goalcurrent.origin - self.origin, 0);
 	dodge = havocbot_dodge();
 	havocbot_movetogoal(dodge);
 	SV_PlayerPhysics();
Index: dpmod/qc/impulse_main.qc
diff -u dpmod/qc/impulse_main.qc:1.7 dpmod/qc/impulse_main.qc:1.8
--- dpmod/qc/impulse_main.qc:1.7	Sun Jun  8 03:56:31 2003
+++ dpmod/qc/impulse_main.qc	Sat Aug  9 12:20:28 2003
@@ -1,4 +1,24 @@
 
+/*
+// frikqcc field pointer test code
+var .float fieldpointertest;
+void() fieldpointertestfunc =
+{
+	fieldpointertest = ammo_shells;
+	self.fieldpointertest = 5;
+};
+*/
+
+/*
+// frikqcc field pointer field test code
+..float fieldpointertest;
+void() fieldpointertestfunc =
+{
+	self.fieldpointertest = ammo_shells;
+	self.(self.fieldpointertest) = 5;
+};
+*/
+
 // FRIK_FILE extension test code
 void () saveme =
 {
@@ -90,6 +110,7 @@
 	local string c;
 	args = tokenize(s);
 	c = argv(0);
+	// edit this to do what you want with the received commands
 	     if (c == "say") clientcommand(self, s);
 	else if (c == "say_team") clientcommand(self, s);
 	else if (c == "name") clientcommand(self, s);
@@ -107,6 +128,8 @@
 	else if (c == "noclip") clientcommand(self, s);
 	else if (c == "notarget") clientcommand(self, s);
 	else if (c == "give") clientcommand(self, s);
+	// please keep this fallback incase new engine commands are added
+	else clientcommand(self, s);
 }
 
 .float isadmin, adminnumber, admindigits, adminattempts;
Index: dpmod/qc/inventory.qc
diff -u dpmod/qc/inventory.qc:1.4 dpmod/qc/inventory.qc:1.5
--- dpmod/qc/inventory.qc:1.4	Sun Jul 27 03:01:18 2003
+++ dpmod/qc/inventory.qc	Sat Aug  9 12:20:28 2003
@@ -106,9 +106,6 @@
 	item.it_absorbitem = Item_GenericAbsorbItem;
 	item.noise1 = "weapons/lock4.wav";
 	item.noise2 = "weapons/lock4.wav";
-	item.mdl = item.model;
-	// invisible until ItemDrop is called
-	item.model = "";
 	return item;
 };
 
@@ -118,6 +115,8 @@
 
 	item = ItemClass_Register("shells");
 	setmodel(item, "progs/backpack.mdl");
+	item.mdl = item.model;
+	item.model = "";
 	setsize(item, '-16 -16 -24', '16 16 8');
 	item.count1 = AMMOMAX_SHELLS;
 	//item.bulkbase = 0;
@@ -125,6 +124,8 @@
 
 	item = ItemClass_Register("nails");
 	setmodel(item, "progs/backpack.mdl");
+	item.mdl = item.model;
+	item.model = "";
 	setsize(item, '-16 -16 -24', '16 16 8');
 	item.count1 = AMMOMAX_NAILS;
 	//item.bulkbase = 0;
@@ -132,6 +133,8 @@
 
 	item = ItemClass_Register("rockets");
 	setmodel(item, "progs/backpack.mdl");
+	item.mdl = item.model;
+	item.model = "";
 	setsize(item, '-16 -16 -24', '16 16 8');
 	item.count1 = AMMOMAX_ROCKETS;
 	//item.bulkbase = 0;
@@ -139,6 +142,8 @@
 
 	item = ItemClass_Register("cells");
 	setmodel(item, "progs/backpack.mdl");
+	item.mdl = item.model;
+	item.model = "";
 	setsize(item, '-16 -16 -24', '16 16 8');
 	item.count1 = AMMOMAX_CELLS;
 	//item.bulkbase = 0;
Index: dpmod/qc/item_backpacks.qc
diff -u dpmod/qc/item_backpacks.qc:1.3 dpmod/qc/item_backpacks.qc:1.4
--- dpmod/qc/item_backpacks.qc:1.3	Sat Jul 12 06:02:55 2003
+++ dpmod/qc/item_backpacks.qc	Sat Aug  9 12:20:28 2003
@@ -9,8 +9,8 @@
 void() BackpackFade =
 {
 	self.nextthink = time;
-//	self.alpha = 1 - (time - self.cnt) * 4;
-//	if (self.alpha < 0.01)
+	self.alpha = 1 - (time - self.cnt) * 4;
+	if (self.alpha < 0.01)
 	{
 		Inventory_DestroyByName(self, "", 99999);
 		remove(self);
@@ -43,143 +43,50 @@
 	oself = self;
 	acount = 0;
 	self.items = self.items - (self.items & other.items);
-	if (other.flags & FL_CLIENT)
-	{
-		sprint(other, "You get ");
-		if (self.items)
-		{
-			//d = IT_WEAPON1;if(self.items & d) {if(acount) sprint(other,", ");s=weaponname(d);sprint(other,s);acount=1;}
-			//d = IT_WEAPON2;if(self.items & d) {if(acount) sprint(other,", ");s=weaponname(d);sprint(other,s);acount=1;}
-			//d = IT_WEAPON3;if(self.items & d) {if(acount) sprint(other,", ");s=weaponname(d);sprint(other,s);acount=1;}
-			//d = IT_WEAPON4;if(self.items & d) {if(acount) sprint(other,", ");s=weaponname(d);sprint(other,s);acount=1;}
-			//d = IT_WEAPON5;if(self.items & d) {if(acount) sprint(other,", ");s=weaponname(d);sprint(other,s);acount=1;}
-			//d = IT_WEAPON6;if(self.items & d) {if(acount) sprint(other,", ");s=weaponname(d);sprint(other,s);acount=1;}
-			//d = IT_WEAPON7;if(self.items & d) {if(acount) sprint(other,", ");s=weaponname(d);sprint(other,s);acount=1;}
-			//d = IT_WEAPON8;if(self.items & d) {if(acount) sprint(other,", ");s=weaponname(d);sprint(other,s);acount=1;}
-			//d = IT_WEAPON9;if(self.items & d) {if(acount) sprint(other,", ");s=weaponname(d);sprint(other,s);acount=1;}
-			//d = IT_WEAPON10;if(self.items & d) {if(acount) sprint(other,", ");s=weaponname(d);sprint(other,s);acount=1;}
-			d = 0;
-			if (self.items & IT_WEAPON1) d = d + 1;
-			if (self.items & IT_WEAPON2) d = d + 1;
-			if (self.items & IT_WEAPON3) d = d + 1;
-			if (self.items & IT_WEAPON4) d = d + 1;
-			if (self.items & IT_WEAPON5) d = d + 1;
-			if (self.items & IT_WEAPON6) d = d + 1;
-			if (self.items & IT_WEAPON7) d = d + 1;
-			if (self.items & IT_WEAPON8) d = d + 1;
-			if (self.items & IT_WEAPON9) d = d + 1;
-			if (self.items & IT_WEAPON10) d = d + 1;
-			if (d >= 3)
-				sprint(other, "several weapons");
-			else if (d == 2)
-				sprint(other, "a couple weapons");
-			else
-				sprint(other, "a weapon");
-			acount=1;
-		}
-	}
 
 	// if the player was using his best weapon, change up to the new one if better
 	self = other;
 	best = W_BestWeapon(TRUE);
 	self = oself;
 
-	// add the ammo
-	//Inventory_AdjustQuantity(other, "shells", Inventory_Quantity(self, "shells"));
-	//Inventory_AdjustQuantity(other, "nails", Inventory_Quantity(self, "nails"));
-	//Inventory_AdjustQuantity(other, "rockets", Inventory_Quantity(self, "rockets"));
-	//Inventory_AdjustQuantity(other, "cells", Inventory_Quantity(self, "cells"));
-	if (self.super_damage_finished > time)
-	if (self.super_damage_finished > other.super_damage_finished)
-	{
-		other.super_time = 1;
-		other.super_damage_finished = self.super_damage_finished;
-		other.items = other.items | IT_QUAD;
-	}
-	if (self.invisible_finished > time)
-	if (self.invisible_finished > other.invisible_finished)
-	{
-		other.invisible_time = 1;
-		other.invisible_finished = self.invisible_finished;
-		other.items = other.items | IT_INVISIBILITY;
-	}
-	if (self.invincible_finished > time)
-	if (self.invincible_finished > other.invincible_finished)
-	{
-		other.invincible_time = 1;
-		other.invincible_finished = self.invincible_finished;
-		other.items = other.items | IT_INVULNERABILITY;
-	}
-
 	new = self.items;
 	old = other.items;
 	other.items = old | new;
 
-	if (other.flags & FL_CLIENT)
+	item = Inventory_GetNextItem(self, world);
+	while (item)
 	{
-		item = Inventory_GetNextItem(self, world);
-		while (item)
+		d = Inventory_AbsorbItem(other, item);
+		if (d)
 		{
-			d = Inventory_AbsorbItem(other, item);
-			if (d)
+			if (other.flags & FL_CLIENT)
 			{
 				s = ftos(d);
 				if (acount)
 					sprint(other, ", ");
+				else
+					sprint(other, "You get ");
 				acount = 1;
 				sprint (other, s);
 				sprint (other, " ");
 				sprint (other, item.netname);
-				if (item.count == 0)
-				{
-					Item_Destroy(item);
-					item = world;
-				}
 			}
-			item = Inventory_GetNextItem(self, item);
-		}
-		/*
-		if (Inventory_Quantity(self, "shells"))
-		{
-			if (acount)
-				sprint(other, ", ");
-			acount = 1;
-			s = ftos(Inventory_Quantity(self, "shells"));
-			sprint (other, s);
-			sprint (other, " shells");
-		}
-		if (Inventory_Quantity(self, "nails"))
-		{
-			if (acount)
-				sprint(other, ", ");
-			acount = 1;
-			s = ftos(Inventory_Quantity(self, "nails"));
-			sprint (other, s);
-			sprint (other, " rounds");
-		}
-		if (Inventory_Quantity(self, "rockets"))
-		{
-			if (acount)
-				sprint(other, ", ");
-			acount = 1;
-			s = ftos(Inventory_Quantity(self, "rockets"));
-			sprint (other, s);
-			sprint (other, " rockets");
-		}
-		if (Inventory_Quantity(self, "cells"))
-		{
-			if (acount)
-				sprint(other, ", ");
-			acount = 1;
-			s = ftos(Inventory_Quantity(self, "cells"));
-			sprint (other, s);
-			sprint (other, " cells");
+			if (item.count == 0)
+			{
+				Item_Destroy(item);
+				item = world;
+			}
 		}
-		*/
+		item = Inventory_GetNextItem(self, item);
+	}
+	if (other.flags & FL_CLIENT)
+	{
 		if (self.super_damage_finished > time)
 		{
 			if (acount)
 				sprint(other, ", ");
+			else
+				sprint(other, "You get ");
 			acount = 1;
 			sprint (other, "quad");
 		}
@@ -187,6 +94,8 @@
 		{
 			if (acount)
 				sprint(other, ", ");
+			else
+				sprint(other, "You get ");
 			acount = 1;
 			sprint (other, "ring");
 		}
@@ -194,13 +103,14 @@
 		{
 			if (acount)
 				sprint(other, ", ");
+			else
+				sprint(other, "You get ");
 			acount = 1;
 			sprint (other, "protection");
 		}
 
-		if (!acount)
-			sprint(other, "nothing you need");
-		sprint (other, "\n");
+		if (acount)
+			sprint (other, "\n");
 		stuffcmd(other, "bf\n");
 	}
 	// backpack touch sound
@@ -210,18 +120,12 @@
 	self = other;
 
 	// change to the weapon
-	old = W_BestWeapon(TRUE); // didn't want to add a new local...
-	if (old & new) // is the best weapon in the pack?
-		self.switchweapon = old; // yep, change to it.
+	best = W_BestWeapon(TRUE);
+	if (best & new) // is the best weapon in the pack?
+		self.switchweapon = best; // yep, change to it.
 
 	self = oself;
 	BackpackRemove();
-	/*
-	self.think = SUB_Remove;
-	self.nextthink = time + 0.1;
-	self.solid = SOLID_NOT;
-	self.touch = SUB_Null;
-	*/
 };
 
 // FIXME: bother to rate backpacks based on their contents?
@@ -237,17 +141,17 @@
 */
 void() DropBackpack =
 {
-	local   entity  item, head, killent;
-	local   float   c, t;
+	local entity item, head, killent;
+	local float c, t;
 
 	if (deathmatch == DM_FRAGFEST || deathmatch == DM_ELIM)
 		return;
 
-	if (deathmatch == DM_RPG)
-		Inventory_DropByName(self, "", 99999);
+	//if (deathmatch == DM_RPG)
+	//	Inventory_DropByName(self, "", 99999);
 
-	if (!(Inventory_Quantity(self, "shells") + Inventory_Quantity(self, "nails") + Inventory_Quantity(self, "rockets") + Inventory_Quantity(self, "cells")))
-	if (!(self.super_damage_finished || self.invisible_finished || self.invincible_finished))
+	if (!Inventory_GetNextItem(self, world))
+	//if (!(Inventory_Quantity(self, "shells") + Inventory_Quantity(self, "nails") + Inventory_Quantity(self, "rockets") + Inventory_Quantity(self, "cells")))
 	if (!(self.items & (IT_WEAPON3 | IT_WEAPON4 | IT_WEAPON5 | IT_WEAPON6 | IT_WEAPON7 | IT_WEAPON8 | IT_WEAPON9 | IT_WEAPON10)))
 		return; // nothing in it
 
@@ -273,32 +177,17 @@
 
 	item = spawn();
 	item.createdtime = time;
-	item.owner = item;
-	item.enemy = item;
+	//item.owner = item;
+	//item.enemy = item;
 	item.classname = "backpack";
-
-	item.items = self.items & (IT_WEAPON1 | IT_WEAPON2 | IT_WEAPON3 | IT_WEAPON4 | IT_WEAPON5 | IT_WEAPON6 | IT_WEAPON7 | IT_WEAPON8 | IT_WEAPON9 | IT_WEAPON10);
-	self.items = self.items - item.items;
-
-	item.super_damage_finished = self.super_damage_finished;
-	item.invisible_finished = self.invisible_finished;
-	item.invincible_finished = self.invincible_finished;
-	self.super_damage_finished = 0;
-	self.invisible_finished = 0;
-	self.invincible_finished = 0;
+	item.havocpickup = TRUE;
+	item.pickupevalfunc = item_backpack_pickupeval;
 
 	item.velocity_x = crandom() * 100;
 	item.velocity_y = crandom() * 100;
 	item.velocity_z = 300;
-
-	if (item.super_damage_finished)
-		item.effects = item.effects | EF_BLUE;
-	if (item.invisible_finished)
-		item.alpha = 0.5;
-	if (item.invincible_finished)
-		item.effects = item.effects | EF_RED;
 
-	item.colormap = self.colormap;
+	item.colormap = self.colormap; // color backpack like player
 	item.flags = FL_ITEM;
 	item.solid = SOLID_TRIGGER;
 	item.movetype = MOVETYPE_TOSS;
@@ -312,29 +201,9 @@
 	else
 		item.nextthink = time + 120;    // remove after 2 minutes
 	item.think = BackpackRemove;
-
-	/*
-	item.havocrating = 0;
-//	if (item.items & IT_WEAPON1) item.havocrating = item.havocrating + 60;
-//	if (item.items & IT_WEAPON2) item.havocrating = item.havocrating + 120;
-	if (item.items & IT_WEAPON3) item.havocrating = item.havocrating + 200;
-	if (item.items & IT_WEAPON4) item.havocrating = item.havocrating + 150;
-	if (item.items & IT_WEAPON5) item.havocrating = item.havocrating + 300;
-	if (item.items & IT_WEAPON6) item.havocrating = item.havocrating + 200;
-	if (item.items & IT_WEAPON7) item.havocrating = item.havocrating + 240;
-	if (item.items & IT_WEAPON8) item.havocrating = item.havocrating + 300;
-	if (item.items & IT_WEAPON9) item.havocrating = item.havocrating + 0;
-	if (item.items & IT_WEAPON10) item.havocrating = item.havocrating + 300;
-	item.havocrating = item.havocrating + Inventory_Quantity(item, "shells") * 60;
-	item.havocrating = item.havocrating + Inventory_Quantity(item, "nails") * 15;
-	item.havocrating = item.havocrating + Inventory_Quantity(item, "rockets") * 120;
-	item.havocrating = item.havocrating + Inventory_Quantity(item, "cells") * 30;
-	if (item.super_damage_finished > time) item.havocrating = item.havocrating + 10 * (item.super_damage_finished - time);
-	if (item.invisible_finished    > time) item.havocrating = item.havocrating + 10 * (item.invisible_finished - time);
-	if (item.invincible_finished   > time) item.havocrating = item.havocrating + 20 * (item.invincible_finished - time);
-	*/
-	item.havocpickup = TRUE;
-	item.pickupevalfunc = item_backpack_pickupeval;
 
+	// this transfers legacy items
+	item.items = self.items & (IT_WEAPON1 | IT_WEAPON2 | IT_WEAPON3 | IT_WEAPON4 | IT_WEAPON5 | IT_WEAPON6 | IT_WEAPON7 | IT_WEAPON8 | IT_WEAPON9 | IT_WEAPON10);
+	// this transfers all inventory items (ammo, etc)
 	Inventory_AbsorbInventory(item, self);
 };
Index: dpmod/qc/m_enforcer.qc
diff -u dpmod/qc/m_enforcer.qc:1.6 dpmod/qc/m_enforcer.qc:1.7
--- dpmod/qc/m_enforcer.qc:1.6	Wed Jul 16 08:16:45 2003
+++ dpmod/qc/m_enforcer.qc	Sat Aug  9 12:20:28 2003
@@ -405,7 +405,6 @@
 	{
 		self.th_missile = enf_missile_rocket;
 		Inventory_SetQuantity(self, "rockets", AMMO_ENFORCER_ROCKETS);
-		//self.items = IT_WEAPON7;
 		if (!self.deathtype) // map makers can override this
 			self.deathtype = " was blasted by an enforcer";
 	}
@@ -413,7 +412,6 @@
 	{
 		self.th_missile = enf_missile_plasma;
 		Inventory_SetQuantity(self, "cells", AMMO_ENFORCER_PLASMACELLS);
-		//self.items = IT_WEAPON8;
 		if (!self.deathtype) // map makers can override this
 			self.deathtype = " was scorched by an enforcer";
 	}
Index: dpmod/qc/m_ogre.qc
diff -u dpmod/qc/m_ogre.qc:1.6 dpmod/qc/m_ogre.qc:1.7
--- dpmod/qc/m_ogre.qc:1.6	Wed Jul 16 08:16:45 2003
+++ dpmod/qc/m_ogre.qc	Sat Aug  9 12:20:28 2003
@@ -466,7 +466,6 @@
 		self.deathtype = " was destroyed by an ogre";
 	Inventory_SetQuantity(self, "rockets", AMMO_OGRE_GRENADES);
 	//Inventory_SetQuantity(self, "nails", 0);
-	//self.items = IT_WEAPON6;
 
 	self.shoulddodge = TRUE;
 	self.dangerrating = 150;
Index: dpmod/qc/m_soldier.qc
diff -u dpmod/qc/m_soldier.qc:1.7 dpmod/qc/m_soldier.qc:1.8
--- dpmod/qc/m_soldier.qc:1.7	Wed Jul 16 08:16:45 2003
+++ dpmod/qc/m_soldier.qc	Sat Aug  9 12:20:28 2003
@@ -499,7 +499,6 @@
 	r = random();
 	if (r < 0.30)
 	{
-		//self.items = IT_WEAPON4;
 		self.th_missile = army_missile_nail;
 		Inventory_SetQuantity(self, "nails", 15);
 		if (!self.deathtype) // map makers can override this
@@ -507,7 +506,6 @@
 	}
 	else if (r < 0.70)
 	{
-		//self.items = IT_WEAPON2;
 		self.th_missile = army_missile_shotgun;
 		Inventory_SetQuantity(self, "shells", 5);
 		if (!self.deathtype) // map makers can override this
Index: dpmod/qc/mode_management.qc
diff -u dpmod/qc/mode_management.qc:1.5 dpmod/qc/mode_management.qc:1.6
--- dpmod/qc/mode_management.qc:1.5	Wed Jul 16 08:16:45 2003
+++ dpmod/qc/mode_management.qc	Sat Aug  9 12:20:28 2003
@@ -288,8 +288,7 @@
 		nextcvarupdate = time + 1;
 		mode_updatecvars();
 	}
-	if (deathmatch == 7)
-		deathmatch7update();
+	deathmatch7update();
 };
 
 // true if items should respawn
@@ -307,7 +306,7 @@
 
 	// don't spawn any monsters until 15 seconds
 	spawnchecktime = 15;
-	if (deathmatch == 7)
+	if (deathmatch == 7 || cvar("scratch1") >= 1 || cvar("spawnmonsters") >= 1)
 		precachemonsters();
 };
 
@@ -466,6 +465,7 @@
 	else if (r < 12) spawnmonster( 4,  8, "monster_zombie"     , monster_zombie     , '-16 -16 -24', '16 16 32');
 };
 
+float monstersprecached;
 void() precachemonster_army;
 void() precachemonster_demon1;
 void() precachemonster_dog;
@@ -493,36 +493,46 @@
 	precachemonster_tarbaby();
 	precachemonster_wizard();
 	precachemonster_zombie();
+	monstersprecached = TRUE;
 };
 
 void() deathmatch7update =
 {
 	local entity e;
-	local float f, monster_count;
-	if (time > spawnchecktime)
+	local float f, monster_count, monsters;
+	if (time < spawnchecktime)
+		return;
+	if (!monstersprecached)
+		return;
+	spawnchecktime = time + 0.2;
+	monsters = 0;
+	if (deathmatch == 7)
+		monsters = 50;
+	f = cvar("scratch1");
+	if (f >= 1)
+		monsters = f;
+	f = cvar("spawnmonsters");
+	if (f >= 1)
+		monsters = f;
+	if (monsters < 1)
+		return;
+	monster_count = 0;
+	e = findchainfloat(iscreature, TRUE);
+	while (e)
+	{
+		if (e.flags & FL_MONSTER)
+			monster_count = monster_count + 1;
+		e = e.chain;
+	}
+	if (monster_count >= monsters)
+		return;
+	e = findchain(classname, "spawningmonster");
+	while (e)
 	{
-		spawnchecktime = time + 0.2;
-		monster_count = 0;
-		e = findchainfloat(iscreature, TRUE);
-		while (e)
-		{
-			if (e.flags & FL_MONSTER)
-				monster_count = monster_count + 1;
-			e = e.chain;
-		}
-		f = cvar("scratch1");
-		if (f < 1)
-			f = 50;
-		if (monster_count < f)
-		{
-			e = findchain(classname, "spawningmonster");
-			while (e)
-			{
-				monster_count = monster_count + 1;
-				e = e.chain;
-			}
-			if (monster_count < f)
-				spawnmonsters();
-		}
+		monster_count = monster_count + 1;
+		e = e.chain;
 	}
+	if (monster_count >= monsters)
+		return;
+	spawnmonsters();
 }
Index: dpmod/qc/plasma.qc
diff -u dpmod/qc/plasma.qc:1.4 dpmod/qc/plasma.qc:1.5
--- dpmod/qc/plasma.qc:1.4	Sun Jun  8 04:02:48 2003
+++ dpmod/qc/plasma.qc	Sat Aug  9 12:20:28 2003
@@ -28,14 +28,6 @@
 		if (self.frame >= 10)
 			self.frame = 0;
 	}
-	/*
-	if (self.owner.classname == "player" && self.owner.weapon == IT_WEAPON8 && self.owner.viewzoom < 0.5)
-	{
-		makevectors(self.owner.v_angle);
-		traceline(self.owner.origin + '0 0 16', self.owner.origin + '0 0 16' + v_forward * 65536, FALSE, self.owner);
-		self.velocity = self.velocity + (normalize(trace_endpos - self.origin) * 10000 - self.velocity) * frametime * 5;
-	}
-	*/
 	if (time > self.count)
 		remove(self);
 };
Index: dpmod/qc/playermovement.qc
diff -u dpmod/qc/playermovement.qc:1.4 dpmod/qc/playermovement.qc:1.5
--- dpmod/qc/playermovement.qc:1.4	Sun Jun  8 03:54:16 2003
+++ dpmod/qc/playermovement.qc	Sat Aug  9 12:20:28 2003
@@ -113,9 +113,9 @@
 		//wishvel = v_forward * self.movement_x + v_right * self.movement_y + v_up * self.movement_z;
 		wishvel = v_forward * self.movement_x + v_right * self.movement_y + '0 0 1' * self.movement_z;
 		if (self.gravity)
-			self.velocity_z += self.gravity * sv_gravity * frametime;
+			self.velocity_z = self.velocity_z + self.gravity * sv_gravity * frametime;
 		else
-			self.velocity_z += sv_gravity * frametime;
+			self.velocity_z = self.velocity_z + sv_gravity * frametime;
 		if (self.ladder_entity.classname == "func_water")
 		{
 			f = vlen(wishvel);
Index: dpmod/qc/rocket.qc
diff -u dpmod/qc/rocket.qc:1.5 dpmod/qc/rocket.qc:1.6
--- dpmod/qc/rocket.qc:1.5	Fri Feb 28 00:13:31 2003
+++ dpmod/qc/rocket.qc	Sat Aug  9 12:20:28 2003
@@ -1,35 +1,10 @@
 
 void(vector org, vector vel, entity own, float damage, float damage2, float type, float lifetime, string dethtype, void(entity t, entity a, string m, float dtyp) obitfunc) LaunchGrenade;
 
-/*
-void(vector org, entity attacker, float damg, float radius, string dt, vector explosioncolor, float quad, void(entity t, entity a, string m, float dtyp) obitfunc) SmallExplosion =
-{
-	local vector v;
-	local entity e;
-	e = spawn();
-	e.owner = attacker;
-	setorigin(e, org);
-	findbetterlocation2(e);
-
-	te_plasmaburn(org);
-	T_RadiusDamage(e, attacker, damg, radius, world, dt, DT_EXPLOSION, obitfunc);
-	remove(e);
-
-	v = findbetterlocation3(org); // move animation away from walls
-	effect(v, "progs/s_explod.spr", 0, 6, 10);
-	//effect(v, "progs/dpexplosion.spr32", 0, 20, 40);
-};
-*/
-
 void() MissileExplode =
 {
 	fightdone = time + 1; // delay stuff until fighting is over
-	/*
-	if (self.owner.weapon == IT_WEAPON4)
-		SmallExplosion(self.origin, self.owner, self.dmg, self.dmg2, self.deathtype, '0 0 0', self.effects & EF_BLUE, self.obitfunc1);
-	else
-	*/
-		Explosion(self.origin, self.owner, self.dmg, self.dmg2, self.deathtype, '0 0 0', self.effects & EF_BLUE, self.obitfunc1);
+	Explosion(self.origin, self.owner, self.dmg, self.dmg2, self.deathtype, '0 0 0', self.effects & EF_BLUE, self.obitfunc1);
 	remove(self);
 };
 
@@ -61,23 +36,7 @@
 	local vector v;
 	self.nextthink = time;
 	fightdone = time + 1; // delay stuff until fighting is over
-	/*
-	//if (self.owner.weapon == IT_WEAPON7)
-	if (self.owner.classname == "player")
-	{
-		makevectors(self.owner.v_angle);
-		traceline(self.owner.origin + '0 0 16', self.owner.origin + '0 0 16' + v_forward * 65536, FALSE, self.owner);
-		v = normalize(trace_endpos - self.origin);
-		//if (normalize(self.velocity) * v < 0.4 || (self.owner.weapon != IT_WEAPON7 && self.owner.weapon != IT_WEAPON4))
-		if (self.owner.weapon != IT_WEAPON7 && self.owner.weapon != IT_WEAPON4)
-			v = normalize(self.velocity);
-		if (self.owner.weapon == IT_WEAPON4)
-			p = 1000;
-		else
-			p = 5000;
-		self.velocity = self.velocity + (v * p - self.velocity) * frametime;
-	}
-	else*/ if ((self.velocity * self.dest) < self.speed)
+	if ((self.velocity * self.dest) < self.speed)
 	{
 		self.velocity = self.velocity + self.dest * self.speed * 2 * frametime;
 		p = self.velocity * self.dest;
@@ -89,7 +48,7 @@
 	}
 	self.angles = vectoangles(self.velocity);
 	p = pointcontents(self.origin);
-	if (/*(self.owner.button3 && self.owner.weapon == IT_WEAPON7) || */time > self.cnt || p == CONTENT_SOLID || p == CONTENT_LAVA)
+	if (time > self.cnt || p == CONTENT_SOLID || p == CONTENT_LAVA)
 	{
 		MissileExplode();
 		return;
Index: dpmod/qc/t_damage.qc
diff -u dpmod/qc/t_damage.qc:1.7 dpmod/qc/t_damage.qc:1.8
--- dpmod/qc/t_damage.qc:1.7	Fri Jul 18 15:08:39 2003
+++ dpmod/qc/t_damage.qc	Sat Aug  9 12:20:28 2003
@@ -192,32 +192,21 @@
 		if (targ.damagemodifier)
 			ratio = ratio * targ.damagemodifier(targ, healthdamage, damage, damgtype, dethtype);
 
-		if (targ.flags & FL_MONSTER) ratio = ratio * monsterresistancescale;
+		if (attacker.flags & FL_MONSTER) ratio = ratio * monsterdamagescale;
+		if (attacker.classname == "player") ratio = ratio * playerdamagescale;
+
 		if (targ.resist_bullet   ) if (damgtype & DTF_RESIST_BULLET   ) ratio = ratio * targ.resist_bullet;
 		if (targ.resist_explosive) if (damgtype & DTF_RESIST_EXPLOSIVE) ratio = ratio * targ.resist_explosive;
 		if (targ.resist_energy   ) if (damgtype & DTF_RESIST_ENERGY   ) ratio = ratio * targ.resist_energy;
 		if (targ.resist_fire     ) if (damgtype & DTF_RESIST_FIRE     ) ratio = ratio * targ.resist_fire;
-
-		// only scales damage done by players
-		if (attacker.classname == "player")
+		if (targ.flags & FL_MONSTER) ratio = ratio * monsterresistancescale;
+		if (targ.items & IT_INVULNERABILITY)
 		{
-			ratio = ratio * playerdamagescale;
-			if (targ.classname == "player")
-			{
-				if (targ.items & IT_INVULNERABILITY)
-				{
-					if (targ != attacker)
-						ratio = ratio * 0.33;
-					else
-						ratio = 0;
-				}
-			}
-			// only scales player damage to monsters
-			else if (targ.flags & FL_MONSTER)
-				ratio = ratio * monsterdamagescale;
+			if (attacker.classname == "player" && targ.classname == "player" && targ != attacker)
+				ratio = ratio * 0.33;
+			else
+				ratio = 0;
 		}
-		else if (targ.items & IT_INVULNERABILITY)
-			ratio = 0;
 
 //		// check for quad damage powerup on the attacker
 //		if (attacker.items & IT_QUAD)
Index: dpmod/qc/w_common.qc
diff -u dpmod/qc/w_common.qc:1.3 dpmod/qc/w_common.qc:1.4
--- dpmod/qc/w_common.qc:1.3	Sun Jun  8 04:02:48 2003
+++ dpmod/qc/w_common.qc	Sat Aug  9 12:20:28 2003
@@ -37,16 +37,18 @@
 };
 */
 
-vector(vector srcvec, vector dstvec) w_directaim =
+vector(vector srcvec, vector dstvec, vector dstvel, float shotspeed) w_directaim =
 {
+	dstvec = dstvec + dstvel * (vlen(dstvec - srcvec) / shotspeed);
 	traceline(srcvec, dstvec, FALSE, self);
 	if (trace_fraction < 1 && trace_ent != self.enemy)
 		return '0 0 0';
 	return dstvec - srcvec;
 };
 
-vector(vector srcvec, vector dstvec) w_rocketaim =
+vector(vector srcvec, vector dstvec, vector dstvel, float shotspeed) w_rocketaim =
 {
+	dstvec = dstvec + dstvel * (vlen(dstvec - srcvec) / shotspeed);
 	if (vlen(dstvec - srcvec) < 150)
 		return '0 0 0';
 	traceline(srcvec, dstvec, FALSE, self);
@@ -55,9 +57,10 @@
 	return dstvec - srcvec;
 };
 
-vector(vector srcvec, vector dstvec) w_grenadeaim =
+vector(vector srcvec, vector dstvec, vector dstvel, float shotspeed) w_grenadeaim =
 {
 	local   vector  v;
+	dstvec = dstvec + dstvel * (vlen(dstvec - srcvec) / shotspeed);
 	if (vlen(dstvec - srcvec) < 150)
 		return '0 0 0';
 	traceline(srcvec, dstvec, FALSE, self);
@@ -68,6 +71,108 @@
 	return findtrajectory_velocity;
 };
 
+float(entity e) w_shouldattack =
+{
+	if (!e.takedamage)
+		return FALSE;
+	if (e.deadflag)
+		return FALSE;
+	if (e.classname == "player")
+	if (coop)
+		return FALSE;
+	if (e.team == self.team)
+	if (self.team != 0)
+	if (teamplay != 0)
+		return FALSE;
+	if (e == self)
+		return FALSE;
+	return TRUE;
+};
+
+.float painintensity;
+.entity aimtarg;
+.float aimlatency;
+.vector aimtargorigin;
+.vector aimtargvelocity;
+.float mousesticktime;
+float(vector v, float maxfiredeviation) w_aimdir =
+{
+	local float dist;
+	local vector desiredang, diffang;
+	// get the desired angles to aim at
+	desiredang = vectoangles(v);
+	desiredang_z = self.v_angle_z;
+
+	// pain throws off aim
+	if (self.painintensity)
+	{
+		// shake from pain
+		desiredang = desiredang + randomvec() * self.painintensity * 0.2;
+	}
+
+	// calculate turn angles
+	diffang = desiredang - self.v_angle;
+	while (diffang_y < -180)
+		diffang_y = diffang_y + 360;
+	while (diffang_y >  180)
+		diffang_y = diffang_y - 360;
+
+	// jitter tracking
+	dist = vlen(diffang);
+	diffang = randomvec() * (dist * 0.15 * (3.5 - skill));
+
+	// simulate slight 'stickyness' of mouse on small moves
+	if (vlen(diffang) < 0.1)
+	{
+		if (time < self.mousesticktime)
+			return vlen(diffang) < maxfiredeviation;
+		else if (random() < 0.5)
+		{
+			self.mousesticktime = time + 0.2;
+			return vlen(diffang) < maxfiredeviation;
+		}
+	}
+
+	// turn
+	self.v_angle = self.v_angle + diffang * (5 * frametime);
+
+	// calculate turn angles again
+	diffang = desiredang - self.v_angle;
+	while (diffang_y < -180)
+		diffang_y = diffang_y + 360;
+	while (diffang_y >  180)
+		diffang_y = diffang_y - 360;
+
+	// decide whether to fire this time
+	return vlen(diffang) < maxfiredeviation;
+};
+
+vector(vector targorigin, vector targvelocity, float shotspeed, float shotdelay) w_shotlead =
+{
+	return targorigin + targvelocity * (shotdelay + vlen(targorigin - shotorg) / shotspeed);
+};
+
+float(float shotspeed, float maxshottime) w_directattackaim =
+{
+	local vector v;
+	v = w_shotlead(self.aimtargorigin, self.aimtargvelocity, shotspeed, self.aimlatency);
+	if (vlen(v - shotorg) < maxshottime * shotspeed)
+		return FALSE;
+	traceline(shotorg, v, FALSE, self);
+	if (trace_fraction == 1)
+		return w_aimdir(v - shotorg, 0.1);
+	if (w_shouldattack(trace_ent))
+		return w_aimdir(v - shotorg, 0.1);
+	return FALSE;
+};
+
+float(float shotspeed, float maxshottime) w_grenadeattackaim =
+{
+	if (!findtrajectorywithleading(shotorg, '0 0 0', '0 0 0', self.aimtarg, shotspeed, maxshottime, 0, self))
+		return FALSE;
+	return w_aimdir(findtrajectory_velocity, 0.1);
+};
+
 void() W_Hostile =
 {
 	// wake up monsters
@@ -114,7 +219,7 @@
 vector weaponaimdir;
 vector weaponaimtarget;
 
-float(float w, float hasammo, float request, void() setupfunc, void() activefunc, void() raisefunc, vector(vector srcvec, vector dstvec) aimfunc, float() ratingfunc, string wname) weapongeneric =
+float(float w, float hasammo, float request, void() setupfunc, void() activefunc, void() raisefunc, vector(vector srcvec, vector dstvec, vector dstvel, float shotspeed) aimfunc, float() ratingfunc, string wname) weapongeneric =
 {
 	if (request == WR_SETUP)
 	{
@@ -127,6 +232,16 @@
 			return FALSE;
 		return hasammo;
 	}
+	if (request == WR_SWITCH)
+	{
+		if (self.items & w)
+		if (hasammo)
+		{
+			self.switchweapon = w;
+			return TRUE;
+		}
+		return FALSE;
+	}
 	if (request == WR_RAISE)
 	{
 		self.weapon = self.switchweapon;
@@ -144,9 +259,10 @@
 		activefunc();
 		return TRUE;
 	}
+	// FIXME: get rid of WR_AIM
 	if (request == WR_AIM)
 	{
-		weaponaimdir = aimfunc(self.origin + '0 0 16', weaponaimtarget);
+		weaponaimdir = aimfunc(self.origin + '0 0 16', weaponaimtarget, '0 0 0', 10000);
 		return weaponaimdir != '0 0 0';
 	}
 	if (request == WR_NAME)
Index: dpmod/qc/w_dbshotgun.qc
diff -u dpmod/qc/w_dbshotgun.qc:1.13 dpmod/qc/w_dbshotgun.qc:1.14
--- dpmod/qc/w_dbshotgun.qc:1.13	Sun Jul 27 03:01:19 2003
+++ dpmod/qc/w_dbshotgun.qc	Sat Aug  9 12:20:28 2003
@@ -111,6 +111,9 @@
 	if (widle(w_dbshotgundrop1))
 		return;
 
+	if (self.aimtarg) // bot target
+		self.button0 = w_directattackaim(6000, 1);
+
 	if (time > self.attack_finished)
 	{
 		if (self.shotgunshells)
@@ -183,6 +186,17 @@
 	precache_sound("weapons/bsgnoammo.wav");
 	precache_sound("weapons/bsgload.wav");
 };
+
+/*
+vector(vector srcvec, vector dstvec, vector dstvel) w_dbshotgunaim =
+{
+	dstvec = dstvec + dstvel * (vlen(dstvec - srcvec) / shotspeed);
+	traceline(srcvec, dstvec, FALSE, self);
+	if (trace_fraction < 1 && trace_ent != self.enemy)
+		return '0 0 0';
+	return dstvec - srcvec;
+};
+*/
 
 float() w_dbshotgunrating = {return genericweaponrating(0, 250, 175);};
 void() w_dbshotgunsetup = {wset(IT_WEAPON3, IT_SHELLS, Inventory_Quantity(self, "shells"), VWEP_SUPER_SHOTGUN, "progs/v_dpshot2.mdl");};
Index: dpmod/qc/w_defs.qc
diff -u dpmod/qc/w_defs.qc:1.3 dpmod/qc/w_defs.qc:1.4
--- dpmod/qc/w_defs.qc:1.3	Sun Jun  8 04:02:48 2003
+++ dpmod/qc/w_defs.qc	Sat Aug  9 12:20:28 2003
@@ -51,8 +51,14 @@
 float WR_AIM = 7; // returns direction to aim the weapon (for bots)
 float WR_NAME = 8; // sets weaponstring to the name of the weapon
 float WR_WEAPONRATING = 9; // returns rating given weaponrange, returns -1 if the weapon is not available
+float WR_SWITCH = 10; // true if it can be selected (has ammo), and also sets self.switchweapon if so
 // FIXME: kill/death/suicide stat requests of some kind
 
 float WS_ACTIVE = 1; // weapon is selected
 float WS_RAISE = 2; // weapon is rising (changes to ACTIVE when done)
 float WS_DROP = 3; // weapon is falling (stays DROP until reselected)
+
+// used by bot ai in some weapons to decide if it should use altfire
+.float altfiretimeout;
+.float altfirechecktimeout;
+
Index: dpmod/qc/w_grenade.qc
diff -u dpmod/qc/w_grenade.qc:1.11 dpmod/qc/w_grenade.qc:1.12
--- dpmod/qc/w_grenade.qc:1.11	Wed Jul 16 08:16:45 2003
+++ dpmod/qc/w_grenade.qc	Sat Aug  9 12:20:28 2003
@@ -105,6 +105,9 @@
 	if (widle(w_grenadedrop1))
 		return;
 
+	if (self.aimtarg) // bot target
+		self.button0 = w_grenadeattackaim(1000, 2);
+
 	if (time > self.detonatetimeout)
 	if (time > self.attack_finished)
 	{
Index: dpmod/qc/w_info.qc
diff -u dpmod/qc/w_info.qc:1.4 dpmod/qc/w_info.qc:1.5
--- dpmod/qc/w_info.qc:1.4	Sat Jul 12 06:02:55 2003
+++ dpmod/qc/w_info.qc	Sat Aug  9 12:20:28 2003
@@ -125,47 +125,6 @@
 };
 
 /*
-float(float w) RankForWeapon =
-{
-	if (w == IT_WEAPON10) return 1;
-	if (w == IT_WEAPON8) return 2;
-	if (w == IT_WEAPON7) return 3;
-	if (w == IT_WEAPON6) return 4;
-	if (w == IT_WEAPON5) return 5;
-	if (w == IT_WEAPON4) return 6;
-	if (w == IT_WEAPON3) return 7;
-	if (w == IT_WEAPON2) return 8;
-	if (w == IT_WEAPON9) return 9;
-	if (w == IT_WEAPON1) return 10;
-	// this should never happen, as it catches all valid weapons in the code above
-	return 100;
-};
-*/
-
-/*
-=============
-Deathmatch_Weapon
-
-Deathmatch weapon change rules for picking up a weapon
-
-=============
-*/
-/*
-void(float old, float new) Deathmatch_Weapon =
-{
-	local float or, nr;
-
-	if (self.health < 1)
-		return;
-	// change self.weapon if desired
-	or = RankForWeapon (self.weapon);
-	nr = RankForWeapon (new);
-	if (nr < or)
-		self.switchweapon = new;
-};
-*/
-
-/*
 ============
 W_ChangeWeapon
 
@@ -178,35 +137,17 @@
 		return;
 	if (self.impulse >= 200)
 		self.impulse = self.impulse - 200;
-	if (self.impulse == 1) {fl = IT_WEAPON1;}
-	if (self.impulse == 2) {fl = IT_WEAPON2;}
-	if (self.impulse == 3) {fl = IT_WEAPON3;}
-	if (self.impulse == 4) {fl = IT_WEAPON4;}
-	if (self.impulse == 5) {fl = IT_WEAPON5;}
-	if (self.impulse == 6) {fl = IT_WEAPON6;}
-	if (self.impulse == 7) {fl = IT_WEAPON7;}
-	if (self.impulse == 8) {fl = IT_WEAPON8;}
-	if (self.impulse == 9) {fl = IT_WEAPON9;}
-	if (self.impulse == 10) {fl = IT_WEAPON10;}
+	if (self.impulse == 1) {setweapon(IT_WEAPON1, WR_SWITCH);}
+	if (self.impulse == 2) {setweapon(IT_WEAPON2, WR_SWITCH);}
+	if (self.impulse == 3) {setweapon(IT_WEAPON3, WR_SWITCH);}
+	if (self.impulse == 4) {setweapon(IT_WEAPON4, WR_SWITCH);}
+	if (self.impulse == 5) {setweapon(IT_WEAPON5, WR_SWITCH);}
+	if (self.impulse == 6) {setweapon(IT_WEAPON6, WR_SWITCH);}
+	if (self.impulse == 7) {setweapon(IT_WEAPON7, WR_SWITCH);}
+	if (self.impulse == 8) {setweapon(IT_WEAPON8, WR_SWITCH);}
+	if (self.impulse == 9) {setweapon(IT_WEAPON9, WR_SWITCH);}
+	if (self.impulse == 10) {setweapon(IT_WEAPON10, WR_SWITCH);}
 	self.impulse = 0;
-	/*
-	if (!(self.items & fl))
-	{
-		// don't have the weapon or the ammo
-		if (self.flags & FL_CLIENT)
-			sprint(self, "That weapon does not appear to be in your posession\n");
-		return;
-	}
-	if (!setweapon(fl, TRUE, FALSE))
-	{
-		// don't have the ammo
-		if (self.flags & FL_CLIENT)
-			sprint (self, "Insufficient ammunition for that weapon\n");
-		return;
-	}
-	*/
-	if (setweapon(fl, WR_SELECTABLE))
-		self.switchweapon = fl;
 };
 
 /*
@@ -221,10 +162,10 @@
 	if (self.health < 1)
 		return;
 
-	Inventory_SetQuantity(self, "shells", 99999);
-	Inventory_SetQuantity(self, "nails", 99999);
-	Inventory_SetQuantity(self, "rockets", 99999);
-	Inventory_SetQuantity(self, "cells", 99999);
+	Inventory_SetQuantity(self, "shells", AMMOMAX_SHELLS);
+	Inventory_SetQuantity(self, "nails", AMMOMAX_NAILS);
+	Inventory_SetQuantity(self, "rockets", AMMOMAX_ROCKETS);
+	Inventory_SetQuantity(self, "cells", AMMOMAX_SHELLS);
 	self.items = self.items
 	 | IT_WEAPON1
 	 | IT_WEAPON2
Index: dpmod/qc/w_lightning.qc
diff -u dpmod/qc/w_lightning.qc:1.4 dpmod/qc/w_lightning.qc:1.5
--- dpmod/qc/w_lightning.qc:1.4	Wed Jul 16 08:16:45 2003
+++ dpmod/qc/w_lightning.qc	Sat Aug  9 12:20:28 2003
@@ -142,6 +142,9 @@
 	if (widle(w_lightningdrop1))
 		return;
 
+	if (self.aimtarg) // bot target
+		self.button0 = w_directattackaim(6000, 0.1);
+
 	if (self.button0)
 	{
 		if (Inventory_Quantity(self, "cells") > 0)
Index: dpmod/qc/w_nailgun.qc
diff -u dpmod/qc/w_nailgun.qc:1.10 dpmod/qc/w_nailgun.qc:1.11
--- dpmod/qc/w_nailgun.qc:1.10	Wed Jul 16 08:16:45 2003
+++ dpmod/qc/w_nailgun.qc	Sat Aug  9 12:20:28 2003
@@ -87,7 +87,6 @@
 	LaunchMine(shotorg, shotdir * 1000 + v_up * 200, self, 200, 70, 20, 10, MINE_LASERTRIP, 60, "LASERTRIPMINE", Obituary_NailgunMine);
 };
 
-
 void() w_nailgundrop1;
 void() w_nailgundrop2;
 void() w_nailgunraise1;
@@ -96,6 +95,22 @@
 {
 	if (widle(w_nailgundrop1))
 		return;
+
+	if (self.aimtarg) // bot target
+	{
+		if (time > self.altfirechecktimeout)
+		{
+			self.altfirechecktimeout = time + 0.1 + random() * 0.2;
+			if (time > self.altfiretimeout)
+			if (vlen(self.aimtarg.origin - self.origin) < 600)
+			if (random() < 0.2)
+				self.altfiretimeout = time + 0.5 + random() * 0.5;
+		}
+		if (Inventory_Quantity(self, "rockets") && time < self.altfiretimeout)
+			self.button3 = w_grenadeattackaim(1000, 1);
+		else
+			self.button0 = w_directattackaim(12000, 2);
+	}
 
 	if (self.button0)
 	{
Index: dpmod/qc/w_pistol.qc
diff -u dpmod/qc/w_pistol.qc:1.9 dpmod/qc/w_pistol.qc:1.10
--- dpmod/qc/w_pistol.qc:1.9	Wed Jul 16 08:16:45 2003
+++ dpmod/qc/w_pistol.qc	Sat Aug  9 12:20:28 2003
@@ -33,6 +33,9 @@
 	if (widle(w_pistoldrop1))
 		return;
 
+	if (self.aimtarg) // bot target
+		self.button0 = w_directattackaim(12000, 2);
+
 	if (self.button0)
 	if (W_ShotsToFire(0.4))
 		W_PistolFireCode();
Index: dpmod/qc/w_plasmarifle.qc
diff -u dpmod/qc/w_plasmarifle.qc:1.12 dpmod/qc/w_plasmarifle.qc:1.13
--- dpmod/qc/w_plasmarifle.qc:1.12	Wed Jul 16 08:16:45 2003
+++ dpmod/qc/w_plasmarifle.qc	Sat Aug  9 12:20:28 2003
@@ -80,6 +80,22 @@
 void() w_plasmarifleraise2;
 void() w_plasmarifle =
 {
+	if (self.aimtarg) // bot target
+	{
+		if (time > self.altfirechecktimeout)
+		{
+			self.altfirechecktimeout = time + 0.1 + random() * 0.2;
+			if (time > self.altfiretimeout)
+			if (random() < 0.2)
+				self.altfiretimeout = time + 0.5 + random() * 0.5;
+		}
+		if (time < self.altfiretimeout)
+			self.button3 = w_directattackaim(25000, 1);
+		else
+			self.button0 = w_directattackaim(25000, 1);
+	}
+
+	/*
 	// FIXME: need overload fire sound (second overload sound)
 	if (self.woverload > 0)
 	{
@@ -89,7 +105,7 @@
 			self.woverload = 0;
 		}
 	}
-	else if (self.button0 && Inventory_Quantity(self, "cells") > 0)
+	else */if (self.button0 && Inventory_Quantity(self, "cells") > 0)
 	{
 		self.wload = W_ShotsToFire(0.05);
 		if (self.wload > 0)
@@ -97,15 +113,34 @@
 	}
 	else if (time >= self.attack_finished)
 	{
-		if (self.button3 && Inventory_Quantity(self, "cells") > 0)
+		if (self.button3 && Inventory_Quantity(self, "cells") > 0 && self.woverload < 50)
+		{
+			// FIXME: need overload charge sound (first overload sound)
+			if (!self.woverload)
+				sound(self, CHAN_WEAPON, "plasma/plasexpl.wav", 1, ATTN_NORM);
+			self.woverload = self.woverload + frametime * 50;
+		}
+		else if (self.woverload > 0)
 		{
-			self.woverload = 12;
+			if (W_ShotsToFire(0.5))
+			{
+				// FIXME: need overload fire sound (second overload sound)
+				if (self.woverload > 50)
+					self.woverload = 50;
+				if (self.woverload > Inventory_Quantity(self, "cells"))
+					self.woverload = Inventory_Quantity(self, "cells");
+				if (self.woverload >= 3)
+					W_PlasmaRifleFire(3, self.woverload / 3, 30, self.woverload * 20);
+				self.woverload = 0;
+			}
+			/*
 			//if (self.woverload > Inventory_Quantity(self, "cells"))
 			//	self.woverload = Inventory_Quantity(self, "cells");
-			Inventory_AdjustQuantity(self, "cells", 0 - self.woverload);
+			//Inventory_AdjustQuantity(self, "cells", 0 - 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);
+			*/
 		}
 		else if (widle(w_plasmarifledrop1))
 			return;
Index: dpmod/qc/w_plasmawave.qc
diff -u dpmod/qc/w_plasmawave.qc:1.4 dpmod/qc/w_plasmawave.qc:1.5
--- dpmod/qc/w_plasmawave.qc:1.4	Wed Jul 16 08:16:45 2003
+++ dpmod/qc/w_plasmawave.qc	Sat Aug  9 12:20:28 2003
@@ -100,6 +100,21 @@
 void() w_plasmawaveraise2;
 void() w_plasmawave =
 {
+	if (self.aimtarg) // bot target
+	{
+		if (time > self.altfirechecktimeout)
+		{
+			self.altfirechecktimeout = time + 0.1 + random() * 0.2;
+			if (time > self.altfiretimeout)
+			if (random() < 0.2)
+				self.altfiretimeout = time + 0.5 + random() * 0.5;
+		}
+		if (time < self.altfiretimeout)
+			self.button3 = w_directattackaim(1000, 3);
+		else
+			self.button0 = w_directattackaim(1000, 3);
+	}
+
 	// FIXME: need overload fire sound (second overload sound)
 	if (self.woverload > 0)
 	{
Index: dpmod/qc/w_rocket.qc
diff -u dpmod/qc/w_rocket.qc:1.11 dpmod/qc/w_rocket.qc:1.12
--- dpmod/qc/w_rocket.qc:1.11	Wed Jul 16 08:16:45 2003
+++ dpmod/qc/w_rocket.qc	Sat Aug  9 12:20:28 2003
@@ -135,6 +135,21 @@
 	if (widle(w_rocketdrop1))
 		return;
 
+	if (self.aimtarg) // bot target
+	{
+		if (time > self.altfirechecktimeout)
+		{
+			self.altfirechecktimeout = time + 0.1 + random() * 0.2;
+			if (time > self.altfiretimeout)
+			if (random() < 0.2)
+				self.altfiretimeout = time + 0.5 + random() * 0.5;
+		}
+		if (time < self.altfiretimeout)
+			self.button3 = w_directattackaim(3000, 1);
+		else
+			self.button0 = w_directattackaim(5000, 1);
+	}
+
 	if (self.button3)
 	{
 		if (W_ShotsToFire(1.2))
Index: dpmod/qc/w_shotgun.qc
diff -u dpmod/qc/w_shotgun.qc:1.12 dpmod/qc/w_shotgun.qc:1.13
--- dpmod/qc/w_shotgun.qc:1.12	Sun Jul 27 03:01:19 2003
+++ dpmod/qc/w_shotgun.qc	Sat Aug  9 12:20:28 2003
@@ -36,6 +36,9 @@
 	if (widle(w_shotgundrop1))
 		return;
 
+	if (self.aimtarg) // bot target
+		self.button0 = w_directattackaim(6000, 1);
+
 	if (self.wload > Inventory_Quantity(self, "shells"))
 		self.wload = Inventory_Quantity(self, "shells");
 
Index: dpmod/qc/w_supernailgun.qc
diff -u dpmod/qc/w_supernailgun.qc:1.10 dpmod/qc/w_supernailgun.qc:1.11
--- dpmod/qc/w_supernailgun.qc:1.10	Wed Jul 16 08:16:45 2003
+++ dpmod/qc/w_supernailgun.qc	Sat Aug  9 12:20:28 2003
@@ -95,6 +95,22 @@
 	if (widle(w_snailgundrop1))
 		return;
 
+	if (self.aimtarg) // bot target
+	{
+		if (time > self.altfirechecktimeout)
+		{
+			self.altfirechecktimeout = time + 0.1 + random() * 0.2;
+			if (time > self.altfiretimeout)
+			if (vlen(self.aimtarg.origin - self.origin) < 600)
+			if (random() < 0.2)
+				self.altfiretimeout = time + 0.5 + random() * 0.5;
+		}
+		if (Inventory_Quantity(self, "rockets") >= 3 && time < self.altfiretimeout)
+			self.button3 = w_grenadeattackaim(1000, 1);
+		else
+			self.button0 = w_directattackaim(12000, 1);
+	}
+
 	if (self.button0)
 	{
 		if (Inventory_Quantity(self, "nails") >= 1)
Index: dpmod/qc/world.qc
diff -u dpmod/qc/world.qc:1.3 dpmod/qc/world.qc:1.4
--- dpmod/qc/world.qc:1.3	Wed Jul 16 08:16:45 2003
+++ dpmod/qc/world.qc	Sat Aug  9 12:20:28 2003
@@ -346,6 +346,12 @@
 		c = c + 1;
 	}
 	maxclients = c;
+
+	registercvar("spawnmonsters", "0");
+	registercvar("damagescale_playerdamage", "0");
+	registercvar("damagescale_monsterdamage", "0");
+	registercvar("damagescale_monsterhealth", "0");
+
 	lastspawn = world;
 	InitDecors ();
 	player_precache(); // get player precaches
@@ -712,23 +718,49 @@
 void() damagescaleupdate =
 {
 	local float f;
+
 	skill = cvar("skill");
+
+	// monster damage multiplier
+	monsterdamagescale = 1;
 	// skill 0 =  25%
 	// skill 1 =  50%
 	// skill 2 =  75%
 	// skill 3 = 100%
-	monsterdamagescale = (skill + 1) / 4;
+	if (skill >= 0)
+	if (skill < 4)
+		monsterdamagescale = (skill + 1) / 4;
+	f = cvar("damagescale_monsterdamage");
+	if (f >= 0.01)
+		monsterdamagescale = f;
+
+	// monster health multiplier (implemented by resisting player damage)
+	monsterresistancescale = 1;
 	f = cvar("coop"); // 1 = 1x health, and so on up
-	if (f < 0.1)
-		f = 1;
-	monsterresistancescale = 1 / f;
-	playerdamagescale = (cvar("temp1") & 127) * 0.05;
-	if (playerdamagescale < 0.1)
-		playerdamagescale = 1.0; // 20 - default scale
-	// 100% is pretty realistic damage
-	// (does lack all the vital organs and other details though...)
-	// 10% is basically Quake damage (pitiful)
-	// 20% is normal
+	if (f >= 0.01)
+		monsterresistancescale = 1 / f;
+	f = cvar("damagescale_monsterhealth"); // 1 = 1x health, and so on up
+	if (f >= 0.01)
+		monsterresistancescale = 1 / f;
+
+	// damage multiplier
+	playerdamagescale = 1.0;
+	f = (cvar("temp1") & 127) * 0.05;
+	if (f >= 0.01)
+		playerdamagescale = f;
+	f = cvar("damagescale_playerdamage");
+	if (f >= 0.01)
+		playerdamagescale = f;
+
+	/*
+	bprint("monsterdamagescale ");
+	bprintfloat(monsterdamagescale);
+	bprint(", monsterresistancescale ");
+	bprintfloat(monsterresistancescale);
+	bprint(", playerdamagescale ");
+	bprintfloat(playerdamagescale);
+	bprint("\n");
+	*/
 };
 
 .float findtarget;


More information about the twilight-commits mailing list