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