]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Split up common/util.qc
authorTimePath <andrew.hardaker1995@gmail.com>
Thu, 5 Nov 2015 09:40:40 +0000 (20:40 +1100)
committerTimePath <andrew.hardaker1995@gmail.com>
Thu, 5 Nov 2015 09:40:40 +0000 (20:40 +1100)
18 files changed:
qcsrc/common/util.qc
qcsrc/common/util.qh
qcsrc/lib/_all.inc
qcsrc/lib/color.qh
qcsrc/lib/cvar.qh
qcsrc/lib/map.qc [new file with mode: 0644]
qcsrc/lib/math.qh
qcsrc/lib/net.qh
qcsrc/lib/oo.qh
qcsrc/lib/random.qc
qcsrc/lib/string.qh
qcsrc/menu/classes.qc [new file with mode: 0644]
qcsrc/menu/command/menu_cmd.qc
qcsrc/menu/draw.qc
qcsrc/menu/draw.qh
qcsrc/menu/menu.qc
qcsrc/menu/oo/classes.qc [deleted file]
qcsrc/menu/progs.inc

index a6a57c7dfc8ff126095a778b8e52c30d9decb311..3e380ca696d06e0a66b0d3bde2423c997fccaa93 100644 (file)
@@ -163,205 +163,6 @@ void depthfirst(entity start, .entity up, .entity downleft, .entity right, void(
        }
 }
 
-// converts a number to a string with the indicated number of decimals
-// works for up to 10 decimals!
-string ftos_decimals(float number, float decimals)
-{
-       // inhibit stupid negative zero
-       if(number == 0)
-               number = 0;
-       // we have sprintf...
-       return sprintf("%.*f", decimals, number);
-}
-
-// Databases (hash tables)
-const float DB_BUCKETS = 8192;
-void db_save(float db, string pFilename)
-{
-       float fh, i, n;
-       fh = fopen(pFilename, FILE_WRITE);
-       if(fh < 0)
-       {
-               LOG_INFO(strcat("^1Can't write DB to ", pFilename));
-               return;
-       }
-       n = buf_getsize(db);
-       fputs(fh, strcat(ftos(DB_BUCKETS), "\n"));
-       for(i = 0; i < n; ++i)
-               fputs(fh, strcat(bufstr_get(db, i), "\n"));
-       fclose(fh);
-}
-
-int db_create()
-{
-       return buf_create();
-}
-
-int db_load(string pFilename)
-{
-       float db, fh, i, j, n;
-       string l;
-       db = buf_create();
-       if(db < 0)
-               return -1;
-       fh = fopen(pFilename, FILE_READ);
-       if(fh < 0)
-               return db;
-       l = fgets(fh);
-       if(stof(l) == DB_BUCKETS)
-       {
-               i = 0;
-               while((l = fgets(fh)))
-               {
-                       if(l != "")
-                               bufstr_set(db, i, l);
-                       ++i;
-               }
-       }
-       else
-       {
-               // different count of buckets, or a dump?
-               // need to reorganize the database then (SLOW)
-               //
-               // note: we also parse the first line (l) in case the DB file is
-               // missing the bucket count
-               do
-               {
-                       n = tokenizebyseparator(l, "\\");
-                       for(j = 2; j < n; j += 2)
-                               db_put(db, argv(j-1), uri_unescape(argv(j)));
-               }
-               while((l = fgets(fh)));
-       }
-       fclose(fh);
-       return db;
-}
-
-void db_dump(float db, string pFilename)
-{
-       float fh, i, j, n, m;
-       fh = fopen(pFilename, FILE_WRITE);
-       if(fh < 0)
-               error(strcat("Can't dump DB to ", pFilename));
-       n = buf_getsize(db);
-       fputs(fh, "0\n");
-       for(i = 0; i < n; ++i)
-       {
-               m = tokenizebyseparator(bufstr_get(db, i), "\\");
-               for(j = 2; j < m; j += 2)
-                       fputs(fh, strcat("\\", argv(j-1), "\\", argv(j), "\n"));
-       }
-       fclose(fh);
-}
-
-void db_close(float db)
-{
-       buf_del(db);
-}
-
-string db_get(float db, string pKey)
-{
-       float h;
-       h = crc16(false, pKey) % DB_BUCKETS;
-       return uri_unescape(infoget(bufstr_get(db, h), pKey));
-}
-
-void db_put(float db, string pKey, string pValue)
-{
-       float h;
-       h = crc16(false, pKey) % DB_BUCKETS;
-       bufstr_set(db, h, infoadd(bufstr_get(db, h), pKey, uri_escape(pValue)));
-}
-
-void db_test()
-{
-       float db, i;
-       LOG_INFO("LOAD...\n");
-       db = db_load("foo.db");
-       LOG_INFO("LOADED. FILL...\n");
-       for(i = 0; i < DB_BUCKETS; ++i)
-               db_put(db, ftos(random()), "X");
-       LOG_INFO("FILLED. SAVE...\n");
-       db_save(db, "foo.db");
-       LOG_INFO("SAVED. CLOSE...\n");
-       db_close(db);
-       LOG_INFO("CLOSED.\n");
-}
-
-// Multiline text file buffers
-int buf_load(string pFilename)
-{
-       float buf, fh, i;
-       string l;
-       buf = buf_create();
-       if(buf < 0)
-               return -1;
-       fh = fopen(pFilename, FILE_READ);
-       if(fh < 0)
-       {
-               buf_del(buf);
-               return -1;
-       }
-       i = 0;
-       while((l = fgets(fh)))
-       {
-               bufstr_set(buf, i, l);
-               ++i;
-       }
-       fclose(fh);
-       return buf;
-}
-
-void buf_save(float buf, string pFilename)
-{
-       float fh, i, n;
-       fh = fopen(pFilename, FILE_WRITE);
-       if(fh < 0)
-               error(strcat("Can't write buf to ", pFilename));
-       n = buf_getsize(buf);
-       for(i = 0; i < n; ++i)
-               fputs(fh, strcat(bufstr_get(buf, i), "\n"));
-       fclose(fh);
-}
-
-string format_time(float seconds)
-{
-       float days, hours, minutes;
-       seconds = floor(seconds + 0.5);
-        days = floor(seconds / 864000);
-        seconds -= days * 864000;
-        hours = floor(seconds / 36000);
-        seconds -= hours * 36000;
-       minutes = floor(seconds / 600);
-       seconds -= minutes * 600;
-        if (days > 0)
-                return sprintf(_("%d days, %02d:%02d:%02d"), days, hours, minutes, seconds);
-        else
-                return sprintf(_("%02d:%02d:%02d"), hours, minutes, seconds);
-}
-
-string mmsss(float tenths)
-{
-       float minutes;
-       string s;
-       tenths = floor(tenths + 0.5);
-       minutes = floor(tenths / 600);
-       tenths -= minutes * 600;
-       s = ftos(1000 + tenths);
-       return strcat(ftos(minutes), ":", substring(s, 1, 2), ".", substring(s, 3, 1));
-}
-
-string mmssss(float hundredths)
-{
-       float minutes;
-       string s;
-       hundredths = floor(hundredths + 0.5);
-       minutes = floor(hundredths / 6000);
-       hundredths -= minutes * 6000;
-       s = ftos(10000 + hundredths);
-       return strcat(ftos(minutes), ":", substring(s, 1, 2), ".", substring(s, 3, 2));
-}
-
 string ScoreString(int pFlags, float pValue)
 {
        string valstr;
@@ -624,23 +425,6 @@ string swapInPriorityList(string order, float i, float j)
        return order;
 }
 
