]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/common/util.qc
Merge remote-tracking branch 'origin/master into samual/weapons
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / util.qc
index 480ebc9fa47aa5b07c2c4f37b5297521a19e77c6..b5c98190ef3ebcedf97ed16001cb94de6a217e85 100644 (file)
@@ -148,7 +148,7 @@ void wordwrap_cb(string s, float l, void(string) callback)
 float dist_point_line(vector p, vector l0, vector ldir)
 {
        ldir = normalize(ldir);
-       
+
        // remove the component in line direction
        p = p - (p * ldir) * ldir;
 
@@ -203,7 +203,6 @@ string ftos_decimals(float number, float decimals)
        return sprintf("%.*f", decimals, number);
 }
 
-float time;
 vector colormapPaletteColor(float c, float isPants)
 {
        switch(c)
@@ -242,7 +241,7 @@ vector colormapPaletteColor(float c, float isPants)
 string fstrunzone(string s)
 {
        string sc;
-       if not(s)
+       if (!s)
                return s;
        sc = strcat(s, "");
        strunzone(s);
@@ -265,7 +264,7 @@ void db_save(float db, string pFilename)
 {
        float fh, i, n;
        fh = fopen(pFilename, FILE_WRITE);
-       if(fh < 0) 
+       if(fh < 0)
        {
                print(strcat("^1Can't write DB to ", pFilename));
                return;
@@ -459,7 +458,7 @@ string ScoreString(float pFlags, float pValue)
                valstr = TIME_ENCODED_TOSTRING(pValue);
        else
                valstr = ftos(pValue);
-       
+
        return valstr;
 }
 
@@ -665,7 +664,7 @@ string fixPriorityList(string order, float from, float to, float subtract, float
                                neworder = strcat(neworder, ftos(w), " ");
                }
        }
-       
+
        return substring(neworder, 0, strlen(neworder) - 1);
 }
 
@@ -678,7 +677,7 @@ string mapPriorityList(string order, string(string) mapfunc)
        neworder = "";
        for(i = 0; i < n; ++i)
                neworder = strcat(neworder, mapfunc(argv(i)), " ");
-       
+
        return substring(neworder, 0, strlen(neworder) - 1);
 }
 
@@ -703,7 +702,7 @@ string swapInPriorityList(string order, float i, float j)
                }
                return substring(s, 0, strlen(s) - 1);
        }
-       
+
        return order;
 }
 
@@ -867,7 +866,7 @@ float cvar_settemp(string tmp_cvar, string tmp_value)
 
        created_saved_value = 0;
 
-       if not(tmp_cvar || tmp_value)
+       if (!(tmp_cvar || tmp_value))
        {
                dprint("Error: Invalid usage of cvar_settemp(string, string); !\n");
                return 0;
@@ -875,7 +874,7 @@ float cvar_settemp(string tmp_cvar, string tmp_value)
 
        if(!cvar_type(tmp_cvar))
        {
-               print(sprintf("Error: cvar %s doesn't exist!\n", tmp_cvar));
+               printf("Error: cvar %s doesn't exist!\n", tmp_cvar);
                return 0;
        }
 
@@ -912,7 +911,7 @@ float cvar_settemp_restore()
                        ++i;
                }
                else
-                       print(sprintf("Error: cvar %s doesn't exist anymore! It can still be restored once it's manually recreated.\n", e.netname));
+                       printf("Error: cvar %s doesn't exist anymore! It can still be restored once it's manually recreated.\n", e.netname);
        }
 
        return i;
@@ -1101,7 +1100,7 @@ vector rgb_to_hsv(vector rgb)
                hsv_y = 0;
        else
                hsv_y = 1 - mi/ma;
-       
+
        return hsv;
 }
 
@@ -1119,7 +1118,7 @@ vector rgb_to_hsl(vector rgb)
        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;
@@ -1127,7 +1126,7 @@ vector rgb_to_hsl(vector rgb)
                hsl_y = (ma - mi) / (2*hsl_z);
        else // if(hsl_z > 0.5)
                hsl_y = (ma - mi) / (2 - 2*hsl_z);
