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