-float cvar_value_issafe(string s)
-{
-       if(strstrofs(s, "\"", 0) >= 0)
-               return 0;
-       if(strstrofs(s, "\\", 0) >= 0)
-               return 0;
-       if(strstrofs(s, ";", 0) >= 0)
-               return 0;
-       if(strstrofs(s, "$", 0) >= 0)
-               return 0;
-       if(strstrofs(s, "\r", 0) >= 0)
-               return 0;
-       if(strstrofs(s, "\n", 0) >= 0)
-               return 0;
-       return 1;
-}
-
 #ifndef MENUQC
 void get_mi_min_max(float mode)
 {
@@ -835,150 +619,6 @@ float cvar_settemp_restore()
        return i;
 }
 
-float rgb_mi_ma_to_hue(vector rgb, float mi, float ma)
-{
-       if(mi == ma)
-               return 0;
-       else if(ma == rgb.x)
-       {
-               if(rgb.y >= rgb.z)
-                       return (rgb.y - rgb.z) / (ma - mi);
-               else
-                       return (rgb.y - rgb.z) / (ma - mi) + 6;
-       }
-       else if(ma == rgb.y)
-               return (rgb.z - rgb.x) / (ma - mi) + 2;
-       else // if(ma == rgb_z)
-               return (rgb.x - rgb.y) / (ma - mi) + 4;
-}
-
-vector hue_mi_ma_to_rgb(float hue, float mi, float ma)
-{
-       vector rgb;
-
-       hue -= 6 * floor(hue / 6);
-
-       //else if(ma == rgb_x)
-       //      hue = 60 * (rgb_y - rgb_z) / (ma - mi);
-       if(hue <= 1)
-       {
-               rgb.x = ma;
-               rgb.y = hue * (ma - mi) + mi;
-               rgb.z = mi;
-       }
-       //else if(ma == rgb_y)
-       //      hue = 60 * (rgb_z - rgb_x) / (ma - mi) + 120;
-       else if(hue <= 2)
-       {
-               rgb.x = (2 - hue) * (ma - mi) + mi;
-               rgb.y = ma;
-               rgb.z = mi;
-       }
-       else if(hue <= 3)
-       {
-               rgb.x = mi;
-               rgb.y = ma;
-               rgb.z = (hue - 2) * (ma - mi) + mi;
-       }
-       //else // if(ma == rgb_z)
-       //      hue = 60 * (rgb_x - rgb_y) / (ma - mi) + 240;
-       else if(hue <= 4)
-       {
-               rgb.x = mi;
-               rgb.y = (4 - hue) * (ma - mi) + mi;
-               rgb.z = ma;
-       }
-       else if(hue <= 5)
-       {
-               rgb.x = (hue - 4) * (ma - mi) + mi;
-               rgb.y = mi;
-               rgb.z = ma;
-       }
-       //else if(ma == rgb_x)
-       //      hue = 60 * (rgb_y - rgb_z) / (ma - mi);
-       else // if(hue <= 6)
-       {
-               rgb.x = ma;
-               rgb.y = mi;
-               rgb.z = (6 - hue) * (ma - mi) + mi;
-       }
-
-       return rgb;
-}
-
-vector rgb_to_hsv(vector rgb)
-{
-       float mi, ma;
-       vector hsv;
-
-       mi = min(rgb.x, rgb.y, rgb.z);
-       ma = max(rgb.x, rgb.y, rgb.z);
-
-       hsv.x = rgb_mi_ma_to_hue(rgb, mi, ma);
-       hsv.z = ma;
-
-       if(ma == 0)
-               hsv.y = 0;
-       else
-               hsv.y = 1 - mi/ma;
-
-       return hsv;
-}
-
-vector hsv_to_rgb(vector hsv)
-{
-       return hue_mi_ma_to_rgb(hsv.x, hsv.z * (1 - hsv.y), hsv.z);
-}
-
-vector rgb_to_hsl(vector rgb)
-{
-       float mi, ma;
-       vector hsl;
-
-       mi = min(rgb.x, rgb.y, rgb.z);
-       ma = max(rgb.x, rgb.y, rgb.z);
-
-       hsl.x = rgb_mi_ma_to_hue(rgb, mi, ma);
-
-       hsl.z = 0.5 * (mi + ma);
-       if(mi == ma)
-               hsl.y = 0;
-       else if(hsl.z <= 0.5)
-               hsl.y = (ma - mi) / (2*hsl.z);
-       else // if(hsl_z > 0.5)
-               hsl.y = (ma - mi) / (2 - 2*hsl.z);
-
-       return hsl;
-}
-
-vector hsl_to_rgb(vector hsl)
-{
-       float mi, ma, maminusmi;
-
-       if(hsl.z <= 0.5)
-               maminusmi = hsl.y * 2 * hsl.z;
-       else
-               maminusmi = hsl.y * (2 - 2 * hsl.z);
-
-       // hsl_z     = 0.5 * mi + 0.5 * ma
-       // maminusmi =     - mi +       ma
-       mi = hsl.z - 0.5 * maminusmi;
-       ma = hsl.z + 0.5 * maminusmi;
-
-       return hue_mi_ma_to_rgb(hsl.x, mi, ma);
-}
-
-string rgb_to_hexcolor(vector rgb)
-{
-       return
-               strcat(
-                       "^x",
-                       DEC_TO_HEXDIGIT(floor(rgb.x * 15 + 0.5)),
-                       DEC_TO_HEXDIGIT(floor(rgb.y * 15 + 0.5)),
-                       DEC_TO_HEXDIGIT(floor(rgb.z * 15 + 0.5))
-               );
-}
-
 float textLengthUpToWidth(string theText, float maxWidth, vector theSize, textLengthUpToWidth_widthFunction_t w)
 {
        // STOP.
@@ -1297,60 +937,6 @@ float isGametypeInFilter(float gt, float tp, float ts, string pattern)
        return 1;
 }
 
