#include "constants.qh"
#include "../client/mutators/events.qh"
#include "mapinfo.qh"
- #include "notifications.qh"
- #include "deathtypes.qh"
+ #include "notifications/all.qh"
+ #include <common/deathtypes/all.qh>
#elif defined(MENUQC)
#elif defined(SVQC)
#include "constants.qh"
#include "../server/autocvars.qh"
#include "../server/defs.qh"
#include "../server/mutators/events.qh"
- #include "notifications.qh"
- #include "deathtypes.qh"
+ #include "notifications/all.qh"
+ #include <common/deathtypes/all.qh>
#include "mapinfo.qh"
#endif
+#ifdef GAMEQC
+/*
+* Get "real" origin, in worldspace, even if ent is attached to something else.
+*/
+vector real_origin(entity ent)
+{
+ vector v = ((ent.absmin + ent.absmax) * 0.5);
+ entity e = ent.tag_entity;
+
+ while(e)
+ {
+ v = v + ((e.absmin + e.absmax) * 0.5);
+ e = e.tag_entity;
+ }
+
+ return v;
+}
+#endif
+
string wordwrap_buffer;
void wordwrap_buffer_put(string s)
return r;
}
-#ifndef MENUQC
-#ifndef CSQC
+#ifdef SVQC
+entity _wordwrap_buffer_sprint_ent;
void wordwrap_buffer_sprint(string s)
-{SELFPARAM();
+{
wordwrap_buffer = strcat(wordwrap_buffer, s);
if(s == "\n")
{
- sprint(self, wordwrap_buffer);
+ sprint(_wordwrap_buffer_sprint_ent, wordwrap_buffer);
wordwrap_buffer = "";
}
}
-void wordwrap_sprint(string s, float l)
-{SELFPARAM();
+void wordwrap_sprint(entity to, string s, float l)
+{
wordwrap_buffer = "";
+ _wordwrap_buffer_sprint_ent = to;
wordwrap_cb(s, l, wordwrap_buffer_sprint);
+ _wordwrap_buffer_sprint_ent = NULL;
if(wordwrap_buffer != "")
- sprint(self, strcat(wordwrap_buffer, "\n"));
+ sprint(to, strcat(wordwrap_buffer, "\n"));
wordwrap_buffer = "";
return;
}
#endif
-#endif
#ifndef SVQC
string draw_UseSkinFor(string pic)
}
}
-// 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;
float lengthLogTable[128];
-float invertLengthLog(float x)
+float invertLengthLog(float dist)
{
int l, r, m;
- if(x >= lengthLogTable[127])
+ if(dist >= lengthLogTable[127])
return 127;
- if(x <= lengthLogTable[0])
+ if(dist <= lengthLogTable[0])
return 0;
l = 0;
while(r - l > 1)
{
m = floor((l + r) / 2);
- if(lengthLogTable[m] < x)
+ if(lengthLogTable[m] < dist)
l = m;
else
r = m;
}
// now: r is >=, l is <
- float lerr = (x - lengthLogTable[l]);
- float rerr = (lengthLogTable[r] - x);
+ float lerr = (dist - lengthLogTable[l]);
+ float rerr = (lengthLogTable[r] - dist);
if(lerr < rerr)
return l;
return r;
if(data == 0)
return '0 0 0';
float p = (data & 0xF000) / 0x1000;
- float y = (data & 0x0F80) / 0x80;
+ float q = (data & 0x0F80) / 0x80;
int len = (data & 0x007F);
- //print("\ndecompress: p ", ftos(p)); print("y ", ftos(y)); print("len ", ftos(len), "\n");
+ //print("\ndecompress: p ", ftos(p)); print("q ", ftos(q)); print("len ", ftos(len), "\n");
if(p == 0)
{
out.x = 0;
out.y = 0;
- if(y == 31)
+ if(q == 31)
out.z = -1;
else
out.z = +1;
}
else
{
- y = .19634954084936207740 * y;
+ q = .19634954084936207740 * q;
p = .19634954084936207740 * p - 1.57079632679489661922;
- out.x = cos(y) * cos(p);
- out.y = sin(y) * cos(p);
+ out.x = cos(q) * cos(p);
+ out.y = sin(q) * cos(p);
out.z = -sin(p);
}
{
vector ang;
float p, y, len;
- if(vlen(vec) == 0)
+ if(vec == '0 0 0')
return 0;
//print("compress: ", vtos(vec), "\n");
ang = vectoangles(vec);
return (p * 0x1000) + (y * 0x80) + len;
}
-void compressShortVector_init()
+STATIC_INIT(compressShortVector)
{
float l = 1;
- float f = pow(2, 1/8);
+ float f = (2 ** (1/8));
int i;
for(i = 0; i < 128; ++i)
{
}
}
-#ifndef MENUQC
+#ifdef GAMEQC
float CheckWireframeBox(entity forent, vector v0, vector dvx, vector dvy, vector dvz)
{
traceline(v0, v0 + dvx, true, forent); if(trace_fraction < 1) return 0;
n = tokenize_console(neworder);
for(w = to; w >= from; --w)
{
+ int wflags = Weapons_from(w).spawnflags;
+ if((wflags & WEP_FLAG_HIDDEN) && (wflags & WEP_FLAG_MUTATORBLOCKED) && !(wflags & WEP_FLAG_NORMAL))
+ continue;
for(i = 0; i < n; ++i)
if(stof(argv(i)) == w)
break;
string mapPriorityList(string order, string(string) mapfunc)
{
string neworder;
- float i, n;
+ float n;
n = tokenize_console(order);
neworder = "";
- for(i = 0; i < n; ++i)
+ for(float i = 0; i < n; ++i)
neworder = strcat(neworder, mapfunc(argv(i)), " ");
return substring(neworder, 0, strlen(neworder) - 1);
string swapInPriorityList(string order, float i, float j)
{
- string s;
- float w, n;
-
- n = tokenize_console(order);
+ float n = tokenize_console(order);
if(i >= 0 && i < n && j >= 0 && j < n && i != j)
{
- s = "";
- for(w = 0; w < n; ++w)
+ string s = "";
+ for(float w = 0; w < n; ++w)
{
if(w == i)
s = strcat(s, argv(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
+#ifdef GAMEQC
void get_mi_min_max(float mode)
{
vector mi, ma;
mi_min = mi;
mi_max = ma;
- MapInfo_Get_ByName(mi_shortname, 0, 0);
+ MapInfo_Get_ByName(mi_shortname, 0, NULL);
if(MapInfo_Map_mins.x < MapInfo_Map_maxs.x)
{
mi_min = MapInfo_Map_mins;
'0 1 0' * ma.y + '0 0 1' * ma.z,
'1 0 0' * ma.x,
MOVE_WORLDONLY,
- world);
+ NULL);
if(!trace_startsolid)
mi_min.x = trace_endpos.x;
'1 0 0' * ma.x + '0 0 1' * ma.z,
'0 1 0' * ma.y,
MOVE_WORLDONLY,
- world);
+ NULL);
if(!trace_startsolid)
mi_min.y = trace_endpos.y;
'1 0 0' * ma.x + '0 1 0' * ma.y,
'0 0 1' * ma.z,
MOVE_WORLDONLY,
- world);
+ NULL);
if(!trace_startsolid)
mi_min.z = trace_endpos.z;
'0 1 0' * ma.y + '0 0 1' * ma.z,
'1 0 0' * mi.x,
MOVE_WORLDONLY,
- world);
+ NULL);
if(!trace_startsolid)
mi_max.x = trace_endpos.x;
'1 0 0' * ma.x + '0 0 1' * ma.z,
'0 1 0' * mi.y,
MOVE_WORLDONLY,
- world);
+ NULL);
if(!trace_startsolid)
mi_max.y = trace_endpos.y;
'1 0 0' * ma.x + '0 1 0' * ma.y,
'0 0 1' * mi.z,
MOVE_WORLDONLY,
- world);
+ NULL);
if(!trace_startsolid)
mi_max.z = trace_endpos.z;
}
float cvar_settemp(string tmp_cvar, string tmp_value)
{
float created_saved_value;
- entity e;
created_saved_value = 0;
if (!(tmp_cvar || tmp_value))
{
- LOG_TRACE("Error: Invalid usage of cvar_settemp(string, string); !\n");
+ LOG_TRACE("Error: Invalid usage of cvar_settemp(string, string); !");
return 0;
}
return 0;
}
- for(e = world; (e = find(e, classname, "saved_cvar_value")); )
- if(e.netname == tmp_cvar)
- created_saved_value = -1; // skip creation
+ IL_EACH(g_saved_cvars, it.netname == tmp_cvar,
+ {
+ created_saved_value = -1; // skip creation
+ break; // no need to continue
+ });
if(created_saved_value != -1)
{
// creating a new entity to keep track of this cvar
- e = spawn();
- e.classname = "saved_cvar_value";
+ entity e = new_pure(saved_cvar_value);
+ IL_PUSH(g_saved_cvars, e);
e.netname = strzone(tmp_cvar);
e.message = strzone(cvar_string(tmp_cvar));
created_saved_value = 1;
return created_saved_value;
}
-float cvar_settemp_restore()
+int cvar_settemp_restore()
{
- float i = 0;
- entity e = world;
+ int j = 0;
+ // FIXME this new-style loop fails!
+#if 0
+ FOREACH_ENTITY_CLASS("saved_cvar_value", true,
+ {
+ if(cvar_type(it.netname))
+ {
+ cvar_set(it.netname, it.message);
+ strunzone(it.netname);
+ strunzone(it.message);
+ delete(it);
+ ++j;
+ }
+ else
+ LOG_INFOF("Error: cvar %s doesn't exist anymore! It can still be restored once it's manually recreated.\n", it.netname);
+ });
+
+#else
+ entity e = NULL;
while((e = find(e, classname, "saved_cvar_value")))
{
if(cvar_type(e.netname))
{
cvar_set(e.netname, e.message);
- remove(e);
- ++i;
+ delete(e);
+ ++j;
}
else
- LOG_INFOF("Error: cvar %s doesn't exist anymore! It can still be restored once it's manually recreated.\n", e.netname);
+ print(sprintf("Error: cvar %s doesn't exist anymore! It can still be restored once it's manually recreated.\n", e.netname));
}
+#endif
- return i;
+ return j;
}
-float rgb_mi_ma_to_hue(vector rgb, float mi, float ma)
+bool isCaretEscaped(string theText, float pos)
{
- 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;
+ int i = 0;
+ while(pos - i >= 1 && substring(theText, pos - i - 1, 1) == "^")
+ ++i;
+ return (i & 1);
}
-vector hue_mi_ma_to_rgb(float hue, float mi, float ma)
+int skipIncompleteTag(string theText, float pos, int len)
{
- vector rgb;
-
- hue -= 6 * floor(hue / 6);
+ int tag_start = -1;
- //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)
+ if(substring(theText, pos - 1, 1) == "^")
{
- 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;
+ if(isCaretEscaped(theText, pos - 1) || pos >= len)
+ return 0;
+
+ int ch = str2chr(theText, pos);
+ if(ch >= '0' && ch <= '9')
+ return 1; // ^[0-9] color code found
+ else if (ch == 'x')
+ tag_start = pos - 1; // ^x tag found
+ else
+ return 0;
}
- else if(hue <= 5)
+ else
{
- rgb.x = (hue - 4) * (ma - mi) + mi;
- rgb.y = mi;
- rgb.z = ma;
+ for(int i = 2; pos - i >= 0 && i <= 4; ++i)
+ {
+ if(substring(theText, pos - i, 2) == "^x")
+ {
+ tag_start = pos - i; // ^x tag found
+ break;
+ }
+ }
}
- //else if(ma == rgb_x)
- // hue = 60 * (rgb_y - rgb_z) / (ma - mi);
- else // if(hue <= 6)
+
+ if(tag_start >= 0)
{
- rgb.x = ma;
- rgb.y = mi;
- rgb.z = (6 - hue) * (ma - mi) + mi;
+ if(tag_start + 5 < len)
+ if(IS_HEXDIGIT(substring(theText, tag_start + 2, 1)))
+ if(IS_HEXDIGIT(substring(theText, tag_start + 3, 1)))
+ if(IS_HEXDIGIT(substring(theText, tag_start + 4, 1)))
+ {
+ if(!isCaretEscaped(theText, tag_start))
+ return 5 - (pos - tag_start); // ^xRGB color code found
+ }
}
-
- 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))
- );
+ return 0;
}
float textLengthUpToWidth(string theText, float maxWidth, vector theSize, textLengthUpToWidth_widthFunction_t w)
if(w(theText, theSize) <= maxWidth)
return strlen(theText); // yeah!
+ bool colors = (w("^7", theSize) == 0);
+
// binary search for right place to cut string
- float ch;
- float left, right, middle; // this always works
+ int len, left, right, middle;
left = 0;
- right = strlen(theText); // this always fails
+ right = len = strlen(theText);
+ int ofs = 0;
do
{
middle = floor((left + right) / 2);
- if(w(substring(theText, 0, middle), theSize) <= maxWidth)
- left = middle;
+ if(colors)
+ ofs = skipIncompleteTag(theText, middle, len);
+ if(w(substring(theText, 0, middle + ofs), theSize) <= maxWidth)
+ left = middle + ofs;
else
right = middle;
}
while(left < right - 1);
- if(w("^7", theSize) == 0) // detect color codes support in the width function
- {
- // NOTE: when color codes are involved, this binary search is,
- // mathematically, BROKEN. However, it is obviously guaranteed to
- // terminate, as the range still halves each time - but nevertheless, it is
- // guaranteed that it finds ONE valid cutoff place (where "left" is in
- // range, and "right" is outside).
-
- // terencehill: the following code detects truncated ^xrgb tags (e.g. ^x or ^x4)
- // and decrease left on the basis of the chars detected of the truncated tag
- // Even if the ^xrgb tag is not complete/correct, left is decreased
- // (sometimes too much but with a correct result)
- // it fixes also ^[0-9]
- while(left >= 1 && substring(theText, left-1, 1) == "^")
- left-=1;
-
- if (left >= 2 && substring(theText, left-2, 2) == "^x") // ^x/
- left-=2;
- else if (left >= 3 && substring(theText, left-3, 2) == "^x")
- {
- ch = str2chr(theText, left-1);
- if( (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F') ) // ^xr/
- left-=3;
- }
- else if (left >= 4 && substring(theText, left-4, 2) == "^x")
- {
- ch = str2chr(theText, left-2);
- if ( (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F') )
- {
- ch = str2chr(theText, left-1);
- if ( (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F') ) // ^xrg/
- left-=4;
- }
- }
- }
-
return left;
}
if(w(theText) <= maxWidth)
return strlen(theText); // yeah!
+ bool colors = (w("^7") == 0);
+
// binary search for right place to cut string
- float ch;
- float left, right, middle; // this always works
+ int len, left, right, middle;
left = 0;
- right = strlen(theText); // this always fails
+ right = len = strlen(theText);
+ int ofs = 0;
do
{
middle = floor((left + right) / 2);
- if(w(substring(theText, 0, middle)) <= maxWidth)
- left = middle;
+ if(colors)
+ ofs = skipIncompleteTag(theText, middle, len);
+ if(w(substring(theText, 0, middle + ofs)) <= maxWidth)
+ left = middle + ofs;
else
right = middle;
}
while(left < right - 1);
- if(w("^7") == 0) // detect color codes support in the width function
- {
- // NOTE: when color codes are involved, this binary search is,
- // mathematically, BROKEN. However, it is obviously guaranteed to
- // terminate, as the range still halves each time - but nevertheless, it is
- // guaranteed that it finds ONE valid cutoff place (where "left" is in
- // range, and "right" is outside).
-
- // terencehill: the following code detects truncated ^xrgb tags (e.g. ^x or ^x4)
- // and decrease left on the basis of the chars detected of the truncated tag
- // Even if the ^xrgb tag is not complete/correct, left is decreased
- // (sometimes too much but with a correct result)
- // it fixes also ^[0-9]
- while(left >= 1 && substring(theText, left-1, 1) == "^")
- left-=1;
-
- if (left >= 2 && substring(theText, left-2, 2) == "^x") // ^x/
- left-=2;
- else if (left >= 3 && substring(theText, left-3, 2) == "^x")
- {
- ch = str2chr(theText, left-1);
- if( (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F') ) // ^xr/
- left-=3;
- }
- else if (left >= 4 && substring(theText, left-4, 2) == "^x")
- {
- ch = str2chr(theText, left-2);
- if ( (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F') )
- {
- ch = str2chr(theText, left-1);
- if ( (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F') ) // ^xrg/
- left-=4;
- }
- }
- }
-
return left;
}
if (start == -1) // no caret found
return "";
int len = strlen(s)-1;
- int i;
- for(i = len; i >= start; --i)
+ for(int i = len; i >= start; --i)
{
if(substring(s, i, 1) != "^")
continue;
if (carets & 1)
{
if(i+1 <= len)
- if(strstrofs("0123456789", substring(s, i+1, 1), 0) >= 0)
+ if(IS_DIGIT(substring(s, i+1, 1)))
return substring(s, i, 2);
if(i+4 <= len)
if(substring(s, i+1, 1) == "x")
- if(strstrofs("0123456789abcdefABCDEF", substring(s, i+2, 1), 0) >= 0)
- if(strstrofs("0123456789abcdefABCDEF", substring(s, i+3, 1), 0) >= 0)
- if(strstrofs("0123456789abcdefABCDEF", substring(s, i+4, 1), 0) >= 0)
+ if(IS_HEXDIGIT(substring(s, i + 2, 1)))
+ if(IS_HEXDIGIT(substring(s, i + 3, 1)))
+ if(IS_HEXDIGIT(substring(s, i + 4, 1)))
return substring(s, i, 5);
}
i -= carets; // this also skips one char before the carets
return strcat(substring(theText, 0, textLengthUpToLength(theText, maxWidth - tw("..."), tw)), "...");
}
-float isGametypeInFilter(float gt, float tp, float ts, string pattern)
+float isGametypeInFilter(Gametype gt, float tp, float ts, string pattern)
{
string subpattern, subpattern2, subpattern3, subpattern4;
subpattern = strcat(",", MapInfo_Type_ToString(gt), ",");
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;
float compressShotOrigin(vector v)
{
- float x, y, z;
- x = rint(v.x * 2);
- y = rint(v.y * 4) + 128;
- z = rint(v.z * 4) + 128;
- if(x > 255 || x < 0)
+ float rx = rint(v.x * 2);
+ float ry = rint(v.y * 4) + 128;
+ float rz = rint(v.z * 4) + 128;
+ if(rx > 255 || rx < 0)
{
- LOG_INFO("shot origin ", vtos(v), " x out of bounds\n");
- x = bound(0, x, 255);
+ LOG_DEBUG("shot origin ", vtos(v), " x out of bounds\n");
+ rx = bound(0, rx, 255);
}
- if(y > 255 || y < 0)
+ if(ry > 255 || ry < 0)
{
- LOG_INFO("shot origin ", vtos(v), " y out of bounds\n");
- y = bound(0, y, 255);
+ LOG_DEBUG("shot origin ", vtos(v), " y out of bounds\n");
+ ry = bound(0, ry, 255);
}
- if(z > 255 || z < 0)
+ if(rz > 255 || rz < 0)
{
- LOG_INFO("shot origin ", vtos(v), " z out of bounds\n");
- z = bound(0, z, 255);
+ LOG_DEBUG("shot origin ", vtos(v), " z out of bounds\n");
+ rz = bound(0, rz, 255);
}
- return x * 0x10000 + y * 0x100 + z;
+ return rx * 0x10000 + ry * 0x100 + rz;
}
vector decompressShotOrigin(int f)
{
return v;
}
-#ifndef MENUQC
+#ifdef GAMEQC
vector healtharmor_maxdamage(float h, float a, float armorblock, int deathtype)
{
// NOTE: we'll always choose the SMALLER value...
float healthdamage, armordamage, armorideal;
- if (deathtype == DEATH_DROWN) // Why should armor help here...
+ if (DEATH_IS(deathtype, DEATH_DROWN)) // Why should armor help here...
armorblock = 0;
vector v;
healthdamage = (h - 1) / (1 - armorblock); // damage we can take if we could use more health
vector healtharmor_applydamage(float a, float armorblock, int deathtype, float damage)
{
vector v;
- if (deathtype == DEATH_DROWN) // Why should armor help here...
+ if (DEATH_IS(deathtype, DEATH_DROWN)) // Why should armor help here...
armorblock = 0;
v.y = bound(0, damage * armorblock, a); // save
v.x = bound(0, damage - v.y, damage); // take
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;
get_model_parameters_bone_aimweight[i] = 0;
}
get_model_parameters_fixbone = 0;
+ get_model_parameters_hidden = false;
-#ifndef MENUQC
+#ifdef GAMEQC
MUTATOR_CALLHOOK(ClearModelParams);
#endif
get_model_parameters_bone_upperbody = s;
if(c == "bone_weapon")
get_model_parameters_bone_weapon = s;
- #ifndef MENUQC
+ #ifdef GAMEQC
MUTATOR_CALLHOOK(GetModelParams, c, s);
#endif
for(int i = 0; i < MAX_AIM_BONES; ++i)
}
if(c == "fixbone")
get_model_parameters_fixbone = stof(s);
+ if(c == "hidden")
+ get_model_parameters_hidden = stob(s);
}
while((s = fgets(fh)))
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()
{
shutdown_running = 1;
Shutdown();
+ shutdownhooks();
}
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
+#ifdef GAMEQC
.float skeleton_bones_index;
void Skeleton_SetBones(entity e)
{
// start with a 1-element queue
queue_start = queue_end = e;
- queue_end.(fld) = world;
+ queue_end.(fld) = NULL;
queue_end.FindConnectedComponent_processing = 1;
// for each queued item:
{
// find all neighbors of queue_start
entity t;
- for(t = world; (t = nxt(t, queue_start, pass)); )
+ for(t = NULL; (t = nxt(t, queue_start, pass)); )
{
if(t.FindConnectedComponent_processing)
continue;
// it is connected? ADD IT. It will look for neighbors soon too.
queue_end.(fld) = t;
queue_end = t;
- queue_end.(fld) = world;
+ queue_end.(fld) = NULL;
queue_end.FindConnectedComponent_processing = 1;
}
}
queue_start.FindConnectedComponent_processing = 0;
}
-#ifndef MENUQC
+#ifdef GAMEQC
vector animfixfps(entity e, vector a, vector b)
{
// multi-frame anim: keep as-is
if(a.y == 1)
{
- float dur;
- dur = frameduration(e.modelindex, a.x);
- if(dur <= 0 && b.y)
+ float dur = frameduration(e.modelindex, a.x);
+ if (dur <= 0 && b.y)
{
a = b;
dur = frameduration(e.modelindex, a.x);
}
- if(dur > 0)
+ if (dur > 0)
a.z = 1.0 / dur;
}
return a;
}
#endif
-#ifdef SVQC
-void dedicated_print(string input) // print(), but only print if the server is not local
-{
- if(server_is_dedicated) { LOG_INFO(input); }
-}
-#endif
-
-#ifndef MENUQC
-float Announcer_PickNumber(float type, float num)
+#ifdef GAMEQC
+Notification Announcer_PickNumber(int type, int num)
{
- switch(type)
+ return = NULL;
+ switch (type)
{
case CNT_GAMESTART:
{
break;
}
}
- return NOTIF_ABORT; // abort sending if none of these numbers were right
}
#endif
-#ifndef MENUQC
+#ifdef GAMEQC
int Mod_Q1BSP_SuperContentsFromNativeContents(int nativecontents)
{
switch(nativecontents)