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(cvar("r_letterbox") == 1)
118 if(self.hideflags & 1)
119 if(cvar("cl_hidewaypoints"))
120 return; // fixed waypoint
122 InterpolateOrigin_Do();
124 t = GetPlayerColor(player_localentnum - 1) + 1;
131 case SPRITERULE_DEFAULT:
135 spriteimage = self.netname;
140 spriteimage = self.netname;
142 case SPRITERULE_TEAMPLAY:
143 if(t == COLOR_SPECTATOR + 1)
144 spriteimage = self.netname3;
145 else if(self.team == t)
146 spriteimage = self.netname2;
148 spriteimage = self.netname;
151 error("Invalid waypointsprite rule!");
155 if(spriteimage == "")
159 dist = vlen(self.origin - view_origin);
162 a = self.alpha * sbar_alpha_fg;
164 if(self.maxdistance > waypointsprite_normdistance)
165 a *= pow(bound(0, (self.maxdistance - dist) / (self.maxdistance - waypointsprite_normdistance), 1), waypointsprite_distancealphaexponent);
166 else if(self.maxdistance > 0)
167 a *= pow(bound(0, (waypointsprite_fadedistance - dist) / (waypointsprite_fadedistance - waypointsprite_normdistance), 1), waypointsprite_distancealphaexponent) * (1 - waypointsprite_minalpha) + waypointsprite_minalpha;
172 // draw the sprite image
175 o = project_3d_to_2d(self.origin);
178 if(o_z < 0 || o_x < 0 || o_y < 0 || o_x > vid_conwidth || o_y > vid_conheight)
180 // scale it to be just in view
184 // get the waypoint angle vector
186 d_x = view_right * (self.origin - view_origin) * vid_conwidth / vid_width;
187 d_y = -view_up * (self.origin - view_origin) * vid_conheight / (vid_height * vid_pixelheight);
191 d = o - '0.5 0 0' * vid_conwidth - '0 0.5 0' * vid_conheight;
194 if(cvar("v_flipped"))
198 f1 = d_x / vid_conwidth;
199 f2 = d_y / vid_conheight;
201 if(max(f1, -f1) > max(f2, -f2))
232 o = d + '0.5 0 0' * vid_conwidth + '0 0.5 0' * vid_conheight;
237 vidscale = max(vid_conwidth / vid_width, vid_conheight / vid_height);
239 t = stof(db_get(tempdb, strcat("/spriteframes/", spriteimage)));
241 spriteimage = strcat("models/sprites/", spriteimage);
243 spriteimage = strcat("models/sprites/", spriteimage, "_frame", ftos(mod(floor((max(0, time - self.spawntime)) * 2), t)));
245 drawrotpic(o, rot * 90 * DEG2RAD, spriteimage, SPRITE_SIZE * waypointsprite_scale * vidscale, SPRITE_HOTSPOT * waypointsprite_scale * vidscale, '1 1 1', a, DRAWFLAG_MIPMAP);
247 if(self.build_finished)
249 if(time < self.build_finished + 0.25)
251 if(time < self.build_started)
252 self.health = self.build_starthealth;
253 else if(time < self.build_finished)
254 self.health = (time - self.build_started) / (self.build_finished - self.build_started) * (1 - self.build_starthealth) + self.build_starthealth;
265 if(self.build_finished)
269 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);
273 void Ent_RemoveWaypointSprite()
276 strunzone(self.netname);
278 strunzone(self.netname2);
280 strunzone(self.netname3);
283 void Ent_WaypointSprite()
285 float sendflags, f, t;
286 sendflags = ReadByte();
289 self.spawntime = time;
291 self.draw2d = Draw_WaypointSprite;
293 InterpolateOrigin_Undo();
300 self.health = t / 191.0;
301 self.build_finished = 0;
305 t = (t - 192) * 256 + ReadByte();
306 self.build_started = servertime;
307 if(self.build_finished)
308 self.build_starthealth = bound(0, self.health, 1);
310 self.build_starthealth = 0;
311 self.build_finished = servertime + t / 32;
312 //print("build: ", ftos(self.build_finished - self.build_started), "\n");
318 self.build_finished = 0;
323 // unfortunately, this needs to be exact (for the 3D display)
324 self.origin_x = ReadCoord();
325 self.origin_y = ReadCoord();
326 self.origin_z = ReadCoord();
331 self.team = ReadByte();
332 self.rule = ReadByte();
338 strunzone(self.netname);
339 self.netname = strzone(ReadString());
345 strunzone(self.netname2);
346 self.netname2 = strzone(ReadString());
352 strunzone(self.netname3);
353 self.netname3 = strzone(ReadString());
358 self.lifetime = ReadCoord();
359 self.fadetime = ReadCoord();
360 self.maxdistance = ReadShort();
361 self.hideflags = ReadByte();
367 self.teamradar_icon = (f & 0x7F);
370 self.(teamradar_times[self.teamradar_time_index]) = time;
371 self.teamradar_time_index = mod(self.teamradar_time_index + 1, MAX_TEAMRADAR_TIMES);
373 self.teamradar_color_x = ReadByte() / 255.0;
374 self.teamradar_color_y = ReadByte() / 255.0;
375 self.teamradar_color_z = ReadByte() / 255.0;
378 InterpolateOrigin_Note();
380 self.entremove = Ent_RemoveWaypointSprite;
383 void WaypointSprite_Load()
385 waypointsprite_fadedistance = vlen(world.maxs - world.mins);
386 waypointsprite_normdistance = cvar("g_waypointsprite_normdistance");
387 waypointsprite_minscale = cvar("g_waypointsprite_minscale");
388 waypointsprite_minalpha = cvar("g_waypointsprite_minalpha");
389 waypointsprite_distancealphaexponent = cvar("g_waypointsprite_distancealphaexponent");
390 waypointsprite_timealphaexponent = cvar("g_waypointsprite_timealphaexponent");
391 waypointsprite_scale = cvar("g_waypointsprite_scale") * (1 - cvar("_menu_alpha"));
392 if(!waypointsprite_scale)
393 waypointsprite_scale = 1.0 * (1 - cvar("_menu_alpha"));
395 if(!waypointsprite_initialized)
397 float dh, n, i, o, f;
398 string s, sname, sframes;
399 dh = search_begin("models/sprites/*_frame*.tga", FALSE, FALSE);
400 n = search_getsize(dh);
401 for(i = 0; i < n; ++i)
403 s = search_getfilename(dh, i);
404 if(substring(s, 0, 15) != "models/sprites/")
406 if(substring(s, strlen(s) - 4, 4) != ".tga")
408 s = substring(s, 15, strlen(s) - 19);
410 o = strstrofs(s, "_frame", 0);
411 sname = strcat("/spriteframes/", substring(s, 0, o));
412 sframes = substring(s, o + 6, strlen(s) - o - 6);
413 f = stof(sframes) + 1;
414 db_put(tempdb, sname, ftos(max(f, stof(db_get(tempdb, sname)))));
418 waypointsprite_initialized = 1;