r6105 - in trunk/data: models/weapons qcsrc/server

DONOTREPLY at icculus.org DONOTREPLY at icculus.org
Wed Mar 11 17:39:57 EDT 2009


Author: lordhavoc
Date: 2009-03-11 17:39:56 -0400 (Wed, 11 Mar 2009)
New Revision: 6105

Added:
   trunk/data/models/weapons/w_uzi.dpm
   trunk/data/models/weapons/w_uzi.dpm.animinfo
   trunk/data/models/weapons/w_uzi.qh
Modified:
   trunk/data/qcsrc/server/cl_client.qc
   trunk/data/qcsrc/server/cl_physics.qc
   trunk/data/qcsrc/server/cl_player.qc
   trunk/data/qcsrc/server/cl_weapons.qc
   trunk/data/qcsrc/server/cl_weaponsystem.qc
   trunk/data/qcsrc/server/defs.qh
   trunk/data/qcsrc/server/g_subs.qc
   trunk/data/qcsrc/server/movelib.qc
   trunk/data/qcsrc/server/pathlib.qc
   trunk/data/qcsrc/server/progs.src
   trunk/data/qcsrc/server/steerlib.qc
   trunk/data/qcsrc/server/w_hlac.qc
   trunk/data/qcsrc/server/w_seeker.qc
   trunk/data/qcsrc/server/w_uzi.qc
Log:
added dpm weapon support
added motorsep's fixed up w_uzi model


Added: trunk/data/models/weapons/w_uzi.dpm
===================================================================
(Binary files differ)


Property changes on: trunk/data/models/weapons/w_uzi.dpm
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/data/models/weapons/w_uzi.dpm.animinfo
===================================================================
--- trunk/data/models/weapons/w_uzi.dpm.animinfo	                        (rev 0)
+++ trunk/data/models/weapons/w_uzi.dpm.animinfo	2009-03-11 21:39:56 UTC (rev 6105)
@@ -0,0 +1,4 @@
+1 12 40 // fire1
+13 12 40 // fire2
+25 48 10 // idle
+0 1 10 // reload

Added: trunk/data/models/weapons/w_uzi.qh
===================================================================
--- trunk/data/models/weapons/w_uzi.qh	                        (rev 0)
+++ trunk/data/models/weapons/w_uzi.qh	2009-03-11 21:39:56 UTC (rev 6105)
@@ -0,0 +1,12 @@
+
+/*
+Generated header file for w_uzi
+This file contains animation definitions for use in code referencing the model, simply add this file to your progs.src before use.
+*/
+
+vector anim_w_uzi_ref1 = '0 1 20';
+vector anim_w_uzi_fire = '1 12 40';
+vector anim_w_uzi_fire2 = '13 12 40';
+vector anim_w_uzi_idle = '25 48 20';
+
+// end of animation definitions for w_uzi

Modified: trunk/data/qcsrc/server/cl_client.qc
===================================================================
--- trunk/data/qcsrc/server/cl_client.qc	2009-03-11 20:45:17 UTC (rev 6104)
+++ trunk/data/qcsrc/server/cl_client.qc	2009-03-11 21:39:56 UTC (rev 6105)
@@ -2274,7 +2274,7 @@
 				self.crouch = TRUE;
 				self.view_ofs = PL_CROUCH_VIEW_OFS;
 				setsize (self, PL_CROUCH_MIN, PL_CROUCH_MAX);
-				player_setanim(self.anim_duck, FALSE, TRUE, TRUE);
+				setanim(self, self.anim_duck, FALSE, TRUE, TRUE);
 			}
 		}
 		else

Modified: trunk/data/qcsrc/server/cl_physics.qc
===================================================================
--- trunk/data/qcsrc/server/cl_physics.qc	2009-03-11 20:45:17 UTC (rev 6104)
+++ trunk/data/qcsrc/server/cl_physics.qc	2009-03-11 21:39:56 UTC (rev 6105)
@@ -83,9 +83,9 @@
 	self.flags &~= FL_JUMPRELEASED;
 
 	if (self.crouch)
-		player_setanim(self.anim_duckjump, FALSE, TRUE, TRUE);
+		setanim(self, self.anim_duckjump, FALSE, TRUE, TRUE);
 	else
-		player_setanim(self.anim_jump, FALSE, TRUE, TRUE);
+		setanim(self, self.anim_jump, FALSE, TRUE, TRUE);
 
 	if(g_jump_grunt)
 		PlayerSound(playersound_jump, CHAN_PLAYER, VOICETYPE_PLAYERSOUND);

Modified: trunk/data/qcsrc/server/cl_player.qc
===================================================================
--- trunk/data/qcsrc/server/cl_player.qc	2009-03-11 20:45:17 UTC (rev 6104)
+++ trunk/data/qcsrc/server/cl_player.qc	2009-03-11 21:39:56 UTC (rev 6105)
@@ -65,30 +65,6 @@
 	self = oldself;
 }
 
-float animparseerror;
-vector animparseline(float animfile)
-{
-	local string line;
-	local float c;
-	local vector anim;
-	if (animfile < 0)
-		return '0 1 2';
-	line = fgets(animfile);
-	c = tokenize_sane(line);
-	if (c != 3)
-	{
-		animparseerror = TRUE;
-		return '0 1 2';
-	}
-	anim_x = stof(argv(0));
-	anim_y = stof(argv(1));
-	anim_z = stof(argv(2));
-	// don't allow completely bogus values
-	if (anim_x < 0 || anim_y < 1 || anim_z < 0.001)
-		anim = '0 1 2';
-	return anim;
-};
-
 void player_setupanimsformodel()
 {
 	local string animfilename;
@@ -155,43 +131,14 @@
 	else
 		dprint("File ", animfilename, " not found, assuming legacy .zym model animation timings\n");
 	// reset animstate now
-	player_setanim(self.anim_idle, TRUE, FALSE, TRUE);
+	setanim(self, self.anim_idle, TRUE, FALSE, TRUE);
 };
 
-void player_setanim(vector anim, float looping, float override, float restart)
-{
-	if (!restart)
-	if (anim_x == self.animstate_startframe)
-	if (anim_y == self.animstate_numframes)
-	if (anim_z == self.animstate_framerate)
-		return;
-	self.animstate_startframe = anim_x;
-	self.animstate_numframes = anim_y;
-	self.animstate_framerate = anim_z;
-	self.animstate_starttime = time;
-	self.animstate_endtime = time + self.animstate_numframes / self.animstate_framerate;
-	self.animstate_looping = looping;
-	self.animstate_override = override;
-	self.frame = self.animstate_startframe;
-};
-
-void player_updateframe()
-{
-	if (time >= self.animstate_endtime)
-	{
-		if (self.animstate_looping)
-		{
-			self.animstate_starttime = self.animstate_endtime;
-			self.animstate_endtime = self.animstate_endtime + self.animstate_numframes / self.animstate_framerate;
-		}
-		self.animstate_override = FALSE;
-	}
-	self.frame = self.animstate_startframe + bound(0, (time - self.animstate_starttime) * self.animstate_framerate, self.animstate_numframes - 1);
-};
-
 void player_anim (void)
 {
-	player_updateframe();
+	updateanim(self);
+	if (self.weaponentity)
+		updateanim(self.weaponentity);
 
 	if (self.deadflag != DEAD_NO)
 	{
@@ -212,43 +159,46 @@
 		if (!(self.flags & FL_ONGROUND))
 		{
 			if (self.crouch)
-				player_setanim(self.anim_duckjump, FALSE, TRUE, FALSE);
+				setanim(self, self.anim_duckjump, FALSE, TRUE, FALSE);
 			else
-				player_setanim(self.anim_jump, FALSE, TRUE, FALSE);
+				setanim(self, self.anim_jump, FALSE, TRUE, FALSE);
 		}
 		else if (self.crouch)
 		{
 			if (self.movement_x * self.movement_x + self.movement_y * self.movement_y > 20)
-				player_setanim(self.anim_duckwalk, TRUE, FALSE, FALSE);
+				setanim(self, self.anim_duckwalk, TRUE, FALSE, FALSE);
 			else
-				player_setanim(self.anim_duckidle, TRUE, FALSE, FALSE);
+				setanim(self, self.anim_duckidle, TRUE, FALSE, FALSE);
 		}
 		else if ((self.movement_x * self.movement_x + self.movement_y * self.movement_y) > 20)
 		{
 			if (self.movement_x > 0 && self.movement_y == 0)
-				player_setanim(self.anim_run, TRUE, FALSE, FALSE);
+				setanim(self, self.anim_run, TRUE, FALSE, FALSE);
 			else if (self.movement_x < 0 && self.movement_y == 0)
-				player_setanim(self.anim_runbackwards, TRUE, FALSE, FALSE);
+				setanim(self, self.anim_runbackwards, TRUE, FALSE, FALSE);
 			else if (self.movement_x == 0 && self.movement_y > 0)
-				player_setanim(self.anim_straferight, TRUE, FALSE, FALSE);
+				setanim(self, self.anim_straferight, TRUE, FALSE, FALSE);
 			else if (self.movement_x == 0 && self.movement_y < 0)
-				player_setanim(self.anim_strafeleft, TRUE, FALSE, FALSE);
+				setanim(self, self.anim_strafeleft, TRUE, FALSE, FALSE);
 			else if (self.movement_x > 0 && self.movement_y > 0)
-				player_setanim(self.anim_forwardright, TRUE, FALSE, FALSE);
+				setanim(self, self.anim_forwardright, TRUE, FALSE, FALSE);
 			else if (self.movement_x > 0 && self.movement_y < 0)
-				player_setanim(self.anim_forwardleft, TRUE, FALSE, FALSE);
+				setanim(self, self.anim_forwardleft, TRUE, FALSE, FALSE);
 			else if (self.movement_x < 0 && self.movement_y > 0)
-				player_setanim(self.anim_backright, TRUE, FALSE, FALSE);
+				setanim(self, self.anim_backright, TRUE, FALSE, FALSE);
 			else if (self.movement_x < 0 && self.movement_y < 0)
-				player_setanim(self.anim_backleft, TRUE, FALSE, FALSE);
+				setanim(self, self.anim_backleft, TRUE, FALSE, FALSE);
 			else
-				player_setanim(self.anim_run, TRUE, FALSE, FALSE);
+				setanim(self, self.anim_run, TRUE, FALSE, FALSE);
 		}
 		else
-			player_setanim(self.anim_idle, TRUE, FALSE, FALSE);
+			setanim(self, self.anim_idle, TRUE, FALSE, FALSE);
 	}
+
+	if (self.weaponentity)
+	if (!self.weaponentity.animstate_override)
+		setanim(self, self.anim_idle, TRUE, FALSE, FALSE);
 }