-vector solve_quadratic(float a, float b, float c) // ax^2 + bx + c = 0
-{
-       vector v;
-       float D;
-       v = '0 0 0';
-       if(a == 0)
-       {
-               if(b != 0)
-               {
-                       v.x = v.y = -c / b;
-                       v.z = 1;
-               }
-               else
-               {
-                       if(c == 0)
-                       {
-                               // actually, every number solves the equation!
-                               v.z = 1;
-                       }
-               }
-       }
-       else
-       {
-               D = b*b - 4*a*c;
-               if(D >= 0)
-               {
-                       D = sqrt(D);
-                       if(a > 0) // put the smaller solution first
-                       {
-                               v.x = ((-b)-D) / (2*a);
-                               v.y = ((-b)+D) / (2*a);
-                       }
-                       else
-                       {
-                               v.x = (-b+D) / (2*a);
-                               v.y = (-b-D) / (2*a);
-                       }
-                       v.z = 1;
-               }
-               else
-               {
-                       // complex solutions!
-                       D = sqrt(-D);
-                       v.x = -b / (2*a);
-                       if(a > 0)
-                               v.y =  D / (2*a);
-                       else
-                               v.y = -D / (2*a);
-                       v.z = 0;
-               }
-       }
-       return v;
-}
-
 vector solve_shotdirection(vector myorg, vector myvel, vector eorg, vector evel, float spd, float newton_style)
 {
        vector ret;
@@ -1535,27 +1121,6 @@ string getcurrentmod()
                return argv(n - 1);
 }
 
-// from the GNU Scientific Library
-float gsl_ran_gaussian_lastvalue;
-float gsl_ran_gaussian_lastvalue_set;
-float gsl_ran_gaussian(float sigma)
-{
-       float a, b;
-       if(gsl_ran_gaussian_lastvalue_set)
-       {
-               gsl_ran_gaussian_lastvalue_set = 0;
-               return sigma * gsl_ran_gaussian_lastvalue;
-       }
-       else
-       {
-               a = random() * 2 * M_PI;
-               b = sqrt(-2 * log(random()));
-               gsl_ran_gaussian_lastvalue = cos(a) * b;
-               gsl_ran_gaussian_lastvalue_set = 1;
-               return sigma * sin(a) * b;
-       }
-}
-
 float matchacl(string acl, string str)
 {
        string t, s;
@@ -1713,57 +1278,6 @@ float get_model_parameters(string m, float sk)
        return 1;
 }
 
-float vercmp_recursive(string v1, string v2)
-{
-       float dot1, dot2;
-       string s1, s2;
-       float r;
-
-       dot1 = strstrofs(v1, ".", 0);
-       dot2 = strstrofs(v2, ".", 0);
-       if(dot1 == -1)
-               s1 = v1;
-       else
-               s1 = substring(v1, 0, dot1);
-       if(dot2 == -1)
-               s2 = v2;
-       else
-               s2 = substring(v2, 0, dot2);
-
-       r = stof(s1) - stof(s2);
-       if(r != 0)
-               return r;
-
-       r = strcasecmp(s1, s2);
-       if(r != 0)
-               return r;
-
-       if(dot1 == -1)
-               if(dot2 == -1)
-                       return 0;
-               else
-                       return -1;
-       else
-               if(dot2 == -1)
-                       return 1;
-               else
-                       return vercmp_recursive(substring(v1, dot1 + 1, 999), substring(v2, dot2 + 1, 999));
-}
-
-float vercmp(string v1, string v2)
-{
-       if(strcasecmp(v1, v2) == 0) // early out check
-               return 0;
-
-       // "git" beats all
-       if(v1 == "git")
-               return 1;
-       if(v2 == "git")
-               return -1;
-
-       return vercmp_recursive(v1, v2);
-}
-
 // x-encoding (encoding as zero length invisible string)
 const string XENCODE_2  = "xX";
 const string XENCODE_22 = "0123456789abcdefABCDEF";
@@ -1807,16 +1321,6 @@ string strlimitedlen(string input, string truncation, float strip_colors, float
                return strcat(substring(input, 0, (strlen(input) - strlen(truncation))), truncation);
 }*/
 
-#ifdef CSQC
-entity ReadCSQCEntity()
-{
-       int f = ReadShort();
-       if(f == 0)
-               return world;
-       return findfloat(world, entnum, f);
-}
-#endif
-
 float shutdown_running;
 #ifdef SVQC
 void SV_Shutdown()
@@ -1840,44 +1344,6 @@ void m_shutdown()
        cvar_settemp_restore(); // this must be done LAST, but in any case
 }
 
