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;
11 .string netname; // primary picture
12 .string netname2; // secondary picture
13 .string netname3; // tertiary picture
14 .float team; // team that gets netname2
22 .float build_starthealth;
23 .float build_finished;
25 vector SPRITE_SIZE = '288 36 0';
26 vector SPRITE_HOTSPOT = '144 36 0';
27 float SPRITE_HEALTHBAR_WIDTH = 96;
28 float SPRITE_HEALTHBAR_HEIGHT = 6;
29 float SPRITE_HEALTHBAR_MARGIN = 4;
30 float SPRITE_HEALTHBAR_BORDER = 1;
31 float SPRITE_HEALTHBAR_BORDERALPHA = 1;
32 float SPRITE_HEALTHBAR_HEALTHALPHA = 0.5;
34 void drawrotpic(vector org, float rot, string pic, vector sz, vector hotspot, vector rgb, float a, float f)
36 vector v1, v2, v3, v4;
38 hotspot = -1 * hotspot;
40 // hotspot-relative coordinates of the corners
42 v2 = hotspot + '1 0 0' * sz_x;
43 v3 = hotspot + '1 0 0' * sz_x + '0 1 0' * sz_y;
44 v4 = hotspot + '0 1 0' * sz_y;
46 // rotate them, and make them absolute
47 rot = -rot; // rotate by the opposite angle, as our coordinate system is reversed
48 v1 = rotate(v1, rot) + org;
49 v2 = rotate(v2, rot) + org;
50 v3 = rotate(v3, rot) + org;
51 v4 = rotate(v4, rot) + org;
54 R_BeginPolygon(pic, f);
55 R_PolygonVertex(v1, '0 0 0', rgb, a);
56 R_PolygonVertex(v2, '1 0 0', rgb, a);
57 R_PolygonVertex(v3, '1 1 0', rgb, a);
58 R_PolygonVertex(v4, '0 1 0', rgb, a);
62 void drawquad(vector o, vector ri, vector up, string pic, vector rgb, float a, float f)
64 R_BeginPolygon(pic, f);
65 R_PolygonVertex(o, '0 0 0', rgb, a);
66 R_PolygonVertex(o + ri, '1 0 0', rgb, a);
67 R_PolygonVertex(o + up + ri, '1 1 0', rgb, a);
68 R_PolygonVertex(o + up, '0 1 0', rgb, a);
72 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)
75 float owidth; // outer width
77 hotspot = -1 * hotspot;
79 // hotspot-relative coordinates of the healthbar corners
84 rot = -rot; // rotate by the opposite angle, as our coordinate system is reversed
85 o = rotate(o, rot) + org;
89 owidth = width + 2 * border;
90 o = o - up * (margin + border + height) + ri * (sz_x - owidth) * 0.5;
92 drawquad(o - up * border, ri * owidth, up * border, "", rgb, a, f);
93 drawquad(o + up * height, ri * owidth, up * border, "", rgb, a, f);
94 drawquad(o, ri * border, up * height, "", rgb, a, f);
95 drawquad(o + ri * (owidth - border), ri * border, up * height, "", rgb, a, f);
96 drawquad(o + ri * (border + align * ((1 - h) * width)), ri * width * h, up * height, "", hrgb, ha, f);
99 void Draw_WaypointSprite()
105 self.alpha = pow(bound(0, (self.fadetime - time) / self.lifetime, 1), waypointsprite_timealphaexponent);
109 if(self.hideflags & 2)
110 return; // radar only
112 if(cvar("cl_hidewaypoints") >= 2)
115 if(self.hideflags & 1)
116 if(cvar("cl_hidewaypoints"))
117 return; // fixed waypoint
119 InterpolateOrigin_Do();
121 t = GetPlayerColor(player_localentnum - 1) + 1;
128 case SPRITERULE_DEFAULT:
132 spriteimage = self.netname;
137 spriteimage = self.netname;
139 case SPRITERULE_TEAMPLAY:
140 if(t == COLOR_SPECTATOR + 1)
141 spriteimage = self.netname3;
142 else if(self.team == t)
143 spriteimage = self.netname2;
145 spriteimage = self.netname;
148 error("Invalid waypointsprite rule!");
152 if(spriteimage == "")
156 dist = vlen(self.origin - view_origin);
159 a = self.alpha * sbar_alpha_fg;
161 if(self.maxdistance > waypointsprite_normdistance)
162 a *= pow(bound(0, (self.maxdistance - dist) / (self.maxdistance - waypointsprite_normdistance), 1), waypointsprite_distancealphaexponent);
163 else if(self.maxdistance > 0)
164 a *= pow(bound(0, (waypointsprite_fadedistance - dist) / (waypointsprite_fadedistance - waypointsprite_normdistance), 1), waypointsprite_distancealphaexponent) * (1 - waypointsprite_minalpha) + waypointsprite_minalpha;
169 // draw the sprite image
172 o = project_3d_to_2d(self.origin);
175 if(o_z < 0 || o_x < 0 || o_y < 0 || o_x > vid_conwidth || o_y > vid_conheight)
177 // scale it to be just in view
181 // get the waypoint angle vector
183 d_x = view_right * (self.origin - view_origin) * vid_conwidth / vid_width;
184 d_y = -view_up * (self.origin - view_origin) * vid_conheight / (vid_height * vid_pixelheight);
188 d = o - '0.5 0 0' * vid_conwidth - '0 0.5 0' * vid_conheight;
191 if(cvar("v_flipped"))
195 f1 = d_x / vid_conwidth;
196 f2 = d_y / vid_conheight;
198 if(max(f1, -f1) > max(f2, -f2))
229 o = d + '0.5 0 0' * vid_conwidth + '0 0.5 0' * vid_conheight;
234 vidscale = max(vid_conwidth / vid_width, vid_conheight / vid_height);
236 t = stof(db_get(tempdb, strcat("/spriteframes/", spriteimage)));
238 spriteimage = strcat("models/sprites/", spriteimage);
240 spriteimage = strcat("models/sprites/", spriteimage, "_frame", ftos(mod(floor((max(0, time - self.spawntime)) * 2), t)));
242 float edgefadealpha = cvar("g_waypointsprite_edgefadealpha");
243 float edgefadescale = cvar("g_waypointsprite_edgefadescale");
244 float edgefadedistance = cvar("g_waypointsprite_edgefadedistance");
245 float edgedistance_min = min4(o_y, o_x,vid_conwidth - o_x, vid_conheight - o_y);
247 float crosshairfadealpha = cvar("g_waypointsprite_crosshairfadealpha");
248 float crosshairfadescale = cvar("g_waypointsprite_crosshairfadescale");
249 float crosshairfadedistance = cvar("g_waypointsprite_crosshairfadedistance");
250 float crosshairdistance; // current distance from waypoint to crosshair
251 crosshairdistance = sqrt( pow(o_x - vid_conwidth/2, 2) + pow(o_y - vid_conheight/2, 2) );
253 if (edgedistance_min < edgefadedistance) {
254 a = a * bound(edgefadealpha, edgedistance_min/edgefadedistance, 1);
255 vidscale = vidscale * bound(edgefadescale, edgedistance_min/edgefadedistance, 1);
256 } else if (crosshairdistance < crosshairfadedistance) {
257 a = a * bound(crosshairfadealpha, crosshairdistance/crosshairfadedistance, 1);
258 vidscale = vidscale * bound(crosshairfadescale, crosshairdistance/crosshairfadedistance, 1);
260 drawrotpic(o, rot * 90 * DEG2RAD, spriteimage, SPRITE_SIZE * waypointsprite_scale * vidscale, SPRITE_HOTSPOT * waypointsprite_scale * vidscale, '1 1 1', a, DRAWFLAG_MIPMAP);
262 if(self.build_finished)
264 if(time < self.build_finished + 0.25)
266 if(time < self.build_started)
267 self.health = self.build_starthealth;
268 else if(time < self.build_finished)
269 self.health = (time - self.build_started) / (self.build_finished - self.build_started) * (1 - self.build_starthealth) + self.build_starthealth;
280 if(self.build_finished)
284 drawhealthbar(o, rot * 90 * DEG2RAD, self.health, SPRITE_SIZE * waypointsprite_scale * vidscale, SPRITE_HOTSPOT * waypointsprite_scale * vidscale, SPRITE_HEALTHBAR_WIDTH, SPRITE_HEALTHBAR_HEIGHT, SPRITE_HEALTHBAR_MARGIN, SPRITE_HEALTHBAR_BORDER, align, self.teamradar_color, a * SPRITE_HEALTHBAR_BORDERALPHA, self.teamradar_color, a * SPRITE_HEALTHBAR_HEALTHALPHA, DRAWFLAG_NORMAL);
288 void Ent_RemoveWaypointSprite()
291 strunzone(self.netname);
293 strunzone(self.netname2);
295 strunzone(self.netname3);
298 void Ent_WaypointSprite()
300 float sendflags, f, t;
301 sendflags = ReadByte();
304 self.spawntime = time;
306 self.draw2d = Draw_WaypointSprite;
308 InterpolateOrigin_Undo();
315 self.health = t / 191.0;
316 self.build_finished = 0;
320 t = (t - 192) * 256 + ReadByte();
321 self.build_started = servertime;
322 if(self.build_finished)
323 self.build_starthealth = bound(0, self.health, 1);
325 self.build_starthealth = 0;
326 self.build_finished = servertime + t / 32;
327 //print("build: ", ftos(self.build_finished - self.build_started), "\n");
333 self.build_finished = 0;
338 // unfortunately, this needs to be exact (for the 3D display)
339 self.origin_x = ReadCoord();
340 self.origin_y = ReadCoord();
341 self.origin_z = ReadCoord();
346 self.team = ReadByte();
347 self.rule = ReadByte();
353 strunzone(self.netname);
354 self.netname = strzone(ReadString());
360 strunzone(self.netname2);
361 self.netname2 = strzone(ReadString());
367 strunzone(self.netname3);
368 self.netname3 = strzone(ReadString());
373 self.lifetime = ReadCoord();
374 self.fadetime = ReadCoord();
375 self.maxdistance = ReadShort();
376 self.hideflags = ReadByte();
382 self.teamradar_icon = (f & 0x7F);
385 self.(teamradar_times[self.teamradar_time_index]) = time;
386 self.teamradar_time_index = mod(self.teamradar_time_index + 1, MAX_TEAMRADAR_TIMES);
388 self.teamradar_color_x = ReadByte() / 255.0;
389 self.teamradar_color_y = ReadByte() / 255.0;
390 self.teamradar_color_z = ReadByte() / 255.0;
393 InterpolateOrigin_Note();
395 self.entremove = Ent_RemoveWaypointSprite;
398 void WaypointSprite_Load()
400 waypointsprite_fadedistance = vlen(world.maxs - world.mins);
401 waypointsprite_normdistance = cvar("g_waypointsprite_normdistance");
402 waypointsprite_minscale = cvar("g_waypointsprite_minscale");
403 waypointsprite_minalpha = cvar("g_waypointsprite_minalpha");
404 waypointsprite_distancealphaexponent = cvar("g_waypointsprite_distancealphaexponent");
405 waypointsprite_timealphaexponent = cvar("g_waypointsprite_timealphaexponent");
406 waypointsprite_scale = cvar("g_waypointsprite_scale") * (1 - cvar("_menu_alpha"));
407 if(!waypointsprite_scale)
408 waypointsprite_scale = 1.0 * (1 - cvar("_menu_alpha"));
410 if(!waypointsprite_initialized)
412 float dh, n, i, o, f;
413 string s, sname, sframes;
414 dh = search_begin("models/sprites/*_frame*.tga", FALSE, FALSE);
415 n = search_getsize(dh);
416 for(i = 0; i < n; ++i)
418 s = search_getfilename(dh, i);
419 if(substring(s, 0, 15) != "models/sprites/")
421 if(substring(s, strlen(s) - 4, 4) != ".tga")
423 s = substring(s, 15, strlen(s) - 19);
425 o = strstrofs(s, "_frame", 0);
426 sname = strcat("/spriteframes/", substring(s, 0, o));
427 sframes = substring(s, o + 6, strlen(s) - o - 6);
428 f = stof(sframes) + 1;
429 db_put(tempdb, sname, ftos(max(f, stof(db_get(tempdb, sname)))));
433 waypointsprite_initialized = 1;