Merge branch 'TimePath/bot_api' into 'master'
authorTimePath <andrew.hardaker1995@gmail.com>
Thu, 8 Oct 2015 06:07:02 +0000 (06:07 +0000)
committerTimePath <andrew.hardaker1995@gmail.com>
Thu, 8 Oct 2015 06:07:02 +0000 (06:07 +0000)
Decouple bots

If we're ever going to develop a new AI, this separation will make switching implementaions trivial

See merge request !237

35 files changed:
qcsrc/client/hud.qc
qcsrc/client/main.qc
qcsrc/client/teamradar.qc
qcsrc/client/teamradar.qh
qcsrc/common/constants.qh
qcsrc/common/mutators/mutator/waypoints/all.inc
qcsrc/common/mutators/mutator/waypoints/all.qh
qcsrc/common/mutators/mutator/waypoints/waypointsprites.qc
qcsrc/common/mutators/mutator/waypoints/waypointsprites.qh
qcsrc/common/turrets/cl_turrets.qc
qcsrc/common/util-pre.qh
qcsrc/common/util.qc
qcsrc/common/util.qh
qcsrc/common/vehicles/sv_vehicles.qc
qcsrc/common/weapons/weapon/shockwave.qc
qcsrc/lib/_all.inc
qcsrc/lib/bits.qh [new file with mode: 0644]
qcsrc/lib/cvar.qh
qcsrc/lib/math.qh
qcsrc/lib/net.qh
qcsrc/lib/prandom.qc [deleted file]
qcsrc/lib/prandom.qh [deleted file]
qcsrc/lib/random.qc [new file with mode: 0644]
qcsrc/lib/random.qh [new file with mode: 0644]
qcsrc/lib/string.qh
qcsrc/lib/vector.qh
qcsrc/server/cl_client.qc
qcsrc/server/ent_cs.qc
qcsrc/server/ent_cs.qh
qcsrc/server/g_world.qc
qcsrc/server/mutators/mutator_buffs.qc
qcsrc/server/t_items.qc
qcsrc/server/teamplay.qc
qcsrc/server/teamplay.qh
qcsrc/warpzonelib/common.qc

index eb577f4..b229917 100644 (file)
@@ -16,6 +16,7 @@
 #include "../common/mapinfo.qh"
 #include "../common/nades/all.qh"
 
+#include "../common/mutators/mutator/waypoints/all.qh"
 #include "../server/mutators/gamemode_ctf.qh"
 
 #include "../common/stats.qh"
@@ -2240,8 +2241,8 @@ void HUD_Radar(void)
                                drawpic(coord - '8 8 0', "gfx/teamradar_icon_glow", '16 16 0', brightcolor, panel_fg_alpha, 0);
                        }
                }
