]> icculus.org git repositories - divverent/nexuiz.git/blob - data/qcsrc/client/waypointsprites.qc
use DRAWFLAG_SCREEN for team radar now (warning: breaks on old engines that are after...
[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_fadedistance;
15 float waypointsprite_normdistance;
16 float waypointsprite_minscale;
17 float waypointsprite_minalpha;
18 float waypointsprite_distancealphaexponent;
19 float waypointsprite_timealphaexponent;
20 float waypointsprite_scale;
21
22 .float rule;
23 .string netname; // primary picture
24 .string netname2; // secondary picture
25 .string netname3; // tertiary picture
26 .float team; // team that gets netname2
27 .float lifetime;
28 .float fadetime;
29 .float maxdistance;
30 .float hideflags;
31
32 vector SPRITE_SIZE = '128 32 0';
33 vector SPRITE_HOTSPOT = '64 32 0';
34
35 void drawrotpic(vector org, float rot, string pic, vector sz, vector hotspot, vector rgb, float a, float f)
36 {
37         vector v1, v2, v3, v4;
38
39         hotspot = -1 * hotspot;
40
41         // hotspot-relative coordinates of the corners
42         v1 = hotspot;
43         v2 = hotspot + '1 0 0' * sz_x;
44         v3 = hotspot + '1 0 0' * sz_x + '0 1 0' * sz_y;
45         v4 = hotspot                  + '0 1 0' * sz_y;
46
47         // rotate them, and make them absolute
48         rot = -rot; // rotate by the opposite angle, as our coordinate system is reversed
49         v1 = rotate(v1, rot) + org;
50         v2 = rotate(v2, rot) + org;
51         v3 = rotate(v3, rot) + org;
52         v4 = rotate(v4, rot) + org;
53
54         // draw them
55         R_BeginPolygon(pic, f);
56         R_PolygonVertex(v1, '0 0 0', rgb, a);
57         R_PolygonVertex(v2, '1 0 0', rgb, a);
58         R_PolygonVertex(v3, '1 1 0', rgb, a);
59         R_PolygonVertex(v4, '0 1 0', rgb, a);
60         R_EndPolygon();
61 }
62
63 void Draw_WaypointSprite()
64 {
65         string spriteimage;
66         float t;
67
68         if(self.lifetime)
69                 self.alpha = pow(bound(0, (self.fadetime - time) / self.lifetime, 1), waypointsprite_timealphaexponent);
70         else
71                 self.alpha = 1;
72
73         if(self.hideflags & 2)
74                 return; // radar only
75
76         if(cvar("cl_hidewaypoints") >= 2)
77                 return;
78
79         if(self.hideflags & 1)
80                 if(cvar("cl_hidewaypoints"))
81                         return; // fixed waypoint
82
83         InterpolateOrigin_Do();
84
85         t = GetPlayerColor(player_localentnum - 1) + 1;
86
87         spriteimage = "";
88
89         // choose the sprite
90         switch(self.rule)
91         {
92                 case SPRITERULE_DEFAULT:
93                         if(self.team)
94                         {
95                                 if(self.team == t)
96                                         spriteimage = self.netname;
97                                 else
98                                         spriteimage = "";
99                         }
100                         else
101                                 spriteimage = self.netname;
102                         break;
103                 case SPRITERULE_TEAMPLAY:
104                         if(self.team == t)
105                                 spriteimage = self.netname2;
106                         else
107                                 spriteimage = self.netname;
108                         break;
109                 default:
110                         error("Invalid waypointsprite rule!");
111                         break;
112         }
113
114         if(spriteimage == "")
115                 return;
116         
117         float dist;
118         dist = vlen(self.origin - view_origin);
119         
120         float a;
121         a = self.alpha;
122
123         if(self.maxdistance > waypointsprite_normdistance)
124                 a *= pow(bound(0, (self.maxdistance - dist) / (self.maxdistance - waypointsprite_normdistance), 1), waypointsprite_distancealphaexponent);
125         else if(self.maxdistance > 0)
126                 a *= pow(bound(0, (waypointsprite_fadedistance - dist) / (waypointsprite_fadedistance - waypointsprite_normdistance), 1), waypointsprite_distancealphaexponent) * (1 - waypointsprite_minalpha) + waypointsprite_minalpha;
127
128         if(a <= 0)
129                 return;
130         
131         // draw the sprite image
132         vector o;
133         float rot;
134         o = project_3d_to_2d(self.origin);
135         rot = 0;
136
137         if(o_z < 0 || o_x < 0 || o_y < 0 || o_x > vid_conwidth || o_y > vid_conheight)
138         {
139                 // scale it to be just in view
140                 vector d;
141                 float f1, f2;
142                 d = o - '0.5 0 0' * vid_conwidth - '0 0.5 0' * vid_conheight;
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         drawrotpic(o, rot * 90 * DEG2RAD, strcat("models/sprites/", spriteimage), SPRITE_SIZE * waypointsprite_scale * vidscale, SPRITE_HOTSPOT * waypointsprite_scale * vidscale, '1 1 1', a, 0);
185 }
186
187 void Ent_WaypointSprite()
188 {
189         float sendflags, f;
190         sendflags = ReadByte();
191
192         self.draw2d = Draw_WaypointSprite;
193
194         InterpolateOrigin_Undo();
195
196         // unfortunately, this needs to be exact (for the 3D display)
197         self.origin_x = ReadCoord();
198         self.origin_y = ReadCoord();
199         self.origin_z = ReadCoord();
200
201         if(sendflags & 1)
202         {
203                 self.team = ReadByte();
204                 self.rule = ReadByte();
205         }
206
207         if(sendflags & 2)
208         {
209                 if(self.netname)
210                         strunzone(self.netname);
211                 self.netname = strzone(ReadString());
212         }
213
214         if(sendflags & 4)
215         {
216                 if(self.netname2)
217                         strunzone(self.netname2);
218                 self.netname2 = strzone(ReadString());
219         }
220
221         if(sendflags & 8)
222         {
223                 if(self.netname3)
224                         strunzone(self.netname3);
225                 self.netname3 = strzone(ReadString());
226         }
227
228         if(sendflags & 16)
229         {
230                 self.lifetime = ReadCoord();
231                 self.fadetime = ReadCoord();
232                 self.maxdistance = ReadShort();
233                 self.hideflags = ReadByte();
234         }
235
236         if(sendflags & 32)
237         {
238                 f = ReadByte();
239                 self.teamradar_icon = (f & 0x7F);
240                 if(f & 0x80)
241                         self.teamradar_time = time;
242                 self.teamradar_color_x = ReadByte() / 255.0;
243                 self.teamradar_color_y = ReadByte() / 255.0;
244                 self.teamradar_color_z = ReadByte() / 255.0;
245         }
246
247         InterpolateOrigin_Note();
248 }
249
250 void Ent_RemoveWaypointSprite()
251 {
252         if(self.netname)
253                 strunzone(self.netname);
254         if(self.netname2)
255                 strunzone(self.netname2);
256         if(self.netname3)
257                 strunzone(self.netname3);
258 }
259
260 void WaypointSprite_Load()
261 {
262         waypointsprite_fadedistance = vlen(world.maxs - world.mins);
263         waypointsprite_normdistance = cvar("g_waypointsprite_normdistance");
264         waypointsprite_minscale = cvar("g_waypointsprite_minscale");
265         waypointsprite_minalpha = cvar("g_waypointsprite_minalpha");
266         waypointsprite_distancealphaexponent = cvar("g_waypointsprite_distancealphaexponent");
267         waypointsprite_timealphaexponent = cvar("g_waypointsprite_timealphaexponent");
268         waypointsprite_scale = cvar("g_waypointsprite_scale");
269         if(!waypointsprite_scale)
270                 waypointsprite_scale = 1.0;
271 }