don't ask me why - put the condition back. maybe a temporary engien bug?
[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
21 vector SPRITE_SIZE = '128 32 0';
22 vector SPRITE_HOTSPOT = '64 32 0';
23
24 void drawrotpic(vector org, float rot, string pic, vector sz, vector hotspot, vector rgb, float a, float f)
25 {
26         vector v1, v2, v3, v4;
27
28         hotspot = -1 * hotspot;
29
30         // hotspot-relative coordinates of the corners
31         v1 = hotspot;
32         v2 = hotspot + '1 0 0' * sz_x;
33         v3 = hotspot + '1 0 0' * sz_x + '0 1 0' * sz_y;
34         v4 = hotspot                  + '0 1 0' * sz_y;
35
36         // rotate them, and make them absolute
37         rot = -rot; // rotate by the opposite angle, as our coordinate system is reversed
38         v1 = rotate(v1, rot) + org;
39         v2 = rotate(v2, rot) + org;
40         v3 = rotate(v3, rot) + org;
41         v4 = rotate(v4, rot) + org;
42
43         // draw them
44         R_BeginPolygon(pic, f);
45         R_PolygonVertex(v1, '0 0 0', rgb, a);
46         R_PolygonVertex(v2, '1 0 0', rgb, a);
47         R_PolygonVertex(v3, '1 1 0', rgb, a);
48         R_PolygonVertex(v4, '0 1 0', rgb, a);
49         R_EndPolygon();
50 }
51
52 void Draw_WaypointSprite()
53 {
54         string spriteimage;
55         float t;
56
57         if(self.lifetime)
58                 self.alpha = pow(bound(0, (self.fadetime - time) / self.lifetime, 1), waypointsprite_timealphaexponent);
59         else
60                 self.alpha = 1;
61
62         if(self.hideflags & 2)
63                 return; // radar only
64
65         if(cvar("cl_hidewaypoints") >= 2)
66                 return;
67
68         if(self.hideflags & 1)
69                 if(cvar("cl_hidewaypoints"))
70                         return; // fixed waypoint
71
72         InterpolateOrigin_Do();
73
74         t = GetPlayerColor(player_localentnum - 1) + 1;
75
76         spriteimage = "";
77
78         // choose the sprite
79         switch(self.rule)
80         {
81                 case SPRITERULE_DEFAULT:
82                         if(self.team)
83                         {
84                                 if(self.team == t)
85                                         spriteimage = self.netname;
86                                 else
87                                         spriteimage = "";
88                         }
89                         else
90                                 spriteimage = self.netname;
91                         break;
92                 case SPRITERULE_TEAMPLAY:
93                         if(t == COLOR_SPECTATOR + 1)
94                                 spriteimage = self.netname3;
95                         else if(self.team == t)
96                                 spriteimage = self.netname2;
97                         else
98                                 spriteimage = self.netname;
99                         break;
100                 default:
101                         error("Invalid waypointsprite rule!");
102                         break;
103         }
104
105         if(spriteimage == "")
106                 return;
107         
108         float dist;
109         dist = vlen(self.origin - view_origin);
110         
111         float a;
112         a = self.alpha;
113
114         if(self.maxdistance > waypointsprite_normdistance)
115                 a *= pow(bound(0, (self.maxdistance - dist) / (self.maxdistance - waypointsprite_normdistance), 1), waypointsprite_distancealphaexponent);
116         else if(self.maxdistance > 0)
117                 a *= pow(bound(0, (waypointsprite_fadedistance - dist) / (waypointsprite_fadedistance - waypointsprite_normdistance), 1), waypointsprite_distancealphaexponent) * (1 - waypointsprite_minalpha) + waypointsprite_minalpha;
118
119         if(a <= 0)
120                 return;
121         
122         // draw the sprite image
123         vector o;
124         float rot;
125         o = project_3d_to_2d(self.origin);
126         rot = 0;
127
128         if(o_z < 0 || o_x < 0 || o_y < 0 || o_x > vid_conwidth || o_y > vid_conheight)
129         {
130                 // scale it to be just in view
131                 vector d;
132                 float f1, f2;
133
134                 // get the waypoint angle vector
135                 d_x = view_right * (self.origin - view_origin) * vid_conwidth / vid_width;
136                 d_y = -view_up * (self.origin - view_origin) * vid_conheight / (vid_height * vid_pixelheight);
137                 d_z = 0;
138                 
139                 //d = o - '0.5 0 0' * vid_conwidth - '0 0.5 0' * vid_conheight;
140
141                 if(cvar("v_flipped"))
142                         d_x = -d_x;
143
144                 f1 = d_x / vid_conwidth;
145                 f2 = d_y / vid_conheight;
146
147                 if(max(f1, -f1) > max(f2, -f2))
148                 {
149                         if(f1 > 0)
150                         {
151                                 // RIGHT edge
152                                 d = d * (0.5 / f1);
153                                 rot = 3;
154                         }
155                         else
156                         {
157                                 // LEFT edge
158                                 d = d * (-0.5 / f1);
159                                 rot = 1;
160                         }
161                 }
162                 else
163                 {
164                         if(f2 > 0)
165                         {
166                                 // BOTTOM edge
167                                 d = d * (0.5 / f2);
168                                 rot = 0;
169                         }
170                         else
171                         {
172                                 // TOP edge
173                                 d = d * (-0.5 / f2);
174                                 rot = 2;
175                         }
176                 }
177
178                 o = d + '0.5 0 0' * vid_conwidth + '0 0.5 0' * vid_conheight;
179         }
180         o_z = 0;
181
182         float vidscale;
183         vidscale = max(vid_conwidth / vid_width, vid_conheight / vid_height);
184
185         t = stof(db_get(tempdb, strcat("/spriteframes/", spriteimage)));
186         if(t == 0)
187                 spriteimage = strcat("models/sprites/", spriteimage);
188         else
189                 spriteimage = strcat("models/sprites/", spriteimage, "_frame", ftos(mod(floor((max(0, time - self.spawntime)) * 2), t)));
190
191         drawrotpic(o, rot * 90 * DEG2RAD, spriteimage, SPRITE_SIZE * waypointsprite_scale * vidscale, SPRITE_HOTSPOT * waypointsprite_scale * vidscale, '1 1 1', a, DRAWFLAG_MIPMAP);
192 }
193
194 void Ent_RemoveWaypointSprite()
195 {
196         if(self.netname)
197                 strunzone(self.netname);
198         if(self.netname2)
199                 strunzone(self.netname2);
200         if(self.netname3)
201                 strunzone(self.netname3);
202 }
203
204 void Ent_WaypointSprite()
205 {
206         float sendflags, f;
207         sendflags = ReadByte();
208
209         if(!self.spawntime)
210                 self.spawntime = time;
211
212         self.draw2d = Draw_WaypointSprite;
213
214         InterpolateOrigin_Undo();
215
216         if(sendflags & 64)
217         {
218                 // unfortunately, this needs to be exact (for the 3D display)
219                 self.origin_x = ReadCoord();
220                 self.origin_y = ReadCoord();
221                 self.origin_z = ReadCoord();
222         }
223
224         if(sendflags & 1)
225         {
226                 self.team = ReadByte();
227                 self.rule = ReadByte();
228         }
229
230         if(sendflags & 2)
231         {
232                 if(self.netname)
233                         strunzone(self.netname);
234                 self.netname = strzone(ReadString());
235         }
236
237         if(sendflags & 4)
238         {
239                 if(self.netname2)
240                         strunzone(self.netname2);
241                 self.netname2 = strzone(ReadString());
242         }
243
244         if(sendflags & 8)
245         {
246                 if(self.netname3)
247                         strunzone(self.netname3);
248                 self.netname3 = strzone(ReadString());
249         }
250
251         if(sendflags & 16)
252         {
253                 self.lifetime = ReadCoord();
254                 self.fadetime = ReadCoord();
255                 self.maxdistance = ReadShort();
256                 self.hideflags = ReadByte();
257         }
258
259         if(sendflags & 32)
260         {
261                 f = ReadByte();
262                 self.teamradar_icon = (f & 0x7F);
263                 if(f & 0x80)
264                 {
265                         self.(teamradar_times[self.teamradar_time_index]) = time;
266                         self.teamradar_time_index = mod(self.teamradar_time_index + 1, MAX_TEAMRADAR_TIMES);
267                 }
268                 self.teamradar_color_x = ReadByte() / 255.0;
269                 self.teamradar_color_y = ReadByte() / 255.0;
270                 self.teamradar_color_z = ReadByte() / 255.0;
271         }
272
273         InterpolateOrigin_Note();
274
275         self.entremove = Ent_RemoveWaypointSprite;
276 }
277
278 void WaypointSprite_Load()
279 {
280         waypointsprite_fadedistance = vlen(world.maxs - world.mins);
281         waypointsprite_normdistance = cvar("g_waypointsprite_normdistance");
282         waypointsprite_minscale = cvar("g_waypointsprite_minscale");
283         waypointsprite_minalpha = cvar("g_waypointsprite_minalpha");
284         waypointsprite_distancealphaexponent = cvar("g_waypointsprite_distancealphaexponent");
285         waypointsprite_timealphaexponent = cvar("g_waypointsprite_timealphaexponent");
286         waypointsprite_scale = cvar("g_waypointsprite_scale");
287         if(!waypointsprite_scale)
288                 waypointsprite_scale = 1.0;
289
290         if(!waypointsprite_initialized)
291         {
292                 float dh, n, i, o, f;
293                 string s, sname, sframes;
294                 dh = search_begin("models/sprites/*_frame*.tga", FALSE, FALSE);
295                 n = search_getsize(dh);
296                 for(i = 0; i < n; ++i)
297                 {
298                         s = search_getfilename(dh, i);
299                         if(substring(s, 0, 15) != "models/sprites/")
300                                 continue;
301                         if(substring(s, strlen(s) - 4, 4) != ".tga")
302                                 continue;
303                         s = substring(s, 15, strlen(s) - 19);
304
305                         o = strstrofs(s, "_frame", 0);
306                         sname = strcat("/spriteframes/", substring(s, 0, o));
307                         sframes = substring(s, o + 6, strlen(s) - o - 6);
308                         f = stof(sframes) + 1;
309                         db_put(tempdb, sname, ftos(max(f, stof(db_get(tempdb, sname)))));
310                 }
311                 search_end(dh);
312         }
313         waypointsprite_initialized = 1;
314 }