r4576 - in trunk/data: gfx qcsrc/client qcsrc/common qcsrc/server

DONOTREPLY at icculus.org DONOTREPLY at icculus.org
Thu Oct 2 07:37:17 EDT 2008


Author: div0
Date: 2008-10-02 07:37:16 -0400 (Thu, 02 Oct 2008)
New Revision: 4576

Added:
   trunk/data/gfx/teamradar_icon_1.tga
   trunk/data/gfx/teamradar_icon_2.tga
   trunk/data/gfx/teamradar_ping.tga
   trunk/data/qcsrc/client/waypointsprites.qc
   trunk/data/qcsrc/client/waypointsprites.qh
Modified:
   trunk/data/qcsrc/client/Main.qc
   trunk/data/qcsrc/client/View.qc
   trunk/data/qcsrc/client/csqc_builtins.qc
   trunk/data/qcsrc/client/main.qh
   trunk/data/qcsrc/client/miscfunctions.qc
   trunk/data/qcsrc/client/progs.src
   trunk/data/qcsrc/client/teamradar.qc
   trunk/data/qcsrc/client/teamradar.qh
   trunk/data/qcsrc/common/constants.qh
   trunk/data/qcsrc/server/cl_client.qc
   trunk/data/qcsrc/server/ctf.qc
   trunk/data/qcsrc/server/keyhunt.qc
   trunk/data/qcsrc/server/keyhunt.qh
   trunk/data/qcsrc/server/mode_onslaught.qc
   trunk/data/qcsrc/server/race.qc
   trunk/data/qcsrc/server/waypointsprites.qc
Log:
new waypointsprite system, onslaught not yet supported


Added: trunk/data/gfx/teamradar_icon_1.tga
===================================================================
(Binary files differ)


Property changes on: trunk/data/gfx/teamradar_icon_1.tga
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/data/gfx/teamradar_icon_2.tga
===================================================================
(Binary files differ)


Property changes on: trunk/data/gfx/teamradar_icon_2.tga
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/data/gfx/teamradar_ping.tga
===================================================================
(Binary files differ)


Property changes on: trunk/data/gfx/teamradar_ping.tga
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Modified: trunk/data/qcsrc/client/Main.qc
===================================================================
--- trunk/data/qcsrc/client/Main.qc	2008-10-02 07:04:58 UTC (rev 4575)
+++ trunk/data/qcsrc/client/Main.qc	2008-10-02 11:37:16 UTC (rev 4576)
@@ -55,6 +55,7 @@
 }
 
 string forcefog;
+void WaypointSprite_Init();
 void CSQC_Init(void)
 {
 #ifdef USE_FTE
@@ -114,6 +115,26 @@
 	GetTeam(COLOR_SPECTATOR, true); // add specs first
 
 	cvar_clientsettemp("_supports_weaponpriority", "1");
+
+
+
+
+	cs_project_is_b0rked = TRUE;
+	R_SetView(VF_VIEWPORT, '0 0 0', '640 480 0');
+	R_SetView(VF_FOV, '90 90 0');
+	R_SetView(VF_ORIGIN, '0 0 0');
+	R_SetView(VF_ANGLES, '0 0 0');
+	R_SetView(VF_PERSPECTIVE, 1);
+	makevectors('0 0 0');
+	vector v;
+	v = cs_project(v_forward);
+	if(v_x - 320 < +1)
+	if(v_x - 320 > -1)
+	if(v_y - 240 < +1)
+	if(v_y - 240 > -1)
+		cs_project_is_b0rked = FALSE;
+
+	WaypointSprite_Init();
 }
 
 // CSQC_Shutdown : Called every time the CSQC code is shutdown (changing maps, quitting, etc)
@@ -511,8 +532,10 @@
 		Ent_Laser();
 	else if(self.enttype == ENT_CLIENT_NAGGER)
 		Ent_Nagger();
+	else if(self.enttype == ENT_CLIENT_WAYPOINT)
+		Ent_WaypointSprite();
 	else
-		error("unknown entity type in CSQC_Ent_Update\n");
+		error("unknown entity type in CSQC_Ent_Update: ", ftos(self.enttype), "\n");
 	
 };
 // Destructor, but does NOT deallocate the entity by calling remove(). Also
@@ -558,6 +581,8 @@
 	{
 		Ent_PointParticles_Remove();
 	}
+	else if(self.enttype == ENT_CLIENT_WAYPOINT)
+		Ent_RemoveWaypointSprite();
 
 	self.enttype = 0;
 	self.classname = "";

Modified: trunk/data/qcsrc/client/View.qc
===================================================================
--- trunk/data/qcsrc/client/View.qc	2008-10-02 07:04:58 UTC (rev 4575)
+++ trunk/data/qcsrc/client/View.qc	2008-10-02 11:37:16 UTC (rev 4576)
@@ -170,7 +170,7 @@
 
 	float frustumx, frustumy, fovx, fovy;
 	frustumy = tan(fov * 0.00872664625997164788) * 0.75 * current_viewzoom;
-	frustumx = frustumy * cvar("vid_width") / cvar("vid_height") / cvar("vid_pixelheight");
+	frustumx = frustumy * vid_width / vid_height / cvar("vid_pixelheight");
 	fovx = atan2(frustumx, 1) / 0.00872664625997164788;
 	fovy = atan2(frustumy, 1) / 0.00872664625997164788;
 
@@ -189,6 +189,32 @@
 	entity e;
 	float fov;
 
+	// Render the Scene
+	view_origin = pmove_org + '0 0 1' * getstati(STAT_VIEWHEIGHT);
+	view_angles = input_angles;
+	makevectors(view_angles);
+	view_forward = v_forward;
+	view_right = v_right;
+	view_up = v_up;
+
+#if 0
+	if(cs_project_is_b0rked)
+	{
+#endif
+		vid_width = cvar("vid_width");
+		vid_height = cvar("vid_height");
+#if 0
+	}
+	else
+	{
+		// THIS IS BROKEN if you had just shot (kicktime)
+		vector v;
+		v = cs_project(view_origin + 1024 * view_forward);
+		vid_width = floor(v_x * 2 + 0.5);
+		vid_height = floor(v_y * 2 + 0.5);
+	}
+#endif
+
 	Fog_Force();
 
 	drawframetime = max(0.000001, time - drawtime);
