]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/common/physics/movetypes/movetypes.qc
Properly check against the world when trying for worldstartsolid, fixes some issues...
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / physics / movetypes / movetypes.qc
index 995c65b4d322061a7f00d0b5f0899a4480af02a4..4539466a24feb9f10d97f6652f3eb31c519af490 100644 (file)
@@ -36,11 +36,15 @@ void _Movetype_WallFriction(entity this, vector stepnormal)  // SV_WallFriction
 vector planes[MAX_CLIP_PLANES];
 int _Movetype_FlyMove(entity this, float dt, bool applygravity, vector stepnormal, float stepheight) // SV_FlyMove
 {
+       if(dt <= 0)
+               return 0;
+
        int blocked = 0;
        int i, j, numplanes = 0;
        float time_left = dt, grav = 0;
        vector push;
-       vector primal_velocity, original_velocity, restore_velocity;
+       vector primal_velocity, original_velocity;
+       vector restore_velocity = this.velocity;
 
        for(i = 0; i < MAX_CLIP_PLANES; ++i)
                planes[i] = '0 0 0';
@@ -59,7 +63,7 @@ int _Movetype_FlyMove(entity this, float dt, bool applygravity, vector stepnorma
                }
        }
 
-       original_velocity = primal_velocity = restore_velocity = this.velocity;
+       original_velocity = primal_velocity = this.velocity;
 
        for(int bumpcount = 0;bumpcount < MAX_CLIP_PLANES;bumpcount++)
        {
@@ -67,8 +71,7 @@ int _Movetype_FlyMove(entity this, float dt, bool applygravity, vector stepnorma
                        break;
 
                push = this.velocity * time_left;
-               _Movetype_PushEntity(this, push, true);
-               if(trace_startsolid)
+               if(!_Movetype_PushEntity(this, push, true, false))
                {
                        // we got teleported by a touch function
                        // let's abort the move
@@ -113,22 +116,19 @@ int _Movetype_FlyMove(entity this, float dt, bool applygravity, vector stepnorma
                        vector org = this.origin;
                        vector steppush = '0 0 1' * stepheight;
 
-                       _Movetype_PushEntity(this, steppush, true);
-                       if(trace_startsolid)
+                       if(!_Movetype_PushEntity(this, steppush, true, false))
                        {
                                blocked |= 8;
                                break;
                        }
-                       _Movetype_PushEntity(this, push, true);
-                       if(trace_startsolid)
+                       if(!_Movetype_PushEntity(this, push, true, false))
                        {
                                blocked |= 8;
                                break;
                        }
                        float trace2_fraction = trace_fraction;
-                       steppush = '0 0 1' * (org.z - this.origin_z);
-                       _Movetype_PushEntity(this, steppush, true);
-                       if(trace_startsolid)
+                       steppush = vec3(0, 0, org.z - this.origin_z);
+                       if(!_Movetype_PushEntity(this, steppush, true, false))
                        {
                                blocked |= 8;
                                break;
@@ -232,6 +232,9 @@ int _Movetype_FlyMove(entity this, float dt, bool applygravity, vector stepnorma
        if(GAMEPLAYFIX_EASIERWATERJUMP(this) && (this.flags & FL_WATERJUMP) && !(blocked & 8))
                this.velocity = primal_velocity;
 
+       if(PHYS_WALLCLIP(this) && this.pm_time && !(this.flags & FL_WATERJUMP) && !(blocked & 8))
+               this.velocity = primal_velocity;
+
        if(applygravity)
        {
                if(!GAMEPLAYFIX_NOGRAVITYONGROUND || !IS_ONGROUND(this))
@@ -345,43 +348,60 @@ void _Movetype_LinkEdict_TouchAreaGrid(entity this)  // SV_LinkEdict_TouchAreaGr
                        trace_plane_normal = '0 0 1';
                        trace_plane_dist = 0;
                        trace_ent = this;
+                       trace_dpstartcontents = 0;
+                       trace_dphitcontents = 0;
+                       trace_dphitq3surfaceflags = 0;
+                       trace_dphittexturename = string_null;
 
                        gettouch(it)(it, this);
                }
     });
 }
 
+bool autocvar__movetype_debug = false;
 void _Movetype_LinkEdict(entity this, bool touch_triggers)  // SV_LinkEdict
 {
-       vector mi, ma;
-       if(this.solid == SOLID_BSP)
-       {
-               // TODO set the absolute bbox
-               mi = this.mins;
-               ma = this.maxs;
-       }
-       else
+       if(autocvar__movetype_debug)
        {
-               mi = this.mins;
-               ma = this.maxs;
-       }
-       mi += this.origin;
-       ma += this.origin;
+               vector mi, ma;
+               if(this.solid == SOLID_BSP)
+               {
+                       // TODO set the absolute bbox
+                       mi = this.mins;
+                       ma = this.maxs;
+               }
+               else
+               {
+                       mi = this.mins;
+                       ma = this.maxs;
+               }
+               mi += this.origin;
+               ma += this.origin;
 
-       if(this.flags & FL_ITEM)
-       {
-               mi -= '15 15 1';
-               ma += '15 15 1';
+               if(this.flags & FL_ITEM)
+               {
+                       mi -= '15 15 1';
+                       ma += '15 15 1';
+               }
+               else
+               {
+                       mi -= '1 1 1';
+                       ma += '1 1 1';
+               }
+
+               this.absmin = mi;
+               this.absmax = ma;
        }
        else
        {
-               mi -= '1 1 1';
-               ma += '1 1 1';
+               setorigin(this, this.origin); // calls SV_LinkEdict
+       #ifdef CSQC
+               // NOTE: CSQC's version of setorigin doesn't expand
+               this.absmin -= '1 1 1';
+               this.absmax += '1 1 1';
+       #endif
        }
 
-       this.absmin = mi;
-       this.absmax = ma;
-
        if(touch_triggers)
                _Movetype_LinkEdict_TouchAreaGrid(this);
 }
@@ -390,11 +410,11 @@ entity _Movetype_TestEntityPosition_ent;
 bool _Movetype_TestEntityPosition(vector ofs)  // SV_TestEntityPosition
 {
     entity this = _Movetype_TestEntityPosition_ent;
-//     vector org = this.origin + ofs;
+       vector org = this.origin + ofs;
 
        int cont = this.dphitcontentsmask;
        this.dphitcontentsmask = DPCONTENTS_SOLID;
-       tracebox(this.origin, this.mins, this.maxs, this.origin, ((this.move_movetype == MOVETYPE_FLY_WORLDONLY) ? MOVE_WORLDONLY : MOVE_NOMONSTERS), this);
+       tracebox(org, this.mins, this.maxs, org, ((this.move_movetype == MOVETYPE_FLY_WORLDONLY) ? MOVE_WORLDONLY : MOVE_NOMONSTERS), this);
        this.dphitcontentsmask = cont;
 
        if(trace_startsolid)
@@ -405,11 +425,11 @@ bool _Movetype_TestEntityPosition(vector ofs)  // SV_TestEntityPosition
        return false;
 }
 
-bool _Movetype_UnstickEntity(entity this)  // SV_UnstickEntity
+int _Movetype_UnstickEntity(entity this)  // SV_UnstickEntity
 {
     _Movetype_TestEntityPosition_ent = this;
        if (!_Movetype_TestEntityPosition(' 0  0  0')) {
-           return true;
+           return UNSTICK_FINE;
        }
        #define X(v) if (_Movetype_TestEntityPosition(v))
        X('-1  0  0') X(' 1  0  0')
@@ -421,20 +441,39 @@ bool _Movetype_UnstickEntity(entity this)  // SV_UnstickEntity
         #define X(i) \
             if (_Movetype_TestEntityPosition('0 0 -1' * i)) \
             if (_Movetype_TestEntityPosition('0 0 1' * i))
-        X(01) X(02) X(03) X(04) X(05) X(06) X(07) X(08)
-        X(09) X(10) X(11) X(12) X(13) X(14) X(15) X(16)
+        X(1) X(2) X(3) X(4) X(5) X(6) X(7) X(8)
+        X(9) X(10) X(11) X(12) X(13) X(14) X(15) X(16)
         X(17)
         #undef X
         {
             LOG_DEBUGF("Can't unstick an entity (edict: %d, classname: %s, origin: %s)",
                 etof(this), this.classname, vtos(this.origin));
-            return false;
+            return UNSTICK_STUCK;
         }
        }
        LOG_DEBUGF("Sucessfully unstuck an entity (edict: %d, classname: %s, origin: %s)",
                etof(this), this.classname, vtos(this.origin));
        _Movetype_LinkEdict(this, true);
-       return true;
+       return UNSTICK_FIXED;
+}
+
+void _Movetype_CheckStuck(entity this)  // SV_CheckStuck
+{
+       int unstick = _Movetype_UnstickEntity(this); // sets test position entity
+       switch(unstick)
+       {
+               case UNSTICK_FINE:
+                       this.oldorigin = this.origin;
+                       break;
+               case UNSTICK_FIXED:
+                       break; // already sorted
+               case UNSTICK_STUCK:
+                       vector offset = this.oldorigin - this.origin;
+                       if(!_Movetype_TestEntityPosition(offset))
+                               _Movetype_LinkEdict(this, false);
+                       // couldn't unstick, should we warn about this?
+                       break;
+       }
 }
 
 vector _Movetype_ClipVelocity(vector vel, vector norm, float f)  // SV_ClipVelocity
@@ -466,20 +505,33 @@ void _Movetype_PushEntityTrace(entity this, vector push)
        tracebox(this.origin, this.mins, this.maxs, end, type, this);
 }
 
-float _Movetype_PushEntity(entity this, vector push, bool failonstartsolid)  // SV_PushEntity
+bool _Movetype_PushEntity(entity this, vector push, bool failonstartsolid, bool dolink)  // SV_PushEntity
 {
        _Movetype_PushEntityTrace(this, push);
 
+       // NOTE: this is a workaround for the QC's lack of a worldstartsolid trace parameter
        if(trace_startsolid && failonstartsolid)
-               return trace_fraction;
+       {
+               int oldtype = this.move_nomonsters;
+               this.move_nomonsters = MOVE_WORLDONLY;
+               _Movetype_PushEntityTrace(this, push);
+               this.move_nomonsters = oldtype;
+               if(trace_startsolid)
+                       return true;
+       }
 
        this.origin = trace_endpos;
 
+       vector last_origin = this.origin;
+
+       if(dolink)
+               _Movetype_LinkEdict(this, true);
+
        if(trace_fraction < 1)
-               if(this.solid >= SOLID_TRIGGER && (!IS_ONGROUND(this) || (this.groundentity != trace_ent)))
+               if(this.solid >= SOLID_TRIGGER && trace_ent && (!IS_ONGROUND(this) || (this.groundentity != trace_ent)))
                        _Movetype_Impact(this, trace_ent);
 
-       return trace_fraction;
+       return (this.origin == last_origin); // false if teleported by touch
 }
 
 
@@ -493,7 +545,7 @@ void _Movetype_Physics_Frame(entity this, float movedt)
        {
                case MOVETYPE_PUSH:
                case MOVETYPE_FAKEPUSH:
-                       LOG_DEBUGF("Physics: Lacking QuakeC support for Push movetype, FIX ME by using engine physics!");
+                       LOG_DEBUG("Physics: Lacking QuakeC support for Push movetype, FIX ME by using engine physics!");
                        break;
                case MOVETYPE_NONE:
                        break;
@@ -519,6 +571,8 @@ void _Movetype_Physics_Frame(entity this, float movedt)
                case MOVETYPE_FLY:
                case MOVETYPE_FLY_WORLDONLY:
                        _Movetype_Physics_Toss(this, movedt);
+                       if(wasfreed(this))
+                               return;
                        _Movetype_LinkEdict(this, true);
                        break;
                case MOVETYPE_PHYSICS:
@@ -533,7 +587,7 @@ void _Movetype_Physics_ClientFrame(entity this, float movedt)
        {
                case MOVETYPE_PUSH:
                case MOVETYPE_FAKEPUSH:
-                       LOG_DEBUGF("Physics: Lacking QuakeC support for Push movetype, FIX ME by using engine physics!");
+                       LOG_DEBUG("Physics: Lacking QuakeC support for Push movetype, FIX ME by using engine physics!");
                        break;
                case MOVETYPE_NONE:
                        break;
@@ -544,7 +598,6 @@ void _Movetype_Physics_ClientFrame(entity this, float movedt)
                        _Movetype_CheckWater(this);
                        this.origin = this.origin + movedt * this.velocity;
                        this.angles = this.angles + movedt * this.avelocity;
-                       _Movetype_LinkEdict(this, false);
                        break;
                case MOVETYPE_STEP:
                        _Movetype_Physics_Step(this, movedt);
@@ -563,6 +616,12 @@ void _Movetype_Physics_ClientFrame(entity this, float movedt)
                case MOVETYPE_PHYSICS:
                        break;
        }
+
+       //_Movetype_CheckVelocity(this);
+
+       _Movetype_LinkEdict(this, true);
+
+       //_Movetype_CheckVelocity(this);
 }
 
 void Movetype_Physics_NoMatchTicrate(entity this, float movedt, bool isclient)  // to be run every move frame