1 string wordwrap_buffer;
3 void wordwrap_buffer_put(string s)
5 wordwrap_buffer = strcat(wordwrap_buffer, s);
8 string wordwrap(string s, float l)
12 wordwrap_cb(s, l, wordwrap_buffer_put);
20 void wordwrap_buffer_sprint(string s)
22 wordwrap_buffer = strcat(wordwrap_buffer, s);
25 sprint(self, wordwrap_buffer);
30 void wordwrap_sprint(string s, float l)
33 wordwrap_cb(s, l, wordwrap_buffer_sprint);
34 if(wordwrap_buffer != "")
35 sprint(self, strcat(wordwrap_buffer, "\n"));
42 string unescape(string in)
47 // but it doesn't seem to be necessary in my tests at least
52 for(i = 0; i < len; ++i)
54 s = substring(in, i, 1);
57 s = substring(in, i+1, 1);
59 str = strcat(str, "\n");
61 str = strcat(str, "\\");
63 str = strcat(str, substring(in, i, 2));
73 void wordwrap_cb(string s, float l, void(string) callback)
76 local float lleft, i, j, wlen;
80 for (i = 0;i < strlen(s);++i)
82 if (substring(s, i, 2) == "\\n")
88 else if (substring(s, i, 1) == "\n")
93 else if (substring(s, i, 1) == " ")
103 for (j = i+1;j < strlen(s);++j)
104 // ^^ this skips over the first character of a word, which
105 // is ALWAYS part of the word
106 // this is safe since if i+1 == strlen(s), i will become
107 // strlen(s)-1 at the end of this block and the function
108 // will terminate. A space can't be the first character we
109 // read here, and neither can a \n be the start, since these
110 // two cases have been handled above.
112 c = substring(s, j, 1);
119 // we need to keep this tempstring alive even if substring is
120 // called repeatedly, so call strcat even though we're not
130 callback(substring(s, i, wlen));
131 lleft = lleft - wlen;
138 float dist_point_line(vector p, vector l0, vector ldir)
140 ldir = normalize(ldir);
142 // remove the component in line direction
143 p = p - (p * ldir) * ldir;
145 // vlen of the remaining vector
149 void depthfirst(entity start, .entity up, .entity downleft, .entity right, void(entity, entity) funcPre, void(entity, entity) funcPost, entity pass)
178 float median(float a, float b, float c)
181 return bound(a, b, c);
182 return bound(c, b, a);
185 // converts a number to a string with the indicated number of decimals
186 // works for up to 10 decimals!
187 string ftos_decimals(float number, float decimals)
193 // if negative, cut off the sign first
195 return strcat("-", ftos_decimals(-number, decimals));
196 // it now is always positive!
199 number = floor(number * pow(10, decimals) + 0.5);
202 result = ftos(number);
203 len = strlen(result);
204 // does it have a decimal point (should not happen)? If there is one, it is always at len-7)
205 // if ftos had fucked it up, which should never happen: "34278.000000"
207 if(substring(result, len - 7, 1) == ".")
209 dprint("ftos(integer) has comma? Can't be. Affected result: ", result, "\n");
210 result = substring(result, 0, len - 7);
215 return result; // don't insert a point for zero decimals
216 // is it too short? If yes, insert leading zeroes
219 result = strcat(substring("0000000000", 0, decimals - len + 1), result);
222 // and now... INSERT THE POINT!
223 tmp = substring(result, len - decimals, decimals);
224 result = strcat(substring(result, 0, len - decimals), ".", tmp);
229 vector colormapPaletteColor(float c, float isPants)
233 case 0: return '0.800000 0.800000 0.800000';
234 case 1: return '0.600000 0.400000 0.000000';
235 case 2: return '0.000000 1.000000 0.501961';
236 case 3: return '0.000000 1.000000 0.000000';
237 case 4: return '1.000000 0.000000 0.000000';
238 case 5: return '0.000000 0.501961 1.000000';
239 case 6: return '0.000000 1.000000 1.000000';
240 case 7: return '0.501961 1.000000 0.000000';
241 case 8: return '0.501961 0.000000 1.000000';
242 case 9: return '1.000000 0.000000 1.000000';
243 case 10: return '1.000000 0.000000 0.501961';
244 case 11: return '0.600000 0.600000 0.600000';
245 case 12: return '1.000000 1.000000 0.000000';
246 case 13: return '0.000000 0.000000 1.000000';
247 case 14: return '1.000000 0.501961 0.000000';
251 '1 0 0' * (0.502 + 0.498 * sin(time / 2.7182818285 + 0.0000000000))
252 + '0 1 0' * (0.502 + 0.498 * sin(time / 2.7182818285 + 2.0943951024))
253 + '0 0 1' * (0.502 + 0.498 * sin(time / 2.7182818285 + 4.1887902048));
256 '1 0 0' * (0.502 + 0.498 * sin(time / 3.1415926536 + 5.2359877560))
257 + '0 1 0' * (0.502 + 0.498 * sin(time / 3.1415926536 + 3.1415926536))
258 + '0 0 1' * (0.502 + 0.498 * sin(time / 3.1415926536 + 1.0471975512));
259 default: return '0.000 0.000 0.000';
263 // unzone the string, and return it as tempstring. Safe to be called on string_null
264 string fstrunzone(string s)
274 // Databases (hash tables)
275 #define DB_BUCKETS 8192
276 void db_save(float db, string pFilename)
279 fh = fopen(pFilename, FILE_WRITE);
281 error(strcat("Can't write DB to ", pFilename));
283 fputs(fh, strcat(ftos(DB_BUCKETS), "\n"));
284 for(i = 0; i < n; ++i)
285 fputs(fh, strcat(bufstr_get(db, i), "\n"));
294 float db_load(string pFilename)
296 float db, fh, i, j, n;
301 fh = fopen(pFilename, FILE_READ);
304 if(stof(fgets(fh)) == DB_BUCKETS)
307 while((l = fgets(fh)))
310 bufstr_set(db, i, l);
316 // different count of buckets?
317 // need to reorganize the database then (SLOW)
318 while((l = fgets(fh)))
320 n = tokenizebyseparator(l, "\\");
321 for(j = 2; j < n; j += 2)
322 db_put(db, uri_unescape(argv(j-1)), uri_unescape(argv(j)));
329 void db_dump(float db, string pFilename)
331 float fh, i, j, n, m;
332 fh = fopen(pFilename, FILE_WRITE);
334 error(strcat("Can't dump DB to ", pFilename));
337 for(i = 0; i < n; ++i)
339 m = tokenizebyseparator(bufstr_get(db, i), "\\");
340 for(j = 2; j < m; j += 2)
341 fputs(fh, strcat("\\", argv(j-1), "\\", argv(j), "\n"));
346 void db_close(float db)
351 string db_get(float db, string pKey)
354 h = mod(crc16(FALSE, pKey), DB_BUCKETS);
355 return uri_unescape(infoget(bufstr_get(db, h), pKey));
358 void db_put(float db, string pKey, string pValue)
361 h = mod(crc16(FALSE, pKey), DB_BUCKETS);
362 bufstr_set(db, h, infoadd(bufstr_get(db, h), pKey, uri_escape(pValue)));
369 db = db_load("foo.db");
370 print("LOADED. FILL...\n");
371 for(i = 0; i < DB_BUCKETS; ++i)
372 db_put(db, ftos(random()), "X");
373 print("FILLED. SAVE...\n");
374 db_save(db, "foo.db");
375 print("SAVED. CLOSE...\n");
380 // Multiline text file buffers
381 float buf_load(string pFilename)
388 fh = fopen(pFilename, FILE_READ);
392 while((l = fgets(fh)))
394 bufstr_set(buf, i, l);
401 void buf_save(float buf, string pFilename)
404 fh = fopen(pFilename, FILE_WRITE);
406 error(strcat("Can't write buf to ", pFilename));
407 n = buf_getsize(buf);
408 for(i = 0; i < n; ++i)
409 fputs(fh, strcat(bufstr_get(buf, i), "\n"));
413 string GametypeNameFromType(float g)
415 if (g == GAME_DEATHMATCH) return "dm";
416 else if (g == GAME_TEAM_DEATHMATCH) return "tdm";
417 else if (g == GAME_DOMINATION) return "dom";
418 else if (g == GAME_CTF) return "ctf";
419 else if (g == GAME_RUNEMATCH) return "rune";
420 else if (g == GAME_LMS) return "lms";
421 else if (g == GAME_KEYHUNT) return "kh";
422 else if (g == GAME_ONSLAUGHT) return "ons";
423 else if (g == GAME_ASSAULT) return "as";