-const float APPROXPASTTIME_ACCURACY_REQUIREMENT = 0.05;
-#define APPROXPASTTIME_MAX (16384 * APPROXPASTTIME_ACCURACY_REQUIREMENT)
-#define APPROXPASTTIME_RANGE (64 * APPROXPASTTIME_ACCURACY_REQUIREMENT)
-// this will use the value:
-//   128
-// accuracy near zero is APPROXPASTTIME_MAX/(256*255)
-// accuracy at x is 1/derivative, i.e.
-//   APPROXPASTTIME_MAX * (1 + 256 * (dt / APPROXPASTTIME_MAX))^2 / 65536
-#ifdef SVQC
-void WriteApproxPastTime(float dst, float t)
-{
-       float dt = time - t;
-
-       // warning: this is approximate; do not resend when you don't have to!
-       // be careful with sendflags here!
-       // we want: 0 -> 0.05, 1 -> 0.1, ..., 255 -> 12.75
-
-       // map to range...
-       dt = 256 * (dt / ((APPROXPASTTIME_MAX / 256) + dt));
-
-       // round...
-       dt = rint(bound(0, dt, 255));
-
-       WriteByte(dst, dt);
-}
-#endif
-#ifdef CSQC
-float ReadApproxPastTime()
-{
-       float dt = ReadByte();
-
-       // map from range...PPROXPASTTIME_MAX / 256
-       dt = (APPROXPASTTIME_MAX / 256) * (dt / (256 - dt));
-
-       return servertime - dt;
-}
-#endif
-
 #ifndef MENUQC
 .float skeleton_bones_index;
 void Skeleton_SetBones(entity e)
index fac4269d7d2489f4991998ff82aec6e2bf6cd4d3..f0d180dad1d0bdb868baea5767806ab52208c75f 100644 (file)
@@ -101,11 +101,6 @@ float almost_in_bounds(float a, float b, float c);
 float power2of(float e);
 float log2of(float x);
 
-const string HEXDIGITS = "0123456789ABCDEF0123456789abcdef";
-#define HEXDIGIT_TO_DEC_RAW(d) (strstrofs(HEXDIGITS, (d), 0))
-#define HEXDIGIT_TO_DEC(d) ((HEXDIGIT_TO_DEC_RAW(d) | 0x10) - 0x10)
-#define DEC_TO_HEXDIGIT(d) (substring(HEXDIGITS, (d), 1))
-
 vector rgb_to_hsl(vector rgb);
 vector hsl_to_rgb(vector hsl);
 vector rgb_to_hsv(vector rgb);
@@ -211,10 +206,6 @@ const float XENCODE_LEN = 5;
 string xencode(float f);
 float xdecode(string s);
 
-#ifdef CSQC
-entity ReadCSQCEntity();
-#endif
-
 #ifndef MENUQC
 string strtolower(string s);
 #endif
index 5a6b7394ec15b7abc6aa3da4f3f695b55c808fa7..4169788148bc3616855b1db7aa060f6b057b9c1d 100644 (file)
@@ -43,6 +43,7 @@
 #include "lazy.qh"
 #include "linkedlist.qh"
 #include "log.qh"
+#include "map.qc"
 #include "math.qh"
 #include "misc.qh"
 #include "net.qh"
index e1748a936f564b6d06611929cd13e84f6cfb1281..442d8ee89ea762ce8459981487b9a4631ef745a6 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef COLOR_H
 #define COLOR_H
 
+#include "string.qh"
+
 #define colormapPaletteColor(c, isPants) colormapPaletteColor_(c, isPants, time)
 vector colormapPaletteColor_(int c, bool isPants, float t)
 {
@@ -34,4 +36,145 @@ vector colormapPaletteColor_(int c, bool isPants, float t)
        }
 }
 