@@ -263,15 +289,6 @@
 
 	R_AddEntities(MASK_NORMAL | MASK_ENGINE | MASK_ENGINEVIEWMODELS);
 
-	// Render the Scene
-	
-	view_origin = pmove_org + '0 0 1' * getstati(STAT_VIEWHEIGHT);
-	view_angles = input_angles;
-	makevectors(view_angles);
-	view_forward = v_forward;
-	view_right = v_right;
-	view_up = v_up;
-	
 	e = self;
 	for(self = world; (self = nextent(self)); )
 		if(self.draw)
@@ -310,6 +327,12 @@
 	}
 	else if(teamplay)
 		teamradar_view();
+
+	e = self;
+	for(self = world; (self = nextent(self)); )
+		if(self.draw2d)
+			self.draw2d();
+	self = e;
 }
 
 void Sbar_Draw();

Modified: trunk/data/qcsrc/client/csqc_builtins.qc
===================================================================
--- trunk/data/qcsrc/client/csqc_builtins.qc	2008-10-02 07:04:58 UTC (rev 4575)
+++ trunk/data/qcsrc/client/csqc_builtins.qc	2008-10-02 11:37:16 UTC (rev 4576)
@@ -147,7 +147,7 @@
 entity (.float fld, float match)					findchainflags = #450;
 entity (.entity fld, entity match)					findchainentity = #403;
 entity (.float fld, float match)					findchainfloat = #403;
-entity (entity start, .entity fld, float match)				findflags = #449;
+entity (entity start, .float fld, float match)				findflags = #449;
 
 float (string pattern, float caseinsensitive, float quiet)		search_begin = #444;
 void (float handle)							search_end = #445;

Modified: trunk/data/qcsrc/client/main.qh
===================================================================
--- trunk/data/qcsrc/client/main.qh	2008-10-02 07:04:58 UTC (rev 4575)
+++ trunk/data/qcsrc/client/main.qh	2008-10-02 11:37:16 UTC (rev 4576)
@@ -111,6 +111,7 @@
 .entity owner;
 
 .void(void) draw;
+.void(void) draw2d;
 float drawframetime;
 vector view_origin, view_angles, view_forward, view_right, view_up;
 
@@ -137,3 +138,6 @@
 float vote_waiting_for_me;
 
 float current_zoomfraction;
+
+float cs_project_is_b0rked;
+float vid_width, vid_height;

Modified: trunk/data/qcsrc/client/miscfunctions.qc
===================================================================
--- trunk/data/qcsrc/client/miscfunctions.qc	2008-10-02 07:04:58 UTC (rev 4575)
+++ trunk/data/qcsrc/client/miscfunctions.qc	2008-10-02 11:37:16 UTC (rev 4576)
@@ -209,3 +209,14 @@
 	}
 	return false;
 }
+
+float PI      = 3.14159265359;
+float DEG2RAD = 0.01745329252;
+vector rotate(vector v, float a)
+{
+	vector w;
+	// FTEQCC SUCKS AGAIN
+	w_x =      v_x * cos(a) + v_y * sin(a);
+	w_y = -1 * v_x * sin(a) + v_y * cos(a);
+	return w;
+}

Modified: trunk/data/qcsrc/client/progs.src
===================================================================
--- trunk/data/qcsrc/client/progs.src	2008-10-02 07:04:58 UTC (rev 4575)
+++ trunk/data/qcsrc/client/progs.src	2008-10-02 11:37:16 UTC (rev 4576)
@@ -11,6 +11,7 @@
 ../common/util.qh
 interpolate.qh
 teamradar.qh
+waypointsprites.qh
 
 main.qh
 
@@ -32,6 +33,7 @@
 View.qc
 interpolate.qc
 teamradar.qc
+waypointsprites.qc
 
 ../common/util.qc
 ../common/gamecommand.qc

Modified: trunk/data/qcsrc/client/teamradar.qc
===================================================================
--- trunk/data/qcsrc/client/teamradar.qc	2008-10-02 07:04:58 UTC (rev 4575)
+++ trunk/data/qcsrc/client/teamradar.qc	2008-10-02 11:37:16 UTC (rev 4576)
@@ -1,5 +1,3 @@
-float DEG2RAD = 0.01745329251994329576;
-
 float teamradar_angle; // player yaw angle
 vector teamradar_origin3d_in_texcoord; // player origin
 vector teamradar_origin2d; // 2D origin
@@ -21,9 +19,8 @@
 	vector out;
 	in -= teamradar_origin3d_in_texcoord;
 
-	out_x = in_y * sin(teamradar_angle * DEG2RAD) + in_x * cos(teamradar_angle * DEG2RAD);
-	out_y = in_y * cos(teamradar_angle * DEG2RAD) - in_x * sin(teamradar_angle * DEG2RAD);
-	out_y = - out_y; // WHY?!? TODO find out whether the map images are mirrored too
+	out = rotate(in, teamradar_angle * DEG2RAD);
+	out_y = - out_y; // screen space is reversed
 
 	out = out * teamradar_size;
 	out += teamradar_origin2d;
@@ -84,6 +81,23 @@
 	R_EndPolygon();
 };
 
+void draw_teamradar_icon(vector coord, float icon, float pingtime, vector rgb, float a)
+{
+	float dt;
+	vector v;
+
+	coord = teamradar_texcoord_to_2dcoord(teamradar_3dcoord_to_texcoord(coord));
+	drawpic(coord - '4 4 0', strcat("gfx/teamradar_icon_", ftos(icon)), '8 8 0', rgb, a, 0);
+	if(pingtime != 0)
+	{
+		dt = time - pingtime;
+		if(dt > 1)
+			return;
+		v = '2 2 0' * teamradar_size * dt;
+		drawpic(coord - 0.5 * v, "gfx/teamradar_ping", v, '1 1 1', 1 - dt, DRAWFLAG_ADDITIVE);
+	}
+}
+
 void() teamradar_view =
 {
 	local float color;
@@ -129,6 +143,8 @@
 	draw_teamradar_player(pmove_org, input_angles, '1 1 1');
 	for(tm = gps_start; tm != world; tm = tm.chain)
 		draw_teamradar_player(tm.origin, tm.angles, rgb);
+	for(tm = world; (tm = findflags(tm, teamradar_icon, 0xFFFFFF)); )
+		draw_teamradar_icon(tm.origin, tm.teamradar_icon, tm.teamradar_time, tm.teamradar_color, tm.alpha);
 
 	drawresetcliparea();
 };

