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 = '256 32 0';
26 vector SPRITE_HOTSPOT = '128 32 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);
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;
190 if(cvar("v_flipped"))
193 f1 = d_x / vid_conwidth;
194 f2 = d_y / vid_conheight;
196 if(max(f1, -f1) > max(f2, -f2))
227 o = d + '0.5 0 0' * vid_conwidth + '0 0.5 0' * vid_conheight;
232 vidscale = max(vid_conwidth / vid_width, vid_conheight / vid_height);
234 t = stof(db_get(tempdb, strcat("/spriteframes/", spriteimage)));
236 spriteimage = strcat("models/sprites/", spriteimage);
238 spriteimage = strcat("models/sprites/", spriteimage, "_frame", ftos(mod(floor((max(0, time - self.spawntime)) * 2), t)));
240 drawrotpic(o, rot * 90 * DEG2RAD, spriteimage, SPRITE_SIZE * waypointsprite_scale * vidscale, SPRITE_HOTSPOT * waypointsprite_scale * vidscale, '1 1 1', a, DRAWFLAG_MIPMAP);
242 if(self.build_finished)
244 if(time < self.build_finished + 0.25)
246 if(time < self.build_started)
247 self.health = self.build_starthealth;
248 else if(time < self.build_finished)
249 self.health = (time - self.build_started) / (self.build_finished - self.build_started) * (1 - self.build_starthealth) + self.build_starthealth;
259 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.build_finished ? 0.5 : 0), self.teamradar_color, a * SPRITE_HEALTHBAR_BORDERALPHA, self.teamradar_color, a * SPRITE_HEALTHBAR_HEALTHALPHA, DRAWFLAG_NORMAL);
263 void Ent_RemoveWaypointSprite()
266 strunzone(self.netname);
268 strunzone(self.netname2);
270 strunzone(self.netname3);
273 void Ent_WaypointSprite()
275 float sendflags, f, t;
276 sendflags = ReadByte();
279 self.spawntime = time;
281 self.draw2d = Draw_WaypointSprite;
283 InterpolateOrigin_Undo();
290 self.health = t / 191.0;
291 self.build_finished = 0;
295 t = (t - 192) * 256 + ReadByte();
296 self.build_started = servertime;
297 if(self.build_finished)
298 self.build_starthealth = bound(0, self.health, 1);
300 self.build_starthealth = 0;
301 self.build_finished = servertime + t / 32;
302 //print("build: ", ftos(self.build_finished - self.build_started), "\n");
310 // unfortunately, this needs to be exact (for the 3D display)
311 self.origin_x = ReadCoord();
312 self.origin_y = ReadCoord();
313 self.origin_z = ReadCoord();
318 self.team = ReadByte();
319 self.rule = ReadByte();
325 strunzone(self.netname);
326 self.netname = strzone(ReadString());
332 strunzone(self.netname2);
333 self.netname2 = strzone(ReadString());
339 strunzone(self.netname3);
340 self.netname3 = strzone(ReadString());
345 self.lifetime = ReadCoord();
346 self.fadetime = ReadCoord();
347 self.maxdistance = ReadShort();
348 self.hideflags = ReadByte();
354 self.teamradar_icon = (f & 0x7F);
357 self.(teamradar_times[self.teamradar_time_index]) = time;
358 self.teamradar_time_index = mod(self.teamradar_time_index + 1, MAX_TEAMRADAR_TIMES);
360 self.teamradar_color_x = ReadByte() / 255.0;
361 self.teamradar_color_y = ReadByte() / 255.0;
362 self.teamradar_color_z = ReadByte() / 255.0;
365 InterpolateOrigin_Note();
367 self.entremove = Ent_RemoveWaypointSprite;
370 void WaypointSprite_Load()
372 waypointsprite_fadedistance = vlen(world.maxs - world.mins);
373 waypointsprite_normdistance = cvar("g_waypointsprite_normdistance");
374 waypointsprite_minscale = cvar("g_waypointsprite_minscale");
375 waypointsprite_minalpha = cvar("g_waypointsprite_minalpha");
376 waypointsprite_distancealphaexponent = cvar("g_waypointsprite_distancealphaexponent");
377 waypointsprite_timealphaexponent = cvar("g_waypointsprite_timealphaexponent");
378 waypointsprite_scale = cvar("g_waypointsprite_scale");
379 if(!waypointsprite_scale)
380 waypointsprite_scale = 1.0;
382 if(!waypointsprite_initialized)
384 float dh, n, i, o, f;
385 string s, sname, sframes;
386 dh = search_begin("models/sprites/*_frame*.tga", FALSE, FALSE);
387 n = search_getsize(dh);
388 for(i = 0; i < n; ++i)
390 s = search_getfilename(dh, i);
391 if(substring(s, 0, 15) != "models/sprites/")
393 if(substring(s, strlen(s) - 4, 4) != ".tga")
395 s = substring(s, 15, strlen(s) - 19);
397 o = strstrofs(s, "_frame", 0);
398 sname = strcat("/spriteframes/", substring(s, 0, o));
399 sframes = substring(s, o + 6, strlen(s) - o - 6);
400 f = stof(sframes) + 1;
401 db_put(tempdb, sname, ftos(max(f, stof(db_get(tempdb, sname)))));
405 waypointsprite_initialized = 1;