]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'Mario/strength_stat_field' into 'master'
authorterencehill <piuntn@gmail.com>
Wed, 6 May 2020 22:56:13 +0000 (22:56 +0000)
committerterencehill <piuntn@gmail.com>
Wed, 6 May 2020 22:56:13 +0000 (22:56 +0000)
Merge branch Mario/strength_stat_field (S merge request)

See merge request xonotic/xonotic-data.pk3dir!795

23 files changed:
effectinfo.txt
qcsrc/client/autocvars.qh
qcsrc/client/miscfunctions.qc
qcsrc/common/effects/effectinfo.inc
qcsrc/common/gamemodes/gamemode/ctf/sv_ctf.qc
qcsrc/common/mutators/mutator/bloodloss/bloodloss.qc
qcsrc/common/mutators/mutator/buffs/cl_buffs.qc
qcsrc/common/mutators/mutator/buffs/sv_buffs.qh
qcsrc/common/t_items.qc
qcsrc/common/weapons/weapon/vaporizer.qc
qcsrc/dpdefs/csprogsdefs.qh
qcsrc/dpdefs/dpextensions.qh
qcsrc/dpdefs/post.qh
qcsrc/dpdefs/progsdefs.qh
qcsrc/lib/_all.inc
qcsrc/lib/csqcmodel/cl_player.qc
qcsrc/lib/deglobalization.qh
qcsrc/menu/xonotic/util.qc
qcsrc/server/bot/default/havocbot/havocbot.qc
qcsrc/server/client.qc
qcsrc/server/miscfunctions.qc
testing.cfg
xonotic-common.cfg

index f7ee6975209a7aee47ab373d0df0de66027f3ea0..8c6a51feaa9fa55bc4ff0c15f2acc28a3a487944 100644 (file)
@@ -3418,30 +3418,6 @@ effect TE_TEI_G3PINK_HIT
        sizeincrease -6
        size 10 10
        trailspacing 40
-effect TE_TEI_G3_HIT
-       type beam
-       alpha 128 128 256
-       color 0xFFFFFF 0xFFFFFF
-       countabsolute 1
-       size 8 8
-       tex 200 200
-effect TE_TEI_G3_HIT
-       type smoke
-       airfriction -4
-       alpha 256 256 512
-       color 0xFFFFFF 0xFFFFFF
-       sizeincrease -2
-       size 2 2
-       trailspacing 20
-       velocityjitter 2 2 2
-effect TE_TEI_G3_HIT
-       type smoke
-       airfriction -4
-       alpha 256 256 512
-       color 0xFFFFFF 0xFFFFFF
-       sizeincrease -6
-       size 10 10
-       trailspacing 40
 effect particlegibs_damage_hit
        type blood
        airfriction 3
@@ -8379,3 +8355,27 @@ effect tr_bullet_weak
        trailspacing 32
        underwater
        velocityjitter 16 16 16
+effect TE_TEI_G3_HIT
+       type beam
+       alpha 128 128 256
+       color 0xFFFFFF 0xFFFFFF
+       countabsolute 1
+       size 8 8
+       tex 200 200
+effect TE_TEI_G3_HIT
+       type smoke
+       airfriction -4
+       alpha 256 256 512
+       color 0xFFFFFF 0xFFFFFF
+       sizeincrease -2
+       size 2 2
+       trailspacing 20
+       velocityjitter 2 2 2
+effect TE_TEI_G3_HIT
+       type smoke
+       airfriction -4
+       alpha 256 256 512
+       color 0xFFFFFF 0xFFFFFF
+       sizeincrease -6
+       size 10 10
+       trailspacing 40
index d125ae8a69aab4a2ec745e86a97f54283913a4a8..4c6696cde139325c341095c9f5a612aee0850d60 100644 (file)
@@ -243,7 +243,7 @@ float autocvar_hud_panel_centerprint_fade_subsequent_minfontsize = 0.75;
 float autocvar_hud_panel_centerprint_fade_minfontsize = 0;
 bool autocvar_hud_panel_centerprint_flip;
 float autocvar_hud_panel_centerprint_fontscale;
-float autocvar_hud_panel_centerprint_fontscale_bold;
+float autocvar_hud_panel_centerprint_fontscale_bold = 1.8;
 float autocvar_hud_panel_centerprint_time;
 bool autocvar_hud_panel_chat;
 bool autocvar_hud_panel_engineinfo;
