sprites in xscale
[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 = '256 32 0';
22 vector SPRITE_HOTSPOT = '128 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                 /*
136                 d_x = view_right * (self.origin - view_origin) * vid_conwidth / vid_width;
137                 d_y = -view_up * (self.origin - view_origin) * vid_conheight / (vid_height * vid_pixelheight);
138                 d_z = 0;
139                 */
140                 
141                 d = o - '0.5 0 0' * vid_conwidth - '0 0.5 0' * vid_conheight;
142
143                 if(cvar("v_flipped"))
144                         d_x = -d_x;
145
146                 f1 = d_x / vid_conwidth;
147                 f2 = d_y / vid_conheight;
148
149                 if(max(f1, -f1) > max(f2, -f2))
150                 {
151                         if(f1 > 0)
152                         {
153                                 // RIGHT edge
154                                 d = d * (0.5 / f1);
155                                 rot = 3;
156                         }
157                         else
158                         {
159                                 // LEFT edge
160                                 d = d * (-0.5 / f1);
161                                 rot = 1;
162                         }
163                 }
164                 else
165                 {
166                         if(f2 > 0)
167                         {
168                                 // BOTTOM edge
169                                 d = d * (0.5 / f2);
170                                 rot = 0;
171                         }
172                         else
173                         {
174                                 // TOP edge
175                                 d = d * (-0.5 / f2);
176                                 rot = 2;
177                         }
178                 }
179
180                 o = d + '0.5 0 0' * vid_conwidth + '0 0.5 0' * vid_conheight;
181         }
182         o_z = 0;
183
184         float vidscale;
185         vidscale = max(vid_conwidth / vid_width, vid_conheight / vid_height);
186
187         t = stof(db_get(tempdb, strcat("/spriteframes/", spriteimage)));
188         if(t == 0)
189                 spriteimage = strcat("models/sprites/", spriteimage);
190         else
191                 spriteimage = strcat("models/sprites/", spriteimage, "_frame", ftos(mod(floor((max(0, time - self.spawntime)) * 2), t)));
192
193         drawrotpic(o, rot * 90 * DEG2RAD, spriteimage, SPRITE_SIZE * waypointsprite_scale * vidscale, SPRITE_HOTSPOT * waypointsprite_scale * vidscale, '1 1 1', a, DRAWFLAG_MIPMAP);
194 }
195
196 void Ent_RemoveWaypointSprite()
197 {
198         if(self.netname)
199                 strunzone(self.netname);
200         if(self.netname2)
201                 strunzone(self.netname2);
202         if(self.netname3)
203                 strunzone(self.netname3);
204 }
205
206 void Ent_WaypointSprite()
207 {
208         float sendflags, f;
209         sendflags = ReadByte();
210
211         if(!self.spawntime)
212                 self.spawntime = time;
213
214         self.draw2d = Draw_WaypointSprite;
215
216         InterpolateOrigin_Undo();
217
218         if(sendflags & 64)
219         {
220                 // unfortunately, this needs to be exact (for the 3D display)
221                 self.origin_x = ReadCoord();
222                 self.origin_y = ReadCoord();
223                 self.origin_z = ReadCoord();
224         }
225
226         if(sendflags & 1)
227         {
228                 self.team = ReadByte();
229                 self.rule = ReadByte();
230         }
231
232         if(sendflags & 2)
233         {
234                 if(self.netname)
235                         strunzone(self.netname);
236                 self.netname = strzone(ReadString());
237         }
238
239         if(sendflags & 4)
240         {
241                 if(self.netname2)
242                         strunzone(self.netname2);
243                 self.netname2 = strzone(ReadString());
244         }
245
246         if(sendflags & 8)
247         {
248                 if(self.netname3)
249                         strunzone(self.netname3);
250                 self.netname3 = strzone(ReadString());
251         }
252
253         if(sendflags & 16)
254         {
255                 self.lifetime = ReadCoord();
256                 self.fadetime = ReadCoord();
257                 self.maxdistance = ReadShort();
258                 self.hideflags = ReadByte();
259         }
260
261         if(sendflags & 32)
262         {
263                 f = ReadByte();
264                 self.teamradar_icon = (f & 0x7F);
265                 if(f & 0x80)
266                 {
267                         self.(teamradar_times[self.teamradar_time_index]) = time;
268                         self.teamradar_time_index = mod(self.teamradar_time_index + 1, MAX_TEAMRADAR_TIMES);
269                 }
270                 self.teamradar_color_x = ReadByte() / 255.0;
271                 self.teamradar_color_y = ReadByte() / 255.0;
272                 self.teamradar_color_z = ReadByte() / 255.0;
273         }
274
275         InterpolateOrigin_Note();
276
277         self.entremove = Ent_RemoveWaypointSprite;
278 }
279
280 void WaypointSprite_Load()
281 {
282         waypointsprite_fadedistance = vlen(world.maxs - world.mins);
283         waypointsprite_normdistance = cvar("g_waypointsprite_normdistance");
284         waypointsprite_minscale = cvar("g_waypointsprite_minscale");
285         waypointsprite_minalpha = cvar("g_waypointsprite_minalpha");
286         waypointsprite_distancealphaexponent = cvar("g_waypointsprite_distancealphaexponent");
287         waypointsprite_timealphaexponent = cvar("g_waypointsprite_timealphaexponent");
288         waypointsprite_scale = cvar("g_waypointsprite_scale");
289         if(!waypointsprite_scale)
290                 waypointsprite_scale = 1.0;
291
292         if(!waypointsprite_initialized)
293         {
294                 float dh, n, i, o, f;
295                 string s, sname, sframes;
296                 dh = search_begin("models/sprites/*_frame*.tga", FALSE, FALSE);
297                 n = search_getsize(dh);
298                 for(i = 0; i < n; ++i)
299                 {
300                         s = search_getfilename(dh, i);
301                         if(substring(s, 0, 15) != "models/sprites/")
302                                 continue;
303                         if(substring(s, strlen(s) - 4, 4) != ".tga")
304                                 continue;
305                         s = substring(s, 15, strlen(s) - 19);
306
307                         o = strstrofs(s, "_frame", 0);
308                         sname = strcat("/spriteframes/", substring(s, 0, o));
309                         sframes = substring(s, o + 6, strlen(s) - o - 6);
310                         f = stof(sframes) + 1;
311                         db_put(tempdb, sname, ftos(max(f, stof(db_get(tempdb, sname)))));
312                 }
313                 search_end(dh);
314         }
315         waypointsprite_initialized = 1;
316 }