]> icculus.org git repositories - divverent/nexuiz.git/blob - data/qcsrc/client/waypointsprites.qc
do not alpha out the number of the armor display
[divverent/nexuiz.git] / data / qcsrc / client / waypointsprites.qc
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;
9 float waypointsprite_edgefadealpha;
10 float waypointsprite_edgefadescale;
11 float waypointsprite_edgefadedistance;
12 float waypointsprite_crosshairfadealpha;
13 float waypointsprite_crosshairfadescale;
14 float waypointsprite_crosshairfadedistance;
15 float waypointsprite_distancefadealpha;
16 float waypointsprite_distancefadescale;
17 float waypointsprite_distancefadedistance;
18
19 .float rule;
20 .string netname; // primary picture
21 .string netname2; // secondary picture
22 .string netname3; // tertiary picture
23 .float team; // team that gets netname2
24 .float lifetime;
25 .float fadetime;
26 .float maxdistance;
27 .float hideflags;
28 .float spawntime;
29 .float health;
30 .float build_started;
31 .float build_starthealth;
32 .float build_finished;
33
34 vector SPRITE_SIZE = '288 36 0';
35 vector SPRITE_HOTSPOT = '144 36 0';
36 float SPRITE_HEALTHBAR_WIDTH = 144;
37 float SPRITE_HEALTHBAR_HEIGHT = 9;
38 float SPRITE_HEALTHBAR_MARGIN = 6;
39 float SPRITE_HEALTHBAR_BORDER = 2;
40 float SPRITE_HEALTHBAR_BORDERALPHA = 1;
41 float SPRITE_HEALTHBAR_HEALTHALPHA = 0.5;
42
43 void drawrotpic(vector org, float rot, string pic, vector sz, vector hotspot, vector rgb, float a, float f)
44 {
45         vector v1, v2, v3, v4;
46
47         hotspot = -1 * hotspot;
48
49         // hotspot-relative coordinates of the corners
50         v1 = hotspot;
51         v2 = hotspot + '1 0 0' * sz_x;
52         v3 = hotspot + '1 0 0' * sz_x + '0 1 0' * sz_y;
53         v4 = hotspot                  + '0 1 0' * sz_y;
54
55         // rotate them, and make them absolute
56         rot = -rot; // rotate by the opposite angle, as our coordinate system is reversed
57         v1 = rotate(v1, rot) + org;
58         v2 = rotate(v2, rot) + org;
59         v3 = rotate(v3, rot) + org;
60         v4 = rotate(v4, rot) + org;
61
62         // draw them
63         R_BeginPolygon(pic, f);
64         R_PolygonVertex(v1, '0 0 0', rgb, a);
65         R_PolygonVertex(v2, '1 0 0', rgb, a);
66         R_PolygonVertex(v3, '1 1 0', rgb, a);
67         R_PolygonVertex(v4, '0 1 0', rgb, a);
68         R_EndPolygon();
69 }
70
71 void drawquad(vector o, vector ri, vector up, string pic, vector rgb, float a, float f)
72 {
73         R_BeginPolygon(pic, f);
74         R_PolygonVertex(o, '0 0 0', rgb, a);
75         R_PolygonVertex(o + ri, '1 0 0', rgb, a);
76         R_PolygonVertex(o + up + ri, '1 1 0', rgb, a);
77         R_PolygonVertex(o + up, '0 1 0', rgb, a);
78         R_EndPolygon();
79 }
80
81 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)
82 {
83         vector o, ri, up;
84         float owidth; // outer width
85
86         hotspot = -1 * hotspot;
87
88         // hotspot-relative coordinates of the healthbar corners
89         o = hotspot;
90         ri = '1 0 0';
91         up = '0 1 0';
92         
93         rot = -rot; // rotate by the opposite angle, as our coordinate system is reversed
94         o = rotate(o, rot) + org;
95         ri = rotate(ri, rot);
96         up = rotate(up, rot);
97
98         owidth = width + 2 * border;
99         o = o - up * (margin + border + height) + ri * (sz_x - owidth) * 0.5;
100
101         drawquad(o - up * border,                               ri * owidth,    up * border, "", rgb,  a,  f);
102         drawquad(o + up * height,                               ri * owidth,    up * border, "", rgb,  a,  f);
103         drawquad(o,                                             ri * border,    up * height, "", rgb,  a,  f);
104         drawquad(o + ri * (owidth - border),                    ri * border,    up * height, "", rgb,  a,  f);
105         drawquad(o + ri * (border + align * ((1 - h) * width)), ri * width * h, up * height, "", hrgb, ha, f);
106 }
107
108 void Draw_WaypointSprite()
109 {
110         string spriteimage;
111         float t;
112
113         if(self.lifetime)
114                 self.alpha = pow(bound(0, (self.fadetime - time) / self.lifetime, 1), waypointsprite_timealphaexponent);
115         else
116                 self.alpha = 1;
117
118         if(self.hideflags & 2)
119                 return; // radar only
120
121         if(cvar("cl_hidewaypoints") >= 2)
122                 return;
123
124         if(self.hideflags & 1)
125                 if(cvar("cl_hidewaypoints"))
126                         return; // fixed waypoint
127
128         InterpolateOrigin_Do();
129
130         t = GetPlayerColor(player_localentnum - 1) + 1;
131
132         spriteimage = "";
133
134         // choose the sprite
135         switch(self.rule)
136         {
137                 case SPRITERULE_DEFAULT:
138                         if(self.team)
139                         {
140                                 if(self.team == t)
141                                         spriteimage = self.netname;
142                                 else
143                                         spriteimage = "";
144                         }
145                         else
146                                 spriteimage = self.netname;
147                         break;
148                 case SPRITERULE_TEAMPLAY:
149                         if(t == COLOR_SPECTATOR + 1)
150                                 spriteimage = self.netname3;
151                         else if(self.team == t)
152                                 spriteimage = self.netname2;
153                         else
154                                 spriteimage = self.netname;
155                         break;
156                 default:
157                         error("Invalid waypointsprite rule!");
158                         break;
159         }
160
161         if(spriteimage == "")
162                 return;
163         
164         float dist;
165         dist = vlen(self.origin - view_origin);
166         
167         float a;
168         a = self.alpha * sbar_alpha_fg;
169
170         if(self.maxdistance > waypointsprite_normdistance)
171                 a *= pow(bound(0, (self.maxdistance - dist) / (self.maxdistance - waypointsprite_normdistance), 1), waypointsprite_distancealphaexponent);
172         else if(self.maxdistance > 0)
173                 a *= pow(bound(0, (waypointsprite_fadedistance - dist) / (waypointsprite_fadedistance - waypointsprite_normdistance), 1), waypointsprite_distancealphaexponent) * (1 - waypointsprite_minalpha) + waypointsprite_minalpha;
174
175         if(a <= 0)
176                 return;
177         
178         // draw the sprite image
179         vector o;
180         float rot;
181         o = project_3d_to_2d(self.origin);
182         rot = 0;
183
184         if(o_z < 0 || o_x < 0 || o_y < 0 || o_x > vid_conwidth || o_y > vid_conheight)
185         {
186                 // scale it to be just in view
187                 vector d;
188                 float f1, f2;
189
190                 // get the waypoint angle vector
191                 /*
192                 d_x = view_right * (self.origin - view_origin) * vid_conwidth / vid_width;
193                 d_y = -view_up * (self.origin - view_origin) * vid_conheight / (vid_height * vid_pixelheight);
194                 d_z = 0;
195                 */
196                 
197                 d = o - '0.5 0 0' * vid_conwidth - '0 0.5 0' * vid_conheight;
198
199                 /*
200                 if(cvar("v_flipped"))
201                         d_x = -d_x;
202                 */
203
204                 f1 = d_x / vid_conwidth;
205                 f2 = d_y / vid_conheight;
206
207                 if(max(f1, -f1) > max(f2, -f2))
208                 {
209                         if(d_z * f1 > 0)
210                         {
211                                 // RIGHT edge
212                                 d = d * (0.5 / f1);
213                                 rot = 3;
214                         }
215                         else
216                         {
217                                 // LEFT edge
218                                 d = d * (-0.5 / f1);
219                                 rot = 1;
220                         }
221                 }
222                 else
223                 {
224                         if(d_z * f2 > 0)
225                         {
226                                 // BOTTOM edge
227                                 d = d * (0.5 / f2);
228                                 rot = 0;
229                         }
230                         else
231                         {
232                                 // TOP edge
233                                 d = d * (-0.5 / f2);
234                                 rot = 2;
235                         }
236                 }
237
238                 o = d + '0.5 0 0' * vid_conwidth + '0 0.5 0' * vid_conheight;
239         }
240         o_z = 0;
241
242         float vidscale;
243         vidscale = max(vid_conwidth / vid_width, vid_conheight / vid_height);
244
245         t = stof(db_get(tempdb, strcat("/spriteframes/", spriteimage)));
246         if(t == 0)
247                 spriteimage = strcat("models/sprites/", spriteimage);
248         else
249                 spriteimage = strcat("models/sprites/", spriteimage, "_frame", ftos(mod(floor((max(0, time - self.spawntime)) * 2), t)));
250
251         float edgedistance_min, crosshairdistance;
252         edgedistance_min = min4(o_y, o_x,vid_conwidth - o_x, vid_conheight - o_y);
253
254         crosshairdistance = sqrt( pow(o_x - vid_conwidth/2, 2) + pow(o_y - vid_conheight/2, 2) );
255
256         t = waypointsprite_scale * vidscale;
257
258         {
259                 a = a * (1 - (1 - waypointsprite_distancefadealpha) * (bound(0, dist/waypointsprite_distancefadedistance, 1)));
260                 t = t * (1 - (1 - waypointsprite_distancefadescale) * (bound(0, dist/waypointsprite_distancefadedistance, 1)));
261         }
262         if (edgedistance_min < waypointsprite_edgefadedistance) {
263                 a = a * (1 - (1 - waypointsprite_edgefadealpha) * (1 - bound(0, edgedistance_min/waypointsprite_edgefadedistance, 1)));
264                 t = t * (1 - (1 - waypointsprite_edgefadescale) * (1 - bound(0, edgedistance_min/waypointsprite_edgefadedistance, 1)));
265         }
266         if(crosshairdistance < waypointsprite_crosshairfadedistance) {
267                 a = a * (1 - (1 - waypointsprite_crosshairfadealpha) * (1 - bound(0, crosshairdistance/waypointsprite_crosshairfadedistance, 1)));
268                 t = t * (1 - (1 - waypointsprite_crosshairfadescale) * (1 - bound(0, crosshairdistance/waypointsprite_crosshairfadedistance, 1)));
269         }
270         drawrotpic(o, rot * 90 * DEG2RAD, spriteimage, SPRITE_SIZE * t, SPRITE_HOTSPOT * t, '1 1 1', a, DRAWFLAG_MIPMAP);
271
272         if(self.build_finished)
273         {
274                 if(time < self.build_finished + 0.25)
275                 {
276                         if(time < self.build_started)
277                                 self.health = self.build_starthealth;
278                         else if(time < self.build_finished)
279                                 self.health = (time - self.build_started) / (self.build_finished - self.build_started) * (1 - self.build_starthealth) + self.build_starthealth;
280                         else
281                                 self.health = 1;
282                 }
283                 else
284                         self.health = -1;
285         }
286
287         if(self.health >= 0)
288         {
289                 float align;
290                 if(self.build_finished)
291                         align = 0.5;
292                 else
293                         align = 0;
294                 drawhealthbar(o, rot * 90 * DEG2RAD, self.health, SPRITE_SIZE * t, SPRITE_HOTSPOT * t, SPRITE_HEALTHBAR_WIDTH * t, SPRITE_HEALTHBAR_HEIGHT * t, SPRITE_HEALTHBAR_MARGIN * t, SPRITE_HEALTHBAR_BORDER * t, align, self.teamradar_color, a * SPRITE_HEALTHBAR_BORDERALPHA, self.teamradar_color, a * SPRITE_HEALTHBAR_HEALTHALPHA, DRAWFLAG_NORMAL);
295         }
296 }
297
298 void Ent_RemoveWaypointSprite()
299 {
300         if(self.netname)
301                 strunzone(self.netname);
302         if(self.netname2)
303                 strunzone(self.netname2);
304         if(self.netname3)
305                 strunzone(self.netname3);
306 }
307
308 void Ent_WaypointSprite()
309 {
310         float sendflags, f, t;
311         sendflags = ReadByte();
312
313         if(!self.spawntime)
314                 self.spawntime = time;
315
316         self.draw2d = Draw_WaypointSprite;
317
318         InterpolateOrigin_Undo();
319
320         if(sendflags & 0x80)
321         {
322                 t = ReadByte();
323                 if(t < 192)
324                 {
325                         self.health = t / 191.0;
326                         self.build_finished = 0;
327                 }
328                 else
329                 {
330                         t = (t - 192) * 256 + ReadByte();
331                         self.build_started = servertime;
332                         if(self.build_finished)
333                                 self.build_starthealth = bound(0, self.health, 1);
334                         else
335                                 self.build_starthealth = 0;
336                         self.build_finished = servertime + t / 32;
337                         //print("build: ", ftos(self.build_finished - self.build_started), "\n");
338                 }
339         }
340         else
341         {
342                 self.health = -1;
343                 self.build_finished = 0;
344         }
345
346         if(sendflags & 64)
347         {
348                 // unfortunately, this needs to be exact (for the 3D display)
349                 self.origin_x = ReadCoord();
350                 self.origin_y = ReadCoord();
351                 self.origin_z = ReadCoord();
352         }
353
354         if(sendflags & 1)
355         {
356                 self.team = ReadByte();
357                 self.rule = ReadByte();
358         }
359
360         if(sendflags & 2)
361         {
362                 if(self.netname)
363                         strunzone(self.netname);
364                 self.netname = strzone(ReadString());
365         }
366
367         if(sendflags & 4)
368         {
369                 if(self.netname2)
370                         strunzone(self.netname2);
371                 self.netname2 = strzone(ReadString());
372         }
373
374         if(sendflags & 8)
375         {
376                 if(self.netname3)
377                         strunzone(self.netname3);
378                 self.netname3 = strzone(ReadString());
379         }
380
381         if(sendflags & 16)
382         {
383                 self.lifetime = ReadCoord();
384                 self.fadetime = ReadCoord();
385                 self.maxdistance = ReadShort();
386                 self.hideflags = ReadByte();
387         }
388
389         if(sendflags & 32)
390         {
391                 f = ReadByte();
392                 self.teamradar_icon = (f & 0x7F);
393                 if(f & 0x80)
394                 {
395                         self.(teamradar_times[self.teamradar_time_index]) = time;
396                         self.teamradar_time_index = mod(self.teamradar_time_index + 1, MAX_TEAMRADAR_TIMES);
397                 }
398                 self.teamradar_color_x = ReadByte() / 255.0;
399                 self.teamradar_color_y = ReadByte() / 255.0;
400                 self.teamradar_color_z = ReadByte() / 255.0;
401         }
402
403         InterpolateOrigin_Note();
404
405         self.entremove = Ent_RemoveWaypointSprite;
406 }
407
408 void WaypointSprite_Load()
409 {
410         waypointsprite_fadedistance = vlen(mi_max - mi_min);
411         waypointsprite_normdistance = cvar("g_waypointsprite_normdistance");
412         waypointsprite_minscale = cvar("g_waypointsprite_minscale");
413         waypointsprite_minalpha = cvar("g_waypointsprite_minalpha");
414         waypointsprite_distancealphaexponent = cvar("g_waypointsprite_distancealphaexponent");
415         waypointsprite_timealphaexponent = cvar("g_waypointsprite_timealphaexponent");
416         waypointsprite_scale = cvar_or("g_waypointsprite_scale", 1) * (1 - cvar("_menu_alpha"));
417         waypointsprite_edgefadealpha = cvar_or("g_waypointsprite_edgefadealpha", 1);
418         waypointsprite_edgefadescale = cvar_or("g_waypointsprite_edgefadescale", 1);
419         waypointsprite_edgefadedistance = cvar("g_waypointsprite_edgefadedistance");
420         waypointsprite_crosshairfadealpha = cvar_or("g_waypointsprite_crosshairfadealpha", 1);
421         waypointsprite_crosshairfadescale = cvar_or("g_waypointsprite_crosshairfadescale", 1);
422         waypointsprite_crosshairfadedistance = cvar("g_waypointsprite_crosshairfadedistance");
423         waypointsprite_distancefadealpha = cvar_or("g_waypointsprite_distancefadealpha", 1);
424         waypointsprite_distancefadescale = cvar_or("g_waypointsprite_distancefadescale", 1);
425         waypointsprite_distancefadedistance = vlen(mi_max - mi_min) * cvar_or("g_waypointsprite_distancefadedistancemultiplier", 1);
426
427         if(!waypointsprite_initialized)
428         {
429                 float dh, n, i, o, f;
430                 string s, sname, sframes;
431                 dh = search_begin("models/sprites/*_frame*.tga", FALSE, FALSE);
432                 n = search_getsize(dh);
433                 for(i = 0; i < n; ++i)
434                 {
435                         s = search_getfilename(dh, i);
436                         if(substring(s, 0, 15) != "models/sprites/")
437                                 continue;
438                         if(substring(s, strlen(s) - 4, 4) != ".tga")
439                                 continue;
440                         s = substring(s, 15, strlen(s) - 19);
441
442                         o = strstrofs(s, "_frame", 0);
443                         sname = strcat("/spriteframes/", substring(s, 0, o));
444                         sframes = substring(s, o + 6, strlen(s) - o - 6);
445                         f = stof(sframes) + 1;
446                         db_put(tempdb, sname, ftos(max(f, stof(db_get(tempdb, sname)))));
447                 }
448                 search_end(dh);
449         }
450         waypointsprite_initialized = 1;
451 }