]> icculus.org git repositories - divverent/nexuiz.git/blob - data/qcsrc/client/waypointsprites.qc
r7877 | div0 | 2009-09-23 06:21:50 -0400 (Wed, 23 Sep 2009) | 2 lines
[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
10 .float rule;
11 .string netname; // primary picture
12 .string netname2; // secondary picture
13 .string netname3; // tertiary picture
14 .float team; // team that gets netname2
15 .float lifetime;
16 .float fadetime;
17 .float maxdistance;
18 .float hideflags;
19 .float spawntime;
20 .float health;
21 .float build_started;
22 .float build_starthealth;
23 .float build_finished;
24
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;
33
34 void drawrotpic(vector org, float rot, string pic, vector sz, vector hotspot, vector rgb, float a, float f)
35 {
36         vector v1, v2, v3, v4;
37
38         hotspot = -1 * hotspot;
39
40         // hotspot-relative coordinates of the corners
41         v1 = hotspot;
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;
45
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;
52
53         // draw them
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);
59         R_EndPolygon();
60 }
61
62 void drawquad(vector o, vector ri, vector up, string pic, vector rgb, float a, float f)
63 {
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);
69         R_EndPolygon();
70 }
71
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)
73 {
74         vector o, ri, up;
75         float owidth; // outer width
76
77         hotspot = -1 * hotspot;
78
79         // hotspot-relative coordinates of the healthbar corners
80         o = hotspot;
81         ri = '1 0 0';
82         up = '0 1 0';
83         
84         rot = -rot; // rotate by the opposite angle, as our coordinate system is reversed
85         o = rotate(o, rot) + org;
86         ri = rotate(ri, rot);
87         up = rotate(up, rot);
88
89         owidth = width + 2 * border;
90         o = o - up * (margin + border + height) + ri * (sz_x - owidth) * 0.5;
91
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);
97 }
98
99 void Draw_WaypointSprite()
100 {
101         string spriteimage;
102         float t;
103
104         if(self.lifetime)
105                 self.alpha = pow(bound(0, (self.fadetime - time) / self.lifetime, 1), waypointsprite_timealphaexponent);
106         else
107                 self.alpha = 1;
108
109         if(self.hideflags & 2)
110                 return; // radar only
111
112         if(cvar("cl_hidewaypoints") >= 2)
113                 return;
114         
115         if(cvar("r_letterbox") == 1)
116                 return;
117
118         if(self.hideflags & 1)
119                 if(cvar("cl_hidewaypoints"))
120                         return; // fixed waypoint
121
122         InterpolateOrigin_Do();
123
124         t = GetPlayerColor(player_localentnum - 1) + 1;
125
126         spriteimage = "";
127
128         // choose the sprite
129         switch(self.rule)
130         {
131                 case SPRITERULE_DEFAULT:
132                         if(self.team)
133                         {
134                                 if(self.team == t)
135                                         spriteimage = self.netname;
136                                 else
137                                         spriteimage = "";
138                         }
139                         else
140                                 spriteimage = self.netname;
141                         break;
142                 case SPRITERULE_TEAMPLAY:
143                         if(t == COLOR_SPECTATOR + 1)
144                                 spriteimage = self.netname3;
145                         else if(self.team == t)
146                                 spriteimage = self.netname2;
147                         else
148                                 spriteimage = self.netname;
149                         break;
150                 default:
151                         error("Invalid waypointsprite rule!");
152                         break;
153         }
154
155         if(spriteimage == "")
156                 return;
157         
158         float dist;
159         dist = vlen(self.origin - view_origin);
160         
161         float a;
162         a = self.alpha * sbar_alpha_fg;
163
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;
168
169         if(a <= 0)
170                 return;
171         
172         // draw the sprite image
173         vector o;
174         float rot;
175         o = project_3d_to_2d(self.origin);
176         rot = 0;
177
178         if(o_z < 0 || o_x < 0 || o_y < 0 || o_x > vid_conwidth || o_y > vid_conheight)
179         {
180                 // scale it to be just in view
181                 vector d;
182                 float f1, f2;
183
184                 // get the waypoint angle vector
185                 /*
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);
188                 d_z = 0;
189                 */
190                 
191                 d = o - '0.5 0 0' * vid_conwidth - '0 0.5 0' * vid_conheight;
192
193                 /*
194                 if(cvar("v_flipped"))
195                         d_x = -d_x;
196                 */
197
198                 f1 = d_x / vid_conwidth;
199                 f2 = d_y / vid_conheight;
200
201                 if(max(f1, -f1) > max(f2, -f2))
202                 {
203                         if(d_z * f1 > 0)
204                         {
205                                 // RIGHT edge
206                                 d = d * (0.5 / f1);
207                                 rot = 3;
208                         }
209                         else
210                         {
211                                 // LEFT edge
212                                 d = d * (-0.5 / f1);
213                                 rot = 1;
214                         }
215                 }
216                 else
217                 {
218                         if(d_z * f2 > 0)
219                         {
220                                 // BOTTOM edge
221                                 d = d * (0.5 / f2);
222                                 rot = 0;
223                         }
224                         else
225                         {
226                                 // TOP edge
227                                 d = d * (-0.5 / f2);
228                                 rot = 2;
229                         }
230                 }
231
232                 o = d + '0.5 0 0' * vid_conwidth + '0 0.5 0' * vid_conheight;
233         }
234         o_z = 0;
235
236         float vidscale;
237         vidscale = max(vid_conwidth / vid_width, vid_conheight / vid_height);
238
239         t = stof(db_get(tempdb, strcat("/spriteframes/", spriteimage)));
240         if(t == 0)
241                 spriteimage = strcat("models/sprites/", spriteimage);
242         else
243                 spriteimage = strcat("models/sprites/", spriteimage, "_frame", ftos(mod(floor((max(0, time - self.spawntime)) * 2), t)));
244
245         drawrotpic(o, rot * 90 * DEG2RAD, spriteimage, SPRITE_SIZE * waypointsprite_scale * vidscale, SPRITE_HOTSPOT * waypointsprite_scale * vidscale, '1 1 1', a, DRAWFLAG_MIPMAP);
246
247         if(self.build_finished)
248         {
249                 if(time < self.build_finished + 0.25)
250                 {
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;
255                         else
256                                 self.health = 1;
257                 }
258                 else
259                         self.health = -1;
260         }
261
262         if(self.health >= 0)
263         {
264                 float align;
265                 if(self.build_finished)
266                         align = 0.5;
267                 else
268                         align = 0;
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);
270         }
271 }
272
273 void Ent_RemoveWaypointSprite()
274 {
275         if(self.netname)
276                 strunzone(self.netname);
277         if(self.netname2)
278                 strunzone(self.netname2);
279         if(self.netname3)
280                 strunzone(self.netname3);
281 }
282
283 void Ent_WaypointSprite()
284 {
285         float sendflags, f, t;
286         sendflags = ReadByte();
287
288         if(!self.spawntime)
289                 self.spawntime = time;
290
291         self.draw2d = Draw_WaypointSprite;
292
293         InterpolateOrigin_Undo();
294
295         if(sendflags & 0x80)
296         {
297                 t = ReadByte();
298                 if(t < 192)
299                 {
300                         self.health = t / 191.0;
301                         self.build_finished = 0;
302                 }
303                 else
304                 {
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);
309                         else
310                                 self.build_starthealth = 0;
311                         self.build_finished = servertime + t / 32;
312                         //print("build: ", ftos(self.build_finished - self.build_started), "\n");
313                 }
314         }
315         else
316         {
317                 self.health = -1;
318                 self.build_finished = 0;
319         }
320
321         if(sendflags & 64)
322         {
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();
327         }
328
329         if(sendflags & 1)
330         {
331                 self.team = ReadByte();
332                 self.rule = ReadByte();
333         }
334
335         if(sendflags & 2)
336         {
337                 if(self.netname)
338                         strunzone(self.netname);
339                 self.netname = strzone(ReadString());
340         }
341
342         if(sendflags & 4)
343         {
344                 if(self.netname2)
345                         strunzone(self.netname2);
346                 self.netname2 = strzone(ReadString());
347         }
348
349         if(sendflags & 8)
350         {
351                 if(self.netname3)
352                         strunzone(self.netname3);
353                 self.netname3 = strzone(ReadString());
354         }
355
356         if(sendflags & 16)
357         {
358                 self.lifetime = ReadCoord();
359                 self.fadetime = ReadCoord();
360                 self.maxdistance = ReadShort();
361                 self.hideflags = ReadByte();
362         }
363
364         if(sendflags & 32)
365         {
366                 f = ReadByte();
367                 self.teamradar_icon = (f & 0x7F);
368                 if(f & 0x80)
369                 {
370                         self.(teamradar_times[self.teamradar_time_index]) = time;
371                         self.teamradar_time_index = mod(self.teamradar_time_index + 1, MAX_TEAMRADAR_TIMES);
372                 }
373                 self.teamradar_color_x = ReadByte() / 255.0;
374                 self.teamradar_color_y = ReadByte() / 255.0;
375                 self.teamradar_color_z = ReadByte() / 255.0;
376         }
377
378         InterpolateOrigin_Note();
379
380         self.entremove = Ent_RemoveWaypointSprite;
381 }
382
383 void WaypointSprite_Load()
384 {
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"));
394
395         if(!waypointsprite_initialized)
396         {
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)
402                 {
403                         s = search_getfilename(dh, i);
404                         if(substring(s, 0, 15) != "models/sprites/")
405                                 continue;
406                         if(substring(s, strlen(s) - 4, 4) != ".tga")
407                                 continue;
408                         s = substring(s, 15, strlen(s) - 19);
409
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)))));
415                 }
416                 search_end(dh);
417         }
418         waypointsprite_initialized = 1;
419 }