[nexuiz-commits] r7005 - in trunk/data: . qcsrc/client qcsrc/common qcsrc/server qcsrc/server/pathlib qcsrc/server/tturrets/include qcsrc/server/tturrets/system qcsrc/server/vehicles

DONOTREPLY at icculus.org DONOTREPLY at icculus.org
Fri Jun 12 06:46:52 EDT 2009


Author: tzork
Date: 2009-06-12 06:46:52 -0400 (Fri, 12 Jun 2009)
New Revision: 7005

Added:
   trunk/data/qcsrc/server/pathlib/
   trunk/data/qcsrc/server/pathlib/costs.qc
   trunk/data/qcsrc/server/pathlib/debug.qc
   trunk/data/qcsrc/server/pathlib/expandnode.qc
   trunk/data/qcsrc/server/pathlib/main.qc
   trunk/data/qcsrc/server/pathlib/movenode.qc
   trunk/data/qcsrc/server/pathlib/pathlib.qh
   trunk/data/qcsrc/server/pathlib/utility.qc
   trunk/data/qcsrc/server/vehicles/
   trunk/data/qcsrc/server/vehicles/racer.qc
   trunk/data/qcsrc/server/vehicles/spiderbot.qc
   trunk/data/qcsrc/server/vehicles/vehicles.qc
   trunk/data/qcsrc/server/vehicles/vehicles.qh
   trunk/data/vehicle_racer.cfg
   trunk/data/vehicle_spiderbot.cfg
Modified:
   trunk/data/qcsrc/client/View.qc
   trunk/data/qcsrc/common/constants.qh
   trunk/data/qcsrc/server/cl_impulse.qc
   trunk/data/qcsrc/server/cl_physics.qc
   trunk/data/qcsrc/server/g_subs.qc
   trunk/data/qcsrc/server/progs.src
   trunk/data/qcsrc/server/tturrets/include/turrets.qh
   trunk/data/qcsrc/server/tturrets/system/system_scoreprocs.qc
   trunk/data/qcsrc/server/w_common.qc
Log:
vehicles server & client code, disabled by default. see vehicles/vehicles.qh

Modified: trunk/data/qcsrc/client/View.qc
===================================================================
--- trunk/data/qcsrc/client/View.qc	2009-06-12 10:21:52 UTC (rev 7004)
+++ trunk/data/qcsrc/client/View.qc	2009-06-12 10:46:52 UTC (rev 7005)
@@ -1,3 +1,10 @@
+#define spider_rocket_icon "gfx/spiderbot/rocket_ico.tga"
+#define spider_rocket_targ "gfx/spiderbot/target.tga"
+#define SPIDER_CROSS "textures/spiderbot/cross.tga"
+#define rkt_size 32
+#define rld_size_x 256
+#define rld_size_y 16
+
 entity porto;
 vector polyline[16];
 float trace_dphitcontents;
@@ -254,7 +261,7 @@
 	// now move the vecs forward as much as requested if possible
 	tracebox(w_shotorg, mi, ma, w_shotorg + view_forward * (vecs_x + nudge), MOVE_NORMAL, trueaim); // FIXME this MOVE_NORMAL part will misbehave a little in csqc
 	w_shotorg = trace_endpos - view_forward * nudge;
-	
+
 	// now test whether we will actually hit the trueaimpoint...
 	tracebox(w_shotorg, mi, ma, trueaimpoint, MOVE_NOMONSTERS, trueaim);
 
@@ -272,6 +279,7 @@
 float view_set;
 float camera_mode;
 string NextFrameCommand;
