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(autocvar_cl_hidewaypoints >= 2)
125 if(self.hideflags & 1)
126 if(autocvar_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(autocvar_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;
344 self.build_finished = 0;
349 // unfortunately, this needs to be exact (for the 3D display)
350 self.origin_x = ReadCoord();
351 self.origin_y = ReadCoord();
352 self.origin_z = ReadCoord();
357 self.team = ReadByte();
358 self.rule = ReadByte();
364 strunzone(self.netname);
365 self.netname = strzone(ReadString());
371 strunzone(self.netname2);
372 self.netname2 = strzone(ReadString());
378 strunzone(self.netname3);
379 self.netname3 = strzone(ReadString());
384 self.lifetime = ReadCoord();
385 self.fadetime = ReadCoord();
386 self.maxdistance = ReadShort();
387 self.hideflags = ReadByte();
393 self.teamradar_icon = (f & 0x7F);
396 self.(teamradar_times[self.teamradar_time_index]) = time;
397 self.teamradar_time_index = mod(self.teamradar_time_index + 1, MAX_TEAMRADAR_TIMES);
399 self.teamradar_color_x = ReadByte() / 255.0;
400 self.teamradar_color_y = ReadByte() / 255.0;
401 self.teamradar_color_z = ReadByte() / 255.0;
404 InterpolateOrigin_Note();
406 self.entremove = Ent_RemoveWaypointSprite;
409 void WaypointSprite_Load_Frames(string ext)
411 float dh, n, i, o, f;
412 string s, sname, sframes;
413 dh = search_begin(strcat("models/sprites/*_frame*", ext), FALSE, FALSE);
416 float ext_len = strlen(ext);
417 n = search_getsize(dh);
418 for(i = 0; i < n; ++i)
420 s = search_getfilename(dh, i);
421 s = substring(s, 15, strlen(s) - 15 - ext_len); // strip models/sprites/ and extension
423 o = strstrofs(s, "_frame", 0);
424 sname = strcat("/spriteframes/", substring(s, 0, o));
425 sframes = substring(s, o + 6, strlen(s) - o - 6);
426 f = stof(sframes) + 1;
427 db_put(tempdb, sname, ftos(max(f, stof(db_get(tempdb, sname)))));
432 void WaypointSprite_Load()
434 waypointsprite_fadedistance = vlen(mi_scale);
435 waypointsprite_normdistance = autocvar_g_waypointsprite_normdistance;
436 waypointsprite_minscale = autocvar_g_waypointsprite_minscale;
437 waypointsprite_minalpha = autocvar_g_waypointsprite_minalpha;
438 waypointsprite_distancealphaexponent = autocvar_g_waypointsprite_distancealphaexponent;
439 waypointsprite_timealphaexponent = autocvar_g_waypointsprite_timealphaexponent;
440 waypointsprite_scale = autocvar_g_waypointsprite_scale;
441 waypointsprite_edgefadealpha = autocvar_g_waypointsprite_edgefadealpha;
442 waypointsprite_edgefadescale = autocvar_g_waypointsprite_edgefadescale;
443 waypointsprite_edgefadedistance = autocvar_g_waypointsprite_edgefadedistance;
444 waypointsprite_crosshairfadealpha = autocvar_g_waypointsprite_crosshairfadealpha;
445 waypointsprite_crosshairfadescale = autocvar_g_waypointsprite_crosshairfadescale;
446 waypointsprite_crosshairfadedistance = autocvar_g_waypointsprite_crosshairfadedistance;
447 waypointsprite_distancefadealpha = autocvar_g_waypointsprite_distancefadealpha;
448 waypointsprite_distancefadescale = autocvar_g_waypointsprite_distancefadescale;
449 waypointsprite_distancefadedistance = waypointsprite_fadedistance * autocvar_g_waypointsprite_distancefadedistancemultiplier;
450 waypointsprite_alpha = autocvar_g_waypointsprite_alpha * (1 - autocvar__menu_alpha);
452 if(!waypointsprite_initialized)
454 WaypointSprite_Load_Frames(".tga");
455 WaypointSprite_Load_Frames(".jpg");
456 waypointsprite_initialized = true;