1 float waypointsprite_initialized;
2 float waypointsprite_fadedistance;
3 float waypointsprite_normdistance;
4 float waypointsprite_minscale;
5 float waypointsprite_minalpha;
6 float waypointsprite_distancealphaexponent;
7 float waypointsprite_timealphaexponent;
8 float waypointsprite_scale;
9 float waypointsprite_edgefadealpha;
10 float waypointsprite_edgefadescale;
11 float waypointsprite_edgefadedistance;
12 float waypointsprite_crosshairfadealpha;
13 float waypointsprite_crosshairfadescale;
14 float waypointsprite_crosshairfadedistance;
15 float waypointsprite_distancefadealpha;
16 float waypointsprite_distancefadescale;
17 float waypointsprite_distancefadedistance;
18 float waypointsprite_alpha;
21 .string netname; // primary picture
22 .string netname2; // secondary picture
23 .string netname3; // tertiary picture
24 .float team; // team that gets netname2
32 .float build_starthealth;
33 .float build_finished;
35 vector SPRITE_SIZE = '288 36 0';
36 vector SPRITE_HOTSPOT = '144 36 0';
37 float SPRITE_HEALTHBAR_WIDTH = 144;
38 float SPRITE_HEALTHBAR_HEIGHT = 9;
39 float SPRITE_HEALTHBAR_MARGIN = 6;
40 float SPRITE_HEALTHBAR_BORDER = 2;
41 float SPRITE_HEALTHBAR_BORDERALPHA = 1;
42 float SPRITE_HEALTHBAR_HEALTHALPHA = 0.5;
44 void drawrotpic(vector org, float rot, string pic, vector sz, vector hotspot, vector rgb, float a, float f)
46 vector v1, v2, v3, v4;
48 hotspot = -1 * hotspot;
50 // hotspot-relative coordinates of the corners
52 v2 = hotspot + '1 0 0' * sz_x;
53 v3 = hotspot + '1 0 0' * sz_x + '0 1 0' * sz_y;
54 v4 = hotspot + '0 1 0' * sz_y;
56 // rotate them, and make them absolute
57 rot = -rot; // rotate by the opposite angle, as our coordinate system is reversed
58 v1 = rotate(v1, rot) + org;
59 v2 = rotate(v2, rot) + org;
60 v3 = rotate(v3, rot) + org;
61 v4 = rotate(v4, rot) + org;
64 R_BeginPolygon(pic, f);
65 R_PolygonVertex(v1, '0 0 0', rgb, a);
66 R_PolygonVertex(v2, '1 0 0', rgb, a);
67 R_PolygonVertex(v3, '1 1 0', rgb, a);
68 R_PolygonVertex(v4, '0 1 0', rgb, a);
72 void drawquad(vector o, vector ri, vector up, string pic, vector rgb, float a, float f)
74 R_BeginPolygon(pic, f);
75 R_PolygonVertex(o, '0 0 0', rgb, a);
76 R_PolygonVertex(o + ri, '1 0 0', rgb, a);
77 R_PolygonVertex(o + up + ri, '1 1 0', rgb, a);
78 R_PolygonVertex(o + up, '0 1 0', rgb, a);
82 void drawhealthbar(vector org, float rot, float h, vector sz, vector hotspot, float width, float height, float margin, float border, float align, vector rgb, float a, vector hrgb, float ha, float f)
85 float owidth; // outer width
87 hotspot = -1 * hotspot;
89 // hotspot-relative coordinates of the healthbar corners
94 rot = -rot; // rotate by the opposite angle, as our coordinate system is reversed
95 o = rotate(o, rot) + org;
99 owidth = width + 2 * border;
100 o = o - up * (margin + border + height) + ri * (sz_x - owidth) * 0.5;
102 drawquad(o - up * border, ri * owidth, up * border, "", rgb, a, f);
103 drawquad(o + up * height, ri * owidth, up * border, "", rgb, a, f);
104 drawquad(o, ri * border, up * height, "", rgb, a, f);
105 drawquad(o + ri * (owidth - border), ri * border, up * height, "", rgb, a, f);
106 drawquad(o + ri * (border + align * ((1 - h) * width)), ri * width * h, up * height, "", hrgb, ha, f);
109 void Draw_WaypointSprite()
115 self.alpha = pow(bound(0, (self.fadetime - time) / self.lifetime, 1), waypointsprite_timealphaexponent);
119 if(self.hideflags & 2)
120 return; // radar only
122 if(cvar("cl_hidewaypoints") >= 2)
125 if(self.hideflags & 1)
126 if(cvar("cl_hidewaypoints"))
127 return; // fixed waypoint
129 InterpolateOrigin_Do();
131 t = GetPlayerColor(player_localentnum - 1) + 1;
138 case SPRITERULE_DEFAULT:
142 spriteimage = self.netname;
147 spriteimage = self.netname;
149 case SPRITERULE_TEAMPLAY:
150 if(t == COLOR_SPECTATOR + 1)
151 spriteimage = self.netname3;
152 else if(self.team == t)
153 spriteimage = self.netname2;
155 spriteimage = self.netname;
158 error("Invalid waypointsprite rule!");
162 if(spriteimage == "")
166 dist = vlen(self.origin - view_origin);
169 a = self.alpha * autocvar_hud_panel_fg_alpha;
171 if(self.maxdistance > waypointsprite_normdistance)
172 a *= pow(bound(0, (self.maxdistance - dist) / (self.maxdistance - waypointsprite_normdistance), 1), waypointsprite_distancealphaexponent);
173 else if(self.maxdistance > 0)
174 a *= pow(bound(0, (waypointsprite_fadedistance - dist) / (waypointsprite_fadedistance - waypointsprite_normdistance), 1), waypointsprite_distancealphaexponent) * (1 - waypointsprite_minalpha) + waypointsprite_minalpha;
179 // draw the sprite image
182 o = project_3d_to_2d(self.origin);
185 if(o_z < 0 || o_x < 0 || o_y < 0 || o_x > vid_conwidth || o_y > vid_conheight)
187 // scale it to be just in view
191 // get the waypoint angle vector
193 d_x = view_right * (self.origin - view_origin) * vid_conwidth / vid_width;
194 d_y = -view_up * (self.origin - view_origin) * vid_conheight / (vid_height * vid_pixelheight);
198 d = o - '0.5 0 0' * vid_conwidth - '0 0.5 0' * vid_conheight;
201 if(cvar("v_flipped"))
205 f1 = d_x / vid_conwidth;
206 f2 = d_y / vid_conheight;
208 if(max(f1, -f1) > max(f2, -f2))
239 o = d + '0.5 0 0' * vid_conwidth + '0 0.5 0' * vid_conheight;
244 vidscale = max(vid_conwidth / vid_width, vid_conheight / vid_height);
246 t = stof(db_get(tempdb, strcat("/spriteframes/", spriteimage)));
248 spriteimage = strcat("models/sprites/", spriteimage);
250 spriteimage = strcat("models/sprites/", spriteimage, "_frame", ftos(mod(floor((max(0, time - self.spawntime)) * 2), t)));
252 float edgedistance_min, crosshairdistance;
253 edgedistance_min = min4(o_y, o_x,vid_conwidth - o_x, vid_conheight - o_y);
255 crosshairdistance = sqrt( pow(o_x - vid_conwidth/2, 2) + pow(o_y - vid_conheight/2, 2) );
257 t = waypointsprite_scale * vidscale;
258 a *= waypointsprite_alpha;
261 a = a * (1 - (1 - waypointsprite_distancefadealpha) * (bound(0, dist/waypointsprite_distancefadedistance, 1)));
262 t = t * (1 - (1 - waypointsprite_distancefadescale) * (bound(0, dist/waypointsprite_distancefadedistance, 1)));
264 if (edgedistance_min < waypointsprite_edgefadedistance) {
265 a = a * (1 - (1 - waypointsprite_edgefadealpha) * (1 - bound(0, edgedistance_min/waypointsprite_edgefadedistance, 1)));
266 t = t * (1 - (1 - waypointsprite_edgefadescale) * (1 - bound(0, edgedistance_min/waypointsprite_edgefadedistance, 1)));
268 if(crosshairdistance < waypointsprite_crosshairfadedistance) {
269 a = a * (1 - (1 - waypointsprite_crosshairfadealpha) * (1 - bound(0, crosshairdistance/waypointsprite_crosshairfadedistance, 1)));
270 t = t * (1 - (1 - waypointsprite_crosshairfadescale) * (1 - bound(0, crosshairdistance/waypointsprite_crosshairfadedistance, 1)));
272 drawrotpic(o, rot * 90 * DEG2RAD, spriteimage, SPRITE_SIZE * t, SPRITE_HOTSPOT * t, '1 1 1', a, DRAWFLAG_MIPMAP);
274 if(self.build_finished)
276 if(time < self.build_finished + 0.25)
278 if(time < self.build_started)
279 self.health = self.build_starthealth;
280 else if(time < self.build_finished)
281 self.health = (time - self.build_started) / (self.build_finished - self.build_started) * (1 - self.build_starthealth) + self.build_starthealth;
292 if(self.build_finished)
296 drawhealthbar(o, rot * 90 * DEG2RAD, self.health, SPRITE_SIZE * t, SPRITE_HOTSPOT * t, SPRITE_HEALTHBAR_WIDTH * t, SPRITE_HEALTHBAR_HEIGHT * t, SPRITE_HEALTHBAR_MARGIN * t, SPRITE_HEALTHBAR_BORDER * t, align, self.teamradar_color, a * SPRITE_HEALTHBAR_BORDERALPHA, self.teamradar_color, a * SPRITE_HEALTHBAR_HEALTHALPHA, DRAWFLAG_NORMAL);
300 void Ent_RemoveWaypointSprite()
303 strunzone(self.netname);
305 strunzone(self.netname2);
307 strunzone(self.netname3);
310 void Ent_WaypointSprite()
312 float sendflags, f, t;
313 sendflags = ReadByte();
316 self.spawntime = time;
318 self.draw2d = Draw_WaypointSprite;
320 InterpolateOrigin_Undo();
327 self.health = t / 191.0;
328 self.build_finished = 0;
332 t = (t - 192) * 256 + ReadByte();
333 self.build_started = servertime;
334 if(self.build_finished)
335 self.build_starthealth = bound(0, self.health, 1);
337 self.build_starthealth = 0;
338 self.build_finished = servertime + t / 32;
339 //print("build: ", ftos(self.build_finished - self.build_started), "\n");
345 self.build_finished = 0;
350 // unfortunately, this needs to be exact (for the 3D display)
351 self.origin_x = ReadCoord();
352 self.origin_y = ReadCoord();
353 self.origin_z = ReadCoord();
358 self.team = ReadByte();
359 self.rule = ReadByte();
365 strunzone(self.netname);
366 self.netname = strzone(ReadString());
372 strunzone(self.netname2);
373 self.netname2 = strzone(ReadString());
379 strunzone(self.netname3);
380 self.netname3 = strzone(ReadString());
385 self.lifetime = ReadCoord();
386 self.fadetime = ReadCoord();
387 self.maxdistance = ReadShort();
388 self.hideflags = ReadByte();
394 self.teamradar_icon = (f & 0x7F);
397 self.(teamradar_times[self.teamradar_time_index]) = time;
398 self.teamradar_time_index = mod(self.teamradar_time_index + 1, MAX_TEAMRADAR_TIMES);
400 self.teamradar_color_x = ReadByte() / 255.0;
401 self.teamradar_color_y = ReadByte() / 255.0;
402 self.teamradar_color_z = ReadByte() / 255.0;
405 InterpolateOrigin_Note();
407 self.entremove = Ent_RemoveWaypointSprite;
410 void WaypointSprite_Load()
412 waypointsprite_fadedistance = vlen(mi_max - mi_min);
413 waypointsprite_normdistance = cvar("g_waypointsprite_normdistance");
414 waypointsprite_minscale = cvar("g_waypointsprite_minscale");
415 waypointsprite_minalpha = cvar("g_waypointsprite_minalpha");
416 waypointsprite_distancealphaexponent = cvar("g_waypointsprite_distancealphaexponent");
417 waypointsprite_timealphaexponent = cvar("g_waypointsprite_timealphaexponent");
418 waypointsprite_scale = cvar_or("g_waypointsprite_scale", 1);
419 waypointsprite_edgefadealpha = cvar_or("g_waypointsprite_edgefadealpha", 1);
420 waypointsprite_edgefadescale = cvar_or("g_waypointsprite_edgefadescale", 1);
421 waypointsprite_edgefadedistance = cvar("g_waypointsprite_edgefadedistance");
422 waypointsprite_crosshairfadealpha = cvar_or("g_waypointsprite_crosshairfadealpha", 1);
423 waypointsprite_crosshairfadescale = cvar_or("g_waypointsprite_crosshairfadescale", 1);
424 waypointsprite_crosshairfadedistance = cvar("g_waypointsprite_crosshairfadedistance");
425 waypointsprite_distancefadealpha = cvar_or("g_waypointsprite_distancefadealpha", 1);
426 waypointsprite_distancefadescale = cvar_or("g_waypointsprite_distancefadescale", 1);
427 waypointsprite_distancefadedistance = vlen(mi_max - mi_min) * cvar_or("g_waypointsprite_distancefadedistancemultiplier", 1);
428 waypointsprite_alpha = cvar_or("g_waypointsprite_alpha", 1) * (1 - cvar("_menu_alpha"));
430 if(!waypointsprite_initialized)
432 float dh, n, i, o, f;
433 string s, sname, sframes;
434 dh = search_begin("models/sprites/*_frame*.tga", FALSE, FALSE);
435 n = search_getsize(dh);
436 for(i = 0; i < n; ++i)
438 s = search_getfilename(dh, i);
439 s = substring(s, 15, strlen(s) - 15 - 4); // strip models/sprites/ and .tga
441 o = strstrofs(s, "_frame", 0);
442 sname = strcat("/spriteframes/", substring(s, 0, o));
443 sframes = substring(s, o + 6, strlen(s) - o - 6);
444 f = stof(sframes) + 1;
445 db_put(tempdb, sname, ftos(max(f, stof(db_get(tempdb, sname)))));
449 waypointsprite_initialized = 1;