Modified: trunk/data/qcsrc/client/teamradar.qh
===================================================================
--- trunk/data/qcsrc/client/teamradar.qh	2008-10-02 07:04:58 UTC (rev 4575)
+++ trunk/data/qcsrc/client/teamradar.qh	2008-10-02 11:37:16 UTC (rev 4576)
@@ -1 +1,6 @@
 void teamradar_view();
+
+// to make entities have dots on the team radar
+.float teamradar_icon;
+.float teamradar_time;
+.vector teamradar_color;

Added: trunk/data/qcsrc/client/waypointsprites.qc
===================================================================
--- trunk/data/qcsrc/client/waypointsprites.qc	                        (rev 0)
+++ trunk/data/qcsrc/client/waypointsprites.qc	2008-10-02 11:37:16 UTC (rev 4576)
@@ -0,0 +1,253 @@
+vector project_3d_to_2d(vector vec)
+{ 
+	vec = cs_project(vec);
+	if(cs_project_is_b0rked)
+	{
+		vec_x += vid_width / 2;
+		vec_y += vid_height / 2;
+	}
+	vec_x *= vid_conwidth / vid_width;
+	vec_y *= vid_conheight / vid_height;
+	return vec;
+}
+
+float waypointsprite_fadedistance;
+float waypointsprite_normdistance;
+float waypointsprite_minscale;
+float waypointsprite_minalpha;
+float waypointsprite_distancealphaexponent;
+float waypointsprite_timealphaexponent;
+
+.float rule;
+.string netname; // primary picture
+.string netname2; // secondary picture
+.string netname3; // tertiary picture
+.float team; // team that gets netname2
+.float lifetime;
+.float fadetime;
+.float maxdistance;
+.float hideflags;
+
+vector SPRITE_SIZE = '128 32 0';
+vector SPRITE_HOTSPOT = '64 32 0';
+
+void drawrotpic(vector org, float rot, string pic, vector sz, vector hotspot, vector rgb, float a, float f)
+{
+	vector v1, v2, v3, v4;
+
+	hotspot = -1 * hotspot;
+
+	// hotspot-relative coordinates of the corners
+	v1 = hotspot;
+	v2 = hotspot + '1 0 0' * sz_x;
+	v3 = hotspot + '1 0 0' * sz_x + '0 1 0' * sz_y;
+	v4 = hotspot                  + '0 1 0' * sz_y;
+
+	// rotate them, and make them absolute
+	v1 = rotate(v1, rot) + org;
+	v2 = rotate(v2, rot) + org;
+	v3 = rotate(v3, rot) + org;
+	v4 = rotate(v4, rot) + org;
+
+	// draw them
+	R_BeginPolygon(pic, f);
+	R_PolygonVertex(v1, '0 0 0', rgb, a);
+	R_PolygonVertex(v2, '1 0 0', rgb, a);
+	R_PolygonVertex(v3, '1 1 0', rgb, a);
+	R_PolygonVertex(v4, '0 1 0', rgb, a);
+	R_EndPolygon();
+}
+
+void Draw_WaypointSprite()
+{
+	string spriteimage;
+	float t;
+
+	if(self.lifetime)
+		self.alpha = pow(bound(0, (self.fadetime - time) / self.lifetime, 1), waypointsprite_timealphaexponent);
+	else
+		self.alpha = 1;
+
+	if(self.hideflags & 2)
+		return; // radar only
+
+	if(self.hideflags & 1)
+		if(cvar("cl_hidewaypoints"))
+			return; // fixed waypoint
+
+	InterpolateOrigin_Do();
+
+	t = GetPlayerColor(player_localentnum - 1) + 1;
+
+	spriteimage = "";
+
+	// choose the sprite
+	switch(self.rule)
+	{
+		case SPRITERULE_DEFAULT:
+			spriteimage = self.netname;
+			break;
+		case SPRITERULE_TEAMPLAY:
+			if(self.team == t)
+				spriteimage = self.netname2;
+			else
+				spriteimage = self.netname;
+			break;
+		default:
+			error("Invalid waypointsprite rule!");
+			break;
+	}
+
+	if(spriteimage == "")
+		return;
+	
+	float dist;
+	dist = vlen(self.origin - view_origin);
+	
+	float a;
+	a = self.alpha;
+
+	if(self.maxdistance > waypointsprite_normdistance)
+		a *= pow(bound(0, (self.maxdistance - dist) / (self.maxdistance - waypointsprite_normdistance), 1), waypointsprite_distancealphaexponent);
+	else if(self.maxdistance > 0)
+		a *= pow(bound(0, (waypointsprite_fadedistance - dist) / (waypointsprite_fadedistance - waypointsprite_normdistance), 1), waypointsprite_distancealphaexponent) * (1 - waypointsprite_minalpha) + waypointsprite_minalpha;
+
+	if(a <= 0)
+		return;
+	
+	// draw the sprite image
+	vector o;
+	float rot;
+	o = project_3d_to_2d(self.origin);
+	rot = 0;
+
+	if(o_z < 0 || o_x < 0 || o_y < 0 || o_x > vid_conwidth || o_y > vid_conheight)
+	{
+		// scale it to be just in view
+		vector d;
+		float f1, f2;
+		d = o - '0.5 0 0' * vid_conwidth - '0 0.5 0' * vid_conheight;
+
+		f1 = d_x / vid_conwidth;
+		f2 = d_y / vid_conheight;
+
+		if(max(f1, -f1) > max(f2, -f2))
+		{
+			if(f1 > 0)
+			{
+				// RIGHT edge
+				d = d * (0.5 / f1);
+				rot = 1;
+			}
+			else
+			{
+				// LEFT edge
+				d = d * (-0.5 / f1);
+				rot = 3;
+			}
+		}
+		else
+		{
+			if(f2 > 0)
+			{
+				// BOTTOM edge
+				d = d * (0.5 / f2);
+				rot = 0;
+			}
+			else
+			{
+				// TOP edge
+				d = d * (-0.5 / f2);
+				rot = 2;
+			}
+		}
+
+		o = d + '0.5 0 0' * vid_conwidth + '0 0.5 0' * vid_conheight;
+	}
+	o_z = 0;
+
+	drawrotpic(o, rot * 90 * DEG2RAD, strcat("models/sprites/", spriteimage), SPRITE_SIZE, SPRITE_HOTSPOT, '1 1 1', a, 0);
+}
+
+void Ent_WaypointSprite()
+{
+	float sendflags, f;
+	sendflags = ReadByte();
+
+	self.draw2d = Draw_WaypointSprite;
+
+	InterpolateOrigin_Undo();
+
+	// unfortunately, this needs to be exact (for the 3D display)
+	self.origin_x = ReadCoord();
+	self.origin_y = ReadCoord();
+	self.origin_z = ReadCoord();
+
+	if(sendflags & 1)
+	{
+		self.team = ReadByte();
+		self.rule = ReadByte();
+	}
+
+	if(sendflags & 2)
+	{
+		if(self.netname)
+			strunzone(self.netname);
+		self.netname = strzone(ReadString());
+	}
+
+	if(sendflags & 4)
+	{
+		if(self.netname2)
+			strunzone(self.netname2);
+		self.netname2 = strzone(ReadString());
+	}
+
+	if(sendflags & 8)
+	{
+		if(self.netname3)
+			strunzone(self.netname3);
+		self.netname3 = strzone(ReadString());
+	}
+
+	if(sendflags & 16)
+	{
+		self.lifetime = ReadCoord();
+		self.fadetime = ReadCoord();
+		self.maxdistance = ReadShort();
+		self.hideflags = ReadByte();
+	}
+
+	if(sendflags & 32)
+	{
+		f = ReadByte();
+		self.teamradar_icon = (f & 0x7F);
+		if(f & 0x80)
+			self.teamradar_time = time;
+		self.teamradar_color_x = ReadByte() / 255.0;
+		self.teamradar_color_y = ReadByte() / 255.0;
+		self.teamradar_color_z = ReadByte() / 255.0;
+	}
+
+	InterpolateOrigin_Note();
+}
+
+void Ent_RemoveWaypointSprite()
+{
+	if(self.netname)
+		strunzone(self.netname);
+	if(self.netname2)
+		strunzone(self.netname2);
+	if(self.netname3)
+		strunzone(self.netname3);
+}
+
+void WaypointSprite_Init()
+{
+	waypointsprite_fadedistance = vlen(world.maxs - world.mins);
+	waypointsprite_normdistance = cvar("g_waypointsprite_normdistance");
+	waypointsprite_minscale = cvar("g_waypointsprite_minscale");
+	waypointsprite_minalpha = cvar("g_waypointsprite_minalpha");
+	waypointsprite_distancealphaexponent = cvar("g_waypointsprite_distancealphaexponent");
+	waypointsprite_timealphaexponent = cvar("g_waypointsprite_timealphaexponent");
+}