+float rgb_mi_ma_to_hue(vector rgb, float mi, float ma)
+{
+       if (mi == ma)
+       {
+               return 0;
+       }
+       else if (ma == rgb.x)
+       {
+               if (rgb.y >= rgb.z) return (rgb.y - rgb.z) / (ma - mi);
+               else return (rgb.y - rgb.z) / (ma - mi) + 6;
+       }
+       else if (ma == rgb.y)
+       {
+               return (rgb.z - rgb.x) / (ma - mi) + 2;
+       }
+       else  // if(ma == rgb_z)
+       {
+               return (rgb.x - rgb.y) / (ma - mi) + 4;
+       }
+}
+
+vector hue_mi_ma_to_rgb(float hue, float mi, float ma)
+{
+       vector rgb;
+
+       hue -= 6 * floor(hue / 6);
+
+       // else if(ma == rgb_x)
+       //      hue = 60 * (rgb_y - rgb_z) / (ma - mi);
+       if (hue <= 1)
+       {
+               rgb.x = ma;
+               rgb.y = hue * (ma - mi) + mi;
+               rgb.z = mi;
+       }
+       // else if(ma == rgb_y)
+       //      hue = 60 * (rgb_z - rgb_x) / (ma - mi) + 120;
+       else if (hue <= 2)
+       {
+               rgb.x = (2 - hue) * (ma - mi) + mi;
+               rgb.y = ma;
+               rgb.z = mi;
+       }
+       else if (hue <= 3)
+       {
+               rgb.x = mi;
+               rgb.y = ma;
+               rgb.z = (hue - 2) * (ma - mi) + mi;
+       }
+       // else // if(ma == rgb_z)
+       //      hue = 60 * (rgb_x - rgb_y) / (ma - mi) + 240;
+       else if (hue <= 4)
+       {
+               rgb.x = mi;
+               rgb.y = (4 - hue) * (ma - mi) + mi;
+               rgb.z = ma;
+       }
+       else if (hue <= 5)
+       {
+               rgb.x = (hue - 4) * (ma - mi) + mi;
+               rgb.y = mi;
+               rgb.z = ma;
+       }
+       // else if(ma == rgb_x)
+       //      hue = 60 * (rgb_y - rgb_z) / (ma - mi);
+       else  // if(hue <= 6)
+       {
+               rgb.x = ma;
+               rgb.y = mi;
+               rgb.z = (6 - hue) * (ma - mi) + mi;
+       }
+
+       return rgb;
+}
+
+vector rgb_to_hsv(vector rgb)
+{
+       float mi, ma;
+       vector hsv;
+
+       mi = min(rgb.x, rgb.y, rgb.z);
+       ma = max(rgb.x, rgb.y, rgb.z);
+
+       hsv.x = rgb_mi_ma_to_hue(rgb, mi, ma);
+       hsv.z = ma;
+
+       if (ma == 0) hsv.y = 0;
+       else hsv.y = 1 - mi / ma;
+
+       return hsv;
+}
+
+vector hsv_to_rgb(vector hsv)
+{
+       return hue_mi_ma_to_rgb(hsv.x, hsv.z * (1 - hsv.y), hsv.z);
+}
+
+vector rgb_to_hsl(vector rgb)
+{
+       float mi, ma;
+       vector hsl;
+
+       mi = min(rgb.x, rgb.y, rgb.z);
+       ma = max(rgb.x, rgb.y, rgb.z);
+
+       hsl.x = rgb_mi_ma_to_hue(rgb, mi, ma);
+
+       hsl.z = 0.5 * (mi + ma);
+       if (mi == ma) hsl.y = 0;
+       else if (hsl.z <= 0.5) hsl.y = (ma - mi) / (2 * hsl.z);
+       else  // if(hsl_z > 0.5)
+               hsl.y = (ma - mi) / (2 - 2 * hsl.z);
+
+       return hsl;
+}
+
+vector hsl_to_rgb(vector hsl)
+{
+       float mi, ma, maminusmi;
+
+       if (hsl.z <= 0.5) maminusmi = hsl.y * 2 * hsl.z;
+       else maminusmi = hsl.y * (2 - 2 * hsl.z);
+
+       // hsl_z     = 0.5 * mi + 0.5 * ma
+       // maminusmi =     - mi +       ma
+       mi = hsl.z - 0.5 * maminusmi;
+       ma = hsl.z + 0.5 * maminusmi;
+
+       return hue_mi_ma_to_rgb(hsl.x, mi, ma);
+}
+
+string rgb_to_hexcolor(vector rgb)
+{
+       return strcat(
+               "^x",
+               DEC_TO_HEXDIGIT(floor(rgb.x * 15 + 0.5)),
+               DEC_TO_HEXDIGIT(floor(rgb.y * 15 + 0.5)),
+               DEC_TO_HEXDIGIT(floor(rgb.z * 15 + 0.5))
+                    );
+}
+
 #endif
index 81aaffe1380eb20b0c72c20513e21a06846f6456..d79ae11544d5467ccbc93e9d7e3bdbb954cd0b19 100644 (file)
@@ -5,7 +5,18 @@
 #include "progname.qh"
 #include "static.qh"
 
-void RegisterCvars(void(string name, string def, string desc, bool archive, string file)f) {}
+void RegisterCvars(void(string name, string def, string desc, bool archive, string file) f) {}
+
+bool cvar_value_issafe(string s)
+{
+       if (strstrofs(s, "\"", 0) >= 0) return false;
+       if (strstrofs(s, "\\", 0) >= 0) return false;
+       if (strstrofs(s, ";", 0) >= 0) return false;
+       if (strstrofs(s, "$", 0) >= 0) return false;
+       if (strstrofs(s, "\r", 0) >= 0) return false;
+       if (strstrofs(s, "\n", 0) >= 0) return false;
+       return true;
+}
 
 /** escape the string to make it safe for consoles */
 string MakeConsoleSafe(string input)
@@ -64,7 +75,7 @@ const noref vector default_vector = '0 0 0';
 #define repr_cvar_vector(x) (sprintf("%v", x))
 
 #define __AUTOCVAR(file, archive, var, type, desc, default) \
-       [[accumulate]] void RegisterCvars(void(string, string, string, bool, string)f) \
+       [[accumulate]] void RegisterCvars(void(string, string, string, bool, string) f) \
        { \
                f( #var, repr_cvar_##type(default), desc, archive, file); \
        } \
diff --git a/qcsrc/lib/map.qc b/qcsrc/lib/map.qc
new file mode 100644 (file)
index 0000000..d71c263
--- /dev/null
@@ -0,0 +1,107 @@
+#ifndef MAP_H
+#define MAP_H
+
+// Databases (hash tables)
+const float DB_BUCKETS = 8192;
+void db_save(float db, string pFilename)
+{
+       int fh = fopen(pFilename, FILE_WRITE);
+       if (fh < 0)
+       {
+               LOG_INFO(strcat("^1Can't write DB to ", pFilename));
+               return;
+       }
+       int n = buf_getsize(db);
+       fputs(fh, strcat(ftos(DB_BUCKETS), "\n"));
+       for (int i = 0; i < n; ++i)
+               fputs(fh, strcat(bufstr_get(db, i), "\n"));
+       fclose(fh);
+}
+
+int db_create()
+{
+       return buf_create();
+}
+
+void db_put(float db, string pKey, string pValue);
+
+int db_load(string pFilename)
+{
+       int db = buf_create();
+       if (db < 0) return -1;
+       int fh = fopen(pFilename, FILE_READ);
+       if (fh < 0) return db;
+       string l = fgets(fh);
+       if (stof(l) == DB_BUCKETS)
+       {
+               for (int i = 0; (l = fgets(fh)); ++i)
+               {
+                       if (l != "") bufstr_set(db, i, l);
+               }
+       }
+       else
+       {
+               // different count of buckets, or a dump?
+               // need to reorganize the database then (SLOW)
+               //
+               // note: we also parse the first line (l) in case the DB file is
+               // missing the bucket count
+               do
+               {
+                       int n = tokenizebyseparator(l, "\\");
+                       for (int j = 2; j < n; j += 2)
+                               db_put(db, argv(j - 1), uri_unescape(argv(j)));
+               }
+               while ((l = fgets(fh)));
+       }
+       fclose(fh);
+       return db;
+}
+
+void db_dump(float db, string pFilename)
+{
+       int fh = fopen(pFilename, FILE_WRITE);
+       if (fh < 0) error(strcat("Can't dump DB to ", pFilename));
+       int n = buf_getsize(db);
+       fputs(fh, "0\n");
+       for (int i = 0; i < n; ++i)
+       {
+               int m = tokenizebyseparator(bufstr_get(db, i), "\\");
+               for (int j = 2; j < m; j += 2)
+                       fputs(fh, strcat("\\", argv(j - 1), "\\", argv(j), "\n"));
+       }
+       fclose(fh);
+}
+
+void db_close(float db)
+{
+       buf_del(db);
+}
+
+string db_get(float db, string pKey)
+{
+       int h = crc16(false, pKey) % DB_BUCKETS;
+       return uri_unescape(infoget(bufstr_get(db, h), pKey));
+}
+
+void db_put(float db, string pKey, string pValue)
+{
+       int h = crc16(false, pKey) % DB_BUCKETS;
+       bufstr_set(db, h, infoadd(bufstr_get(db, h), pKey, uri_escape(pValue)));
+}
+
+void db_test()
+{
+       LOG_INFO("LOAD...\n");
+       int db = db_load("foo.db");
+       LOG_INFO("LOADED. FILL...\n");
+       for (int i = 0; i < DB_BUCKETS; ++i)
+               db_put(db, ftos(random()), "X");
+       LOG_INFO("FILLED. SAVE...\n");
+       db_save(db, "foo.db");
+       LOG_INFO("SAVED. CLOSE...\n");
+       db_close(db);
+       LOG_INFO("CLOSED.\n");
+}
+
+#endif
index ea968e84c7763c35477c4674e0ce7f68e341609c..a32e9b47c7bed891127f9da79479388d10c89541 100644 (file)
@@ -247,5 +247,57 @@ float log2of(float x)
                                        else return 0;
 }
 