-       
+
        return hsl;
 }
 
@@ -1139,7 +1138,7 @@ vector hsl_to_rgb(vector hsl)
                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;
@@ -1200,7 +1199,7 @@ float textLengthUpToWidth(string theText, float maxWidth, vector theSize, textLe
                // 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
@@ -1228,7 +1227,7 @@ float textLengthUpToWidth(string theText, float maxWidth, vector theSize, textLe
                                }
                        }
        }
-       
+
        return left;
 }
 
@@ -1264,7 +1263,7 @@ float textLengthUpToLength(string theText, float maxWidth, textLengthUpToLength_
                // 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
@@ -1292,7 +1291,7 @@ float textLengthUpToLength(string theText, float maxWidth, textLengthUpToLength_
                                }
                        }
        }
-       
+
        return left;
 }
 
@@ -1313,7 +1312,7 @@ string find_last_color_code(string s)
                        ++carets;
 
                // check if carets aren't all escaped
-               if (carets == 1 || mod(carets, 2) == 1) // first check is just an optimization
+               if (carets & 1)
                {
                        if(i+1 <= len)
                        if(strstrofs("0123456789", substring(s, i+1, 1), 0) >= 0)
@@ -1339,7 +1338,7 @@ string getWrappedLine(float w, vector theFontSize, textLengthUpToWidth_widthFunc
        string s;
 
        s = getWrappedLine_remaining;
-       
+
        if(w <= 0)
        {
                getWrappedLine_remaining = string_null;
@@ -1385,7 +1384,7 @@ string getWrappedLineLen(float w, textLengthUpToLength_lenFunction_t tw)
        string s;
 
        s = getWrappedLine_remaining;
-       
+
        if(w <= 0)
        {
                getWrappedLine_remaining = string_null;
@@ -1477,7 +1476,7 @@ float isGametypeInFilter(float gt, float tp, float ts, string pattern)
                if(strstrofs(strcat(",", pattern, ","), subpattern2, 0) < 0)
                if(strstrofs(strcat(",", pattern, ","), subpattern3, 0) < 0)
                {
-                       if not(subpattern4)
+                       if (!subpattern4)
                                return 0;
                        if(strstrofs(strcat(",", pattern, ","), subpattern4, 0) < 0)
                                return 0;
@@ -1713,7 +1712,7 @@ void check_unacceptable_compiler_bugs()
                error("fteqcc bug introduced with revision 3178 detected. Please upgrade fteqcc to a later revision, downgrade fteqcc to revision 3177, or pester Spike until he fixes it. You can set _allow_unacceptable_compiler_bugs 1 to skip this check, but expect stuff to be horribly broken then.");
 
        string s = "";
-       if not(s)
+       if (!s)
                error("The empty string counts as false. We do not want that!");
 }
 
@@ -1832,10 +1831,13 @@ void RandomSelection_Add(entity e, float f, string s, float weight, float priori
        }
 }
 
-vector healtharmor_maxdamage(float h, float a, float armorblock)
+#ifndef MENUQC
+vector healtharmor_maxdamage(float h, float a, float armorblock, float deathtype)
 {
        // NOTE: we'll always choose the SMALLER value...
        float healthdamage, armordamage, armorideal;
+       if (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
        armordamage = a + (h - 1); // damage we can take if we could use more armor
@@ -1854,14 +1856,17 @@ vector healtharmor_maxdamage(float h, float a, float armorblock)
        return v;
 }
 
-vector healtharmor_applydamage(float a, float armorblock, float damage)
+vector healtharmor_applydamage(float a, float armorblock, float deathtype, float damage)
 {
        vector v;
+       if (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
        v_z = 0;
        return v;
 }
+#endif
 
 string getcurrentmod()
 {
@@ -1884,6 +1889,22 @@ float ReadInt24_t()
        v += ReadByte(); // note: this is unsigned
        return v;
 }
+vector ReadInt48_t()
+{
+       vector v;
+       v_x = ReadInt24_t();
+       v_y = ReadInt24_t();
+       v_z = 0;
+       return v;
+}
+vector ReadInt72_t()
+{
+       vector v;
+       v_x = ReadInt24_t();
+       v_y = ReadInt24_t();
+       v_z = ReadInt24_t();
+       return v;
+}
 #else
 void WriteInt24_t(float dst, float val)
 {
@@ -1891,6 +1912,17 @@ void WriteInt24_t(float dst, float val)
        WriteShort(dst, (v = floor(val / 256)));
        WriteByte(dst, val - v * 256); // 0..255
 }
+void WriteInt48_t(float dst, vector val)
+{
+       WriteInt24_t(dst, val_x);
+       WriteInt24_t(dst, val_y);
+}
+void WriteInt72_t(float dst, vector val)
+{
+       WriteInt24_t(dst, val_x);
+       WriteInt24_t(dst, val_y);
+       WriteInt24_t(dst, val_z);
+}
 #endif
 #endif
 
@@ -2020,7 +2052,7 @@ float get_model_parameters(string m, float sk)
        }
        get_model_parameters_fixbone = 0;
 
-       if not(m)
+       if (!m)
                return 1;
 
        if(substring(m, -9, 5) == "_lod1" || substring(m, -9, 5) == "_lod2")
@@ -2254,11 +2286,11 @@ float xdecode(string s)
 
 float lowestbit(float f)
 {
-       f &~= f * 2;
-       f &~= f * 4;
-       f &~= f * 16;
-       f &~= f * 256;
-       f &~= f * 65536;
+       f &= ~(f * 2);
+       f &= ~(f * 4);
+       f &= ~(f * 16);
+       f &= ~(f * 256);
+       f &= ~(f * 65536);
        return f;
 }
 
@@ -2291,12 +2323,12 @@ float InterpretBoolean(string input)
                case "true":
                case "on":
                        return TRUE;
-               
+
                case "no":
                case "false":
                case "off":
                        return FALSE;
-               
+
                default: return stof(input);
        }
 }
@@ -2427,7 +2459,7 @@ float cubic_speedfunc_is_sane(float startspeedfactor, float endspeedfactor)
        /*
        // if this is the case, the possible zeros of the first derivative are outside
        // 0..1
-       We can calculate this condition as condition 
+       We can calculate this condition as condition
        if(se <= 3)
                return TRUE;
        */
@@ -2460,6 +2492,28 @@ float cubic_speedfunc_is_sane(float startspeedfactor, float endspeedfactor)
        // (3, [0..3])
        // (3.5, [0.2..2.3])
        // (4, 1)
+
+       /*
+          On another note:
+          inflection point is always at (2s + e - 3) / (3s + 3e - 6).
+
+          s + e - 2 == 0: no inflection
+
+          s + e > 2:
+          0 < inflection < 1 if:
+          0 < 2s + e - 3 < 3s + 3e - 6
+          2s + e > 3 and 2e + s > 3
+
+          s + e < 2:
+          0 < inflection < 1 if:
+          0 > 2s + e - 3 > 3s + 3e - 6
+          2s + e < 3 and 2e + s < 3
+
+          Therefore: there is an inflection point iff:
+          e outside (3 - s)/2 .. 3 - s*2
+
+          in other words, if (s,e) in triangle (1,1)(0,3)(0,1.5) or in triangle (1,1)(3,0)(1.5,0)
+       */
 }
 
 .float FindConnectedComponent_processing;
@@ -2504,199 +2558,6 @@ void FindConnectedComponent(entity e, .entity fld, findNextEntityNearFunction_t
                queue_start.FindConnectedComponent_processing = 0;
 }
 
-
-#ifndef MENUQC
-vector cliptoplane(vector v, vector p)
-{
-       return v - (v * p) * p;
-}
-
-vector solve_cubic_pq(float p, float q)
-{
-       float D, u, v, a;
-       D = q*q/4.0 + p*p*p/27.0;
-       if(D < 0)
-       {
-               // irreducibilis
-               a = 1.0/3.0 * acos(-q/2.0 * sqrt(-27.0/(p*p*p)));
-               u = sqrt(-4.0/3.0 * p);
-               // a in range 0..pi/3
-               // cos(a)
-               // cos(a + 2pi/3)
-               // cos(a + 4pi/3)
-               return
-                       u *
-                       (
-                               '1 0 0' * cos(a + 2.0/3.0*M_PI)
-                               +
-                               '0 1 0' * cos(a + 4.0/3.0*M_PI)
-                               +
-                               '0 0 1' * cos(a)
-                       );
-       }
-       else if(D == 0)
-       {
-               // simple
-               if(p == 0)
-                       return '0 0 0';
-               u = 3*q/p;
-               v = -u/2;
-               if(u >= v)
-                       return '1 1 0' * v + '0 0 1' * u;
-               else
-                       return '0 1 1' * v + '1 0 0' * u;
-       }
-       else
-       {
-               // cardano
-               u = cbrt(-q/2.0 + sqrt(D));
-               v = cbrt(-q/2.0 - sqrt(D));
-               return '1 1 1' * (u + v);
-       }
-}
-vector solve_cubic_abcd(float a, float b, float c, float d)
-{
-       // y = 3*a*x + b
-       // x = (y - b) / 3a
-       float p, q;
-       vector v;
-       p = (9*a*c - 3*b*b);
-       q = (27*a*a*d - 9*a*b*c + 2*b*b*b);
-       v = solve_cubic_pq(p, q);
-       v = (v -  b * '1 1 1') * (1.0 / (3.0 * a));
-       if(a < 0)
-               v += '1 0 -1' * (v_z - v_x); // swap x, z
-       return v;
-}
-
-vector findperpendicular(vector v)
-{
-       vector p;
-       p_x = v_z;
-       p_y = -v_x;
-       p_z = v_y;
-       return normalize(cliptoplane(p, v));
-}
-
-vector W_CalculateSpread(vector forward, float spread, float spreadfactor, float spreadstyle)
-{
-       float sigma;
-       vector v1 = '0 0 0', v2;
-       float dx, dy, r;
-       float sstyle;
-       spread *= spreadfactor; //g_weaponspreadfactor;
-       if(spread <= 0)
-               return forward;
-       sstyle = spreadstyle; //autocvar_g_projectiles_spread_style;
-       
-       if(sstyle == 0)
-       {
-               // this is the baseline for the spread value!
-               // standard deviation: sqrt(2/5)
-               // density function: sqrt(1-r^2)
-               return forward + randomvec() * spread;
-       }
-       else if(sstyle == 1)
-       {
-               // same thing, basically
-               return normalize(forward + cliptoplane(randomvec() * spread, forward));
-       }
-       else if(sstyle == 2)
-       {
-               // circle spread... has at sigma=1 a standard deviation of sqrt(1/2)
-               sigma = spread * 0.89442719099991587855; // match baseline stddev
-               v1 = findperpendicular(forward);
-               v2 = cross(forward, v1);
-               // random point on unit circle
-               dx = random() * 2 * M_PI;
-               dy = sin(dx);
-               dx = cos(dx);
-               // radius in our dist function
-               r = random();
-               r = sqrt(r);
-               return normalize(forward + (v1 * dx + v2 * dy) * r * sigma);
-       }
-       else if(sstyle == 3) // gauss 3d
-       {
-               sigma = spread * 0.44721359549996; // match baseline stddev
-               // note: 2D gaussian has sqrt(2) times the stddev of 1D, so this factor is right
-               v1 = forward;
-               v1_x += gsl_ran_gaussian(sigma);
-               v1_y += gsl_ran_gaussian(sigma);
-               v1_z += gsl_ran_gaussian(sigma);
-               return v1;
-       }
-       else if(sstyle == 4) // gauss 2d
-       {
-               sigma = spread * 0.44721359549996; // match baseline stddev
-               // note: 2D gaussian has sqrt(2) times the stddev of 1D, so this factor is right
-               v1_x = gsl_ran_gaussian(sigma);
-               v1_y = gsl_ran_gaussian(sigma);
-               v1_z = gsl_ran_gaussian(sigma);
-               return normalize(forward + cliptoplane(v1, forward));
-       }
-       else if(sstyle == 5) // 1-r
-       {
-               sigma = spread * 1.154700538379252; // match baseline stddev
-               v1 = findperpendicular(forward);
-               v2 = cross(forward, v1);
-               // random point on unit circle
-               dx = random() * 2 * M_PI;
-               dy = sin(dx);
-               dx = cos(dx);
-               // radius in our dist function
-               r = random();
-               r = solve_cubic_abcd(-2, 3, 0, -r) * '0 1 0';
-               return normalize(forward + (v1 * dx + v2 * dy) * r * sigma);
-       }
-       else if(sstyle == 6) // 1-r^2
-       {
-               sigma = spread * 1.095445115010332; // match baseline stddev
-               v1 = findperpendicular(forward);
-               v2 = cross(forward, v1);
-               // random point on unit circle
-               dx = random() * 2 * M_PI;
-               dy = sin(dx);
-               dx = cos(dx);
-               // radius in our dist function
-               r = random();
-               r = sqrt(1 - r);
-               r = sqrt(1 - r);
-               return normalize(forward + (v1 * dx + v2 * dy) * r * sigma);
-       }
-       else if(sstyle == 7) // (1-r) (2-r)
-       {
-               sigma = spread * 1.224744871391589; // match baseline stddev
-               v1 = findperpendicular(forward);
-               v2 = cross(forward, v1);
-               // random point on unit circle
-               dx = random() * 2 * M_PI;
-               dy = sin(dx);
-               dx = cos(dx);
-               // radius in our dist function
-               r = random();
-               r = 1 - sqrt(r);
-               r = 1 - sqrt(r);
-               return normalize(forward + (v1 * dx + v2 * dy) * r * sigma);
-       }
-       else
-               error("g_projectiles_spread_style must be 0 (sphere), 1 (flattened sphere), 2 (circle), 3 (gauss 3D), 4 (gauss plane), 5 (linear falloff), 6 (quadratic falloff), 7 (stronger falloff)!");
-       return '0 0 0';
-       /*
-        * how to derive falloff functions:
-        * rho(r) := (2-r) * (1-r);
-        * a : 0;
-        * b : 1;
-        * rhor(r) := r * rho(r);
-        * cr(t) := integrate(rhor(r), r, a, t);
-        * scr(t) := integrate(rhor(r) * r^2, r, a, t);
-        * variance : scr(b) / cr(b);
-        * solve(cr(r) = rand * cr(b), r), programmmode:false;
-        * sqrt(0.4 / variance), numer;
-        */
-}
-#endif
-
 #ifdef SVQC
 vector combine_to_vector(float x, float y, float z)
 {
@@ -2750,12 +2611,12 @@ void backtrace(string msg)
 string CCR(string input)
 {
        // See the autocvar declarations in util.qh for default values
-       
+
        // foreground/normal colors
-       input = strreplace("^F1", strcat("^", autocvar_hud_colorset_foreground_1), input); 
-       input = strreplace("^F2", strcat("^", autocvar_hud_colorset_foreground_2), input); 
-       input = strreplace("^F3", strcat("^", autocvar_hud_colorset_foreground_3), input); 
-       input = strreplace("^F4", strcat("^", autocvar_hud_colorset_foreground_4), input); 
+       input = strreplace("^F1", strcat("^", autocvar_hud_colorset_foreground_1), input);
+       input = strreplace("^F2", strcat("^", autocvar_hud_colorset_foreground_2), input);
+       input = strreplace("^F3", strcat("^", autocvar_hud_colorset_foreground_3), input);
+       input = strreplace("^F4", strcat("^", autocvar_hud_colorset_foreground_4), input);
 
        // "kill" colors
        input = strreplace("^K1", strcat("^", autocvar_hud_colorset_kill_1), input);
@@ -2805,21 +2666,165 @@ void dedicated_print(string input) // print(), but only print if the server is n
 #endif
 
 #ifndef MENUQC
-float Announcer_PickNumber(float num)
+float Announcer_PickNumber(float type, float num)
 {
-       switch(num)
+       switch(type)
        {
-               case 10: num = ANNCE_NUM_10; break;
-               case 9:  num = ANNCE_NUM_9;  break;
-               case 8:  num = ANNCE_NUM_8;  break;
-               case 7:  num = ANNCE_NUM_7;  break;
-               case 6:  num = ANNCE_NUM_6;  break;
-               case 5:  num = ANNCE_NUM_5;  break;
-               case 4:  num = ANNCE_NUM_4;  break;
-               case 3:  num = ANNCE_NUM_3;  break;
-               case 2:  num = ANNCE_NUM_2;  break;
-               case 1:  num = ANNCE_NUM_1;  break;
+               case CNT_GAMESTART:
+               {
+                       switch(num)
+                       {
+                               case 10: return ANNCE_NUM_GAMESTART_10;
+                               case 9:  return ANNCE_NUM_GAMESTART_9;
+                               case 8:  return ANNCE_NUM_GAMESTART_8;
+                               case 7:  return ANNCE_NUM_GAMESTART_7;
+                               case 6:  return ANNCE_NUM_GAMESTART_6;
+                               case 5:  return ANNCE_NUM_GAMESTART_5;
+                               case 4:  return ANNCE_NUM_GAMESTART_4;
+                               case 3:  return ANNCE_NUM_GAMESTART_3;
+                               case 2:  return ANNCE_NUM_GAMESTART_2;
+                               case 1:  return ANNCE_NUM_GAMESTART_1;
+                       }
+                       break;
+               }
+               case CNT_IDLE:
+               {
+                       switch(num)
+                       {
+                               case 10: return ANNCE_NUM_IDLE_10;
+                               case 9:  return ANNCE_NUM_IDLE_9;
+                               case 8:  return ANNCE_NUM_IDLE_8;
+                               case 7:  return ANNCE_NUM_IDLE_7;
+                               case 6:  return ANNCE_NUM_IDLE_6;
+                               case 5:  return ANNCE_NUM_IDLE_5;
+                               case 4:  return ANNCE_NUM_IDLE_4;
+                               case 3:  return ANNCE_NUM_IDLE_3;
+                               case 2:  return ANNCE_NUM_IDLE_2;
+                               case 1:  return ANNCE_NUM_IDLE_1;
+                       }
+                       break;
+               }
+               case CNT_KILL:
+               {
+                       switch(num)
+                       {
+                               case 10: return ANNCE_NUM_KILL_10;
+                               case 9:  return ANNCE_NUM_KILL_9;
+                               case 8:  return ANNCE_NUM_KILL_8;
+                               case 7:  return ANNCE_NUM_KILL_7;
+                               case 6:  return ANNCE_NUM_KILL_6;
+                               case 5:  return ANNCE_NUM_KILL_5;
+                               case 4:  return ANNCE_NUM_KILL_4;
+                               case 3:  return ANNCE_NUM_KILL_3;
+                               case 2:  return ANNCE_NUM_KILL_2;
+                               case 1:  return ANNCE_NUM_KILL_1;
+                       }
+                       break;
+               }
+               case CNT_RESPAWN:
+               {
+                       switch(num)
+                       {
+                               case 10: return ANNCE_NUM_RESPAWN_10;
+                               case 9:  return ANNCE_NUM_RESPAWN_9;
+                               case 8:  return ANNCE_NUM_RESPAWN_8;
+                               case 7:  return ANNCE_NUM_RESPAWN_7;
+                               case 6:  return ANNCE_NUM_RESPAWN_6;
+                               case 5:  return ANNCE_NUM_RESPAWN_5;
+                               case 4:  return ANNCE_NUM_RESPAWN_4;
+                               case 3:  return ANNCE_NUM_RESPAWN_3;
+                               case 2:  return ANNCE_NUM_RESPAWN_2;
+                               case 1:  return ANNCE_NUM_RESPAWN_1;
+                       }
+                       break;
+               }
+               case CNT_ROUNDSTART:
+               {
+                       switch(num)
+                       {
+                               case 10: return ANNCE_NUM_ROUNDSTART_10;
+                               case 9:  return ANNCE_NUM_ROUNDSTART_9;
+                               case 8:  return ANNCE_NUM_ROUNDSTART_8;
+                               case 7:  return ANNCE_NUM_ROUNDSTART_7;
+                               case 6:  return ANNCE_NUM_ROUNDSTART_6;
+                               case 5:  return ANNCE_NUM_ROUNDSTART_5;
+                               case 4:  return ANNCE_NUM_ROUNDSTART_4;
+                               case 3:  return ANNCE_NUM_ROUNDSTART_3;
+                               case 2:  return ANNCE_NUM_ROUNDSTART_2;
+                               case 1:  return ANNCE_NUM_ROUNDSTART_1;
+                       }
+                       break;
+               }
+               default:
+               {
+                       switch(num)
+                       {
+                               case 10: return ANNCE_NUM_10;
+                               case 9:  return ANNCE_NUM_9;
+                               case 8:  return ANNCE_NUM_8;
+                               case 7:  return ANNCE_NUM_7;
+                               case 6:  return ANNCE_NUM_6;
+                               case 5:  return ANNCE_NUM_5;
+                               case 4:  return ANNCE_NUM_4;
+                               case 3:  return ANNCE_NUM_3;
+                               case 2:  return ANNCE_NUM_2;
+                               case 1:  return ANNCE_NUM_1;
+                       }
+                       break;
+               }
        }
-       return num;
+       return NOTIF_ABORT; // abort sending if none of these numbers were right
+}
+#endif
+
+#ifndef MENUQC
+float Mod_Q1BSP_SuperContentsFromNativeContents(float nativecontents)
+{
+       switch(nativecontents)
+       {
+               case CONTENT_EMPTY:
+                       return 0;
+               case CONTENT_SOLID:
+                       return DPCONTENTS_SOLID | DPCONTENTS_OPAQUE;
+               case CONTENT_WATER:
+                       return DPCONTENTS_WATER;
+               case CONTENT_SLIME:
+                       return DPCONTENTS_SLIME;
+               case CONTENT_LAVA:
+                       return DPCONTENTS_LAVA | DPCONTENTS_NODROP;
+               case CONTENT_SKY:
+                       return DPCONTENTS_SKY | DPCONTENTS_NODROP | DPCONTENTS_OPAQUE; // to match behaviour of Q3 maps, let sky count as opaque
+       }
+       return 0;
+}
+
+float Mod_Q1BSP_NativeContentsFromSuperContents(float supercontents)
+{
+       if(supercontents & (DPCONTENTS_SOLID | DPCONTENTS_BODY))
+               return CONTENT_SOLID;
+       if(supercontents & DPCONTENTS_SKY)
+               return CONTENT_SKY;
+       if(supercontents & DPCONTENTS_LAVA)
+               return CONTENT_LAVA;
+       if(supercontents & DPCONTENTS_SLIME)
+               return CONTENT_SLIME;
+       if(supercontents & DPCONTENTS_WATER)
+               return CONTENT_WATER;
+       return CONTENT_EMPTY;
 }
 #endif
+
+vector bezier_quadratic_getpoint(vector a, vector b, vector c, float t)
+{
+       return
+               (c - 2 * b + a) * (t * t) +
+               (b - a) * (2 * t) +
+               a;
+}
+
+vector bezier_quadratic_getderivative(vector a, vector b, vector c, float t)
+{
+       return
+               (c - 2 * b + a) * (2 * t) +
+               (b - a) * 2;
+}