Added: trunk/data/qcsrc/client/waypointsprites.qh
===================================================================
--- trunk/data/qcsrc/client/waypointsprites.qh	                        (rev 0)
+++ trunk/data/qcsrc/client/waypointsprites.qh	2008-10-02 11:37:16 UTC (rev 4576)
@@ -0,0 +1,3 @@
+// they are drawn using a .draw function
+void Ent_WaypointSprite();
+void Ent_RemoveWaypointSprite();

Modified: trunk/data/qcsrc/common/constants.qh
===================================================================
--- trunk/data/qcsrc/common/constants.qh	2008-10-02 07:04:58 UTC (rev 4575)
+++ trunk/data/qcsrc/common/constants.qh	2008-10-02 11:37:16 UTC (rev 4576)
@@ -19,7 +19,7 @@
 // Revision 18: warmup
 // Revision 19: fog
 // Revision 20: naggers
-// Revision 21: entcs for players optimized (position data down from 12 to 7 bytes)
+// Revision 21: entcs for players optimized (position data down from 12 to 7 bytes); waypointsprites in csqc for team radar
 #define CSQC_REVISION 21
 
 // probably put these in common/
@@ -50,9 +50,15 @@
 const float ENT_CLIENT_POINTPARTICLES = 6;
 const float ENT_CLIENT_RAINSNOW = 7;
 const float ENT_CLIENT_LASER = 8;
-const float ENT_CLIENT_NAGGER = 9; // [flags] [votecalledvote]
-const float ENT_CLIENT_WAYPOINT = 10;
+const float ENT_CLIENT_NAGGER = 9; // flags [votecalledvote]
+const float ENT_CLIENT_WAYPOINT = 10; // flags origin [team displayrule] [spritename] [spritename2] [spritename3] [lifetime maxdistance hideable]
 
+	const float SPRITERULE_DEFAULT = 0;
+	const float SPRITERULE_TEAMPLAY = 1;
+
+	const float RADARICON_FLAG = 1;
+	const float RADARICON_FLAGCARRIER = 2;
+
 ///////////////////////////
 // key constants
 

Modified: trunk/data/qcsrc/server/cl_client.qc
===================================================================
--- trunk/data/qcsrc/server/cl_client.qc	2008-10-02 07:04:58 UTC (rev 4575)
+++ trunk/data/qcsrc/server/cl_client.qc	2008-10-02 11:37:16 UTC (rev 4576)
@@ -1305,8 +1305,6 @@
 		self.killindicator = world;
 	}
 
-	WaypointSprite_PlayerGone();
-
 	DropAllRunes(self);
 	kh_Key_DropAll(self, TRUE);
 
@@ -1315,6 +1313,8 @@
 	if(self.flagcarried)
 		DropFlag(self.flagcarried, world, world);
 
+	WaypointSprite_PlayerGone();
+
 	save = self.flags;
 	self.flags = self.flags - (self.flags & FL_CLIENT);
 	bot_relinkplayerlist();

