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);
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;
193 if(cvar("v_flipped"))
196 f1 = d_x / vid_conwidth;
197 f2 = d_y / vid_conheight;
199 if(max(f1, -f1) > max(f2, -f2))
230 o = d + '0.5 0 0' * vid_conwidth + '0 0.5 0' * vid_conheight;
235 vidscale = max(vid_conwidth / vid_width, vid_conheight / vid_height);
237 t = stof(db_get(tempdb, strcat("/spriteframes/", spriteimage)));
239 spriteimage = strcat("models/sprites/", spriteimage);
241 spriteimage = strcat("models/sprites/", spriteimage, "_frame", ftos(mod(floor((max(0, time - self.spawntime)) * 2), t)));
243 drawrotpic(o, rot * 90 * DEG2RAD, spriteimage, SPRITE_SIZE * waypointsprite_scale * vidscale, SPRITE_HOTSPOT * waypointsprite_scale * vidscale, '1 1 1', a, DRAWFLAG_MIPMAP);
245 if(self.build_finished)
247 if(time < self.build_finished + 0.25)
249 if(time < self.build_started)
250 self.health = self.build_starthealth;
251 else if(time < self.build_finished)
252 self.health = (time - self.build_started) / (self.build_finished - self.build_started) * (1 - self.build_starthealth) + self.build_starthealth;
263 if(self.build_finished)
267 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);
271 void Ent_RemoveWaypointSprite()
274 strunzone(self.netname);
276 strunzone(self.netname2);
278 strunzone(self.netname3);
281 void Ent_WaypointSprite()
283 float sendflags, f, t;
284 sendflags = ReadByte();
287 self.spawntime = time;
289 self.draw2d = Draw_WaypointSprite;
291 InterpolateOrigin_Undo();
298 self.health = t / 191.0;
299 self.build_finished = 0;
303 t = (t - 192) * 256 + ReadByte();
304 self.build_started = servertime;
305 if(self.build_finished)
306 self.build_starthealth = bound(0, self.health, 1);
308 self.build_starthealth = 0;
309 self.build_finished = servertime + t / 32;
310 //print("build: ", ftos(self.build_finished - self.build_started), "\n");
316 self.build_finished = 0;
321 // unfortunately, this needs to be exact (for the 3D display)
322 self.origin_x = ReadCoord();
323 self.origin_y = ReadCoord();
324 self.origin_z = ReadCoord();
329 self.team = ReadByte();
330 self.rule = ReadByte();
336 strunzone(self.netname);
337 self.netname = strzone(ReadString());
343 strunzone(self.netname2);
344 self.netname2 = strzone(ReadString());
350 strunzone(self.netname3);
351 self.netname3 = strzone(ReadString());
356 self.lifetime = ReadCoord();
357 self.fadetime = ReadCoord();
358 self.maxdistance = ReadShort();
359 self.hideflags = ReadByte();
365 self.teamradar_icon = (f & 0x7F);
368 self.(teamradar_times[self.teamradar_time_index]) = time;
369 self.teamradar_time_index = mod(self.teamradar_time_index + 1, MAX_TEAMRADAR_TIMES);
371 self.teamradar_color_x = ReadByte() / 255.0;
372 self.teamradar_color_y = ReadByte() / 255.0;
373 self.teamradar_color_z = ReadByte() / 255.0;
376 InterpolateOrigin_Note();
378 self.entremove = Ent_RemoveWaypointSprite;
381 void WaypointSprite_Load()
383 waypointsprite_fadedistance = vlen(world.maxs - world.mins);
384 waypointsprite_normdistance = cvar("g_waypointsprite_normdistance");
385 waypointsprite_minscale = cvar("g_waypointsprite_minscale");
386 waypointsprite_minalpha = cvar("g_waypointsprite_minalpha");
387 waypointsprite_distancealphaexponent = cvar("g_waypointsprite_distancealphaexponent");
388 waypointsprite_timealphaexponent = cvar("g_waypointsprite_timealphaexponent");
389 waypointsprite_scale = cvar("g_waypointsprite_scale");
390 if(!waypointsprite_scale)
391 waypointsprite_scale = 1.0;
393 if(!waypointsprite_initialized)
395 float dh, n, i, o, f;
396 string s, sname, sframes;
397 dh = search_begin("models/sprites/*_frame*.tga", FALSE, FALSE);
398 n = search_getsize(dh);
399 for(i = 0; i < n; ++i)
401 s = search_getfilename(dh, i);
402 if(substring(s, 0, 15) != "models/sprites/")
404 if(substring(s, strlen(s) - 4, 4) != ".tga")
406 s = substring(s, 15, strlen(s) - 19);
408 o = strstrofs(s, "_frame", 0);
409 sname = strcat("/spriteframes/", substring(s, 0, o));
410 sframes = substring(s, o + 6, strlen(s) - o - 6);
411 f = stof(sframes) + 1;
412 db_put(tempdb, sname, ftos(max(f, stof(db_get(tempdb, sname)))));
416 waypointsprite_initialized = 1;