[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