Modified: trunk/data/qcsrc/server/ctf.qc
===================================================================
--- trunk/data/qcsrc/server/ctf.qc	2008-10-02 07:04:58 UTC (rev 4575)
+++ trunk/data/qcsrc/server/ctf.qc	2008-10-02 11:37:16 UTC (rev 4576)
@@ -136,6 +136,7 @@
 	PlayerScore_Add(p, SP_CTF_DROPS, +1);
 	e.playerid = attacker.playerid;
 	
+	WaypointSprite_Ping(p.waypointsprite_attachedforcarrier);
 	WaypointSprite_DetachCarrier(p);
 	LogCTF("dropped", p.team, p);
 
@@ -331,6 +332,8 @@
 		setorigin(self, FLAG_CARRY_POS);
 		setattachment(self, other, "");
 		WaypointSprite_AttachCarrier("flagcarrier", other);
+		WaypointSprite_UpdateTeamRadar(other.waypointsprite_attachedforcarrier, RADARICON_FLAGCARRIER, '1 1 0');
+		WaypointSprite_Ping(self.sprite);
 
 		return;
 	}
@@ -405,6 +408,7 @@
 			setorigin(self, FLAG_CARRY_POS);
 			setattachment(self, other, "");
 			WaypointSprite_AttachCarrier("flagcarrier", other);
+			WaypointSprite_UpdateTeamRadar(other.waypointsprite_attachedforcarrier, RADARICON_FLAGCARRIER, '1 1 0');
 		}
 	}
 };
@@ -552,6 +556,7 @@
 	waypoint_spawnforitem(self);
 
 	WaypointSprite_SpawnFixed("redbase", self.origin + '0 0 37', self, sprite);