-//End change by Supajoe on 11:44 PM EST 11/16/03 (Subject: Player animations)
 
 void SpawnThrownWeapon (vector org, float w)
 {
@@ -371,9 +321,9 @@
 
 				if(sv_gentle < 1) {		
 					if (random() > 0.5)
-						player_setanim(self.anim_pain1, FALSE, TRUE, TRUE);
+						setanim(self, self.anim_pain1, FALSE, TRUE, TRUE);
 					else
-						player_setanim(self.anim_pain2, FALSE, TRUE, TRUE);
+						setanim(self, self.anim_pain2, FALSE, TRUE, TRUE);
 
 					if(!DEATH_ISWEAPON(deathtype, WEP_LASER) || attacker != self || self.health < 2 * cvar("g_balance_laser_primary_damage") * cvar("g_balance_selfdamagepercent") + 1)
 					// exclude pain sounds for laserjumps as long as you aren't REALLY low on health and would die of the next two
@@ -520,12 +470,12 @@
 			self.respawn_countdown = -1; // do not count down
 		if (random() < 0.5)
 		{
-			player_setanim(self.anim_die1, FALSE, TRUE, TRUE);
+			setanim(self, self.anim_die1, FALSE, TRUE, TRUE);
 			self.dead_frame = self.anim_dead1_x;
 		}
 		else
 		{
-			player_setanim(self.anim_die2, FALSE, TRUE, TRUE);
+			setanim(self, self.anim_die2, FALSE, TRUE, TRUE);
 			self.dead_frame = self.anim_dead2_x;
 		}
 		// set damage function to corpse damage

Modified: trunk/data/qcsrc/server/cl_weapons.qc
===================================================================
--- trunk/data/qcsrc/server/cl_weapons.qc	2009-03-11 20:45:17 UTC (rev 6104)
+++ trunk/data/qcsrc/server/cl_weapons.qc	2009-03-11 21:39:56 UTC (rev 6105)
@@ -307,7 +307,7 @@
 	{
 		if (self.weaponentity.state == WS_CLEAR)
 		{
-			player_setanim(self.anim_draw, FALSE, TRUE, TRUE);
+			setanim(self, self.anim_draw, FALSE, TRUE, TRUE);
 			self.weaponentity.state = WS_RAISE;
 			weapon_action(self.switchweapon, WR_SETUP);
 			// VorteX: add player model weapon select frame here

Modified: trunk/data/qcsrc/server/cl_weaponsystem.qc
===================================================================
--- trunk/data/qcsrc/server/cl_weaponsystem.qc	2009-03-11 20:45:17 UTC (rev 6104)
+++ trunk/data/qcsrc/server/cl_weaponsystem.qc	2009-03-11 21:39:56 UTC (rev 6105)
@@ -257,7 +257,7 @@
 	float tb;
 	self.nextthink = time;
 	if (intermission_running)
-		self.frame = WFRAME_IDLE;
+		self.frame = self.anim_idle_x;
 	if (self.owner.weaponentity != self)
 	{
 		remove(self);
@@ -273,11 +273,40 @@
 		self.cnt = self.owner.weapon;
 		self.dmg = self.owner.modelindex;
 		self.deadflag = self.owner.deadflag;
+
+		string animfilename;
+		float animfile;
 		if (self.owner.weaponname != "")
-			setmodel(self, strcat("models/weapons/w_", self.owner.weaponname, ".zym")); // precision set below
+		{
+			animfilename = strcat("models/weapons/w_", self.owner.weaponname, ".dpm.animinfo");
+			animfile = fopen(animfilename, FILE_READ);
+			if (animfile >= 0)
+			{
+				animparseerror = FALSE;
+				self.anim_fire1  = animparseline(animfile);
+				self.anim_fire2  = animparseline(animfile);
+				self.anim_idle   = animparseline(animfile);
+				self.anim_reload = animparseline(animfile);
+				fclose(animfile);
+				if (animparseerror)
+					print("Parse error in ", animfilename, ", some player animations are broken\n");
+				setmodel(self, strcat("models/weapons/w_", self.owner.weaponname, ".dpm")); // precision set below
+			}
+			else
+			{
+				self.anim_fire1  = '0 1 10';
+				self.anim_fire2  = '1 1 10';
+				self.anim_idle   = '2 1 10';
+				self.anim_reload = '3 1 10';
+				setmodel(self, strcat("models/weapons/w_", self.owner.weaponname, ".zym")); // precision set below
+			}
+		}
 		else
 			self.model = "";
 
+		// reset animstate now
+		setanim(self, self.anim_idle, TRUE, FALSE, TRUE);
+
 		if(cvar("g_shootfromcenter") || cvar("g_shootfromeye"))
 		{
 			entity e;
@@ -570,15 +599,29 @@
 
 void weapon_thinkf(float fr, float t, void() func)
 {
-	if (fr >= 0)
+	vector a;
+	float restartanim;
+
+	if (fr == WFRAME_FIRE1 || fr == WFRAME_FIRE2)
+		restartanim = TRUE;
+	else
+		restartanim = FALSE;
+
+	if (self.weaponentity)
 	{
-		if (self.weaponentity != world)
+		if (fr == WFRAME_IDLE)
+			a = self.weaponentity.anim_idle;
+		else if (fr == WFRAME_FIRE1)
+			a = self.weaponentity.anim_fire1;
+		else if (fr == WFRAME_FIRE2)
+			a = self.weaponentity.anim_fire2;
+		else if (fr == WFRAME_RELOAD)
+			a = self.weaponentity.anim_reload;
+		setanim(self.weaponentity, a, restartanim == FALSE, restartanim, restartanim);
+
+		if(reset)
 		{
-			if(fr == WFRAME_FIRE1 || fr == WFRAME_FIRE2)
-			{
-				BITXOR_ASSIGN(self.weaponentity.effects, EF_TELEPORT_BIT);
-			}
-			self.weaponentity.frame = fr;
+			BITXOR_ASSIGN(self.weaponentity.effects, EF_TELEPORT_BIT);
 		}
 	}
 
@@ -617,14 +660,14 @@
 	self.weapon_think = func;
 	//dprint("next ", ftos(self.weapon_nextthink), "\n");
 
-	if (fr == WFRAME_FIRE1 || fr == WFRAME_FIRE2)
+	if (reset)
 	if (t)
 	if (!self.crouch) // shoot anim stands up, this looks bad
 	{
 		local vector anim;
 		anim = self.anim_shoot;
 		anim_z = anim_y / t;
-		player_setanim(anim, FALSE, TRUE, TRUE);
+		setanim(self, anim, FALSE, TRUE, TRUE);
 	}
 };
 

Modified: trunk/data/qcsrc/server/defs.qh
===================================================================
--- trunk/data/qcsrc/server/defs.qh	2009-03-11 20:45:17 UTC (rev 6104)
+++ trunk/data/qcsrc/server/defs.qh	2009-03-11 21:39:56 UTC (rev 6105)
@@ -147,8 +147,14 @@
 .vector anim_backright; // player running backward and right
 .vector anim_backleft; // player running back and left
 
+// weapon animation vectors:
+.vector anim_fire1;
+.vector anim_fire2;
+.vector anim_idle;
+.vector anim_reload;
+
 void() player_setupanimsformodel;
-void player_setanim(vector anim, float looping, float override, float restart);
+void setanim(entity e, vector anim, float looping, float override, float restart);
 
 .string mdl;
 

Modified: trunk/data/qcsrc/server/g_subs.qc
===================================================================
--- trunk/data/qcsrc/server/g_subs.qc	2009-03-11 20:45:17 UTC (rev 6104)
+++ trunk/data/qcsrc/server/g_subs.qc	2009-03-11 21:39:56 UTC (rev 6105)
@@ -12,6 +12,61 @@
 	// if anything breaks, tell the mapper to fix his map! info_null is meant to remove itself immediately.
 }
 
+void setanim(entity e, vector anim, float looping, float override, float restart)
+{
+	if (!restart)
+	if (anim_x == e.animstate_startframe)
+	if (anim_y == e.animstate_numframes)
+	if (anim_z == e.animstate_framerate)
+		return;
+	e.animstate_startframe = anim_x;
+	e.animstate_numframes = anim_y;
+	e.animstate_framerate = anim_z;
+	e.animstate_starttime = time;
+	e.animstate_endtime = time + e.animstate_numframes / e.animstate_framerate;
+	e.animstate_looping = looping;
+	e.animstate_override = override;
+	e.frame = e.animstate_startframe;
+};
+
+void updateanim(entity e)
+{
+	if (time >= e.animstate_endtime)
+	{
+		if (e.animstate_looping)
+		{
+			e.animstate_starttime = e.animstate_endtime;
+			e.animstate_endtime = e.animstate_endtime + e.animstate_numframes / e.animstate_framerate;
+		}
+		e.animstate_override = FALSE;
+	}
+	e.frame = e.animstate_startframe + bound(0, (time - e.animstate_starttime) * e.animstate_framerate, e.animstate_numframes - 1);
+};
+
+float animparseerror;
+vector animparseline(float animfile)
+{
+	local string line;
+	local float c;
+	local vector anim;
+	if (animfile < 0)
+		return '0 1 2';
+	line = fgets(animfile);
+	c = tokenize_sane(line);
+	if (c != 3)
+	{
+		animparseerror = TRUE;
+		return '0 1 2';
+	}
+	anim_x = stof(argv(0));
+	anim_y = stof(argv(1));
+	anim_z = stof(argv(2));
+	// don't allow completely bogus values
+	if (anim_x < 0 || anim_y < 1 || anim_z < 0.001)
+		anim = '0 1 2';
+	return anim;
+};
+
 /*
 ==================
 SUB_Remove

Modified: trunk/data/qcsrc/server/movelib.qc
===================================================================
--- trunk/data/qcsrc/server/movelib.qc	2009-03-11 20:45:17 UTC (rev 6104)
+++ trunk/data/qcsrc/server/movelib.qc	2009-03-11 21:39:56 UTC (rev 6105)
@@ -1,132 +1,132 @@
-/**
-    Simulate drag
-    self.velocity = movelib_vdrag(self.velocity,0.02,0.5);
-**/
-vector movelib_dragvec(float drag, float exp)
-{
-    float lspeed,ldrag;
-
-    lspeed = vlen(self.velocity);
-    ldrag = lspeed * drag;
-    ldrag = ldrag * (drag * exp);
-    ldrag = 1 - (ldrag / lspeed);
-
-    return self.velocity * ldrag;
-}
-
-/**
-    Simulate drag
-    self.velocity = movelib_vdrag(somespeed,0.01,0.7);
-**/
-float movelib_dragflt(float fspeed,float drag,float exp)
-{
-    float ldrag;
-
-    ldrag = fspeed * drag;
-    ldrag = ldrag * ldrag * exp;
-    ldrag = 1 - (ldrag / fspeed);
-
-    return ldrag;
-}
-
-/**
-    Do a inertia simulation based on velocity.
-    Basicaly, this allows you to simulate objects loss steering with speed.
-    self.velocity = movelib_inertia_fromspeed(self.velocity,newvel,1000,0.1,0.9);
-**/
-vector movelib_inertmove_byspeed(vector vel_new, float vel_max,float newmin,float oldmax)
-{
-    float influense;
-
-    influense = vlen(self.velocity) * (1 / vel_max);
-
-    influense = bound(newmin,influense,oldmax);
-
-    return (vel_new * (1 - influense)) + (self.velocity * influense);
-}
-
-vector movelib_inertmove(vector new_vel,float new_bias)
-{
-    return new_vel * new_bias + self.velocity * (1-new_bias);
-}
-
-.float  movelib_lastupdate;
-void movelib_move(vector force,float max_velocity,float drag,float mass,float breakforce)
-{
-    float deltatime;
-    float acceleration;
-    //float mspeed;
-
-    deltatime = time - self.movelib_lastupdate;
-    if (deltatime > 0.15) deltatime = 0;
-    self.movelib_lastupdate = time;
-    if(!deltatime) return;
-
-    //mspeed = vlen(self.velocity);
-
-    if(mass)
-        acceleration = vlen(force) / mass;
-    else
-        acceleration = vlen(force);
-
-    if(self.flags & FL_ONGROUND)
-    {
-        if(breakforce)
-        {
-            breakforce = 1 - ((breakforce / mass) * deltatime);
-            self.velocity = self.velocity * breakforce;
-        }
-
-        self.velocity = self.velocity + force * (acceleration * deltatime);
-    }
-
-    self.velocity = self.velocity + '0 0 -1' * sv_gravity * deltatime;
-
-    if(drag)
-        self.velocity = movelib_dragvec(drag, 1);
-
-    if(max_velocity)
-    if(vlen(self.velocity) > max_velocity)
-        self.velocity = normalize(self.velocity) * max_velocity;
-}
-
-void movelib_move_simple(vector newdir,float velo,float turnrate)
-{
-    vector olddir;
-
-    olddir = normalize(self.velocity);
-
-    self.velocity = normalize(olddir + newdir * turnrate) * velo;
-}
-
-/*
-vector movelib_accelerate(float force)
-{
-    vector vel;
-    vel = self.velocity;
-    vel = normalize(vel) * (vlen(vel) + force);
-    self.velocity = self.velocity  + vel;
-}
-
-
-vector movelib_decelerate(float force,float mass)
-{
-    vector vel;
-    float decel;
-
-    if(mass)
-        decel = force / mass;
-    else
-        decel = force;
-
-    vel = self.velocity;
-    vel = normalize(vel) * max((vlen(vel) - decel),0);
-    self.velocity = self.velocity - vel;
-
-    if(vlen(self.velocity) < 5) self.velocity = '0 0 0';
-}
-*/
-vector movelib_velocity_transfer(entity source,entity destination)
-{
-    return '0 0 0';
-}
+/**
+    Simulate drag
+    self.velocity = movelib_vdrag(self.velocity,0.02,0.5);
+**/
+vector movelib_dragvec(float drag, float exp)
+{
+    float lspeed,ldrag;
+
+    lspeed = vlen(self.velocity);
+    ldrag = lspeed * drag;
+    ldrag = ldrag * (drag * exp);
+    ldrag = 1 - (ldrag / lspeed);
+
+    return self.velocity * ldrag;
+}
+
+/**
+    Simulate drag
+    self.velocity = movelib_vdrag(somespeed,0.01,0.7);
+**/
+float movelib_dragflt(float fspeed,float drag,float exp)
+{
+    float ldrag;
+
+    ldrag = fspeed * drag;
+    ldrag = ldrag * ldrag * exp;
+    ldrag = 1 - (ldrag / fspeed);
+
+    return ldrag;
+}
+
+/**
+    Do a inertia simulation based on velocity.
+    Basicaly, this allows you to simulate objects loss steering with speed.
+    self.velocity = movelib_inertia_fromspeed(self.velocity,newvel,1000,0.1,0.9);
+**/
+vector movelib_inertmove_byspeed(vector vel_new, float vel_max,float newmin,float oldmax)
+{
+    float influense;
+
+    influense = vlen(self.velocity) * (1 / vel_max);
+
+    influense = bound(newmin,influense,oldmax);
+
+    return (vel_new * (1 - influense)) + (self.velocity * influense);
+}
+
+vector movelib_inertmove(vector new_vel,float new_bias)
+{
+    return new_vel * new_bias + self.velocity * (1-new_bias);
+}
+
+.float  movelib_lastupdate;
+void movelib_move(vector force,float max_velocity,float drag,float mass,float breakforce)
+{
+    float deltatime;
+    float acceleration;
+    //float mspeed;
+
+    deltatime = time - self.movelib_lastupdate;
+    if (deltatime > 0.15) deltatime = 0;
+    self.movelib_lastupdate = time;
+    if(!deltatime) return;
+
+    //mspeed = vlen(self.velocity);
+
+    if(mass)
+        acceleration = vlen(force) / mass;
+    else
+        acceleration = vlen(force);
+
+    if(self.flags & FL_ONGROUND)
+    {
+        if(breakforce)
+        {
+            breakforce = 1 - ((breakforce / mass) * deltatime);
+            self.velocity = self.velocity * breakforce;
+        }
+
+        self.velocity = self.velocity + force * (acceleration * deltatime);
+    }
+
+    self.velocity = self.velocity + '0 0 -1' * sv_gravity * deltatime;
+
+    if(drag)
+        self.velocity = movelib_dragvec(drag, 1);
+
+    if(max_velocity)
+    if(vlen(self.velocity) > max_velocity)
+        self.velocity = normalize(self.velocity) * max_velocity;
+}
+
+void movelib_move_simple(vector newdir,float velo,float turnrate)
+{
+    vector olddir;
+
+    olddir = normalize(self.velocity);
+
+    self.velocity = normalize(olddir + newdir * turnrate) * velo;
+}
+
+/*
+vector movelib_accelerate(float force)
+{
+    vector vel;
+    vel = self.velocity;
+    vel = normalize(vel) * (vlen(vel) + force);
+    self.velocity = self.velocity  + vel;
+}
+
+
+vector movelib_decelerate(float force,float mass)
+{
+    vector vel;
+    float decel;
+
+    if(mass)
+        decel = force / mass;
+    else
+        decel = force;
+
+    vel = self.velocity;
+    vel = normalize(vel) * max((vlen(vel) - decel),0);
+    self.velocity = self.velocity - vel;
+
+    if(vlen(self.velocity) < 5) self.velocity = '0 0 0';
+}
+*/
+vector movelib_velocity_transfer(entity source,entity destination)
+{
+    return '0 0 0';
+}

Modified: trunk/data/qcsrc/server/pathlib.qc
===================================================================
--- trunk/data/qcsrc/server/pathlib.qc	2009-03-11 20:45:17 UTC (rev 6104)
+++ trunk/data/qcsrc/server/pathlib.qc	2009-03-11 21:39:56 UTC (rev 6105)
@@ -1,480 +1,480 @@
-#define PFL_GROUNDSNAP 1
-#define PFL_NOOPTIMIZE 2
-#define PFL_SUBPATH3D  4
-
-#define PT_QUICKSTAR 1
-#define PT_QUICKBOX  2
-#define PT_ASTAR     4  // FIXME NOT IMPLEMENTED
-
-//#define PATHLIB_RDFIELDS
-#ifdef PATHLIB_RDFIELDS
-    #define path_flags lip
-
-    #define path_subpathing_size autoswitch
-    #define path_subpathing_bboxexpand welcomemessage_time
-
-    #define path_next swampslug
-    #define path_prev lasertarget
-#else
-    .entity path_next;
-    .entity path_prev;
-
-    .float path_subpathing_size;
-    .float path_subpathing_bboxexpand;
-    .float path_flags;
-#endif
-
-#define pathlib_garbagetime 120
-#define pathib_maxdivide 512
-
-.float(vector start,vector end) path_validate;
-
-float pathlib_stdproc_path_validate(vector start,vector end)
-{
-    tracebox(start, self.mins, self.maxs, end, MOVE_WORLDONLY, self);
-
-    if(vlen(trace_endpos - end) < 32)
-        return 1;
-
-    return 0;
-}
-
-vector pathlib_groundsnap(vector where)
-{
-    float lsize;
-
-    lsize = vlen(self.mins - self.maxs) * 0.25;
-
-    traceline(where + ('0 0 1' * lsize) ,where - '0 0 10240',MOVE_WORLDONLY,self);
-
-    return trace_endpos + ('0 0 1' * lsize);
-
-}
-
-entity pathlib_createpoint(entity parent,entity next,entity first,vector where)
-{
-    entity point;
-
-    point = spawn();
-    point.classname = "path_node";
-
-    if(first)
-        point.owner = first;
-    else
-    {
-        point.classname = "path_master";
-        point.owner = point;
-    }
-
-    if(parent)
-        point.path_prev = parent;
-
-    if(next)
-    {
-        point.path_next = next;
-    }
-    else
-        point.classname = "path_end";
-
-    if (point.owner.path_flags & PFL_GROUNDSNAP)
-        where = pathlib_groundsnap(where);
-
-    setorigin(point,where);
-
-
-    return point;
-}
-
-/*
-float pathlib_scoresubpath(vector start,vector point,vector end,float minstep)
-{
-    float dist_stp,dist_pte,dist_total;
-
-    dist_stp = vlen(start - point);
-    if(dist_stp < minstep)
-        return 100000000;
-
-    dist_pte = vlen(point - end);
-    dist_total = dist_stp + dist_pte;
-    return -1;
-}
-*/
-
-vector pathlib_subpath_quickbox(entity start,vector vcrash,entity end,float maxsize)
-{
-
-    float step;
-    float pathscore;
-    float pathscore_best;
-    float dist;
-    vector bestpoint,point;
-    float zmin,zmax;
-    vector box;
-
-    pathscore_best = 0;
-
-    step = vlen(self.maxs - self.mins) * start.owner.path_subpathing_bboxexpand;
-
-    if(start.owner.path_flags & PFL_SUBPATH3D)
-    {
-        zmin = maxsize * -1;
-        zmax = maxsize;
-    }
-    else
-    {
-        zmin = 0;
-        zmax = 1;
-    }
-
-    for(box_z = zmin; box_z < zmax; box_z += step)
-    for(box_y = -maxsize; box_y < maxsize; box_y += step)
-    for(box_x = -maxsize; box_x < maxsize; box_x += step)
-    {
-
-        point = vcrash + box;
-
-        if(start.owner.path_flags & PFL_GROUNDSNAP)
-            point = pathlib_groundsnap(point);
-
-        if(self.path_validate(start.origin,point))
-        {
-            dist = vlen(start.origin - point);
-            if(dist > step)
-            {
-                pathscore = 1 / (dist + vlen(point - end.origin));
-                if(pathscore > pathscore_best)
-                {
-                    bestpoint = point;
-                    pathscore_best = pathscore;
-                }
-            }
-        }
-
-    }
-
-    if(pathscore_best != 0)
-        return bestpoint;
-
-    return start.origin;
-}
-
-vector pathlib_subpath_quickstar(entity start,entity end,float gridsize)
-{
-    vector point, best_point;
-    float  score, best_score;
-    vector dir_end;
-
-    dir_end   = normalize(end.origin - start.origin);
-    dir_end_x = dir_end_x * -1;
-
-    makevectors(dir_end);
-
-    best_score = 0;
-    score      = 0;
-
-    best_point = start.origin;
-
-    // Forward
-    point = start.origin + v_forward * gridsize;
-    point  = pathlib_groundsnap(point);
-    if(self.path_validate(start.origin,point)) score = 1 / vlen(point - end.origin);
-    if(score < best_score) { best_point = point; best_score = score; }
-    //te_lightning1(world,start.origin,point);
-
-    // Forward-right
-    point = start.origin + (v_forward + v_right * 0.5) * gridsize;
-    point  = pathlib_groundsnap(point);
-    if(self.path_validate(start.origin,point)) score = 1 / vlen(point - end.origin);
-    if(score < best_score) { best_point = point; best_score = score; }
-    //te_lightning1(world,start.origin,point);
-
-
-    // Forward-left
-    point = start.origin + (v_forward - v_right * 0.5) * gridsize;
-    point  = pathlib_groundsnap(point);
-    if(self.path_validate(start.origin,point)) score = 1 / vlen(point - end.origin);
-    if(score < best_score) { best_point = point; best_score = score; }
-    //te_lightning1(world,start.origin,point);
-
-
-    // Right
-    point = start.origin + v_right * gridsize;
-    point  = pathlib_groundsnap(point);
-    if(self.path_validate(start.origin,point)) score = 1 / vlen(point - end.origin);
-    if(score < best_score) { best_point = point; best_score = score; }
-    //te_lightning1(world,start.origin,point);
-
-    // Left
-    point = start.origin - v_right * gridsize;
-    point  = pathlib_groundsnap(point);
-    if(self.path_validate(start.origin,point)) score = 1 / vlen(point - end.origin);
-    if(score < best_score) { best_point = point; best_score = score; }
-    //te_lightning1(world,start.origin,point);
-
-    // Back
-    point = start.origin - v_forward * gridsize;
-    point  = pathlib_groundsnap(point);
-    if(self.path_validate(start.origin,point)) score = 1 / vlen(point - end.origin);
-    if(score < best_score) { best_point = point; best_score = score; }
-    //te_lightning1(world,start.origin,point);
-
-    // Back-right
-
-    point = start.origin - (v_forward + v_right * 0.5) * gridsize;
-    point  = pathlib_groundsnap(point);
-    if(self.path_validate(start.origin,point)) score = 1 / vlen(point - end.origin);
-    if(score < best_score) { best_point = point; best_score = score; }
-    //te_lightning1(world,start.origin,point);
-
-    // Back-left
-    point = start.origin - (v_forward - v_right * 0.5) * gridsize;
-    point  = pathlib_groundsnap(point);
-    if(self.path_validate(start.origin,point)) score = 1 / vlen(point - end.origin);
-    if(score < best_score) { best_point = point; best_score = score; }
-    //te_lightning1(world,start.origin,point);
-
-    return(best_point);
-}
-
-float pathlib_path(entity start,entity end,float pathing_method)
-{
-    vector vcrash;
-    vector subpath_point;
-    entity subpoint;
-
-    // Fail.
-    if(start.cnt > pathib_maxdivide)
-    {
-        bprint("To many segments!\n");
-        return 0;
-    }
-
-    if(self.path_validate(start.origin,end.origin))
-        return 1;
-
-    vcrash = trace_endpos;
-
-    switch(pathing_method)
-    {
-        case PT_QUICKSTAR:
-            subpath_point = pathlib_subpath_quickstar(start,end,start.owner.path_subpathing_size);
-            break;
-        case PT_QUICKBOX:
-            subpath_point = pathlib_subpath_quickbox(start,vcrash,end,start.owner.path_subpathing_size);
-            break;
-        case PT_ASTAR:
-            dprint("Pathlib error: A* pathing not implemented!\n");
-            return 0;
-        default:
-            subpath_point = pathlib_subpath_quickstar(start,end,start.owner.path_subpathing_size);
-            dprint("Pathlib warning: unknown pathing method, using quickstar!\n");
-            break;
-    }
-
-    if(subpath_point == start.origin)
-        return 0; // Fail.
-
-    subpoint = pathlib_createpoint(start,end,start.owner,subpath_point);
-
-    subpoint.cnt = start.cnt +1;
-    start.path_next = subpoint;
-    end.path_prev = subpoint;
-
-    if(self.path_validate(start.origin,end.origin))
-        return 1;
-
-    return pathlib_path(subpoint,end,pathing_method);
-}
-
-void pathlib_path_optimize(entity start,entity end)
-{
-    entity point,point_tmp;
-    float c;
-
-    point = start.path_next;
-
-    while(point != end)
-    {
-        ++c;
-        if(c > 5000)
-        {
-            dprint("pathlib_path_optimize runaway!\n");
-            return;
-        }
-
-        point_tmp = point;
-        point = point.path_next;
-        if(self.path_validate(point_tmp.path_prev.origin,point_tmp.path_next.origin))
-        {
-
-            point_tmp.path_next.path_prev = point_tmp.path_prev;
-            point_tmp.path_prev.path_next = point_tmp.path_next;
-            remove(point_tmp);
-        }
-    }
-}
-
-void pathlib_deletepath(entity start)
-{
-    entity e;
-
-    e = findchainentity(owner, start);
-    while(e)
-    {
-        e.think = SUB_Remove;
-        e.nextthink = time;
-        e = e.chain;
-    }
-}
-
-//#define DEBUGPATHING
-#ifdef DEBUGPATHING
-void pathlib_showpath(entity start)
-{
-    entity e;
-    e = start;
-    while(e.path_next)
-    {
-        te_lightning1(e,e.origin,e.path_next.origin);
-        e = e.path_next;
-    }
-}
-
-void path_dbg_think()
-{
-    pathlib_showpath(self);
-    self.nextthink = time + 1;
-}
-#endif
-/**
-    Pathing from 'from' to 'to'
-**/
-entity pathlib_makepath(vector from, vector to,float pathflags,float subpathing_size, float subpathing_bboxexpand,float pathing_method)
-{
-    entity e_start,e_end;
-
-    if(!self.path_validate)
-        self.path_validate = pathlib_stdproc_path_validate;
-
-
-    if(subpathing_size < 10)
-        subpathing_size = 500;
-
-    if(subpathing_bboxexpand < 1)
-        subpathing_bboxexpand = 1;
-
-    if(pathflags & PFL_GROUNDSNAP)
-    {
-        from = pathlib_groundsnap(from);
-        to = pathlib_groundsnap(to);
-    }
-
-    e_start = pathlib_createpoint(world,world,world,from);
-    e_start.path_flags = pathflags;
-
-    e_start.path_subpathing_size = subpathing_size;
-    e_start.path_subpathing_bboxexpand = subpathing_bboxexpand;
-
-    e_start.owner = e_start;
-
-    e_end = pathlib_createpoint(e_start,world,e_start,to);
-    e_start.path_next = e_end;
-    e_start.cnt = 0;
-
-    if(!pathlib_path(e_start,e_end,pathing_method))
-    {
-        bprint("Fail, Fail, Fail!\n");
-        pathlib_deletepath(e_start);
-        remove(e_start);
-
-        return world;
-    }
-
-    pathlib_path_optimize(e_start,e_end);
-
-#ifdef DEBUGPATHING
-    e_start.think = path_dbg_think;
-    e_start.nextthink = time + 1;
-#endif
-
-    return e_start;
-
-}
-
-/*
-.entity goalcurrent, goalstack01, goalstack02, goalstack03;
-.entity goalstack04, goalstack05, goalstack06, goalstack07;
-.entity goalstack08, goalstack09, goalstack10, goalstack11;
-.entity goalstack12, goalstack13, goalstack14, goalstack15;
-.entity goalstack16, goalstack17, goalstack18, goalstack19;
-.entity goalstack20, goalstack21, goalstack22, goalstack23;
-.entity goalstack24, goalstack25, goalstack26, goalstack27;
-.entity goalstack28, goalstack29, goalstack30, goalstack31;
-*/
-
-#define node_left  goalstack01
-#define node_right goalstack02
-#define node_front goalstack03
-#define node_back  goalstack04
-
-#define node_open    goalstack05
-#define node_closed  goalstack06
-#define node_blocked goalstack07
-
-
-
-float pointinbox(vector point,vector box,float ssize)
-{
-    return 0;
-}
-#ifdef DEBUGPATHING
-
-/* TESTING */
-void pathlib_test_think()
-{
-    pathlib_showpath(self.enemy);
-
-    self.nextthink = time + 0.5;
-}
-void pathlib_test_dinit()
-{
-    entity path;
-    entity end;
-
-    if(self.target == "")
-    {
-        bprint("^1 ==== ERROR: pathlib_test with no target. ====\n");
-        remove(self);
-        return;
-    }
-
-    end = find(world,targetname,self.target);
-    if(!end)
-    {
-        bprint("^1 ==== ERROR: pathlib_test with no valid target. ====\n");
-        remove(self);
-        return;
-    }
-
-    setsize(self,'-50 -50 0','50 50 50');
-    path = pathlib_makepath(self.origin,end.origin, PFL_GROUNDSNAP,500,1.25,PT_QUICKSTAR);
-
-    if(!path)
-    {
-        bprint("^1 ==== ERROR: pathlib_test pathing fail ====\n");
-        remove(self);
-        return;
-    }
-
-    self.enemy = path;
-    self.think = pathlib_test_think;
-    self.nextthink = time + 0.5;
-
-}
-void spawnfunc_pathlib_test()
-{
-    self.think = pathlib_test_dinit;
-    self.nextthink = time + 2;
-}
-
-#endif
+#define PFL_GROUNDSNAP 1
+#define PFL_NOOPTIMIZE 2
+#define PFL_SUBPATH3D  4
+
+#define PT_QUICKSTAR 1
+#define PT_QUICKBOX  2
+#define PT_ASTAR     4  // FIXME NOT IMPLEMENTED
+
+//#define PATHLIB_RDFIELDS
+#ifdef PATHLIB_RDFIELDS
+    #define path_flags lip
+
+    #define path_subpathing_size autoswitch
+    #define path_subpathing_bboxexpand welcomemessage_time
+
+    #define path_next swampslug
+    #define path_prev lasertarget
+#else
+    .entity path_next;
+    .entity path_prev;
+
+    .float path_subpathing_size;
+    .float path_subpathing_bboxexpand;
+    .float path_flags;
+#endif
+
+#define pathlib_garbagetime 120
+#define pathib_maxdivide 512
+
+.float(vector start,vector end) path_validate;
+
+float pathlib_stdproc_path_validate(vector start,vector end)
+{
+    tracebox(start, self.mins, self.maxs, end, MOVE_WORLDONLY, self);
+
+    if(vlen(trace_endpos - end) < 32)
+        return 1;
+
+    return 0;
+}
+
+vector pathlib_groundsnap(vector where)
+{
+    float lsize;
+
+    lsize = vlen(self.mins - self.maxs) * 0.25;
+
+    traceline(where + ('0 0 1' * lsize) ,where - '0 0 10240',MOVE_WORLDONLY,self);
+
+    return trace_endpos + ('0 0 1' * lsize);
+
+}
+
+entity pathlib_createpoint(entity parent,entity next,entity first,vector where)
+{
+    entity point;
+
+    point = spawn();
+    point.classname = "path_node";
+
+    if(first)
+        point.owner = first;
+    else
+    {
+        point.classname = "path_master";
+        point.owner = point;
+    }
+
+    if(parent)
+        point.path_prev = parent;
+
+    if(next)
+    {
+        point.path_next = next;
+    }
+    else
+        point.classname = "path_end";
+
+    if (point.owner.path_flags & PFL_GROUNDSNAP)
+        where = pathlib_groundsnap(where);
+
+    setorigin(point,where);
+
+
+    return point;
+}
+
+/*
+float pathlib_scoresubpath(vector start,vector point,vector end,float minstep)
+{
+    float dist_stp,dist_pte,dist_total;
+
+    dist_stp = vlen(start - point);
+    if(dist_stp < minstep)
+        return 100000000;
+
+    dist_pte = vlen(point - end);
+    dist_total = dist_stp + dist_pte;
+    return -1;
+}
+*/
+
+vector pathlib_subpath_quickbox(entity start,vector vcrash,entity end,float maxsize)
+{
+
+    float step;
+    float pathscore;
+    float pathscore_best;
+    float dist;
+    vector bestpoint,point;
+    float zmin,zmax;
+    vector box;
+
+    pathscore_best = 0;
+
+    step = vlen(self.maxs - self.mins) * start.owner.path_subpathing_bboxexpand;
+
+    if(start.owner.path_flags & PFL_SUBPATH3D)
+    {
+        zmin = maxsize * -1;
+        zmax = maxsize;
+    }
+    else
+    {
+        zmin = 0;
+        zmax = 1;
+    }
+
+    for(box_z = zmin; box_z < zmax; box_z += step)
+    for(box_y = -maxsize; box_y < maxsize; box_y += step)
+    for(box_x = -maxsize; box_x < maxsize; box_x += step)
+    {
+
+        point = vcrash + box;
+
+        if(start.owner.path_flags & PFL_GROUNDSNAP)
+            point = pathlib_groundsnap(point);
+
+        if(self.path_validate(start.origin,point))
+        {
+            dist = vlen(start.origin - point);
+            if(dist > step)
+            {
+                pathscore = 1 / (dist + vlen(point - end.origin));
+                if(pathscore > pathscore_best)
+                {
+                    bestpoint = point;
+                    pathscore_best = pathscore;
+                }
+            }
+        }
+
+    }
+
+    if(pathscore_best != 0)
+        return bestpoint;
+
+    return start.origin;
+}
+
+vector pathlib_subpath_quickstar(entity start,entity end,float gridsize)
+{
+    vector point, best_point;
+    float  score, best_score;
+    vector dir_end;
+
+    dir_end   = normalize(end.origin - start.origin);
+    dir_end_x = dir_end_x * -1;
+
+    makevectors(dir_end);
+
+    best_score = 0;
+    score      = 0;
+
+    best_point = start.origin;
+
+    // Forward
+    point = start.origin + v_forward * gridsize;
+    point  = pathlib_groundsnap(point);
+    if(self.path_validate(start.origin,point)) score = 1 / vlen(point - end.origin);
+    if(score < best_score) { best_point = point; best_score = score; }
+    //te_lightning1(world,start.origin,point);
+
+    // Forward-right
+    point = start.origin + (v_forward + v_right * 0.5) * gridsize;
+    point  = pathlib_groundsnap(point);
+    if(self.path_validate(start.origin,point)) score = 1 / vlen(point - end.origin);
+    if(score < best_score) { best_point = point; best_score = score; }
+    //te_lightning1(world,start.origin,point);
+
+
+    // Forward-left
+    point = start.origin + (v_forward - v_right * 0.5) * gridsize;
+    point  = pathlib_groundsnap(point);
+    if(self.path_validate(start.origin,point)) score = 1 / vlen(point - end.origin);
+    if(score < best_score) { best_point = point; best_score = score; }
+    //te_lightning1(world,start.origin,point);
+
+
+    // Right
+    point = start.origin + v_right * gridsize;
+    point  = pathlib_groundsnap(point);
+    if(self.path_validate(start.origin,point)) score = 1 / vlen(point - end.origin);
+    if(score < best_score) { best_point = point; best_score = score; }
+    //te_lightning1(world,start.origin,point);
+
+    // Left
+    point = start.origin - v_right * gridsize;
+    point  = pathlib_groundsnap(point);
+    if(self.path_validate(start.origin,point)) score = 1 / vlen(point - end.origin);
+    if(score < best_score) { best_point = point; best_score = score; }
+    //te_lightning1(world,start.origin,point);
+
+    // Back
+    point = start.origin - v_forward * gridsize;
+    point  = pathlib_groundsnap(point);
+    if(self.path_validate(start.origin,point)) score = 1 / vlen(point - end.origin);
+    if(score < best_score) { best_point = point; best_score = score; }
+    //te_lightning1(world,start.origin,point);
+
+    // Back-right
+
+    point = start.origin - (v_forward + v_right * 0.5) * gridsize;
+    point  = pathlib_groundsnap(point);
+    if(self.path_validate(start.origin,point)) score = 1 / vlen(point - end.origin);
+    if(score < best_score) { best_point = point; best_score = score; }
+    //te_lightning1(world,start.origin,point);
+
+    // Back-left
+    point = start.origin - (v_forward - v_right * 0.5) * gridsize;
+    point  = pathlib_groundsnap(point);
+    if(self.path_validate(start.origin,point)) score = 1 / vlen(point - end.origin);
+    if(score < best_score) { best_point = point; best_score = score; }
+    //te_lightning1(world,start.origin,point);
+
+    return(best_point);
+}
+
+float pathlib_path(entity start,entity end,float pathing_method)
+{
+    vector vcrash;
+    vector subpath_point;
+    entity subpoint;
+
+    // Fail.
+    if(start.cnt > pathib_maxdivide)
+    {
+        bprint("To many segments!\n");
+        return 0;
+    }
+
+    if(self.path_validate(start.origin,end.origin))
+        return 1;
+
+    vcrash = trace_endpos;
+
+    switch(pathing_method)
+    {
+        case PT_QUICKSTAR:
+            subpath_point = pathlib_subpath_quickstar(start,end,start.owner.path_subpathing_size);
+            break;
+        case PT_QUICKBOX:
+            subpath_point = pathlib_subpath_quickbox(start,vcrash,end,start.owner.path_subpathing_size);
+            break;
+        case PT_ASTAR:
+            dprint("Pathlib error: A* pathing not implemented!\n");
+            return 0;
+        default:
+            subpath_point = pathlib_subpath_quickstar(start,end,start.owner.path_subpathing_size);
+            dprint("Pathlib warning: unknown pathing method, using quickstar!\n");
+            break;
+    }
+
+    if(subpath_point == start.origin)
+        return 0; // Fail.
+
+    subpoint = pathlib_createpoint(start,end,start.owner,subpath_point);
+
+    subpoint.cnt = start.cnt +1;
+    start.path_next = subpoint;
+    end.path_prev = subpoint;
+
+    if(self.path_validate(start.origin,end.origin))
+        return 1;
+
+    return pathlib_path(subpoint,end,pathing_method);
+}
+
+void pathlib_path_optimize(entity start,entity end)
+{
+    entity point,point_tmp;
+    float c;
+
+    point = start.path_next;
+
+    while(point != end)
+    {
+        ++c;
+        if(c > 5000)
+        {
+            dprint("pathlib_path_optimize runaway!\n");
+            return;
+        }
+
+        point_tmp = point;
+        point = point.path_next;
+        if(self.path_validate(point_tmp.path_prev.origin,point_tmp.path_next.origin))
+        {
+
+            point_tmp.path_next.path_prev = point_tmp.path_prev;
+            point_tmp.path_prev.path_next = point_tmp.path_next;
+            remove(point_tmp);
+        }
+    }
+}
+
+void pathlib_deletepath(entity start)
+{
+    entity e;
+
+    e = findchainentity(owner, start);
+    while(e)
+    {
+        e.think = SUB_Remove;
+        e.nextthink = time;
+        e = e.chain;
+    }
+}
+
+//#define DEBUGPATHING
+#ifdef DEBUGPATHING
+void pathlib_showpath(entity start)
+{
+    entity e;
+    e = start;
+    while(e.path_next)
+    {
+        te_lightning1(e,e.origin,e.path_next.origin);
+        e = e.path_next;
+    }
+}
+
+void path_dbg_think()
+{
+    pathlib_showpath(self);
+    self.nextthink = time + 1;
+}
+#endif
+/**
+    Pathing from 'from' to 'to'
+**/
+entity pathlib_makepath(vector from, vector to,float pathflags,float subpathing_size, float subpathing_bboxexpand,float pathing_method)
+{
+    entity e_start,e_end;
+
+    if(!self.path_validate)
+        self.path_validate = pathlib_stdproc_path_validate;
+
+
+    if(subpathing_size < 10)
+        subpathing_size = 500;
+
+    if(subpathing_bboxexpand < 1)
+        subpathing_bboxexpand = 1;
+
+    if(pathflags & PFL_GROUNDSNAP)
+    {
+        from = pathlib_groundsnap(from);
+        to = pathlib_groundsnap(to);
+    }
+
+    e_start = pathlib_createpoint(world,world,world,from);
+    e_start.path_flags = pathflags;
+
+    e_start.path_subpathing_size = subpathing_size;
+    e_start.path_subpathing_bboxexpand = subpathing_bboxexpand;
+
+    e_start.owner = e_start;
+
+    e_end = pathlib_createpoint(e_start,world,e_start,to);
+    e_start.path_next = e_end;
+    e_start.cnt = 0;
+
+    if(!pathlib_path(e_start,e_end,pathing_method))
+    {
+        bprint("Fail, Fail, Fail!\n");
+        pathlib_deletepath(e_start);
+        remove(e_start);
+
+        return world;
+    }
+
+    pathlib_path_optimize(e_start,e_end);
+
+#ifdef DEBUGPATHING
+    e_start.think = path_dbg_think;
+    e_start.nextthink = time + 1;
+#endif
+
+    return e_start;
+
+}
+
+/*
+.entity goalcurrent, goalstack01, goalstack02, goalstack03;
+.entity goalstack04, goalstack05, goalstack06, goalstack07;
+.entity goalstack08, goalstack09, goalstack10, goalstack11;
+.entity goalstack12, goalstack13, goalstack14, goalstack15;
+.entity goalstack16, goalstack17, goalstack18, goalstack19;
+.entity goalstack20, goalstack21, goalstack22, goalstack23;
+.entity goalstack24, goalstack25, goalstack26, goalstack27;
+.entity goalstack28, goalstack29, goalstack30, goalstack31;
+*/
+
+#define node_left  goalstack01
+#define node_right goalstack02
+#define node_front goalstack03
+#define node_back  goalstack04
+
+#define node_open    goalstack05
+#define node_closed  goalstack06
+#define node_blocked goalstack07
+
+
+
+float pointinbox(vector point,vector box,float ssize)
+{
+    return 0;
+}
+#ifdef DEBUGPATHING
+
+/* TESTING */
+void pathlib_test_think()
+{
+    pathlib_showpath(self.enemy);
+
+    self.nextthink = time + 0.5;
+}
+void pathlib_test_dinit()
+{
+    entity path;
+    entity end;
+
+    if(self.target == "")
+    {
+        bprint("^1 ==== ERROR: pathlib_test with no target. ====\n");
+        remove(self);
+        return;
+    }
+
+    end = find(world,targetname,self.target);
+    if(!end)
+    {
+        bprint("^1 ==== ERROR: pathlib_test with no valid target. ====\n");
+        remove(self);
+        return;
+    }
+
+    setsize(self,'-50 -50 0','50 50 50');
+    path = pathlib_makepath(self.origin,end.origin, PFL_GROUNDSNAP,500,1.25,PT_QUICKSTAR);
+
+    if(!path)
+    {
+        bprint("^1 ==== ERROR: pathlib_test pathing fail ====\n");
+        remove(self);
+        return;
+    }
+
+    self.enemy = path;
+    self.think = pathlib_test_think;
+    self.nextthink = time + 0.5;
+
+}
+void spawnfunc_pathlib_test()
+{
+    self.think = pathlib_test_dinit;
+    self.nextthink = time + 2;
+}
+
+#endif

Modified: trunk/data/qcsrc/server/progs.src
===================================================================
--- trunk/data/qcsrc/server/progs.src	2009-03-11 20:45:17 UTC (rev 6104)
+++ trunk/data/qcsrc/server/progs.src	2009-03-11 21:39:56 UTC (rev 6105)
@@ -81,8 +81,28 @@
 
 g_triggers.qc
 
+// model animation files
+../../models/weapons/w_campingrifle.qh
+../../models/weapons/w_crylink.qh
+../../models/weapons/w_electro.qh
+../../models/weapons/w_flamethrower.qh
+../../models/weapons/w_gl.qh
+../../models/weapons/w_hagar.qh
+../../models/weapons/w_hlac.qh
+../../models/weapons/w_hlacmod.qh
+../../models/weapons/w_hookgun.qh
+../../models/weapons/w_laser.qh
+../../models/weapons/w_minstanex.qh
+../../models/weapons/w_nex.qh
+../../models/weapons/w_porto.qh
+../../models/weapons/w_rl.qh
+../../models/weapons/w_seeker.qh
+../../models/weapons/w_shotgun.qh
+../../models/weapons/w_uzi.qh
+
 cl_weaponsystem.qc
 w_common.qc
+
 w_laser.qc
 w_shotgun.qc
 w_uzi.qc

Modified: trunk/data/qcsrc/server/steerlib.qc
===================================================================
--- trunk/data/qcsrc/server/steerlib.qc	2009-03-11 20:45:17 UTC (rev 6104)
+++ trunk/data/qcsrc/server/steerlib.qc	2009-03-11 21:39:56 UTC (rev 6105)
@@ -1,448 +1,448 @@
-/**
-    Uniform pull towards a point
-**/
-vector steerlib_pull(vector point)
-{
-    return normalize(point - self.origin);
-}
-
-/**
-    Uniform push from a point
-**/
-vector steerlib_push(vector point)
-{
-    return normalize(self.origin - point);
-}
-
-/**
-    Pull toward a point, The further away, the stronger the pull.
-**/
-vector steerlib_arrive(vector point,float maximal_distance)
-{
-    float distance;
-    vector direction;
-
-    distance = bound(0.001,vlen(self.origin - point),maximal_distance);
-    direction = normalize(point - self.origin);
-    return  direction * (distance / maximal_distance);
-}
-
-/**
-    Pull toward a point increasing the pull the closer we get
-**/
-vector steerlib_attract(vector point, float maximal_distance)
-{
-    float distance;
-    vector direction;
-
-    distance = bound(0.001,vlen(self.origin - point),maximal_distance);
-    direction = normalize(point - self.origin);
-
-    return  direction * (1-(distance / maximal_distance));
-}
-
-vector steerlib_attract2(vector point, float min_influense,float max_distance,float max_influense)
-{
-    float distance;
-    vector direction;
-    float influense;
-
-    distance  = bound(0.00001,vlen(self.origin - point),max_distance);
-    direction = normalize(point - self.origin);
-
-    influense = 1 - (distance / max_distance);
-    influense = min_influense + (influense * (max_influense - min_influense));
-
-    return  direction * influense;
-}
-
-/*
-vector steerlib_attract2(vector point, float maximal_distance,float min_influense,float max_influense,float distance)
-{
-    //float distance;
-    vector current_direction;
-    vector target_direction;
-    float i_target,i_current;
-
-    if(!distance)
-        distance = vlen(self.origin - point);
-
-    distance = bound(0.001,distance,maximal_distance);
-
-    target_direction = normalize(point - self.origin);
-    current_direction = normalize(self.velocity);
-
-    i_target = bound(min_influense,(1-(distance / maximal_distance)),max_influense);
-    i_current = 1 - i_target;
-
-    // i_target = bound(min_influense,(1-(distance / maximal_distance)),max_influense);
-
-    string s;
-    s = ftos(i_target);
-    bprint("IT: ",s,"\n");
-    s = ftos(i_current);
-    bprint("IC  : ",s,"\n");
-
-    return  normalize((target_direction * i_target) + (current_direction * i_current));
-}
-*/
-/**
-    Move away from a point.
-**/
-vector steerlib_repell(vector point,float maximal_distance)
-{
-    float distance;
-    vector direction;
-
-    distance = bound(0.001,vlen(self.origin - point),maximal_distance);
-    direction = normalize(self.origin - point);
-
-    return  direction * (1-(distance / maximal_distance));
-}
-
-/**
-    Try to keep at ideal_distance away from point
-**/
-vector steerlib_standoff(vector point,float ideal_distance)
-{
-    float distance;
-    vector direction;
-
-    distance = vlen(self.origin - point);
-
-
-    if(distance < ideal_distance)
-    {
-        direction = normalize(self.origin - point);
-        return direction * (distance / ideal_distance);
-    }
-
-    direction = normalize(point - self.origin);
-    return direction * (ideal_distance / distance);
-
-}
-
-/**
-    A random heading in a forward halfcicrle
-
-    use like:
-    self.target = steerlib_waner(256,32,self.target)
-
-    where range is the cicrle radius and tresh is how close we need to be to pick a new heading.
-**/
-vector steerlib_waner(float range,float tresh,vector oldpoint)
-{
-    vector wander_point;
-    wander_point = v_forward - oldpoint;
-
-    if (vlen(wander_point) > tresh)
-        return oldpoint;
-
-    range = bound(0,range,1);
-
-    wander_point = self.origin + v_forward * 128;
-    wander_point = wander_point + randomvec() * (range * 128) - randomvec() * (range * 128);
-
-    return normalize(wander_point - self.origin);
-}
-
-/**
-    Dodge a point. dont work to well.
-**/
-vector steerlib_dodge(vector point,vector dodge_dir,float min_distance)
-{
-    float distance;
-
-    distance = max(vlen(self.origin - point),min_distance);
-
-    return dodge_dir * (min_distance/distance);
-}
-
-/**
-    flocking by .flock_id
-    Group will move towards the unified direction while keeping close to eachother.
-**/
-.float flock_id;
-vector steerlib_flock(float radius, float standoff,float separation_force,float flock_force)
-{
-    entity flock_member;
-    vector push,pull;
-    float ccount;
-
-    flock_member = findradius(self.origin,radius);
-    while(flock_member)
-    {
-        if(flock_member != self)
-        if(flock_member.flock_id == self.flock_id)
-        {
-            ++ccount;
-            push = push + (steerlib_repell(flock_member.origin,standoff) * separation_force);
-            pull = pull + (steerlib_arrive(flock_member.origin + flock_member.velocity,radius) * flock_force);
-        }
-        flock_member = flock_member.chain;
-    }
-    return push + (pull* (1 / ccount));
-}
-
-/**
-    All members want to be in the center, and keep away from eachother.
-    The furtehr form the center the more they want to be there.
-
-    This results in a aligned movement (?!) much like flocking.
-**/
-vector steerlib_swarm(float radius, float standoff,float separation_force,float swarm_force)
-{
-    entity swarm_member;
-    vector force,center;
-    float ccount;
-
-    swarm_member = findradius(self.origin,radius);
-
-    while(swarm_member)
-    {
-        if(swarm_member.flock_id == self.flock_id)
-        {
-            ++ccount;
-            center = center + swarm_member.origin;
-            force = force + (steerlib_repell(swarm_member.origin,standoff) * separation_force);
-        }
-        swarm_member = swarm_member.chain;
-    }
-
-    center = center * (1 / ccount);
-    force = force + (steerlib_arrive(center,radius) * swarm_force);
-
-    return force;
-}
-
-/**
-    Steer towards the direction least obstructed.
-    Run four tracelines in a forward funnel, bias each diretion negative if something is found there.
-**/
-vector steerlib_traceavoid(float pitch,float length)
-{
-    vector vup_left,vup_right,vdown_left,vdown_right;
-    float fup_left,fup_right,fdown_left,fdown_right;
-    vector upwish,downwish,leftwish,rightwish;
-    vector v_left,v_down;
-
-    v_left = v_right * -1;
-    v_down = v_up * -1;
-
-    vup_left = (v_forward + (v_left * pitch + v_up * pitch)) * length;
-    traceline(self.origin, self.origin +  vup_left,MOVE_NOMONSTERS,self);
-    fup_left = trace_fraction;
-
-    //te_lightning1(world,self.origin, trace_endpos);
-
-    vup_right = (v_forward + (v_right * pitch + v_up * pitch)) * length;
-    traceline(self.origin,self.origin + vup_right ,MOVE_NOMONSTERS,self);
-    fup_right = trace_fraction;
-
-    //te_lightning1(world,self.origin, trace_endpos);
-
-    vdown_left = (v_forward + (v_left * pitch + v_down * pitch)) * length;
-    traceline(self.origin,self.origin + vdown_left,MOVE_NOMONSTERS,self);
-    fdown_left = trace_fraction;
-
-    //te_lightning1(world,self.origin, trace_endpos);
-
-    vdown_right = (v_forward + (v_right * pitch + v_down * pitch)) * length;
-    traceline(self.origin,self.origin + vdown_right,MOVE_NOMONSTERS,self);
-    fdown_right = trace_fraction;
-
-    //te_lightning1(world,self.origin, trace_endpos);
-
-    upwish    = v_up    * (fup_left   + fup_right);
-    downwish  = v_down  * (fdown_left + fdown_right);
-    leftwish  = v_left  * (fup_left   + fdown_left);
-    rightwish = v_right * (fup_right  + fdown_right);
-
-    return (upwish+leftwish+downwish+rightwish) * 0.25;
-
-}
-
-
-
-//////////////////////////////////////////////
-//     Testting                             //
-// Everything below this point is a mess :D //
-//////////////////////////////////////////////
-//#define TLIBS_TETSLIBS
-#ifdef TLIBS_TETSLIBS
-void flocker_die()
-{
-	sound (self, CHAN_PROJECTILE, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
-
-	pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1);
-
-    self.owner.cnt += 1;
-    self.owner = world;
-
-    self.nextthink = time;
-    self.think = SUB_Remove;
-}
-
-
-void flocker_think()
-{
-    vector dodgemove,swarmmove;
-    vector reprellmove,wandermove,newmove;
-
-    self.angles_x = self.angles_x * -1;
-    makevectors(self.angles);
-    self.angles_x = self.angles_x * -1;
-
-    dodgemove   = steerlib_traceavoid(0.35,1000);
-    swarmmove   = steerlib_flock(500,75,700,500);
-    reprellmove = steerlib_repell(self.owner.enemy.origin+self.enemy.velocity,2000) * 700;
-
-    if(vlen(dodgemove) == 0)
-    {
-        self.pos1 = steerlib_waner(0.5,0.1,self.pos1);
-        wandermove  = self.pos1 * 50;
-    }
-    else
-        self.pos1 = normalize(self.velocity);
-
-    dodgemove = dodgemove * vlen(self.velocity) * 5;
-
-    newmove = swarmmove + reprellmove + wandermove + dodgemove;
-    self.velocity = movelib_inertmove_byspeed(newmove,300,0.2,0.9);
-    //self.velocity  = movelib_inertmove(dodgemove,0.65);
-
-    self.velocity = movelib_dragvec(0.01,0.6);
-
-    self.angles = vectoangles(self.velocity);
-
-    if(self.health <= 0)
-        flocker_die();
-    else
-        self.nextthink = time + 0.1;
-}
-
-
-void spawn_flocker()
-{
-    entity flocker;
-
-    flocker = spawn ();
-
-    setorigin(flocker, self.origin + '0 0 32');
-    setmodel (flocker, "models/turrets/rocket.md3");
-    setsize (flocker, '-3 -3 -3', '3 3 3');
-
-    flocker.flock_id   = self.flock_id;
-    flocker.classname  = "flocker";
-    flocker.owner      = self;
-    flocker.think      = flocker_think;
-    flocker.nextthink  = time + random() * 5;
-    flocker.solid      = SOLID_BBOX;
-    flocker.movetype   = MOVETYPE_BOUNCEMISSILE;
-    flocker.effects    = EF_LOWPRECISION;
-    flocker.velocity   = randomvec() * 300;
-    flocker.angles     = vectoangles(flocker.velocity);
-    flocker.health     = 10;
-    flocker.pos1      = normalize(flocker.velocity + randomvec() * 0.1);
-
-    self.cnt = self.cnt -1;
-
-}
-
-void flockerspawn_think()
-{
-
-
-    if(self.cnt > 0)
-        spawn_flocker();
-
-    self.nextthink = time + self.delay;
-
-}
-
-void flocker_hunter_think()
-{
-    vector dodgemove,attractmove,newmove;
-    entity e,ee;
-    float d,bd;
-
-    self.angles_x = self.angles_x * -1;
-    makevectors(self.angles);
-    self.angles_x = self.angles_x * -1;
-
-    if(self.enemy)
-    if(vlen(self.enemy.origin - self.origin) < 64)
-    {
-        ee = self.enemy;
-        ee.health = -1;
-        self.enemy = world;
-
-    }
-
-    if(!self.enemy)
-    {
-        e = findchainfloat(flock_id,self.flock_id);
-        while(e)
-        {
-            d = vlen(self.origin - e.origin);
-
-            if(e != self.owner)
-            if(e != ee)
-            if(d > bd)
-            {
-                self.enemy = e;
-                bd = d;
-            }
-            e = e.chain;
-        }
-    }
-
-    if(self.enemy)
-        attractmove = steerlib_attract(self.enemy.origin+self.enemy.velocity * 0.1,5000) * 1250;
-    else
-        attractmove = normalize(self.velocity) * 200;
-
-    dodgemove = steerlib_traceavoid(0.35,1500) * vlen(self.velocity);
-
-    newmove = dodgemove + attractmove;
-    self.velocity = movelib_inertmove_byspeed(newmove,1250,0.3,0.7);
-    self.velocity = movelib_dragvec(0.01,0.5);
-
-
-    self.angles = vectoangles(self.velocity);
-    self.nextthink = time + 0.1;
-}
-
-
-float globflockcnt;
-void spawnfunc_flockerspawn()
-{
-    precache_model ( "models/turrets/rocket.md3");
-    precache_model("models/turrets/c512.md3");
-    ++globflockcnt;
-
-    if(!self.cnt)      self.cnt = 20;
-    if(!self.delay)    self.delay = 0.25;
-    if(!self.flock_id) self.flock_id = globflockcnt;
-
-    self.think     = flockerspawn_think;
-    self.nextthink = time + 0.25;
-
-    self.enemy = spawn();
-
-    setmodel(self.enemy, "models/turrets/rocket.md3");
-    setorigin(self.enemy,self.origin + '0 0 768' + (randomvec() * 128));
-
-    self.enemy.classname = "FLock Hunter";
-    self.enemy.scale     = 3;
-    self.enemy.effects   = EF_LOWPRECISION;
-    self.enemy.movetype  = MOVETYPE_BOUNCEMISSILE;
-    self.enemy.solid     = SOLID_BBOX;
-    self.enemy.think     = flocker_hunter_think;
-    self.enemy.nextthink = time + 10;
-    self.enemy.flock_id  = self.flock_id;
-    self.enemy.owner     = self;
-}
-#endif
-
-
+/**
+    Uniform pull towards a point
+**/
+vector steerlib_pull(vector point)
+{
+    return normalize(point - self.origin);
+}
+
+/**
+    Uniform push from a point
+**/
+vector steerlib_push(vector point)
+{
+    return normalize(self.origin - point);
+}
+
+/**
+    Pull toward a point, The further away, the stronger the pull.
+**/
+vector steerlib_arrive(vector point,float maximal_distance)
+{
+    float distance;
+    vector direction;
+
+    distance = bound(0.001,vlen(self.origin - point),maximal_distance);
+    direction = normalize(point - self.origin);
+    return  direction * (distance / maximal_distance);
+}
+
+/**
+    Pull toward a point increasing the pull the closer we get
+**/
+vector steerlib_attract(vector point, float maximal_distance)
+{
+    float distance;
+    vector direction;
+
+    distance = bound(0.001,vlen(self.origin - point),maximal_distance);
+    direction = normalize(point - self.origin);
+
+    return  direction * (1-(distance / maximal_distance));
+}
+
+vector steerlib_attract2(vector point, float min_influense,float max_distance,float max_influense)
+{
+    float distance;
+    vector direction;
+    float influense;
+
+    distance  = bound(0.00001,vlen(self.origin - point),max_distance);
+    direction = normalize(point - self.origin);
+
+    influense = 1 - (distance / max_distance);
+    influense = min_influense + (influense * (max_influense - min_influense));
+
+    return  direction * influense;
+}
+
+/*
+vector steerlib_attract2(vector point, float maximal_distance,float min_influense,float max_influense,float distance)
+{
+    //float distance;
+    vector current_direction;
+    vector target_direction;
+    float i_target,i_current;
+
+    if(!distance)
+        distance = vlen(self.origin - point);
+
+    distance = bound(0.001,distance,maximal_distance);
+
+    target_direction = normalize(point - self.origin);
+    current_direction = normalize(self.velocity);
+
+    i_target = bound(min_influense,(1-(distance / maximal_distance)),max_influense);
+    i_current = 1 - i_target;
+
+    // i_target = bound(min_influense,(1-(distance / maximal_distance)),max_influense);
+
+    string s;
+    s = ftos(i_target);
+    bprint("IT: ",s,"\n");
+    s = ftos(i_current);
+    bprint("IC  : ",s,"\n");
+
+    return  normalize((target_direction * i_target) + (current_direction * i_current));
+}
+*/
+/**
+    Move away from a point.
+**/
+vector steerlib_repell(vector point,float maximal_distance)
+{
+    float distance;
+    vector direction;
+
+    distance = bound(0.001,vlen(self.origin - point),maximal_distance);
+    direction = normalize(self.origin - point);
+
+    return  direction * (1-(distance / maximal_distance));
+}
+
+/**
+    Try to keep at ideal_distance away from point
+**/
+vector steerlib_standoff(vector point,float ideal_distance)
+{
+    float distance;
+    vector direction;
+
+    distance = vlen(self.origin - point);
+
+
+    if(distance < ideal_distance)
+    {
+        direction = normalize(self.origin - point);
+        return direction * (distance / ideal_distance);
+    }
+
+    direction = normalize(point - self.origin);
+    return direction * (ideal_distance / distance);
+
+}
+
+/**
+    A random heading in a forward halfcicrle
+
+    use like:
+    self.target = steerlib_waner(256,32,self.target)
+
+    where range is the cicrle radius and tresh is how close we need to be to pick a new heading.
+**/
+vector steerlib_waner(float range,float tresh,vector oldpoint)
+{
+    vector wander_point;
+    wander_point = v_forward - oldpoint;
+
+    if (vlen(wander_point) > tresh)
+        return oldpoint;
+
+    range = bound(0,range,1);
+
+    wander_point = self.origin + v_forward * 128;
+    wander_point = wander_point + randomvec() * (range * 128) - randomvec() * (range * 128);
+
+    return normalize(wander_point - self.origin);
+}
+
+/**
+    Dodge a point. dont work to well.
+**/
+vector steerlib_dodge(vector point,vector dodge_dir,float min_distance)
+{
+    float distance;
+
+    distance = max(vlen(self.origin - point),min_distance);
+
+    return dodge_dir * (min_distance/distance);
+}
+
+/**
+    flocking by .flock_id
+    Group will move towards the unified direction while keeping close to eachother.
+**/
+.float flock_id;
+vector steerlib_flock(float radius, float standoff,float separation_force,float flock_force)
+{
+    entity flock_member;
+    vector push,pull;
+    float ccount;
+
+    flock_member = findradius(self.origin,radius);
+    while(flock_member)
+    {
+        if(flock_member != self)
+        if(flock_member.flock_id == self.flock_id)
+        {
+            ++ccount;
+            push = push + (steerlib_repell(flock_member.origin,standoff) * separation_force);
+            pull = pull + (steerlib_arrive(flock_member.origin + flock_member.velocity,radius) * flock_force);
+        }
+        flock_member = flock_member.chain;
+    }
+    return push + (pull* (1 / ccount));
+}
+
+/**
+    All members want to be in the center, and keep away from eachother.
+    The furtehr form the center the more they want to be there.
+
+    This results in a aligned movement (?!) much like flocking.
+**/
+vector steerlib_swarm(float radius, float standoff,float separation_force,float swarm_force)
+{
+    entity swarm_member;
+    vector force,center;
+    float ccount;
+
+    swarm_member = findradius(self.origin,radius);
+
+    while(swarm_member)
+    {
+        if(swarm_member.flock_id == self.flock_id)
+        {
+            ++ccount;
+            center = center + swarm_member.origin;
+            force = force + (steerlib_repell(swarm_member.origin,standoff) * separation_force);
+        }
+        swarm_member = swarm_member.chain;
+    }
+
+    center = center * (1 / ccount);
+    force = force + (steerlib_arrive(center,radius) * swarm_force);
+
+    return force;
+}
+
+/**
+    Steer towards the direction least obstructed.
+    Run four tracelines in a forward funnel, bias each diretion negative if something is found there.
+**/
+vector steerlib_traceavoid(float pitch,float length)
+{
+    vector vup_left,vup_right,vdown_left,vdown_right;
+    float fup_left,fup_right,fdown_left,fdown_right;
+    vector upwish,downwish,leftwish,rightwish;
+    vector v_left,v_down;
+
+    v_left = v_right * -1;
+    v_down = v_up * -1;
+
+    vup_left = (v_forward + (v_left * pitch + v_up * pitch)) * length;
+    traceline(self.origin, self.origin +  vup_left,MOVE_NOMONSTERS,self);
+    fup_left = trace_fraction;
+
+    //te_lightning1(world,self.origin, trace_endpos);
+
+    vup_right = (v_forward + (v_right * pitch + v_up * pitch)) * length;
+    traceline(self.origin,self.origin + vup_right ,MOVE_NOMONSTERS,self);
+    fup_right = trace_fraction;
+
+    //te_lightning1(world,self.origin, trace_endpos);
+
+    vdown_left = (v_forward + (v_left * pitch + v_down * pitch)) * length;
+    traceline(self.origin,self.origin + vdown_left,MOVE_NOMONSTERS,self);
+    fdown_left = trace_fraction;
+
+    //te_lightning1(world,self.origin, trace_endpos);
+
+    vdown_right = (v_forward + (v_right * pitch + v_down * pitch)) * length;
+    traceline(self.origin,self.origin + vdown_right,MOVE_NOMONSTERS,self);
+    fdown_right = trace_fraction;
+
+    //te_lightning1(world,self.origin, trace_endpos);
+
+    upwish    = v_up    * (fup_left   + fup_right);
+    downwish  = v_down  * (fdown_left + fdown_right);
+    leftwish  = v_left  * (fup_left   + fdown_left);
+    rightwish = v_right * (fup_right  + fdown_right);
+
+    return (upwish+leftwish+downwish+rightwish) * 0.25;
+
+}
+
+
+
+//////////////////////////////////////////////
+//     Testting                             //
+// Everything below this point is a mess :D //
+//////////////////////////////////////////////
+//#define TLIBS_TETSLIBS
+#ifdef TLIBS_TETSLIBS
+void flocker_die()
+{
+	sound (self, CHAN_PROJECTILE, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
+
+	pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1);
+
+    self.owner.cnt += 1;
+    self.owner = world;
+
+    self.nextthink = time;
+    self.think = SUB_Remove;
+}
+
+
+void flocker_think()
+{
+    vector dodgemove,swarmmove;
+    vector reprellmove,wandermove,newmove;
+
+    self.angles_x = self.angles_x * -1;
+    makevectors(self.angles);
+    self.angles_x = self.angles_x * -1;
+
+    dodgemove   = steerlib_traceavoid(0.35,1000);
+    swarmmove   = steerlib_flock(500,75,700,500);
+    reprellmove = steerlib_repell(self.owner.enemy.origin+self.enemy.velocity,2000) * 700;
+
+    if(vlen(dodgemove) == 0)
+    {
+        self.pos1 = steerlib_waner(0.5,0.1,self.pos1);
+        wandermove  = self.pos1 * 50;
+    }
+    else
+        self.pos1 = normalize(self.velocity);
+
+    dodgemove = dodgemove * vlen(self.velocity) * 5;
+
+    newmove = swarmmove + reprellmove + wandermove + dodgemove;
+    self.velocity = movelib_inertmove_byspeed(newmove,300,0.2,0.9);
+    //self.velocity  = movelib_inertmove(dodgemove,0.65);
+
+    self.velocity = movelib_dragvec(0.01,0.6);
+
+    self.angles = vectoangles(self.velocity);
+
+    if(self.health <= 0)
+        flocker_die();
+    else
+        self.nextthink = time + 0.1;
+}
+
+
+void spawn_flocker()
+{
+    entity flocker;
+
+    flocker = spawn ();
+
+    setorigin(flocker, self.origin + '0 0 32');
+    setmodel (flocker, "models/turrets/rocket.md3");
+    setsize (flocker, '-3 -3 -3', '3 3 3');
+
+    flocker.flock_id   = self.flock_id;
+    flocker.classname  = "flocker";
+    flocker.owner      = self;
+    flocker.think      = flocker_think;
+    flocker.nextthink  = time + random() * 5;
+    flocker.solid      = SOLID_BBOX;
+    flocker.movetype   = MOVETYPE_BOUNCEMISSILE;
+    flocker.effects    = EF_LOWPRECISION;
+    flocker.velocity   = randomvec() * 300;
+    flocker.angles     = vectoangles(flocker.velocity);
+    flocker.health     = 10;
+    flocker.pos1      = normalize(flocker.velocity + randomvec() * 0.1);
+
+    self.cnt = self.cnt -1;
+
+}
+
+void flockerspawn_think()
+{
+
+
+    if(self.cnt > 0)
+        spawn_flocker();
+
+    self.nextthink = time + self.delay;
+
+}
+
+void flocker_hunter_think()
+{
+    vector dodgemove,attractmove,newmove;
+    entity e,ee;
+    float d,bd;
+
+    self.angles_x = self.angles_x * -1;
+    makevectors(self.angles);
+    self.angles_x = self.angles_x * -1;
+
+    if(self.enemy)
+    if(vlen(self.enemy.origin - self.origin) < 64)
+    {
+        ee = self.enemy;
+        ee.health = -1;
+        self.enemy = world;
+
+    }
+
+    if(!self.enemy)
+    {
+        e = findchainfloat(flock_id,self.flock_id);
+        while(e)
+        {
+            d = vlen(self.origin - e.origin);
+
+            if(e != self.owner)
+            if(e != ee)
+            if(d > bd)
+            {
+                self.enemy = e;
+                bd = d;
+            }
+            e = e.chain;
+        }
+    }
+
+    if(self.enemy)
+        attractmove = steerlib_attract(self.enemy.origin+self.enemy.velocity * 0.1,5000) * 1250;
+    else
+        attractmove = normalize(self.velocity) * 200;
+
+    dodgemove = steerlib_traceavoid(0.35,1500) * vlen(self.velocity);
+
+    newmove = dodgemove + attractmove;
+    self.velocity = movelib_inertmove_byspeed(newmove,1250,0.3,0.7);
+    self.velocity = movelib_dragvec(0.01,0.5);
+
+
+    self.angles = vectoangles(self.velocity);
+    self.nextthink = time + 0.1;
+}
+
+
+float globflockcnt;
+void spawnfunc_flockerspawn()
+{
+    precache_model ( "models/turrets/rocket.md3");
+    precache_model("models/turrets/c512.md3");
+    ++globflockcnt;
+
+    if(!self.cnt)      self.cnt = 20;
+    if(!self.delay)    self.delay = 0.25;
+    if(!self.flock_id) self.flock_id = globflockcnt;
+
+    self.think     = flockerspawn_think;
+    self.nextthink = time + 0.25;
+
+    self.enemy = spawn();
+
+    setmodel(self.enemy, "models/turrets/rocket.md3");
+    setorigin(self.enemy,self.origin + '0 0 768' + (randomvec() * 128));
+
+    self.enemy.classname = "FLock Hunter";
+    self.enemy.scale     = 3;
+    self.enemy.effects   = EF_LOWPRECISION;
+    self.enemy.movetype  = MOVETYPE_BOUNCEMISSILE;
+    self.enemy.solid     = SOLID_BBOX;
+    self.enemy.think     = flocker_hunter_think;
+    self.enemy.nextthink = time + 10;
+    self.enemy.flock_id  = self.flock_id;
+    self.enemy.owner     = self;
+}
+#endif
+
+

Modified: trunk/data/qcsrc/server/w_hlac.qc
===================================================================
--- trunk/data/qcsrc/server/w_hlac.qc	2009-03-11 20:45:17 UTC (rev 6104)
+++ trunk/data/qcsrc/server/w_hlac.qc	2009-03-11 21:39:56 UTC (rev 6105)
@@ -1,216 +1,216 @@
-.float HLAC_bulletcounter;
-void W_HLAC_Touch (void)
-{
-	PROJECTILE_TOUCH;
-
-	self.event_damage = SUB_Null;
-
-    RadiusDamage (self, self.owner, cvar("g_balance_hlac_primary_damage"), cvar("g_balance_hlac_primary_edgedamage"), cvar("g_balance_hlac_primary_radius"), world, cvar("g_balance_hlac_primary_force"), self.projectiledeathtype, other);
-
-	remove (self);
-}
-
-void W_HLAC_Touch2 (void)
-{
-	PROJECTILE_TOUCH;
-
-	self.event_damage = SUB_Null;
-
-    RadiusDamage (self, self.owner, cvar("g_balance_hlac_secondary_damage"), cvar("g_balance_hlac_secondary_edgedamage"), cvar("g_balance_hlac_secondary_radius"), world, cvar("g_balance_hlac_secondary_force"), self.projectiledeathtype, other);
-
-	remove (self);
-}
-
-void W_HLAC_Attack (void)
-{
-	local entity missile;
-    float spread;
-
-    if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
-    {
-        self.ammo_cells = self.ammo_cells - cvar("g_balance_hlac_primary_ammo");
-    }
-
-    spread = cvar("g_balance_hlac_primary_spread_min") + (cvar("g_balance_hlac_primary_spread_add") * self.HLAC_bulletcounter);
-    spread = min(spread,cvar("g_balance_hlac_primary_spread_max"));
-    if(self.crouch)
-        spread = spread * cvar("g_balance_hlac_primary_spread_crouchmod");
-
-	W_SetupShot (self, '24 8 -11', FALSE, 3, "weapons/lasergun_fire.wav");
-	pointparticles(particleeffectnum("laser_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
-	if (!g_norecoil)
-	{
-		self.punchangle_x = random () - 0.5;
-		self.punchangle_y = random () - 0.5;
-	}
-
-	missile = spawn ();
-	missile.owner = self;
-	missile.classname = "hlacbolt";
-	// missile.dmg = issecondary;
-	missile.bot_dodge = TRUE;
-
-    missile.bot_dodgerating = cvar("g_balance_hlac_primary_damage");
-
-	missile.movetype = MOVETYPE_FLY;
-	missile.solid = SOLID_BBOX;
-
-	setorigin (missile, w_shotorg);
-
-    missile.velocity = (w_shotdir + randomvec() * spread) * cvar("g_balance_hlac_primary_speed");
-
-	W_SetupProjectileVelocity(missile);
-	missile.angles = vectoangles (missile.velocity);
-
-	missile.touch = W_HLAC_Touch;
-	missile.think = SUB_Remove;
-
-    missile.nextthink = time + cvar("g_balance_hlac_primary_lifetime");
-
-	missile.flags = FL_PROJECTILE;
-	missile.projectiledeathtype = WEP_HLAC;
-
-	CSQCProjectile(missile, TRUE, PROJECTILE_HLAC, TRUE);
-}
-
-void W_HLAC_Attack2f (void)
-{
-	local entity missile;
-    float spread;
-
-    spread = cvar("g_balance_hlac_secondary_spread");
-
-
-    if(self.crouch)
-        spread = spread * cvar("g_balance_hlac_secondary_spread_crouchmod");
-
-	W_SetupShot (self, '25 8 -8', FALSE, 3, "weapons/lasergun_fire.wav");
-	pointparticles(particleeffectnum("laser_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
-
-	missile = spawn ();
-	missile.owner = self;
-	missile.classname = "hlacbolt";
-	// missile.dmg = issecondary;
-	missile.bot_dodge = TRUE;
-
-    missile.bot_dodgerating = cvar("g_balance_hlac_secondary_damage");
-
-	missile.movetype = MOVETYPE_FLY;
-	missile.solid = SOLID_BBOX;
-
-	setorigin (missile, w_shotorg);
-
-    missile.velocity = (w_shotdir + randomvec() * spread) * cvar("g_balance_hlac_secondary_speed");
-
-	W_SetupProjectileVelocity(missile);
-	missile.angles = vectoangles (missile.velocity);
-
-	missile.touch = W_HLAC_Touch2;
-	missile.think = SUB_Remove;
-
-    missile.nextthink = time + cvar("g_balance_hlac_secondary_lifetime");
-
-	missile.flags = FL_PROJECTILE;
-	missile.projectiledeathtype = WEP_HLAC | HITTYPE_SECONDARY;
-
-	CSQCProjectile(missile, TRUE, PROJECTILE_HLAC, TRUE);
-}
-
-void W_HLAC_Attack2 (void)
-{
-    float i;
-
-    if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
-    {
-        self.ammo_cells = self.ammo_cells - cvar("g_balance_hlac_secondary_ammo");
-    }
-
-    for(i=cvar("g_balance_hlac_secondary_shots");i>0;--i)
-        W_HLAC_Attack2f();
-
-	if (!g_norecoil)
-	{
-		self.punchangle_x = random () - 0.5;
-		self.punchangle_y = random () - 0.5;
-	}
-
-	// ATTACK_FINISHED(self) = time + cvar("g_balance_hlac_secondary_refire");
-}
-
-
-// weapon frames
-void HLAC_fire1_02()
-{
-	if(self.weapon != self.switchweapon) // abort immediately if switching
-	{
-		w_ready();
-		return;
-	}
-
-	if (self.BUTTON_ATCK)
-	{
-		if (!weapon_action(self.weapon, WR_CHECKAMMO1))
-		{
-			W_SwitchWeapon_Force(self, w_getbestweapon(self));
-			w_ready();
-			return;
-		}
-
-		ATTACK_FINISHED(self) = time + cvar("g_balance_hlac_primary_refire");
-		W_HLAC_Attack();
-		self.HLAC_bulletcounter = self.HLAC_bulletcounter + 1;
-        weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_hlac_primary_refire"), HLAC_fire1_02);
-	}
-	else
-	{
-		weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_hlac_primary_animtime"), w_ready);
-	}
-};
-
-void spawnfunc_weapon_hlac (void)
-{
-	weapon_defaultspawnfunc(WEP_HLAC);
-}
-
-float w_hlac(float req)
-{
-	if (req == WR_AIM)
-        self.BUTTON_ATCK = bot_aim(cvar("g_balance_hlac_primary_speed"), 0, cvar("g_balance_hlac_primary_lifetime"), FALSE);
-	else if (req == WR_THINK)
-	{
-		if (self.BUTTON_ATCK)
-		if (weapon_prepareattack(0, cvar("g_balance_hlac_primary_refire")))
-		{
-			self.HLAC_bulletcounter = 0;
-			W_HLAC_Attack();
-			weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_hlac_primary_refire"), HLAC_fire1_02);
-		}
-
-		if (self.BUTTON_ATCK2)
-		if (weapon_prepareattack(1, cvar("g_balance_hlac_secondary_refire")))
-		{
-			W_HLAC_Attack2();
-			weapon_thinkf(WFRAME_FIRE2, cvar("g_balance_hlac_secondary_animtime"), w_ready);
-		}
-
-	}
-	else if (req == WR_PRECACHE)
-	{
-        precache_model ("models/weapons/g_hlac.md3");
-		precache_model ("models/weapons/v_hlac.md3");
-		precache_model ("models/weapons/w_hlac.zym");
-		precache_sound ("weapons/lasergun_fire.wav");
-
-	}
-	else if (req == WR_SETUP)
-		weapon_setup(WEP_HLAC);
-	else if (req == WR_CHECKAMMO1)
-		return self.ammo_cells >= cvar("g_balance_hlac_primary_ammo");
-	else if (req == WR_CHECKAMMO2)
-		return self.ammo_cells >= cvar("g_balance_hlac_secondary_ammo");
-	else if (req == WR_SUICIDEMESSAGE)
-		w_deathtypestring = "should have used a smaller gun";
-	else if (req == WR_KILLMESSAGE)
-		w_deathtypestring = "was cut down by";
-	return TRUE;
-};
+.float HLAC_bulletcounter;
+void W_HLAC_Touch (void)
+{
+	PROJECTILE_TOUCH;
+
+	self.event_damage = SUB_Null;
+
+    RadiusDamage (self, self.owner, cvar("g_balance_hlac_primary_damage"), cvar("g_balance_hlac_primary_edgedamage"), cvar("g_balance_hlac_primary_radius"), world, cvar("g_balance_hlac_primary_force"), self.projectiledeathtype, other);
+
+	remove (self);
+}
+
+void W_HLAC_Touch2 (void)
+{
+	PROJECTILE_TOUCH;
+
+	self.event_damage = SUB_Null;
+
+    RadiusDamage (self, self.owner, cvar("g_balance_hlac_secondary_damage"), cvar("g_balance_hlac_secondary_edgedamage"), cvar("g_balance_hlac_secondary_radius"), world, cvar("g_balance_hlac_secondary_force"), self.projectiledeathtype, other);
+
+	remove (self);
+}
+
+void W_HLAC_Attack (void)
+{
+	local entity missile;
+    float spread;
+
+    if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
+    {
+        self.ammo_cells = self.ammo_cells - cvar("g_balance_hlac_primary_ammo");
+    }
+
+    spread = cvar("g_balance_hlac_primary_spread_min") + (cvar("g_balance_hlac_primary_spread_add") * self.HLAC_bulletcounter);
+    spread = min(spread,cvar("g_balance_hlac_primary_spread_max"));
+    if(self.crouch)
+        spread = spread * cvar("g_balance_hlac_primary_spread_crouchmod");
+
+	W_SetupShot (self, '24 8 -11', FALSE, 3, "weapons/lasergun_fire.wav");
+	pointparticles(particleeffectnum("laser_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
+	if (!g_norecoil)
+	{
+		self.punchangle_x = random () - 0.5;
+		self.punchangle_y = random () - 0.5;
+	}
+
+	missile = spawn ();
+	missile.owner = self;
+	missile.classname = "hlacbolt";
+	// missile.dmg = issecondary;
+	missile.bot_dodge = TRUE;
+
+    missile.bot_dodgerating = cvar("g_balance_hlac_primary_damage");
+
+	missile.movetype = MOVETYPE_FLY;
+	missile.solid = SOLID_BBOX;
+
+	setorigin (missile, w_shotorg);
+
+    missile.velocity = (w_shotdir + randomvec() * spread) * cvar("g_balance_hlac_primary_speed");
+
+	W_SetupProjectileVelocity(missile);
+	missile.angles = vectoangles (missile.velocity);
+
+	missile.touch = W_HLAC_Touch;
+	missile.think = SUB_Remove;
+
+    missile.nextthink = time + cvar("g_balance_hlac_primary_lifetime");
+
+	missile.flags = FL_PROJECTILE;
+	missile.projectiledeathtype = WEP_HLAC;
+
+	CSQCProjectile(missile, TRUE, PROJECTILE_HLAC, TRUE);
+}
+
+void W_HLAC_Attack2f (void)
+{
+	local entity missile;
+    float spread;
+
+    spread = cvar("g_balance_hlac_secondary_spread");
+
+
+    if(self.crouch)
+        spread = spread * cvar("g_balance_hlac_secondary_spread_crouchmod");
+
+	W_SetupShot (self, '25 8 -8', FALSE, 3, "weapons/lasergun_fire.wav");
+	pointparticles(particleeffectnum("laser_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
+
+	missile = spawn ();
+	missile.owner = self;
+	missile.classname = "hlacbolt";
+	// missile.dmg = issecondary;
+	missile.bot_dodge = TRUE;
+
+    missile.bot_dodgerating = cvar("g_balance_hlac_secondary_damage");
+
+	missile.movetype = MOVETYPE_FLY;
+	missile.solid = SOLID_BBOX;
+
+	setorigin (missile, w_shotorg);
+
+    missile.velocity = (w_shotdir + randomvec() * spread) * cvar("g_balance_hlac_secondary_speed");
+
+	W_SetupProjectileVelocity(missile);
+	missile.angles = vectoangles (missile.velocity);
+
+	missile.touch = W_HLAC_Touch2;
+	missile.think = SUB_Remove;
+
+    missile.nextthink = time + cvar("g_balance_hlac_secondary_lifetime");
+
+	missile.flags = FL_PROJECTILE;
+	missile.projectiledeathtype = WEP_HLAC | HITTYPE_SECONDARY;
+
+	CSQCProjectile(missile, TRUE, PROJECTILE_HLAC, TRUE);
+}
+
+void W_HLAC_Attack2 (void)
+{
+    float i;
+
+    if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
+    {
+        self.ammo_cells = self.ammo_cells - cvar("g_balance_hlac_secondary_ammo");
+    }
+
+    for(i=cvar("g_balance_hlac_secondary_shots");i>0;--i)
+        W_HLAC_Attack2f();
+
+	if (!g_norecoil)
+	{
+		self.punchangle_x = random () - 0.5;
+		self.punchangle_y = random () - 0.5;
+	}
+
+	// ATTACK_FINISHED(self) = time + cvar("g_balance_hlac_secondary_refire");
+}
+
+
+// weapon frames
+void HLAC_fire1_02()
+{
+	if(self.weapon != self.switchweapon) // abort immediately if switching
+	{
+		w_ready();
+		return;
+	}
+
+	if (self.BUTTON_ATCK)
+	{
+		if (!weapon_action(self.weapon, WR_CHECKAMMO1))
+		{
+			W_SwitchWeapon_Force(self, w_getbestweapon(self));
+			w_ready();
+			return;
+		}
+
+		ATTACK_FINISHED(self) = time + cvar("g_balance_hlac_primary_refire");
+		W_HLAC_Attack();
+		self.HLAC_bulletcounter = self.HLAC_bulletcounter + 1;
+        weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_hlac_primary_refire"), HLAC_fire1_02);
+	}
+	else
+	{
+		weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_hlac_primary_animtime"), w_ready);
+	}
+};
+
+void spawnfunc_weapon_hlac (void)
+{
+	weapon_defaultspawnfunc(WEP_HLAC);
+}
+
+float w_hlac(float req)
+{
+	if (req == WR_AIM)
+        self.BUTTON_ATCK = bot_aim(cvar("g_balance_hlac_primary_speed"), 0, cvar("g_balance_hlac_primary_lifetime"), FALSE);
+	else if (req == WR_THINK)
+	{
+		if (self.BUTTON_ATCK)
+		if (weapon_prepareattack(0, cvar("g_balance_hlac_primary_refire")))
+		{
+			self.HLAC_bulletcounter = 0;
+			W_HLAC_Attack();
+			weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_hlac_primary_refire"), HLAC_fire1_02);
+		}
+
+		if (self.BUTTON_ATCK2)
+		if (weapon_prepareattack(1, cvar("g_balance_hlac_secondary_refire")))
+		{
+			W_HLAC_Attack2();
+			weapon_thinkf(WFRAME_FIRE2, cvar("g_balance_hlac_secondary_animtime"), w_ready);
+		}
+
+	}
+	else if (req == WR_PRECACHE)
+	{
+        precache_model ("models/weapons/g_hlac.md3");
+		precache_model ("models/weapons/v_hlac.md3");
+		precache_model ("models/weapons/w_hlac.zym");
+		precache_sound ("weapons/lasergun_fire.wav");
+
+	}
+	else if (req == WR_SETUP)
+		weapon_setup(WEP_HLAC);
+	else if (req == WR_CHECKAMMO1)
+		return self.ammo_cells >= cvar("g_balance_hlac_primary_ammo");
+	else if (req == WR_CHECKAMMO2)
+		return self.ammo_cells >= cvar("g_balance_hlac_secondary_ammo");
+	else if (req == WR_SUICIDEMESSAGE)
+		w_deathtypestring = "should have used a smaller gun";
+	else if (req == WR_KILLMESSAGE)
+		w_deathtypestring = "was cut down by";
+	return TRUE;
+};

Modified: trunk/data/qcsrc/server/w_seeker.qc
===================================================================
--- trunk/data/qcsrc/server/w_seeker.qc	2009-03-11 20:45:17 UTC (rev 6104)
+++ trunk/data/qcsrc/server/w_seeker.qc	2009-03-11 21:39:56 UTC (rev 6105)
@@ -1,471 +1,471 @@
-//.float speed; = switchweapon
-//.float proxytime; = autoswitch
-//.float tl; = wait
-
-void Seeker_Missile_Explode ()
-{
-	self.event_damage = SUB_Null;
-	RadiusDamage (self, self.owner, cvar("g_balance_seeker_missile_damage"), cvar("g_balance_seeker_missile_edgedamage"), cvar("g_balance_seeker_missile_radius"), world, cvar("g_balance_seeker_missile_force"), self.projectiledeathtype, other);
-
-	remove (self);
-}
-
-void Seeker_Missile_Touch()
-{
-	PROJECTILE_TOUCH;
-
-	Seeker_Missile_Explode();
-}
-
-void Seeker_Missile_Think()
-{
-	entity e;
-	vector desireddir, olddir, newdir, eorg;
-	float turnrate;
-	float dist;
-
-	if (time > self.cnt)
-		Seeker_Missile_Explode();
-
-	if (!self.switchweapon)
-		self.switchweapon = cvar("g_balance_seeker_missile_speed");
-
-	if ((self.switchweapon < cvar("g_balance_seeker_missile_speed_max")) && cvar("g_balance_seeker_missile_speed_accel"))
-		self.switchweapon = self.switchweapon * cvar("g_balance_seeker_missile_accel");
-
-	if (self.switchweapon > cvar("g_balance_seeker_missile_speed_max"))
-		self.switchweapon = self.switchweapon * cvar("g_balance_seeker_missile_decel");
-
-	if (self.enemy != world)
-		if (self.enemy.takedamage != DAMAGE_AIM || self.enemy.deadflag != DEAD_NO)
-			self.enemy = world;
-
-	if (self.enemy != world)
-	{
-		e               = self.enemy;
-		eorg            = 0.5 * (e.absmin + e.absmax);
-		turnrate        = cvar("g_balance_seeker_missile_turnrate");		    // how fast to turn
-		desireddir      = normalize(eorg - self.origin);
-		olddir          = normalize(self.velocity);				            // get my current direction
-		dist            = vlen(eorg - self.origin);
-
-		// Do evasive maneuvers for world objects? ( this should be a cpu hog. :P )
-		if (cvar("g_balance_seeker_missile_smart") && (dist > cvar("g_balance_seeker_missile_smart_mindist")))
-		{
-			// Is it a better idea (shorter distance) to trace to the target itself?
-			if ( vlen(self.origin + olddir * self.wait) < dist)
-				traceline(self.origin, self.origin + olddir * self.wait, FALSE, self);
-			else
-				traceline(self.origin, eorg, FALSE, self);
-
-			// Setup adaptive tracelength
-			self.wait = vlen(self.origin - trace_endpos);
-			if (self.wait < cvar("g_balance_seeker_missile_smart_trace_min")) self.wait = cvar("g_balance_seeker_missile_smart_trace_min");
-			if (self.wait > cvar("g_balance_seeker_missile_smart_trace_max")) self.wait = cvar("g_balance_seeker_missile_smart_trace_max");
-
-			// Calc how important it is that we turn and add this to the desierd (enemy) dir.
-			desireddir  = normalize(((trace_plane_normal * (1 - trace_fraction)) + (desireddir * trace_fraction)) * 0.5);
-		}
-
-		//newdir = normalize((olddir + desireddir * turnrate) * 0.5);// take the average of the 2 directions; not the best method but simple & easy
-		newdir = normalize(olddir + desireddir * turnrate);// take the average of the 2 directions; not the best method but simple & easy
-
-		self.velocity = newdir * self.switchweapon;			                    // make me fly in the new direction at my flight speed
-	}
-
-	// Proxy
-	if (cvar("g_balance_seeker_missile_proxy"))
-	{
-		if ( dist <= cvar("g_balance_seeker_missile_proxy_maxrange"))
-		{
-			if (self.autoswitch == 0)
-			{
-				self.autoswitch = time + cvar("g_balance_seeker_missile_proxy_delay");
-			}
-			else
-			{
-				if (self.autoswitch <= time)
-				{
-					Seeker_Missile_Explode();
-					self.autoswitch = 0;
-				}
-			}
-		}
-		else
-		{
-			if (self.autoswitch != 0)
-				self.autoswitch = 0;
-		}
-	}
-	///////////////
-
-	if (self.enemy.deadflag != DEAD_NO)
-	{
-		self.enemy = world;
-		self.cnt = time + 1 + (random() * 4);
-		self.nextthink = self.cnt;
-		return;
-	}
-
-	self.angles = vectoangles(self.velocity);			// turn model in the new flight direction
-	self.nextthink = time + 0.05;
-
-	UpdateCSQCProjectile(self);
-}
-
-
-
-void Seeker_Missile_Damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
-{
-	float d;
-	d = damage;
-
-	if (self.owner == attacker)
-		d = d * 0.25;
-
-	self.health = self.health - d;
-
-	if (self.health <= 0)
-		W_PrepareExplosionByDamage(attacker, Seeker_Missile_Explode);
-}
-
-void Seeker_Missile_Animate()
-{
-	self.frame = self.frame +1;
-	self.nextthink = time + 0.05;
-
-	if (self.enemy != world)
-		if (self.enemy.takedamage != DAMAGE_AIM || self.enemy.deadflag != DEAD_NO)
-			self.enemy = world;
-
-	if(self.frame == 5)
-	{
-		self.think           = Seeker_Missile_Think;
-		self.nextthink       = time;// + cvar("g_balance_seeker_missile_activate_delay"); // cant dealy with csqc projectiles
-
-		if (cvar("g_balance_seeker_guided_proxy"))
-			self.movetype    = MOVETYPE_BOUNCEMISSILE;
-		else
-			self.movetype    = MOVETYPE_FLYMISSILE;
-	}
-
-	UpdateCSQCProjectile(self);
-}
-
-void Seeker_Fire_Missile(vector f_org)
-{
-	local entity missile;
-
-	if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
-		self.ammo_rockets = self.ammo_rockets - cvar("g_balance_seeker_missile_ammo");
-
-	makevectors(self.v_angle);
-	W_SetupShot (self, f_org, FALSE, 2, "weapons/seeker_fire.wav");
-	pointparticles(particleeffectnum("seeker_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
-
-	//self.detornator         = FALSE;
-
-	missile                 = spawn();
-	missile.owner           = self;
-	missile.classname       = "seeker_missile";
-	missile.bot_dodge       = TRUE;
-	missile.bot_dodgerating = cvar("g_balance_seeker_missile_damage");
-
-	missile.think           = Seeker_Missile_Animate;
-
-	//if (!cvar("g_balance_seeker_missile_proxy"))
-	missile.touch           = Seeker_Missile_Touch;
-
-	missile.event_damage    = Seeker_Missile_Damage;
-	missile.nextthink       = time;// + 0.2;// + cvar("g_balance_seeker_missile_activate_delay");
-	missile.cnt             = time + cvar("g_balance_seeker_missile_lifetime");
-	missile.enemy           = self.enemy;
-	missile.switchweapon           = cvar("g_balance_seeker_missile_speed");
-	missile.solid           = SOLID_BBOX;
-	missile.scale           = 2;
-	missile.takedamage          = DAMAGE_YES;
-	missile.damageforcescale    = 4;
-	missile.health              = 5;
-	missile.projectiledeathtype = WEP_SEEKER;
-
-	setorigin (missile, w_shotorg);
-	setsize (missile, '-2 -2 -2', '2 2 2');
-
-
-	missile.movetype    = MOVETYPE_FLYMISSILE;// MOVETYPE_TOSS;
-
-	missile.flags       = FL_PROJECTILE;
-
-	missile.velocity    = (w_shotdir + '0 0 0.45') * missile.switchweapon;
-	W_SetupProjectileVelocity(missile);
-
-	missile.switchweapon = vlen(missile.velocity);
-	missile.angles = vectoangles (missile.velocity);
-
-	CSQCProjectile(missile, FALSE, PROJECTILE_SEEKER, TRUE);
-}
-
-void Seeker_Vollycontroler_Think()
-{
-	float c;
-	entity oldself,oldenemy;
-	self.cnt = self.cnt - 1;
-
-	if ((self.owner.ammo_rockets < cvar("g_balance_seeker_missile_ammo")) || (self.cnt <= -1) || (self.owner.deadflag != DEAD_NO))
-	{
-		remove(self);
-		return;
-	}
-
-	self.nextthink = time + cvar("g_balance_seeker_missile_delay");
-
-	oldself = self;
-	self = self.owner;
-
-	oldenemy = self.enemy;
-	self.enemy = oldself.enemy;
-
-	c = mod(oldself.cnt, 4);
-	switch(c)
-	{
-		case 0:
-			Seeker_Fire_Missile('37.5 17 -22');
-			break;
-		case 1:
-			Seeker_Fire_Missile('37.5 9.5 -22');
-			break;
-		case 2:
-			Seeker_Fire_Missile('40 17 -29');
-			break;
-		case 3:
-		default:
-			Seeker_Fire_Missile('40 9.5 -29');
-			break;
-	}
-
-	self.enemy = oldenemy;
-	self = oldself;
-}
-
-void Seeker_Tag_Explode ()
-{
-	//if(other==self.owner)
-	//    return;
-	Damage_DamageInfo(self.origin, 0, 0, 0, self.velocity, WEP_SEEKER | HITTYPE_BOUNCE);
-
-	remove (self);
-}
-
-void Seeker_Tag_Damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
-{
-	self.health = self.health - damage;
-	if (self.health <= 0)
-		Seeker_Tag_Explode();
-}
-
-void Seeker_Tag_Think()
-{
-	remove(self);
-	return;
-}
-
-void Seeker_Tag_Touch()
-{
-	vector dir;
-	vector org2;
-
-	dir     = normalize (self.owner.origin - self.origin);
-	org2    = findbetterlocation (self.origin, 8);
-
-	te_knightspike(org2);
-
-	self.event_damage = SUB_Null;
-	Damage_DamageInfo(self.origin, 0, 0, 0, self.velocity, WEP_SEEKER | HITTYPE_HEADSHOT);
-
-	if (other.takedamage == DAMAGE_AIM && other.deadflag == DEAD_NO)
-	{
-		entity e;
-		e           = spawn();
-		e.cnt       = cvar("g_balance_seeker_missile_count");
-		e.owner     = self.owner;
-		e.enemy     = other;
-		e.think     = Seeker_Vollycontroler_Think;
-		e.nextthink = time;
-
-		//sprint(self.owner, "^1Target lock ^3[^7 ",other.netname, " ^3]^1 acquired - autofire activated.\n");
-		//sprint(other,"^1You are targeted!\n");
-
-		// stuffcmd(other,"play2 weapons/zany-alarm4.ogg\n");
-		// stuffcmd(self.owner, "play2 weapons/zany-lock4.ogg\n");
-	}
-
-	remove(self);
-	return;
-}
-
-
-
-void Seeker_Fire_Tag()
-{
-	local entity missile;
-	if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
-		self.ammo_rockets = self.ammo_rockets - cvar("g_balance_seeker_tag_ammo");
-
-	W_SetupShot (self, '56 13 -15', FALSE, 2, "weapons/tag_fire.wav");
-
-	missile                 = spawn();
-	missile.owner           = self;
-	missile.classname       = "seeker_tag";
-	missile.bot_dodge       = TRUE;
-	missile.bot_dodgerating = 50;
-	missile.touch           = Seeker_Tag_Touch;
-	missile.think           = Seeker_Tag_Think;
-	missile.nextthink       = time + 15;
-	missile.movetype        = MOVETYPE_FLY;
-	missile.solid           = SOLID_BBOX;
-	missile.owner           = self;
-
-	missile.takedamage       = DAMAGE_YES;
-	missile.event_damage    = Seeker_Tag_Explode;
-	missile.health          = 5;
-
-	setorigin (missile, w_shotorg);
-
-	missile.flags       = FL_PROJECTILE;
-
-	missile.velocity    = w_shotdir  * cvar("g_balance_seeker_tag_speed");
-	missile.movetype    = MOVETYPE_BOUNCEMISSILE;
-	W_SetupProjectileVelocity(missile);
-	missile.angles = vectoangles (missile.velocity);
-
-	CSQCProjectile(missile, TRUE, PROJECTILE_TAG, FALSE); // has sound
-}
-
-
-void Seeker_Flac_Explode ()
-{
-	self.event_damage = SUB_Null;
-
-	RadiusDamage (self, self.owner, cvar("g_balance_seeker_flac_damage"), cvar("g_balance_seeker_flac_edgedamage"), cvar("g_balance_seeker_flac_radius"), world, cvar("g_balance_seeker_flac_force"), self.projectiledeathtype, other);
-
-	remove (self);
-}
-
-void Seeker_Flac_Touch()
-{
-	PROJECTILE_TOUCH;
-
-	Seeker_Flac_Explode();
-}
-
-void Seeker_Fire_Flac()
-{
-	local entity missile;
-	vector f_org;
-	float c;
-
-	if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
-		self.ammo_rockets = self.ammo_rockets - cvar("g_balance_seeker_flac_ammo");
-
-	c = mod(self.bulletcounter, 4);
-	switch(c)
-	{
-		case 1:
-			f_org = '37.5 17 -22';
-			break;
-		case 2:
-			f_org = '37.5 9.5 -22';
-			break;
-		case 3:
-			f_org = '40 17 -29';
-			break;
-		case 0:
-		default:
-			f_org = '40 9.5 -29';
-			break;
-	}
-	W_SetupShot (self, f_org, FALSE, 2, "weapons/flac_fire.wav");
-
-	pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
-
-	missile = spawn ();
-	missile.owner = missile.realowner = self;
-	missile.classname = "missile";
-	missile.bot_dodge = TRUE;
-	missile.bot_dodgerating = cvar("g_balance_seeker_flac_damage");
-	missile.touch = Seeker_Flac_Explode;
-	missile.use = Seeker_Flac_Explode;
-	missile.think = Seeker_Flac_Explode;
-	missile.nextthink = time + cvar("g_balance_seeker_flac_lifetime") + cvar("g_balance_seeker_flac_lifetime_rand");
-	missile.solid = SOLID_BBOX;
-	missile.scale = 0.4; // BUG: the model is too big
-	missile.projectiledeathtype = WEP_SEEKER;
-	setorigin (missile, w_shotorg);
-	missile.projectiledeathtype = WEP_SEEKER | HITTYPE_SECONDARY;
-
-	missile.movetype = MOVETYPE_FLY;
-	w_shotdir = w_shotdir + '0 0 0.3';
-	missile.velocity    = (w_shotdir  + randomvec() * cvar("g_balance_seeker_flac_spread")) * cvar("g_balance_seeker_flac_speed");
-
-	W_SetupProjectileVelocity(missile);
-
-	missile.angles = vectoangles (missile.velocity);
-	missile.flags = FL_PROJECTILE;
-
-	CSQCProjectile(missile, TRUE, PROJECTILE_FLAC, TRUE);
-}
-
-void spawnfunc_weapon_seeker (void)
-{
-	weapon_defaultspawnfunc(WEP_SEEKER);
-}
-
-float w_seeker(float req)
-{
-	if (req == WR_AIM)
-		self.BUTTON_ATCK = bot_aim(cvar("g_balance_seeker_tag_speed"), 0, 20, FALSE);
-
-	else if (req == WR_THINK)
-	{
-		if (self.BUTTON_ATCK)
-			if (weapon_prepareattack(0, cvar("g_balance_seeker_tag_refire")))
-			{
-				Seeker_Fire_Tag();
-				weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_seeker_tag_animtime"), w_ready);
-			}
-
-		if (self.BUTTON_ATCK2)
-			if (weapon_prepareattack(1, cvar("g_balance_seeker_flac_refire")))
-			{
-				Seeker_Fire_Flac();
-				weapon_thinkf(WFRAME_FIRE2, cvar("g_balance_seeker_flac_animtime"), w_ready);
-			}
-
-	}
-	else if (req == WR_PRECACHE)
-	{
-		precache_model ("models/weapons/g_seeker.md3");
-		precache_model ("models/weapons/v_seeker.md3");
-		precache_model ("models/weapons/w_seeker.zym");
-		precache_sound ("weapons/tag_fire.wav");
-		precache_sound ("weapons/flac_fire.wav");
-		precache_sound ("weapons/seeker_fire.wav");
-	}
-	else if (req == WR_SETUP)
-		weapon_setup(WEP_SEEKER);
-	else if (req == WR_CHECKAMMO1)
-		return self.ammo_rockets >= cvar("g_balance_seeker_tag_ammo") + cvar("g_balance_seeker_missile_ammo");
-	else if (req == WR_CHECKAMMO2)
-		return self.ammo_rockets >= cvar("g_balance_seeker_flac_ammo");
-	else if (req == WR_SUICIDEMESSAGE)
-		w_deathtypestring = "played with tiny rockets";
-	else if (req == WR_KILLMESSAGE)
-	{
-		if(w_deathtype & HITTYPE_SECONDARY)
-			w_deathtypestring = "ran into #'s flac";
-		else
-			w_deathtypestring = "was tagged by";
-	}
-	return TRUE;
-};
-
+//.float speed; = switchweapon
+//.float proxytime; = autoswitch
+//.float tl; = wait
+
+void Seeker_Missile_Explode ()
+{
+	self.event_damage = SUB_Null;
+	RadiusDamage (self, self.owner, cvar("g_balance_seeker_missile_damage"), cvar("g_balance_seeker_missile_edgedamage"), cvar("g_balance_seeker_missile_radius"), world, cvar("g_balance_seeker_missile_force"), self.projectiledeathtype, other);
+
+	remove (self);
+}
+
+void Seeker_Missile_Touch()
+{
+	PROJECTILE_TOUCH;
+
+	Seeker_Missile_Explode();
+}
+
+void Seeker_Missile_Think()
+{
+	entity e;
+	vector desireddir, olddir, newdir, eorg;
+	float turnrate;
+	float dist;
+
+	if (time > self.cnt)
+		Seeker_Missile_Explode();
+
+	if (!self.switchweapon)
+		self.switchweapon = cvar("g_balance_seeker_missile_speed");
+
+	if ((self.switchweapon < cvar("g_balance_seeker_missile_speed_max")) && cvar("g_balance_seeker_missile_speed_accel"))
+		self.switchweapon = self.switchweapon * cvar("g_balance_seeker_missile_accel");
+
+	if (self.switchweapon > cvar("g_balance_seeker_missile_speed_max"))
+		self.switchweapon = self.switchweapon * cvar("g_balance_seeker_missile_decel");
+
+	if (self.enemy != world)
+		if (self.enemy.takedamage != DAMAGE_AIM || self.enemy.deadflag != DEAD_NO)
+			self.enemy = world;
+
+	if (self.enemy != world)
+	{
+		e               = self.enemy;
+		eorg            = 0.5 * (e.absmin + e.absmax);
+		turnrate        = cvar("g_balance_seeker_missile_turnrate");		    // how fast to turn
+		desireddir      = normalize(eorg - self.origin);
+		olddir          = normalize(self.velocity);				            // get my current direction
+		dist            = vlen(eorg - self.origin);
+
+		// Do evasive maneuvers for world objects? ( this should be a cpu hog. :P )
+		if (cvar("g_balance_seeker_missile_smart") && (dist > cvar("g_balance_seeker_missile_smart_mindist")))
+		{
+			// Is it a better idea (shorter distance) to trace to the target itself?
+			if ( vlen(self.origin + olddir * self.wait) < dist)
+				traceline(self.origin, self.origin + olddir * self.wait, FALSE, self);
+			else
+				traceline(self.origin, eorg, FALSE, self);
+
+			// Setup adaptive tracelength
+			self.wait = vlen(self.origin - trace_endpos);
+			if (self.wait < cvar("g_balance_seeker_missile_smart_trace_min")) self.wait = cvar("g_balance_seeker_missile_smart_trace_min");
+			if (self.wait > cvar("g_balance_seeker_missile_smart_trace_max")) self.wait = cvar("g_balance_seeker_missile_smart_trace_max");
+
+			// Calc how important it is that we turn and add this to the desierd (enemy) dir.
+			desireddir  = normalize(((trace_plane_normal * (1 - trace_fraction)) + (desireddir * trace_fraction)) * 0.5);
+		}
+
+		//newdir = normalize((olddir + desireddir * turnrate) * 0.5);// take the average of the 2 directions; not the best method but simple & easy
+		newdir = normalize(olddir + desireddir * turnrate);// take the average of the 2 directions; not the best method but simple & easy
+
+		self.velocity = newdir * self.switchweapon;			                    // make me fly in the new direction at my flight speed
+	}
+
+	// Proxy
+	if (cvar("g_balance_seeker_missile_proxy"))
+	{
+		if ( dist <= cvar("g_balance_seeker_missile_proxy_maxrange"))
+		{
+			if (self.autoswitch == 0)
+			{
+				self.autoswitch = time + cvar("g_balance_seeker_missile_proxy_delay");
+			}
+			else
+			{
+				if (self.autoswitch <= time)
+				{
+					Seeker_Missile_Explode();
+					self.autoswitch = 0;
+				}
+			}
+		}
+		else
+		{
+			if (self.autoswitch != 0)
+				self.autoswitch = 0;
+		}
+	}
+	///////////////
+
+	if (self.enemy.deadflag != DEAD_NO)
+	{
+		self.enemy = world;
+		self.cnt = time + 1 + (random() * 4);
+		self.nextthink = self.cnt;
+		return;
+	}
+
+	self.angles = vectoangles(self.velocity);			// turn model in the new flight direction
+	self.nextthink = time + 0.05;
+
+	UpdateCSQCProjectile(self);
+}
+
+
+
+void Seeker_Missile_Damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+{
+	float d;
+	d = damage;
+
+	if (self.owner == attacker)
+		d = d * 0.25;
+
+	self.health = self.health - d;
+
+	if (self.health <= 0)
+		W_PrepareExplosionByDamage(attacker, Seeker_Missile_Explode);
+}
+
+void Seeker_Missile_Animate()
+{
+	self.frame = self.frame +1;
+	self.nextthink = time + 0.05;
+
+	if (self.enemy != world)
+		if (self.enemy.takedamage != DAMAGE_AIM || self.enemy.deadflag != DEAD_NO)
+			self.enemy = world;
+
+	if(self.frame == 5)
+	{
+		self.think           = Seeker_Missile_Think;
+		self.nextthink       = time;// + cvar("g_balance_seeker_missile_activate_delay"); // cant dealy with csqc projectiles
+
+		if (cvar("g_balance_seeker_guided_proxy"))
+			self.movetype    = MOVETYPE_BOUNCEMISSILE;
+		else
+			self.movetype    = MOVETYPE_FLYMISSILE;
+	}
+
+	UpdateCSQCProjectile(self);
+}
+
+void Seeker_Fire_Missile(vector f_org)
+{
+	local entity missile;
+
+	if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
+		self.ammo_rockets = self.ammo_rockets - cvar("g_balance_seeker_missile_ammo");
+
+	makevectors(self.v_angle);
+	W_SetupShot (self, f_org, FALSE, 2, "weapons/seeker_fire.wav");
+	pointparticles(particleeffectnum("seeker_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
+
+	//self.detornator         = FALSE;
+
+	missile                 = spawn();
+	missile.owner           = self;
+	missile.classname       = "seeker_missile";
+	missile.bot_dodge       = TRUE;
+	missile.bot_dodgerating = cvar("g_balance_seeker_missile_damage");
+
+	missile.think           = Seeker_Missile_Animate;
+
+	//if (!cvar("g_balance_seeker_missile_proxy"))
+	missile.touch           = Seeker_Missile_Touch;
+
+	missile.event_damage    = Seeker_Missile_Damage;
+	missile.nextthink       = time;// + 0.2;// + cvar("g_balance_seeker_missile_activate_delay");
+	missile.cnt             = time + cvar("g_balance_seeker_missile_lifetime");
+	missile.enemy           = self.enemy;
+	missile.switchweapon           = cvar("g_balance_seeker_missile_speed");
+	missile.solid           = SOLID_BBOX;
+	missile.scale           = 2;
+	missile.takedamage          = DAMAGE_YES;
+	missile.damageforcescale    = 4;
+	missile.health              = 5;
+	missile.projectiledeathtype = WEP_SEEKER;
+
+	setorigin (missile, w_shotorg);
+	setsize (missile, '-2 -2 -2', '2 2 2');
+
+
+	missile.movetype    = MOVETYPE_FLYMISSILE;// MOVETYPE_TOSS;
+
+	missile.flags       = FL_PROJECTILE;
+
+	missile.velocity    = (w_shotdir + '0 0 0.45') * missile.switchweapon;
+	W_SetupProjectileVelocity(missile);
+
+	missile.switchweapon = vlen(missile.velocity);
+	missile.angles = vectoangles (missile.velocity);
+
+	CSQCProjectile(missile, FALSE, PROJECTILE_SEEKER, TRUE);
+}
+
+void Seeker_Vollycontroler_Think()
+{
+	float c;
+	entity oldself,oldenemy;
+	self.cnt = self.cnt - 1;
+
+	if ((self.owner.ammo_rockets < cvar("g_balance_seeker_missile_ammo")) || (self.cnt <= -1) || (self.owner.deadflag != DEAD_NO))
+	{
+		remove(self);
+		return;
+	}
+
+	self.nextthink = time + cvar("g_balance_seeker_missile_delay");
+
+	oldself = self;
+	self = self.owner;
+
+	oldenemy = self.enemy;
+	self.enemy = oldself.enemy;
+
+	c = mod(oldself.cnt, 4);
+	switch(c)
+	{
+		case 0:
+			Seeker_Fire_Missile('37.5 17 -22');
+			break;
+		case 1:
+			Seeker_Fire_Missile('37.5 9.5 -22');
+			break;
+		case 2:
+			Seeker_Fire_Missile('40 17 -29');
+			break;
+		case 3:
+		default:
+			Seeker_Fire_Missile('40 9.5 -29');
+			break;
+	}
+
+	self.enemy = oldenemy;
+	self = oldself;
+}
+
+void Seeker_Tag_Explode ()
+{
+	//if(other==self.owner)
+	//    return;
+	Damage_DamageInfo(self.origin, 0, 0, 0, self.velocity, WEP_SEEKER | HITTYPE_BOUNCE);
+
+	remove (self);
+}
+
+void Seeker_Tag_Damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+{
+	self.health = self.health - damage;
+	if (self.health <= 0)
+		Seeker_Tag_Explode();
+}
+
+void Seeker_Tag_Think()
+{
+	remove(self);
+	return;
+}
+
+void Seeker_Tag_Touch()
+{
+	vector dir;
+	vector org2;
+
+	dir     = normalize (self.owner.origin - self.origin);
+	org2    = findbetterlocation (self.origin, 8);
+
+	te_knightspike(org2);
+
+	self.event_damage = SUB_Null;
+	Damage_DamageInfo(self.origin, 0, 0, 0, self.velocity, WEP_SEEKER | HITTYPE_HEADSHOT);
+
+	if (other.takedamage == DAMAGE_AIM && other.deadflag == DEAD_NO)
+	{
+		entity e;
+		e           = spawn();
+		e.cnt       = cvar("g_balance_seeker_missile_count");
+		e.owner     = self.owner;
+		e.enemy     = other;
+		e.think     = Seeker_Vollycontroler_Think;
+		e.nextthink = time;
+
+		//sprint(self.owner, "^1Target lock ^3[^7 ",other.netname, " ^3]^1 acquired - autofire activated.\n");
+		//sprint(other,"^1You are targeted!\n");
+
+		// stuffcmd(other,"play2 weapons/zany-alarm4.ogg\n");
+		// stuffcmd(self.owner, "play2 weapons/zany-lock4.ogg\n");
+	}
+
+	remove(self);
+	return;
+}
+
+
+
+void Seeker_Fire_Tag()
+{
+	local entity missile;
+	if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
+		self.ammo_rockets = self.ammo_rockets - cvar("g_balance_seeker_tag_ammo");
+
+	W_SetupShot (self, '56 13 -15', FALSE, 2, "weapons/tag_fire.wav");
+
+	missile                 = spawn();
+	missile.owner           = self;
+	missile.classname       = "seeker_tag";
+	missile.bot_dodge       = TRUE;
+	missile.bot_dodgerating = 50;
+	missile.touch           = Seeker_Tag_Touch;
+	missile.think           = Seeker_Tag_Think;
+	missile.nextthink       = time + 15;
+	missile.movetype        = MOVETYPE_FLY;
+	missile.solid           = SOLID_BBOX;
+	missile.owner           = self;
+
+	missile.takedamage       = DAMAGE_YES;
+	missile.event_damage    = Seeker_Tag_Explode;
+	missile.health          = 5;
+
+	setorigin (missile, w_shotorg);
+
+	missile.flags       = FL_PROJECTILE;
+
+	missile.velocity    = w_shotdir  * cvar("g_balance_seeker_tag_speed");
+	missile.movetype    = MOVETYPE_BOUNCEMISSILE;
+	W_SetupProjectileVelocity(missile);
+	missile.angles = vectoangles (missile.velocity);
+
+	CSQCProjectile(missile, TRUE, PROJECTILE_TAG, FALSE); // has sound
+}
+
+
+void Seeker_Flac_Explode ()
+{
+	self.event_damage = SUB_Null;
+
+	RadiusDamage (self, self.owner, cvar("g_balance_seeker_flac_damage"), cvar("g_balance_seeker_flac_edgedamage"), cvar("g_balance_seeker_flac_radius"), world, cvar("g_balance_seeker_flac_force"), self.projectiledeathtype, other);
+
+	remove (self);
+}
+
+void Seeker_Flac_Touch()
+{
+	PROJECTILE_TOUCH;
+
+	Seeker_Flac_Explode();
+}
+
+void Seeker_Fire_Flac()
+{
+	local entity missile;
+	vector f_org;
+	float c;
+
+	if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
+		self.ammo_rockets = self.ammo_rockets - cvar("g_balance_seeker_flac_ammo");
+
+	c = mod(self.bulletcounter, 4);
+	switch(c)
+	{
+		case 1:
+			f_org = '37.5 17 -22';
+			break;
+		case 2:
+			f_org = '37.5 9.5 -22';
+			break;
+		case 3:
+			f_org = '40 17 -29';
+			break;
+		case 0:
+		default:
+			f_org = '40 9.5 -29';
+			break;
+	}
+	W_SetupShot (self, f_org, FALSE, 2, "weapons/flac_fire.wav");
+
+	pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
+
+	missile = spawn ();
+	missile.owner = missile.realowner = self;
+	missile.classname = "missile";
+	missile.bot_dodge = TRUE;
+	missile.bot_dodgerating = cvar("g_balance_seeker_flac_damage");
+	missile.touch = Seeker_Flac_Explode;
+	missile.use = Seeker_Flac_Explode;
+	missile.think = Seeker_Flac_Explode;
+	missile.nextthink = time + cvar("g_balance_seeker_flac_lifetime") + cvar("g_balance_seeker_flac_lifetime_rand");
+	missile.solid = SOLID_BBOX;
+	missile.scale = 0.4; // BUG: the model is too big
+	missile.projectiledeathtype = WEP_SEEKER;
+	setorigin (missile, w_shotorg);
+	missile.projectiledeathtype = WEP_SEEKER | HITTYPE_SECONDARY;
+
+	missile.movetype = MOVETYPE_FLY;
+	w_shotdir = w_shotdir + '0 0 0.3';
+	missile.velocity    = (w_shotdir  + randomvec() * cvar("g_balance_seeker_flac_spread")) * cvar("g_balance_seeker_flac_speed");
+
+	W_SetupProjectileVelocity(missile);
+
+	missile.angles = vectoangles (missile.velocity);
+	missile.flags = FL_PROJECTILE;
+
+	CSQCProjectile(missile, TRUE, PROJECTILE_FLAC, TRUE);
+}
+
+void spawnfunc_weapon_seeker (void)
+{
+	weapon_defaultspawnfunc(WEP_SEEKER);
+}
+
+float w_seeker(float req)
+{
+	if (req == WR_AIM)
+		self.BUTTON_ATCK = bot_aim(cvar("g_balance_seeker_tag_speed"), 0, 20, FALSE);
+
+	else if (req == WR_THINK)
+	{
+		if (self.BUTTON_ATCK)
+			if (weapon_prepareattack(0, cvar("g_balance_seeker_tag_refire")))
+			{
+				Seeker_Fire_Tag();
+				weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_seeker_tag_animtime"), w_ready);
+			}
+
+		if (self.BUTTON_ATCK2)
+			if (weapon_prepareattack(1, cvar("g_balance_seeker_flac_refire")))
+			{
+				Seeker_Fire_Flac();
+				weapon_thinkf(WFRAME_FIRE2, cvar("g_balance_seeker_flac_animtime"), w_ready);
+			}
+
+	}
+	else if (req == WR_PRECACHE)
+	{
+		precache_model ("models/weapons/g_seeker.md3");
+		precache_model ("models/weapons/v_seeker.md3");
+		precache_model ("models/weapons/w_seeker.zym");
+		precache_sound ("weapons/tag_fire.wav");
+		precache_sound ("weapons/flac_fire.wav");
+		precache_sound ("weapons/seeker_fire.wav");
+	}
+	else if (req == WR_SETUP)
+		weapon_setup(WEP_SEEKER);
+	else if (req == WR_CHECKAMMO1)
+		return self.ammo_rockets >= cvar("g_balance_seeker_tag_ammo") + cvar("g_balance_seeker_missile_ammo");
+	else if (req == WR_CHECKAMMO2)
+		return self.ammo_rockets >= cvar("g_balance_seeker_flac_ammo");
+	else if (req == WR_SUICIDEMESSAGE)
+		w_deathtypestring = "played with tiny rockets";
+	else if (req == WR_KILLMESSAGE)
+	{
+		if(w_deathtype & HITTYPE_SECONDARY)
+			w_deathtypestring = "ran into #'s flac";
+		else
+			w_deathtypestring = "was tagged by";
+	}
+	return TRUE;
+};
+

Modified: trunk/data/qcsrc/server/w_uzi.qc
===================================================================
--- trunk/data/qcsrc/server/w_uzi.qc	2009-03-11 20:45:17 UTC (rev 6104)
+++ trunk/data/qcsrc/server/w_uzi.qc	2009-03-11 21:39:56 UTC (rev 6105)
@@ -1,3 +1,4 @@
+
 // leilei's fancy muzzleflash stuff
 void W_Uzi_Flash_Go() {
 	if (self.frame > 10){
@@ -128,11 +129,13 @@
 		precache_model ("models/uziflash.md3");
 		precache_model ("models/weapons/g_uzi.md3");
 		precache_model ("models/weapons/v_uzi.md3");
-		precache_model ("models/weapons/w_uzi.zym");
+		precache_model ("models/weapons/w_uzi.dpm");
 		precache_sound ("weapons/uzi_fire.wav");
 	}
 	else if (req == WR_SETUP)
+	{
 		weapon_setup(WEP_UZI);
+	}
 	else if (req == WR_CHECKAMMO1)
 		return self.ammo_nails >= cvar("g_balance_uzi_first_ammo");
 	else if (req == WR_CHECKAMMO2)




More information about the nexuiz-commits mailing list