index d801ceabd7d7ccde6edf099e3aacd4b6f67b1a44..1af1b971ffe91272af6cfcb915c1de041cbf49a8 100644 (file)
@@ -422,18 +422,11 @@ void PolyDrawModel(entity e)
 
 void DrawCircleClippedPic(vector centre, float radi, string pic, float f, vector rgb, float a, float drawflag)
 {
-       float d;
        vector ringsize, v, t;
        ringsize = radi * '1 1 0';
        centre = HUD_Shift(centre);
        ringsize = HUD_Scale(ringsize);
 
-       float co = cos(f * 2 * M_PI);
-       float si = sin(f * 2 * M_PI);
-       float q = fabs(co) + fabs(si);
-       co /= q;
-       si /= q;
-
        if(f >= 1)
        {
                // draw full rectangle
@@ -454,22 +447,18 @@ void DrawCircleClippedPic(vector centre, float radi, string pic, float f, vector
                        v.y -= 0.5 * ringsize.y;        t -= '0.5 -0.5 0';
                        R_PolygonVertex(v, t, rgb, a);
                R_EndPolygon();
+               return;  // Complete rectangle, nothing more needed.
+       }
 
-               d = q - 1;
-               if(d > 0)
-               {
-                       R_BeginPolygon(pic, drawflag, true);
-                               v = centre;                     t = '0.5 0.5 0';
-                               R_PolygonVertex(v, t, rgb, a);
+       float co = cos(f * 2 * M_PI);
+       float si = sin(f * 2 * M_PI);
+       float q = fabs(co) + fabs(si);
+       co /= q;
+       si /= q;
 
-                               v = centre;                     t = '0.5 0.5 0';
-                               v.x += 0.5 * ringsize.x;        t += '0.5 0.5 0';
-                               R_PolygonVertex(v, t, rgb, a);
-               }
-       }
-       else if(f > 0.75)
+       if(f > 0.75)
        {
-               // draw upper and first triangle
+               // draw upper half in full
                R_BeginPolygon(pic, drawflag, true);
                        v = centre;                     t = '0.5 0.5 0';
                        v.x += 0.5 * ringsize.x;        t += '0.5 0.5 0';
@@ -483,6 +472,7 @@ void DrawCircleClippedPic(vector centre, float radi, string pic, float f, vector
                        v.x -= 0.5 * ringsize.x;        t -= '0.5 0.5 0';
                        R_PolygonVertex(v, t, rgb, a);
                R_EndPolygon();
+               // draw clipped lower half as a quad
                R_BeginPolygon(pic, drawflag, true);
                        v = centre;                     t = '0.5 0.5 0';
                        R_PolygonVertex(v, t, rgb, a);
@@ -494,14 +484,10 @@ void DrawCircleClippedPic(vector centre, float radi, string pic, float f, vector
                        v = centre;                     t = '0.5 0.5 0';
                        v.y -= 0.5 * ringsize.y;        t -= '0.5 -0.5 0';
                        R_PolygonVertex(v, t, rgb, a);
-
-               d = q - 0.75;
-               if(d <= 0)
-                       R_EndPolygon();
        }
        else if(f > 0.5)
        {
-               // draw upper triangle
+               // draw upper half in full
                R_BeginPolygon(pic, drawflag, true);
                        v = centre;                     t = '0.5 0.5 0';
                        v.x += 0.5 * ringsize.x;        t += '0.5 0.5 0';
@@ -515,22 +501,18 @@ void DrawCircleClippedPic(vector centre, float radi, string pic, float f, vector
                        v.x -= 0.5 * ringsize.x;        t -= '0.5 0.5 0';
                        R_PolygonVertex(v, t, rgb, a);
                R_EndPolygon();
+               // draw clipped lower half as a triangle
+               R_BeginPolygon(pic, drawflag, true);
+                       v = centre;                     t = '0.5 0.5 0';
+                       R_PolygonVertex(v, t, rgb, a);
 
-               d = q - 0.5;
-               if(d > 0)
-               {
-                       R_BeginPolygon(pic, drawflag, true);
-                               v = centre;                     t = '0.5 0.5 0';
-                               R_PolygonVertex(v, t, rgb, a);
-
-                               v = centre;                     t = '0.5 0.5 0';
-                               v.x -= 0.5 * ringsize.x;        t -= '0.5 0.5 0';
-                               R_PolygonVertex(v, t, rgb, a);
-               }
+                       v = centre;                     t = '0.5 0.5 0';
+                       v.x -= 0.5 * ringsize.x;        t -= '0.5 0.5 0';
+                       R_PolygonVertex(v, t, rgb, a);
        }
        else if(f > 0.25)
        {
-               // draw first triangle
+               // draw clipped lower half as a quad
                R_BeginPolygon(pic, drawflag, true);
                        v = centre;                     t = '0.5 0.5 0';
                        R_PolygonVertex(v, t, rgb, a);
@@ -542,34 +524,30 @@ void DrawCircleClippedPic(vector centre, float radi, string pic, float f, vector
                        v = centre;                     t = '0.5 0.5 0';
                        v.y += 0.5 * ringsize.y;        t += '0.5 -0.5 0';
                        R_PolygonVertex(v, t, rgb, a);
-
-               d = q - 0.25;
-               if(d <= 0)
-                       R_EndPolygon();
        }
-       else
+       else if (f > 0)
        {
-               d = q;
-               if(d > 0)
-               {
-                       R_BeginPolygon(pic, drawflag, true);
-                               v = centre;                     t = '0.5 0.5 0';
-                               R_PolygonVertex(v, t, rgb, a);
-
-                               v = centre;                     t = '0.5 0.5 0';
-                               v.x += 0.5 * ringsize.x;        t += '0.5 0.5 0';
-                               R_PolygonVertex(v, t, rgb, a);
-               }
-       }
+               // draw clipped lower half as a triangle
+               R_BeginPolygon(pic, drawflag, true);
+                       v = centre;                     t = '0.5 0.5 0';
+                       R_PolygonVertex(v, t, rgb, a);
 
-       if(d > 0)
-       {
                        v = centre;                     t = '0.5 0.5 0';
-                       v.x += co * 0.5 * ringsize.x;   t += co * '0.5 0.5 0';
-                       v.y += si * 0.5 * ringsize.y;   t += si * '0.5 -0.5 0';
+                       v.x += 0.5 * ringsize.x;        t += '0.5 0.5 0';
                        R_PolygonVertex(v, t, rgb, a);
-               R_EndPolygon();
        }
+       else
+       {
+               // Nothing to draw.
+               return;
+       }
+
+       // The last, moving vertex.
+               v = centre;                     t = '0.5 0.5 0';
+               v.x += co * 0.5 * ringsize.x;   t += co * '0.5 0.5 0';
+               v.y += si * 0.5 * ringsize.y;   t += si * '0.5 -0.5 0';
+               R_PolygonVertex(v, t, rgb, a);
+       R_EndPolygon();
 }
 
 /** engine callback */
index 7c2dde1ed7a98ac2a061d53bb18339d92de963ca..3713e9a1abc80601fe7aece807abd579a1714790 100644 (file)
@@ -5154,49 +5154,6 @@ TE_TEI_G3(YELLOW, "0xffff00", "0xffff11", "0x202000", "0x404000")
 TE_TEI_G3(PINK, "0xFF00FF", "0xFF11FF", "0x200020", "0x400040")
 #undef TE_TEI_G3
 
-// Vaporizer hit effect
-DEF(TE_TEI_G3_HIT);
-SUB(TE_TEI_G3_HIT) {
-       MY(alpha_min) = 128;
-       MY(alpha_max) = 128;
-       MY(alpha_fade) = 256;
-       MY(color_min) = "0xFFFFFF";
-       MY(color_max) = "0xFFFFFF";
-       MY(countabsolute) = 1;
-       MY(size_min) = 8;
-       MY(size_max) = 8;
-       MY(tex_min) = 200;
-       MY(tex_max) = 200;
-       MY(type) = "beam";
-}
-SUB(TE_TEI_G3_HIT) /* rings */ {
-       MY(airfriction) = -4;
-       MY(alpha_min) = 256;
-       MY(alpha_max) = 256;
-       MY(alpha_fade) = 512;
-       MY(color_min) = "0xFFFFFF";
-       MY(color_max) = "0xFFFFFF";
-       MY(sizeincrease) = -2;
-       MY(size_min) = 2;
-       MY(size_max) = 2;
-       MY(trailspacing) = 20;
-       MY(type) = "smoke";
-       MY(velocityjitter) = '2.0 2.0 2.0';
-}
-SUB(TE_TEI_G3_HIT) {
-       MY(airfriction) = -4;
-       MY(alpha_min) = 256;
-       MY(alpha_max) = 256;
-       MY(alpha_fade) = 512;
-       MY(color_min) = "0xFFFFFF";
-       MY(color_max) = "0xFFFFFF";
-       MY(sizeincrease) = -6;
-       MY(size_min) = 10;
-       MY(size_max) = 10;
-       MY(trailspacing) = 40;
-       MY(type) = "smoke";
-}
-
 #include "effectinfo_gentle_particlegibs.inc"
 
 #include "effectinfo_onslaught.inc"
@@ -9086,3 +9043,46 @@ SUB(tr_bullet_weak) {
        MY(underwater) = true;
        MY(velocityjitter) = '16.0 16.0 16.0';
 }
+
+// Vaporizer hit effect
+DEF(TE_TEI_G3_HIT);
+SUB(TE_TEI_G3_HIT) {
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 128;
+       MY(alpha_fade) = 256;
+       MY(color_min) = "0xFFFFFF";
+       MY(color_max) = "0xFFFFFF";
+       MY(countabsolute) = 1;
+       MY(size_min) = 8;
+       MY(size_max) = 8;
+       MY(tex_min) = 200;
+       MY(tex_max) = 200;
+       MY(type) = "beam";
+}
+SUB(TE_TEI_G3_HIT) /* rings */ {
+       MY(airfriction) = -4;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 512;
+       MY(color_min) = "0xFFFFFF";
+       MY(color_max) = "0xFFFFFF";
+       MY(sizeincrease) = -2;
+       MY(size_min) = 2;
+       MY(size_max) = 2;
+       MY(trailspacing) = 20;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '2.0 2.0 2.0';
+}
+SUB(TE_TEI_G3_HIT) {
+       MY(airfriction) = -4;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 512;
+       MY(color_min) = "0xFFFFFF";
+       MY(color_max) = "0xFFFFFF";
+       MY(sizeincrease) = -6;
+       MY(size_min) = 10;
+       MY(size_max) = 10;
+       MY(trailspacing) = 40;
+       MY(type) = "smoke";
+}
index cfe8d4058d983d42a4ceca3c45e74706b72a99b3..9f38cd9c36252dfe596b2a62e92fc849d2462682 100644 (file)
@@ -1147,6 +1147,7 @@ METHOD(Flag, giveTo, bool(Flag this, entity flag, entity toucher))
 .float last_respawn;
 void ctf_RespawnFlag(entity flag)
 {
+       flag.watertype = CONTENT_EMPTY; // TODO: it is unclear why this workaround is needed, likely many other potential breakage points!!
        // check for flag respawn being called twice in a row
        if(flag.last_respawn > time - 0.5)
                { backtrace("flag respawn called twice quickly! please notify Samual about this..."); }
index 2a0ebec455a3016b192630684880ab66703dcbd5..41ceaa91fab751c6bfa7761d77f15cdc44ff9058 100644 (file)
@@ -57,12 +57,12 @@ MUTATOR_HOOKFUNCTION(bloodloss, BuildMutatorsPrettyString)
 #ifdef CSQC
 MUTATOR_HOOKFUNCTION(bloodloss, PlayerCanCrouch)
 {
-       if(STAT(HEALTH) <= STAT(BLOODLOSS))
+       if(STAT(HEALTH) > 0 && STAT(HEALTH) <= STAT(BLOODLOSS))
                M_ARGV(1, bool) = true; // do_crouch
 }
 MUTATOR_HOOKFUNCTION(bloodloss, PlayerJump)
 {
-       if(STAT(HEALTH) <= STAT(BLOODLOSS))
+       if(STAT(HEALTH) > 0 && STAT(HEALTH) <= STAT(BLOODLOSS))
                return true;
 }
 #endif
index 790a10a86b8f16da4b5f0f0f65900d1813ca89a2..349ca20b872c17f468117dccecaa1152128778ca 100644 (file)
@@ -3,10 +3,11 @@
 REGISTER_MUTATOR(cl_buffs, true);
 MUTATOR_HOOKFUNCTION(cl_buffs, HUD_Powerups_add)
 {
-    int allBuffs = STAT(BUFFS);
-    FOREACH(Buffs, it.m_itemid & allBuffs, {
-               addPowerupItem(it.m_name, strcat("buff_", it.netname), it.m_color, bound(0, STAT(BUFF_TIME) - time, 99), 60);
-       });
+       int allBuffs = STAT(BUFFS);
+       if (allBuffs)
+               FOREACH(Buffs, it.m_itemid & allBuffs, {
+                       addPowerupItem(it.m_name, strcat("buff_", it.netname), it.m_color, bound(0, STAT(BUFF_TIME) - time, 99), 60);
+               });
 }
 MUTATOR_HOOKFUNCTION(cl_buffs, WP_Format)
 {
index 88efc94ebb298e7df9158a872a274abb22e14fce..b585811873758a94aee4a68592364f36ca749005 100644 (file)
@@ -82,3 +82,5 @@ const vector BUFF_MAX = ('16 16 60');
 
 // client side options
 .float cvar_cl_buffs_autoreplace;
+
+float buff_Available(entity buff);
index 213410543961917eea730055a65f123f2060d111..0fcc35a31cbaf069b0533f76149a67125e2fdef3 100644 (file)
@@ -23,6 +23,7 @@
     #include <common/weapons/_all.qh>
 
     #include <common/mutators/mutator/buffs/buffs.qh>
+       #include <common/mutators/mutator/buffs/sv_buffs.qh>
 
     #include "../lib/warpzone/util_server.qh"
 #elif defined(CSQC)
@@ -1618,28 +1619,36 @@ float GiveWeapon(entity e, float wpn, float op, float val)
 bool GiveBuff(entity e, Buff thebuff, int op, int val)
 {
        bool had_buff = (STAT(BUFFS, e) & thebuff.m_itemid);
+       float new_buff_time = ((had_buff) ? STAT(BUFF_TIME, e) : 0);
        switch (op)
        {
                case OP_SET:
-                       STAT(BUFF_TIME, e) = val;
+                       new_buff_time = val;
                        break;
                case OP_MIN:
-                       STAT(BUFF_TIME, e) = max(STAT(BUFF_TIME, e), val);
+                       new_buff_time = max(new_buff_time, val);
                        break;
                case OP_MAX:
-                       STAT(BUFF_TIME, e) = min(STAT(BUFF_TIME, e), val);
+                       new_buff_time = min(new_buff_time, val);
                        break;
                case OP_PLUS:
-                       STAT(BUFF_TIME, e) += val;
+                       new_buff_time += val;
                        break;
                case OP_MINUS:
-                       STAT(BUFF_TIME, e) -= val;
+                       new_buff_time -= val;
                        break;
        }
-       if(STAT(BUFF_TIME, e) <= 0)
+       if(new_buff_time <= 0)
+       {
+               if(had_buff)
+                       STAT(BUFF_TIME, e) = new_buff_time;
                STAT(BUFFS, e) &= ~thebuff.m_itemid;
+       }
        else
+       {
+               STAT(BUFF_TIME, e) = new_buff_time;
                STAT(BUFFS, e) = thebuff.m_itemid; // NOTE: replaces any existing buffs on the player!
+       }
        bool have_buff = (STAT(BUFFS, e) & thebuff.m_itemid);
        return (had_buff != have_buff);
 }
@@ -1827,7 +1836,7 @@ float GiveItems(entity e, float beginarg, float endarg)
                                got += GiveResourceValue(e, RES_FUEL, op, val);
                                break;
                        default:
-                               FOREACH(Buffs, it != BUFF_Null && Buff_UndeprecateName(cmd) == it.netname,
+                               FOREACH(Buffs, it != BUFF_Null && buff_Available(it) && Buff_UndeprecateName(cmd) == it.netname,
                                {
                                        got += GiveBuff(e, it, op, val);
                                        break;
index cfdbe7b7e933461e0566c9a053255fe9f418da22..e71ed7478a327227a021e91491aaf352bec50784 100644 (file)
@@ -280,7 +280,7 @@ void W_RocketMinsta_Attack3 (entity actor, .entity weaponentity)
 
 METHOD(Vaporizer, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
 {
-    if(GetResource(actor, thiswep.ammo_type) > 0)
+    if((actor.items & IT_UNLIMITED_AMMO) || GetResource(actor, thiswep.ammo_type) > 0)
         PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, weaponentity, 1000000, 0, 1, false);
     else
         PHYS_INPUT_BUTTON_ATCK2(actor) = bot_aim(actor, weaponentity, WEP_CVAR_SEC(vaporizer, speed), 0, WEP_CVAR_SEC(vaporizer, lifetime), false); // WEAPONTODO: replace with proper vaporizer cvars
index 9453157f7000591bf273c07ed20aff7438404636..eaea70f5e9eb33d3fb45377a5d1c6e907aa5d119 100644 (file)
 #undef STAT_MOVEVARS_TIMESCALE
 #undef STAT_MOVEVARS_GRAVITY
 
-#pragma noref 0
-
 #define use use1
 .void(entity this, entity actor, entity trigger) use;
 #define touch move_touch
 
-// deglobalization:
-
 void(vector ang) _makevectors_hidden = #1;
-//#define makevectors DO_NOT_USE_GLOBALS_PREFER_MAKE_VECTORS_MACRO_INSTEAD
-
-#define makestatic DO_NOT_USE_GLOBALS // not used anywhere so not wrapped
-
-#define skel_get_bonerel DO_NOT_USE_GLOBALS // not used anywhere so not wrapped
-
 vector(float skel, float bonenum) _skel_get_boneabs_hidden = #270;
-//#define skel_get_boneabs DO_NOT_USE_GLOBALS_PREFER_SKEL_GET_BONE_ABS_MACRO_INSTEAD
-
 void(float skel, float bonenum, vector org) _skel_set_bone_hidden = #271;
-//#define skel_set_bone DO_NOT_USE_GLOBALS_PREFER_SKEL_SET_BONE_MACRO_INSTEAD
-
-#define skel_mul_bone DO_NOT_USE_GLOBALS // not used anywhere so not wrapped
-
-#define skel_mul_bones DO_NOT_USE_GLOBALS // not used anywhere so not wrapped
-
 void(vector org, float radius, vector lightcolours) _adddynamiclight_hidden = #305;
-//#define adddynamiclight DO_NOT_USE_GLOBALS_PREFER_ADD_DYNAMIC_LIGHT_MACRO_INSTEAD
-#define adddynamiclight2 DO_NOT_USE_GLOBALS // not used anywhere so not wrapped
-
 void(vector dir) _vectorvectors_hidden = #432;
-#define vectorvectors DO_NOT_USE_GLOBALS_PREFER_VECTOR_VECTORS_MACRO_INSTEAD
-
 vector(entity ent, float tagindex) _gettaginfo_hidden = #452;
-//#define gettaginfo DO_NOT_USE_GLOBALS_PREFER_GET_TAG_INFO_MACRO_INSTEAD
 
-#define getentity DO_NOT_USE_GLOBALS // not used anywhere so not wrapped
-#define getentityvec DO_NOT_USE_GLOBALS // not used anywhere so not wrapped
+#pragma noref 0
index d6f6a072a0fea688e192219b28e21184a8c7b76b..578d58b27b3c2f68477973fa37035c7dd9cb8347 100644 (file)
@@ -62,21 +62,8 @@ int(string s1, string s2, int len) _strncasecmp = #230;
 int() _buf_create = #460;
 #define buf_create _buf_create
 
-#pragma noref 0
-
-// deglobalization:
-
-#define skel_get_bonerel DO_NOT_USE_GLOBALS // not used anywhere so not wrapped
-
 vector(float skel, float bonenum) _skel_get_boneabs_hidden = #270;
-//#define skel_get_boneabs DO_NOT_USE_GLOBALS_PREFER_SKEL_GET_BONE_ABS_MACRO_INSTEAD
-
 void(float skel, float bonenum, vector org) _skel_set_bone_hidden = #271;
-//#define skel_set_bone DO_NOT_USE_GLOBALS_PREFER_SKEL_SET_BONE_MACRO_INSTEAD
-
-#define skel_mul_bone DO_NOT_USE_GLOBALS // not used anywhere so not wrapped
-
-#define skel_mul_bones DO_NOT_USE_GLOBALS // not used anywhere so not wrapped
-
 vector(entity ent, float tagindex) _gettaginfo_hidden = #452;
-//#define gettaginfo DO_NOT_USE_GLOBALS_PREFER_GET_TAG_INFO_MACRO_INSTEAD
+
+#pragma noref 0
index 70e5f378422af7850a91ec65cf8857d6c61ae0d8..93ea3612b7cc50e1fc19547f767a0ce077554b04 100644 (file)
 #else
        #define NULL (RVALUE, world)
 #endif
+
+// Shadow functions which use globals - see deglobalization.qh for details.
+#define makevectors DO_NOT_USE_GLOBALS_PREFER_MAKE_VECTORS_MACRO_INSTEAD
+#define aim DO_NOT_USE_GLOBALS
+#define makestatic DO_NOT_USE_GLOBALS
+#define skel_get_bonerel DO_NOT_USE_GLOBALS
+#define skel_get_boneabs DO_NOT_USE_GLOBALS_PREFER_SKEL_GET_BONE_ABS_MACRO_INSTEAD
+#define skel_set_bone DO_NOT_USE_GLOBALS_PREFER_SKEL_SET_BONE_MACRO_INSTEAD
+#define skel_mul_bone DO_NOT_USE_GLOBALS
+#define skel_mul_bones DO_NOT_USE_GLOBALS
+#define adddynamiclight DO_NOT_USE_GLOBALS_PREFER_ADD_DYNAMIC_LIGHT_MACRO_INSTEAD
+#define adddynamiclight2 DO_NOT_USE_GLOBALS
+#define vectorvectors DO_NOT_USE_GLOBALS_PREFER_VECTOR_VECTORS_MACRO_INSTEAD
+#define gettaginfo DO_NOT_USE_GLOBALS_PREFER_GET_TAG_INFO_MACRO_INSTEAD
+#define getentity DO_NOT_USE_GLOBALS
+#define getentityvec DO_NOT_USE_GLOBALS
index a8d8a4a486a0824cb200182a176ebf856762f8ed..f4e2bdaf7b182777ea2fdfcfb417112a19450b2b 100644 (file)
     if (IS_REAL_CLIENT(_cl)) stuffcmd(_cl, __VA_ARGS__); \
 MACRO_END
 
-#pragma noref 0
-
 #define use use1
 .void(entity this, entity actor, entity trigger) use;
 
-// deglobalization:
-
 void(vector ang) _makevectors_hidden = #1;
-//#define makevectors DO_NOT_USE_GLOBALS_PREFER_MAKE_VECTORS_MACRO_INSTEAD
 
-#define aim DO_NOT_USE_GLOBALS // not used anywhere so not wrapped
-
-#define makestatic DO_NOT_USE_GLOBALS // not used anywhere so not wrapped
+#pragma noref 0
index 3bbb17ccf8715ddfced52d63453e41e7f40cc3e2..0bef0b6e0e944feebfe54c14fea8728a9bc6d295 100644 (file)
 
 #include "warpzone/mathlib.qc"
 
+// needs to be included before any of the functions which use globals are called
+#include "deglobalization.qh"
+
 #include "accumulate.qh"
 #include "angle.qc"
 #include "arraylist.qh"
 #include "counting.qh"
 #include "cvar.qh"
 #include "defer.qh"
-#include "deglobalization.qh"
 #include "draw.qh"
 #include "enumclass.qh"
 #include "file.qh"
index 25fd5cdfa1d84874bf5bb70939ee35f027141e3b..a5610b3de4024428a748bb7aaf375376d569e827 100644 (file)
@@ -108,6 +108,8 @@ void CSQCPlayer_SetMinsMaxs(entity this)
        {
                this.mins = PHYS_PL_MIN(this);
                this.maxs = PHYS_PL_MAX(this);
+               if (IS_DEAD(this))
+                       this.maxs.z = 5;
                this.view_ofs = PHYS_PL_VIEWOFS(this);
        }
 }
@@ -567,7 +569,8 @@ void CSQCPlayer_SetCamera()
 #endif
                        CSQCPlayer_SetMinsMaxs(e);
 
-                       e.angles_y = input_angles.y;
+                       if (!IS_DEAD(e))
+                               e.angles.y = input_angles.y;
                }
 
                // relink
index 3d7f82067440137e64db91a8bc7c78cf53c5ca37..3f71fd8ace4cf920e5a036047208b14b20f8bdeb 100644 (file)
@@ -1,40 +1,85 @@
+#include "lib/accumulate.qh"
 #include "lib/float.qh"
+#include "lib/log.qh"
 #include "lib/misc.qh"
 #include "lib/static.qh"
 #include "lib/vector.qh"
 
-// These macros wrap functions which use globals so mutation only occurs inside them and is not visible from outside.
-// Functions for which all usages are replaced with these macros can be hidden by #defines inside our `*defs.qh` files
-// to prevent anyone from using them accidentally in the future
+// These macros wrap functions which use globals so mutation of global state only occurs inside them and is not visible from outside.
+// This helps prevent bugs where refactoring accidentally breaks implicit assumptions about global state ("pls call makevectors before calling this").
+// Currently only functions that use v_forward/v_right/v_up are wrapped since those are most common.
+// Some functions don't have wrappers because they're not used anywhere.
 
-// TODO stuff in the engine that uses the v_forward/v_right/v_up globals and is not wrapped yet:
-//  - RF_USEAXIS, addentities, predraw,
-//    - CL_GetEntityMatrix (in engine but is called from other functions so transitively any of them can use the globals - e.g. V_CalcRefdef, maybe others)
-//    - however RF_USEAXIS is only used if MF_ROTATE is used which is only set in one place
-//  - e.camera_transform / CL_VM_TransformView (in engine)
-//    - this is the only used function that both sets and gets the globals (aim does too but isn't used in our code)
+// Steps (slightly inspired by steps in self.qh):
+// 1) (done) Create alternative names for the builtins (e.g. _makevectors_hidden) to be used inside wrappers.
+//    Shadow the originals with macros that tell the user to use the wrappers instead. These are in the *defs.qh files.
+// 2) Create wrapper macros with the same name (e.g. makevectors) that still use globals but log their usage.
+//     - Would be nice to also log reads and writes to the globals themselves. Probably possible with macros, comma expressions and [[alias]].
+// 3) Create wrapper macros that use locals (e.g. MAKE_VECTORS).
+//    TODO stuff in the engine that uses the v_forward/v_right/v_up globals and is not wrapped yet:
+//     - RF_USEAXIS, addentities, predraw,
+//       - CL_GetEntityMatrix (in engine but is called from other functions so transitively any of them can use the globals - e.g. V_CalcRefdef, maybe others)
+//       - however RF_USEAXIS is only used if MF_ROTATE is used which is only set in one place
+//     - e.camera_transform / CL_VM_TransformView (in engine)
+//       - this is the only used function that both sets and gets the globals (aim does too but isn't used in our code)
+// 4) Gradually replace uses of each function with its wrapper.
+// 5) When a function is no longer used, remove the wrapper with the same name to cause compile errors that will prevent accidental use in the future.
 
-// convenience for deglobalization code - don't use these just to hide that globals are still used
-#define CLEAR_V_GLOBALS() v_forward = VEC_NAN; v_right = VEC_NAN; v_up = VEC_NAN
-#define GET_V_GLOBALS(forward, right, up) forward = v_forward; right = v_right; up = v_up
-#define SET_V_GLOBALS(forward, right, up) v_forward = forward; v_right = right; v_up = up
+// Final checking:
+// When all functions which use a global have been replaced with the wrappers,
+// the wrappers can check that the global contains NaN before its use and set it to NaN after its use.
+// This should detect if there is any remaining global mutation (even in the engine).
+// NaN is the most likely value to expose remaining usages - e.g. functions like traceline crash on it.
+
+#ifdef GAMEQC // menu doesn't use any globals
+
+// compile time switches in case perf is an issue
+#define DEGLOB_LOGGING 1
+#define DEGLOB_CLEAR 1
+
+const int DEGLOB_ORIGINAL = 1;
+const int DEGLOB_WRAPPED = 2;
+#if DEGLOB_LOGGING
+int autocvar_debug_deglobalization_logging = 0;
+// Varargs to this should already be stringized, otherwise they're expanded first which makes them less readable.
+// The downside is redundant quotes, fortunately none of these functions take strings.
+#define DEGLOB_LOG(kind, name, ...) deglob_log(kind, name, __FILE__, __LINE__, __FUNC__, #__VA_ARGS__)
+// This needs to be a function, not a macro,
+// because some wrappers of the old functions need to use comma expressions
+// because they return values.
+void deglob_log(int kind, string name, string file, int line, string func, string more_text) {
+       if (autocvar_debug_deglobalization_logging & kind) {
+               LOG_INFOF("%s %f %s %s:%d:%s args: %s", PROGNAME, time, name, file, line, func, more_text);
+       }
+}
+#else
+#define DEGLOB_LOG(kind, name, ...)
+void deglob_log(int kind, string name, string file, int line, string func, string more_text) {}
+#endif
 
-#ifdef GAMEQC
+// convenience for deglobalization code - don't use these just to hide that globals are still used
+#define GET_V_GLOBALS(forward, right, up) MACRO_BEGIN forward = v_forward; right = v_right; up = v_up; MACRO_END
+#define SET_V_GLOBALS(forward, right, up) MACRO_BEGIN v_forward = forward; v_right = right; v_up = up; MACRO_END
+#if DEGLOB_CLEAR
+bool autocvar_debug_deglobalization_clear = true;
+#define CLEAR_V_GLOBALS() MACRO_BEGIN \
+       if (autocvar_debug_deglobalization_clear) { \
+               v_forward = VEC_NAN; v_right = VEC_NAN; v_up = VEC_NAN \
+       } \
+MACRO_END
 STATIC_INIT(globals) {
        // set to NaN to more easily detect uninitialized use
-       // TODO when all functions are wrapped and the raw functions are not used anymore,
-       // uncomment the defines in *progs.qh files that hide the raw functions
-       // and assert that the global vectors are NaN before calling the raw functions here
-       // to make sure nobody (even builtins) is accidentally using them - NaN is the most likely value to expose remaining usages
-
        CLEAR_V_GLOBALS();
 }
+#else
+#define CLEAR_V_GLOBALS()
 #endif
 
 /// Same as the `makevectors` builtin but uses the provided locals instead of the `v_*` globals.
 /// Always use this instead of raw `makevectors` to make the data flow clear.
 /// Note that you might prefer `FIXED_MAKE_VECTORS` for new code.
 #define MAKE_VECTORS(angles, forward, right, up) MACRO_BEGIN \
+       DEGLOB_LOG(DEGLOB_WRAPPED, "MAKE_VECTORS", #angles); \
        _makevectors_hidden(angles); \
        GET_V_GLOBALS(forward, right, up); \
        CLEAR_V_GLOBALS(); \
@@ -42,24 +87,28 @@ MACRO_END
 
 /// Returns all 4 vectors by assigning to them (instead of returning a value) for consistency (and sanity)
 #define SKEL_GET_BONE_ABS(skel, bonenum, forward, right, up, origin) MACRO_BEGIN \
+       DEGLOB_LOG(DEGLOB_WRAPPED, "SKEL_GET_BONE_ABS", #skel, #bonenum); \
        origin = _skel_get_boneabs_hidden(skel, bonenum) \
        GET_V_GLOBALS(forward, right, up); \
        CLEAR_V_GLOBALS(); \
 MACRO_END
 
 #define SKEL_SET_BONE(skel, bonenum, org, forward, right, up) MACRO_BEGIN \
+       DEGLOB_LOG(DEGLOB_WRAPPED, "SKEL_SET_BONE", #skel, #bonenum, #org); \
        SET_V_GLOBALS(forward, right, up); \
        _skel_set_bone_hidden(skel, bonenum, org); \
        CLEAR_V_GLOBALS(); \
 MACRO_END
 
 #define ADD_DYNAMIC_LIGHT(org, radius, lightcolours, forward, right, up) MACRO_BEGIN \
+       DEGLOB_LOG(DEGLOB_WRAPPED, "ADD_DYNAMIC_LIGHT", #org, #radius, #lightcolours); \
        SET_V_GLOBALS(forward, right, up); \
        _adddynamiclight_hidden(org, radius, lightcolours); \
        CLEAR_V_GLOBALS(); \
 MACRO_END
 
 #define VECTOR_VECTORS(forward_in, forward, right, up) MACRO_BEGIN \
+       DEGLOB_LOG(DEGLOB_WRAPPED, "VECTOR_VECTORS", #forward_in); \
        _vectorvectors_hidden(forward_in); \
        GET_V_GLOBALS(forward, right, up); \
        CLEAR_V_GLOBALS(); \
@@ -67,7 +116,40 @@ MACRO_END
 
 /// Note that this only avoids the v_* globals, not the gettaginfo_* ones
 #define GET_TAG_INFO(ent, tagindex, forward, right, up, origin) MACRO_BEGIN \
+       DEGLOB_LOG(DEGLOB_WRAPPED, "GET_TAG_INFO", #ent, #tagindex); \
        origin = _gettaginfo_hidden(ent, tagindex); \
        GET_V_GLOBALS(forward, right, up); \
        CLEAR_V_GLOBALS(); \
 MACRO_END
+
+#undef makevectors
+#define makevectors(angles) MACRO_BEGIN \
+       DEGLOB_LOG(DEGLOB_ORIGINAL, "makevectors", #angles); \
+       _makevectors_hidden(angles); \
+MACRO_END
+
+#undef skel_get_boneabs
+#define skel_get_boneabs(skel, bonenum) ( \
+       deglob_log(DEGLOB_ORIGINAL, "skel_get_boneabs", __FILE__, __LINE__, __FUNC__, #skel ", " #bonenum), \
+       _skel_get_boneabs_hidden(skel, bonenum) \
+)
+
+#undef skel_set_bone
+#define skel_set_bone(skel, bonenum, org) MACRO_BEGIN \
+       DEGLOB_LOG(DEGLOB_ORIGINAL, "skel_set_bone", #skel, #bonenum, #org); \
+       _skel_set_bone_hidden(skel, bonenum, org); \
+MACRO_END
+
+#undef adddynamiclight
+#define adddynamiclight(org, radius, lightcolours) MACRO_BEGIN \
+       DEGLOB_LOG(DEGLOB_ORIGINAL, "adddynamiclight", #org, #radius, #lightcolours); \
+       _adddynamiclight_hidden(org, radius, lightcolours); \
+MACRO_END
+
+#undef gettaginfo
+#define gettaginfo(ent, tagindex) ( \
+       deglob_log(DEGLOB_ORIGINAL, "gettaginfo", __FILE__, __LINE__, __FUNC__, #ent ", " #tagindex), \
+       _gettaginfo_hidden(ent, tagindex) \
+)
+
+#endif // GAMEQC
index a126b9e5da2713f68fc1cf4f952950a035aadec8..5e9fdb03d96d9a0ab079810d52fe799fdbf41625 100644 (file)
@@ -127,6 +127,7 @@ void makeCallback(entity e, entity cbent, void(entity, entity) cbfunc)
 .bool disabled;
 void setDependent_Check(entity e)
 {
+       bool disabled_prev = e.disabled;
        float f;
        string s;
        if(e.func_setDependent)
@@ -165,6 +166,8 @@ void setDependent_Check(entity e)
                                e.disabled = (e.disabled + ((f >= e.cvar3Max_setDependent) && (f <= e.cvar3Min_setDependent)) > e.op_setDependent);
                }
        }
+       if (disabled_prev != e.disabled && e.loadCvars)
+               e.loadCvars(e);
 }
 void setDependent_Draw(entity e)
 {
index db56478f87eadd33a7c63ba318d575b8e5d80215..f5587d69dc87176b980b38080ecdbc4ecef26772 100644 (file)
@@ -48,7 +48,7 @@ void havocbot_ai(entity this)
                else
                {
                        if (!this.jumppadcount && !STAT(FROZEN, this)
-                               && !(this.goalcurrent_prev && (this.goalcurrent_prev.wpflags & WAYPOINTFLAG_JUMP)))
+                               && !(this.goalcurrent_prev && (this.goalcurrent_prev.wpflags & WAYPOINTFLAG_JUMP) && !IS_ONGROUND(this)))
                        {
                                // find a new goal
                                this.havocbot_role(this); // little too far down the rabbit hole
index 76bb8f8c2f33128a1a4f538b8f3d7309f8b27586..6feb1cda3b7d486446a4c8597253e69a33378bf6 100644 (file)
@@ -2271,7 +2271,8 @@ void ObserverThink(entity this)
                        if(this.flags & FL_SPAWNING)
                        {
                                this.flags &= ~FL_SPAWNING;
-                               Join(this);
+                               if(joinAllowed(this))
+                                       Join(this);
                                return;
                        }
                }
index 4e2113f53fe3baf148c7c7308c371c51efc45c87..9dd468c2d74982c15a6e83691debb4b4c9254bcb 100644 (file)
@@ -856,9 +856,14 @@ void readplayerstartcvars()
 
 void precache_playermodel(string m)
 {
-       float globhandle, i, n;
+       int globhandle, i, n;
        string f;
 
+       // remove :<skinnumber> suffix
+       int j = strstrofs(m, ":", 0);
+       if(j >= 0)
+               m = substring(m, 0, j);
+
        if(substring(m, -9, 5) == "_lod1")
                return;
        if(substring(m, -9, 5) == "_lod2")
index 58df92720d14048b7bae33a3fb3a073d5850cb38..f000a084aacbe22fa29ceee679c29ee679947323 100644 (file)
@@ -1,8 +1,7 @@
 // https://forums.xonotic.org/showthread.php?tid=8190
 // https://gitlab.com/xonotic/xonotic-data.pk3dir/merge_requests/738
-alias test_blaster_switch "settemp g_balance_blaster_primary_animtime 0.1 ; settemp g_balance_blaster_switchdelay_drop 0.1 ; g_balance_blaster_switchdelay_raise 0.1"
+alias test_blaster_switch "settemp g_balance_blaster_primary_animtime 0.1 ; settemp g_balance_blaster_switchdelay_drop 0.1 ; settemp g_balance_blaster_switchdelay_raise 0.1"
 
-// https://gitlab.com/xonotic/xonotic-data.pk3dir/merge_requests/614
 alias test_crylink_sec_horizontal "settemp g_balance_crylink_secondary_linkexplode 0 ; settemp g_balance_crylink_secondary_other_fadetime 2 ; settemp g_balance_crylink_secondary_other_lifetime 2 ; settemp g_balance_crylink_secondary_speed 4000 ; settemp g_balance_crylink_secondary_spread 0.08 ; settemp g_balance_crylink_secondary_spreadtype 0"
 
 alias test_rocket_flying "settemp g_balance_devastator_remote_jump 1"
index 4fd0ee0c1488965a1eae4bd06164ab018a710b4e..7a2c4611ad2ce287500b5cf3aa91827621f7c4ca 100644 (file)
@@ -144,6 +144,9 @@ seta snd_channel9volume 1 "QuakeC controlled ambient sound volume"
 snd_identicalsoundrandomization_time -0.1
 snd_identicalsoundrandomization_tics    1
 
+set debug_deglobalization_logging 0 "bitfield: 1 logs usage of the old functions which use globals implicitly, 2 logs usage of the new wrappers; support for this can be disabled at compile time for better performance"
+set debug_deglobalization_clear 0 "make the new wrappers set globals to NaN after use, this helps find bugs but can result in crashes; support for this can be disabled at compile time for better performance"
+
 // load console command aliases and settings
 exec commands.cfg