support cl_hidewaypoints 2 (hide all)
[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
21 .float rule;
22 .string netname; // primary picture
23 .string netname2; // secondary picture
24 .string netname3; // tertiary picture
25 .float team; // team that gets netname2
26 .float lifetime;
27 .float fadetime;
28 .float maxdistance;
29 .float hideflags;
30
31 vector SPRITE_SIZE = '128 32 0';
32 vector SPRITE_HOTSPOT = '64 32 0';
33
34 void drawrotpic(vector org, float rot, string pic, vector sz, vector hotspot, vector rgb, float a, float f)
35 {
36         vector v1, v2, v3, v4;
37
38         hotspot = -1 * hotspot;
39
40         // hotspot-relative coordinates of the corners
41         v1 = hotspot;
42         v2 = hotspot + '1 0 0' * sz_x;
43         v3 = hotspot + '1 0 0' * sz_x + '0 1 0' * sz_y;
44         v4 = hotspot                  + '0 1 0' * sz_y;
45
46         // rotate them, and make them absolute
47         v1 = rotate(v1, rot) + org;
48         v2 = rotate(v2, rot) + org;
49         v3 = rotate(v3, rot) + org;
50         v4 = rotate(v4, rot) + org;
51
52         // draw them
53         R_BeginPolygon(pic, f);
54         R_PolygonVertex(v1, '0 0 0', rgb, a);
55         R_PolygonVertex(v2, '1 0 0', rgb, a);
56         R_PolygonVertex(v3, '1 1 0', rgb, a);
57         R_PolygonVertex(v4, '0 1 0', rgb, a);
58         R_EndPolygon();
59 }
60
61 void Draw_WaypointSprite()
62 {
63         string spriteimage;
64         float t;
65
66         if(self.lifetime)
67                 self.alpha = pow(bound(0, (self.fadetime - time) / self.lifetime, 1), waypointsprite_timealphaexponent);
68         else
69                 self.alpha = 1;
70
71         if(self.hideflags & 2)
72                 return; // radar only
73
74         if(cvar("cl_hidewaypoints") >= 2)
75                 return;
76
77         if(self.hideflags & 1)
78                 if(cvar("cl_hidewaypoints"))
79                         return; // fixed waypoint
80
81         InterpolateOrigin_Do();
82
83         t = GetPlayerColor(player_localentnum - 1) + 1;
84
85         spriteimage = "";
86
87         // choose the sprite
88         switch(self.rule)
89         {
90                 case SPRITERULE_DEFAULT:
91                         spriteimage = self.netname;
92                         break;
93                 case SPRITERULE_TEAMPLAY:
94                         if(self.team == t)
95                                 spriteimage = self.netname2;
96                         else
97                                 spriteimage = self.netname;
98                         break;
99                 default:
100                         error("Invalid waypointsprite rule!");
101                         break;
102         }
103
104         if(spriteimage == "")
105                 return;
106         
107         float dist;
108         dist = vlen(self.origin - view_origin);
109         
110         float a;
111         a = self.alpha;
112
113         if(self.maxdistance > waypointsprite_normdistance)
114                 a *= pow(bound(0, (self.maxdistance - dist) / (self.maxdistance - waypointsprite_normdistance), 1), waypointsprite_distancealphaexponent);
115         else if(self.maxdistance > 0)
116                 a *= pow(bound(0, (waypointsprite_fadedistance - dist) / (waypointsprite_fadedistance - waypointsprite_normdistance), 1), waypointsprite_distancealphaexponent) * (1 - waypointsprite_minalpha) + waypointsprite_minalpha;
117
118         if(a <= 0)
119                 return;
120         
121         // draw the sprite image
122         vector o;
123         float rot;
124         o = project_3d_to_2d(self.origin);
125         rot = 0;
126
127         if(o_z < 0 || o_x < 0 || o_y < 0 || o_x > vid_conwidth || o_y > vid_conheight)
128         {
129                 // scale it to be just in view
130                 vector d;
131                 float f1, f2;
132                 d = o - '0.5 0 0' * vid_conwidth - '0 0.5 0' * vid_conheight;
133
134                 f1 = d_x / vid_conwidth;
135                 f2 = d_y / vid_conheight;
136
137                 if(max(f1, -f1) > max(f2, -f2))
138                 {
139                         if(f1 > 0)
140                         {
141                                 // RIGHT edge
142                                 d = d * (0.5 / f1);
143                                 rot = 1;
144                         }
145                         else
146                         {
147                                 // LEFT edge
148                                 d = d * (-0.5 / f1);
149                                 rot = 3;
150                         }
151                 }
152                 else
153                 {
154                         if(f2 > 0)
155                         {
156                                 // BOTTOM edge
157                                 d = d * (0.5 / f2);
158                                 rot = 0;
159                         }
160                         else
161                         {
162                                 // TOP edge
163                                 d = d * (-0.5 / f2);
164                                 rot = 2;
165                         }
166                 }
167
168                 o = d + '0.5 0 0' * vid_conwidth + '0 0.5 0' * vid_conheight;
169         }
170         o_z = 0;
171
172         drawrotpic(o, rot * 90 * DEG2RAD, strcat("models/sprites/", spriteimage), SPRITE_SIZE, SPRITE_HOTSPOT, '1 1 1', a, 0);
173 }
174
175 void Ent_WaypointSprite()
176 {
177         float sendflags, f;
178         sendflags = ReadByte();
179
180         self.draw2d = Draw_WaypointSprite;
181
182         InterpolateOrigin_Undo();
183
184         // unfortunately, this needs to be exact (for the 3D display)
185         self.origin_x = ReadCoord();
186         self.origin_y = ReadCoord();
187         self.origin_z = ReadCoord();
188
189         if(sendflags & 1)
190         {
191                 self.team = ReadByte();
192                 self.rule = ReadByte();
193         }
194
195         if(sendflags & 2)
196         {
197                 if(self.netname)
198                         strunzone(self.netname);
199                 self.netname = strzone(ReadString());
200         }
201
202         if(sendflags & 4)
203         {
204                 if(self.netname2)
205                         strunzone(self.netname2);
206                 self.netname2 = strzone(ReadString());
207         }
208
209         if(sendflags & 8)
210         {
211                 if(self.netname3)
212                         strunzone(self.netname3);
213                 self.netname3 = strzone(ReadString());
214         }
215
216         if(sendflags & 16)
217         {
218                 self.lifetime = ReadCoord();
219                 self.fadetime = ReadCoord();
220                 self.maxdistance = ReadShort();
221                 self.hideflags = ReadByte();
222         }
223
224         if(sendflags & 32)
225         {
226                 f = ReadByte();
227                 self.teamradar_icon = (f & 0x7F);
228                 if(f & 0x80)
229                         self.teamradar_time = time;
230                 self.teamradar_color_x = ReadByte() / 255.0;
231                 self.teamradar_color_y = ReadByte() / 255.0;
232                 self.teamradar_color_z = ReadByte() / 255.0;
233         }
234
235         InterpolateOrigin_Note();
236 }
237
238 void Ent_RemoveWaypointSprite()
239 {
240         if(self.netname)
241                 strunzone(self.netname);
242         if(self.netname2)
243                 strunzone(self.netname2);
244         if(self.netname3)
245                 strunzone(self.netname3);
246 }
247
248 void WaypointSprite_Init()
249 {
250         waypointsprite_fadedistance = vlen(world.maxs - world.mins);
251         waypointsprite_normdistance = cvar("g_waypointsprite_normdistance");
252         waypointsprite_minscale = cvar("g_waypointsprite_minscale");
253         waypointsprite_minalpha = cvar("g_waypointsprite_minalpha");
254         waypointsprite_distancealphaexponent = cvar("g_waypointsprite_distancealphaexponent");
255         waypointsprite_timealphaexponent = cvar("g_waypointsprite_timealphaexponent");
256 }