+/** ax^2 + bx + c = 0 */
+vector solve_quadratic(float a, float b, float c)
+{
+       vector v;
+       float D;
+       v = '0 0 0';
+       if (a == 0)
+       {
+               if (b != 0)
+               {
+                       v.x = v.y = -c / b;
+                       v.z = 1;
+               }
+               else
+               {
+                       if (c == 0)
+                       {
+                               // actually, every number solves the equation!
+                               v.z = 1;
+                       }
+               }
+       }
+       else
+       {
+               D = b * b - 4 * a * c;
+               if (D >= 0)
+               {
+                       D = sqrt(D);
+                       if (a > 0)  // put the smaller solution first
+                       {
+                               v.x = ((-b) - D) / (2 * a);
+                               v.y = ((-b) + D) / (2 * a);
+                       }
+                       else
+                       {
+                               v.x = (-b + D) / (2 * a);
+                               v.y = (-b - D) / (2 * a);
+                       }
+                       v.z = 1;
+               }
+               else
+               {
+                       // complex solutions!
+                       D = sqrt(-D);
+                       v.x = -b / (2 * a);
+                       if (a > 0) v.y =  D / (2 * a);
+                       else v.y = -D / (2 * a);
+                       v.z = 0;
+               }
+       }
+       return v;
+}
 
 #endif
index bcb8af632850117d5741a06b4e49a1a25ac62f2a..1f8d27e80aedfebfd484c6d01374e7abf5dfd969 100644 (file)
@@ -4,12 +4,12 @@
 #ifdef SVQC
        .int Version;  // deprecated, use SendFlags
        .int SendFlags;
-       .bool(entity to, int sendflags)SendEntity;
-       .bool(entity this, entity to, int sendflags)SendEntity3;
+       .bool(entity to, int sendflags) SendEntity;
+       .bool(entity this, entity to, int sendflags) SendEntity3;
 
        bool SendEntity_self(entity to, int sendflags) { return self.SendEntity3(self, to, sendflags); }
 
-       void Net_LinkEntity(entity e, bool docull, float dt, bool(entity this, entity to, int sendflags)sendfunc)
+       void Net_LinkEntity(entity e, bool docull, float dt, bool(entity this, entity to, int sendflags) sendfunc)
        {
                if (e.classname == "") e.classname = "net_linked";
 
@@ -37,7 +37,7 @@
        .void() uncustomizeentityforclient;
        .float uncustomizeentityforclient_set;
 
-       void SetCustomizer(entity e, float()customizer, void()uncustomizer)
+       void SetCustomizer(entity e, float() customizer, void() uncustomizer)
        {
                e.customizeentityforclient = customizer;
                e.uncustomizeentityforclient = uncustomizer;
@@ -148,7 +148,17 @@ STATIC_INIT(RegisterTempEntities_renumber)
 }
 
 #ifndef MENUQC
+       const float APPROXPASTTIME_ACCURACY_REQUIREMENT = 0.05;
+       #define APPROXPASTTIME_MAX (16384 * APPROXPASTTIME_ACCURACY_REQUIREMENT)
+       #define APPROXPASTTIME_RANGE (64 * APPROXPASTTIME_ACCURACY_REQUIREMENT)
+
        #ifdef CSQC
+               entity ReadCSQCEntity()
+               {
+                       int f = ReadShort();
+                       if (f == 0) return world;
+                       return findfloat(world, entnum, f);
+               }
                int ReadInt24_t()
                {
                        int v = ReadShort() << 8; // note: this is signed
@@ -171,6 +181,17 @@ STATIC_INIT(RegisterTempEntities_renumber)
                        v.z = ReadInt24_t();
                        return v;
                }
+
+               float ReadApproxPastTime()
+               {
+                       float dt = ReadByte();
+
+                       // map from range...PPROXPASTTIME_MAX / 256
+                       dt = (APPROXPASTTIME_MAX / 256) * (dt / (256 - dt));
+
+                       return servertime - dt;
+               }
+
        #else
                const int MSG_ENTITY = 5;
 
@@ -192,10 +213,44 @@ STATIC_INIT(RegisterTempEntities_renumber)
                        WriteInt24_t(dst, val.z);
                }
 