+	WaypointSprite_UpdateTeamRadar(self.sprite, RADARICON_FLAG, '1 0 0');
 };
 
 /*QUAKED spawnfunc_item_flag_team2 (0 0.5 0.8) (-48 -48 -24) (48 48 64)
@@ -634,6 +639,7 @@
 	waypoint_spawnforitem(self);
 
 	WaypointSprite_SpawnFixed("bluebase", self.origin + '0 0 37', self, sprite);
+	WaypointSprite_UpdateTeamRadar(self.sprite, RADARICON_FLAG, '0 0 1');
 };
 
 

Modified: trunk/data/qcsrc/server/keyhunt.qc
===================================================================
--- trunk/data/qcsrc/server/keyhunt.qc	2008-10-02 07:04:58 UTC (rev 4575)
+++ trunk/data/qcsrc/server/keyhunt.qc	2008-10-02 11:37:16 UTC (rev 4576)
@@ -308,8 +308,16 @@
 		{
 			// player is now a key carrier
 			WaypointSprite_AttachCarrier("", player);
-			player.waypointsprite_attachedforcarrier.waypointsprite_for_player = kh_KeyCarrier_waypointsprite_for_player;
-			player.waypointsprite_attachedforcarrier.team = player.team;
+			player.waypointsprite_attachedforcarrier.waypointsprite_visible_for_player = kh_KeyCarrier_waypointsprite_visible_for_player;
+			WaypointSprite_UpdateRule(player.waypointsprite_attachedforcarrier, player.team, SPRITERULE_TEAMPLAY);
+			if(player.team == COLOR_TEAM1)
+				WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, "keycarrier-red", "keycarrier-friend", "");
+			else if(player.team == COLOR_TEAM2)
+				WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, "keycarrier-blue", "keycarrier-friend", "");
+			else if(player.team == COLOR_TEAM3)
+				WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, "keycarrier-yellow", "keycarrier-friend", "");
+			else if(player.team == COLOR_TEAM4)
+				WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, "keycarrier-pink", "keycarrier-friend", "");
 		}
 	}
 	
@@ -378,7 +386,7 @@
 	centerprint(initial_owner, strcat("You are starting with the ", key.netname, "\n"));  // message to player at start of round
 
 	WaypointSprite_Spawn("", 0, 0, key, '0 0 1' * KH_KEY_WP_ZSHIFT, world, key.team, key, waypointsprite_attachedforcarrier, FALSE);
-	key.waypointsprite_attachedforcarrier.waypointsprite_for_player = kh_Key_waypointsprite_for_player;
+	key.waypointsprite_attachedforcarrier.waypointsprite_visible_for_player = kh_Key_waypointsprite_visible_for_player;
 
 	kh_Key_AssignTo(key, initial_owner);
 }
@@ -450,6 +458,8 @@
 	{
 		kh_interferemsg_time = time + 0.2;
 		kh_interferemsg_team = player.team;
+
+		// audit all key carrier sprites, update them to RUN HERE
 	}
 }
 
@@ -853,37 +863,24 @@
 	kh_tracking_enabled = TRUE;
 }
 
-float kh_Key_waypointsprite_for_player(entity e) // ??
+float kh_Key_waypointsprite_visible_for_player(entity e) // ??
 {
 	if(!kh_tracking_enabled)
-		return 0;
+		return FALSE;
 	if(!self.owner)
-		return kh_sprite_dropped;
+		return TRUE;
 	if(!self.owner.owner)
-		return kh_sprite_dropped;
-	return 0;  // draw only when key is not owned
+		return TRUE;
+	return FALSE;  // draw only when key is not owned
 }
 
-float kh_KeyCarrier_waypointsprite_for_player(entity e)  // runs all the time
+float kh_KeyCarrier_waypointsprite_visible_for_player(entity e)  // runs all the time
 {
 	if(e.classname != "player" || self.team != e.team)
 		if(!kh_tracking_enabled)
-			return 0;
+			return FALSE;
 
-	// e is spectator? That's no team mate...
-	if(e.classname != "player")
-		return kh_GetCarrierSprite(self.team, -1);
-
-	// e is no key carrier: simple case...
-	if(!e.kh_next)
-		return kh_GetCarrierSprite(self.team, e.team);
-
-	// e is a key carrier: if any key is dropped or owned by another team, show
-	// the carrier sprite; otherwise show run here
-	if(kh_Key_AllOwnedByWhichTeam() == e.team)
-		return kh_sprite_finish;
-
-	return kh_GetCarrierSprite(self.team, e.team);
+	return TRUE;
 }
 
 float kh_HandleFrags(entity attacker, entity targ, float f)  // adds to the player score

Modified: trunk/data/qcsrc/server/keyhunt.qh
===================================================================
--- trunk/data/qcsrc/server/keyhunt.qh	2008-10-02 07:04:58 UTC (rev 4575)
+++ trunk/data/qcsrc/server/keyhunt.qh	2008-10-02 11:37:16 UTC (rev 4576)
@@ -19,8 +19,8 @@
 void kh_EnableTrackingDevice();
 void kh_init();
 void kh_finalize();
-float kh_KeyCarrier_waypointsprite_for_player(entity e);
-float kh_Key_waypointsprite_for_player(entity e);
+float kh_KeyCarrier_waypointsprite_visible_for_player(entity e);
+float kh_Key_waypointsprite_visible_for_player(entity e);
 void kh_setstatus();
 float kh_HandleFrags(entity attacker, entity targ, float f);
 float kh_Key_AllOwnedByWhichTeam();

Modified: trunk/data/qcsrc/server/mode_onslaught.qc
===================================================================
--- trunk/data/qcsrc/server/mode_onslaught.qc	2008-10-02 07:04:58 UTC (rev 4575)
+++ trunk/data/qcsrc/server/mode_onslaught.qc	2008-10-02 11:37:16 UTC (rev 4576)
@@ -422,6 +422,7 @@
 	self.nextthink = time;
 };
 
+#ifdef YOU_HAVE_FIXED_ONSLAUGHT_WAYPOINTS
 float onslaught_generator_waypointsprite_for_player(entity e)
 {
 	if(e.classname == "player")
@@ -484,6 +485,7 @@
 	}
 	return 0;
 }
+#endif
 
 /*QUAKED spawnfunc_onslaught_generator (0 .5 .8) (-32 -32 -24) (32 32 64)
 Base generator.
@@ -502,6 +504,7 @@
 		return;
 	}
 
+#ifdef YOU_HAVE_FIXED_ONSLAUGHT_WAYPOINTS
 	if(!ons_sprite_cp_blue)
 	{
 		precache_model("models/sprites/ons-cp-blue.sp2");
@@ -538,6 +541,7 @@
 		setmodel(self, "models/sprites/ons-gen-shielded.sp2");
 		ons_sprite_gen_shielded = self.modelindex;
 	}
+#endif
 
 	local entity e;
 	precache_model("models/onslaught/generator.md3");
@@ -575,8 +579,10 @@
 	self.think = onslaught_generator_delayed;
 	self.nextthink = time + 0.2;
 
+#ifdef YOU_HAVE_FIXED_ONSLAUGHT_WAYPOINTS
 	WaypointSprite_SpawnFixed(string_null, e.origin + '0 0 1' * e.maxs_z, self, sprite);
 	self.sprite.waypointsprite_for_player = onslaught_generator_waypointsprite_for_player;
+#endif
 };
 
 void onslaught_generator_reset()
@@ -774,8 +780,10 @@
 
 	waypoint_spawnforitem(self);
 
+#ifdef YOU_HAVE_FIXED_ONSLAUGHT_WAYPOINTS
 	WaypointSprite_SpawnFixed(string_null, e.origin + '0 0 1' * e.maxs_z, self, sprite);
 	self.sprite.waypointsprite_for_player = onslaught_controlpoint_waypointsprite_for_player;
+#endif
 };
 
 void onslaught_controlpoint_reset()

Modified: trunk/data/qcsrc/server/race.qc
===================================================================
--- trunk/data/qcsrc/server/race.qc	2008-10-02 07:04:58 UTC (rev 4575)
+++ trunk/data/qcsrc/server/race.qc	2008-10-02 11:37:16 UTC (rev 4576)
@@ -396,12 +396,12 @@
 	checkpoint_passed();
 }
 
-float race_waypointsprite_for_player(entity e)
+float race_waypointsprite_visible_for_player(entity e)
 {
 	if(e.race_checkpoint == -1)
-		return self.modelindex;
+		return TRUE;
 	else if(e.race_checkpoint == self.owner.race_checkpoint)
-		return self.modelindex;
+		return TRUE;
 	else
 		return FALSE;
 }
@@ -444,7 +444,7 @@
 		precache_model("models/sprites/race-finish.sp2");
 		WaypointSprite_SpawnFixed("race-finish", o, self, sprite);
 	}
-	self.sprite.waypointsprite_for_player = race_waypointsprite_for_player;
+	self.sprite.waypointsprite_visible_for_player = race_waypointsprite_visible_for_player;
 }
 
 void race_AbandonRaceCheck(entity p)

Modified: trunk/data/qcsrc/server/waypointsprites.qc
===================================================================
--- trunk/data/qcsrc/server/waypointsprites.qc	2008-10-02 07:04:58 UTC (rev 4575)
+++ trunk/data/qcsrc/server/waypointsprites.qc	2008-10-02 11:37:16 UTC (rev 4576)
@@ -1,64 +1,86 @@
-float waypointsprite_normdistance;
-float waypointsprite_minscale;
-float waypointsprite_fadedistance;
-float waypointsprite_minalpha;
-float waypointsprite_distancealphaexponent;
-float waypointsprite_timealphaexponent;
-float waypointsprite_deployed_lifetime;
-float waypointsprite_deadlifetime;
-float waypointsprite_limitedrange;
-
 ..entity owned_by_field;
-.float(entity) waypointsprite_for_player; // returns a model index or 0 for hide
-float waypointsprite_for_player_default(entity e)
-{
-	// personal waypoints
-	if(self.enemy)
-		if(self.enemy != other)
-			return FALSE;
+.float rule;
+.string model2;
+.string model3;
 
-	// team waypoints
-	if(self.team)
+.float(entity) waypointsprite_visible_for_player;
+
+void WaypointSprite_UpdateSprites(entity e, string m1, string m2, string m3)
+{
+	if(m1 != e.model)
 	{
-		if(self.team != other.team)
-			return FALSE;
-		if(other.classname != "player")
-			return FALSE;
+		e.model = m1;
+		e.SendFlags |= 2;
 	}
+	if(m2 != e.model2)
+	{
+		e.model2 = m2;
+		e.SendFlags |= 4;
+	}
+	if(m3 != e.model3)
+	{
+		e.model3 = m3;
+		e.SendFlags |= 8;
+	}
+}
 
-	// fixed waypoints
-	if(self.currentammo) // hidable?
-		if(other.cvar_cl_hidewaypoints) // wants to hide;
-			return FALSE;
+void WaypointSprite_UpdateOrigin(entity e, vector o)
+{
+	e.origin = o;
+	e.SendFlags |= 128;
+}
 
-	// otherwise, accept the model
-	return self.modelindex;
+void WaypointSprite_UpdateRule(entity e, float t, float r)
+{
+	e.rule = r;
+	e.team = t;
+	e.SendFlags |= 1;
 }
 
+void WaypointSprite_UpdateTeamRadar(entity e, float icon, vector col)
+{
+	e.cnt = (icon & 0x7F);
+	e.colormod = col;
+	e.SendFlags |= 32;
+}
+
+void WaypointSprite_Ping(entity e)
+{
+	e.cnt |= 0x80;
+	e.SendFlags |= 32;
+}
+
+void WaypointSprite_FadeOutIn(entity e, float t)
+{
+	if(!e.health)
+	{
+		e.health = t;
+		e.teleport_time = time + t;
+	}
+	else if(t < (e.teleport_time - time))
+	{
+		// accelerate the waypoint's dying
+		// ensure:
+		//   (e.teleport_time - time) / wp.health stays
+		//   e.teleport_time = time + fadetime
+		float current_fadetime;
+		current_fadetime = e.teleport_time - time;
+		e.teleport_time = time + t;
+		e.health = e.health * t / current_fadetime;
+	}
+
+	e.SendFlags |= 16;
+}
+
+float waypointsprite_limitedrange, waypointsprite_deployed_lifetime, waypointsprite_deadlifetime;
 void WaypointSprite_Init()
 {
-	waypointsprite_fadedistance = vlen(world.maxs - world.mins);
-	waypointsprite_normdistance = cvar("g_waypointsprite_normdistance");
-	waypointsprite_minscale = cvar("g_waypointsprite_minscale");
-	waypointsprite_minalpha = cvar("g_waypointsprite_minalpha");
-	waypointsprite_distancealphaexponent = cvar("g_waypointsprite_distancealphaexponent");
-	waypointsprite_timealphaexponent = cvar("g_waypointsprite_timealphaexponent");
+	waypointsprite_limitedrange = cvar("g_waypointsprite_limitedrange");
 	waypointsprite_deployed_lifetime = cvar("g_waypointsprite_deployed_lifetime");
 	waypointsprite_deadlifetime = cvar("g_waypointsprite_deadlifetime");
-	waypointsprite_limitedrange = cvar("g_waypointsprite_limitedrange");
-
-	precache_model("models/sprites/bluebase.sp2");
-	precache_model("models/sprites/flagcarrier.sp2");
-	precache_model("models/sprites/here.sp2");
-	precache_model("models/sprites/helpme.sp2");
-	precache_model("models/sprites/redbase.sp2");
-	precache_model("models/sprites/waypoint.sp2");
-	precache_model("models/sprites/danger.sp2");
 }
-
 void WaypointSprite_InitClient(entity e)
 {
-	stuffcmd(e, "\nalias \"g_waypointsprite_personal\" \"impulse 30\"\n alias \"g_waypointsprite_personal_p\" \"impulse 31\"\n alias \"g_waypointsprite_personal_d\" \"impulse 32\"\n alias \"g_waypointsprite_team_helpme\" \"impulse 33\"\n alias \"g_waypointsprite_team_here\" \"impulse 34\"\n alias \"g_waypointsprite_team_here_p\" \"impulse 35\"\n alias \"g_waypointsprite_team_here_d\" \"impulse 36\"\n alias \"g_waypointsprite_team_danger\" \"impulse 37\"\n alias \"g_waypointsprite_team_danger_p\" \"impulse 38\"\n alias \"g_waypointsprite_team_danger_d\" \"impulse 39\"\n alias \"g_waypointsprite_clear_personal\" \"impulse 47\"\n alias \"g_waypointsprite_clear\" \"impulse 48\"\n alias \"g_waypointsprite_toggle\" \"impulse 49\"\n");
 }
 
 void WaypointSprite_Kill(entity wp)
@@ -77,34 +99,11 @@
 	if(wp.owner)
 	{
 		if(wp.exteriormodeltoclient == wp.owner)
-		{
-			setattachment(wp, world, "");
-#ifdef ATTACHMENT_WORKS_WITH_EF_NODEPTHTEST
-			setorigin(wp, wp.origin + wp.exteriormodeltoclient.origin);
-#else
-			setorigin(wp, wp.view_ofs + wp.exteriormodeltoclient.origin);
-#endif
 			wp.exteriormodeltoclient = world;
-		}
 		wp.owner.(wp.owned_by_field) = world;
 		wp.owner = world;
 
-		if(!wp.health)
-		{
-			wp.health = fadetime;
-			wp.teleport_time = time + fadetime;
-		}
-		else if(fadetime < (wp.teleport_time - time))
-		{
-			// accelerate the spawnfunc_waypoint's dying
-			// ensure:
-			//   (wp.teleport_time - time) / wp.health stays
-			//   wp.teleport_time = time + fadetime
-			float current_fadetime;
-			current_fadetime = wp.teleport_time - time;
-			wp.teleport_time = time + fadetime;
-			wp.health = wp.health * fadetime / current_fadetime;
-		}
+		WaypointSprite_FadeOutIn(wp, fadetime);
 	}
 }
 
@@ -115,91 +114,91 @@
 	doremove = FALSE;
 
 	if(self.health)
+	{
 		if(time >= self.teleport_time)
 			doremove = TRUE;
+	}
 
+	if(self.exteriormodeltoclient)
+		WaypointSprite_UpdateOrigin(self, self.exteriormodeltoclient.origin + self.view_ofs);
+
 	if(doremove)
 		WaypointSprite_Kill(self);
 	else
-		self.nextthink = time;
+		self.nextthink = time; // WHY?!?
 }
 
-float WaypointSprite_CustomizeEntityForClient()
+float WaypointSprite_visible_for_player(entity e)
 {
-	vector realorigin, porigin;
-	float distancealpha, timealpha;
-	float distance;
-	float newmodel;
+	// personal waypoints
+	if(self.enemy)
+		if(self.enemy != other)
+			return FALSE;
 
-	if(self.health)
+	// team waypoints
+	if(self.team && self.rule == SPRITERULE_DEFAULT)
 	{
-		timealpha = bound(0, (self.teleport_time - time) / self.health, 1);
-		if(timealpha == 0)
+		if(self.team != other.team)
 			return FALSE;
-		timealpha = pow(timealpha, waypointsprite_timealphaexponent);
+		if(other.classname != "player")
+			return FALSE;
 	}
-	else
-		timealpha = 1;
 
-	// customize WP
-	newmodel = self.waypointsprite_for_player(other);
-	if(newmodel == 0)
-		return FALSE;
-	self.modelindex = newmodel;
+	return TRUE;
+}
 
-	porigin = other.origin + other.view_ofs_z * '0 0 1';
+float WaypointSprite_Customize()
+{
+	// this is not in SendEntity because it shall run every frame, not just every update
 
-#ifdef ATTACHMENT_WORKS_WITH_EF_NODEPTHTEST
-	realorigin = self.exteriormodeltoclient.origin + self.origin;
-#else
-	if(self.exteriormodeltoclient)
+	return self.waypointsprite_visible_for_player(other);
+}
+
+float WaypointSprite_SendEntity(entity to, float sendflags)
+{
+	WriteByte(MSG_ENTITY, ENT_CLIENT_WAYPOINT);
+	WriteByte(MSG_ENTITY, sendflags);
+	WriteCoord(MSG_ENTITY, self.origin_x);
+	WriteCoord(MSG_ENTITY, self.origin_y);
+	WriteCoord(MSG_ENTITY, self.origin_z);
+
+	if(sendflags & 1)
 	{
-		if(self.exteriormodeltoclient == other)
-		{
-			setattachment(self, other, "");
-			setorigin(self, self.view_ofs);
-			realorigin = other.origin + self.origin;
-		}
-		else
-		{
-			setattachment(self, world, "");
-			setorigin(self, self.exteriormodeltoclient.origin + self.view_ofs);
-			realorigin = self.origin;
-		}
+		WriteByte(MSG_ENTITY, self.team);
+		WriteByte(MSG_ENTITY, self.rule);
 	}
-	else
-		realorigin = self.origin;
-#endif
 
-	distance = vlen(realorigin - porigin);
+	if(sendflags & 2)
+		WriteString(MSG_ENTITY, self.model);
 
-	if(self.max_health)
-		if(distance >= self.max_health)
-			return FALSE;
+	if(sendflags & 4)
+		WriteString(MSG_ENTITY, self.model2);
 
-	self.scale = max(1, distance / waypointsprite_normdistance) * waypointsprite_minscale;
+	if(sendflags & 8)
+		WriteString(MSG_ENTITY, self.model3);
 
-	if(self.max_health > waypointsprite_normdistance)
+	if(sendflags & 16)
 	{
-		// alpha 1 at normdistance, alpha 0 at maxdistance
-		distancealpha = bound(0, (self.max_health - distance) / (self.max_health - waypointsprite_normdistance), 1);
-		distancealpha = pow(distancealpha, waypointsprite_distancealphaexponent);
+		WriteCoord(MSG_ENTITY, self.health);
+		WriteCoord(MSG_ENTITY, self.teleport_time);
+		WriteShort(MSG_ENTITY, self.max_health); // maxdist
+		float f;
+		f = 0;
+		if(self.currentammo)
+			f |= 1; // hideable
+		if(self.exteriormodeltoclient == to)
+			f |= 2; // my own
+		WriteByte(MSG_ENTITY, f);
 	}
-	else if(self.max_health)
+
+	if(sendflags & 32)
 	{
-		// alpha 1 if visible
-		distancealpha = 1;
+		WriteByte(MSG_ENTITY, self.cnt); // icon on radar
+		WriteByte(MSG_ENTITY, self.colormod_x * 255.0);
+		WriteByte(MSG_ENTITY, self.colormod_y * 255.0);
+		WriteByte(MSG_ENTITY, self.colormod_z * 255.0);
 	}
-	else
-	{
-		// alpha 1 at normdistance, alpha minalpha at fadedistance
-		distancealpha = bound(0, (waypointsprite_fadedistance - distance) / (waypointsprite_fadedistance - waypointsprite_normdistance), 1);
-		distancealpha = pow(distancealpha, waypointsprite_distancealphaexponent);
-		distancealpha = distancealpha * (1 - waypointsprite_minalpha) + waypointsprite_minalpha;
-	}
 
-	self.alpha = timealpha * distancealpha;
-
 	return TRUE;
 }
 
@@ -219,14 +218,7 @@
 	wp.health = lifetime;
 	wp.exteriormodeltoclient = ref;
 	if(ref)
-	{
-#ifdef ATTACHMENT_WORKS_WITH_EF_NODEPTHTEST
-		setattachment(wp, ref, "");
-		setorigin(wp, ofs);
-#else
 		wp.view_ofs = ofs;
-#endif
-	}
 	else
 		setorigin(wp, ofs);
 	wp.enemy = showto;
@@ -241,16 +233,14 @@
 		wp.owned_by_field = ownfield;
 	}
 	wp.max_health = maxdistance;
-	wp.customizeentityforclient = WaypointSprite_CustomizeEntityForClient;
 	wp.think = WaypointSprite_Think;
 	wp.nextthink = time;
 	wp.effects = EF_NODEPTHTEST | EF_LOWPRECISION;
-	if(spr != "")
-		setmodel(wp, strcat("models/sprites/", spr, ".sp2")); // precision set above
-	else
-		wp.model = "waypoint";
-	setsize(wp, '0 0 0', '0 0 0');
-	wp.waypointsprite_for_player = waypointsprite_for_player_default;
+	wp.model = spr;
+	wp.modelindex = 1;
+	wp.SendEntity = WaypointSprite_SendEntity;
+	wp.customizeentityforclient = WaypointSprite_Customize;
+	wp.waypointsprite_visible_for_player = WaypointSprite_visible_for_player;
 	return wp;
 }
 




More information about the nexuiz-commits mailing list