]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/menu/xonotic/util.qc
Merge remote branch 'origin/morphed/flag'
[xonotic/xonotic-data.pk3dir.git] / qcsrc / menu / xonotic / util.qc
1 float tooltipdb;
2 void loadTooltips()
3 {
4         tooltipdb = db_load("tooltips.db");
5 }
6 void unloadTooltips()
7 {
8         db_close(tooltipdb);
9         tooltipdb = -1;
10 }
11 string getZonedTooltipForIdentifier(string s)
12 {
13         string t;
14         if(s == "")
15                 return string_null;
16         t = db_get(tooltipdb, s);
17         if(t == "-")
18                 return string_null;
19         if(t != "")
20                 return strzone(t);
21         t = cvar_description(s);
22         if(t != "" && t != "custom cvar")
23                 return strzone(t);
24         dprint("WARNING: no tooltip set for ", s, "\n");
25         return string_null;
26 }
27
28 void forAllDescendants(entity root, void(entity, entity) funcPre, void(entity, entity) funcPost, entity pass)
29 {
30         depthfirst(root, parent, firstChild, nextSibling, funcPre, funcPost, pass);
31 }
32
33 .string cvarName;
34 void SUB_Null_ee(entity e1, entity e2)
35 {
36 }
37 void saveCvarsOf(entity ignore, entity e)
38 {
39         if(e.saveCvars)
40                 e.saveCvars(e);
41 }
42 void loadCvarsOf(entity ignore, entity e)
43 {
44         if(e.loadCvars)
45                 e.loadCvars(e);
46 }
47 void saveAllCvars(entity root)
48 {
49         forAllDescendants(root, saveCvarsOf, SUB_Null_ee, NULL);
50 }
51 void loadAllCvars(entity root)
52 {
53         forAllDescendants(root, loadCvarsOf, SUB_Null_ee, NULL);
54 }
55
56 .string cvarNames_Multi;
57 .void(entity me) saveCvars_Multi;
58 void saveCvarsMulti(entity me)
59 {
60         float n, i;
61         string s;
62
63         me.saveCvars_Multi(me);
64         s = cvar_string(me.cvarName);
65
66         n = tokenize_console(me.cvarNames_Multi);
67         for(i = 0; i < n; ++i)
68                 cvar_set(argv(i), s);
69 }
70 void makeMulti(entity e, string otherCvars)
71 {
72         e.cvarNames_Multi = otherCvars;
73         e.saveCvars_Multi = e.saveCvars;
74         e.saveCvars = saveCvarsMulti;
75 }
76
77 .void(entity me) saveCvars_Callback;
78 .entity saveCvars_Callback_ent;
79 .void(entity me, entity cb) saveCvars_Callback_func;
80 void saveCvarsCallback(entity me)
81 {
82         me.saveCvars_Callback(me);
83         me.saveCvars_Callback_func(me.saveCvars_Callback_ent, me);
84 }
85 void makeCallback(entity e, entity cbent, void(entity, entity) cbfunc)
86 {
87         e.saveCvars_Callback = e.saveCvars;
88         e.saveCvars = saveCvarsCallback;
89         e.saveCvars_Callback_ent = cbent;
90         e.saveCvars_Callback_func = cbfunc;
91 }
92
93 .void(entity) draw_setDependent;
94 .string cvar_setDependent;
95 .float cvarMin_setDependent;
96 .float cvarMax_setDependent;
97 .string cvar2_setDependent;
98 .float cvar2Min_setDependent;
99 .float cvar2Max_setDependent;
100 .string cvar3_setDependent;
101 .float cvar3Min_setDependent;
102 .float cvar3Max_setDependent;
103 .float op_setDependent;
104 .string cvarString_setDependent;
105 .string cvarValue_setDependent;
106 .float(entity) func_setDependent;
107 void setDependent_Check(entity e)
108 {
109         float f;
110         string s;
111         if(e.func_setDependent)
112         {
113                 e.disabled = !(e.func_setDependent(e));
114         }
115         else if(e.cvarString_setDependent)
116         {
117                 s = cvar_string(e.cvarString_setDependent);
118                 e.disabled = (cvar_string(e.cvarString_setDependent) == e.cvarValue_setDependent);
119         }
120         else
121         {
122                 if(e.cvar_setDependent)
123                 {
124                         f = cvar(e.cvar_setDependent);
125                         if(e.cvarMin_setDependent <= e.cvarMax_setDependent)
126                                 e.disabled = ((f < e.cvarMin_setDependent) || (f > e.cvarMax_setDependent));
127                         else
128                                 e.disabled = ((f >= e.cvarMax_setDependent) && (f <= e.cvarMin_setDependent));
129                 }
130                 if(e.cvar2_setDependent)
131                 {
132                         f = cvar(e.cvar2_setDependent);
133                         if(e.cvar2Min_setDependent <= e.cvar2Max_setDependent)
134                                 e.disabled = (e.disabled + ((f < e.cvar2Min_setDependent) || (f > e.cvar2Max_setDependent)) > e.op_setDependent);
135                         else
136                                 e.disabled = (e.disabled + ((f >= e.cvar2Max_setDependent) && (f <= e.cvar2Min_setDependent)) > e.op_setDependent);
137                 }
138                 if(e.cvar3_setDependent)
139                 {
140                         f = cvar(e.cvar3_setDependent);
141                         if(e.cvar3Min_setDependent <= e.cvar3Max_setDependent)
142                                 e.disabled = (e.disabled + ((f < e.cvar3Min_setDependent) || (f > e.cvar3Max_setDependent)) > e.op_setDependent);
143                         else
144                                 e.disabled = (e.disabled + ((f >= e.cvar3Max_setDependent) && (f <= e.cvar3Min_setDependent)) > e.op_setDependent);
145                 }
146         }
147 }
148 void setDependent_Draw(entity e)
149 {
150         setDependent_Check(e);
151         e.draw_setDependent(e);
152 }
153 void setDependent(entity e, string theCvarName, float theCvarMin, float theCvarMax)
154 {
155         e.draw_setDependent = e.draw;
156         e.cvar_setDependent = theCvarName;
157         e.cvarMin_setDependent = theCvarMin;
158         e.cvarMax_setDependent = theCvarMax;
159         e.cvar2_setDependent = string_null;
160         e.cvar3_setDependent = string_null;
161         e.func_setDependent = func_null;
162         e.draw = setDependent_Draw;
163         setDependent_Check(e);
164 }
165 void setDependentStringNotEqual(entity e, string theCvarName, string theCvarValue)
166 {
167         e.draw_setDependent = e.draw;
168         e.cvarString_setDependent = theCvarName;
169         e.cvarValue_setDependent = theCvarValue;
170         e.cvar_setDependent = string_null;
171         e.cvar2_setDependent = string_null;
172         e.cvar3_setDependent = string_null;
173         e.func_setDependent = func_null;
174         e.draw = setDependent_Draw;
175         setDependent_Check(e);
176 }
177 void setDependentAND(entity e, string theCvarName, float theCvarMin, float theCvarMax, string theCvar2Name, float theCvar2Min, float theCvar2Max)
178 {
179         e.draw_setDependent = e.draw;
180         e.cvar_setDependent = theCvarName;
181         e.cvarMin_setDependent = theCvarMin;
182         e.cvarMax_setDependent = theCvarMax;
183         e.cvar2_setDependent = theCvar2Name;
184         e.cvar2Min_setDependent = theCvar2Min;
185         e.cvar2Max_setDependent = theCvar2Max;
186         e.cvar3_setDependent = string_null;
187         e.op_setDependent = 0;
188         e.func_setDependent = func_null;
189         e.draw = setDependent_Draw;
190         setDependent_Check(e);
191 }
192 void setDependentOR(entity e, string theCvarName, float theCvarMin, float theCvarMax, string theCvar2Name, float theCvar2Min, float theCvar2Max)
193 {
194         e.draw_setDependent = e.draw;
195         e.cvar_setDependent = theCvarName;
196         e.cvarMin_setDependent = theCvarMin;
197         e.cvarMax_setDependent = theCvarMax;
198         e.cvar2_setDependent = theCvar2Name;
199         e.cvar2Min_setDependent = theCvar2Min;
200         e.cvar2Max_setDependent = theCvar2Max;
201         e.cvar3_setDependent = string_null;
202         e.op_setDependent = 1;
203         e.func_setDependent = func_null;
204         e.draw = setDependent_Draw;
205         setDependent_Check(e);
206 }
207 void setDependentAND3(entity e, string theCvarName, float theCvarMin, float theCvarMax, string theCvar2Name, float theCvar2Min, float theCvar2Max, string theCvar3Name, float theCvar3Min, float theCvar3Max)
208 {
209         e.draw_setDependent = e.draw;
210         e.cvar_setDependent = theCvarName;
211         e.cvarMin_setDependent = theCvarMin;
212         e.cvarMax_setDependent = theCvarMax;
213         e.cvar2_setDependent = theCvar2Name;
214         e.cvar2Min_setDependent = theCvar2Min;
215         e.cvar2Max_setDependent = theCvar2Max;
216         e.cvar3_setDependent = theCvar3Name;
217         e.cvar3Min_setDependent = theCvar3Min;
218         e.cvar3Max_setDependent = theCvar3Max;
219         e.op_setDependent = 0;
220         e.func_setDependent = func_null;
221         e.draw = setDependent_Draw;
222         setDependent_Check(e);
223 }
224 void setDependentWeird(entity e, float(entity) func)
225 {
226         e.draw_setDependent = e.draw;
227         e.func_setDependent = func;
228         e.draw = setDependent_Draw;
229         setDependent_Check(e);
230 }
231
232 // URI SYSTEM ////////////////////////////////////////////////////////
233
234 float _Nex_ExtResponseSystem_Queried;
235 string _Nex_ExtResponseSystem_UpdateTo;
236
237 void URI_Get_Callback(float id, float status, string data)
238 {
239         if (id == URI_GET_DISCARD)
240         {
241                 // discard
242         }
243         else if(id == URI_GET_UPDATENOTIFICATION)
244         {
245                 UpdateNotification_URI_Get_Callback(id, status, data);
246         }
247         else if(id >= URI_GET_CURL && id <= URI_GET_CURL_END)
248         {
249                 Curl_URI_Get_Callback(id, status, data);
250         }
251         else
252         {
253                 print("Received HTTP request data for an invalid id ", ftos(id), ".\n");
254         }
255 }
256
257 void UpdateNotification_URI_Get_Callback(float id, float status, string data)
258 {
259         float n;
260
261         if(_Nex_ExtResponseSystem_UpdateTo)
262         {
263                 print("error: UpdateNotification_URI_Get_Callback has been called before\n");
264                 return;
265         }
266         if(status != 0)
267         {
268                 print(sprintf("error receiving update notification: status is %d\n", status));
269                 return;
270         }
271         if(substring(data, 0, 1) == "<")
272         {
273                 print("error: received HTML instead of an update notification\n");
274                 return;
275         }
276         if(strstrofs(data, "\r", 0) != -1)
277         {
278                 print("error: received carriage returns from update notification server\n");
279                 return;
280         }
281
282         if(data == "")
283                 n = 0;
284         else
285                 n = tokenizebyseparator(data, "\n");
286         
287         if(n >= 1)
288         {
289                 _Nex_ExtResponseSystem_UpdateTo = argv(0);
290
291                 if(vercmp(cvar_string("g_xonoticversion"), _Nex_ExtResponseSystem_UpdateTo) >= 0)
292                 {
293                         _Nex_ExtResponseSystem_UpdateTo = ""; // no update needed
294                 }
295                 else
296                 {
297                         // update needed
298                         if(n >= 2)
299                                 print(sprintf("Update can be downloaded at:\n%s\n", argv(1)));
300                 }
301
302                 _Nex_ExtResponseSystem_UpdateTo = strzone(_Nex_ExtResponseSystem_UpdateTo);
303         }
304 }
305
306 // END OF URI SYSTEM ////////////////////////////////////////////////////////
307
308 float preMenuInit()
309 {
310         vector sz;
311         vector boxA, boxB;
312
313         MapInfo_Cache_Create();
314         MapInfo_Enumerate();
315         if(!MapInfo_FilterGametype(MAPINFO_TYPE_ALL, 0, 0, 0, 1))
316         {
317                 draw_reset_cropped();
318
319                 sz = eX * 0.025 + eY * 0.025 * (draw_scale_x / draw_scale_y);
320                 draw_CenterText('0.5 0.5 0' - 1.25 * sz_y * eY, "Autogenerating mapinfo for newly added maps...", sz, '1 1 1', 1, 0);
321
322                 boxA = '0.05 0.5 0' + 0.25 * sz_y * eY;
323                 boxB = '0.95 0.5 0' + 1.25 * sz_y * eY;
324                 draw_Fill(boxA, boxB - boxA, '1 1 1', 1);
325                 
326                 boxA += sz * 0.1;
327                 boxB -= sz * 0.1;
328                 draw_Fill(boxA, boxB - boxA, '0.1 0.1 0.1', 1);
329
330                 boxB_x = boxA_x * (1 - MapInfo_progress) + boxB_x * MapInfo_progress;
331                 draw_Fill(boxA, boxB - boxA, '0 0 1', 1);
332
333                 return FALSE;
334         }
335         return TRUE;
336 }
337
338 string campaign_name_previous;
339 float campaign_won_previous;
340 #ifdef WATERMARK
341 var string autocvar_menu_watermark = WATERMARK();
342 #else
343 var string autocvar_menu_watermark = "";
344 #endif
345 void postMenuDraw()
346 {
347         if(autocvar_menu_watermark != "")
348         {
349                 vector fs = '48 48 0';
350                 draw_CenterText('0.5 0.1 0', autocvar_menu_watermark, globalToBoxSize('32 32 0', draw_scale), '1 1 1', 0.05, 1);
351         }
352 }
353 void preMenuDraw()
354 {
355         vector fs, sz, line, mid;
356
357         if(cvar("menu_updatecheck"))
358         {
359                 if(!_Nex_ExtResponseSystem_Queried)
360                 {
361                         _Nex_ExtResponseSystem_Queried = 1;
362                         uri_get(sprintf("http://www.xonotic.org/dl/checkupdate.txt?version=%s", uri_escape(cvar_string("g_xonoticversion"))), URI_GET_UPDATENOTIFICATION);
363                         //crypto_uri_postbuf(sprintf("http://www.xonotic.org/dl/t/checkupdate2.cgi?version=%s", uri_escape(cvar_string("g_xonoticversion"))), URI_GET_UPDATENOTIFICATION, "application/x-www-urlencoded", "hello=world&foo=bar", -1, 0);
364                 }
365         }
366
367         if(_Nex_ExtResponseSystem_UpdateTo != "")
368         {
369                 // TODO rather turn this into a dialog
370                 fs = ((1/draw_scale_x) * eX + (1/draw_scale_y) * eY) * 12;
371                 line = eY * fs_y;
372                 sz_x = draw_TextWidth("  http://www.xonotic.com/  ", 0, fs);
373                 sz_y = 3 * fs_y;
374
375                 draw_alpha = sin(time * 0.112 - 0.3) * 10;
376                 mid = eX * (0.5 + 0.5 * (1 - sz_x) * cos(time * 0.071))
377                     + eY * (0.5 + 0.5 * (1 - sz_y) * sin(time * 0.071));
378
379                 draw_Fill(mid - 0.5 * sz, sz, '1 1 0', 1);
380                 draw_CenterText(mid - 1 * line, strcat("Update to ", _Nex_ExtResponseSystem_UpdateTo, " now!"), fs, '1 0 0', 1, 0);
381                 draw_CenterText(mid - 0 * line, "http://www.xonotic.org/", fs, '0 0 1', 1, 0);
382         }
383         if not(campaign_name_previous)
384                 campaign_name_previous = strzone(strcat(campaign_name, "x")); // force unequal
385         if(campaign_name == campaign_name_previous)
386         {
387                 if(cvar(strcat("g_campaign", campaign_name, "_won")))
388                 {
389                         if(!campaign_won_previous)
390                         {
391                                 m_display();
392                                 DialogOpenButton_Click_withCoords(NULL, main.winnerDialog, '0 0 0', eX * conwidth + eY * conheight);
393                         }
394                         campaign_won_previous = 1;
395                 }
396                 else
397                         campaign_won_previous = 0;
398         }
399         else
400         {
401                 strunzone(campaign_name_previous);
402                 campaign_name_previous = strzone(campaign_name);
403                 campaign_won_previous = cvar(strcat("g_campaign", campaign_name, "_won"));
404         }
405 }
406
407 string resolvemod(string m)
408 {
409         if(m == "=")
410                 return getcurrentmod();
411         else
412                 return m;
413 }
414
415 string HUD_Panel_GetSettingName(float theSetting)
416 {
417         switch(theSetting) {
418                 case HUD_MENU_ENABLE: return ""; break;
419                 default: return "";
420         }
421 }