+               // this will use the value:
+               //   128
+               // accuracy near zero is APPROXPASTTIME_MAX/(256*255)
+               // accuracy at x is 1/derivative, i.e.
+               //   APPROXPASTTIME_MAX * (1 + 256 * (dt / APPROXPASTTIME_MAX))^2 / 65536
+               void WriteApproxPastTime(float dst, float t)
+               {
+                       float dt = time - t;
+
+                       // warning: this is approximate; do not resend when you don't have to!
+                       // be careful with sendflags here!
+                       // we want: 0 -> 0.05, 1 -> 0.1, ..., 255 -> 12.75
+
+                       // map to range...
+                       dt = 256 * (dt / ((APPROXPASTTIME_MAX / 256) + dt));
+
+                       // round...
+                       dt = rint(bound(0, dt, 255));
+
+                       WriteByte(dst, dt);
+               }
+
                // allow writing to also pass through to spectators (like so spectators see the same centerprints as players for example)
-        #define WRITESPECTATABLE_MSG_ONE_VARNAME(varname,statement) entity varname; varname = msg_entity; FOR_EACH_REALCLIENT(msg_entity) if(msg_entity == varname || (msg_entity.classname == STR_SPECTATOR && msg_entity.enemy == varname)) statement msg_entity = varname
-        #define WRITESPECTATABLE_MSG_ONE(statement) WRITESPECTATABLE_MSG_ONE_VARNAME(oldmsg_entity, statement)
-        #define WRITESPECTATABLE(msg,statement) if(msg == MSG_ONE) { WRITESPECTATABLE_MSG_ONE(statement); } else statement float WRITESPECTATABLE_workaround = 0
+               #define WRITESPECTATABLE_MSG_ONE_VARNAME(varname, statement) \
+                       entity varname; varname = msg_entity; \
+                       FOR_EACH_REALCLIENT(msg_entity) \
+                       if (msg_entity == varname || (msg_entity.classname == STR_SPECTATOR && msg_entity.enemy == varname)) \
+                               statement msg_entity = varname
+               #define WRITESPECTATABLE_MSG_ONE(statement) \
+                       do \
+                       { \
+                               WRITESPECTATABLE_MSG_ONE_VARNAME(oldmsg_entity, statement); \
+                       } \
+                       while (0)
+               #define WRITESPECTATABLE(msg, statement) \
+                       if (msg == MSG_ONE) WRITESPECTATABLE_MSG_ONE(statement); \
+                       else \
+                               statement float WRITESPECTATABLE_workaround = 0
        #endif
 #endif
 
index 1b4b6bbbaebae3fd7f9e0f0967c0d1899b7b2c30..a0d6f35db34b9ba8e76ba2af2c1aa3457779d1bb 100644 (file)
@@ -3,6 +3,7 @@
 
 #include "misc.qh"
 #include "nil.qh"
+#include "static.qh"
 
 #ifdef MENUQC
        #define NULL (null_entity)
index be0f80a089c15b5057f25c974a1533963ba79c57..aff961c55da56b9dcde016c90335dbee7026d5e9 100644 (file)
@@ -66,6 +66,26 @@ float DistributeEvenly_GetRandomized(float weight)
        return f;
 }
 
+// from the GNU Scientific Library
+float gsl_ran_gaussian_lastvalue;
+float gsl_ran_gaussian_lastvalue_set;
+float gsl_ran_gaussian(float sigma)
+{
+       if (gsl_ran_gaussian_lastvalue_set)
+       {
+               gsl_ran_gaussian_lastvalue_set = 0;
+               return sigma * gsl_ran_gaussian_lastvalue;
+       }
+       else
+       {
+               float a = random() * 2 * M_PI;
+               float b = sqrt(-2 * log(random()));
+               gsl_ran_gaussian_lastvalue = cos(a) * b;
+               gsl_ran_gaussian_lastvalue_set = 1;
+               return sigma * sin(a) * b;
+       }
+}
+
 // prandom - PREDICTABLE random number generator (not seeded yet)
 
 #ifdef USE_PRANDOM
index 048b5c721b9d7365b60240109b8b06495ce55881..6f61155800d5af390011bd645b005655b61e14ae 100644 (file)
@@ -1,6 +1,10 @@
 #ifndef STRING_H
 #define STRING_H
 
+#include "nil.qh"
+#include "sort.qh"
+#include "oo.qh"
+
 #ifndef SVQC
        float stringwidth_colors(string s, vector theSize)
        {
@@ -13,8 +17,6 @@
        }
 #endif
 
-// Timer (#5)
-//
 // TODO: macro
 string seconds_tostring(float sec)
 {
@@ -23,6 +25,37 @@ string seconds_tostring(float sec)
        return sprintf("%d:%02d", minutes, sec);
 }
 
+string format_time(float seconds)
+{
+       seconds = floor(seconds + 0.5);
+       float days = floor(seconds / 864000);
+       seconds -= days * 864000;
+       float hours = floor(seconds / 36000);
+       seconds -= hours * 36000;
+       float minutes = floor(seconds / 600);
+       seconds -= minutes * 600;
+       if (days > 0) return sprintf(_("%d days, %02d:%02d:%02d"), days, hours, minutes, seconds);
+       else return sprintf(_("%02d:%02d:%02d"), hours, minutes, seconds);
+}
+
+string mmsss(float tenths)
+{
+       tenths = floor(tenths + 0.5);
+       float minutes = floor(tenths / 600);
+       tenths -= minutes * 600;
+       string s = ftos(1000 + tenths);
+       return strcat(ftos(minutes), ":", substring(s, 1, 2), ".", substring(s, 3, 1));
+}
+
+string mmssss(float hundredths)
+{
+       hundredths = floor(hundredths + 0.5);
+       float minutes = floor(hundredths / 6000);
+       hundredths -= minutes * 6000;
+       string s = ftos(10000 + hundredths);
+       return strcat(ftos(minutes), ":", substring(s, 1, 2), ".", substring(s, 3, 2));
+}
+
 int ColorTranslateMode;
 
 string ColorTranslateRGB(string s)
