X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fcommon%2Fphysics%2Fmovetypes%2Fpush.qc;h=c3c16b904fc278aa8948896d01d4796ae2b7284b;hb=df02c7e6ca72093f5ecd2ad90e317ff648c6a525;hp=5a0426edce7ffba41c69eb48b8c293a1b5c07b46;hpb=5972fcfdf1ffe5bef1df9edc2de2944abbeba280;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/common/physics/movetypes/push.qc b/qcsrc/common/physics/movetypes/push.qc index 5a0426edc..c3c16b904 100644 --- a/qcsrc/common/physics/movetypes/push.qc +++ b/qcsrc/common/physics/movetypes/push.qc @@ -1,153 +1,223 @@ -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)) + { + // 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); + // 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); } }