+void CSQC_spider_HUD();
 void CSQC_UpdateView(float w, float h)
 {
 	entity e;
@@ -491,75 +499,91 @@
 	// draw sbar
  	if(cvar("r_letterbox") == 0) {
  		Sbar_DrawCenterPrint(); // draw centerprint messages even if viewsize >= 120
- 		
- 		if(cvar("viewsize") < 120)
- 			CSQC_common_hud();
+
  	}
 
-	// crosshair goes VERY LAST
-	if(!scoreboard_active && !ons_showmap && !camera_active) {
-		// TrueAim check
-		float goodshot;
+    float hud;
+    hud = getstati(STAT_HUD);
+    if(hud == HUD_SPIDEBOT)
+    {
+        vector sz;
+        CSQC_spider_HUD();
+        sz = drawgetimagesize(SPIDER_CROSS);
+        sz_x *= cvar_or("cl_vehicle_spiderbot_cross_size",1);
+        sz_y *= cvar_or("cl_vehicle_spiderbot_cross_size",1);
+        drawpic('0.5 0 0' * (vid_conwidth - sz_x) + '0 0.5 0' * (vid_conheight - sz_y), SPIDER_CROSS, sz, '1 1 1', cvar_or("cl_vehicle_spiderbot_cross_alpha",0.6), DRAWFLAG_NORMAL);
+    }
+    else
+    {
+        if(cvar("r_letterbox") == 0)
+            if(cvar("viewsize") < 120)
+                CSQC_common_hud();
 
-		if(cvar("crosshair_hittest"))
-			goodshot = TrueAimCheck();
-		else
-			goodshot = TRUE;
+        // crosshair goes VERY LAST
+        if(!scoreboard_active && !ons_showmap && !camera_active) {
+            // TrueAim check
+            float goodshot;
 
-		string wcross_style;
-		wcross_style = cvar_string("crosshair");
+            if(cvar("crosshair_hittest"))
+                goodshot = TrueAimCheck();
+            else
+                goodshot = TRUE;
 
-		if (wcross_style != "0") {
-			vector wcross_color, wcross_size;
-			string wcross_wep, wcross_name;
-			float wcross_alpha, wcross_sizefloat;
+            string wcross_style;
+            wcross_style = cvar_string("crosshair");
 
-			wcross_color_x = cvar("crosshair_color_red");
-			wcross_color_y = cvar("crosshair_color_green");
-			wcross_color_z = cvar("crosshair_color_blue");
-			wcross_alpha = cvar("crosshair_color_alpha");
-			wcross_sizefloat = cvar("crosshair_size");
-			if (cvar("crosshair_per_weapon")) {
-				e = get_weaponinfo(activeweapon);
-				if (e && e.netname != "")
-				{
-					wcross_wep = e.netname;
-					wcross_style = cvar_string(strcat("crosshair_", wcross_wep));
-					if(wcross_style == "")
-						wcross_style = e.netname;
+            if (wcross_style != "0") {
+                vector wcross_color, wcross_size;
+                string wcross_wep, wcross_name;
+                float wcross_alpha, wcross_sizefloat;
 
-					if(!cvar("crosshair_color_override"))
-					{
-						wcross_color_x = cvar(strcat("crosshair_", wcross_wep, "_color_red"));
-						wcross_color_y = cvar(strcat("crosshair_", wcross_wep, "_color_green"));
-						wcross_color_z = cvar(strcat("crosshair_", wcross_wep, "_color_blue"));
-					}
+                wcross_color_x = cvar("crosshair_color_red");
+                wcross_color_y = cvar("crosshair_color_green");
+                wcross_color_z = cvar("crosshair_color_blue");
+                wcross_alpha = cvar("crosshair_color_alpha");
+                wcross_sizefloat = cvar("crosshair_size");
+                if (cvar("crosshair_per_weapon")) {
+                    e = get_weaponinfo(activeweapon);
+                    if (e && e.netname != "")
+                    {
+                        wcross_wep = e.netname;
+                        wcross_style = cvar_string(strcat("crosshair_", wcross_wep));
+                        if(wcross_style == "")
+                            wcross_style = e.netname;
 
-					wcross_alpha *= cvar(strcat("crosshair_", wcross_wep, "_color_alpha"));
-					wcross_sizefloat *= cvar(strcat("crosshair_", wcross_wep, "_size"));
-				}
-			}
+                        if(!cvar("crosshair_color_override"))
+                        {
+                            wcross_color_x = cvar(strcat("crosshair_", wcross_wep, "_color_red"));
+                            wcross_color_y = cvar(strcat("crosshair_", wcross_wep, "_color_green"));
+                            wcross_color_z = cvar(strcat("crosshair_", wcross_wep, "_color_blue"));
+                        }
 
-			wcross_name = strcat("gfx/crosshair", wcross_style);
+                        wcross_alpha *= cvar(strcat("crosshair_", wcross_wep, "_color_alpha"));
+                        wcross_sizefloat *= cvar(strcat("crosshair_", wcross_wep, "_size"));
+                    }
+                }
 
-			wcross_size = drawgetimagesize(wcross_name);
-			wcross_size_x *= wcross_sizefloat;
-			wcross_size_y *= wcross_sizefloat;
+                wcross_name = strcat("gfx/crosshair", wcross_style);
 
-			if(goodshot)
-			{
-				drawpic('0.5 0 0' * (vid_conwidth - wcross_size_x) + '0 0.5 0' * (vid_conheight - wcross_size_y), wcross_name, wcross_size, wcross_color, wcross_alpha, DRAWFLAG_NORMAL);
-			}
-			else
-			{
-				wcross_alpha *= 0.04 * 0.75;
-				for(i = -2; i <= 2; ++i)
-					for(j = -2; j <= 2; ++j)
-						drawpic('0.5 0 0' * (vid_conwidth - wcross_size_x + i) + '0 0.5 0' * (vid_conheight - wcross_size_y + j), wcross_name, wcross_size, wcross_color, wcross_alpha, DRAWFLAG_NORMAL);
-			}
-		}
-	}
+                wcross_size = drawgetimagesize(wcross_name);
+                wcross_size_x *= wcross_sizefloat;
+                wcross_size_y *= wcross_sizefloat;
 
+                if(goodshot)
+                {
+                    drawpic('0.5 0 0' * (vid_conwidth - wcross_size_x) + '0 0.5 0' * (vid_conheight - wcross_size_y), wcross_name, wcross_size, wcross_color, wcross_alpha, DRAWFLAG_NORMAL);
+                }
+                else
+                {
+                    wcross_alpha *= 0.04 * 0.75;
+                    for(i = -2; i <= 2; ++i)
+                        for(j = -2; j <= 2; ++j)
+                            drawpic('0.5 0 0' * (vid_conwidth - wcross_size_x + i) + '0 0.5 0' * (vid_conheight - wcross_size_y + j), wcross_name, wcross_size, wcross_color, wcross_alpha, DRAWFLAG_NORMAL);
+                }
+            }
+        }
+    }
+
 	if(NextFrameCommand)
 	{
 		localcmd("\n", NextFrameCommand, "\n");
@@ -568,12 +592,88 @@
 }
 
 void Sbar_Draw();
+void CSQC_spider_HUD()
+{
+    float rockets,reload,heat,hp,shield,i;
+    vector p,pp;
+
+    rockets = getstati(STAT_SPIDERBOT_ROCKETS);
+    heat    = min(getstatf(STAT_SPIDERBOT_HEAT),1);
+    reload  = min(getstatf(STAT_SPIDERBOT_RELOAD),1);
+    hp      = min(getstatf(STAT_SPIDERBOT_HEALTH),1);
+    shield  = min(getstatf(STAT_SPIDERBOT_SHIELD),1);
+
+    // Draw health bar
+    p = '0.5 0 0' * (vid_conwidth - (rkt_size * 8));
+    p = p + '0 1 0' * vid_conheight - '0 32 0';
+    //pp = ('0 1 0' * hp) + ('1 0 0' * (1-hp));
+    drawfill(p, '256 0 0' * shield + '0 8 0' , '0.5 0.5 1', 0.75, DRAWFLAG_NORMAL);
+    p_y += 8;
+    drawfill(p, '256 0 0' * hp + '0 8 0' , '0 1 0', 0.75, DRAWFLAG_NORMAL);
+    p_x += 256 * hp;
+    drawfill(p, '256 0 0' * (1-hp) + '0 8 0' , '0 0 0', 0.75, DRAWFLAG_NORMAL);
+
+    // Draw minigun heat indicator
+    p = '0.5 0 0' * (vid_conwidth - 256);
+    p = p + '0 1 0' * vid_conheight - '0 34  0';
+    drawfill(p, '256 0 0' * (1-heat) + '0 2 0' ,'0 0 1', 0.5, DRAWFLAG_NORMAL);
+    p_x += 256 * (1-heat);
+    drawfill(p, '256 0 0' * heat  + '0 2 0' , '1 0 0', 0.5, DRAWFLAG_NORMAL);
+
+    // Draw rocket icons for loaded/empty tubes.
+    pp = '0.5 0 0' * (vid_conwidth - (rkt_size * 8));
+    pp += '0 1 0' * vid_conheight - '0 64 0';
+    for(i = 0; i < 8; ++i)
+    {
+        p = pp + '1 0 0' * (rkt_size * i);
+        if(rockets == 8)
+        {
+            if(floor(reload * 8) == i)
+            {
+                drawpic(p, spider_rocket_icon, '1 1 0' * rkt_size, '1 0 0' + '0 1 0' * ((reload*8)-i), 0.75 , DRAWFLAG_NORMAL);
+            }
+            else if(i < reload * 8)
+                drawpic(p, spider_rocket_icon, '1 1 0' * rkt_size, '1 1 0', 0.75 , DRAWFLAG_NORMAL);
+            else
+                drawpic(p, spider_rocket_icon, '1 1 0' * rkt_size, '0.5 0.5 0.5', 0.75, DRAWFLAG_NORMAL);
+        }
+        else
+        {
+            if(i < rockets)
+                drawpic(p, spider_rocket_icon, '1 1 0' * rkt_size, '0 0 0', 0.25, DRAWFLAG_NORMAL);
+            else
+                drawpic(p, spider_rocket_icon, '1 1 0' * rkt_size, '0 1 0' * reload, 0.75, DRAWFLAG_NORMAL);
+        }
+    }
+
+	if (sb_showscores)
+	{
+		Sbar_DrawScoreboard();
+		Sbar_DrawCenterPrint();
+	}
+
+}
 void CSQC_common_hud(void)
 {
+
 	// Sbar_SortFrags(); done in Sbar_Draw
-	Sbar_Draw();
+    float hud;
+    hud = getstati(STAT_HUD);
+
+    //hud = 10;
+    switch(hud)
+    {
+        case HUD_NORMAL:
+            Sbar_Draw();
+            break;
+
+        case HUD_SPIDEBOT:
+            CSQC_spider_HUD();
+            break;
+    }
 }
 
+
 // following vectors must be global to allow seamless switching between camera modes
 vector camera_offset, current_camera_offset, mouse_angles, current_angles, current_origin, current_position;
 void CSQC_Demo_Camera()

Modified: trunk/data/qcsrc/common/constants.qh
===================================================================
--- trunk/data/qcsrc/common/constants.qh	2009-06-12 10:21:52 UTC (rev 7004)
+++ trunk/data/qcsrc/common/constants.qh	2009-06-12 10:46:52 UTC (rev 7005)
@@ -77,7 +77,10 @@
 const float ENT_CLIENT_MAPVOTE = 17;
 const float ENT_CLIENT_CLIENTDATA = 18;
 const float ENT_CLIENT_RANDOMSEED = 19;
-const float ENT_CLIENT_WALL = 20;
+const float ENT_CLIENT_WALL = 20;
+const float ENT_CLIENT_SPIDERBOT = 21;
+
+const float ENT_CLIENT_TURRET = 40;
 
 const float SPRITERULE_DEFAULT = 0;
 const float SPRITERULE_TEAMPLAY = 1;
@@ -257,6 +260,24 @@
 const float CTF_STATE_ATTACK = 1;
 const float CTF_STATE_DEFEND = 2;
 const float CTF_STATE_COMMANDER = 3;
+
+const float STAT_HUD = 50;
+const float HUD_NORMAL = 0;
+const float HUD_SPIDEBOT = 10;
+
+const float STAT_SPIDERBOT_HEALTH  = 60;
+const float STAT_SPIDERBOT_ROCKETS = 61;
+const float STAT_SPIDERBOT_HEAT    = 62;
+const float STAT_SPIDERBOT_RELOAD  = 63;
+const float STAT_SPIDERBOT_ENERGY  = 64;
+const float STAT_SPIDERBOT_SHIELD  = 65;
+
+//const float STAT_SPIDERBOT_AIM     53 // compressShotOrigin
+
+//const float STAT_SPIDERBOT_TARGET  54 // compressShotOrigin
+
+
+
 
 // moved that here so the client knows the max.
 // # of maps, I'll use arrays for them :P

Modified: trunk/data/qcsrc/server/cl_impulse.qc
===================================================================
--- trunk/data/qcsrc/server/cl_impulse.qc	2009-06-12 10:21:52 UTC (rev 7004)
+++ trunk/data/qcsrc/server/cl_impulse.qc	2009-06-12 10:46:52 UTC (rev 7005)
@@ -92,6 +92,9 @@
  * 220 to 229: next weapon shortcuts
  * 230 to 253: individual weapons (up to 24)
  */
+void spawnfunc_racer();
+//void spawnfunc_hov();
+//void spawnfunc_vehicle_hoover();
 
 void ImpulseCommands (void)
 {
@@ -110,6 +113,43 @@
 	if (timeoutStatus == 2) //don't allow any impulses while the game is paused
 		return;
 
+
+
+    if(imp >= 21 && imp <= 29)
+    {
+                entity r,os;
+
+        switch(imp)
+        {
+            case 21:
+                os = self;
+                r = spawn();
+                self = r;
+                setorigin(r,os.origin + v_forward * 256);
+                spawnfunc_racer();
+                self = os;
+                return;
+            /*
+            case 22:
+                os = self;
+                r = spawn();
+                self = r;
+                setorigin(r,os.origin + v_forward * 256);
+                spawnfunc_hov();
+                self = os;
+                return;
+            case 23:
+                os = self;
+                r = spawn();
+                self = r;
+                setorigin(r,os.origin + v_forward * 256);
+                spawnfunc_vehicle_hoover();
+                self = os;
+                return;
+            */
+        }
+    }
+
 	if (imp >= 1 && imp <= 9)
 	{
 		// weapon switching impulses

Modified: trunk/data/qcsrc/server/cl_physics.qc
===================================================================
--- trunk/data/qcsrc/server/cl_physics.qc	2009-06-12 10:21:52 UTC (rev 7004)
+++ trunk/data/qcsrc/server/cl_physics.qc	2009-06-12 10:46:52 UTC (rev 7005)
@@ -62,10 +62,10 @@
 	if(!sv_pogostick)
 		if (!(self.flags & FL_JUMPRELEASED))
 			return;
-			
+
 	if(self.health <= g_bloodloss)
 		return;
-	
+
 	if(sv_doublejump)
 		if(time < self.doublejump_nextjumptime)
 			return;
@@ -103,7 +103,7 @@
 
 	if(g_jump_grunt)
 		PlayerSound(playersound_jump, CHAN_PLAYER, VOICETYPE_PLAYERSOUND);
-	
+
 	if(sv_doublejump)
 	{
 		// we're moving upwards at self.velocity_z
@@ -421,10 +421,10 @@
 	vector curvel, wishvel, acceldir, curdir;
 	float addspeed, accelspeed, curspeed, f;
 	float dot;
-	
+
 	if(wishspeed == 0)
 		return;
-	
+
 	curvel = self.velocity;
 	curvel_z = 0;
 	curspeed = vlen(curvel);
@@ -462,6 +462,7 @@
 .string lastclassname;
 
 void Nixnex_GiveCurrentWeapon();
+.float() PlayerPhysplug;
 void SV_PlayerPhysics()
 {
 	local vector wishvel, wishdir, v;
@@ -469,6 +470,10 @@
 	string temps;
 	float buttons_prev;
 
+    if(self.PlayerPhysplug)
+        if(self.PlayerPhysplug())
+            return;
+
 	buttons = self.BUTTON_ATCK + 2 * self.BUTTON_JUMP + 4 * self.BUTTON_ATCK2 + 8 * self.BUTTON_ZOOM + 16 * self.BUTTON_CROUCH + 32 * self.BUTTON_HOOK + 64 * self.BUTTON_USE;
 	if(!sv_maxidle_spectatorsareidle || self.movetype == MOVETYPE_WALK)
 	{

Modified: trunk/data/qcsrc/server/g_subs.qc
===================================================================
--- trunk/data/qcsrc/server/g_subs.qc	2009-06-12 10:21:52 UTC (rev 7004)
+++ trunk/data/qcsrc/server/g_subs.qc	2009-06-12 10:46:52 UTC (rev 7005)
@@ -1,4 +1,6 @@
 void SUB_Null() {};
+float SUB_True() { return 1; }
+float SUB_False() { return 0; }
 
 void(vector destangle, float tspeed, void() func) SUB_CalcAngleMove;
 void()  SUB_CalcMoveDone;
@@ -240,14 +242,14 @@
 
 	if (!tspeed)
 		objerror ("No speed is defined!");
-	
+
 	// take the shortest distance for the angles
 	self.angles_x -= 360 * floor((self.angles_x - destangle_x) / 360 + 0.5);
 	self.angles_y -= 360 * floor((self.angles_y - destangle_y) / 360 + 0.5);
 	self.angles_z -= 360 * floor((self.angles_z - destangle_z) / 360 + 0.5);
 	delta = destangle - self.angles;
 	traveltime = vlen (delta) / tspeed;
-  
+
 	self.think1 = func;
 	self.finalangle = destangle;
 	self.think = SUB_CalcAngleMoveDone;

Added: trunk/data/qcsrc/server/pathlib/costs.qc
===================================================================
--- trunk/data/qcsrc/server/pathlib/costs.qc	                        (rev 0)
+++ trunk/data/qcsrc/server/pathlib/costs.qc	2009-06-12 10:46:52 UTC (rev 7005)
@@ -0,0 +1,144 @@
+float pathlib_g_static(entity parent,vector to, float static_cost)
+{
+    return parent.pathlib_node_g + static_cost;
+}
+
+float pathlib_g_static_water(entity parent,vector to, float static_cost)
+{
+    if(inwater(to))
+        return parent.pathlib_node_g + static_cost * pathlib_movecost_waterfactor;
+    else
+        return parent.pathlib_node_g + static_cost;
+}
+
+float pathlib_g_euclidean(entity parent,vector to, float static_cost)
+{
+    return parent.pathlib_node_g + vlen(parent.origin - to);
+}
+
+float pathlib_g_euclidean_water(entity parent,vector to, float static_cost)
+{
+    if(inwater(to))
+        return parent.pathlib_node_g + vlen(parent.origin - to) * pathlib_movecost_waterfactor;
+    else
+        return parent.pathlib_node_g + vlen(parent.origin - to);
+}
+
+
+/**
+    Manhattan Menas we expect to move up,down left or right
+    No diagonal moves espected. (like moving bewteen city blocks)
+**/
+float pathlib_h_manhattan(vector a,vector b)
+{
+    //h(n) = D * (abs(n.x-goal.x) + abs(n.y-goal.y))
+
+    float h;
+    h  = fabs(a_x - b_x);
+    h += fabs(a_y - b_y);
+    h *= pathlib_gridsize;
+
+    return h;
+}
+
+/**
+    This heuristic consider both stright and disagonal moves
+    to have teh same cost.
+**/
+float pathlib_h_diagonal(vector a,vector b)
+{
+    //h(n) = D * max(abs(n.x-goal.x), abs(n.y-goal.y))
+    float h,x,y;
+
+    x = fabs(a_x - b_x);
+    y = fabs(a_y - b_y);
+    h = pathlib_movecost * max(x,y);
+
+    return h;
+}
+
+/**
+    This heuristic only considers the stright line distance.
+    Will usualy mean a lower H then G meaning A* Will speand more
+    and run slower.
+**/
+float pathlib_h_euclidean(vector a,vector b)
+{
+    return vlen(a - b);
+}
+
+/**
+    This heuristic consider both stright and disagonal moves,
+    But has a separate cost for diagonal moves.
+**/
+float pathlib_h_diagonal2(vector a,vector b)
+{
+    float h_diag,h_str,h,x,y;
+
+    /*
+    h_diagonal(n) = min(abs(n.x-goal.x), abs(n.y-goal.y))
+    h_straight(n) = (abs(n.x-goal.x) + abs(n.y-goal.y))
+    h(n) = D2 * h_diagonal(n) + D * (h_straight(n) - 2*h_diagonal(n)))
+    */
+
+    x = fabs(a_x - b_x);
+    y = fabs(a_y - b_y);
+
+    h_diag = min(x,y);
+    h_str = x + y;
+
+    h =  pathlib_movecost_diag * h_diag;
+    h += pathlib_movecost * (h_str - 2 * h_diag);
+
+    return h;
+}
+
+/**
+    This heuristic consider both stright and disagonal moves,
+    But has a separate cost for diagonal moves.
+**/
+float pathlib_h_diagonal2sdp(vector preprev,vector prev,vector point,vector end)
+{
+    float h_diag,h_str,h,x,y,z;
+
+    //h_diagonal(n) = min(abs(n.x-goal.x), abs(n.y-goal.y))
+    //h_straight(n) = (abs(n.x-goal.x) + abs(n.y-goal.y))
+    //h(n) = D2 * h_diagonal(n) + D * (h_straight(n) - 2*h_diagonal(n)))
+
+    x = fabs(point_x - end_x);
+    y = fabs(point_y - end_y);
+    z = fabs(point_z - end_z);
+
+    h_diag = min3(x,y,z);
+    h_str = x + y + z;
+
+    h =  pathlib_movecost_diag * h_diag;
+    h += pathlib_movecost * (h_str - 2 * h_diag);
+
+    float m;
+    vector d1,d2;
+
+    d1 = normalize(preprev - point);
+    d2 = normalize(prev    - point);
+    m = vlen(d1-d2);
+
+    return h * m;
+}
+
+
+float pathlib_h_diagonal3(vector a,vector b)
+{
+    float h_diag,h_str,h,x,y,z;
+
+    x = fabs(a_x - b_x);
+    y = fabs(a_y - b_y);
+    z = fabs(a_z - b_z);
+
+    h_diag = min3(x,y,z);
+    h_str = x + y + z;
+
+    h =  pathlib_movecost_diag * h_diag;
+    h += pathlib_movecost * (h_str - 2 * h_diag);
+
+    return h;
+}

Added: trunk/data/qcsrc/server/pathlib/debug.qc
===================================================================
--- trunk/data/qcsrc/server/pathlib/debug.qc	                        (rev 0)
+++ trunk/data/qcsrc/server/pathlib/debug.qc	2009-06-12 10:46:52 UTC (rev 7005)
@@ -0,0 +1,117 @@
+
+void mark_error(vector where,float lifetime);
+void mark_info(vector where,float lifetime);
+entity mark_misc(vector where,float lifetime);
+
+
+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;
+}
+
+void __showpath2_think()
+{
+    mark_info(self.origin,1);
+    if(self.path_next)
+    {
+        self.path_next.think     = __showpath2_think;
+        self.path_next.nextthink = time + 0.15;
+    }
+    else
+    {
+        self.owner.think     = __showpath2_think;
+        self.owner.nextthink = time + 0.15;
+    }
+}
+
+void pathlib_showpath2(entity path)
+{
+    path.think     = __showpath2_think;
+    path.nextthink = time;
+}
+
+
+void pathlib_showsquare2(entity node ,vector ncolor,float align)
+{
+
+    node.alpha     = 0.25;
+    node.scale     = pathlib_gridsize / 512.001;
+    node.solid     = SOLID_NOT;
+
+    setmodel(node,"models/pathlib/square.md3");
+    setorigin(node,node.origin);
+    node.colormod = ncolor;
+
+    if(align)
+    {
+        traceline(node.origin + '0 0 32',node.origin - '0 0 128',MOVE_WORLDONLY,node);
+        node.angles = vectoangles(trace_plane_normal);
+        node.angles_x -= 90;
+    }
+}
+
+void pathlib_showsquare(vector where,float goodsquare,float lifetime)
+{
+    entity s;
+
+    if(!lifetime)
+        lifetime = time + 30;
+    else
+        lifetime += time;
+
+    s           = spawn();
+    s.alpha     = 0.25;
+    s.think     = SUB_Remove;
+    s.nextthink = lifetime;
+    s.scale     = pathlib_gridsize / 512.001;
+    s.solid     = SOLID_NOT;
+
+    if(goodsquare)
+        setmodel(s,"models/pathlib/goodsquare.md3");
+    else
+        setmodel(s,"models/pathlib/badsquare.md3");
+
+
+
+    traceline(where + '0 0 32',where - '0 0 128',MOVE_WORLDONLY,s);
+
+    s.angles = vectoangles(trace_plane_normal);
+    s.angles_x -= 90;
+    setorigin(s,where);
+}
+
+void pathlib_showedge(vector where,float lifetime,float rot)
+{
+    entity e;
+
+    if(!lifetime)
+        lifetime = time + 30;
+    else
+        lifetime += time;
+
+    e           = spawn();
+    e.alpha     = 0.25;
+    e.think     = SUB_Remove;
+    e.nextthink = lifetime;
+    e.scale     = pathlib_gridsize / 512;
+    e.solid     = SOLID_NOT;
+    setorigin(e,where);
+    setmodel(e,"models/pathlib/edge.md3");
+    //traceline(where + '0 0 32',where - '0 0 128',MOVE_WORLDONLY,e);
+    //e.angles = vectoangles(trace_plane_normal);
+    e.angles_y = rot;
+    //e.angles_x += 90;
+
+}

Added: trunk/data/qcsrc/server/pathlib/expandnode.qc
===================================================================
--- trunk/data/qcsrc/server/pathlib/expandnode.qc	                        (rev 0)
+++ trunk/data/qcsrc/server/pathlib/expandnode.qc	2009-06-12 10:46:52 UTC (rev 7005)
@@ -0,0 +1,196 @@
+vector plib_points2[8];
+vector plib_points[8];
+float  plib_fvals[8];
+
+float pathlib_expandnode_starf(entity node, vector start, vector goal)
+{
+    vector where,f,r,t;
+    float i,fc,fc2,c;
+    entity nap;
+
+    where = node.origin;
+
+    f = PLIB_FORWARD * pathlib_gridsize;
+    r = PLIB_RIGHT   * pathlib_gridsize;
+
+    // Forward
+    plib_points[0] = where + f;
+
+    // Back
+    plib_points[1] = where - f;
+
+    // Right
+    plib_points[2] = where + r;
+
+    // Left
+    plib_points[3] = where - r;
+
+    // Forward-right
+    plib_points[4] = where + f + r;
+
+    // Forward-left
+    plib_points[5] = where + f - r;
+
+    // Back-right
+    plib_points[6] = where - f + r;
+
+    // Back-left
+    plib_points[7] = where - f - r;
+
+    for(i=0;i < 8; ++i)
+    {
+        t = plib_points[i];
+        fc  = pathlib_heuristic(t,goal) + pathlib_cost(node,t,pathlib_gridsize);
+        plib_fvals[i] = fc;
+
+    }
+
+    fc = plib_fvals[0];
+    plib_points2[0] = plib_points[0];
+    vector bp;
+    bp = plib_points[0];
+    for(i = 0; i < 8; ++i)
+    {
+        c = 0;
+        nap = pathlib_nodeatpoint(plib_points[i]);
+        if(nap)
+            if(nap.owner == openlist)
+                c = 1;
+        else
+            c = 1;
+
+        if(c)
+        if(plib_fvals[i] < fc)
+        {
+            bp = plib_points[i];
+            fc = plib_fvals[i];
+            plib_points2[fc2] = plib_points[i];
+            ++fc2;
+        }
+
+        /*
+        nap = pathlib_nodeatpoint(plib_points[i]);
+        if(nap)
+        if not nap.owner == closedlist)
+        {
+        }
+        */
+    }
+
+    pathlib_makenode(node,start,bp,goal,pathlib_gridsize);
+
+    for(i = 0; i < 3; ++i)
+    {
+        pathlib_makenode(node,start,plib_points2[i],goal,pathlib_gridsize);
+    }
+
+    return pathlib_open_cnt;
+}
+
+float pathlib_expandnode_star(entity node, vector start, vector goal)
+{
+    vector point,where,f,r;
+
+    where = node.origin;
+
+    f = PLIB_FORWARD * pathlib_gridsize;
+    r = PLIB_RIGHT   * pathlib_gridsize;
+
+    // Forward
+    point = where + f;
+    pathlib_makenode(node,start,point,goal,pathlib_movecost);
+
+    // Back
+    point = where - f;
+    pathlib_makenode(node,start,point,goal,pathlib_movecost);
+
+    // Right
+    point = where + r;
+    pathlib_makenode(node,start,point,goal,pathlib_movecost);
+
+    // Left
+    point = where - r;
+    pathlib_makenode(node,start,point,goal,pathlib_movecost);
+
+    // Forward-right
+    point = where + f + r;
+    pathlib_makenode(node,start,point,goal,pathlib_movecost_diag);
+
+    // Forward-left
+    point = where + f - r;
+    pathlib_makenode(node,start,point,goal,pathlib_movecost_diag);
+
+    // Back-right
+    point = where - f + r;
+    pathlib_makenode(node,start,point,goal,pathlib_movecost_diag);
+
+    // Back-left
+    point = where - f - r;
+    pathlib_makenode(node,start,point,goal,pathlib_movecost_diag);
+
+    return pathlib_open_cnt;
+}
+
+float pathlib_expandnode_octagon(entity node, vector start, vector goal)
+{
+    vector point,where,f,r;
+
+    where = node.origin;
+
+    f = PLIB_FORWARD * pathlib_gridsize;
+    r = PLIB_RIGHT   * pathlib_gridsize;
+
+    // Forward
+    point = where + f;
+    pathlib_makenode(node,start,point,goal,pathlib_movecost);
+
+    // Back
+    point = where - f;
+    pathlib_makenode(node,start,point,goal,pathlib_movecost);
+
+    // Right
+    point = where + r;
+    pathlib_makenode(node,start,point,goal,pathlib_movecost);
+
+    // Left
+    point = where - r;
+    pathlib_makenode(node,start,point,goal,pathlib_movecost);
+
+    f = PLIB_FORWARD * pathlib_gridsize * 0.5;
+    r = PLIB_RIGHT   * pathlib_gridsize * 0.5;
+
+    // Forward-right
+    point = where + f + r;
+    pathlib_makenode(node,start,point,goal,pathlib_movecost);
+
+
+    // Forward-left
+    point = where + f - r;
+    pathlib_makenode(node,start,point,goal,pathlib_movecost);
+
+
+    // Back-right
+    point = where - f + r;
+    pathlib_makenode(node,start,point,goal,pathlib_movecost);
+
+    // Back-left
+    point = where - f - r;
+    pathlib_makenode(node,start,point,goal,pathlib_movecost);
+
+    return pathlib_open_cnt;
+}
+
+float pathlib_expandnode_box(entity node, vector start, vector goal)
+{
+    vector v;
+
+    for(v_z = node.origin_z - pathlib_gridsize; v_z <= node.origin_z + pathlib_gridsize; v_z += pathlib_gridsize)
+    for(v_y = node.origin_y - pathlib_gridsize; v_y <= node.origin_y + pathlib_gridsize; v_y += pathlib_gridsize)
+    for(v_x = node.origin_x - pathlib_gridsize; v_x <= node.origin_x + pathlib_gridsize; v_x += pathlib_gridsize)
+    {
+        //if(vlen(v - node.origin))
+            pathlib_makenode(node,start,v,goal,pathlib_movecost);
+    }
+
+    return pathlib_open_cnt;
+}

Added: trunk/data/qcsrc/server/pathlib/main.qc
===================================================================
--- trunk/data/qcsrc/server/pathlib/main.qc	                        (rev 0)
+++ trunk/data/qcsrc/server/pathlib/main.qc	2009-06-12 10:46:52 UTC (rev 7005)
@@ -0,0 +1,534 @@
+void pathlib_deletepath(entity start)
+{
+    entity e;
+
+    e = findchainentity(owner, start);
+    while(e)
+    {
+        e.think = SUB_Remove;
+        e.nextthink = time;
+        e = e.chain;
+    }
+}
+
+//#define PATHLIB_NODEEXPIRE 0.05
+#define PATHLIB_NODEEXPIRE 20
+
+void dumpnode(entity n)
+{
+    n.is_path_node = FALSE;
+    n.think        = SUB_Remove;
+    n.nextthink    = time;
+}
+
+entity pathlib_mknode(vector where,entity parent)
+{
+    entity node;
+
+    node = pathlib_nodeatpoint(where);
+    if(node)
+    {
+        mark_error(where,60);
+        return node;
+    }
+
+    node = spawn();
+
+    node.think        = SUB_Remove;
+    node.nextthink    = time + PATHLIB_NODEEXPIRE;
+    node.is_path_node = TRUE;
+    node.owner        = openlist;
+    node.path_prev    = parent;
+
+    setmodel(node,"models/pathlib/square.md3");
+    setsize(node,'0 0 0','0 0 0');
+    node.colormod = randomvec() * 2;
+    node.alpha = 0.25;
+    node.scale     = pathlib_gridsize / 512.001;
+
+    //pathlib_showsquare2(node,'1 1 1',0);//(node.medium & CONTENT_EMPTY));
+    setorigin(node, where);
+    node.medium = pointcontents(where);
+
+    mark_info(where,60);
+    //pathlib_showsquare(where,1,30);
+
+
+    ++pathlib_made_cnt;
+    ++pathlib_open_cnt;
+
+    return node;
+}
+
+float pathlib_makenode_adaptive(entity parent,vector start, vector to, vector goal,float cost)
+{
+    entity node;
+    float h,g,f,doedge;
+    vector where;
+
+    ++pathlib_searched_cnt;
+
+    if(inwater(parent.origin))
+    {
+        pathlib_expandnode = pathlib_expandnode_box;
+        pathlib_movenode   = pathlib_swimnode;
+    }
+    else
+    {
+        if(inwater(to))
+        {
+            pathlib_expandnode = pathlib_expandnode_box;
+            pathlib_movenode   = pathlib_walknode;
+        }
+        else
+        {
+            //if(edge_check(parent.origin))
+            //    return 0;
+
+            pathlib_expandnode = pathlib_expandnode_star;
+            pathlib_movenode   = pathlib_walknode;
+            doedge = 1;
+        }
+    }
+
+    node = pathlib_nodeatpoint(to);
+    if(node)
+    {
+        ++pathlib_merge_cnt;
+
+        if(node.owner == openlist)
+        {
+            h = pathlib_heuristic(node.origin,goal);
+            g = pathlib_cost(parent,node.origin,cost);
+            f = g + h;
+
+            if(node.pathlib_node_g > g)
+            {
+                node.pathlib_node_h = h;
+                node.pathlib_node_g = g;
+                node.pathlib_node_f = f;
+
+                node.path_prev = parent;
+            }
+
+            if not (best_open_node)
+                best_open_node = node;
+            else if(best_open_node.pathlib_node_f > node.pathlib_node_f)
+                best_open_node = node;
+        }
+
+        return 1;
+    }
+
+    where = pathlib_movenode(parent.origin,to,0);
+    if not(pathlib_movenode_goodnode)
+        return 0;
+
+    if(pathlib_nodeatpoint(where))
+    {
+        dprint("NAP WHERE :",vtos(where),"\n");
+        dprint("not NAP TO:",vtos(to),"\n");
+        dprint("NAP-NNAP:",ftos(vlen(to-where)),"\n\n");
+        return 0;
+    }
+
+    if(doedge)
+        if not (tile_check(where))
+            return 0;
+
+    h = pathlib_heuristic(where,goal);
+    g = pathlib_cost(parent,where,cost);
+    f = g + h;
+
+
+    /*
+    node = findradius(where,pathlib_gridsize * 0.5);
+    while(node)
+    {
+        if(node.is_path_node == TRUE)
+        {
+            ++pathlib_merge_cnt;
+            if(node.owner == openlist)
+            {
+                if(node.pathlib_node_g > g)
+                {
+                    //pathlib_movenode(where,node.origin,0);
+                    //if(pathlib_movenode_goodnode)
+                    //{
+                        //mark_error(node.origin + '0 0 128',30);
+                        node.pathlib_node_h = h;
+                        node.pathlib_node_g = g;
+                        node.pathlib_node_f = f;
+                        node.path_prev = parent;
+                    //}
+                }
+
+                if not (best_open_node)
+                    best_open_node = node;
+                else if(best_open_node.pathlib_node_f > node.pathlib_node_f)
+                    best_open_node = node;
+            }
+
+            return 1;
+        }
+        node = node.chain;
+    }
+    */
+
+    node = pathlib_mknode(where,parent);
+    node.pathlib_node_h = h;
+    node.pathlib_node_g = g;
+    node.pathlib_node_f = f;
+
+    if not (best_open_node)
+        best_open_node = node;
+    else if(best_open_node.pathlib_node_f > node.pathlib_node_f)
+        best_open_node = node;
+
+    return 1;
+}
+
+entity pathlib_getbestopen()
+{
+    entity node;
+    entity bestnode;
+
+    if(best_open_node)
+    {
+        ++pathlib_bestcash_hits;
+        pathlib_bestcash_saved += pathlib_open_cnt;
+
+        return best_open_node;
+    }
+
+    node = findchainentity(owner,openlist);
+    if(!node)
+        return world;
+
+    bestnode = node;
+    while(node)
+    {
+        ++pathlib_bestopen_seached;
+        if(node.pathlib_node_f < bestnode.pathlib_node_f)
+            bestnode = node;
+
+        node = node.chain;
+    }
+
+    return bestnode;
+}
+
+void pathlib_close_node(entity node,vector goal)
+{
+
+    if(node.owner == closedlist)
+    {
+        dprint("Pathlib: Tried to close a closed node!\n");
+        return;
+    }
+
+    if(node == best_open_node)
+        best_open_node = world;
+
+    ++pathlib_closed_cnt;
+    --pathlib_open_cnt;
+
+    node.owner = closedlist;
+
+    if(vlen(node.origin - goal) <= pathlib_gridsize)
+    {
+        vector goalmove;
+
+        goalmove = pathlib_walknode(node.origin,goal,1);
+        if(pathlib_movenode_goodnode)
+        {
+            goal_node         = node;
+            pathlib_foundgoal = TRUE;
+        }
+    }
+}
+
+void pathlib_cleanup()
+{
+    best_open_node = world;
+
+    //return;
+
+    entity node;
+
+    node = findfloat(world,is_path_node, TRUE);
+    while(node)
+    {
+        /*
+        node.owner = openlist;
+        node.pathlib_node_g = 0;
+        node.pathlib_node_h = 0;
+        node.pathlib_node_f = 0;
+        node.path_prev = world;
+        */
+
+        dumpnode(node);
+        node = findfloat(node,is_path_node, TRUE);
+    }
+
+    if(openlist)
+        remove(openlist);
+
+    if(closedlist)
+        remove(closedlist);
+
+    openlist       = world;
+    closedlist     = world;
+
+}
+
+float Cosine_Interpolate(float a, float b, float x)
+{
+    float ft,f;
+
+	ft = x * 3.1415927;
+	f = (1 - cos(ft)) * 0.5;
+
+	return  a*(1-f) + b*f;
+}
+
+float buildpath_nodefilter_directional(vector n,vector c,vector p)
+{
+    vector d1,d2;
+
+    d2 = normalize(p - c);
+    d1 = normalize(c - n);
+
+    if(vlen(d1-d2) < 0.25)
+    {
+        //mark_error(c,30);
+        return 1;
+    }
+    //mark_info(c,30);
+    return 0;
+}
+
+float buildpath_nodefilter_moveskip(vector n,vector c,vector p)
+{
+    pathlib_walknode(p,n,1);
+    if(pathlib_movenode_goodnode)
+        return 1;
+
+    return 0;
+}
+
+entity path_build(entity next, vector where, entity prev, entity start)
+{
+    entity path;
+
+    if(prev && next)
+        if(buildpath_nodefilter)
+            if(buildpath_nodefilter(next.origin,where,prev.origin))
+                return next;
+
+
+    path           = spawn();
+    path.owner     = start;
+    path.path_next = next;
+
+    setorigin(path,where);
+
+    if(!next)
+        path.classname = "path_end";
+    else
+    {
+        if(!prev)
+            path.classname = "path_start";
+        else
+            path.classname = "path_node";
+    }
+
+    return path;
+}
+
+entity pathlib_astar(vector from,vector to)
+{
+    entity path, start, end, open, n, ln;
+    float ptime, ftime, ctime;
+
+    ptime = gettime(GETTIME_REALTIME);
+    pathlib_starttime = ptime;
+
+    pathlib_cleanup();
+
+    // Select water<->land capable node make/link
+    pathlib_makenode     = pathlib_makenode_adaptive;
+    // Select XYZ cost estimate
+    //pathlib_heuristic    = pathlib_h_diagonal3;
+    pathlib_heuristic    = pathlib_h_diagonal;
+    // Select distance + waterfactor cost
+    pathlib_cost         = pathlib_g_euclidean_water;
+    // Select star expander
+    pathlib_expandnode   = pathlib_expandnode_star;
+    // Select walk simulation movement test
+    pathlib_movenode     = pathlib_walknode;
+    // Filter final nodes by direction
+    buildpath_nodefilter = buildpath_nodefilter_directional;
+    // Filter tiles with cross pattern
+    tile_check = tile_check_cross;
+
+    // If the start is in water we need diffrent settings
+    if(inwater(from))
+    {
+        // Select volumetric node expaner
+        pathlib_expandnode = pathlib_expandnode_box;
+
+        // Water movement test
+        pathlib_movenode   = pathlib_swimnode;
+    }
+
+    if not(openlist)
+        openlist       = spawn();
+
+    if not(closedlist)
+        closedlist     = spawn();
+
+    pathlib_closed_cnt       = 0;
+    pathlib_open_cnt         = 0;
+    pathlib_made_cnt         = 0;
+    pathlib_merge_cnt        = 0;
+    pathlib_searched_cnt     = 0;
+    pathlib_bestopen_seached = 0;
+    pathlib_bestcash_hits    = 0;
+    pathlib_bestcash_saved   = 0;
+
+    pathlib_gridsize       = 128;
+    pathlib_movecost       = pathlib_gridsize;
+    pathlib_movecost_diag  = vlen(('1 1 0' * pathlib_gridsize));
+    pathlib_movecost_waterfactor = 1;
+    pathlib_foundgoal      = 0;
+
+    movenode_boxmax   = self.maxs * 1.25;
+    movenode_boxmin   = self.mins * 1.25;
+
+    movenode_stepsize = 32;
+
+    tile_check_size = 65;
+    tile_check_up   = '0 0 128';
+    tile_check_down = '0 0 128';
+
+    movenode_stepup   = '0 0 36';
+    movenode_maxdrop  = '0 0 128';
+    movenode_boxup    = '0 0 72';
+
+    from_x = fsnap(from_x,pathlib_gridsize);
+    from_y = fsnap(from_y,pathlib_gridsize);
+
+    to_x = fsnap(to_x,pathlib_gridsize);
+    to_y = fsnap(to_y,pathlib_gridsize);
+
+    dprint("AStar init\n");
+    path = pathlib_mknode(from,world);
+    pathlib_close_node(path,to);
+    if(pathlib_foundgoal)
+    {
+        dprint("AStar: Goal found on first node!\n");
+
+        open           = spawn();
+        open.owner     = open;
+        open.classname = "path_end";
+        setorigin(open,path.origin);
+
+        pathlib_cleanup();
+
+        return open;
+    }
+
+    if(pathlib_expandnode(path,from,to) <= 0)
+    {
+        dprint("AStar path fail.\n");
+        pathlib_cleanup();
+
+        return world;
+    }
+
+    best_open_node = pathlib_getbestopen();
+    n = best_open_node;
+    pathlib_close_node(best_open_node,to);
+    if(inwater(n.origin))
+        pathlib_expandnode_box(n,from,to);
+    else
+        pathlib_expandnode_star(n,from,to);
+
+    while(pathlib_open_cnt)
+    {
+        if((gettime(GETTIME_REALTIME) - pathlib_starttime) > pathlib_maxtime)
+        {
+            dprint("Path took to long to compute!\n");
+            dprint("Nodes - created: ", ftos(pathlib_made_cnt),"\n");
+            dprint("Nodes -    open: ", ftos(pathlib_open_cnt),"\n");
+            dprint("Nodes -  merged: ", ftos(pathlib_merge_cnt),"\n");
+            dprint("Nodes -  closed: ", ftos(pathlib_closed_cnt),"\n");
+
+            pathlib_cleanup();
+            return world;
+        }
+
+        best_open_node = pathlib_getbestopen();
+        n = best_open_node;
+        pathlib_close_node(best_open_node,to);
+
+        if(inwater(n.origin))
+            pathlib_expandnode_box(n,from,to);
+        else
+            pathlib_expandnode(n,from,to);
+
+        if(pathlib_foundgoal)
+        {
+            dprint("Target found. Rebuilding and filtering path...\n");
+            ftime = gettime(GETTIME_REALTIME);
+            ptime = ftime - ptime;
+
+            start = path_build(world,path.origin,world,world);
+            end   = path_build(world,goal_node.origin,world,start);
+            ln    = end;
+
+            open = goal_node;
+            for(open = goal_node; open.path_prev != path; open = open.path_prev)
+            {
+                n    = path_build(ln,open.origin,open.path_prev,start);
+                ln.path_prev = n;
+                ln = n;
+            }
+            start.path_next = n;
+            n.path_prev = start;
+            ftime = gettime(GETTIME_REALTIME) - ftime;
+
+            ctime = gettime(GETTIME_REALTIME);
+            pathlib_cleanup();
+            ctime = gettime(GETTIME_REALTIME) - ctime;
+
+
+#ifdef DEBUGPATHING
+            pathlib_showpath2(start);
+
+            dprint("Time used -      pathfinding: ", ftos(ptime),"\n");
+            dprint("Time used - rebuild & filter: ", ftos(ftime),"\n");
+            dprint("Time used -          cleanup: ", ftos(ctime),"\n");
+            dprint("Time used -            total: ", ftos(ptime + ftime + ctime),"\n");
+            dprint("Time used -         # frames: ", ftos(ceil((ptime + ftime + ctime) / sys_ticrate)),"\n\n");
+            dprint("Nodes -         created: ", ftos(pathlib_made_cnt),"\n");
+            dprint("Nodes -            open: ", ftos(pathlib_open_cnt),"\n");
+            dprint("Nodes -          merged: ", ftos(pathlib_merge_cnt),"\n");
+            dprint("Nodes -          closed: ", ftos(pathlib_closed_cnt),"\n");
+            dprint("Nodes -        searched: ", ftos(pathlib_searched_cnt),"\n");
+            dprint("Nodes bestopen searched: ", ftos(pathlib_bestopen_seached),"\n");
+            dprint("Nodes bestcash -   hits: ", ftos(pathlib_bestcash_hits),"\n");
+            dprint("Nodes bestcash -   save: ", ftos(pathlib_bestcash_saved),"\n");
+            dprint("AStar done.\n");
+#endif
+            return start;
+        }
+    }
+
+    dprint("A* Faild to find a path! Try a smaller gridsize.\n");
+
+    pathlib_cleanup();
+
+    return world;
+}

Added: trunk/data/qcsrc/server/pathlib/movenode.qc
===================================================================
--- trunk/data/qcsrc/server/pathlib/movenode.qc	                        (rev 0)
+++ trunk/data/qcsrc/server/pathlib/movenode.qc	2009-06-12 10:46:52 UTC (rev 7005)
@@ -0,0 +1,126 @@
+vector pathlib_wateroutnode(vector start,vector end)
+{
+    vector surface;
+
+    pathlib_movenode_goodnode = 0;
+
+    end_x = fsnap(end_x, pathlib_gridsize);
+    end_y = fsnap(end_y, pathlib_gridsize);
+
+    traceline(end + ('0 0 0.25' * pathlib_gridsize),end - ('0 0 1' * pathlib_gridsize),MOVE_WORLDONLY,self);
+    end = trace_endpos;
+
+    if not(pointcontents(end - '0 0 1') == CONTENT_SOLID)
+        return end;
+
+    for(surface = start ; surface_z < (end_z + 32); ++surface_z)
+    {
+        if(pointcontents(surface) == CONTENT_EMPTY)
+            break;
+    }
+
+    if(pointcontents(surface + '0 0 1') != CONTENT_EMPTY)
+        return end;
+
+    tracebox(start + '0 0 64', movenode_boxmin,movenode_boxmax, end + '0 0 64', MOVE_WORLDONLY, self);
+    if(trace_fraction == 1)
+        pathlib_movenode_goodnode = 1;
+
+    if(fabs(surface_z - end_z) > 32)
+        pathlib_movenode_goodnode = 0;
+
+    return end;
+}
+
+vector pathlib_swimnode(vector start,vector end)
+{
+    pathlib_movenode_goodnode = 0;
+
+    if(pointcontents(start) != CONTENT_WATER)
+        return end;
+
+    end_x = fsnap(end_x, pathlib_gridsize);
+    end_y = fsnap(end_y, pathlib_gridsize);
+
+    if(pointcontents(end) == CONTENT_EMPTY)
+        return pathlib_wateroutnode( start, end);
+
+    tracebox(start, movenode_boxmin,movenode_boxmax, end, MOVE_WORLDONLY, self);
+    if(trace_fraction == 1)
+        pathlib_movenode_goodnode = 1;
+
+    return end;
+}
+
+vector pathlib_flynode(vector start,vector end)
+{
+    pathlib_movenode_goodnode = 0;
+
+    end_x = fsnap(end_x, pathlib_gridsize);
+    end_y = fsnap(end_y, pathlib_gridsize);
+
+    tracebox(start, movenode_boxmin,movenode_boxmax, end, MOVE_WORLDONLY, self);
+    if(trace_fraction == 1)
+        pathlib_movenode_goodnode = 1;
+
+    return end;
+}
+
+vector pathlib_walknode(vector start,vector end,float doedge)
+{
+    vector direction,point,last_point,s,e;
+    float steps, distance, i;
+
+    pathlib_movenode_goodnode = 0;
+
+    end_x = fsnap(end_x,pathlib_gridsize);
+    end_y = fsnap(end_y,pathlib_gridsize);
+    start_x = fsnap(start_x,pathlib_gridsize);
+    start_y = fsnap(start_y,pathlib_gridsize);
+
+    // Find the floor
+    traceline(start + movenode_stepup, start - movenode_maxdrop,MOVE_WORLDONLY,self);
+    if(trace_fraction == 1.0)
+        return trace_endpos;
+
+    start = trace_endpos;
+
+    // Find the direcion, without Z
+    s   = start; e   = end;
+    //e_z = 0; s_z = 0;
+    direction = normalize(e - s);
+
+    distance  = vlen(start - end);
+    steps     = rint(distance / movenode_stepsize);
+
+    last_point = start;
+    for(i = 1; i < steps; ++i)
+    {
+        point = last_point + (direction * movenode_stepsize);
+        traceline(point + movenode_stepup,point - movenode_maxdrop,MOVE_WORLDONLY,self);
+        if(trace_fraction == 1.0)
+            return trace_endpos;
+
+        last_point = trace_endpos;
+    }
+
+    point = last_point + (direction * movenode_stepsize);
+    point_x = fsnap(point_x,pathlib_gridsize);
+    point_y = fsnap(point_y,pathlib_gridsize);
+
+    //dprint("end_x:  ",ftos(end_x),  "  end_y:  ",ftos(end_y),"\n");
+    //dprint("point_x:",ftos(point_x),"  point_y:",ftos(point_y),"\n\n");
+
+    traceline(point + movenode_stepup, point - movenode_maxdrop,MOVE_WORLDONLY,self);
+    if(trace_fraction == 1.0)
+        return trace_endpos;
+
+    last_point = trace_endpos;
+
+    tracebox(start + movenode_boxup, movenode_boxmin,movenode_boxmax, last_point + movenode_boxup, MOVE_WORLDONLY, self);
+    if(trace_fraction != 1.0)
+        return trace_endpos;
+
+    pathlib_movenode_goodnode = 1;
+    return last_point;
+}

Added: trunk/data/qcsrc/server/pathlib/pathlib.qh
===================================================================
--- trunk/data/qcsrc/server/pathlib/pathlib.qh	                        (rev 0)
+++ trunk/data/qcsrc/server/pathlib/pathlib.qh	2009-06-12 10:46:52 UTC (rev 7005)
@@ -0,0 +1,99 @@
+.entity path_next;
+.entity path_prev;
+
+#define inwater(point) (pointcontents(point) == CONTENT_WATER)
+#define medium spawnshieldtime
+
+#define PLIB_FORWARD '0 1 0'
+//#define PLIB_BACK    '0 -1 0'
+#define PLIB_RIGHT   '1 0 0'
+//#define PLIB_LEFT    '-1 0 0'
+
+#define DEBUGPATHING
+#ifdef DEBUGPATHING
+void pathlib_showpath(entity start);
+void pathlib_showpath2(entity path);
+#endif
+
+entity openlist;
+entity closedlist;
+entity goal_node;
+
+.float is_path_node;
+.float pathlib_node_g;
+.float pathlib_node_h;
+.float pathlib_node_f;
+
+float pathlib_open_cnt;
+float pathlib_closed_cnt;
+float pathlib_made_cnt;
+float pathlib_merge_cnt;
+float pathlib_searched_cnt;
+float pathlib_bestopen_seached;
+float pathlib_bestcash_hits;
+float pathlib_bestcash_saved;
+float pathlib_gridsize;
+float pathlib_movecost;
+float pathlib_movecost_diag;
+float pathlib_movecost_waterfactor;
+float pathlib_foundgoal;
+
+float pathlib_starttime;
+#define pathlib_maxtime 5
+
+entity best_open_node;
+
+vector tile_check_up;
+vector tile_check_down;
+float  tile_check_size;
+float      tile_check_cross(vector where);
+float      tile_check_plus(vector where);
+float      tile_check_star(vector where);
+var float  tile_check(vector where);
+
+float  movenode_stepsize;
+vector movenode_stepup;
+vector movenode_maxdrop;
+vector movenode_boxup;
+vector movenode_boxmax;
+vector movenode_boxmin;
+float  pathlib_movenode_goodnode;
+
+vector     pathlib_wateroutnode(vector start, vector end);
+vector     pathlib_swimnode(vector start, vector end);
+vector     pathlib_flynode(vector start, vector end);
+vector     pathlib_walknode(vector start, vector end, float doedge);
+var vector pathlib_movenode(vector start, vector end, float doedge);
+
+float      pathlib_expandnode_star(entity node, vector start, vector goal);
+float      pathlib_expandnode_box(entity node, vector start, vector goal);
+float      pathlib_expandnode_octagon(entity node, vector start, vector goal);
+var float  pathlib_expandnode(entity node, vector start, vector goal);
+
+float      pathlib_g_static(entity parent, vector to, float static_cost);
+float      pathlib_g_static_water(entity parent, vector to, float static_cost);
+float      pathlib_g_euclidean(entity parent, vector to, float static_cost);
+float      pathlib_g_euclidean_water(entity parent, vector to, float static_cost);
+var float  pathlib_cost(entity parent, vector to, float static_cost);
+
+float      pathlib_h_manhattan(vector a, vector b);
+float      pathlib_h_diagonal(vector a, vector b);
+float      pathlib_h_euclidean(vector a,vector b);
+float      pathlib_h_diagonal2(vector a, vector b);
+float      pathlib_h_diagonal3(vector a, vector b);
+float      pathlib_h_diagonal2sdp(vector preprev, vector prev, vector point, vector end);
+var float  pathlib_heuristic(vector from, vector to);
+
+var float  pathlib_makenode(entity parent,vector start, vector to, vector goal,float cost);
+var float  buildpath_nodefilter(vector n,vector c,vector p);
+
+
+#ifdef DEBUGPATHING
+#include "debug.qc"
+#endif
+
+#include "utility.qc"
+#include "movenode.qc"
+#include "costs.qc"
+#include "expandnode.qc"
+#include "main.qc"

Added: trunk/data/qcsrc/server/pathlib/utility.qc
===================================================================
--- trunk/data/qcsrc/server/pathlib/utility.qc	                        (rev 0)
+++ trunk/data/qcsrc/server/pathlib/utility.qc	2009-06-12 10:46:52 UTC (rev 7005)
@@ -0,0 +1,162 @@
+float fsnap(float val,float fsize)
+{
+    return rint(val / fsize) * fsize;
+}
+
+vector vsnap(vector point,float fsize)
+{
+    vector vret;
+
+    vret_x = rint(point_x / fsize) * fsize;
+    vret_y = rint(point_y / fsize) * fsize;
+    vret_z = ceil(point_z / fsize) * fsize;
+
+    return vret;
+}
+
+float location_isok(vector point, float water_isok, float air_isok)
+{
+    float pc,pc2;
+
+    if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)
+        return 0;
+
+    pc  = pointcontents(point);
+    pc2 = pointcontents(point - '0 0 1');
+
+    switch(pc)
+    {
+        case CONTENT_SOLID:
+            break;
+
+        case CONTENT_SLIME:
+            break;
+
+        case CONTENT_LAVA:
+            break;
+
+        case CONTENT_SKY:
+            break;
+
+        case CONTENT_EMPTY:
+            if (pc2 == CONTENT_SOLID)
+                return 1;
+
+            if (pc2 == CONTENT_EMPTY)
+                if(air_isok)
+                    return 1;
+
+            if (pc2 == CONTENT_WATER)
+                if(water_isok)
+                    return 1;
+
+            break;
+
+        case CONTENT_WATER:
+            if (water_isok)
+                return 1;
+
+            break;
+    }
+
+    return 0;
+}
+
+entity pathlib_nodeatpoint(vector where)
+{
+    entity node;
+
+    ++pathlib_searched_cnt;
+
+    where_x = fsnap(where_x,pathlib_gridsize);
+    where_y = fsnap(where_y,pathlib_gridsize);
+
+    node = findradius(where,pathlib_gridsize * 0.5);
+    while(node)
+    {
+        if(node.is_path_node == TRUE)
+            return node;
+
+        node = node.chain;
+    }
+
+    return world;
+}
+
+float tile_check_cross(vector where)
+{
+    vector p,f,r;
+
+    f = PLIB_FORWARD * tile_check_size;
+    r = PLIB_RIGHT   * tile_check_size;
+
+    // forward-right
+    p = where + f + r;
+    traceline(p+tile_check_up,p-tile_check_down,MOVE_WORLDONLY,self);
+    if not (location_isok(trace_endpos,1,0))
+        return 0;
+
+    // Forward-left
+    p = where + f - r;
+    traceline(p+tile_check_up,p-tile_check_down,MOVE_WORLDONLY,self);
+    if not (location_isok(trace_endpos,1,0))
+        return 0;
+
+    // Back-right
+    p = where - f + r;
+    traceline(p+tile_check_up,p-tile_check_down,MOVE_WORLDONLY,self);
+    if not (location_isok(trace_endpos,1,0))
+        return 0;
+
+    //Back-left
+    p = where - f - r;
+    traceline(p+tile_check_up,p-tile_check_down,MOVE_WORLDONLY,self);
+    if not (location_isok(trace_endpos,1,0))
+        return 0;
+
+    return 1;
+}
+
+float tile_check_plus(vector where)
+{
+    vector p,f,r;
+
+    f = PLIB_FORWARD * tile_check_size;
+    r = PLIB_RIGHT   * tile_check_size;
+
+    // forward
+    p = where + f;
+    traceline(p+tile_check_up,p-tile_check_down,MOVE_WORLDONLY,self);
+    if not (location_isok(trace_endpos,1,0))
+        return 0;
+
+    //left
+    p = where - r;
+    traceline(p+tile_check_up,p-tile_check_down,MOVE_WORLDONLY,self);
+    if not (location_isok(trace_endpos,1,0))
+        return 0;
+
+
+    // Right
+    p = where + r;
+    traceline(p+tile_check_up,p-tile_check_down,MOVE_WORLDONLY,self);
+    if not (location_isok(trace_endpos,1,0))
+        return 0;
+
+    //Back
+    p = where - f;
+    traceline(p+tile_check_up,p-tile_check_down,MOVE_WORLDONLY,self);
+    if not (location_isok(trace_endpos,1,0))
+        return 0;
+
+    return 1;
+}
+
+float tile_check_star(vector where)
+{
+    if(tile_check_plus(where))
+        return tile_check_cross(where);
+
+    return 0;
+}
+

Modified: trunk/data/qcsrc/server/progs.src
===================================================================
--- trunk/data/qcsrc/server/progs.src	2009-06-12 10:21:52 UTC (rev 7004)
+++ trunk/data/qcsrc/server/progs.src	2009-06-12 10:46:52 UTC (rev 7005)
@@ -74,7 +74,7 @@
 verbstack.qc
 movelib.qc
 steerlib.qc
-pathlib.qc
+pathlib/pathlib.qh
 
 g_world.qc
 g_casings.qc
@@ -159,6 +159,7 @@
 
 //// tZork Turrets ////
 tturrets/include/turrets.qh
+vehicles/vehicles.qh
 
 scores.qc
 

Modified: trunk/data/qcsrc/server/tturrets/include/turrets.qh
===================================================================
--- trunk/data/qcsrc/server/tturrets/include/turrets.qh	2009-06-12 10:21:52 UTC (rev 7004)
+++ trunk/data/qcsrc/server/tturrets/include/turrets.qh	2009-06-12 10:46:52 UTC (rev 7005)
@@ -23,7 +23,7 @@
 #include "../units/unit_tessla.qc"     /// Chain lightning capabale turret
 #include "../units/unit_walker.qc"     /// Moving minigun-rocket-meele err thing
 #include "../units/unit_ewheel.qc"     /// A evil wheel. with guns on.
-//#include "../units/unit_repulsor.qc"   /// Fires a wave that knocks foes back
-//#include "../units/unit_hive.qc"
+//#include "../units/unit_repulsor.qc" /// Fires a wave that knocks foes back
+//#include "../units/unit_hive.qc"     /// Swarm AI
 
 #endif // TTURRETS_ENABLED

Modified: trunk/data/qcsrc/server/tturrets/system/system_scoreprocs.qc
===================================================================
--- trunk/data/qcsrc/server/tturrets/system/system_scoreprocs.qc	2009-06-12 10:21:52 UTC (rev 7004)
+++ trunk/data/qcsrc/server/tturrets/system/system_scoreprocs.qc	2009-06-12 10:46:52 UTC (rev 7005)
@@ -99,7 +99,7 @@
         score *= 0.001;
     }
 
-#ifndef TURRET_DEBUG
+#ifdef TURRET_DEBUG
     string sd,sa,sm,sp,ss;
     string sdt,sat,smt,spt;
 

Added: trunk/data/qcsrc/server/vehicles/racer.qc
===================================================================
--- trunk/data/qcsrc/server/vehicles/racer.qc	                        (rev 0)
+++ trunk/data/qcsrc/server/vehicles/racer.qc	2009-06-12 10:46:52 UTC (rev 7005)
@@ -0,0 +1,642 @@
+#define RACER_MIN '-40 -40 0'
+#define RACER_MAX '40 40 44'
+
+void racer_exit(float eject);
+void racer_enter();
+
+float  jetfromtag_power;
+float  jetfromtag_normpower;
+float  jetfromtag_nosolid;
+vector jetfromtag_origin;
+
+vector jetfromtag(string tagname,float jet_length,float air_power,float solid_power)
+{
+    vector force_dir;
+    float  air_frac, solid_frac, air_pwr, solid_pwr;
+
+    jetfromtag_origin = gettaginfo(self,gettagindex(self,tagname));
+    v_forward = normalize(v_forward);
+    //dprint("dd:",vtos(v_forward)," - ",vtos(force_dir),"\n");
+
+    force_dir = jetfromtag_origin - v_forward * jet_length;
+    traceline(jetfromtag_origin, force_dir, MOVE_NORMAL, self);
+    //te_lightning1(world,jetfromtag_origin,force_dir);
+
+    solid_frac = 1 - trace_fraction;
+    air_frac   = trace_fraction;
+
+    if(solid_frac < 0.1)
+        jetfromtag_nosolid += 1;
+
+    //if(solid_frac < 0.5)
+        //solid_frac = solid_frac * solid_frac;
+        //solid_frac = solid_frac * 1.5;
+
+    solid_pwr = solid_frac * solid_power;
+    air_pwr   = air_frac * air_power;
+
+    //float pmax;
+    //pmax = air_power+solid_power;
+    //pmax = min(pmax,max(self.velocity_z * cvar("g_vehicle_racer_powerfac"),800));
+    //jetfromtag_power     = min(solid_pwr + air_pwr,max(self.velocity_z * cvar("g_vehicle_racer_powerfac"),800));
+    jetfromtag_power     = solid_pwr + air_pwr;
+    jetfromtag_normpower = jetfromtag_power / (air_power+solid_power);
+    if(trace_fraction == 1)
+        return v_forward;
+    else
+        return v_forward * (jetfromtag_power + cvar("g_vehicle_racer_power_min"));
+
+    // - (v_forward * cvar("g_vehicle_racer_springk"));
+}
+
+/*
+vector jetfromtag2(string tagname,float jet_length,float air_power,float solid_power)
+{
+    vector force_dir;
+    float  solid_frac, solid_pwr;
+
+    jetfromtag_origin = gettaginfo(self,gettagindex(self,tagname));
+    v_forward = normalize(v_forward);
+
+    force_dir = jetfromtag_origin - v_forward * jet_length;
+    traceline(jetfromtag_origin, force_dir, MOVE_NORMAL, self);
+
+    if(trace_fraction == 1)
+    {
+        jetfromtag_power     = 0;
+        jetfromtag_normpower = 0;
+        return v_forward * 0.1;
+    }
+
+    float pwr_up,pwr_down;
+
+    pwr_up = (1 - trace_fraction);
+    pwr_down = (trace_fraction * -1);
+
+    jetfromtag_power = pwr_up + pwr_down;
+    jetfromtag_normpower = jetfromtag_power / solid_power;
+    return v_forward * jetfromtag_power;
+
+
+
+}
+*/
+
+void racer_align4point(float spring_length,float spring_up,float blendrate)
+{
+    vector fl_org,fl_force,fr_org,fr_force,bl_org,bl_force,br_org,br_force;
+    vector push_vector,align;
+    //vector c1,c2;
+    float fl_push, fr_push, bl_push, br_push;
+
+    jetfromtag_nosolid = 0;
+
+    fr_force = jetfromtag("tag_engine_fr",spring_length,cvar("g_vehicle_racer_power_air"), cvar("g_vehicle_racer_power_solid"));
+    fr_org   = jetfromtag_origin; fr_push = jetfromtag_normpower;
+
+    fl_force = jetfromtag("tag_engine_fl",spring_length,cvar("g_vehicle_racer_power_air"), cvar("g_vehicle_racer_power_solid"));
+    fl_org   = jetfromtag_origin; fl_push = jetfromtag_normpower;
+
+    br_force = jetfromtag("tag_engine_br",spring_length,cvar("g_vehicle_racer_power_air"), cvar("g_vehicle_racer_power_solid"));
+    br_org   = jetfromtag_origin; br_push = jetfromtag_normpower;
+
+    bl_force = jetfromtag("tag_engine_bl",spring_length,cvar("g_vehicle_racer_power_air"), cvar("g_vehicle_racer_power_solid"));
+    bl_org   = jetfromtag_origin; bl_push = jetfromtag_normpower;
+
+    push_vector = fr_force + fl_force + br_force + bl_force;
+    //c1 = (fr_org + fl_org + br_org + bl_org) - (self.origin *4);
+
+    /*
+    vector vtmp;
+    vtmp =  normalize((fr_org + fr_force) - self.origin);
+    vtmp += normalize((br_org + br_force) - self.origin);
+    vtmp += normalize((fl_org + fl_force) - self.origin);
+    vtmp += normalize((bl_org + bl_force) - self.origin);
+    //vtmp = vtmp * 0.25;
+    */
+    //dprint("a1:",vtos(vtmp)," a2",vtos(vtmp - self.angles),"\n");
+    align = align;
+
+    align_x = (fl_push - bl_push);
+    align_x += (fr_push - br_push);
+    align_x *= 360;
+
+    align_z = (fl_push - fr_push);
+    align_z += (bl_push - br_push);
+    align_z *= 360;
+
+    self.angles_x *= 0.96;
+    self.angles_z *= 0.96;
+
+    self.angles_x += align_x * frametime;
+    self.angles_z += align_z * frametime;
+    //c1 = normalize(self.velocity);
+    //c2 = normalize(push_vector - self.velocity);
+   // dprint("VR: ",vtos(c2),"\n");
+    //if(c2_z == -1)
+    //    push_vector_z *= 5;
+
+    self.velocity =  self.velocity + (push_vector * frametime);
+    self.velocity_z -= sv_gravity * frametime;
+}
+
+void racer_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+{
+    self.velocity += force;
+}
+
+float racer_pplug()
+{
+    entity player,racer;
+    float ftmp,ftmp2;
+
+
+    player = self;
+    racer = self.vehicle;
+    player.fixangle = FALSE;
+
+    player.BUTTON_ZOOM = 0;
+    player.BUTTON_CROUCH = 0;
+
+    self = racer;
+
+    if(player.BUTTON_USE)
+    {
+        self = racer;
+        racer_exit(0);
+        self = player;
+        return 0;
+    }
+
+    racer.angles_x *= -1;
+    makevectors(racer.angles);
+    racer.angles_x *= -1;
+
+    // Turn Body
+    ftmp = cvar("g_vehicle_racer_turnspeed") / server_fps;
+    ftmp2 = ftmp * -1;
+
+    ftmp = bound(ftmp2,shortangle_f(player.v_angle_y - racer.angles_y,racer.angles_y),ftmp);
+
+    //if(racer.flags & FL_ONGROUND)
+    {
+        racer.angles_y = safeangle(racer.angles_y + ftmp);
+        //player.angles = racer.angles;
+        if(player.BUTTON_JUMP)
+        {
+            player.BUTTON_JUMP = 0;
+            racer.velocity  = racer.velocity  + v_forward * 250 + v_up * 600;
+        }
+        else
+        {
+            if(vlen(player.movement) == 0)
+            {
+                self = racer;
+                //movelib_beak_simple(cvar("g_vehicle_racer_speed_stop"));
+                ftmp = self.velocity_z;
+                self.velocity = self.velocity - self.velocity * cvar("g_vehicle_racer_speed_stop");
+                self.velocity_z = ftmp;
+            }
+            else
+            {
+
+                if(player.movement_x != 0)
+                {
+                    if(player.movement_x > 0)
+                    {
+                        player.movement_x = 1;
+                    }
+                    else if(player.movement_x < 0)
+                    {
+                        player.movement_x = -1;
+                    }
+                }
+
+                if(player.movement_y != 0)
+                {
+                    if(player.movement_y < 0)
+                    {
+                        player.movement_y = -1;
+                    }
+                    else if(player.movement_y > 0)
+                    {
+                        player.movement_y = 1;
+                    }
+                }
+
+                self = racer;
+                self.velocity  = self.velocity + ((v_right * player.movement_y) * cvar("g_vehicle_racer_speed_strafe")) * frametime;
+                self.velocity  = self.velocity + ((v_forward * player.movement_x) * cvar("g_vehicle_racer_speed_forward")) * frametime;
+            }
+        }
+        self = racer;
+    }
+
+    vector df;
+    df = vlen(self.velocity) * cvar("g_vehicle_racer_downforce") * v_up;
+    //te_lightning1(self,self.origin,self.origin - df);
+    self.velocity = self.velocity - df;
+
+    player.movement = racer.velocity;
+    self = racer;
+    racer_align4point(cvar("g_vehicle_racer_springlength"),100,cvar("g_vehicle_racer_inert"));
+
+    if(cvar("g_vehicle_racer_drag"))
+        self.velocity  = movelib_dragvec(cvar("g_vehicle_racer_drag"),cvar("g_vehicle_racer_dragexp"));
+
+
+
+    player.BUTTON_ATCK = player.BUTTON_ATCK2 = 0;
+    self = player;
+    setorigin(player,racer.origin);
+    player.velocity = racer.velocity;
+
+    //player.v_angle = racer.angles;
+    //player.v_angle_x *= -1;
+
+    /*
+    msg_entity = player;
+    player.angles = racer.angles;
+    //player.fixangle = TRUE;
+    WriteByte (MSG_ONE, SVC_SETVIEWANGLES);  // 10 = SVC_SETVIEWANGLES
+    //WriteAngle(MSG_ONE, player.v_angle_x - (racer.angles_x * -1));    // tilt
+    WriteAngle(MSG_ONE, racer.angles_x * -1);    // tilt
+    WriteAngle(MSG_ONE, player.v_angle_y);    // yaw
+    WriteAngle(MSG_ONE, (racer.angles_z + player.v_angle_z) * 0.5);    // flip
+    */
+
+    return 1;
+}
+
+void racer_think()
+{
+    //if(self.flags & FL_ONGROUND)
+    //{
+        movelib_beak_simple(cvar("g_vehicle_racer_speed_stop"));
+        //racer_align4point(300,100);
+    //}
+    self.nextthink = time;
+}
+
+void racer_enter()
+{
+    self.owner = other;
+    self.owner.angles = self.angles;
+
+    //setattachment(other,self,"");
+    self.nextthink = 0;
+    self.think = SUB_Null;
+    self.owner.takedamage     = DAMAGE_NO;
+    self.owner.solid          = SOLID_NOT;
+    self.owner.movetype       = MOVETYPE_NOCLIP;
+    //setsize(self.owner,spiderbot_MIN,spiderbot_MAX);
+    self.owner.alpha          = -1;
+    self.owner.PlayerPhysplug = racer_pplug;
+    self.owner.vehicle        = self;
+    self.owner.event_damage   = SUB_Null;
+    //self.event_damage         = vehicle_stdproc_damage ;
+    //self.colormap             = self.owner.colormap;
+    //self.tur_head.colormap    = self.owner.colormap;
+    //self.vehicle_hudmodel.viewmodelforclient = self.owner;
+    //self.owner.hud            = HUD_SPIDEBOT;
+    //self.owner.vehicle_health = (self.vehicle_health / cvar("g_vehicle_spiderbot_health"));
+    //self.owner.vehicle_shield = (self.vehicle_shield / cvar("g_vehicle_spiderbot_shield"));
+
+    //setorigin(self.owner,self.origin);
+    //setattachment(self.owner,self,"");
+    //setorigin(self.owner,'0 0 0');
+
+    msg_entity = other;
+    WriteByte (MSG_ONE, SVC_SETVIEWPORT);
+    WriteEntity( MSG_ONE, self.vehicle_viewport);
+
+    WriteByte (MSG_ONE, SVC_SETVIEWANGLES);  // 10 = SVC_SETVIEWANGLES
+    WriteAngle(MSG_ONE,  self.angles_x);    // tilt
+    WriteAngle(MSG_ONE,  self.angles_y);    // yaw
+    WriteAngle(MSG_ONE,  self.angles_z);    // flip
+
+    //self.owner.view_ofs = '0 0 0';
+    //self.tur_head.nodrawtoclient = self.owner;
+}
+
+void racer_exit(float eject)
+{
+    self.velocity = '0 0 0';
+
+    msg_entity = self.owner;
+    WriteByte (MSG_ONE, SVC_SETVIEWPORT);
+    WriteEntity( MSG_ONE, self.owner);
+
+    //setattachment(self.owner,world,"");
+    self.think = racer_think;
+    self.nextthink = time;
+
+    self.owner.takedamage     = DAMAGE_AIM;
+    self.owner.solid          = SOLID_SLIDEBOX;
+    self.owner.movetype       = MOVETYPE_WALK;
+
+    setsize(self.owner,PL_MIN,PL_MAX);
+
+    self.owner.alpha          = 1;
+    self.owner.PlayerPhysplug = SUB_Null;
+    self.owner.vehicle        = world;
+	self.owner.view_ofs       = PL_VIEW_OFS;
+	//self.owner.hud            = HUD_NORMAL;
+	self.owner.event_damage   = PlayerDamage;
+
+	//self.colormap            = 1024;
+	//self.tur_head.colormap = 1024;
+
+	//self.vehicle_hudmodel.viewmodelforclient = self;
+	//self.tur_head.nodrawtoclient             = self;
+
+    setattachment(self.owner,world,"");
+
+	if(eject)
+	{
+	    makevectors(self.angles);
+	    setorigin(self.owner,self.origin + v_forward * 100);
+	    self.owner.velocity = (v_up + v_forward * 0.25) * 750;
+	}
+	else
+        setorigin(self.owner,self.origin - v_forward * 200);
+
+    self.owner = world;
+}
+
+
+void racer_touch()
+{
+    if(self.owner)
+    {
+        if(vlen(self.velocity) == 0)
+            return;
+
+        if(other.classname != "player")
+            return;
+
+        vector a;
+        a = normalize(other.origin - self.origin);
+        a = a - normalize(self.velocity);
+        //dprint("a:",vtos(a),"\n");
+
+        return;
+    }
+
+    if(other.classname != "player")
+        return;
+
+    if(other.deadflag != DEAD_NO)
+        return;
+
+    if(other.vehicle != world)
+        return;
+
+    racer_enter();
+}
+
+/*
+float spiderbot_customizeentityforclient()
+{
+    if(self.deadflag == DEAD_DEAD)
+        return FALSE;
+    if(self.owner == other)
+        self.tur_head.alpha = -1;
+    else
+        self.tur_head.alpha = 1;
+    return TRUE;
+}
+*/
+
+void racer_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force);
+void racer_spawn()
+{
+    self.think = racer_think;
+    self.nextthink = time;
+
+    //self.vehicle_health = CCVAR("_health");
+    //self.vehicle_shield = CCVAR("_shield");
+    //self.event_damage = vehicle_stdproc_damage;
+    //self.event_damage = spiderbot_damage;
+    //self.iscreature = TRUE;
+    self.scale = 0.5;
+    self.movetype   = MOVETYPE_FLY;
+    self.solid      = SOLID_SLIDEBOX;
+    //self.takedamage = DAMAGE_AIM;
+    self.touch      = racer_touch;
+    //self.alpha = self.tur_head.alpha = self.gun1.alpha = self.gun2.alpha = 1;
+    self.alpha = 1;
+    //self.tur_head.angles = '0 0 0';
+	//self.colormap = 1024;
+	//self.tur_head.colormap = 1024;
+	self.deadflag    = DEAD_NO;
+    self.bot_attack = TRUE;
+    setorigin(self,self.origin + '0 0 128');
+    setsize(self,RACER_MIN*0.5,RACER_MAX*0.5);
+    setorigin(self,self.tur_aimpos);
+    pointparticles(particleeffectnum("teleport"), self.origin + '0 0 64', '0 0 0', 1);
+}
+
+void racer_blowup()
+{
+    /*
+    sound (self, CHAN_PROJECTILE, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
+    pointparticles(particleeffectnum("rocket_explode"), findbetterlocation (self.origin, 16), '0 0 0', 1);
+
+    //RadiusDamage (self, self.owner, self.owner.shot_dmg, self.owner.shot_dmg * 0.5, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET, world);
+    RadiusDamage (self, self, 250, 15, 250, world, 250, DEATH_TURRET, world);
+
+    self.alpha = self.tur_head.alpha = self.gun1.alpha = self.gun2.alpha = -1;
+    self.nextthink  = time + 10;
+    self.think      = spiderbot_spawn;
+
+    setorigin(self,self.tur_aimpos);
+    */
+}
+
+void racer_die()
+{
+
+    /*
+    self.health = 0;
+    self.event_damage = SUB_Null;
+    self.iscreature = FALSE;
+    self.solid      = SOLID_NOT;
+    self.takedamage = DAMAGE_NO;
+    self.touch      = SUB_Null;
+    self.nextthink  = time + random() * 2;
+    self.think      = spiderbot_blowup;
+    self.deadflag    = DEAD_DEAD;
+	self.vehicle_hudmodel.viewmodelforclient = self;
+	self.frame = 0;
+	self.tur_head.frame = 0;
+	*/
+}
+
+void racer_dinit()
+{
+
+    server_fps = (1 / sys_ticrate);
+
+    /*
+    addstat(STAT_HUD, AS_INT,  hud);
+	addstat(STAT_SPIDERBOT_ROCKETS, AS_INT,   rockets);
+	addstat(STAT_SPIDERBOT_RELOAD,  AS_FLOAT, rockets_reload);
+	addstat(STAT_SPIDERBOT_HEAT,    AS_FLOAT, vehicle_heat);
+	addstat(STAT_SPIDERBOT_HEALTH,  AS_FLOAT, vehicle_health);
+	addstat(STAT_SPIDERBOT_SHIELD,  AS_FLOAT, vehicle_shield);
+	*/
+
+    if (self.netname == "")      self.netname     = "Race PoD";
+
+    self.vehicle_viewport = spawn();
+    self.event_damage = racer_damage;
+    //self.gravity = 2;
+    //self.vehicle_hudmodel = spawn();
+    //self.vehicle_flags = VHF_HASSHIELD | VHF_SHIELDREGEN | VHF_HEALTHREGEN;
+    //self.cvar_basename = "g_vehicle_spiderbot";
+
+    setmodel (self.vehicle_viewport, "models/null.md3");
+    setmodel(self,"models/racers/waka.dpm");
+
+    setattachment(self.vehicle_viewport,self,"");
+    //self.tur_head.customizeentityforclient = spiderbot_customizeentityforclient;
+
+    setorigin(self.vehicle_viewport,'-400 0 40  ');
+    self.tur_aimpos = self.origin;
+    racer_spawn();
+
+    //self.vehicle_die = spiderbot_die;
+    //self.vehicle_exit = spiderbot_exit;
+}
+
+void spawnfunc_racer()
+{
+    g_turrets_common_precash();
+
+    precache_model ( "models/racers/waka.dpm");
+
+    self.think = racer_dinit;
+    self.nextthink = time + 0.5;
+}
+/*
+onClipEvent (load) {
+	// inertia relates to the quantity of energy that
+	// the spring will carry
+	// inertia = 1 would mean that the spring doesn't
+	// loose any energy, and that it will oscillate
+	// forever
+	inertia = 0.9 ;
+
+	// k relates to the spring, and how "hard" it will be.
+	// The higher k the faster the mass will come back.
+	k = 0.1 ;
+}
+
+onClipEvent (enterFrame) {
+
+	// We calculate the distance to the mouse
+	x = -this._x + _root._xmouse ;
+	y = -this._y + _root._ymouse ;
+
+	//We calculate the amount by which the mass will to move
+	xp = xp * inertia + x*k ;
+	yp = yp * inertia + y*k ;
+
+	//We move it
+	_x += xp ;
+	_y += yp ;
+}
+*/
+
+/*
+.float inertia;
+.float k;
+.float mass;
+.entity springtarget;
+//.float dt;
+void func_spring_think()
+{
+
+    float deltatime;
+    deltatime = time - other.lastpushtime;
+    if (pushdeltatime > 0.15) pushdeltatime = 0;
+    other.lastpushtime = time;
+    if(!pushdeltatime) return;
+
+
+    vector dist;
+    //vector move;
+    dist = (self.springtarget.origin *-1) + self.origin;
+    dist = '-1 -1 -1' * vlen(self.springtarget.origin - self.origin);
+    self.springtarget.velocity_x *= self.inertia + dist_x * self.k;
+    self.springtarget.velocity_y *= self.inertia + dist_y * self.k;
+    self.springtarget.velocity_z *= self.inertia + dist_z * self.k;
+
+    self.nextthink = time;
+}
+
+void func_spring_init()
+{
+    self.springtarget = find(world, targetname, self.target);
+    if(!self.springtarget)
+    {
+        objerror("func_spring cant find its .target!\n");
+        remove(self);
+        return;
+    }
+    self.think = func_spring_think;
+    self.nextthink = time;
+}
+
+void springtarget_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+{
+    dprint("Smack!\n");
+    self.velocity = self.velocity +force;
+}
+
+void spawnfunc_func_springtarget()
+{
+	self.mdl = self.model;
+	setmodel(self, self.mdl);
+
+	self.effects |= EF_LOWPRECISION;
+	setsize (self, self.mins , self.maxs);
+    self.movetype = MOVETYPE_BOUNCE;
+    setorigin(self,self.origin);
+    self.solid = SOLID_BSP;
+    self.takedamage = DAMAGE_YES;
+    self.event_damage = springtarget_damage;
+    dprint("spawnfunc_func_springtarget!\n");
+}
+
+void spawnfunc_func_spring()
+{
+    if(self.target == "")
+    {
+        objerror("func_spring w/o target!\n");
+        //remove(self);
+        return;
+    }
+
+    if(!self.inertia)
+        self.inertia = 0.9;
+
+    if(!self.k)
+        self.k = 0.1;
+
+    if(!self.mass)
+        self.mass = 1;
+
+	self.mdl = self.model;
+	setmodel(self, self.mdl);
+
+	self.effects |= EF_LOWPRECISION;
+	setsize (self, self.mins , self.maxs);
+	self.movetype = MOVETYPE_FLY;
+	self.think = func_spring_init;
+	self.nextthink = time +1;
+	dprint("spawnfunc_func_spring!\n");
+
+}
+*/

Added: trunk/data/qcsrc/server/vehicles/spiderbot.qc
===================================================================
--- trunk/data/qcsrc/server/vehicles/spiderbot.qc	                        (rev 0)
+++ trunk/data/qcsrc/server/vehicles/spiderbot.qc	2009-06-12 10:46:52 UTC (rev 7005)
@@ -0,0 +1,776 @@
+#define MODEL_SPIDERBOT_FORWARD_START 1
+#define MODEL_SPIDERBOT_FORWARD_END 31
+#define MODEL_SPIDERBOT_FORWARD_LENGTH 31
+
+#define MODEL_SPIDERBOT_BACKWARDS_START 32
+#define MODEL_SPIDERBOT_BACKWARDS_END 62
+#define MODEL_SPIDERBOT_BACKWARDS_LENGTH 31
+
+#define MODEL_SPIDERBOT_LEFT_START 63
+#define MODEL_SPIDERBOT_LEFT_END 93
+#define MODEL_SPIDERBOT_LEFT_LENGTH 31
+
+#define MODEL_SPIDERBOT_RIGHT_START 94
+#define MODEL_SPIDERBOT_RIGHT_END 124
+#define MODEL_SPIDERBOT_RIGHT_LENGTH 31
+
+#define MODEL_SPIDERBOT_JUMP_START 125
+#define MODEL_SPIDERBOT_JUMP_END 155
+#define MODEL_SPIDERBOT_JUMP_LENGTH 31
+
+#define spiderbot_MIN '-75 -75 5'
+#define spiderbot_MAX '75 75 105'
+
+/*
+.void() anim_now;
+.void() anim_next;
+
+void spider_anim_idle()
+{
+    movelib_beak_simple(cvar("g_vehicle_spiderbot_speed_stop"));
+    if(self.anim_next != self.anim_now)
+        self.anim_now = self.anim_next;
+}
+
+void spider_anim_forward()
+{
+    movelib_move_simple(normalize(v_forward),cvar("g_vehicle_spiderbot_speed_walk"),cvar("g_vehicle_spiderbot_movement_inertia"));
+
+    if((self.frame < MODEL_SPIDERBOT_FORWARD_START) || (self.frame > MODEL_SPIDERBOT_FORWARD_END))
+        self.frame = MODEL_SPIDERBOT_FORWARD_START;
+    else
+        self.frame += 0.8;
+
+    if(self.frame > MODEL_SPIDERBOT_FORWARD_END)
+        self.anim_now = self.anim_next;
+}
+
+void spider_anim_backward()
+{
+    movelib_move_simple(normalize(v_forward * -1),cvar("g_vehicle_spiderbot_speed_walk"),cvar("g_vehicle_spiderbot_movement_inertia"));
+
+    if(self.frame < MODEL_SPIDERBOT_BACKWARDS_START)
+        self.frame = MODEL_SPIDERBOT_BACKWARDS_START;
+    else
+        self.frame += 0.8;
+
+    if(self.frame > MODEL_SPIDERBOT_BACKWARDS_END)
+        self.anim_now = self.anim_next;
+}
+
+void spider_anim_strafel()
+{
+    movelib_move_simple(normalize(v_right * -1),cvar("g_vehicle_spiderbot_speed_strafe"),cvar("g_vehicle_spiderbot_movement_inertia"));
+
+    if(self.frame < MODEL_SPIDERBOT_LEFT_START)
+        self.frame = MODEL_SPIDERBOT_LEFT_START;
+    else
+        self.frame += 0.8;
+
+    if(self.frame > MODEL_SPIDERBOT_LEFT_END)
+        self.anim_now = self.anim_next;
+}
+
+void spider_anim_strafer()
+{
+    movelib_move_simple(normalize(v_right),cvar("g_vehicle_spiderbot_speed_strafe"),cvar("g_vehicle_spiderbot_movement_inertia"));
+
+    if(self.frame < MODEL_SPIDERBOT_RIGHT_START)
+        self.frame = MODEL_SPIDERBOT_RIGHT_START;
+    else
+        self.frame += 0.8;
+
+    if(self.frame > MODEL_SPIDERBOT_RIGHT_END)
+        self.anim_now = self.anim_next;
+}
+
+void spider_anim_jump()
+{
+    //movelib_move_simple(normalize(v_forward),cvar("g_vehicle_spiderbot_speed_walk"),cvar("g_vehicle_spiderbot_movement_inertia"));
+
+    if(self.frame < MODEL_SPIDERBOT_JUMP_START)
+        self.frame = MODEL_SPIDERBOT_JUMP_START;
+    else
+        self.frame += 1;
+
+    if(self.frame <= 8)
+        movelib_beak_simple(cvar("g_vehicle_spiderbot_speed_stop"));
+
+    if(self.frame == 9)
+        self.velocity = v_forward * 400 + v_up * 400;
+
+    if(self.frame >= 19)
+        movelib_beak_simple(cvar("g_vehicle_spiderbot_speed_stop"));
+
+    if(self.frame > MODEL_SPIDERBOT_JUMP_END)
+        self.anim_now = self.anim_next;
+}
+
+void anim_do()
+{
+    if not (self.anim_now)
+        self.anim_now = self.anim_next;
+
+    self.anim_now();
+}
+
+*/
+
+void anim_do()
+{
+    self.frame = self.frame + 0.8;
+    if ((self.frame < self.anim_start) || (self.frame > self.anim_end))
+        if(self.anim_start == 0)
+        {
+            self.frame = 0;
+            self.anim_end = 0;
+        }
+        else
+            self.frame = self.anim_start;
+}
+
+void spiderbot_exit(float eject);
+void spiderbot_enter();
+
+void spiderbot_rocket_explode()
+{
+    vector org2;
+
+    if(self.event_damage != SUB_Null)
+    {
+        self.event_damage = SUB_Null;
+        self.think = spiderbot_rocket_explode;
+        self.nextthink = time;
+        return;
+    }
+
+    sound (self, CHAN_PROJECTILE, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
+    org2 = findbetterlocation (self.origin, 16);
+    pointparticles(particleeffectnum("rocket_explode"), org2, '0 0 0', 1);
+    w_deathtypestring = "dident escape the rocket barrage";
+
+    if(!self.owner)
+        self.owner = self.realowner;
+
+    RadiusDamage (self, self.owner,
+     cvar("g_vehicle_spiderbot_rocket_damage"),
+     cvar("g_vehicle_spiderbot_rocket_edgedamage"),
+     cvar("g_vehicle_spiderbot_rocket_radius"), world,
+     cvar("g_vehicle_spiderbot_rocket_force"), DEATH_TURRET, world);
+
+    remove (self);
+}
+
+void spiderbot_rocket_touch()
+{
+    if(self.owner)
+    {
+        if(other == self.owner.vehicle)
+            return;
+
+        if(other == self.owner.vehicle.tur_head)
+            return;
+    }
+
+    PROJECTILE_TOUCH;
+    spiderbot_rocket_explode();
+}
+
+void spiderbot_rocket_think()
+{
+    vector newdir,olddir;
+
+    self.nextthink  = time;
+    if not(self.owner)
+    {
+        UpdateCSQCProjectile(self);
+        return;
+    }
+
+    self.solid      = SOLID_BBOX;
+    self.touch      = spiderbot_rocket_touch;
+    olddir = normalize(self.velocity);
+    newdir = normalize(self.owner.cursor_trace_endpos - self.origin);
+    newdir += randomvec() * cvar("g_vehicle_spiderbot_rocket_noise");
+    self.velocity = normalize(olddir + newdir * cvar("g_vehicle_spiderbot_rocket_turnrate")) * cvar("g_vehicle_spiderbot_rocket_speed");
+
+    UpdateCSQCProjectile(self);
+}
+
+void spiderbot_rocket_do()
+{
+    entity missile;
+
+    if(self.gun2.cnt > time)
+        return;
+
+    if(self.tur_head.frame > 7)
+        self.tur_head.frame = 0;
+
+    if not (self.owner.BUTTON_ATCK2)
+        return;
+
+    self.tur_head.frame += 1;
+    if(self.tur_head.frame > 7)
+        self.attack_finished_single = cvar("g_vehicle_spiderbot_rocket_reload");
+    else
+        self.attack_finished_single = cvar("g_vehicle_spiderbot_rocket_refire");
+
+    self.gun2.cnt = time + self.attack_finished_single;
+
+    sound (self, CHAN_WEAPON, "weapons/rocket_fire.wav", VOL_BASE, ATTN_NORM);
+    missile                    = spawn ();
+    setsize (missile, '-3 -1 -1', '3 1 1'); // give it some size so it can be shot
+    setorigin(missile,gettaginfo(self.tur_head,gettagindex(self.tur_head,"tag_fire")));
+    te_explosion (missile.origin);
+
+    missile.classname       = "spiderbot_rocket";
+    missile.owner           = self.owner;
+    missile.bot_dodge       = TRUE;
+    missile.bot_dodgerating = 75;
+    missile.nextthink       = time;// + 0.2;
+    missile.movetype        = MOVETYPE_FLYMISSILE;
+    missile.velocity        = normalize(v_forward + (v_up * 0.5) + randomvec() * 0.25) * cvar("g_vehicle_spiderbot_rocket_speed");
+    missile.angles          = vectoangles(missile.velocity);
+    missile.think           = spiderbot_rocket_think;
+    missile.flags           = FL_PROJECTILE;
+    missile.solid           = SOLID_NOT;
+
+	CSQCProjectile(missile, FALSE, PROJECTILE_ROCKET, FALSE); // no culling, has fly sound
+}
+
+void spiderbot_minigun_fire_Flash_Go() {
+	if (self.frame > 10){
+		self.alpha = -1;
+		setmodel(self,"");
+		return;
+	}
+
+	self.frame = self.frame + 2;
+	self.alpha = self.alpha - 0.2;
+	self.nextthink = time + 0.02;
+}
+
+void spiderbot_minigun_fire(entity gun,float trail)
+{
+
+    entity flash;
+    vector v;
+    v = gettaginfo(gun,gettagindex(gun,"barrels"));
+    v_forward = normalize(v_forward);
+
+    sound (gun, CHAN_WEAPON, "weapons/uzi_fire.wav", VOL_BASE, ATTN_NORM);
+
+    fireBullet (v, v_forward, cvar("g_vehicle_spiderbot_minigun_spread"), cvar("g_vehicle_spiderbot_minigun_damage"),
+        cvar("g_vehicle_spiderbot_minigun_spread"), DEATH_TURRET, 0);
+
+    if not (gun.enemy)
+    {
+        gun.enemy = spawn();
+        setattachment(gun.enemy , gun, "barrels");
+        setorigin(gun.enemy ,gun.enemy.origin + '48 0 0');
+    }
+
+    flash = gun.enemy; //spawn();
+    setmodel(flash, "models/uziflash.md3"); // precision set below
+    flash.think = spiderbot_minigun_fire_Flash_Go;
+    flash.nextthink = time + 0.02;
+    flash.frame = 2;
+    flash.angles_z = flash.v_angle_z + random() * 180;
+    flash.alpha = 1;
+    flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
+    if(trail)
+        trailparticles(self, particleeffectnum("EF_MGTURRETTRAIL"), v, trace_endpos);
+}
+
+void spiderbot_miniguns_do()
+{
+    if ((self.owner.BUTTON_ATCK) && (self.owner.vehicle_heat < 1) && (self.tur_head.attack_finished_single < time))
+    {
+
+        self.gun1.angles_z += 36;
+        self.gun2.angles_z -= 36;
+        if(self.gun1.angles_z >= 360)
+        {
+            self.gun1.angles_z = 0;
+            self.gun2.angles_z = 360;
+        }
+
+        self = self.owner;
+        if(self.uzi_bulletcounter == 1)
+        {
+            spiderbot_minigun_fire(self.vehicle.gun1,0);
+            spiderbot_minigun_fire(self.vehicle.gun2,1);
+            self.uzi_bulletcounter = 0;
+        }
+        else
+        {
+            spiderbot_minigun_fire(self.vehicle.gun1,1);
+            spiderbot_minigun_fire(self.vehicle.gun2,0);
+            self.uzi_bulletcounter += 1;
+        }
+
+        self = self.vehicle;
+        self.owner.vehicle_heat += cvar("g_vehicle_spiderbot_minigun_heat");
+        if(self.owner.vehicle_heat >= 1)
+        {
+            self.vehicle_heat = 1;
+            self.owner.vehicle_heat = 1;
+            self.tur_head.attack_finished_single = (1/(cvar("g_vehicle_spiderbot_minigun_cooldown") * server_fps))+time;
+        }
+        else
+            self.tur_head.attack_finished_single = cvar("g_vehicle_spiderbot_minigun_refire") + time;
+
+        return;
+    }
+    else
+        if(self.vehicle_heat != 0)
+        {
+            self.vehicle_heat = max(self.vehicle_heat - cvar("g_vehicle_spiderbot_minigun_cooldown"),0);
+            if(self.tur_head.attack_finished_single < time)
+            {
+                self.vehicle_heat = 0;
+                self.owner.vehicle_heat = 0;
+            }
+            else
+            {
+                if(self.tur_head.uzi_bulletcounter < time)
+                {
+                    self.tur_head.uzi_bulletcounter = time + 0.2;
+                    self.owner.vehicle_heat  = self.vehicle_heat;
+                }
+                else
+                    self.owner.vehicle_heat = 1;
+            }
+        }
+        else
+            self.owner.vehicle_heat = max(self.owner.vehicle_heat - cvar("g_vehicle_spiderbot_minigun_cooldown"),0);
+
+}
+
+float spiderbot_pplug()
+{
+    vector ad;
+    entity player,spider;
+    float ftmp,ftmp2;
+
+    player = self;
+    spider = self.vehicle;
+
+/*
+	self.BUTTON_ATCK = 0;
+	self.button1 = 0;
+	self.BUTTON_JUMP = 0;
+	self.BUTTON_ATCK2 = 0;
+
+
+	self.BUTTON_HOOK = 0;
+	self.BUTTON_INFO = 0;
+	self.button8 = 0;
+	self.BUTTON_CHAT = 0;
+	self.BUTTON_USE = 0;
+*/
+
+    player.BUTTON_ZOOM = 0;
+    player.BUTTON_CROUCH = 0;
+
+
+    if(player.BUTTON_USE)
+    {
+        self = spider;
+        spiderbot_exit(0);
+        self = player;
+        return 0;
+    }
+
+    player.exteriormodeltoclient = spider.tur_head;
+
+    spider.tur_head.angles_x *= -1;
+    spider.angles_x *= -1;
+    //player.angles_x *= -1;
+    makevectors(spider.angles);
+
+    //ad = player.v_angle - (spider.tur_head.angles + spider.angles);
+    ad = player.v_angle -  (spider.tur_head.angles + spider.angles);
+
+    // Rotate head
+    ftmp = cvar("g_vehicle_spiderbot_head_turnspeed") / server_fps;
+    ftmp2 = ftmp * -1;
+    spider.tur_head.angles_y += bound(ftmp2,shortangle_f(ad_y,spider.tur_head.angles_y),ftmp);
+    spider.tur_head.angles_y = bound(cvar("g_vehicle_spiderbot_head_turnlimit") * -1,spider.tur_head.angles_y,cvar("g_vehicle_spiderbot_head_turnlimit"));
+
+    // Pitch head
+    ftmp = cvar("g_vehicle_spiderbot_head_pitchspeed") / server_fps;
+    ftmp2 = ftmp * -1;
+    spider.tur_head.angles_x += bound(ftmp2,shortangle_f(ad_x,spider.tur_head.angles_x),ftmp);
+    spider.tur_head.angles_x = bound(cvar("g_vehicle_spiderbot_head_pitchlimit_down"),spider.tur_head.angles_x,cvar("g_vehicle_spiderbot_head_pitchlimit_up"));
+
+    spider.tur_head.angles_x *= -1;
+    spider.angles_x *= -1;
+    //player.angles_x *= -1;
+
+    // Turn Body
+    ftmp = cvar("g_vehicle_spiderbot_turnspeed") / server_fps;
+    ftmp2 = ftmp * -1;
+    ftmp = bound(ftmp2,spider.tur_head.angles_y,ftmp);
+
+    self = spider;
+    if(spider.flags & FL_ONGROUND)
+    {
+        if(player.BUTTON_JUMP)
+        {
+            player.BUTTON_JUMP = 0;
+            spider.anim_start = MODEL_SPIDERBOT_JUMP_START;
+            spider.anim_end   = MODEL_SPIDERBOT_JUMP_END;
+            spider.velocity   = v_forward * 700 + v_up * 600;
+        }
+        else
+        {
+            if(vlen(player.movement) == 0)
+            {
+                movelib_beak_simple(cvar("g_vehicle_spiderbot_speed_stop"));
+                spider.anim_start = 0;
+                spider.anim_end = 0;
+            }
+            else
+            {
+                spider.angles_y = safeangle(spider.angles_y + ftmp);
+                spider.tur_head.angles_y -= ftmp;
+
+                if(player.movement_x != 0)
+                {
+                    if(player.movement_x > 0)
+                    {
+                        player.movement_x = 1;
+                        spider.anim_start = MODEL_SPIDERBOT_FORWARD_START;
+                        spider.anim_end   = MODEL_SPIDERBOT_FORWARD_END;
+                    }
+                    else if(player.movement_x < 0)
+                    {
+                        player.movement_x = -1;
+                        spider.anim_start = MODEL_SPIDERBOT_BACKWARDS_START;
+                        spider.anim_end   = MODEL_SPIDERBOT_BACKWARDS_END;
+
+                    }
+                    player.movement_y = 0;
+                    movelib_move_simple(normalize(v_forward * player.movement_x),cvar("g_vehicle_spiderbot_speed_walk"),cvar("g_vehicle_spiderbot_movement_inertia"));
+                }
+                else if(player.movement_y != 0)
+                {
+                    if(player.movement_y < 0)
+                    {
+                        player.movement_y = -1;
+                        spider.anim_start = MODEL_SPIDERBOT_LEFT_START;
+                        spider.anim_end   = MODEL_SPIDERBOT_LEFT_END;
+                    }
+                    else if(player.movement_y > 0)
+                    {
+                        player.movement_y = 1;
+                        spider.anim_start = MODEL_SPIDERBOT_RIGHT_START;
+                        spider.anim_end   = MODEL_SPIDERBOT_RIGHT_END;
+                    }
+                    movelib_move_simple(normalize(v_right * player.movement_y),cvar("g_vehicle_spiderbot_speed_strafe"),cvar("g_vehicle_spiderbot_movement_inertia"));
+                }
+
+            }
+        }
+        movelib_groundalign4point(300,100,0.25);
+    }
+
+    anim_do();
+    spiderbot_miniguns_do();
+    spiderbot_rocket_do();
+    vehicle_stdproc_regen();
+
+    player.BUTTON_ATCK = player.BUTTON_ATCK2 = 0;
+    player.rockets = spider.tur_head.frame;
+
+    if(spider.gun2.cnt <= time)
+        player.rockets_reload = 1;
+    else
+        player.rockets_reload = 1 - ((spider.gun2.cnt - time) /spider.attack_finished_single);
+
+    self = player;
+
+    setorigin(player,spider.origin + '0 0 64');
+    player.velocity = spider.velocity;
+
+    return 1;
+}
+
+void spiderbot_think()
+{
+    if(self.flags & FL_ONGROUND)
+    {
+        movelib_beak_simple(cvar("g_vehicle_spiderbot_speed_stop"));
+        //movelib_groundalign4point(300,100);
+    }
+
+    self.nextthink = time;
+}
+
+void spiderbot_enter()
+{
+    self.owner = other;
+
+    self.event_damage         = vehicle_stdproc_damage ;
+    self.colormap             = self.owner.colormap;
+    self.tur_head.colormap    = self.owner.colormap;
+    self.vehicle_hudmodel.viewmodelforclient = self.owner;
+    self.nextthink = 0;
+    self.owner.angles         = self.angles;
+    self.owner.takedamage     = DAMAGE_NO;
+    self.owner.solid          = SOLID_NOT;
+    self.owner.movetype       = MOVETYPE_NOCLIP;
+    self.owner.alpha          = -1;
+    self.owner.PlayerPhysplug = spiderbot_pplug;
+    self.owner.vehicle        = self;
+    self.owner.event_damage   = SUB_Null;
+    self.owner.hud            = HUD_SPIDEBOT;
+    self.owner.vehicle_health = (self.vehicle_health / cvar("g_vehicle_spiderbot_health"));
+    self.owner.vehicle_shield = (self.vehicle_shield / cvar("g_vehicle_spiderbot_shield"));
+    self.team                   = self.owner.team;
+
+    //setorigin(self.owner,self.origin);
+    //setattachment(self.owner,self,"");
+    //setorigin(self.owner,'0 0 0');
+
+    msg_entity = other;
+    WriteByte (MSG_ONE, SVC_SETVIEWPORT);
+    WriteEntity( MSG_ONE, self.vehicle_viewport);
+
+    WriteByte (MSG_ONE, SVC_SETVIEWANGLES);  // 10 = SVC_SETVIEWANGLES
+    WriteAngle(MSG_ONE, self.tur_head.angles_x + self.angles_x);    // tilt
+    WriteAngle(MSG_ONE, self.tur_head.angles_y + self.angles_y);    // yaw
+    WriteAngle(MSG_ONE, 0);    // roll
+    //WriteAngle(MSG_ONE, self.tur_head.angles_z + self.angles_z);    // roll
+
+    //self.owner.view_ofs = '0 0 0';
+    //self.tur_head.nodrawtoclient = self.owner;
+}
+
+void spiderbot_exit(float eject)
+{
+    entity e;
+
+    e = findchain(classname,"spiderbot_rocket");
+    while(e)
+    {
+        if(e.owner == self.owner)
+        {
+            e.realowner = self.owner;
+            e.owner = world;
+            //e.solid = SOLID_BBOX;
+            //e.think = SUB_Null;
+            //e.nextthink = -1;
+        }
+        e = e.chain;
+    }
+
+    self.velocity = '0 0 0';
+
+    msg_entity = self.owner;
+    WriteByte (MSG_ONE, SVC_SETVIEWPORT);
+    WriteEntity( MSG_ONE, self.owner);
+
+    WriteByte (MSG_ONE, SVC_SETVIEWANGLES);  // 10 = SVC_SETVIEWANGLES
+    WriteAngle(MSG_ONE, 0);    // tilt
+    WriteAngle(MSG_ONE, self.angles_y);    // yaw
+    WriteAngle(MSG_ONE, 0);    // roll
+
+    //setattachment(self.owner,world,"");
+    self.think = spiderbot_think;
+    self.nextthink = time;
+    self.owner.takedamage     = DAMAGE_AIM;
+    self.owner.solid          = SOLID_SLIDEBOX;
+    self.owner.movetype       = MOVETYPE_WALK;
+
+    setsize(self.owner,PL_MIN,PL_MAX);
+
+    self.owner.alpha          = 1;
+    self.owner.PlayerPhysplug = SUB_Null;
+    self.owner.vehicle        = world;
+	self.owner.view_ofs       = PL_VIEW_OFS;
+	self.owner.hud            = HUD_NORMAL;
+	self.owner.event_damage   = PlayerDamage;
+
+	self.colormap            = 1024;
+	self.tur_head.colormap   = 1024;
+    self.team                = -1;
+
+	self.vehicle_hudmodel.viewmodelforclient = self;
+	self.tur_head.nodrawtoclient             = self;
+
+    setattachment(self.owner,world,"");
+
+	makevectors(self.angles);
+	if(eject)
+	{
+	    setorigin(self.owner,self.origin + v_forward * 100 + '0 0 64');
+	    self.owner.velocity = (v_up + v_forward * 0.25) * 750;
+	}
+	else
+        setorigin(self.owner,self.origin - v_forward * 200 + '0 0 64');
+
+    self.owner = world;
+}
+
+void spiderbot_touch()
+{
+    if(self.owner)
+    {
+        if(vlen(self.velocity) == 0)
+            return;
+
+        if(other.classname != "player")
+            return;
+
+        //todo: add check for velocity here (so we dont cush players runing onto us from behind)
+
+        Damage(other,self,self.owner,cvar("g_vehicle_spiderbot_crush_dmg"),DEATH_TURRET,'0 0 0', normalize(other.origin - self.origin) * cvar("g_vehicle_spiderbot_crush_force") );
+        return;
+    }
+
+    if(other.classname != "player")
+        return;
+
+    if(other.deadflag != DEAD_NO)
+        return;
+
+    if(other.vehicle != world)
+        return;
+
+    spiderbot_enter();
+}
+
+float spiderbot_customizeentityforclient()
+{
+    if(self.deadflag == DEAD_DEAD)
+        return FALSE;
+
+    return TRUE;
+}
+
+//void spiderbot_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force);
+void spiderbot_spawn()
+{
+    self.think = spiderbot_think;
+    self.nextthink = time;
+
+    self.vehicle_health = CCVAR("_health");
+    self.vehicle_shield = CCVAR("_shield");
+    self.event_damage = vehicle_stdproc_damage;
+    self.iscreature = TRUE;
+    self.movetype   = MOVETYPE_WALK;
+    self.solid      = SOLID_SLIDEBOX;
+    self.takedamage = DAMAGE_AIM;
+    self.touch      = spiderbot_touch;
+    self.alpha      = self.tur_head.alpha = self.gun1.alpha = self.gun2.alpha = 1;
+    self.tur_head.angles = '0 0 0';
+	self.colormap = 1024;
+	self.tur_head.colormap = 1024;
+	self.deadflag    = DEAD_NO;
+    self.bot_attack = TRUE;
+
+    setsize(self,spiderbot_MIN,spiderbot_MAX);
+    setorigin(self,self.tur_aimpos);
+    pointparticles(particleeffectnum("teleport"), self.origin + '0 0 64', '0 0 0', 1);
+}
+
+void spiderbot_blowup()
+{
+    sound (self, CHAN_PROJECTILE, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
+    pointparticles(particleeffectnum("rocket_explode"), findbetterlocation (self.origin, 16), '0 0 0', 1);
+
+    RadiusDamage (self, self, 250, 15, 250, world, 250, DEATH_TURRET, world);
+
+    self.alpha = self.tur_head.alpha = self.gun1.alpha = self.gun2.alpha = -1;
+    self.nextthink  = time + 10;
+    self.think      = spiderbot_spawn;
+
+    setorigin(self,self.tur_aimpos);
+}
+
+void spiderbot_die()
+{
+
+    self.health = 0;
+    self.event_damage = SUB_Null;
+    self.iscreature = FALSE;
+    self.solid      = SOLID_NOT;
+    self.takedamage = DAMAGE_NO;
+    self.touch      = SUB_Null;
+    self.nextthink  = time + random() * 2;
+    self.think      = spiderbot_blowup;
+    self.deadflag    = DEAD_DEAD;
+	self.vehicle_hudmodel.viewmodelforclient = self;
+	self.frame = 0;
+	self.tur_head.frame = 0;
+
+}
+
+void vewhicle_spiderbot_dinit()
+{
+
+    server_fps = (1 / sys_ticrate);
+
+    addstat(STAT_HUD, AS_INT,  hud);
+	addstat(STAT_SPIDERBOT_ROCKETS, AS_INT,   rockets);
+	addstat(STAT_SPIDERBOT_RELOAD,  AS_FLOAT, rockets_reload);
+	addstat(STAT_SPIDERBOT_HEAT,    AS_FLOAT, vehicle_heat);
+	addstat(STAT_SPIDERBOT_HEALTH,  AS_FLOAT, vehicle_health);
+	addstat(STAT_SPIDERBOT_SHIELD,  AS_FLOAT, vehicle_shield);
+
+    if (self.netname == "")      self.netname     = "spiderbot";
+
+    self.tur_head = spawn();
+    self.gun1 = spawn();
+    self.gun2 = spawn();
+    self.vehicle_viewport = spawn();
+    self.gravity = 2;
+    self.vehicle_hudmodel = spawn();
+    self.vehicle_flags = VHF_HASSHIELD | VHF_SHIELDREGEN | VHF_HEALTHREGEN;
+    self.cvar_basename = "g_vehicle_spiderbot";
+
+    setmodel (self.vehicle_hudmodel, "models/spiderbot/cp.md3");
+    setmodel (self.vehicle_viewport, "models/null.md3");
+    setmodel(self,"models/spiderbot/spiderbot.dpm");
+    setmodel(self.tur_head,"models/spiderbot/spiderbot_top.dpm");
+    setmodel(self.gun1,"models/spiderbot/spiderbot_barrels.dpm");
+    setmodel(self.gun2,"models/spiderbot/spiderbot_barrels.dpm");
+
+    setattachment(self.tur_head,self,"tag_head");
+    setattachment(self.vehicle_hudmodel,self.tur_head,"");
+    setattachment(self.vehicle_viewport,self.vehicle_hudmodel,"");
+    setattachment(self.gun1,self.tur_head,"tag_hardpoint01");
+    setattachment(self.gun2,self.tur_head,"tag_hardpoint02");
+
+    self.tur_head.owner = self;
+    self.customizeentityforclient          = spiderbot_customizeentityforclient;
+
+    setorigin(self.vehicle_viewport,'35 0 -14');
+    self.tur_aimpos = self.origin;
+    spiderbot_spawn();
+
+    self.vehicle_die = spiderbot_die;
+    self.vehicle_exit = spiderbot_exit;
+}
+
+void spawnfunc_vehicle_spiderbot()
+{
+    // g_turrets_common_precash();
+
+    precache_model ( "models/spiderbot/cr.md3");
+    precache_model ( "models/vhshield.md3");
+    precache_model ( "models/spiderbot/cp.md3");
+    precache_model ( "models/spiderbot/spiderbot.dpm");
+    precache_model ( "models/spiderbot/spiderbot_top.dpm");
+    precache_model ( "models/spiderbot/spiderbot_barrels.dpm");
+
+    precache_model ( "models/turrets/rocket.md3");
+    precache_sound ( "weapons/rocket_impact.wav" );
+
+    self.team                = -1;
+    self.think = vewhicle_spiderbot_dinit;
+    self.nextthink = time + 0.5;
+}

Added: trunk/data/qcsrc/server/vehicles/vehicles.qc
===================================================================
--- trunk/data/qcsrc/server/vehicles/vehicles.qc	                        (rev 0)
+++ trunk/data/qcsrc/server/vehicles/vehicles.qc	2009-06-12 10:46:52 UTC (rev 7005)
@@ -0,0 +1,183 @@
+void vehicle_stdproc_enter()
+{
+    self.owner = other;
+
+    msg_entity = other;
+    WriteByte (MSG_ONE, SVC_SETVIEWPORT);
+    WriteEntity( MSG_ONE, self.vehicle_viewport);
+
+    WriteByte (MSG_ONE, SVC_SETVIEWANGLES);
+    WriteAngle(MSG_ONE, self.vehicle_viewport.angles_x + self.angles_x);    // tilt
+    WriteAngle(MSG_ONE, self.vehicle_viewport.angles_y + self.angles_y);    // yaw
+    WriteAngle(MSG_ONE, self.vehicle_viewport.angles_z + self.angles_z);    // flip
+
+    //setattachment(other,self,"");
+    self.nextthink = 0;
+    self.owner.takedamage     = DAMAGE_NO;
+    self.owner.solid          = SOLID_NOT;
+    self.owner.alpha          = -1;
+    //self.owner.PlayerPhysplug = spiderbot_pplug;
+    self.owner.vehicle           = self;
+    self.owner.event_damage   = SUB_Null;
+    self.owner.vehicle_health             = (self.health / cvar("g_vehicle_spiderbot_health"));
+    self.owner.hud            = HUD_SPIDEBOT;
+    self.colormap             = self.owner.colormap;
+    self.tur_head.colormap    = self.owner.colormap;
+    self.vehicle_hudmodel.viewmodelforclient   = self.owner;
+    //self.tur_head.nodrawtoclient = self.owner;
+
+
+}
+
+void vehicle_stdproc_exit(float eject)
+{
+    self.velocity = '0 0 0';
+
+    msg_entity = self.owner;
+    WriteByte (MSG_ONE, SVC_SETVIEWPORT);
+    WriteEntity( MSG_ONE, self.owner);
+
+    //setattachment(self.owner,world,"");
+    //self.think = spiderbot_think;
+    //self.nextthink = time;
+
+    self.owner.takedamage     = DAMAGE_AIM;
+    self.owner.solid          = SOLID_SLIDEBOX;
+    self.owner.alpha          = 1;
+    self.owner.PlayerPhysplug = SUB_Null;
+    self.owner.vehicle        = world;
+	self.owner.view_ofs       = PL_VIEW_OFS;
+	self.owner.hud            = HUD_NORMAL;
+	self.owner.event_damage   = PlayerDamage;
+	self.colormap = 1024;
+	self.tur_head.colormap = 1024;
+	self.vehicle_hudmodel.viewmodelforclient   = self;
+	//self.tur_head.nodrawtoclient = self;
+
+	if(eject)
+	{
+	    makevectors(self.angles);
+	    setorigin(self.owner,self.origin + v_forward * 100);
+	    self.owner.velocity = (v_up + v_forward * 0.25) * 750;
+	}
+	else
+        setorigin(self.owner,self.origin - v_forward * 200);
+
+    self.owner = world;
+}
+
+void vehicle_stdproc_regen()
+{
+    float smax,hmax;
+
+    smax = CCVAR("_shield");
+    hmax = CCVAR("_health");
+
+    if(self.vehicle_flags & VHF_HASSHIELD)
+    if(self.vehicle_flags & VHF_SHIELDREGEN)
+    if(self.vehicle_shield < smax)
+    if(self.dmg_time + CCVAR("_shield_regen_dmgpause") < time)
+    {
+        self.vehicle_shield = min(self.vehicle_shield + CCVAR("_shield_regen") / server_fps,smax);
+
+        if(self.owner)
+            self.owner.vehicle_shield = self.vehicle_shield / cvar(strcat(self.cvar_basename,"_shield"));
+    }
+
+    if(self.vehicle_flags & VHF_HEALTHREGEN)
+    if(self.dmg_time + CCVAR("_health_regen_dmgpause") < time)
+    if(self.vehicle_health < hmax)
+    {
+        self.vehicle_health = min(self.vehicle_health + CCVAR("_health_regen") / server_fps,hmax);
+
+        if(self.owner)
+            self.owner.vehicle_health = self.vehicle_health / CCVAR("_health");
+    }
+}
+
+void shieldhit_think()
+{
+    self.alpha = self.alpha - 0.125;
+    if not(self.alpha <= 0)
+    {
+        self.nextthink = time;
+    }
+    else
+    {
+        setmodel(self,"");
+        self.alpha = -1;
+    }
+    //self.think = SUB_Remove;
+}
+
+void vehicle_stdproc_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+{
+
+    float ddmg_take;
+
+    self.dmg_time = time;
+
+    if((self.vehicle_flags & VHF_HASSHIELD) && (self.vehicle_shield > 0))
+    {
+        if not (self.tur_head.enemy)
+            self.tur_head.enemy = spawn();
+
+        entity sh;
+
+        sh = self.tur_head.enemy;
+        sh.colormod = '1 1 1';
+        sh.alpha = 0.5;
+        sh.scale  = (128 / vlen(self.maxs - self.mins))*2;
+        //sh.scale = 1.25;
+
+        sh.effects = EF_LOWPRECISION;
+        sh.angles = vectoangles(normalize(hitloc - self.origin)) - self.angles;
+
+        setmodel(sh,"models/vhshield.md3");
+        setattachment(sh,self,"");
+        sh.think = shieldhit_think;
+        sh.nextthink = time;
+
+
+        self.vehicle_shield -= damage;
+        if(self.vehicle_shield < 0)
+        {
+            sh.colormod = '10 0 -1';
+            ddmg_take = fabs(self.vehicle_shield);
+            self.vehicle_shield = 0;
+
+            self.vehicle_health -= ddmg_take;
+        }
+    }
+    else
+        self.vehicle_health -= damage;
+
+
+    if(self.owner)
+    {
+        self.owner.vehicle_health = self.vehicle_health / CCVAR("_health");
+
+        if(self.vehicle_flags & VHF_HASSHIELD)
+            self.owner.vehicle_shield = self.vehicle_shield / cvar(strcat(self.cvar_basename,"_shield"));
+
+    }
+
+    if(self.vehicle_health <= 0)
+    {
+        if(self.owner)
+            self.vehicle_exit(VHEF_EJECT);
+
+        self.vehicle_die();
+    }
+
+
+}
+
+void bugmenot()
+{
+    self.vehicle_exit       = self.vehicle_exit;
+    self.vehicle_enter      = self.vehicle_exit;
+    self.vehicle_die        = self.vehicle_exit;
+    self.vehicle_spawn      = self.vehicle_exit;
+    self.vehicle_message    = self.vehicle_exit;
+}

Added: trunk/data/qcsrc/server/vehicles/vehicles.qh
===================================================================
--- trunk/data/qcsrc/server/vehicles/vehicles.qh	                        (rev 0)
+++ trunk/data/qcsrc/server/vehicles/vehicles.qh	2009-06-12 10:46:52 UTC (rev 7005)
@@ -0,0 +1,52 @@
+//#define VEHICLES_ENABLED
+#ifdef VEHICLES_ENABLED
+
+#message "with tZork vehicles (experimental)"
+
+float SVC_SETVIEWPORT = 5;    // Net.Protocol 0x05
+float SVC_SETVIEWANGLES = 10; // Net.Protocol 0x0A
+float SVC_UPDATEENTITY = 128; // Net.Protocol 0x80
+
+#define CCVAR(part) cvar(strcat(self.cvar_basename,part))
+//.string cvar_basename;
+
+.float vehicle_flags;
+#define VHF_HASSHIELD 2
+#define VHF_SHIELDREGEN 4
+#define VHF_HEALTHREGEN 8
+
+.float hud;
+.float rockets;
+.float rockets_reload;
+.entity gun1;
+.entity gun2;
+
+.float vehicle_health;
+.float vehicle_shield;
+.float vehicle_heat;
+
+.entity vehicle;
+.entity vehicle_viewport;
+.entity vehicle_hudmodel;
+
+.float anim_start;
+.float anim_end;
+
+.float dmg_time;
+
+float server_fps;
+
+#define VHEF_NORMAL 0
+#define VHEF_EJECT 1
+
+.void(float exit_flags) vehicle_exit;
+.void() vehicle_enter;
+.void() vehicle_die;
+.void() vehicle_spawn;
+.float(float message) vehicle_message;
+
+#include "vehicles.qc"
+#include "spiderbot.qc"
+#include "racer.qc"
+
+#endif

Modified: trunk/data/qcsrc/server/w_common.qc
===================================================================
--- trunk/data/qcsrc/server/w_common.qc	2009-06-12 10:21:52 UTC (rev 7004)
+++ trunk/data/qcsrc/server/w_common.qc	2009-06-12 10:46:52 UTC (rev 7005)
@@ -442,54 +442,33 @@
 		CSQCProjectile(proj, TRUE, PROJECTILE_BULLET, TRUE);
 }
 
-/*
- * not used any more
+
 void fireBullet (vector start, vector dir, float spread, float damage, float force, float dtype, float tracer)
 {
 	vector  end;
-	local entity e;
+	//local entity e;
 
-	if(cvar("g_ballistics_force"))
-	{
-		if (DEATH_ISWEAPON(dtype, WEP_SHOTGUN))
-			fireBallisticBullet(start, dir, spread, cvar("g_ballistics_force_shotgun_speed"), 5, damage, 0, force, dtype, 0, 1, cvar("g_ballistics_force_shotgun_bulletconstant"));
-		else
-			fireBallisticBullet(start, dir, spread, cvar("g_ballistics_force_uzi_speed"), 5, damage, 0, force, dtype, 0, 1, cvar("g_ballistics_force_shotgun_bulletconstant"));
-		return;
-	}
-
-	dir = dir + randomvec() * spread;
+	dir = normalize(dir + randomvec() * spread);
 	end = start + dir * MAX_SHOT_DISTANCE;
 	if(self.antilag_debug)
 		traceline_antilag (self, start, end, FALSE, self, self.antilag_debug);
 	else
 		traceline_antilag (self, start, end, FALSE, self, ANTILAG_LATENCY(self));
 
-	if (tracer)
-	{
-		e = spawn();
-		e.owner = self;
-		e.movetype = MOVETYPE_FLY;
-		e.solid = SOLID_NOT;
-		e.think = SUB_Remove;
-		e.nextthink = time + vlen(trace_endpos - start) / 6000;
-		e.velocity = dir * 6000;
-		e.angles = vectoangles(e.velocity);
-		setorigin (e, start);
-		e.flags = FL_PROJECTILE;
+    end = trace_endpos;
 
-		CSQCProjectile(e, TRUE, PROJECTILE_BULLET, TRUE);
-	}
-
 	if ((trace_fraction != 1.0) && (pointcontents (trace_endpos) != CONTENT_SKY))
 	{
+		pointparticles(particleeffectnum("TE_KNIGHTSPIKE"),end,trace_plane_normal * 2500,1);
 		if (trace_ent.solid == SOLID_BSP && !(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT))
 			Damage_DamageInfo(trace_endpos, damage, 0, 0, dir * force, dtype);
 		Damage (trace_ent, self, self, damage, dtype, trace_endpos, dir * force);
+		//void(float effectnum, vector org, vector vel, float howmany) pointparticles = #337; // same as in CSQC
 	}
+	trace_endpos = end;
 }
-*/
 
+
 void W_PrepareExplosionByDamage(entity attacker, void() explode)
 {
 	self.takedamage = DAMAGE_NO;

Added: trunk/data/vehicle_racer.cfg
===================================================================
--- trunk/data/vehicle_racer.cfg	                        (rev 0)
+++ trunk/data/vehicle_racer.cfg	2009-06-12 10:46:52 UTC (rev 7005)
@@ -0,0 +1,15 @@
+set g_vehicle_racer_health             250
+set g_vehicle_racer_turnspeed          360
+set g_vehicle_racer_speed_stop         0.1	
+set g_vehicle_racer_speed_forward      2000
+set g_vehicle_racer_speed_strafe       1000
+set g_vehicle_racer_movement_inertia   0.15
+set g_vehicle_racer_power_air          0
+set g_vehicle_racer_power_solid        5000
+set g_vehicle_racer_drag               0.25
+set g_vehicle_racer_dragexp            0.75
+set g_vehicle_racer_downforce          0.05
+set g_vehicle_racer_springlength       200
+set g_vehicle_racer_inert              0.25
+set g_vehicle_racer_drag2              0.01
+set g_vehicle_racer_drag2exp           0.85

Added: trunk/data/vehicle_spiderbot.cfg
===================================================================
--- trunk/data/vehicle_spiderbot.cfg	                        (rev 0)
+++ trunk/data/vehicle_spiderbot.cfg	2009-06-12 10:46:52 UTC (rev 7005)
@@ -0,0 +1,45 @@
+set g_vehicle_spiderbot_health                   875
+set g_vehicle_spiderbot_health_regen       	 10
+set g_vehicle_spiderbot_health_regen_dmgpause    10
+
+set g_vehicle_spiderbot_shield          125
+set g_vehicle_spiderbot_shield_block    1
+set g_vehicle_spiderbot_shield_regen    25
+set g_vehicle_spiderbot_shield_regen_dmgpause 0.25
+
+set g_vehicle_spiderbot_turnspeed       90
+set g_vehicle_spiderbot_head_turnspeed  120
+set g_vehicle_spiderbot_head_turnlimit  120
+set g_vehicle_spiderbot_head_pitchspeed 60
+set g_vehicle_spiderbot_head_pitchlimit_up   8
+set g_vehicle_spiderbot_head_pitchlimit_down -24
+
+set g_vehicle_spiderbot_speed_stop         50
+set g_vehicle_spiderbot_speed_walk         400
+set g_vehicle_spiderbot_speed_strafe       300
+set g_vehicle_spiderbot_movement_inertia   0.25
+
+set g_vehicle_spiderbot_minigun_bulletconstant 200
+set g_vehicle_spiderbot_minigun_damage         20
+set g_vehicle_spiderbot_minigun_spread         0.015
+set g_vehicle_spiderbot_minigun_speed          50000
+set g_vehicle_spiderbot_minigun_refire         0.025
+set g_vehicle_spiderbot_minigun_heat           0.015
+set g_vehicle_spiderbot_minigun_cooldown       0.015
+
+set g_vehicle_spiderbot_rocket_damage     75
+set g_vehicle_spiderbot_rocket_edgedamage 15
+set g_vehicle_spiderbot_rocket_force      150
+set g_vehicle_spiderbot_rocket_radius     150
+set g_vehicle_spiderbot_rocket_reload     2.5
+set g_vehicle_spiderbot_rocket_refire     0.15
+set g_vehicle_spiderbot_rocket_speed      900
+set g_vehicle_spiderbot_rocket_turnrate   0.25
+set g_vehicle_spiderbot_rocket_noise      0.25
+
+set g_vehicle_spiderbot_crush_dmg         50
+set g_vehicle_spiderbot_crush_force       50
+
+
+set cl_vehicle_spiderbot_cross_alpha 0.4
+set cl_vehicle_spiderbot_cross_size 1



More information about the nexuiz-commits mailing list