@@ -209,4 +242,79 @@ bool isInvisibleString(string s)
        return true;
 }
 
+// Multiline text file buffers
+
+int buf_load(string pFilename)
+{
+       int buf = buf_create();
+       if (buf < 0) return -1;
+       int fh = fopen(pFilename, FILE_READ);
+       if (fh < 0)
+       {
+               buf_del(buf);
+               return -1;
+       }
+       string l;
+       for (int i = 0; (l = fgets(fh)); ++i)
+               bufstr_set(buf, i, l);
+       fclose(fh);
+       return buf;
+}
+
+void buf_save(float buf, string pFilename)
+{
+       int fh = fopen(pFilename, FILE_WRITE);
+       if (fh < 0) error(strcat("Can't write buf to ", pFilename));
+       int n = buf_getsize(buf);
+       for (int i = 0; i < n; ++i)
+               fputs(fh, strcat(bufstr_get(buf, i), "\n"));
+       fclose(fh);
+}
+
+/**
+ * converts a number to a string with the indicated number of decimals
+ * works for up to 10 decimals!
+ */
+string ftos_decimals(float number, int decimals)
+{
+       // inhibit stupid negative zero
+       if (number == 0) number = 0;
+       // we have sprintf...
+       return sprintf("%.*f", decimals, number);
+}
+
+int vercmp_recursive(string v1, string v2)
+{
+       int dot1 = strstrofs(v1, ".", 0);
+       int dot2 = strstrofs(v2, ".", 0);
+       string s1 = (dot1 == -1) ? v1 : substring(v1, 0, dot1);
+       string s2 = (dot2 == -1) ? v2 : substring(v2, 0, dot2);
+
+       float r;
+       r = stof(s1) - stof(s2);
+       if (r != 0) return r;
+
+       r = strcasecmp(s1, s2);
+       if (r != 0) return r;
+
+       if (dot1 == -1) return (dot2 == -1) ? 0 : -1;
+       else return (dot2 == -1) ? 1 : vercmp_recursive(substring(v1, dot1 + 1, 999), substring(v2, dot2 + 1, 999));
+}
+
+int vercmp(string v1, string v2)
+{
+       if (strcasecmp(v1, v2) == 0) return 0;  // early out check
+
+       // "git" beats all
+       if (v1 == "git") return 1;
+       if (v2 == "git") return -1;
+
+       return vercmp_recursive(v1, v2);
+}
+
+const string HEXDIGITS = "0123456789ABCDEF0123456789abcdef";
+#define HEXDIGIT_TO_DEC_RAW(d) (strstrofs(HEXDIGITS, (d), 0))
+#define HEXDIGIT_TO_DEC(d) ((HEXDIGIT_TO_DEC_RAW(d) | 0x10) - 0x10)
+#define DEC_TO_HEXDIGIT(d) (substring(HEXDIGITS, (d), 1))
+
 #endif
diff --git a/qcsrc/menu/classes.qc b/qcsrc/menu/classes.qc
new file mode 100644 (file)
index 0000000..9454a31
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef CLASSES_H
+#define CLASSES_H
+
+#include "classes.inc"
+#define IMPLEMENTATION
+#include "classes.inc"
+#undef IMPLEMENTATION
+
+#endif
index 6293241f12abc5586bb133c15df4e098d22b2d94..5a5fe26a68ea7b191497c89d9793c8902d9abbb8 100644 (file)
@@ -1,7 +1,7 @@
 #include "menu_cmd.qh"
 
 #include "../menu.qh"
-#include "../oo/classes.qc"
+#include "../classes.qc"
 
 #include "../mutators/events.qh"
 
index 7edc6eff50d8a4c172371d19c026e10fecba6b46..b2ce50382a5e16b7a647085f93cd59ad16aede0f 100644 (file)
@@ -27,16 +27,6 @@ void draw_reset(float cw, float ch, float ox, float oy)
        draw_endBoldFont();
 }
 
-void draw_beginBoldFont()
-{
-       drawfont = FONT_USER+3;
-}
-
-void draw_endBoldFont()
-{
-       drawfont = FONT_USER+0;
-}
-
 vector globalToBox(vector v, vector theOrigin, vector theScale)
 {
        v -= theOrigin;
index 873ccb6df31e3695760db9b33002da2fe1a23665..bb12e29c8162efc889bbf84f1c5109c8113e01cf 100644 (file)
@@ -10,8 +10,8 @@ vector draw_scale;
 float draw_alpha;
 
 void draw_reset(float cw, float ch, float ox, float oy);
-void draw_beginBoldFont();
-void draw_endBoldFont();
+#define draw_beginBoldFont() do { drawfont = FONT_USER + 3; } while (0)
+#define draw_endBoldFont() do { drawfont = FONT_USER + 0; } while (0)
 void draw_setMousePointer(string pic, vector theSize, vector theOffset);
 void draw_drawMousePointer(vector where);
 
index bd5a24fee05e2af34c05f9a2bd0a8611ef7e6de4..ad2b000f93bfbeddb9c100a00c44c8e77f0ac9ce 100644 (file)
@@ -1,5 +1,5 @@
 #include "menu.qh"
-#include "oo/classes.qc"
+#include "classes.qc"
 #include "xonotic/util.qh"
 
 #include "../common/items/all.qh"
diff --git a/qcsrc/menu/oo/classes.qc b/qcsrc/menu/oo/classes.qc
deleted file mode 100644 (file)
index 16a830d..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef CLASSES_H
-#define CLASSES_H
-
-#include "../classes.inc"
-#define IMPLEMENTATION
-#include "../classes.inc"
-#undef IMPLEMENTATION
-
-#endif
index ae221de272b18dae865438e36afdfef9786ce0b9..5282a01888d791d9d61e47d4e9f7451fc6846282 100644 (file)
@@ -2,7 +2,7 @@
 
 #define world NULL
 
-#include "oo/classes.qc"
+#include "classes.qc"
 
 #include "draw.qc"
 #include "menu.qc"