diff --git a/nq/source/sv_phys.c b/nq/source/sv_phys.c index 1dbf69ac0..aff5189a9 100644 --- a/nq/source/sv_phys.c +++ b/nq/source/sv_phys.c @@ -397,24 +397,35 @@ SV_PushEntity (edict_t *ent, vec3_t push) } static qboolean -SV_Push (edict_t *pusher, vec3_t move) +SV_Push (edict_t *pusher, vec3_t tmove, vec3_t amove) { float solid_save; int num_moved, i, e; edict_t *check, *block; edict_t **moved_edict; - vec3_t entorig; - vec3_t mins, maxs, pushorig; + vec3_t entorig, move, org, org2; + vec3_t mins, maxs, pushtorig, pushaorig; vec3_t *moved_from; + vec3_t forward = {1, 0, 0}; + vec3_t right = {0, -1, 0}; + vec3_t up = {0, 0, 1}; int mark; - VectorAdd (SVvector (pusher, absmin), move, mins); - VectorAdd (SVvector (pusher, absmax), move, maxs); + VectorAdd (SVvector (pusher, absmin), tmove, mins); + VectorAdd (SVvector (pusher, absmax), tmove, maxs); - VectorCopy (SVvector (pusher, origin), pushorig); + if (!VectorIsZero (amove)) { + vec3_t a; + VectorSubtract (vec3_origin, amove, a); + AngleVectors (a, forward, right, up); + } + + VectorCopy (SVvector (pusher, origin), pushtorig); + VectorCopy (SVvector (pusher, angles), pushaorig); // move the pusher to it's final position - VectorAdd (SVvector (pusher, origin), move, SVvector (pusher, origin)); + VectorAdd (SVvector (pusher, origin), tmove, SVvector (pusher, origin)); + VectorAdd (SVvector (pusher, angles), amove, SVvector (pusher, angles)); SV_LinkEdict (pusher, false); mark = Hunk_LowMark (); @@ -460,6 +471,15 @@ SV_Push (edict_t *pusher, vec3_t move) moved_edict[num_moved] = check; num_moved++; + // calculate destination position + VectorSubtract (SVvector (check, origin), + SVvector (pusher, origin), org); + org2[0] = DotProduct (org, forward); + org2[1] = -DotProduct (org, right); + org2[2] = DotProduct (org, up); + VectorSubtract (org2, org, move); + VectorAdd (move, tmove, move); + // try moving the contacted entity solid_save = SVfloat (pusher, solid); SVfloat (pusher, solid) = SOLID_NOT; @@ -468,6 +488,8 @@ SV_Push (edict_t *pusher, vec3_t move) block = SV_TestEntityPosition (check); if (!block) { + VectorAdd (SVvector (check, angles), amove, + SVvector (check, angles)); continue; } // if it is still inside the pusher, block @@ -484,7 +506,8 @@ SV_Push (edict_t *pusher, vec3_t move) VectorCopy (entorig, SVvector (check, origin)); SV_LinkEdict (check, true); - VectorCopy (pushorig, SVvector (pusher, origin)); + VectorCopy (pushtorig, SVvector (pusher, origin)); + VectorCopy (pushaorig, SVvector (pusher, angles)); SV_LinkEdict (pusher, false); // if the pusher has a "blocked" function, call it @@ -495,6 +518,8 @@ SV_Push (edict_t *pusher, vec3_t move) // move back any entities we already moved for (i = 0; i < num_moved; i++) { VectorCopy (moved_from[i], SVvector (moved_edict[i], origin)); + VectorSubtract (SVvector (moved_edict[i], angles), amove, + SVvector (moved_edict[i], angles)); SV_LinkEdict (moved_edict[i], false); } Hunk_FreeToLowMark (mark); @@ -508,15 +533,18 @@ static void SV_PushMove (edict_t *pusher, float movetime) { vec3_t move; + vec3_t amove; - if (VectorIsZero (SVvector (pusher, velocity))) { + if (VectorIsZero (SVvector (pusher, velocity)) + && VectorIsZero (SVvector (pusher, avelocity))) { SVfloat (pusher, ltime) += movetime; return; } VectorScale (SVvector (pusher, velocity), movetime, move); + VectorScale (SVvector (pusher, avelocity), movetime, amove); - if (SV_Push (pusher, move)) + if (SV_Push (pusher, move, amove)) SVfloat (pusher, ltime) += movetime; } diff --git a/nq/source/world.c b/nq/source/world.c index f07d4ee6a..6526298b2 100644 --- a/nq/source/world.c +++ b/nq/source/world.c @@ -455,11 +455,25 @@ SV_LinkEdict (edict_t *ent, qboolean touch_triggers) if (ent->free) return; - // set the abs box - VectorAdd (SVvector (ent, origin), SVvector (ent, mins), - SVvector (ent, absmin)); - VectorAdd (SVvector (ent, origin), SVvector (ent, maxs), - SVvector (ent, absmax)); + if (SVfloat (ent, solid) == SOLID_BSP + && !VectorIsZero (SVvector (ent, angles)) && ent != sv.edicts) { + float m, v; + vec3_t r; + m = DotProduct (SVvector (ent, mins), SVvector (ent, mins)); + v = DotProduct (SVvector (ent, maxs), SVvector (ent, maxs)); + if (m < v) + m = v; + m = sqrt (m); + VectorSet (m, m, m, r); + VectorSubtract (SVvector (ent, origin), r, SVvector (ent, absmin)); + VectorAdd (SVvector (ent, origin), r, SVvector (ent, absmax)); + } else { + // set the abs box + VectorAdd (SVvector (ent, origin), SVvector (ent, mins), + SVvector (ent, absmin)); + VectorAdd (SVvector (ent, origin), SVvector (ent, maxs), + SVvector (ent, absmax)); + } // to make items easier to pick up and allow them to be grabbed off // of shelves, the abs sizes are expanded @@ -591,6 +605,9 @@ SV_ClipMoveToEntity (edict_t *touched, const vec3_t start, hull_t *hull; trace_t trace; vec3_t offset, start_l, end_l; + vec3_t forward, right, up; + int rot = 0; + vec3_t temp; // fill in a default trace memset (&trace, 0, sizeof (trace_t)); @@ -607,12 +624,50 @@ SV_ClipMoveToEntity (edict_t *touched, const vec3_t start, VectorSubtract (start, offset, start_l); VectorSubtract (end, offset, end_l); + if (SVfloat (touched, solid) == SOLID_BSP + && !VectorIsZero (SVvector (touched, angles)) + && touched != sv.edicts) { + rot = 1; + AngleVectors (SVvector (touched, angles), forward, right, up); + VectorNegate (right, right); // convert lhs to rhs + + VectorCopy (start_l, temp); + start_l[0] = DotProduct (temp, forward); + start_l[1] = DotProduct (temp, right); + start_l[2] = DotProduct (temp, up); + + VectorCopy (end_l, temp); + end_l[0] = DotProduct (temp, forward); + end_l[1] = DotProduct (temp, right); + end_l[2] = DotProduct (temp, up); + } + // trace a line through the apropriate clipping hull MOD_TraceLine (hull, hull->firstclipnode, start_l, end_l, &trace); - // fix trace up by the offset - if (trace.fraction != 1) + + // fix trace up by the rotation and offset + if (trace.fraction != 1) { + if (rot) { + vec_t t; + + // transpose the rotation matrix to get its inverse + t = forward[1]; forward[1] = right[0]; right[0] = t; + t = forward[2]; forward[2] = up[0]; up[0] = t; + t = right[2]; right[2] = up[1]; up[1] = t; + + VectorCopy (trace.endpos, temp); + trace.endpos[0] = DotProduct (temp, forward); + trace.endpos[1] = DotProduct (temp, right); + trace.endpos[2] = DotProduct (temp, up); + + VectorCopy (trace.plane.normal, temp); + trace.plane.normal[0] = DotProduct (temp, forward); + trace.plane.normal[1] = DotProduct (temp, right); + trace.plane.normal[2] = DotProduct (temp, up); + } VectorAdd (trace.endpos, offset, trace.endpos); + } // did we clip the move? if (trace.fraction < 1 || trace.startsolid)