-
-               draw_teamradar_icon(tm.origin, tm.teamradar_icon, tm, tm.teamradar_color, panel_fg_alpha);
+               entity icon = RadarIcons[tm.teamradar_icon];
+               draw_teamradar_icon(tm.origin, icon, tm, spritelookupcolor(tm, icon.netname, tm.teamradar_color), panel_fg_alpha);
        }
        for(tm = world; (tm = find(tm, classname, "entcs_receiver")); )
        {
index bc3fb43..bb60a91 100644 (file)
@@ -389,33 +389,31 @@ float CSQC_InputEvent(float bInputType, float nPrimary, float nSecondary)
 
 void Ent_RemoveEntCS()
 {SELFPARAM();
-       entcs_receiver[self.sv_entnum] = world;
+       entcs_receiver[self.sv_entnum] = NULL;
 }
 void Ent_ReadEntCS()
 {SELFPARAM();
-    int sf;
        InterpolateOrigin_Undo();
-
        self.classname = "entcs_receiver";
-       sf = ReadByte();
+       int sf = ReadByte();
 
-       if(sf & 1)
+       if(sf & BIT(0))
                self.sv_entnum = ReadByte();
-       if(sf & 2)
+       if (sf & BIT(1))
        {
                self.origin_x = ReadShort();
                self.origin_y = ReadShort();
                self.origin_z = ReadShort();
                setorigin(self, self.origin);
        }
-       if(sf & 4)
+       if (sf & BIT(2))
        {
                self.angles_y = ReadByte() * 360.0 / 256;
                self.angles_x = self.angles_z = 0;
        }
-       if(sf & 8)
+       if (sf & BIT(3))
                self.healthvalue = ReadByte() * 10;
-       if(sf & 16)
+       if (sf & BIT(4))
                self.armorvalue = ReadByte() * 10;
 
        entcs_receiver[self.sv_entnum] = self;
index 8eaf7e4..7623e9d 100644 (file)
@@ -132,10 +132,10 @@ void draw_teamradar_player(vector coord3d, vector pangles, vector rgb)
        R_EndPolygon();
 }
 
-void draw_teamradar_icon(vector coord, float icon, entity pingdata, vector rgb, float a)
+void draw_teamradar_icon(vector coord, entity icon, entity pingdata, vector rgb, float a)
 {
        coord = teamradar_texcoord_to_2dcoord(teamradar_3dcoord_to_texcoord(coord));
-       drawpic(coord - '4 4 0', strcat("gfx/teamradar_icon_", ftos(icon)), '8 8 0', rgb, a, 0);
+       drawpic(coord - '4 4 0', strcat("gfx/teamradar_icon_", ftos(icon.m_radaricon)), '8 8 0', rgb, a, 0);
 
        if(pingdata)
        {
index 8aefc0f..78ef5ee 100644 (file)
@@ -41,7 +41,7 @@ void draw_teamradar_background(float fg);
 
 void draw_teamradar_player(vector coord3d, vector pangles, vector rgb);
 
-void draw_teamradar_icon(vector coord, float icon, entity pingdata, vector rgb, float a);
+void draw_teamradar_icon(vector coord, entity icon, entity pingdata, vector rgb, float a);
 
 void draw_teamradar_link(vector start, vector end, int colors);
 
index 2fcd63c..a4329ad 100644 (file)
@@ -134,20 +134,6 @@ const int SPRITERULE_DEFAULT = 0;
 const int SPRITERULE_TEAMPLAY = 1;
 const int SPRITERULE_SPECTATOR = 2;
 
-const int RADARICON_NONE = 0;
-const int RADARICON_FLAG = 1;
-const int RADARICON_FLAGCARRIER = 1;
-const int RADARICON_HERE = 1; // TODO make these 3 and 4, and make images for them
-const int RADARICON_DANGER = 1;
-const int RADARICON_WAYPOINT = 1;
-const int RADARICON_HELPME = 1;
-const int RADARICON_CONTROLPOINT = 1;
-const int RADARICON_GENERATOR = 1;
-const int RADARICON_OBJECTIVE = 1;
-const int RADARICON_DOMPOINT = 1;
-const int RADARICON_POWERUP = 1;
-const int RADARICON_TAGGED = 1;
-
 ///////////////////////////
 // keys pressed
 const int KEY_FORWARD = 1;
index e1153c2..47fafe7 100644 (file)
@@ -1,6 +1,4 @@
 /** If you register a new waypoint, make sure to add it to this list */
-REGISTER_WAYPOINT(, "", '0 0 0', 1);
-#define WP_Null WP_
 
 REGISTER_WAYPOINT(Waypoint, _("Waypoint"), '0 1 1', 1);
 REGISTER_WAYPOINT(Helpme, _("Help me!"), '1 0.5 0', 1);
index 6120888..f7fd038 100644 (file)
@@ -25,6 +25,34 @@ ENDCLASS(Waypoint)
 
 #define REGISTER_WAYPOINT(id, text, color, blink) REGISTER_WAYPOINT_(id, NEW(Waypoint, #id, text, color, blink))
 
+REGISTRY(RadarIcons, BITS(7))
+REGISTER_REGISTRY(RegisterRadarIcons)
+.int m_radaricon;
+#define REGISTER_RADARICON(id, num) REGISTER(RegisterRadarIcons, RADARICON, RadarIcons, id, m_id, new(RadarIcon)) { this.m_radaricon = num; this.netname = #id; }
+
+REGISTER_WAYPOINT(Null, "", '0 0 0', 1);
+
+REGISTER_RADARICON(NONE,            0);
+REGISTER_RADARICON(FLAG,            1);
+REGISTER_RADARICON(FLAGCARRIER,     1);
+
+// TODO make these 3 and 4, and make images for them
+REGISTER_RADARICON(HERE,            1);
+REGISTER_RADARICON(DANGER,          1);
+
+REGISTER_RADARICON(WAYPOINT,        1);
+REGISTER_RADARICON(HELPME,          1);
+REGISTER_RADARICON(CONTROLPOINT,    1);
+REGISTER_RADARICON(GENERATOR,       1);
+REGISTER_RADARICON(OBJECTIVE,       1);
+REGISTER_RADARICON(DOMPOINT,        1);
+REGISTER_RADARICON(TAGGED,          1);
+
+REGISTER_RADARICON(Buff,            1);
+REGISTER_RADARICON(Item,            1);
+REGISTER_RADARICON(Vehicle,         1);
+REGISTER_RADARICON(Weapon,          1);
+
 #include "all.inc"
 
 #endif
index 9adf1a9..3be3266 100644 (file)
@@ -210,8 +210,8 @@ void Ent_WaypointSprite()
     if (sendflags & 32)
     {
         int f = ReadByte();
-        self.teamradar_icon = (f & 0x7F);
-        if (f & 0x80)
+        self.teamradar_icon = f & BITS(7);
+        if (f & BIT(7))
         {
             self.(teamradar_times[self.teamradar_time_index]) = time;
             self.teamradar_time_index = (self.teamradar_time_index + 1) % MAX_TEAMRADAR_TIMES;
@@ -242,11 +242,11 @@ float spritelookupblinkvalue(string s)
     return 1;
 }
 
-vector spritelookupcolor(string s, vector def)
-{SELFPARAM();
-    if (s == WP_Weapon.netname) return get_weaponinfo(self.wp_extra).wpcolor;
-    if (s == WP_Item.netname) return Items[self.wp_extra].m_color;
-    if (s == WP_Buff.netname) return Buffs[self.wp_extra].m_color;
+vector spritelookupcolor(entity this, string s, vector def)
+{
+    if (s == WP_Weapon.netname  || s == RADARICON_Weapon.netname) return get_weaponinfo(this.wp_extra).wpcolor;
+    if (s == WP_Item.netname    || s == RADARICON_Item.netname) return Items[this.wp_extra].m_color;
+    if (s == WP_Buff.netname    || s == RADARICON_Buff.netname) return Buffs[this.wp_extra].m_color;
     return def;
 }
 
@@ -529,7 +529,7 @@ void Draw_WaypointSprite(entity this)
     else if (self.maxdistance > 0)
         a *= pow(bound(0, (waypointsprite_fadedistance - dist) / (waypointsprite_fadedistance - waypointsprite_normdistance), 1), waypointsprite_distancealphaexponent) * (1 - waypointsprite_minalpha) + waypointsprite_minalpha;
 
-    vector rgb = spritelookupcolor(spriteimage, self.teamradar_color);
+    vector rgb = spritelookupcolor(self, spriteimage, self.teamradar_color);
     if (rgb == '0 0 0')
     {
         self.teamradar_color = '1 0 1';
@@ -827,10 +827,11 @@ void WaypointSprite_UpdateRule(entity e, float t, float r)
     e.SendFlags |= 1;
 }
 
-void WaypointSprite_UpdateTeamRadar(entity e, float icon, vector col)
+void WaypointSprite_UpdateTeamRadar(entity e, entity icon, vector col)
 {
     // no check, as this is never called without doing an actual change (usually only once)
-    e.cnt = (icon & 0x7F) | (e.cnt & 0x80);
+    int i = icon.m_id;
+    e.cnt = (e.cnt & BIT(7)) | (i & BITS(7));
     e.colormod = col;
     e.SendFlags |= 32;
 }
@@ -841,7 +842,7 @@ void WaypointSprite_Ping(entity e)
     if (time < e.waypointsprite_pingtime) return;
     e.waypointsprite_pingtime = time + 0.3;
     // ALWAYS sends (this causes a radar circle), thus no check
-    e.cnt |= 0x80;
+    e.cnt |= BIT(7);
     e.SendFlags |= 32;
 }
 
@@ -1001,7 +1002,7 @@ entity WaypointSprite_Spawn(
     entity showto, float t, // show to whom? Use a flag to indicate a team
     entity own, .entity ownfield, // remove when own gets killed
     float hideable, // true when it should be controlled by cl_hidewaypoints
-    float icon // initial icon
+    entity icon // initial icon
 )
 {
     entity wp = new(sprite_waypoint);
@@ -1033,7 +1034,7 @@ entity WaypointSprite_Spawn(
     wp.customizeentityforclient = WaypointSprite_Customize;
     wp.waypointsprite_visible_for_player = WaypointSprite_visible_for_player;
     wp.reset2 = WaypointSprite_Reset;
-    wp.cnt = icon;
+    wp.cnt = icon.m_id;
     wp.colormod = spr.m_color;
     Net_LinkEntity(wp, false, 0, WaypointSprite_SendEntity);
     return wp;
@@ -1044,7 +1045,7 @@ entity WaypointSprite_SpawnFixed(
     vector ofs,
     entity own,
     .entity ownfield,
-    float icon // initial icon
+    entity icon // initial icon
 )
 {
     return WaypointSprite_Spawn(spr, 0, 0, world, ofs, world, 0, own, ownfield, true, icon);
@@ -1054,7 +1055,7 @@ entity WaypointSprite_DeployFixed(
     entity spr,
     float limited_range,
     vector ofs,
-    float icon // initial icon
+    entity icon // initial icon
 )
 {SELFPARAM();
     float t;
@@ -1073,7 +1074,7 @@ entity WaypointSprite_DeployFixed(
 entity WaypointSprite_DeployPersonal(
     entity spr,
     vector ofs,
-    float icon // initial icon
+    entity icon // initial icon
 )
 {SELFPARAM();
     return WaypointSprite_Spawn(spr, 0, 0, world, ofs, world, 0, self, waypointsprite_deployed_personal, false, icon);
@@ -1082,7 +1083,7 @@ entity WaypointSprite_DeployPersonal(
 entity WaypointSprite_Attach(
     entity spr,
     float limited_range,
-    float icon // initial icon
+    entity icon // initial icon
 )
 {SELFPARAM();
     float t;
@@ -1103,7 +1104,7 @@ entity WaypointSprite_Attach(
 entity WaypointSprite_AttachCarrier(
     entity spr,
     entity carrier,
-    float icon // initial icon and color
+    entity icon // initial icon and color
 )
 {
     WaypointSprite_Kill(carrier.waypointsprite_attached); // FC overrides attached
index 2be4ff8..c9a5534 100644 (file)
@@ -98,7 +98,7 @@ vector drawspritearrow(vector o, float ang, vector rgb, float a, float t);
 vector drawspritetext(vector o, float ang, float minwidth, vector rgb, float a, vector fontsize, string s);
 
 float spritelookupblinkvalue(string s);
-vector spritelookupcolor(string s, vector def);
+vector spritelookupcolor(entity this, string s, vector def);
 string spritelookuptext(string s);
 
 vector fixrgbexcess_move(vector rgb, vector src, vector dst);
@@ -142,7 +142,7 @@ void WaypointSprite_UpdateOrigin(entity e, vector o);
 
 void WaypointSprite_UpdateRule(entity e, float t, float r);
 
-void WaypointSprite_UpdateTeamRadar(entity e, float icon, vector col);
+void WaypointSprite_UpdateTeamRadar(entity e, entity icon, vector col);
 
 .float waypointsprite_pingtime;
 .float waypointsprite_helpmetime;
@@ -182,7 +182,7 @@ entity WaypointSprite_Spawn(
     entity showto, float t, // show to whom? Use a flag to indicate a team
     entity own, .entity ownfield, // remove when own gets killed
     float hideable, // true when it should be controlled by cl_hidewaypoints
-    float icon // initial icon
+    entity icon // initial icon
 );
 
 entity WaypointSprite_SpawnFixed(
@@ -190,7 +190,7 @@ entity WaypointSprite_SpawnFixed(
     vector ofs,
     entity own,
     .entity ownfield,
-    float icon // initial icon
+    entity icon // initial icon
 );
 
 .entity waypointsprite_deployed_fixed;
@@ -198,14 +198,14 @@ entity WaypointSprite_DeployFixed(
     entity spr,
     float limited_range,
     vector ofs,
-    float icon // initial icon
+    entity icon // initial icon
 );
 
 .entity waypointsprite_deployed_personal;
 entity WaypointSprite_DeployPersonal(
     entity spr,
     vector ofs,
-    float icon // initial icon
+    entity icon // initial icon
 );
 
 .entity waypointsprite_attached;
@@ -213,13 +213,13 @@ entity WaypointSprite_DeployPersonal(
 entity WaypointSprite_Attach(
     entity spr,
     float limited_range,
-    float icon // initial icon
+    entity icon // initial icon
 );
 
 entity WaypointSprite_AttachCarrier(
     entity spr,
     entity carrier,
-    float icon // initial icon
+    entity icon // initial icon
 );
 
 void WaypointSprite_DetachCarrier(entity carrier);
index e62a4cc..582113c 100644 (file)
@@ -99,7 +99,7 @@ void turret_draw2d(entity this)
 
        string spriteimage = self.netname;
        float a = self.alpha * autocvar_hud_panel_fg_alpha;
-       vector rgb = spritelookupcolor(spriteimage, self.teamradar_color);
+       vector rgb = spritelookupcolor(self, spriteimage, self.teamradar_color);
 
 
        if(self.maxdistance > waypointsprite_normdistance)
index ad9be12..dfb4071 100644 (file)
 #define GET(name) name##get
 #define GETTER(type, name) type GET(name)() { return name; }
 
-#define BIT(n) (1 << (n))
-#ifndef BRANCHLESS_BITSET
-    #define BITSET(var, mask, flag) (flag ? (var) | (mask) : (var) &~ (mask))
-#else
-    #define BITSET(var, mask, flag) ((var) ^ (-(flag) ^ (var)) & (mask))
-#endif
-
 #endif
index 4b6a346..c304ed8 100644 (file)
@@ -72,37 +72,6 @@ string draw_UseSkinFor(string pic)
 }
 #endif
 
-string unescape(string in)
-{
-       float i, len;
-       string str, s;
-
-       // but it doesn't seem to be necessary in my tests at least
-       in = strzone(in);
-
-       len = strlen(in);
-       str = "";
-       for(i = 0; i < len; ++i)
-       {
-               s = substring(in, i, 1);
-               if(s == "\\")
-               {
-                       s = substring(in, i+1, 1);
-                       if(s == "n")
-                               str = strcat(str, "\n");
-                       else if(s == "\\")
-                               str = strcat(str, "\\");
-                       else
-                               str = strcat(str, substring(in, i, 2));
-                       ++i;
-               } else
-                       str = strcat(str, s);
-       }
-
-       strunzone(in);
-       return str;
-}
-
 void wordwrap_cb(string s, float l, void(string) callback)
 {
        string c;
@@ -168,17 +137,6 @@ void wordwrap_cb(string s, float l, void(string) callback)
        strunzone(s);
 }
 
-float dist_point_line(vector p, vector l0, vector ldir)
-{
-       ldir = normalize(ldir);
-
-       // remove the component in line direction
-       p = p - (p * ldir) * ldir;
-
-       // vlen of the remaining vector
-       return vlen(p);
-}
-
 void depthfirst(entity start, .entity up, .entity downleft, .entity right, void(entity, entity) funcPre, void(entity, entity) funcPost, entity pass)
 {
        entity e;
@@ -208,13 +166,6 @@ void depthfirst(entity start, .entity up, .entity downleft, .entity right, void(
        }
 }
 
-float median(float a, float b, float c)
-{
-       if(a < c)
-               return bound(a, b, c);
-       return bound(c, b, a);
-}
-
 // 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)
@@ -226,9 +177,9 @@ string ftos_decimals(float number, float decimals)
        return sprintf("%.*f", decimals, number);
 }
 
-vector colormapPaletteColor(float c, float isPants)
+vector colormapPaletteColor(float c, bool isPants)
 {
-       switch(c)
+       switch (c)
        {
                case  0: return '1.000000 1.000000 1.000000';
                case  1: return '1.000000 0.333333 0.000000';
@@ -246,7 +197,7 @@ vector colormapPaletteColor(float c, float isPants)
                case 13: return '0.000000 0.333333 1.000000';
                case 14: return '1.000000 0.666667 0.000000';
                case 15:
-                       if(isPants)
+                       if (isPants)
                                return
                                          '1 0 0' * (0.502 + 0.498 * sin(time / 2.7182818285 + 0.0000000000))
                                        + '0 1 0' * (0.502 + 0.498 * sin(time / 2.7182818285 + 2.0943951024))
@@ -260,17 +211,6 @@ vector colormapPaletteColor(float c, float isPants)
        }
 }
 
-// unzone the string, and return it as tempstring. Safe to be called on string_null
-string fstrunzone(string s)
-{
-       string sc;
-       if (!s)
-               return s;
-       sc = strcat(s, "");
-       strunzone(s);
-       return sc;
-}
-
 // Databases (hash tables)
 const float DB_BUCKETS = 8192;
 void db_save(float db, string pFilename)
@@ -932,103 +872,6 @@ float cvar_settemp_restore()
        return i;
 }
 
-float almost_equals(float a, float b)
-{
-       float eps;
-       eps = (max(a, -a) + max(b, -b)) * 0.001;
-       if(a - b < eps && b - a < eps)
-               return true;
-       return false;
-}
-
-float almost_in_bounds(float a, float b, float c)
-{
-       float eps;
-       eps = (max(a, -a) + max(c, -c)) * 0.001;
-       if(a > c)
-               eps = -eps;
-       return b == median(a - eps, b, c + eps);
-}
-
-float power2of(float e)
-{
-       return pow(2, e);
-}
-float log2of(float x)
-{
-       // NOTE: generated code
-       if(x > 2048)
-               if(x > 131072)
-                       if(x > 1048576)
-                               if(x > 4194304)
-                                       return 23;
-                               else
-                                       if(x > 2097152)
-                                               return 22;
-                                       else
-                                               return 21;
-                       else
-                               if(x > 524288)
-                                       return 20;
-                               else
-                                       if(x > 262144)
-                                               return 19;
-                                       else
-                                               return 18;
-               else
-                       if(x > 16384)
-                               if(x > 65536)
-                                       return 17;
-                               else
-                                       if(x > 32768)
-                                               return 16;
-                                       else
-                                               return 15;
-                       else
-                               if(x > 8192)
-                                       return 14;
-                               else
-                                       if(x > 4096)
-                                               return 13;
-                                       else
-                                               return 12;
-       else
-               if(x > 32)
-                       if(x > 256)
-                               if(x > 1024)
-                                       return 11;
-                               else
-                                       if(x > 512)
-                                               return 10;
-                                       else
-                                               return 9;
-                       else
-                               if(x > 128)
-                                       return 8;
-                               else
-                                       if(x > 64)
-                                               return 7;
-                                       else
-                                               return 6;
-               else
-                       if(x > 4)
-                               if(x > 16)
-                                       return 5;
-                               else
-                                       if(x > 8)
-                                               return 4;
-                                       else
-                                               return 3;
-                       else
-                               if(x > 2)
-                                       return 2;
-                               else
-                                       if(x > 1)
-                                               return 1;
-                                       else
-                                               return 0;
-}
-
 float rgb_mi_ma_to_hue(vector rgb, float mi, float ma)
 {
        if(mi == ma)
@@ -1173,15 +1016,6 @@ string rgb_to_hexcolor(vector rgb)
                );
 }
 
-// requires that m2>m1 in all coordinates, and that m4>m3
-float boxesoverlap(vector m1, vector m2, vector m3, vector m4) {return m2_x >= m3_x && m1_x <= m4_x && m2_y >= m3_y && m1_y <= m4_y && m2_z >= m3_z && m1_z <= m4_z;}
-
-// requires the same, but is a stronger condition
-float boxinsidebox(vector smins, vector smaxs, vector bmins, vector bmaxs) {return smins.x >= bmins.x && smaxs.x <= bmaxs.x && smins.y >= bmins.y && smaxs.y <= bmaxs.y && smins.z >= bmins.z && smaxs.z <= bmaxs.z;}
-
-#ifndef MENUQC
-#endif
-
 float textLengthUpToWidth(string theText, float maxWidth, vector theSize, textLengthUpToWidth_widthFunction_t w)
 {
        // STOP.
@@ -1500,47 +1334,6 @@ float isGametypeInFilter(float gt, float tp, float ts, string pattern)
        return 1;
 }
 
-string substring_range(string s, float b, float e)
-{
-       return substring(s, b, e - b);
-}
-
-string swapwords(string str, float i, float j)
-{
-       float n;
-       string s1, s2, s3, s4, s5;
-       float si, ei, sj, ej, s0, en;
-       n = tokenizebyseparator(str, " "); // must match g_maplist processing in ShuffleMaplist and "shuffle"
-       si = argv_start_index(i);
-       sj = argv_start_index(j);
-       ei = argv_end_index(i);
-       ej = argv_end_index(j);
-       s0 = argv_start_index(0);
-       en = argv_end_index(n-1);
-       s1 = substring_range(str, s0, si);
-       s2 = substring_range(str, si, ei);
-       s3 = substring_range(str, ei, sj);
-       s4 = substring_range(str, sj, ej);
-       s5 = substring_range(str, ej, en);
-       return strcat(s1, s4, s3, s2, s5);
-}
-
-string _shufflewords_str;
-void _shufflewords_swapfunc(float i, float j, entity pass)
-{
-       _shufflewords_str = swapwords(_shufflewords_str, i, j);
-}
-string shufflewords(string str)
-{
-       float n;
-       _shufflewords_str = str;
-       n = tokenizebyseparator(str, " ");
-       shuffle(n, _shufflewords_swapfunc, world);
-       str = _shufflewords_str;
-       _shufflewords_str = string_null;
-       return str;
-}
-
 vector solve_quadratic(float a, float b, float c) // ax^2 + bx + c = 0
 {
        vector v;
@@ -1730,37 +1523,6 @@ vector decompressShotOrigin(int f)
        return v;
 }
 
-
-void RandomSelection_Init()
-{
-       RandomSelection_totalweight = 0;
-       RandomSelection_chosen_ent = world;
-       RandomSelection_chosen_float = 0;
-       RandomSelection_chosen_string = string_null;
-       RandomSelection_best_priority = -1;
-}
-void RandomSelection_Add(entity e, float f, string s, float weight, float priority)
-{
-       if(priority > RandomSelection_best_priority)
-       {
-               RandomSelection_best_priority = priority;
-               RandomSelection_chosen_ent = e;
-               RandomSelection_chosen_float = f;
-               RandomSelection_chosen_string = s;
-               RandomSelection_totalweight = weight;
-       }
-       else if(priority == RandomSelection_best_priority)
-       {
-               RandomSelection_totalweight += weight;
-               if(random() * RandomSelection_totalweight <= weight)
-               {
-                       RandomSelection_chosen_ent = e;
-                       RandomSelection_chosen_float = f;
-                       RandomSelection_chosen_string = s;
-               }
-       }
-}
-
 #ifndef MENUQC
 vector healtharmor_maxdamage(float h, float a, float armorblock, int deathtype)
 {
@@ -1810,63 +1572,6 @@ string getcurrentmod()
                return argv(n - 1);
 }
 
-#ifndef MENUQC
-#ifdef CSQC
-int ReadInt24_t()
-{
-       int v = ReadShort() * 256; // note: this is signed
-       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)
-{
-       float v;
-       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
-
-float float2range11(float f)
-{
-       // continuous function mapping all reals into -1..1
-       return f / (fabs(f) + 1);
-}
-
-float float2range01(float f)
-{
-       // continuous function mapping all reals into 0..1
-       return 0.5 + 0.5 * float2range11(f);
-}
-
 // from the GNU Scientific Library
 float gsl_ran_gaussian_lastvalue;
 float gsl_ran_gaussian_lastvalue_set;
@@ -1888,22 +1593,6 @@ float gsl_ran_gaussian(float sigma)
        }
 }
 
-string car(string s)
-{
-       float o;
-       o = strstrofs(s, " ", 0);
-       if(o < 0)
-               return s;
-       return substring(s, 0, o);
-}
-string cdr(string s)
-{
-       float o;
-       o = strstrofs(s, " ", 0);
-       if(o < 0)
-               return string_null;
-       return substring(s, o + 1, strlen(s) - (o + 1));
-}
 float matchacl(string acl, string str)
 {
        string t, s;
@@ -1937,14 +1626,6 @@ float matchacl(string acl, string str)
        }
        return r;
 }
-float startsWith(string haystack, string needle)
-{
-       return substring(haystack, 0, strlen(needle)) == needle;
-}
-float startsWithNocase(string haystack, string needle)
-{
-       return strcasecmp(substring(haystack, 0, strlen(needle)), needle) == 0;
-}
 
 string get_model_datafilename(string m, float sk, string fil)
 {
@@ -2069,28 +1750,6 @@ float get_model_parameters(string m, float sk)
        return 1;
 }
 
-vector vec2(vector v)
-{
-       v.z = 0;
-       return v;
-}
-
-#ifndef MENUQC
-vector NearestPointOnBox(entity box, vector org)
-{
-       vector m1, m2, nearest;
-
-       m1 = box.mins + box.origin;
-       m2 = box.maxs + box.origin;
-
-       nearest.x = bound(m1_x, org.x, m2_x);
-       nearest.y = bound(m1_y, org.y, m2_y);
-       nearest.z = bound(m1_z, org.z, m2_z);
-
-       return nearest;
-}
-#endif
-
 float vercmp_recursive(string v1, string v2)
 {
        float dot1, dot2;
@@ -2142,26 +1801,6 @@ float vercmp(string v1, string v2)
        return vercmp_recursive(v1, v2);
 }
 
-float u8_strsize(string s)
-{
-       float l, i, c;
-       l = 0;
-       for(i = 0; ; ++i)
-       {
-               c = str2chr(s, i);
-               if(c <= 0)
-                       break;
-               ++l;
-               if(c >= 0x80)
-                       ++l;
-               if(c >= 0x800)
-                       ++l;
-               if(c >= 0x10000)
-                       ++l;
-       }
-       return l;
-}
-
 // x-encoding (encoding as zero length invisible string)
 const string XENCODE_2  = "xX";
 const string XENCODE_22 = "0123456789abcdefABCDEF";
@@ -2196,16 +1835,6 @@ float xdecode(string s)
        return ((a * 22 + b) * 22 + c) * 22 + d;
 }
 
-int lowestbit(int f)
-{
-       f &= ~(f * 2);
-       f &= ~(f * 4);
-       f &= ~(f * 16);
-       f &= ~(f * 256);
-       f &= ~(f * 65536);
-       return f;
-}
-
 /*
 string strlimitedlen(string input, string truncation, float strip_colors, float limit)
 {
@@ -2215,16 +1844,6 @@ string strlimitedlen(string input, string truncation, float strip_colors, float
                return strcat(substring(input, 0, (strlen(input) - strlen(truncation))), truncation);
 }*/
 
-// escape the string to make it safe for consoles
-string MakeConsoleSafe(string input)
-{
-       input = strreplace("\n", "", input);
-       input = strreplace("\\", "\\\\", input);
-       input = strreplace("$", "$$", input);
-       input = strreplace("\"", "\\\"", input);
-       return input;
-}
-
 #ifdef CSQC
 entity ReadCSQCEntity()
 {
@@ -2332,80 +1951,6 @@ void queue_to_execute_next_frame(string s)
        to_execute_next_frame = strzone(s);
 }
 
-float cubic_speedfunc(float startspeedfactor, float endspeedfactor, float x)
-{
-       return
-               (((     startspeedfactor + endspeedfactor - 2
-               ) * x - 2 * startspeedfactor - endspeedfactor + 3
-               ) * x + startspeedfactor
-               ) * x;
-}
-
-float cubic_speedfunc_is_sane(float startspeedfactor, float endspeedfactor)
-{
-       if(startspeedfactor < 0 || endspeedfactor < 0)
-               return false;
-
-       /*
-       // if this is the case, the possible zeros of the first derivative are outside
-       // 0..1
-       We can calculate this condition as condition
-       if(se <= 3)
-               return true;
-       */
-
-       // better, see below:
-       if(startspeedfactor <= 3 && endspeedfactor <= 3)
-               return true;
-
-       // if this is the case, the first derivative has no zeros at all
-       float se = startspeedfactor + endspeedfactor;
-       float s_e = startspeedfactor - endspeedfactor;
-       if(3 * (se - 4) * (se - 4) + s_e * s_e <= 12) // an ellipse
-               return true;
-
-       // Now let s <= 3, s <= 3, s+e >= 3 (triangle) then we get se <= 6 (top right corner).
-       // we also get s_e <= 6 - se
-       // 3 * (se - 4)^2 + (6 - se)^2
-       // is quadratic, has value 12 at 3 and 6, and value < 12 in between.
-       // Therefore, above "better" check works!
-
-       return false;
-
-       // known good cases:
-       // (0, [0..3])
-       // (0.5, [0..3.8])
-       // (1, [0..4])
-       // (1.5, [0..3.9])
-       // (2, [0..3.7])
-       // (2.5, [0..3.4])
-       // (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;
 void FindConnectedComponent(entity e, .entity fld, findNextEntityNearFunction_t nxt, isConnectedFunction_t iscon, entity pass)
 {
@@ -2448,61 +1993,6 @@ void FindConnectedComponent(entity e, .entity fld, findNextEntityNearFunction_t
                queue_start.FindConnectedComponent_processing = 0;
 }
 
-#ifdef SVQC
-vector combine_to_vector(float x, float y, float z)
-{
-       vector result; result_x = x; result_y = y; result_z = z;
-       return result;
-}
-
-vector get_corner_position(entity box, float corner)
-{
-       switch(corner)
-       {
-               case 1: return combine_to_vector(box.absmin.x, box.absmin.y, box.absmin.z);
-               case 2: return combine_to_vector(box.absmax.x, box.absmin.y, box.absmin.z);
-               case 3: return combine_to_vector(box.absmin.x, box.absmax.y, box.absmin.z);
-               case 4: return combine_to_vector(box.absmin.x, box.absmin.y, box.absmax.z);
-               case 5: return combine_to_vector(box.absmax.x, box.absmax.y, box.absmin.z);
-               case 6: return combine_to_vector(box.absmin.x, box.absmax.y, box.absmax.z);
-               case 7: return combine_to_vector(box.absmax.x, box.absmin.y, box.absmax.z);
-               case 8: return combine_to_vector(box.absmax.x, box.absmax.y, box.absmax.z);
-               default: return '0 0 0';
-       }
-}
-#endif
-
-// color code replace, place inside of sprintf and parse the string
-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);
-
-       // "kill" colors
-       input = strreplace("^K1", strcat("^", autocvar_hud_colorset_kill_1), input);
-       input = strreplace("^K2", strcat("^", autocvar_hud_colorset_kill_2), input);
-       input = strreplace("^K3", strcat("^", autocvar_hud_colorset_kill_3), input);
-
-       // background colors
-       input = strreplace("^BG", strcat("^", autocvar_hud_colorset_background), input);
-       input = strreplace("^N", "^7", input); // "none"-- reset to white...
-       return input;
-}
-
-vector vec3(float x, float y, float z)
-{
-       vector v;
-       v.x = x;
-       v.y = y;
-       v.z = z;
-       return v;
-}
-
 #ifndef MENUQC
 vector animfixfps(entity e, vector a, vector b)
 {
@@ -2678,18 +2168,3 @@ int Mod_Q1BSP_NativeContentsFromSuperContents(int supercontents)
        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;
-}
index 4af1680..a2774aa 100644 (file)
@@ -152,14 +152,6 @@ string rankings_reply, ladder_reply, lsmaps_reply, maplist_reply, monsterlist_re
 string records_reply[10];
 #endif
 
-float RandomSelection_totalweight;
-float RandomSelection_best_priority;
-entity RandomSelection_chosen_ent;
-float RandomSelection_chosen_float;
-string RandomSelection_chosen_string;
-void RandomSelection_Init();
-void RandomSelection_Add(entity e, float f, string s, float weight, float priority);
-
 #ifndef MENUQC
 vector healtharmor_maxdamage(float h, float a, float armorblock, int deathtype); // returns vector: maxdamage, armorideal, 1 if fully armored
 vector healtharmor_applydamage(float a, float armorblock, int deathtype, float damage); // returns vector: take, save, 0
@@ -225,8 +217,6 @@ const float XENCODE_LEN = 5;
 string xencode(float f);
 float xdecode(string s);
 
-int lowestbit(float f);
-
 #ifdef CSQC
 entity ReadCSQCEntity();
 #endif
@@ -276,11 +266,6 @@ typedef entity(entity cur, entity near, entity pass) findNextEntityNearFunction_
 typedef float(entity a, entity b, entity pass) isConnectedFunction_t;
 void FindConnectedComponent(entity e, .entity fld, findNextEntityNearFunction_t nxt, isConnectedFunction_t iscon, entity pass);
 
-#ifdef SVQC
-vector combine_to_vector(float x, float y, float z);
-vector get_corner_position(entity box, float corner);
-#endif
-
 // expand multiple arguments into one argument by stripping parenthesis
 #define XPD(...) __VA_ARGS__
 
@@ -288,19 +273,6 @@ vector get_corner_position(entity box, float corner);
 #define fprintf(file, ...) fputs(file, sprintf(__VA_ARGS__))
 #define bprintf(...) bprint(sprintf(__VA_ARGS__))
 
-// color code replace, place inside of sprintf and parse the string... defaults described as constants
-// foreground/normal colors
-string autocvar_hud_colorset_foreground_1 = "2"; // F1 - Green  // primary priority (important names, etc)
-string autocvar_hud_colorset_foreground_2 = "3"; // F2 - Yellow // secondary priority (items, locations, numbers, etc)
-string autocvar_hud_colorset_foreground_3 = "4"; // F3 - Blue   // tertiary priority or relatively inconsequential text
-string autocvar_hud_colorset_foreground_4 = "1"; // F4 - Red    // notice/attention grabbing texting
-// "kill" colors
-string autocvar_hud_colorset_kill_1 = "1"; // K1 - Red    // "bad" or "dangerous" text (death messages against you, kill notifications, etc)
-string autocvar_hud_colorset_kill_2 = "3"; // K2 - Yellow // similar to above, but less important... OR, a highlight out of above message type
-string autocvar_hud_colorset_kill_3 = "4"; // K3 - Blue   // "good" or "beneficial" text (you fragging someone, etc)
-// background color
-string autocvar_hud_colorset_background = "7"; // BG - White // neutral/unimportant text
-
 string CCR(string input);
 
 #ifndef MENUQC
index c2e41dd..7108e80 100644 (file)
@@ -529,7 +529,7 @@ void vehicles_showwp()
                rgb = Team_ColorRGB(self.team);
        else
                rgb = '1 1 1';
-       entity wp = WaypointSprite_Spawn(WP_Vehicle, 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, true, RADARICON_POWERUP);
+       entity wp = WaypointSprite_Spawn(WP_Vehicle, 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, true, RADARICON_Vehicle);
        wp.colormod = rgb;
        if(self.waypointsprite_attached)
        {
index 4965ba6..cc4daf0 100644 (file)
@@ -439,7 +439,7 @@ void W_Shockwave_Attack(void)
                                        );
 
                                // figure out the direction of force
-                               vel = normalize(combine_to_vector(head.velocity.x, head.velocity.y, 0));
+                               vel = normalize(vec3(head.velocity.x, head.velocity.y, 0));
                                vel *=
                                        (
                                                bound(0, (vlen(vel) / autocvar_sv_maxspeed), 1)
index 7dc6074..c00c5a1 100644 (file)
@@ -3,6 +3,7 @@
 #include "../warpzonelib/mathlib.qc"
 
 #include "accumulate.qh"
+#include "bits.qh"
 #include "counting.qh"
 #include "cvar.qh"
 #include "defer.qh"
@@ -18,8 +19,8 @@
 #include "oo.qh"
 #include "p2mathlib.qc"
 #include "player.qh"
-#include "prandom.qc"
 #include "progname.qh"
+#include "random.qc"
 #include "registry.qh"
 #include "replicate.qh"
 #include "sort.qh"
diff --git a/qcsrc/lib/bits.qh b/qcsrc/lib/bits.qh
new file mode 100644 (file)
index 0000000..86b5df5
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef BITS_H
+#define BITS_H
+
+#define BIT(n) (1 << (n))
+#define BITS(n) (BIT(n) - 1)
+#ifndef BRANCHLESS_BITSET
+    #define BITSET(var, mask, flag) (flag ? (var) | (mask) : (var) &~ (mask))
+#else
+    #define BITSET(var, mask, flag) ((var) ^ (-(flag) ^ (var)) & (mask))
+#endif
+
+int lowestbit(int f)
+{
+    f &= ~(f << 1);
+    f &= ~(f << 2);
+    f &= ~(f << 4);
+    f &= ~(f << 8);
+    f &= ~(f << 16);
+    return f;
+}
+
+#endif
index a02ec0f..e30de50 100644 (file)
@@ -6,6 +6,16 @@
 
 void RegisterCvars(void(string name, string def, string desc, bool archive, string file) f) { }
 
+/** escape the string to make it safe for consoles */
+string MakeConsoleSafe(string input)
+{
+       input = strreplace("\n", "", input);
+       input = strreplace("\\", "\\\\", input);
+       input = strreplace("$", "$$", input);
+       input = strreplace("\"", "\\\"", input);
+       return input;
+}
+
 void RegisterCvars_Set(string name, string def, string desc, bool archive, string file)
 {
     string val = string_null;
@@ -14,9 +24,9 @@ void RegisterCvars_Set(string name, string def, string desc, bool archive, strin
         // Need to unset first to change the default
         localcmd(sprintf("\nunset %s\n", name));
     }
-    localcmd(sprintf("\n%s %s \"%s\" \"%s\"\n", (archive ? "seta" : "set"), name, def, desc));
+    localcmd(sprintf("\n%s %s \"%s\" \"%s\"\n", (archive ? "seta" : "set"), name, MakeConsoleSafe(def), MakeConsoleSafe(desc)));
     if (val) {
-        localcmd(sprintf("\n%s \"%s\"\n", name, val));
+        localcmd(sprintf("\n%s \"%s\"\n", name, MakeConsoleSafe(val)));
     }
 }
 
index a8a5290..1a707a4 100644 (file)
@@ -3,23 +3,23 @@
 
 void mean_accumulate(entity e, .float a, .float c, float mean, float value, float weight)
 {
-       if (weight == 0)
-               return;
-       if (mean == 0)
-               e.(a) *= pow(value, weight);
-       else
-               e.(a) += pow(value, mean) * weight;
-       e.(c) += weight;
+    if (weight == 0)
+        return;
+    if (mean == 0)
+        e.(a) *= pow(value, weight);
+    else
+        e.(a) += pow(value, mean) * weight;
+    e.(c) += weight;
 }
 
 float mean_evaluate(entity e, .float a, .float c, float mean)
 {
-       if (e.(c) == 0)
-               return 0;
-       if (mean == 0)
-               return pow(e.(a), 1.0 / e.(c));
-       else
-               return pow(e.(a) / e.(c), 1.0 / mean);
+    if (e.(c) == 0)
+        return 0;
+    if (mean == 0)
+        return pow(e.(a), 1.0 / e.(c));
+    else
+        return pow(e.(a) / e.(c), 1.0 / mean);
 }
 
 #define MEAN_ACCUMULATE(prefix,v,w) mean_accumulate(self,prefix##_accumulator,prefix##_count,prefix##_mean,v,w)
@@ -33,9 +33,9 @@ crandom
 Returns a random number between -1.0 and 1.0
 ==================
 */
-float crandom (void)
+float crandom()
 {
-       return 2 * (random () - 0.5);
+    return 2 * (random() - 0.5);
 }
 
 
@@ -46,27 +46,16 @@ Angc used for animations
 */
 
 
-float angc (float a1, float a2)
+float angc(float a1, float a2)
 {
-       float   a;
-
-       while (a1 > 180)
-               a1 = a1 - 360;
-       while (a1 < -179)
-               a1 = a1 + 360;
-
-       while (a2 > 180)
-               a2 = a2 - 360;
-       while (a2 < -179)
-               a2 = a2 + 360;
-
-       a = a1 - a2;
-       while (a > 180)
-               a = a - 360;
-       while (a < -179)
-               a = a + 360;
-
-       return a;
+    while (a1 > 180) a1 -= 360;
+    while (a1 < -179) a1 += 360;
+    while (a2 > 180) a2 -= 360;
+    while (a2 < -179) a2 += 360;
+    float a = a1 - a2;
+    while (a > 180) a -= 360;
+    while (a < -179) a += 360;
+    return a;
 }
 
 float fsnap(float val,float fsize)
@@ -87,7 +76,208 @@ vector vsnap(vector point,float fsize)
 
 vector lerpv(float t0, vector v0, float t1, vector v1, float t)
 {
-       return v0 + (v1 - v0) * ((t - t0) / (t1 - t0));
+    return v0 + (v1 - v0) * ((t - t0) / (t1 - t0));
+}
+
+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;
+}
+
+float cubic_speedfunc(float startspeedfactor, float endspeedfactor, float x)
+{
+    return
+        (((     startspeedfactor + endspeedfactor - 2
+        ) * x - 2 * startspeedfactor - endspeedfactor + 3
+        ) * x + startspeedfactor
+        ) * x;
+}
+
+bool cubic_speedfunc_is_sane(float startspeedfactor, float endspeedfactor)
+{
+    if (startspeedfactor < 0 || endspeedfactor < 0)
+        return false;
+
+    /*
+    // if this is the case, the possible zeros of the first derivative are outside
+    // 0..1
+    We can calculate this condition as condition
+    if(se <= 3)
+        return true;
+    */
+
+    // better, see below:
+    if (startspeedfactor <= 3 && endspeedfactor <= 3)
+        return true;
+
+    // if this is the case, the first derivative has no zeros at all
+    float se = startspeedfactor + endspeedfactor;
+    float s_e = startspeedfactor - endspeedfactor;
+    if (3 * (se - 4) * (se - 4) + s_e * s_e <= 12) // an ellipse
+        return true;
+
+    // Now let s <= 3, s <= 3, s+e >= 3 (triangle) then we get se <= 6 (top right corner).
+    // we also get s_e <= 6 - se
+    // 3 * (se - 4)^2 + (6 - se)^2
+    // is quadratic, has value 12 at 3 and 6, and value < 12 in between.
+    // Therefore, above "better" check works!
+
+    return false;
+
+    // known good cases:
+    // (0, [0..3])
+    // (0.5, [0..3.8])
+    // (1, [0..4])
+    // (1.5, [0..3.9])
+    // (2, [0..3.7])
+    // (2.5, [0..3.4])
+    // (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)
+    */
+}
+
+/** continuous function mapping all reals into -1..1 */
+float float2range11(float f)
+{
+    return f / (fabs(f) + 1);
 }
 
+/** continuous function mapping all reals into 0..1 */
+float float2range01(float f)
+{
+    return 0.5 + 0.5 * float2range11(f);
+}
+
+float median(float a, float b, float c)
+{
+    return (a < c) ? bound(a, b, c) : bound(c, b, a);
+}
+
+float almost_equals(float a, float b)
+{
+    float eps = (max(a, -a) + max(b, -b)) * 0.001;
+    return a - b < eps && b - a < eps;
+}
+
+float almost_in_bounds(float a, float b, float c)
+{
+    float eps = (max(a, -a) + max(c, -c)) * 0.001;
+    if (a > c)
+        eps = -eps;
+    return b == median(a - eps, b, c + eps);
+}
+
+float power2of(float e)
+{
+    return pow(2, e);
+}
+
+float log2of(float x)
+{
+    // NOTE: generated code
+    if (x > 2048)
+        if (x > 131072)
+            if (x > 1048576)
+                if (x > 4194304)
+                    return 23;
+                else
+                    if (x > 2097152)
+                        return 22;
+                    else
+                        return 21;
+            else
+                if (x > 524288)
+                    return 20;
+                else
+                    if (x > 262144)
+                        return 19;
+                    else
+                        return 18;
+        else
+            if (x > 16384)
+                if (x > 65536)
+                    return 17;
+                else
+                    if (x > 32768)
+                        return 16;
+                    else
+                        return 15;
+            else
+                if (x > 8192)
+                    return 14;
+                else
+                    if (x > 4096)
+                        return 13;
+                    else
+                        return 12;
+    else
+        if (x > 32)
+            if (x > 256)
+                if (x > 1024)
+                    return 11;
+                else
+                    if (x > 512)
+                        return 10;
+                    else
+                        return 9;
+            else
+                if (x > 128)
+                    return 8;
+                else
+                    if (x > 64)
+                        return 7;
+                    else
+                        return 6;
+        else
+            if (x > 4)
+                if (x > 16)
+                    return 5;
+                else
+                    if (x > 8)
+                        return 4;
+                    else
+                        return 3;
+            else
+                if (x > 2)
+                    return 2;
+                else
+                    if (x > 1)
+                        return 1;
+                    else
+                        return 0;
+}
+
+
 #endif
index 2928ce8..04faffc 100644 (file)
@@ -118,4 +118,49 @@ STATIC_INIT(RegisterTempEntities_renumber) {
     }
 }
 
+#ifndef MENUQC
+#ifdef CSQC
+int ReadInt24_t()
+{
+    int v = ReadShort() << 8; // note: this is signed
+    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)
+{
+    float v;
+    WriteShort(dst, (v = floor(val >> 8)));
+    WriteByte(dst, val - (v << 8)); // 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
+
 #endif
diff --git a/qcsrc/lib/prandom.qc b/qcsrc/lib/prandom.qc
deleted file mode 100644 (file)
index 4f58822..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-#include "prandom.qh"
-
-// prandom - PREDICTABLE random number generator (not seeded yet)
-
-#ifdef USE_PRANDOM
-float prandom_seed;
-float prandom()
-{
-       float c;
-       c = crc16(false, strcat(ftos(prandom_seed), ftos(prandom_seed + M_PI)));
-       prandom_seed = c;
-
-#ifdef USE_PRANDOM_DEBUG
-       LOG_TRACE("RANDOM -> ", ftos(c), "\n");
-#endif
-
-       return c / 65536; // in [0..1[
-}
-
-vector prandomvec()
-{
-       vector v;
-
-       do
-       {
-               v.x = prandom();
-               v.y = prandom();
-               v.z = prandom();
-       }
-       while(v * v > 1);
-
-       return v;
-}
-
-void psrandom(float seed)
-{
-       prandom_seed = seed;
-#ifdef USE_PRANDOM_DEBUG
-       LOG_TRACE("SRANDOM ", ftos(seed), "\n");
-#endif
-}
-
-#ifdef USE_PRANDOM_DEBUG
-void prandom_debug()
-{
-       LOG_TRACE("Current random seed = ", ftos(prandom_seed), "\n");
-}
-#endif
-#endif
diff --git a/qcsrc/lib/prandom.qh b/qcsrc/lib/prandom.qh
deleted file mode 100644 (file)
index a7653a5..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef PRANDOM_H
-#define PRANDOM_H
-
-// prandom - PREDICTABLE random number generator
-
-#define USE_PRANDOM
-
-#ifdef USE_PRANDOM
-float prandom();
-vector prandomvec();
-
-void psrandom(float seed);
-#ifdef USE_PRANDOM_DEBUG
-void prandom_debug();
-#else
-#define prandom_debug()
-#endif
-#else
-#define prandom random
-#define prandomvec randomvec
-#define psrandom(x)
-#define prandom_debug()
-#endif
-#endif
diff --git a/qcsrc/lib/random.qc b/qcsrc/lib/random.qc
new file mode 100644 (file)
index 0000000..149323b
--- /dev/null
@@ -0,0 +1,81 @@
+#include "random.qh"
+
+void RandomSelection_Init()
+{
+    RandomSelection_totalweight = 0;
+    RandomSelection_chosen_ent = NULL;
+    RandomSelection_chosen_float = 0;
+    RandomSelection_chosen_string = string_null;
+    RandomSelection_best_priority = -1;
+}
+
+void RandomSelection_Add(entity e, float f, string s, float weight, float priority)
+{
+    if (priority > RandomSelection_best_priority)
+    {
+        RandomSelection_best_priority = priority;
+        RandomSelection_chosen_ent = e;
+        RandomSelection_chosen_float = f;
+        RandomSelection_chosen_string = s;
+        RandomSelection_totalweight = weight;
+    }
+    else if (priority == RandomSelection_best_priority)
+    {
+        RandomSelection_totalweight += weight;
+        if (random() * RandomSelection_totalweight <= weight)
+        {
+            RandomSelection_chosen_ent = e;
+            RandomSelection_chosen_float = f;
+            RandomSelection_chosen_string = s;
+        }
+    }
+}
+
+
+// prandom - PREDICTABLE random number generator (not seeded yet)
+
+#ifdef USE_PRANDOM
+float prandom_seed;
+float prandom()
+{
+    float c;
+    c = crc16(false, strcat(ftos(prandom_seed), ftos(prandom_seed + M_PI)));
+    prandom_seed = c;
+
+#ifdef USE_PRANDOM_DEBUG
+    LOG_TRACE("RANDOM -> ", ftos(c), "\n");
+#endif
+
+    return c / 65536; // in [0..1[
+}
+
+vector prandomvec()
+{
+    vector v;
+
+    do
+    {
+        v.x = prandom();
+        v.y = prandom();
+        v.z = prandom();
+    }
+    while(v * v > 1);
+
+    return v;
+}
+
+void psrandom(float seed)
+{
+    prandom_seed = seed;
+#ifdef USE_PRANDOM_DEBUG
+    LOG_TRACE("SRANDOM ", ftos(seed), "\n");
+#endif
+}
+
+#ifdef USE_PRANDOM_DEBUG
+void prandom_debug()
+{
+    LOG_TRACE("Current random seed = ", ftos(prandom_seed), "\n");
+}
+#endif
+#endif
diff --git a/qcsrc/lib/random.qh b/qcsrc/lib/random.qh
new file mode 100644 (file)
index 0000000..551cf21
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef RANDOM_H
+#define RANDOM_H
+
+float RandomSelection_totalweight;
+float RandomSelection_best_priority;
+entity RandomSelection_chosen_ent;
+float RandomSelection_chosen_float;
+string RandomSelection_chosen_string;
+
+void RandomSelection_Init();
+void RandomSelection_Add(entity e, float f, string s, float weight, float priority);
+
+// prandom - PREDICTABLE random number generator
+
+#define USE_PRANDOM
+
+#ifdef USE_PRANDOM
+float prandom();
+vector prandomvec();
+
+void psrandom(float seed);
+#ifdef USE_PRANDOM_DEBUG
+void prandom_debug();
+#else
+#define prandom_debug()
+#endif
+#else
+#define prandom random
+#define prandomvec randomvec
+#define psrandom(x)
+#define prandom_debug()
+#endif
+#endif
index faf81b2..ede2edf 100644 (file)
@@ -4,12 +4,12 @@
 #ifndef SVQC
 float stringwidth_colors(string s, vector theSize)
 {
-       return stringwidth(s, true, theSize);
+    return stringwidth(s, true, theSize);
 }
 
 float stringwidth_nocolors(string s, vector theSize)
 {
-       return stringwidth(s, false, theSize);
+    return stringwidth(s, false, theSize);
 }
 #endif
 
@@ -18,21 +18,174 @@ float stringwidth_nocolors(string s, vector theSize)
 // TODO: macro
 string seconds_tostring(float sec)
 {
-       float minutes;
-       minutes = floor(sec / 60);
-
-       sec -= minutes * 60;
-       return sprintf("%d:%02d", minutes, sec);
+    float minutes = floor(sec / 60);
+    sec -= minutes * 60;
+    return sprintf("%d:%02d", minutes, sec);
 }
 
 int ColorTranslateMode;
 
 string ColorTranslateRGB(string s)
 {
-       if(ColorTranslateMode & 1)
-               return strdecolorize(s);
-       else
-               return s;
+    return (ColorTranslateMode & 1) ? strdecolorize(s) : s;
+}
+
+// color code replace, place inside of sprintf and parse the string... defaults described as constants
+// foreground/normal colors
+string autocvar_hud_colorset_foreground_1 = "2"; // F1 - Green  // primary priority (important names, etc)
+string autocvar_hud_colorset_foreground_2 = "3"; // F2 - Yellow // secondary priority (items, locations, numbers, etc)
+string autocvar_hud_colorset_foreground_3 = "4"; // F3 - Blue   // tertiary priority or relatively inconsequential text
+string autocvar_hud_colorset_foreground_4 = "1"; // F4 - Red    // notice/attention grabbing texting
+// "kill" colors
+string autocvar_hud_colorset_kill_1 = "1"; // K1 - Red    // "bad" or "dangerous" text (death messages against you, kill notifications, etc)
+string autocvar_hud_colorset_kill_2 = "3"; // K2 - Yellow // similar to above, but less important... OR, a highlight out of above message type
+string autocvar_hud_colorset_kill_3 = "4"; // K3 - Blue   // "good" or "beneficial" text (you fragging someone, etc)
+// background color
+string autocvar_hud_colorset_background = "7"; // BG - White // neutral/unimportant text
+
+/** color code replace, place inside of sprintf and parse the string */
+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);
+
+    // "kill" colors
+    input = strreplace("^K1", strcat("^", autocvar_hud_colorset_kill_1), input);
+    input = strreplace("^K2", strcat("^", autocvar_hud_colorset_kill_2), input);
+    input = strreplace("^K3", strcat("^", autocvar_hud_colorset_kill_3), input);
+
+    // background colors
+    input = strreplace("^BG", strcat("^", autocvar_hud_colorset_background), input);
+    input = strreplace("^N", "^7", input); // "none"-- reset to white...
+    return input;
+}
+
+bool startsWith(string haystack, string needle)
+{
+    return substring(haystack, 0, strlen(needle)) == needle;
+}
+
+bool startsWithNocase(string haystack, string needle)
+{
+    return strcasecmp(substring(haystack, 0, strlen(needle)), needle) == 0;
+}
+
+/** unzone the string, and return it as tempstring. Safe to be called on string_null */
+string fstrunzone(string s)
+{
+    if (!s) return s;
+    string sc = strcat(s, "");
+    strunzone(s);
+    return sc;
+}
+
+string car(string s)
+{
+    int o = strstrofs(s, " ", 0);
+    if (o < 0) return s;
+    return substring(s, 0, o);
+}
+
+string cdr(string s)
+{
+    int o = strstrofs(s, " ", 0);
+    if (o < 0) return string_null;
+    return substring(s, o + 1, strlen(s) - (o + 1));
+}
+
+string substring_range(string s, float b, float e)
+{
+    return substring(s, b, e - b);
+}
+
+string swapwords(string str, float i, float j)
+{
+    float n;
+    string s1, s2, s3, s4, s5;
+    float si, ei, sj, ej, s0, en;
+    n = tokenizebyseparator(str, " "); // must match g_maplist processing in ShuffleMaplist and "shuffle"
+    si = argv_start_index(i);
+    sj = argv_start_index(j);
+    ei = argv_end_index(i);
+    ej = argv_end_index(j);
+    s0 = argv_start_index(0);
+    en = argv_end_index(n-1);
+    s1 = substring_range(str, s0, si);
+    s2 = substring_range(str, si, ei);
+    s3 = substring_range(str, ei, sj);
+    s4 = substring_range(str, sj, ej);
+    s5 = substring_range(str, ej, en);
+    return strcat(s1, s4, s3, s2, s5);
+}
+
+string _shufflewords_str;
+void _shufflewords_swapfunc(float i, float j, entity pass)
+{
+    _shufflewords_str = swapwords(_shufflewords_str, i, j);
+}
+string shufflewords(string str)
+{
+    _shufflewords_str = str;
+    int n = tokenizebyseparator(str, " ");
+    shuffle(n, _shufflewords_swapfunc, NULL);
+    str = _shufflewords_str;
+    _shufflewords_str = string_null;
+    return str;
+}
+
+string unescape(string in)
+{
+    in = strzone(in); // but it doesn't seem to be necessary in my tests at least
+
+    int len = strlen(in);
+    string str = "";
+    for (int i = 0; i < len; ++i) {
+        string s = substring(in, i, 1);
+        if (s == "\\") {
+            s = substring(in, i + 1, 1);
+            if (s == "n")
+                str = strcat(str, "\n");
+            else if (s == "\\")
+                str = strcat(str, "\\");
+            else
+                str = strcat(str, substring(in, i, 2));
+            ++i;
+            continue;
+        }
+        str = strcat(str, s);
+    }
+    strunzone(in);
+    return str;
+}
+
+string strwords(string s, int w)
+{
+    int endpos = 0;
+    for (; w && endpos >= 0; --w) endpos = strstrofs(s, " ", endpos + 1);
+    if (endpos < 0) return s;
+    return substring(s, 0, endpos);
+}
+
+bool strhasword(string s, string w)
+{
+    return strstrofs(strcat(" ", s, " "), strcat(" ", w, " "), 0) >= 0;
+}
+
+int u8_strsize(string s)
+{
+    int l = 0;
+    for (int i = 0, c; (c = str2chr(s, i)) > 0; ++i, ++l)
+    {
+        l += (c >= 0x80);
+        l += (c >= 0x800);
+        l += (c >= 0x10000);
+    }
+    return l;
 }
 
 #endif
index d81a795..b57e27a 100644 (file)
@@ -7,28 +7,86 @@ const vector eZ = '0 0 1';
 
 vector randompos(vector m1, vector m2)
 {
-       vector v;
-       m2 = m2 - m1;
-       v_x = m2_x * random() + m1_x;
-       v_y = m2_y * random() + m1_y;
-       v_z = m2_z * random() + m1_z;
-       return  v;
+    vector v;
+    m2 = m2 - m1;
+    v_x = m2_x * random() + m1_x;
+    v_y = m2_y * random() + m1_y;
+    v_z = m2_z * random() + m1_z;
+    return     v;
 }
 
 float vlen2d(vector v)
 {
-       return sqrt(v.x * v.x + v.y * v.y);
+    return sqrt(v.x * v.x + v.y * v.y);
 }
 
 float vlen_maxnorm2d(vector v)
 {
-       return max(v.x, v.y, -v.x, -v.y);
+    return max(v.x, v.y, -v.x, -v.y);
 }
 
 float vlen_minnorm2d(vector v)
 {
-       return min(max(v.x, -v.x), max(v.y, -v.y));
+    return min(max(v.x, -v.x), max(v.y, -v.y));
 }
 
+float dist_point_line(vector p, vector l0, vector ldir)
+{
+    ldir = normalize(ldir);
+
+    // remove the component in line direction
+    p = p - (p * ldir) * ldir;
+
+    // vlen of the remaining vector
+    return vlen(p);
+}
+
+/** requires that m2>m1 in all coordinates, and that m4>m3 */
+float boxesoverlap(vector m1, vector m2, vector m3, vector m4) {return m2_x >= m3_x && m1_x <= m4_x && m2_y >= m3_y && m1_y <= m4_y && m2_z >= m3_z && m1_z <= m4_z;}
+
+/** requires the same as boxesoverlap, but is a stronger condition */
+float boxinsidebox(vector smins, vector smaxs, vector bmins, vector bmaxs) {return smins.x >= bmins.x && smaxs.x <= bmaxs.x && smins.y >= bmins.y && smaxs.y <= bmaxs.y && smins.z >= bmins.z && smaxs.z <= bmaxs.z;}
+
+
+vector vec2(vector v)
+{
+    v.z = 0;
+    return v;
+}
+
+vector vec3(float x, float y, float z)
+{
+    vector v; v.x = x; v.y = y; v.z = z;
+    return v;
+}
+
+#ifndef MENUQC
+vector get_corner_position(entity box, int corner)
+{
+    switch (corner) {
+        case 1: return vec3(box.absmin.x, box.absmin.y, box.absmin.z);
+        case 2: return vec3(box.absmax.x, box.absmin.y, box.absmin.z);
+        case 3: return vec3(box.absmin.x, box.absmax.y, box.absmin.z);
+        case 4: return vec3(box.absmin.x, box.absmin.y, box.absmax.z);
+        case 5: return vec3(box.absmax.x, box.absmax.y, box.absmin.z);
+        case 6: return vec3(box.absmin.x, box.absmax.y, box.absmax.z);
+        case 7: return vec3(box.absmax.x, box.absmin.y, box.absmax.z);
+        case 8: return vec3(box.absmax.x, box.absmax.y, box.absmax.z);
+        default: return '0 0 0';
+    }
+}
+
+vector NearestPointOnBox(entity box, vector org)
+{
+    vector m1 = box.mins + box.origin;
+    vector m2 = box.maxs + box.origin;
+
+    vector ret;
+    ret.x = bound(m1.x, org.x, m2.x);
+    ret.y = bound(m1.y, org.y, m2.y);
+    ret.z = bound(m1.z, org.z, m2.z);
+    return ret;
+}
+#endif
 
 #endif
index 1270803..adf2542 100644 (file)
@@ -1215,7 +1215,7 @@ void ClientConnect (void)
        else
                stuffcmd(self, "set _teams_available 0\n");
 
-       attach_entcs();
+       attach_entcs(self);
 
        bot_relinkplayerlist();
 
@@ -1301,8 +1301,7 @@ void ClientDisconnect (void)
 
        bot_clientdisconnect();
 
-       if(self.entcs)
-               detach_entcs();
+       detach_entcs(self);
 
        if(autocvar_sv_eventlog)
                GameLogEcho(strcat(":part:", ftos(self.playerid)));
index 904f4c9..768eae3 100644 (file)
@@ -1,34 +1,10 @@
+#include "ent_cs.qh"
 #include "_all.qh"
 
-#include "defs.qh"
-#include "mutators/mutators_include.qh"
-
-/**
- * The point of these entities is to avoid the problems
- * with clientprediction.
- * If you add SendEntity to players, the engine will not
- * do any prediction anymore, and you'd have to write the whole
- * prediction code in CSQC, you want that? :P
- * Data can depend on gamemode. For now, it serves as GPS entities
- * in onslaught... YAY ;)
- */
-
-// Beware: do not redefine those in other files
-// and NO, you cannot use ".version", which already exists (at least
-// it did when I added this) But you have to use .Version
-// Capital V
-
-.entity entcs;
-
-void entcs_init()
-{
-       LOG_INFO("Initializing ClientSide information entities\n");
-}
-
 float entcs_customize()
-{SELFPARAM();
-       entity o;
-       o = self.owner;
+{
+       SELFPARAM();
+       entity o = self.owner;
        if(o.deadflag != DEAD_NO)
                return false;
        if (!IS_PLAYER(o))
@@ -46,72 +22,66 @@ bool entcs_send(entity this, entity to, int sf)
 {
        WriteByte(MSG_ENTITY, ENT_CLIENT_ENTCS);
        WriteByte(MSG_ENTITY, sf);
-       if(sf & 1)
-               WriteByte(MSG_ENTITY, num_for_edict(self.owner)-1);
-       if(sf & 2)
+       if(sf & BIT(0))
+               WriteByte(MSG_ENTITY, num_for_edict(self.owner) - 1);
+       if(sf & BIT(1))
        {
                WriteShort(MSG_ENTITY, self.origin.x);
                WriteShort(MSG_ENTITY, self.origin.y);
                WriteShort(MSG_ENTITY, self.origin.z);
        }
-       if(sf & 4)
+       if(sf & BIT(2))
                WriteByte(MSG_ENTITY, self.angles.y * 256.0 / 360);
-       if(sf & 8)
+       if(sf & BIT(3))
                WriteByte(MSG_ENTITY, self.health / 10); // FIXME use a better scale?
-       if(sf & 16)
+       if(sf & BIT(4))
                WriteByte(MSG_ENTITY, self.armorvalue / 10); // FIXME use a better scale?
        return true;
 }
 
 void entcs_think()
-{SELFPARAM();
+{
+       SELFPARAM();
        self.nextthink = time + 0.033333333333; // increase this to like 0.15 once the client can do smoothing
-
-       entity o;
-       o = self.owner;
-
-       if(o.origin != self.origin)
+       entity o = self.owner;
+       if (o.origin != self.origin)
        {
                setorigin(self, o.origin);
-               self.SendFlags |= 2;
+               self.SendFlags |= BIT(1);
        }
-       if(o.angles.y != self.angles.y)
+       if (o.angles.y != self.angles.y)
        {
                self.angles = o.angles;
-               self.SendFlags |= 4;
+               self.SendFlags |= BIT(2);
        }
-       if(o.health != self.health)
+       if (o.health != self.health)
        {
                self.health = o.health;
-               self.SendFlags |= 8;
+               self.SendFlags |= BIT(3);
        }
-       if(o.armorvalue != self.armorvalue)
+       if (o.armorvalue != self.armorvalue)
        {
                self.armorvalue = o.armorvalue;
-               self.SendFlags |= 16;
+               self.SendFlags |= BIT(4);
        }
 }
 
-entity attach_entcs()
-{SELFPARAM();
-       entity ent;
-
-       ent = spawn();
-       ent.classname = "entcs_sender_v2";
-       ent.owner = self;
+entity attach_entcs(entity e)
+{
+       entity ent = e.entcs = new(entcs_sender);
+       ent.owner = e;
        ent.think = entcs_think;
        ent.nextthink = time;
 
        Net_LinkEntity(ent, false, 0, entcs_send);
        ent.customizeentityforclient = entcs_customize;
 
-       self.entcs = ent;
-
        return ent;
 }
 
-void detach_entcs()
-{SELFPARAM();
-       remove(self.entcs);
-       self.entcs = world;
+void detach_entcs(entity e)
+{
+       if (!e.entcs) return;
+       remove(e.entcs);
+       e.entcs = NULL;
 }
index 1e875b5..1cfc854 100644 (file)
  * in onslaught... YAY ;)
  */
 
-// Beware: do not redefine those in other files
-// and NO, you cannot use ".version", which already exists (at least
-// it did when I added this) But you have to use .Version
-// Capital V
-
 .entity entcs;
 
-void entcs_init();
-
 float entcs_customize();
 
 bool entcs_send(entity this, entity to, int sf);
 
 void entcs_think();
 
-entity attach_entcs();
+entity attach_entcs(entity e);
+
+void detach_entcs(entity e);
 
-void detach_entcs();
 #endif
index efc3b95..b202f28 100644 (file)
@@ -999,22 +999,6 @@ string Map_Filename(float position)
        return strcat("maps/", argv(position), ".bsp");
 }
 
-string strwords(string s, float w)
-{
-       float endpos;
-       for(endpos = 0; w && endpos >= 0; --w)
-               endpos = strstrofs(s, " ", endpos + 1);
-       if(endpos < 0)
-               return s;
-       else
-               return substring(s, 0, endpos);
-}
-
-float strhasword(string s, string w)
-{
-       return strstrofs(strcat(" ", s, " "), strcat(" ", w, " "), 0) >= 0;
-}
-
 void Map_MarkAsRecent(string m)
 {
        cvar_set("g_maplist_mostrecent", strwords(strcat(m, " ", autocvar_g_maplist_mostrecent), max(0, autocvar_g_maplist_mostrecent_count)));
index da47be4..7aeadce 100644 (file)
@@ -92,9 +92,9 @@ float buff_Waypoint_visible_for_player(entity plr)
 void buff_Waypoint_Spawn(entity e)
 {
        entity buff = buff_FirstFromFlags(e.buffs);
-       entity wp = WaypointSprite_Spawn(WP_Buff, 0, autocvar_g_buffs_waypoint_distance, e, '0 0 1' * e.maxs.z, world, e.team, e, buff_waypoint, true, RADARICON_POWERUP);
+       entity wp = WaypointSprite_Spawn(WP_Buff, 0, autocvar_g_buffs_waypoint_distance, e, '0 0 1' * e.maxs.z, world, e.team, e, buff_waypoint, true, RADARICON_Buff);
        wp.wp_extra = buff.m_id;
-       WaypointSprite_UpdateTeamRadar(e.buff_waypoint, RADARICON_POWERUP, e.glowmod);
+       WaypointSprite_UpdateTeamRadar(e.buff_waypoint, RADARICON_Buff, e.glowmod);
        e.buff_waypoint.waypointsprite_visible_for_player = buff_Waypoint_visible_for_player;
 }
 
index e19b5d4..964b05e 100644 (file)
@@ -473,7 +473,7 @@ void Item_RespawnCountdown (void)
                                {
                                        entity wi = get_weaponinfo(self.weapon);
                                        if (wi.m_id) {
-                                               entity wp = WaypointSprite_Spawn(WP_Weapon, 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, true, RADARICON_POWERUP);
+                                               entity wp = WaypointSprite_Spawn(WP_Weapon, 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, true, RADARICON_Weapon);
                                                wp.wp_extra = wi.m_id;
                                                break;
                                        }
@@ -481,7 +481,7 @@ void Item_RespawnCountdown (void)
                                {
                                        entity ii = self.itemdef;
                                        if (ii.m_id) {
-                                               entity wp = WaypointSprite_Spawn(WP_Item, 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, true, RADARICON_POWERUP);
+                                               entity wp = WaypointSprite_Spawn(WP_Item, 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, true, RADARICON_Item);
                                                wp.wp_extra = ii.m_id;
                                                break;
                                        }
index 8f0120c..35a764c 100644 (file)
@@ -245,9 +245,6 @@ void InitGameplayMode()
                MUTATOR_ADD(gamemode_invasion);
        }
 
-       if(teamplay)
-               entcs_init();
-
        cache_mutatormsg = strzone("");
        cache_lastmutatormsg = strzone("");
 
index 8ce6eae..3ce05ac 100644 (file)
@@ -13,8 +13,6 @@ float cb1, cb2, cb3, cb4;
 
 void TeamchangeFrags(entity e);
 
-void entcs_init();
-
 void LogTeamchange(float player_id, float team_number, float type);
 
 void default_delayedinit();
index c10658f..0eaaac9 100644 (file)
@@ -587,8 +587,8 @@ bool WarpZoneLib_BadEntity(entity e)
                case "ent_client_scoreinfo":
                case "saved_cvar_value":
                case "accuracy":
-               case "entcs_sender_v2":
-               case "entcs_receiver_v2":
+               case "entcs_sender":
+               case "entcs_receiver":
                case "clientinit":
                case "sprite_waypoint":
                case "waypoint":