}
}
-// 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;
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)
{
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.
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;
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;
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";
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()
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)
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);
string xencode(float f);
float xdecode(string s);
-#ifdef CSQC
-entity ReadCSQCEntity();
-#endif
-
#ifndef MENUQC
string strtolower(string s);
#endif
#include "lazy.qh"
#include "linkedlist.qh"
#include "log.qh"
+#include "map.qc"
#include "math.qh"
#include "misc.qh"
#include "net.qh"
#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)
{
}
}
+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
#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)
#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); \
} \
--- /dev/null
+#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
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
#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";
.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;
}
#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
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;
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
#include "misc.qh"
#include "nil.qh"
+#include "static.qh"
#ifdef MENUQC
#define NULL (null_entity)
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
#ifndef STRING_H
#define STRING_H
+#include "nil.qh"
+#include "sort.qh"
+#include "oo.qh"
+
#ifndef SVQC
float stringwidth_colors(string s, vector theSize)
{
}
#endif
-// Timer (#5)
-//
// TODO: macro
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)
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
--- /dev/null
+#ifndef CLASSES_H
+#define CLASSES_H
+
+#include "classes.inc"
+#define IMPLEMENTATION
+#include "classes.inc"
+#undef IMPLEMENTATION
+
+#endif
#include "menu_cmd.qh"
#include "../menu.qh"
-#include "../oo/classes.qc"
+#include "../classes.qc"
#include "../mutators/events.qh"
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;
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);
#include "menu.qh"
-#include "oo/classes.qc"
+#include "classes.qc"
#include "xonotic/util.qh"
#include "../common/items/all.qh"
+++ /dev/null
-#ifndef CLASSES_H
-#define CLASSES_H
-
-#include "../classes.inc"
-#define IMPLEMENTATION
-#include "../classes.inc"
-#undef IMPLEMENTATION
-
-#endif
#define world NULL
-#include "oo/classes.qc"
+#include "classes.qc"
#include "draw.qc"
#include "menu.qc"