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 vector SPRITE_SIZE = '256 32 0';
23 vector SPRITE_HOTSPOT = '128 32 0';
24 float SPRITE_HEALTHBAR_WIDTH = 96;
25 float SPRITE_HEALTHBAR_HEIGHT = 6;
26 float SPRITE_HEALTHBAR_MARGIN = 4;
27 float SPRITE_HEALTHBAR_BORDER = 1;
28 float SPRITE_HEALTHBAR_BORDERALPHA = 1;
29 float SPRITE_HEALTHBAR_HEALTHALPHA = 0.5;
31 void drawrotpic(vector org, float rot, string pic, vector sz, vector hotspot, vector rgb, float a, float f)
33 vector v1, v2, v3, v4;
35 hotspot = -1 * hotspot;
37 // hotspot-relative coordinates of the corners
39 v2 = hotspot + '1 0 0' * sz_x;
40 v3 = hotspot + '1 0 0' * sz_x + '0 1 0' * sz_y;
41 v4 = hotspot + '0 1 0' * sz_y;
43 // rotate them, and make them absolute
44 rot = -rot; // rotate by the opposite angle, as our coordinate system is reversed
45 v1 = rotate(v1, rot) + org;
46 v2 = rotate(v2, rot) + org;
47 v3 = rotate(v3, rot) + org;
48 v4 = rotate(v4, rot) + org;
51 R_BeginPolygon(pic, f);
52 R_PolygonVertex(v1, '0 0 0', rgb, a);
53 R_PolygonVertex(v2, '1 0 0', rgb, a);
54 R_PolygonVertex(v3, '1 1 0', rgb, a);
55 R_PolygonVertex(v4, '0 1 0', rgb, a);
59 void drawquad(vector o, vector ri, vector up, string pic, vector rgb, float a, float f)
61 R_BeginPolygon(pic, f);
62 R_PolygonVertex(o, '0 0 0', rgb, a);
63 R_PolygonVertex(o + ri, '1 0 0', rgb, a);
64 R_PolygonVertex(o + up + ri, '1 1 0', rgb, a);
65 R_PolygonVertex(o + up, '0 1 0', rgb, a);
69 void drawhealthbar(vector org, float rot, float h, vector sz, vector hotspot, float width, float height, float margin, float border, vector rgb, float a, vector hrgb, float ha, float f)
72 float owidth; // outer width
74 hotspot = -1 * hotspot;
76 // hotspot-relative coordinates of the healthbar corners
81 rot = -rot; // rotate by the opposite angle, as our coordinate system is reversed
82 o = rotate(o, rot) + org;
86 owidth = width + 2 * border;
87 o = o - up * (margin + border + height) + ri * (sz_x - owidth) * 0.5;
89 drawquad(o - up * border, ri * owidth, up * border, "", rgb, a, f);
90 drawquad(o + up * height, ri * owidth, up * border, "", rgb, a, f);
91 drawquad(o, ri * border, up * height, "", rgb, a, f);
92 drawquad(o + ri * (owidth - border), ri * border, up * height, "", rgb, a, f);
93 drawquad(o + ri * border, ri * width * h, up * height, "", hrgb, ha, f);
96 void Draw_WaypointSprite()
102 self.alpha = pow(bound(0, (self.fadetime - time) / self.lifetime, 1), waypointsprite_timealphaexponent);
106 if(self.hideflags & 2)
107 return; // radar only
109 if(cvar("cl_hidewaypoints") >= 2)
112 if(self.hideflags & 1)
113 if(cvar("cl_hidewaypoints"))
114 return; // fixed waypoint
116 InterpolateOrigin_Do();
118 t = GetPlayerColor(player_localentnum - 1) + 1;
125 case SPRITERULE_DEFAULT:
129 spriteimage = self.netname;
134 spriteimage = self.netname;
136 case SPRITERULE_TEAMPLAY:
137 if(t == COLOR_SPECTATOR + 1)
138 spriteimage = self.netname3;
139 else if(self.team == t)
140 spriteimage = self.netname2;
142 spriteimage = self.netname;
145 error("Invalid waypointsprite rule!");
149 if(spriteimage == "")
153 dist = vlen(self.origin - view_origin);
158 if(self.maxdistance > waypointsprite_normdistance)
159 a *= pow(bound(0, (self.maxdistance - dist) / (self.maxdistance - waypointsprite_normdistance), 1), waypointsprite_distancealphaexponent);
160 else if(self.maxdistance > 0)
161 a *= pow(bound(0, (waypointsprite_fadedistance - dist) / (waypointsprite_fadedistance - waypointsprite_normdistance), 1), waypointsprite_distancealphaexponent) * (1 - waypointsprite_minalpha) + waypointsprite_minalpha;
166 // draw the sprite image
169 o = project_3d_to_2d(self.origin);
172 if(o_z < 0 || o_x < 0 || o_y < 0 || o_x > vid_conwidth || o_y > vid_conheight)
174 // scale it to be just in view
178 // get the waypoint angle vector
180 d_x = view_right * (self.origin - view_origin) * vid_conwidth / vid_width;
181 d_y = -view_up * (self.origin - view_origin) * vid_conheight / (vid_height * vid_pixelheight);
185 d = o - '0.5 0 0' * vid_conwidth - '0 0.5 0' * vid_conheight;
187 if(cvar("v_flipped"))
190 f1 = d_x / vid_conwidth;
191 f2 = d_y / vid_conheight;
193 if(max(f1, -f1) > max(f2, -f2))
224 o = d + '0.5 0 0' * vid_conwidth + '0 0.5 0' * vid_conheight;
229 vidscale = max(vid_conwidth / vid_width, vid_conheight / vid_height);
231 t = stof(db_get(tempdb, strcat("/spriteframes/", spriteimage)));
233 spriteimage = strcat("models/sprites/", spriteimage);
235 spriteimage = strcat("models/sprites/", spriteimage, "_frame", ftos(mod(floor((max(0, time - self.spawntime)) * 2), t)));
237 drawrotpic(o, rot * 90 * DEG2RAD, spriteimage, SPRITE_SIZE * waypointsprite_scale * vidscale, SPRITE_HOTSPOT * waypointsprite_scale * vidscale, '1 1 1', a, DRAWFLAG_MIPMAP);
241 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, self.teamradar_color, a * SPRITE_HEALTHBAR_BORDERALPHA, self.teamradar_color, a * SPRITE_HEALTHBAR_HEALTHALPHA, DRAWFLAG_NORMAL);
245 void Ent_RemoveWaypointSprite()
248 strunzone(self.netname);
250 strunzone(self.netname2);
252 strunzone(self.netname3);
255 void Ent_WaypointSprite()
258 sendflags = ReadByte();
261 self.spawntime = time;
263 self.draw2d = Draw_WaypointSprite;
265 InterpolateOrigin_Undo();
268 self.health = ReadByte() / 255.0;
274 // unfortunately, this needs to be exact (for the 3D display)
275 self.origin_x = ReadCoord();
276 self.origin_y = ReadCoord();
277 self.origin_z = ReadCoord();
282 self.team = ReadByte();
283 self.rule = ReadByte();
289 strunzone(self.netname);
290 self.netname = strzone(ReadString());
296 strunzone(self.netname2);
297 self.netname2 = strzone(ReadString());
303 strunzone(self.netname3);
304 self.netname3 = strzone(ReadString());
309 self.lifetime = ReadCoord();
310 self.fadetime = ReadCoord();
311 self.maxdistance = ReadShort();
312 self.hideflags = ReadByte();
318 self.teamradar_icon = (f & 0x7F);
321 self.(teamradar_times[self.teamradar_time_index]) = time;
322 self.teamradar_time_index = mod(self.teamradar_time_index + 1, MAX_TEAMRADAR_TIMES);
324 self.teamradar_color_x = ReadByte() / 255.0;
325 self.teamradar_color_y = ReadByte() / 255.0;
326 self.teamradar_color_z = ReadByte() / 255.0;
329 InterpolateOrigin_Note();
331 self.entremove = Ent_RemoveWaypointSprite;
334 void WaypointSprite_Load()
336 waypointsprite_fadedistance = vlen(world.maxs - world.mins);
337 waypointsprite_normdistance = cvar("g_waypointsprite_normdistance");
338 waypointsprite_minscale = cvar("g_waypointsprite_minscale");
339 waypointsprite_minalpha = cvar("g_waypointsprite_minalpha");
340 waypointsprite_distancealphaexponent = cvar("g_waypointsprite_distancealphaexponent");
341 waypointsprite_timealphaexponent = cvar("g_waypointsprite_timealphaexponent");
342 waypointsprite_scale = cvar("g_waypointsprite_scale");
343 if(!waypointsprite_scale)
344 waypointsprite_scale = 1.0;
346 if(!waypointsprite_initialized)
348 float dh, n, i, o, f;
349 string s, sname, sframes;
350 dh = search_begin("models/sprites/*_frame*.tga", FALSE, FALSE);
351 n = search_getsize(dh);
352 for(i = 0; i < n; ++i)
354 s = search_getfilename(dh, i);
355 if(substring(s, 0, 15) != "models/sprites/")
357 if(substring(s, strlen(s) - 4, 4) != ".tga")
359 s = substring(s, 15, strlen(s) - 19);
361 o = strstrofs(s, "_frame", 0);
362 sname = strcat("/spriteframes/", substring(s, 0, o));
363 sframes = substring(s, o + 6, strlen(s) - o - 6);
364 f = stof(sframes) + 1;
365 db_put(tempdb, sname, ftos(max(f, stof(db_get(tempdb, sname)))));
369 waypointsprite_initialized = 1;