]> icculus.org git repositories - divverent/nexuiz.git/blob - data/qcsrc/client/miscfunctions.qc
sync crosshair effects to weapon switch delay
[divverent/nexuiz.git] / data / qcsrc / client / miscfunctions.qc
1 var float(string text, float handleColors) stringwidth;
2
3 entity players;
4 entity teams;
5
6 void restartAnnouncer_Think() {
7         float countdown_rounded, countdown;
8         countdown = getstatf(STAT_GAMESTARTTIME) - time;
9         countdown_rounded = floor(0.5 + countdown);
10         if(countdown <= 0) {
11                 if (!spectatee_status) //do cprint only for players
12                         centerprint("^1Begin!");
13
14                 sound(self, CHAN_VOICE, "announcer/robotic/begin.wav", VOL_BASEVOICE, ATTN_NONE);
15                 //reset maptime announcers now as well
16                 announcer_5min = announcer_1min = FALSE;
17
18                 remove(self);
19                 return;
20         }
21         else {
22                 if (!spectatee_status) //do cprint only for players
23                         centerprint(strcat("^1Game starts in ", ftos(countdown_rounded), " seconds"));
24
25                 if(countdown_rounded <= 3 && countdown_rounded >= 1) {
26                         sound(self, CHAN_VOICE, strcat("announcer/robotic/", ftos(countdown_rounded), ".wav"), VOL_BASEVOICE, ATTN_NONE);
27                 }
28
29                 self.nextthink = getstatf(STAT_GAMESTARTTIME) - (countdown - 1);
30         }
31 }
32
33 /**
34  * Plays the 1minute or 5 minutes (of maptime) remaining sound, if client wants it
35  */
36 void maptimeAnnouncer() {
37     float timelimit;
38     timelimit = getstatf(STAT_TIMELIMIT);
39     float timeleft;
40     timeleft = max(0, timelimit * 60 + getstatf(STAT_GAMESTARTTIME) - time);
41
42     //5 minute check
43     if (cvar("cl_sound_maptime_warning") >= 2) {
44         //make sure that after connect (and e.g. 4 minutes left) we will not get a wrong sound
45         if(announcer_5min)
46         {
47                         if(timeleft > 300)
48                                 announcer_5min = FALSE;
49         }
50         else if (timelimit > 0 && timeleft < 300 && timeleft > 299) {
51                         announcer_5min = TRUE;
52                         //dprint("i will play the sound, I promise!\n");
53                         sound(self, CHAN_VOICE, "announcer/robotic/5minutesremain.wav", VOL_BASEVOICE, ATTN_NONE);
54                 }
55     }
56
57     //1 minute check
58     if (cvar("cl_sound_maptime_warning") == 1 || cvar("cl_sound_maptime_warning") == 3) {
59         if (announcer_1min)
60         {
61                         if(timeleft > 60)
62                                 announcer_1min = FALSE;
63         }
64         else if (timelimit > 0 && timeleft < 60) {
65                         announcer_1min = TRUE;
66                         sound(self, CHAN_VOICE, "announcer/robotic/1minuteremains.wav", VOL_BASEVOICE, ATTN_NONE);
67         }
68         }
69 }
70
71 /**
72  * Add all future announcer sounds precaches here.
73  * TODO: make all announcer sound() calls client-side in the end, to allow queues etc.
74  */
75 void Announcer_Precache () {
76     precache_sound ("announcer/robotic/1minuteremains.wav");
77         precache_sound ("announcer/robotic/5minutesremain.wav");
78 }
79
80 void AuditLists()
81 {
82         entity e;
83         entity prev;
84
85         prev = players;
86         for(e = prev.sort_next; e; prev = e, e = e.sort_next)
87         {
88                 if(prev != e.sort_prev)
89                         error(strcat("sort list chain error\nplease submit the output of 'prvm_edicts client' to the developers"));
90         }
91
92         prev = teams;
93         for(e = prev.sort_next; e; prev = e, e = e.sort_next)
94         {
95                 if(prev != e.sort_prev)
96                         error(strcat("sort list chain error\nplease submit the output of 'prvm_edicts client' to the developers"));
97         }
98 }
99
100
101 float RegisterPlayer(entity player)
102 {
103         entity pl;
104         AuditLists();
105         for(pl = players.sort_next; pl; pl = pl.sort_next)
106                 if(pl == player)
107                         error("Player already registered!");
108         player.sort_next = players.sort_next;
109         player.sort_prev = players;
110         if(players.sort_next)
111                 players.sort_next.sort_prev = player;
112         players.sort_next = player;
113         AuditLists();
114         return true;
115 }
116
117 void RemovePlayer(entity player)
118 {
119         entity pl, parent;
120         AuditLists();
121         parent = players;
122         for(pl = players.sort_next; pl && pl != player; pl = pl.sort_next)
123                 parent = pl;
124
125         if(!pl)
126         {
127                 error("Trying to remove a player which is not in the playerlist!");
128                 return;
129         }
130         parent.sort_next = player.sort_next;
131         if(player.sort_next)
132                 player.sort_next.sort_prev = parent;
133         AuditLists();
134 }
135
136 void MoveToLast(entity e)
137 {
138         AuditLists();
139         other = e.sort_next;
140         while(other)
141         {
142                 SORT_SWAP(other, e);
143                 other = e.sort_next;
144         }
145         AuditLists();
146 }
147
148 float RegisterTeam(entity Team)
149 {
150         entity tm;
151         AuditLists();
152         for(tm = teams.sort_next; tm; tm = tm.sort_next)
153                 if(tm == Team)
154                         error("Team already registered!");
155         Team.sort_next = teams.sort_next;
156         Team.sort_prev = teams;
157         if(teams.sort_next)
158                 teams.sort_next.sort_prev = Team;
159         teams.sort_next = Team;
160         AuditLists();
161         return true;
162 }
163
164 void RemoveTeam(entity Team)
165 {
166         entity tm, parent;
167         AuditLists();
168         parent = teams;
169         for(tm = teams.sort_next; tm && tm != Team; tm = tm.sort_next)
170                 parent = tm;
171
172         if(!tm)
173         {
174                 print("Trying to remove a team which is not in the teamlist!");
175                 return;
176         }
177         parent.sort_next = Team.sort_next;
178         if(Team.sort_next)
179                 Team.sort_next.sort_prev = parent;
180         AuditLists();
181 }
182
183 entity GetTeam(float Team, float add)
184 {
185         float num;
186         entity tm;
187         num = (Team == COLOR_SPECTATOR) ? 16 : Team;
188         if(teamslots[num])
189                 return teamslots[num];
190         if not(add)
191                 return NULL;
192         tm = spawn();
193         tm.team = Team;
194         teamslots[num] = tm;
195         RegisterTeam(tm);
196         return tm;
197 }
198
199 void CSQC_CheckEngine()
200 {
201         sbar_font = FONT_USER+1;
202         sbar_bigfont = FONT_USER+2;
203 }
204
205 vector Sbar_GetFontsize(string cvarname)
206 {
207         vector v;
208         v = stov(cvar_string(cvarname));
209         if(v_x == 0)
210                 v = '8 8 0';
211         if(v_y == 0)
212                 v_y = v_x;
213         v_z = 0;
214         return v;
215 }
216
217 float Sbar_GetWidth(float teamcolumnwidth)
218 {
219         float f;
220         f = cvar("sbar_width");
221         if(f == 0)
222                 f = 640;
223         if(f < 320)
224                 f = 320;
225         if(f > vid_conwidth - 2 * teamcolumnwidth)
226                 f = vid_conwidth - 2 * teamcolumnwidth;
227         return f;
228 }
229
230 float PreviewExists(string name)
231 {
232         float f;
233         string file;
234
235         if(cvar("cl_readpicture_force"))
236                 return false;
237
238         file = strcat(name, ".tga");
239         f = fopen(file, FILE_READ);
240         if(f >= 0)
241         {
242                 fclose(f);
243                 return true;
244         }
245         file = strcat(name, ".png");
246         f = fopen(file, FILE_READ);
247         if(f >= 0)
248         {
249                 fclose(f);
250                 return true;
251         }
252         file = strcat(name, ".jpg");
253         f = fopen(file, FILE_READ);
254         if(f >= 0)
255         {
256                 fclose(f);
257                 return true;
258         }
259         file = strcat(name, ".pcx");
260         f = fopen(file, FILE_READ);
261         if(f >= 0)
262         {
263                 fclose(f);
264                 return true;
265         }
266         return false;
267 }
268
269 float PI      = 3.14159265359;
270 float DEG2RAD = 0.01745329252;
271 vector rotate(vector v, float a)
272 {
273         vector w;
274         // FTEQCC SUCKS AGAIN
275         w_x =      v_x * cos(a) + v_y * sin(a);
276         w_y = -1 * v_x * sin(a) + v_y * cos(a);
277         return w;
278 }
279
280 float ColorTranslateMode;
281
282 string ColorTranslateRGB(string s)
283 {
284         if(ColorTranslateMode & 1)
285                 return strdecolorize(s);
286         else
287                 return s;
288 }
289
290 float cvar_or(string cv, float v)
291 {
292         string s;
293         s = cvar_string(cv);
294         if(s == "")
295                 return v;
296         else
297                 return stof(s);
298 }
299
300 vector project_3d_to_2d(vector vec)
301 {
302         vec = cs_project(vec);
303         if(cs_project_is_b0rked > 0)
304         {
305                 vec_x *= vid_conwidth / vid_width;
306                 vec_y *= vid_conheight / vid_height;
307         }
308         return vec;
309 }
310
311 void dummyfunction(float a1, float a2, float a3, float a4, float a5, float a6, float a7, float a8)
312 {
313 }
314
315 float expandingbox_sizefactor_from_fadelerp(float fadelerp)
316 {
317         return 1.2 / (1.2 - fadelerp);
318 }
319
320 vector expandingbox_resize_centered_box_offset(float sz, vector boxsize, float boxxsizefactor)
321 {
322         boxsize_x *= boxxsizefactor; // easier interface for text
323         return boxsize * (0.5 * (1 - sz));
324 }
325
326 void drawborderlines(float thickness, vector pos, vector dim, vector color, float alpha, float drawflag)
327 {
328         vector line_dim;
329
330         // left and right lines
331         pos_x -= thickness;
332         line_dim_x = thickness;
333         line_dim_y = dim_y;
334         drawfill(pos, line_dim, color, alpha, drawflag);
335         drawfill(pos + (dim_x + thickness) * '1 0 0', line_dim, color, alpha, drawflag);
336
337         // upper and lower lines
338         pos_y -= thickness;
339         line_dim_x = dim_x + thickness * 2; // make upper and lower lines longer
340         line_dim_y = thickness;
341         drawfill(pos, line_dim, color, alpha, drawflag);
342         drawfill(pos + (dim_y + thickness) * '0 1 0', line_dim, color, alpha, drawflag);
343 }
344
345 void drawpic_tiled(vector pos, string pic, vector sz, vector area, vector color, float alpha, float drawflag)
346 {
347         vector current_pos, end_pos, new_size, ratio;
348         end_pos = pos + area;
349
350         current_pos_y = pos_y;
351         while (current_pos_y < end_pos_y)
352         {
353                 current_pos_x = pos_x;
354                 while (current_pos_x < end_pos_x)
355                 {
356                         new_size_x = min(sz_x, end_pos_x - current_pos_x);
357                         new_size_y = min(sz_y, end_pos_y - current_pos_y);
358                         ratio_x = new_size_x / sz_x;
359                         ratio_y = new_size_y / sz_y;
360                         drawsubpic(current_pos, new_size, pic, '0 0 0', ratio, color, alpha, drawflag);
361                         current_pos_x += sz_x;
362                 }
363                 current_pos_y += sz_y;
364         }
365 }
366
367 void drawpic_expanding(vector position, string pic, vector scale, vector rgb, float alpha, float flag, float fadelerp)
368 {
369         float sz;
370         sz = expandingbox_sizefactor_from_fadelerp(fadelerp);
371
372         drawpic(position + expandingbox_resize_centered_box_offset(sz, scale, 1), pic, scale * sz, rgb, alpha * (1 - fadelerp), flag);
373 }
374
375 void drawpic_expanding_two(vector position, string pic, vector scale, vector rgb, float alpha, float flag, float fadelerp)
376 {
377         drawpic_expanding(position, pic, scale, rgb, alpha, flag, fadelerp);
378         drawpic(position, pic, scale, rgb, alpha * fadelerp, flag);
379 }
380
381 void drawstring_expanding(vector position, string text, vector scale, vector rgb, float alpha, float flag, float fadelerp)
382 {
383         float sz;
384         sz = expandingbox_sizefactor_from_fadelerp(fadelerp);
385
386         dummyfunction(0, 0, 0, 0, 0, 0, 0, 0);
387         drawstring(position + expandingbox_resize_centered_box_offset(sz, scale, stringwidth(text, FALSE)), text, scale * sz, rgb, alpha * (1 - fadelerp), flag);
388 }
389
390 void drawcolorcodedstring_expanding(vector position, string text, vector scale, float alpha, float flag, float fadelerp)
391 {
392         float sz;
393         sz = expandingbox_sizefactor_from_fadelerp(fadelerp);
394
395         dummyfunction(0, 0, 0, 0, 0, 0, 0, 0);
396         drawcolorcodedstring(position + expandingbox_resize_centered_box_offset(sz, scale, stringwidth(text, TRUE)), text, scale * sz, alpha * (1 - fadelerp), flag);
397 }