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