]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/common/physics/movetypes/movetypes.qc
Replace some per-frame physics loops with intrusive lists
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / physics / movetypes / movetypes.qc
index ef9fbdf0f16b4e66388a9d6bf8312b106c065a70..68d4c366016f922f0374e54a69a8b34ac1c9dfdd 100644 (file)
@@ -7,6 +7,8 @@ void set_movetype(entity this, int mt)
        if (mt == MOVETYPE_PHYSICS || mt == MOVETYPE_PUSH || mt == MOVETYPE_FAKEPUSH) {
                this.move_qcphysics = false;
        }
+       if(!IL_CONTAINS(g_moveables, this))
+               IL_PUSH(g_moveables, this); // add it to the moveable entities list (even if it doesn't move!) logic: if an object never sets its movetype, we assume it never does anything notable
        this.movetype = (this.move_qcphysics) ? MOVETYPE_NONE : mt;
 }
 #elif defined(CSQC)
@@ -34,8 +36,10 @@ 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
+int _Movetype_FlyMove(entity this, float dt, bool applygravity, bool applystepnormal, float stepheight) // SV_FlyMove
 {
+       move_stepnormal = '0 0 0';
+
        if(dt <= 0)
                return 0;
 
@@ -52,7 +56,7 @@ int _Movetype_FlyMove(entity this, float dt, bool applygravity, vector stepnorma
        if(applygravity)
        {
                this.move_didgravity = 1;
-               grav = dt * (PHYS_ENTGRAVITY(this) ? PHYS_ENTGRAVITY(this) : 1) * PHYS_GRAVITY(this);
+               grav = dt * (this.gravity ? this.gravity : 1) * PHYS_GRAVITY(this);
 
                if(!GAMEPLAYFIX_NOGRAVITYONGROUND || !IS_ONGROUND(this))
                {
@@ -150,8 +154,8 @@ int _Movetype_FlyMove(entity this, float dt, bool applygravity, vector stepnorma
                        // step - return it to caller
                        blocked |= 2;
                        // save the trace for player extrafriction
-                       if(stepnormal)
-                               stepnormal = trace_plane_normal;
+                       if(applystepnormal)
+                               move_stepnormal = trace_plane_normal;
                }
 
                if(my_trace_fraction >= 0.001)
@@ -322,10 +326,13 @@ void _Movetype_CheckWaterTransition(entity ent)  // SV_CheckWaterTransition
 
 void _Movetype_Impact(entity this, entity oth)  // SV_Impact
 {
-       if(gettouch(this))
+       if(!this && !oth)
+               return;
+
+       if(this.solid != SOLID_NOT && gettouch(this))
                gettouch(this)(this, oth);
 
-       if(gettouch(oth))
+       if(oth.solid != SOLID_NOT && gettouch(oth))
                gettouch(oth)(oth, this);
 }
 
@@ -348,6 +355,10 @@ 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);
                }
@@ -408,16 +419,20 @@ bool _Movetype_TestEntityPosition(vector ofs)  // SV_TestEntityPosition
     entity this = _Movetype_TestEntityPosition_ent;
        vector org = this.origin + ofs;
 
-       int cont = this.dphitcontentsmask;
-       this.dphitcontentsmask = DPCONTENTS_SOLID;
+       //int cont = this.dphitcontentsmask;
+       //this.dphitcontentsmask = DPCONTENTS_SOLID;
        tracebox(org, this.mins, this.maxs, org, ((this.move_movetype == MOVETYPE_FLY_WORLDONLY) ? MOVE_WORLDONLY : MOVE_NOMONSTERS), this);
-       this.dphitcontentsmask = cont;
+       //this.dphitcontentsmask = cont;
 
        if(trace_startsolid)
                return true;
 
        if(vdist(trace_endpos - this.origin, >, 0.0001))
-               this.origin = trace_endpos;
+       {
+               tracebox(trace_endpos, this.mins, this.maxs, trace_endpos, MOVE_NOMONSTERS, this);
+               if(!trace_startsolid)
+                       this.origin = trace_endpos;
+       }
        return false;
 }
 
@@ -428,6 +443,7 @@ int _Movetype_UnstickEntity(entity this)  // SV_UnstickEntity
            return UNSTICK_FINE;
        }
        #define X(v) if (_Movetype_TestEntityPosition(v))
