]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/common/physics/movetypes/push.qc
Rename t_items.qc to items.qc
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / physics / movetypes / push.qc
index 5a0426edce7ffba41c69eb48b8c293a1b5c07b46..66ff42a69f30b4ca5ab8584ca1cae7edef23b2cf 100644 (file)
-void _Movetype_PushMove(entity this, float dt)  // SV_PushMove
+#include "push.qh"
+void _Movetype_PushMove(entity this, float dt) // SV_PushMove
 {
-       if (this.move_velocity == '0 0 0' && this.move_avelocity == '0 0 0')
+       if(this.velocity == '0 0 0' && this.avelocity == '0 0 0')
        {
-               this.move_ltime += dt;
+               this.ltime += dt;
                return;
        }
 
-       switch (this.solid)
+       switch(this.solid)
        {
-               // LordHavoc: valid pusher types
+               // LadyHavoc: valid pusher types
                case SOLID_BSP:
                case SOLID_BBOX:
                case SOLID_SLIDEBOX:
-               case SOLID_CORPSE:  // LordHavoc: this would be weird...
+               case SOLID_CORPSE: // LadyHavoc: this would be weird...
                        break;
-               // LordHavoc: no collisions
+               // LadyHavoc: no collisions
                case SOLID_NOT:
                case SOLID_TRIGGER:
-                       this.move_origin = this.move_origin + dt * this.move_velocity;
-                       this.move_angles = this.move_angles + dt * this.move_avelocity;
-                       this.move_angles_x -= 360.0 * floor(this.move_angles.x * (1.0 / 360.0));
-                       this.move_angles_y -= 360.0 * floor(this.move_angles.y * (1.0 / 360.0));
-                       this.move_angles_z -= 360.0 * floor(this.move_angles.z * (1.0 / 360.0));
-                       this.move_ltime += dt;
-                       _Movetype_LinkEdict(this, true);
+               {
+                       this.origin = this.origin + dt * this.velocity;
+                       this.angles = this.angles + dt * this.avelocity;
+                       this.angles_x -= 360.0 * floor(this.angles_x * (1.0 / 360.0));
+                       this.angles_y -= 360.0 * floor(this.angles_y * (1.0 / 360.0));
+                       this.angles_z -= 360.0 * floor(this.angles_z * (1.0 / 360.0));
+                       this.ltime += dt;
+                       _Movetype_LinkEdict(this, false);
                        return;
+               }
                default:
-                       LOG_TRACEF("_Movetype_PushMove: entity %e, unrecognized solid type %d\n", this, this.solid);
+               {
+                       LOG_INFOF("_Movetype_Physics_Push: entity #%d, unrecognized solid type %d", etof(this), this.solid);
                        return;
+               }
+       }
+       if(!this.modelindex)
+       {
+               LOG_INFOF("_Movetype_Physics_Push: entity #%d has an invalid modelindex %d", etof(this), this.modelindex);
+               return;
        }
 
-       bool rotated = (this.move_angles * this.move_angles) + (this.move_avelocity * this.move_avelocity) > 0;
+       bool rotated = ((vlen2(this.angles) + vlen2(this.avelocity)) > 0);
 
-       vector move1 = this.move_velocity * dt;
-       vector moveangle = this.move_avelocity * dt;
+       vector move1 = this.velocity * dt;
+       vector moveangle = this.avelocity * dt;
 
-       makevectors_matrix(-moveangle);
+       vector a = -moveangle;
+       vector forward, left, up;
+       MAKE_VECTORS(a, forward, left, up);
+       left *= -1; // actually make it left!
 
-//     vector pushorig = this.move_origin;
-//     vector pushang = this.move_angles;
-//     float pushltime = this.move_ltime;
+       vector pushorig = this.origin;
+       vector pushang = this.angles;
+       float pushltime = this.ltime;
 
-// move the pusher to its final position
+       // move the pusher to its final position
 
-       this.move_origin = this.move_origin + dt * this.move_velocity;
-       this.move_angles = this.move_angles + dt * this.move_avelocity;
+       this.origin = this.origin + dt * this.velocity;
+       this.angles = this.angles + dt * this.avelocity;
+       this.ltime += dt;
+       _Movetype_LinkEdict(this, false); // pulls absmin/absmax from the engine
 
-       this.move_ltime += dt;
-       _Movetype_LinkEdict(this, true);
+       if(this.move_movetype == MOVETYPE_FAKEPUSH) // Tenebrae's MOVETYPE_PUSH variant that doesn't push...
+       {
+               this.angles_x -= 360.0 * floor(this.angles_x * (1.0 / 360.0));
+               this.angles_y -= 360.0 * floor(this.angles_y * (1.0 / 360.0));
+               this.angles_z -= 360.0 * floor(this.angles_z * (1.0 / 360.0));
+               return;
+       }
 
-       int savesolid = this.solid;
+       IL_CLEAR(g_pushmove_moved); // make sure it's not somehow uncleared
 
-       if (this.move_movetype != MOVETYPE_FAKEPUSH)
+       for(entity check = findradius((this.absmin + this.absmax) * 0.5, vlen(this.absmax - this.absmin) * 0.5 + 1); check; check = check.chain)
        {
-           FOREACH_ENTITY_RADIUS(0.5 * (this.absmin + this.absmax), 0.5 * vlen(this.absmax - this.absmin), true, {
-                       switch (it.move_movetype)
-                       {
-                               case MOVETYPE_NONE:
-                               case MOVETYPE_PUSH:
-                               case MOVETYPE_FOLLOW:
-                               case MOVETYPE_NOCLIP:
-                               case MOVETYPE_FLY_WORLDONLY:
-                                       continue;
-                               default:
-                                       break;
-                       }
-
-                       if (it.owner == this)
+               switch(check.move_movetype)
+               {
+                       case MOVETYPE_NONE:
+                       case MOVETYPE_PUSH:
+                       case MOVETYPE_FOLLOW:
+                       case MOVETYPE_NOCLIP:
+                       case MOVETYPE_FLY_WORLDONLY:
                                continue;
-
-                       if (this.owner == it)
+                       default:
+                               break;
+               }
+
+               if(check.owner == this || this.owner == check)
+                       continue;
+
+               // if the entity is standing on the pusher, it will definitely be moved
+               // if the entity is not standing on the pusher, but is in the pusher's
+               // final position, move it
+               if (!IS_ONGROUND(check) || check.groundentity != this)
+               {
+                       tracebox(check.origin, check.mins, check.maxs, check.origin, MOVE_NOMONSTERS, check);
+                       if(!trace_startsolid)
                                continue;
-
-                       vector pivot = it.mins + 0.5 * (it.maxs - it.mins);
-                       vector move;
-                       if (rotated)
-                       {
-                               vector org = (it.move_origin - this.move_origin) + pivot;
-                               vector org2;
-                               org2.x = org * v_forward;
-                               org2.y = org * v_right;
-                               org2.z = org * v_up;
-                               move = (org2 - org) + move1;
-                       }
-                       else
+               }
+               vector pivot = check.mins + 0.5 * (check.maxs - check.mins);
+               vector move;
+
+               if(rotated)
+               {
+                       vector org = check.origin - this.origin;
+                       org = org + pivot;
+
+                       vector org2;
+                       org2.x = (org * forward);
+                       org2.y = (org * left);
+                       org2.z = (org * up);
+                       move = org2 - org;
+                       move = move + move1;
+               }
+               else
+                       move = move1;
+
+               check.moved_from = check.origin;
+               check.moved_fromangles = check.angles;
+               IL_PUSH(g_pushmove_moved, check);
+
+               // physics objects need better collisions than this code can do
+               if(check.move_movetype == MOVETYPE_PHYSICS)
+               {
+                       check.origin = check.origin + move;
+                       _Movetype_LinkEdict(check, true);
+                       continue;
+               }
+
+               // try moving the contacted entity
+               int savesolid = this.solid;
+               this.solid = SOLID_NOT;
+               if(!_Movetype_PushEntity(check, move, true, true))
+               {
+                       // entity "check" got teleported
+                       check.angles_y += trace_fraction * moveangle.y;
+                       this.solid = savesolid;
+                       continue; // pushed enough
+               }
+               // FIXME: turn players specially
+               check.angles_y += trace_fraction * moveangle.y;
+               this.solid = savesolid;
+
+               // this trace.fraction < 1 check causes items to fall off of pushers
+               // if they pass under or through a wall
+               // the groundentity check causes items to fall off of ledges
+               if(check.move_movetype != MOVETYPE_WALK && (trace_fraction < 1 || check.groundentity != this))
+                       UNSET_ONGROUND(check);
+
+               // if it is still inside the pusher, block
+               tracebox(check.origin, check.mins, check.maxs, check.origin, MOVE_NOMONSTERS, check);
+               if(trace_startsolid)
+               {
+                       if(_Movetype_NudgeOutOfSolid_PivotIsKnownGood(check, pivot))
                        {
-                               move = move1;
+                               // hack to invoke all necessary movement triggers
+                               _Movetype_PushEntity(check, '0 0 0', true, true);
+                               // we could fix it or entity "check" was telported
+                               continue;
                        }
 
-                       // physics objects need better collisions than this code can do
-                       if (it.move_movetype == 32)  // MOVETYPE_PHYSICS
+                       // still inside pusher, so it's really blocked
+
+                       // fail the move
+                       if(check.mins_x == check.maxs_x)
+                               continue;
+                       if(check.solid == SOLID_NOT || check.solid == SOLID_TRIGGER)
                        {
-                               it.move_origin = it.move_origin + move;
-                               _Movetype_LinkEdict(it, true);
+                               // corpse
+                               check.mins_x = check.mins_y = 0;
+                               check.maxs = check.mins;
                                continue;
                        }
 
-                       // try moving the contacted entity
-                       this.solid = SOLID_NOT;
-                       bool flag = false;
-                       flag = _Movetype_PushEntity(it, move, true);
-                       if (!flag)
-                       {
-                               // entity "it" got teleported
-                               it.move_angles_y += trace_fraction * moveangle.y;
-                               this.solid = savesolid;
-                               continue;  // pushed enough
-                       }
-                       // FIXME: turn players specially
-                       it.move_angles_y += trace_fraction * moveangle.y;
-                       this.solid = savesolid;
+                       this.origin = pushorig;
+                       this.angles = pushang;
+                       this.ltime = pushltime;
+                       _Movetype_LinkEdict(this, false);
 
-                       // this trace.fraction < 1 check causes items to fall off of pushers
-                       // if they pass under or through a wall
-                       // the groundentity check causes items to fall off of ledges
-                       if (it.move_movetype != MOVETYPE_WALK && (trace_fraction < 1 || it.move_groundentity != this))
-                               it.move_flags &= ~FL_ONGROUND;
-        });
+                       // move back any entities we already moved
+                       IL_EACH(g_pushmove_moved, true,
+                       {
+                               check.origin = check.moved_from;
+                               check.angles = check.moved_fromangles;
+                               _Movetype_LinkEdict(check, false);
+                       });
+
+                       // if the pusher has a "blocked" function, call it, otherwise just stay in place until the obstacle is gone
+                       if(getblocked(this))
+                               getblocked(this)(this, check);
+                       break;
+               }
        }
-
-       this.move_angles_x -= 360.0 * floor(this.move_angles.x * (1.0 / 360.0));
-       this.move_angles_y -= 360.0 * floor(this.move_angles.y * (1.0 / 360.0));
-       this.move_angles_z -= 360.0 * floor(this.move_angles.z * (1.0 / 360.0));
+       this.angles_x -= 360.0 * floor(this.angles_x * (1.0 / 360.0));
+       this.angles_y -= 360.0 * floor(this.angles_y * (1.0 / 360.0));
+       this.angles_z -= 360.0 * floor(this.angles_z * (1.0 / 360.0));
+       IL_CLEAR(g_pushmove_moved); // clean up
 }
 
-void _Movetype_Physics_Pusher(entity this, float dt)  // SV_Physics_Pusher
+void _Movetype_Physics_Push(entity this, float dt) // SV_Physics_Pusher
 {
-       float oldltime = this.move_ltime;
-       float thinktime = this.move_nextthink;
-       float movetime;
-       if (thinktime < this.move_ltime + dt)
+       float oldltime = this.ltime;
+       float movetime = dt;
+       if(this.nextthink < this.ltime + dt)
        {
-               movetime = thinktime - this.move_ltime;
-               if (movetime < 0)
+               movetime = this.nextthink - this.ltime;
+               if(movetime < 0)
                        movetime = 0;
        }
-       else
-       {
-               movetime = dt;
-       }
 
-       if (movetime)
-               // advances this.move_ltime if not blocked
+       if(movetime)
+       {
+               // advances this.ltime if not blocked
                _Movetype_PushMove(this, movetime);
+       }
 
-       if (thinktime > oldltime && thinktime <= this.move_ltime)
+       if(this.nextthink > oldltime && this.nextthink <= this.ltime)
        {
-               this.move_nextthink = 0;
-               this.move_time = time;
-               this.move_think(this);
+               this.nextthink = 0;
+               getthink(this)(this);
        }
 }