+       X('0  0  -1') X(' 0  0  1')
        X('-1  0  0') X(' 1  0  0')
        X(' 0 -1  0') X(' 0  1  0')
        X('-1 -1  0') X(' 1 -1  0')
@@ -437,8 +453,8 @@ int _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(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
         {
@@ -449,7 +465,7 @@ int _Movetype_UnstickEntity(entity this)  // SV_UnstickEntity
        }
        LOG_DEBUGF("Sucessfully unstuck an entity (edict: %d, classname: %s, origin: %s)",
                etof(this), this.classname, vtos(this.origin));
-       _Movetype_LinkEdict(this, true);
+       _Movetype_LinkEdict(this, false);
        return UNSTICK_FIXED;
 }
 
@@ -505,10 +521,11 @@ bool _Movetype_PushEntity(entity this, vector push, bool failonstartsolid, bool
 {
        _Movetype_PushEntityTrace(this, push);
 
+       // NOTE: this is a workaround for the QC's lack of a worldstartsolid trace parameter
        if(trace_startsolid && failonstartsolid)
        {
                int oldtype = this.move_nomonsters;
-               this.move_nomonsters = MOVE_NOMONSTERS;
+               this.move_nomonsters = MOVE_WORLDONLY;
                _Movetype_PushEntityTrace(this, push);
                this.move_nomonsters = oldtype;
                if(trace_startsolid)
@@ -519,12 +536,10 @@ bool _Movetype_PushEntity(entity this, vector push, bool failonstartsolid, bool
 
        vector last_origin = this.origin;
 
-       if(dolink)
-               _Movetype_LinkEdict(this, true);
+       _Movetype_LinkEdict(this, dolink);
 
-       if(trace_fraction < 1)
-               if(this.solid >= SOLID_TRIGGER && (!IS_ONGROUND(this) || (this.groundentity != trace_ent)))
-                       _Movetype_Impact(this, trace_ent);
+       if((this.solid >= SOLID_TRIGGER && trace_fraction < 1 && (!IS_ONGROUND(this) || this.groundentity != trace_ent)))
+               _Movetype_Impact(this, trace_ent);
 
        return (this.origin == last_origin); // false if teleported by touch
 }
@@ -540,7 +555,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;
@@ -582,7 +597,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;
@@ -650,12 +665,14 @@ void Movetype_Physics_MatchServer(entity this, bool sloppy)
        Movetype_Physics_MatchTicrate(this, TICRATE, sloppy);
 }
 
+// saved .move_*
 .vector tic_origin;
 .vector tic_velocity;
 .int tic_flags;
 .vector tic_avelocity;
 .vector tic_angles;
 
+// saved .*
 .vector tic_saved_origin;
 .vector tic_saved_velocity;
 .int tic_saved_flags;
@@ -663,6 +680,8 @@ void Movetype_Physics_MatchServer(entity this, bool sloppy)
 .vector tic_saved_angles;
 void Movetype_Physics_MatchTicrate(entity this, float tr, bool sloppy)  // SV_Physics_Entity
 {
+       // this hack exists to contain the physics feature
+       // (so entities can place themselves in the world and not need to update .tic_* themselves)
 #define X(s) \
        if(this.(s) != this.tic_saved_##s) \
                this.tic_##s = this.(s)
@@ -674,25 +693,21 @@ void Movetype_Physics_MatchTicrate(entity this, float tr, bool sloppy)  // SV_Ph
        X(angles);
 #undef X
 
+       this.flags = this.tic_flags;
+       this.velocity = this.tic_velocity;
+       setorigin(this, this.tic_origin);
+       this.avelocity = this.tic_avelocity;
+       this.angles = this.tic_angles;
+
        if(tr <= 0)
        {
-               this.flags = this.tic_flags;
-               this.velocity = this.tic_velocity;
-               this.origin = this.tic_origin;
-               this.avelocity = this.tic_avelocity;
-               this.angles = this.tic_angles;
                Movetype_Physics_NoMatchServer(this);
-               this.tic_origin = this.origin;
-               this.tic_velocity = this.velocity;
-               this.tic_avelocity = this.avelocity;
-               this.tic_angles = this.angles;
-               this.tic_flags = this.flags;
-
-               this.tic_saved_flags = this.flags;
-               this.tic_saved_velocity = this.velocity;
-               this.tic_saved_origin = this.origin;
-               this.tic_saved_avelocity = this.avelocity;
-               this.tic_saved_angles = this.angles;
+
+               this.tic_saved_flags = this.tic_flags = this.flags;
+               this.tic_saved_velocity = this.tic_velocity = this.velocity;
+               this.tic_saved_origin = this.tic_origin = this.origin;
+               this.tic_saved_avelocity = this.tic_avelocity = this.avelocity;
+               this.tic_saved_angles = this.tic_angles = this.angles;
                return;
        }
 
@@ -705,23 +720,27 @@ void Movetype_Physics_MatchTicrate(entity this, float tr, bool sloppy)  // SV_Ph
        if(!this.move_didgravity)
                this.move_didgravity = ((this.move_movetype == MOVETYPE_BOUNCE || this.move_movetype == MOVETYPE_TOSS) && !(this.tic_flags & FL_ONGROUND));
 
-       for (int i = 0; i < n; ++i)
+       for (int j = 0; j < n; ++j)
        {
-               this.flags = this.tic_flags;
-               this.velocity = this.tic_velocity;
-               setorigin(this, this.tic_origin);
-               this.avelocity = this.tic_avelocity;
-               this.angles = this.tic_angles;
                _Movetype_Physics_Frame(this, tr);
-               this.tic_origin = this.origin;
-               this.tic_velocity = this.velocity;
-               this.tic_avelocity = this.avelocity;
-               this.tic_angles = this.angles;
-               this.tic_flags = this.flags;
                if(wasfreed(this))
                        return;
        }
 
+       // update the physics fields
+       this.tic_origin = this.origin;
+       this.tic_velocity = this.velocity;
+       this.tic_avelocity = this.avelocity;
+       this.tic_angles = this.angles;
+       this.tic_flags = this.flags;
+
+       // restore their actual values
+       this.flags = this.tic_saved_flags;
+       this.velocity = this.tic_saved_velocity;
+       setorigin(this, this.tic_saved_origin);
+       //this.avelocity = this.tic_saved_avelocity;
+       this.angles = this.tic_saved_angles;
+
        this.avelocity = this.tic_avelocity;
 
        if(dt > 0 && this.move_movetype != MOVETYPE_NONE && !(this.tic_flags & FL_ONGROUND))
@@ -733,7 +752,7 @@ void Movetype_Physics_MatchTicrate(entity this, float tr, bool sloppy)  // SV_Ph
                {
                        this.velocity_z -= (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE ? 0.5 : 1)
                            * dt
-                           * (this.gravity ? this.gravity : 1)
+                           * ((this.gravity) ? this.gravity : 1)
                            * PHYS_GRAVITY(this);
                }
 
@@ -745,16 +764,16 @@ void Movetype_Physics_MatchTicrate(entity this, float tr, bool sloppy)  // SV_Ph
                }
                else
                {
-                       vector oldorg = this.origin;
-                       this.origin = this.tic_origin;
+                       setorigin(this, this.tic_origin);
                        _Movetype_PushEntityTrace(this, dt * this.velocity);
-                       this.origin = oldorg;
                        if(!trace_startsolid)
                                setorigin(this, trace_endpos);
+                       else
+                               setorigin(this, this.tic_saved_origin);
                }
 
                if(this.move_didgravity > 0 && GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
-                       this.velocity_z -= 0.5 * dt * (this.gravity ? this.gravity : 1) * PHYS_GRAVITY(this);
+                       this.velocity_z -= 0.5 * dt * ((this.gravity) ? this.gravity : 1) * PHYS_GRAVITY(this);
        }
        else
        {
@@ -763,6 +782,8 @@ void Movetype_Physics_MatchTicrate(entity this, float tr, bool sloppy)  // SV_Ph
                setorigin(this, this.tic_origin);
        }
 
+       this.flags = this.tic_flags;
+
        this.tic_saved_flags = this.flags;
        this.tic_saved_velocity = this.velocity;
        this.tic_saved_origin = this.origin;