This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
pushmove objects do not obey gravity, and do not interact with each other or trigger fields, but block normal movement and push normal objects when they move.
-onground is set for toss objects when they come to a complete rest. it is set for steping or walking objects
+onground is set for toss objects when they come to a complete rest. it is set for steping or walking objects
doors, plats, etc are SOLID_BSP, and MOVETYPE_PUSH
bonus items are SOLID_TRIGGER touch, and MOVETYPE_TOSS
*/
-cvar_t sv_friction = {"sv_friction","4",false,true};
-cvar_t sv_stopspeed = {"sv_stopspeed","100"};
-cvar_t sv_gravity = {"sv_gravity","800",false,true};
-cvar_t sv_maxvelocity = {"sv_maxvelocity","2000"};
-cvar_t sv_nostep = {"sv_nostep","0"};
+cvar_t sv_friction = {CVAR_NOTIFY, "sv_friction","4"};
+cvar_t sv_stopspeed = {CVAR_NOTIFY, "sv_stopspeed","100"};
+cvar_t sv_gravity = {CVAR_NOTIFY, "sv_gravity","800"};
+cvar_t sv_maxvelocity = {CVAR_NOTIFY, "sv_maxvelocity","2000"};
+cvar_t sv_nostep = {CVAR_NOTIFY, "sv_nostep","0"};
+cvar_t sv_stepheight = {CVAR_NOTIFY, "sv_stepheight", "18"};
+cvar_t sv_jumpstep = {CVAR_NOTIFY, "sv_jumpstep", "1"};
+cvar_t sv_wallfriction = {CVAR_NOTIFY, "sv_wallfriction", "1"};
+cvar_t sv_newflymove = {CVAR_NOTIFY, "sv_newflymove", "1"};
#define MOVE_EPSILON 0.01
void SV_Physics_Toss (edict_t *ent);
+void SV_Phys_Init (void)
+{
+ Cvar_RegisterVariable(&sv_stepheight);
+ Cvar_RegisterVariable(&sv_jumpstep);
+ Cvar_RegisterVariable(&sv_wallfriction);
+ Cvar_RegisterVariable(&sv_newflymove);
+}
+
/*
================
SV_CheckAllEnts
*/
void SV_CheckAllEnts (void)
{
- int e;
- edict_t *check;
+ int e;
+ edict_t *check;
-// see if any solid entities are inside the final position
+ // see if any solid entities are inside the final position
check = NEXT_EDICT(sv.edicts);
- for (e=1 ; e<sv.num_edicts ; e++, check = NEXT_EDICT(check))
+ for (e = 1;e < sv.num_edicts;e++, check = NEXT_EDICT(check))
{
- if (check->free)
+ if (check->e->free)
continue;
- if (check->v.movetype == MOVETYPE_PUSH
- || check->v.movetype == MOVETYPE_NONE
- || check->v.movetype == MOVETYPE_FOLLOW
- || check->v.movetype == MOVETYPE_NOCLIP)
+ if (check->v->movetype == MOVETYPE_PUSH
+ || check->v->movetype == MOVETYPE_NONE
+ || check->v->movetype == MOVETYPE_FOLLOW
+ || check->v->movetype == MOVETYPE_NOCLIP)
continue;
if (SV_TestEntityPosition (check))
*/
void SV_CheckVelocity (edict_t *ent)
{
- int i;
- float wishspeed;
+ int i;
+ float wishspeed;
//
// bound velocity
//
for (i=0 ; i<3 ; i++)
{
- if (IS_NAN(ent->v.velocity[i]))
+ if (IS_NAN(ent->v->velocity[i]))
{
- Con_Printf ("Got a NaN velocity on %s\n", pr_strings + ent->v.classname);
- ent->v.velocity[i] = 0;
+ Con_Printf ("Got a NaN velocity on %s\n", PR_GetString(ent->v->classname));
+ ent->v->velocity[i] = 0;
}
- if (IS_NAN(ent->v.origin[i]))
+ if (IS_NAN(ent->v->origin[i]))
{
- Con_Printf ("Got a NaN origin on %s\n", pr_strings + ent->v.classname);
- ent->v.origin[i] = 0;
+ Con_Printf ("Got a NaN origin on %s\n", PR_GetString(ent->v->classname));
+ ent->v->origin[i] = 0;
}
- // LordHavoc: maxvelocity fix, see below
-/*
- if (ent->v.velocity[i] > sv_maxvelocity.value)
- ent->v.velocity[i] = sv_maxvelocity.value;
- else if (ent->v.velocity[i] < -sv_maxvelocity.value)
- ent->v.velocity[i] = -sv_maxvelocity.value;
-*/
}
// LordHavoc: max velocity fix, inspired by Maddes's source fixes, but this is faster
- wishspeed = DotProduct(ent->v.velocity, ent->v.velocity);
+ wishspeed = DotProduct(ent->v->velocity, ent->v->velocity);
if (wishspeed > sv_maxvelocity.value * sv_maxvelocity.value)
{
wishspeed = sv_maxvelocity.value / sqrt(wishspeed);
- ent->v.velocity[0] *= wishspeed;
- ent->v.velocity[1] *= wishspeed;
- ent->v.velocity[2] *= wishspeed;
- wishspeed = sv_maxvelocity.value;
+ ent->v->velocity[0] *= wishspeed;
+ ent->v->velocity[1] *= wishspeed;
+ ent->v->velocity[2] *= wishspeed;
}
}
*/
qboolean SV_RunThink (edict_t *ent)
{
- float thinktime;
+ float thinktime;
- thinktime = ent->v.nextthink;
+ thinktime = ent->v->nextthink;
if (thinktime <= 0 || thinktime > sv.time + sv.frametime)
return true;
-
+
+ // don't let things stay in the past.
+ // it is possible to start that way by a trigger with a local time.
if (thinktime < sv.time)
- thinktime = sv.time; // don't let things stay in the past.
- // it is possible to start that way
- // by a trigger with a local time.
- ent->v.nextthink = 0;
+ thinktime = sv.time;
+
+ ent->v->nextthink = 0;
pr_global_struct->time = thinktime;
pr_global_struct->self = EDICT_TO_PROG(ent);
pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
- PR_ExecuteProgram (ent->v.think, "NULL think function");
- return !ent->free;
+ PR_ExecuteProgram (ent->v->think, "NULL think function");
+ return !ent->e->free;
}
/*
*/
void SV_Impact (edict_t *e1, edict_t *e2)
{
- int old_self, old_other;
-
+ int old_self, old_other;
+
old_self = pr_global_struct->self;
old_other = pr_global_struct->other;
-
+
pr_global_struct->time = sv.time;
- if (e1->v.touch && e1->v.solid != SOLID_NOT)
+ if (e1->v->touch && e1->v->solid != SOLID_NOT)
{
pr_global_struct->self = EDICT_TO_PROG(e1);
pr_global_struct->other = EDICT_TO_PROG(e2);
- PR_ExecuteProgram (e1->v.touch, "");
+ PR_ExecuteProgram (e1->v->touch, "");
}
-
- if (e2->v.touch && e2->v.solid != SOLID_NOT)
+
+ if (e2->v->touch && e2->v->solid != SOLID_NOT)
{
pr_global_struct->self = EDICT_TO_PROG(e2);
pr_global_struct->other = EDICT_TO_PROG(e1);
- PR_ExecuteProgram (e2->v.touch, "");
+ PR_ExecuteProgram (e2->v->touch, "");
}
pr_global_struct->self = old_self;
returns the blocked flags (1 = floor, 2 = step / wall)
==================
*/
-#define STOP_EPSILON 0.1
-
-int ClipVelocity (vec3_t in, vec3_t normal, vec3_t out, float overbounce)
+#define STOP_EPSILON 0.1
+void ClipVelocity (vec3_t in, vec3_t normal, vec3_t out, float overbounce)
{
- float backoff;
- float change;
- int i, blocked;
-
- blocked = 0;
- if (normal[2] > 0)
- blocked |= 1; // floor
- if (!normal[2])
- blocked |= 2; // step
-
- backoff = DotProduct (in, normal) * overbounce;
+ int i;
+ float backoff;
- for (i=0 ; i<3 ; i++)
- {
- change = normal[i]*backoff;
- out[i] = in[i] - change;
+ backoff = -DotProduct (in, normal) * overbounce;
+ VectorMA(in, backoff, normal, out);
+
+ for (i = 0;i < 3;i++)
if (out[i] > -STOP_EPSILON && out[i] < STOP_EPSILON)
out[i] = 0;
- }
-
- return blocked;
}
1 = floor
2 = wall / step
4 = dead stop
-If steptrace is not NULL, the trace of any vertical wall hit will be stored
+If stepnormal is not NULL, the plane normal of any vertical wall hit will be stored
============
*/
-// LordHavoc: increased from 5 to 20, to partially fix angled corner sticking
-// (example - start.bsp hall to e1m4, leading to the pool there are two
-// angled corners, which you could get stuck on, now they are just a one
-// frame hiccup)
-#define MAX_CLIP_PLANES 20
-int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace)
+// LordHavoc: increased from 5 to 20
+#define MAX_CLIP_PLANES 20
+int SV_FlyMove (edict_t *ent, float time, float *stepnormal)
{
- int bumpcount, numbumps;
- vec3_t dir;
- float d;
- int numplanes;
- vec3_t planes[MAX_CLIP_PLANES];
- vec3_t primal_velocity, original_velocity, new_velocity;
- int i, j;
- trace_t trace;
- vec3_t end;
- float time_left;
- int blocked;
-
- numbumps = 4;
-
- blocked = 0;
- VectorCopy (ent->v.velocity, original_velocity);
- VectorCopy (ent->v.velocity, primal_velocity);
- numplanes = 0;
-
- time_left = time;
-
- for (bumpcount=0 ; bumpcount<numbumps ; bumpcount++)
+ if (sv_newflymove.integer)
{
- if (!ent->v.velocity[0] && !ent->v.velocity[1] && !ent->v.velocity[2])
- break;
+ int blocked, impact, bumpcount;
+ vec3_t end, primal_velocity;
+ trace_t trace;
- for (i=0 ; i<3 ; i++)
- end[i] = ent->v.origin[i] + time_left * ent->v.velocity[i];
+ blocked = 0;
+ VectorCopy (ent->v->velocity, primal_velocity);
- trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, false, ent);
+ for (bumpcount = 0;bumpcount < 4;bumpcount++)
+ {
+ if (!ent->v->velocity[0] && !ent->v->velocity[1] && !ent->v->velocity[2])
+ break;
- if (trace.allsolid)
- { // entity is trapped in another solid
- VectorClear(ent->v.velocity);
- return 3;
- }
+ VectorMA(ent->v->origin, time, ent->v->velocity, end);
+ trace = SV_Move (ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NORMAL, ent);
+ //Con_Printf("trace %f %f %f : %f : %f %f %f\n", trace.endpos[0], trace.endpos[1], trace.endpos[2], trace.fraction, trace.plane.normal[0], trace.plane.normal[1], trace.plane.normal[2]);
- if (trace.fraction > 0)
- { // actually covered some distance
- VectorCopy (trace.endpos, ent->v.origin);
- VectorCopy (ent->v.velocity, original_velocity);
- numplanes = 0;
- }
+ if (trace.allsolid)
+ {
+ // LordHavoc: note: this code is what makes entities stick in place if embedded in another object (which can be the world)
+ // entity is trapped in another solid
+ VectorClear(ent->v->velocity);
+ return 3;
+ }
+
+ if (trace.fraction > 0)
+ {
+ // actually covered some distance
+ VectorCopy (trace.endpos, ent->v->origin);
+ }
- if (trace.fraction == 1)
- break; // moved the entire distance
+ // break if it moved the entire distance
+ if (trace.fraction == 1)
+ break;
- if (!trace.ent)
- Host_Error ("SV_FlyMove: !trace.ent");
+ if (!trace.ent)
+ Host_Error ("SV_FlyMove: !trace.ent");
- if (trace.plane.normal[2] > 0.7)
- {
- blocked |= 1; // floor
- if (trace.ent->v.solid == SOLID_BSP)
+ if ((int) ent->v->flags & FL_ONGROUND)
{
- ent->v.flags = (int)ent->v.flags | FL_ONGROUND;
- ent->v.groundentity = EDICT_TO_PROG(trace.ent);
+ if (ent->v->groundentity == EDICT_TO_PROG(trace.ent))
+ impact = false;
+ else
+ {
+ ent->v->flags = (int)ent->v->flags & ~FL_ONGROUND;
+ impact = true;
+ }
}
- }
- if (!trace.plane.normal[2])
- {
- blocked |= 2; // step
- if (steptrace)
- *steptrace = trace; // save for player extrafriction
- }
+ else
+ impact = true;
-//
-// run the impact function
-//
- SV_Impact (ent, trace.ent);
- if (ent->free)
- break; // removed by the impact function
-
-
- time_left -= time_left * trace.fraction;
-
- // cliped to another plane
- if (numplanes >= MAX_CLIP_PLANES)
- { // this shouldn't really happen
- VectorClear(ent->v.velocity);
- return 3;
+ if (trace.plane.normal[2] > 0.7)
+ {
+ // floor
+ blocked |= 1;
+ ent->v->flags = (int)ent->v->flags | FL_ONGROUND;
+ ent->v->groundentity = EDICT_TO_PROG(trace.ent);
+ }
+ if (!trace.plane.normal[2])
+ {
+ // step
+ blocked |= 2;
+ // save the trace for player extrafriction
+ if (stepnormal)
+ VectorCopy(trace.plane.normal, stepnormal);
+ }
+
+ // run the impact function
+ if (impact)
+ {
+ SV_Impact (ent, trace.ent);
+
+ // break if removed by the impact function
+ if (ent->e->free)
+ break;
+ }
+
+ time *= 1 - trace.fraction;
+
+ ClipVelocity (ent->v->velocity, trace.plane.normal, ent->v->velocity, 1);
}
- VectorCopy (trace.plane.normal, planes[numplanes]);
- numplanes++;
+ return blocked;
+ }
+ else
+ {
+ int i, j, blocked, impact, numplanes, bumpcount, numbumps;
+ float d, time_left;
+ vec3_t dir, end, planes[MAX_CLIP_PLANES], primal_velocity, original_velocity, new_velocity;
+ trace_t trace;
-//
-// modify original_velocity so it parallels all of the clip planes
-//
- for (i=0 ; i<numplanes ; i++)
+ numbumps = 4;
+
+ blocked = 0;
+ VectorCopy (ent->v->velocity, original_velocity);
+ VectorCopy (ent->v->velocity, primal_velocity);
+ numplanes = 0;
+
+ time_left = time;
+
+ for (bumpcount=0 ; bumpcount<numbumps ; bumpcount++)
{
- ClipVelocity (original_velocity, planes[i], new_velocity, 1);
- for (j=0 ; j<numplanes ; j++)
- if (j != i)
+ if (!ent->v->velocity[0] && !ent->v->velocity[1] && !ent->v->velocity[2])
+ break;
+
+ for (i=0 ; i<3 ; i++)
+ end[i] = ent->v->origin[i] + time_left * ent->v->velocity[i];
+
+ trace = SV_Move (ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NORMAL, ent);
+
+ if (trace.allsolid)
+ {
+ // LordHavoc: note: this code is what makes entities stick in place if embedded in another object (which can be the world)
+ // entity is trapped in another solid
+ VectorClear(ent->v->velocity);
+ return 3;
+ }
+
+ if (trace.fraction > 0)
+ {
+ // actually covered some distance
+ VectorCopy (trace.endpos, ent->v->origin);
+ VectorCopy (ent->v->velocity, original_velocity);
+ numplanes = 0;
+ }
+
+ // break if it moved the entire distance
+ if (trace.fraction == 1)
+ break;
+
+ if (!trace.ent)
+ Host_Error ("SV_FlyMove: !trace.ent");
+
+ if ((int) ent->v->flags & FL_ONGROUND)
+ {
+ if (ent->v->groundentity == EDICT_TO_PROG(trace.ent))
+ impact = false;
+ else
{
- if (DotProduct (new_velocity, planes[j]) < 0)
- break; // not ok
+ ent->v->flags = (int)ent->v->flags & ~FL_ONGROUND;
+ impact = true;
}
- if (j == numplanes)
- break;
- }
-
- if (i != numplanes)
- { // go along this plane
- VectorCopy (new_velocity, ent->v.velocity);
- }
- else
- { // go along the crease
- if (numplanes != 2)
+ }
+ else
+ impact = true;
+
+ if (trace.plane.normal[2] > 0.7)
{
-// Con_Printf ("clip velocity, numplanes == %i\n",numplanes);
- VectorClear(ent->v.velocity);
- return 7;
+ // floor
+ blocked |= 1;
+ ent->v->flags = (int)ent->v->flags | FL_ONGROUND;
+ ent->v->groundentity = EDICT_TO_PROG(trace.ent);
+ }
+ if (!trace.plane.normal[2])
+ {
+ // step
+ blocked |= 2;
+ // save the trace for player extrafriction
+ if (stepnormal)
+ VectorCopy(trace.plane.normal, stepnormal);
}
- CrossProduct (planes[0], planes[1], dir);
- d = DotProduct (dir, ent->v.velocity);
- VectorScale (dir, d, ent->v.velocity);
- }
-//
-// if original velocity is against the original velocity, stop dead
-// to avoid tiny occilations in sloping corners
-//
- if (DotProduct (ent->v.velocity, primal_velocity) <= 0)
- {
- VectorClear(ent->v.velocity);
- return blocked;
+ // run the impact function
+ if (impact)
+ {
+ SV_Impact (ent, trace.ent);
+
+ // break if removed by the impact function
+ if (ent->e->free)
+ break;
+ }
+
+
+ time_left -= time_left * trace.fraction;
+
+ // clipped to another plane
+ if (numplanes >= MAX_CLIP_PLANES)
+ {
+ // this shouldn't really happen
+ VectorClear(ent->v->velocity);
+ return 3;
+ }
+
+ VectorCopy (trace.plane.normal, planes[numplanes]);
+ numplanes++;
+
+ // modify original_velocity so it parallels all of the clip planes
+ for (i=0 ; i<numplanes ; i++)
+ {
+ ClipVelocity (original_velocity, planes[i], new_velocity, 1);
+ for (j=0 ; j<numplanes ; j++)
+ if (j != i)
+ {
+ // not ok
+ if (DotProduct (new_velocity, planes[j]) < 0)
+ break;
+ }
+ if (j == numplanes)
+ break;
+ }
+
+ if (i != numplanes)
+ {
+ // go along this plane
+ VectorCopy (new_velocity, ent->v->velocity);
+ }
+ else
+ {
+ // go along the crease
+ if (numplanes != 2)
+ {
+ VectorClear(ent->v->velocity);
+ return 7;
+ }
+ CrossProduct (planes[0], planes[1], dir);
+ // LordHavoc: thanks to taniwha of QuakeForge for pointing out this fix for slowed falling in corners
+ VectorNormalize(dir);
+ d = DotProduct (dir, ent->v->velocity);
+ VectorScale (dir, d, ent->v->velocity);
+ }
+
+ // if original velocity is against the original velocity,
+ // stop dead to avoid tiny occilations in sloping corners
+ if (DotProduct (ent->v->velocity, primal_velocity) <= 0)
+ {
+ VectorClear(ent->v->velocity);
+ return blocked;
+ }
}
- }
- return blocked;
+ return blocked;
+ }
}
*/
void SV_AddGravity (edict_t *ent)
{
- float ent_gravity;
-
- eval_t *val;
+ float ent_gravity;
+ eval_t *val;
val = GETEDICTFIELDVALUE(ent, eval_gravity);
if (val!=0 && val->_float)
ent_gravity = val->_float;
else
ent_gravity = 1.0;
- ent->v.velocity[2] -= ent_gravity * sv_gravity.value * sv.frametime;
+ ent->v->velocity[2] -= ent_gravity * sv_gravity.value * sv.frametime;
}
Does not change the entities velocity at all
============
*/
-trace_t SV_PushEntity (edict_t *ent, vec3_t push)
+trace_t SV_PushEntity (edict_t *ent, vec3_t push, vec3_t pushangles)
{
- trace_t trace;
- vec3_t end;
-
- VectorAdd (ent->v.origin, push, end);
-
- if (ent->v.movetype == MOVETYPE_FLYMISSILE)
- trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_MISSILE, ent);
- else if (ent->v.solid == SOLID_TRIGGER || ent->v.solid == SOLID_NOT)
- // only clip against bmodels
- trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NOMONSTERS, ent);
+ trace_t trace;
+ vec3_t end;
+
+ VectorAdd (ent->v->origin, push, end);
+
+ if (ent->v->movetype == MOVETYPE_FLYMISSILE)
+ trace = SV_Move (ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_MISSILE, ent);
+ else if (ent->v->solid == SOLID_TRIGGER || ent->v->solid == SOLID_NOT)
+ // only clip against bmodels
+ trace = SV_Move (ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NOMONSTERS, ent);
else
- trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NORMAL, ent);
-
- VectorCopy (trace.endpos, ent->v.origin);
- SV_LinkEdict (ent, true);
+ trace = SV_Move (ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NORMAL, ent);
- if (trace.ent)
- SV_Impact (ent, trace.ent);
+ VectorCopy (trace.endpos, ent->v->origin);
+ // FIXME: turn players specially
+ ent->v->angles[1] += trace.fraction * pushangles[1];
+ SV_LinkEdict (ent, true);
+ if (trace.fraction < 1 && trace.ent && (!((int)ent->v->flags & FL_ONGROUND) || ent->v->groundentity != EDICT_TO_PROG(trace.ent)))
+ SV_Impact (ent, trace.ent);
return trace;
-}
+}
/*
============
*/
+trace_t SV_ClipMoveToEntity (edict_t *ent, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end);
void SV_PushMove (edict_t *pusher, float movetime)
{
- int i, e;
- edict_t *check;
- vec3_t mins, maxs, move;
- vec3_t entorig, pushorig;
- int num_moved;
- edict_t *moved_edict[MAX_EDICTS];
- vec3_t moved_from[MAX_EDICTS];
- float savesolid;
-
- switch ((int) pusher->v.solid)
+ int i, e, index;
+ edict_t *check, *ed;
+ float savesolid, movetime2, pushltime;
+ vec3_t mins, maxs, move, move1, moveangle, pushorig, pushang, a, forward, left, up, org, org2;
+ int num_moved;
+ model_t *pushermodel;
+ trace_t trace;
+
+ switch ((int) pusher->v->solid)
{
// LordHavoc: valid pusher types
case SOLID_BSP:
// LordHavoc: no collisions
case SOLID_NOT:
case SOLID_TRIGGER:
- VectorMA (pusher->v.origin, movetime, pusher->v.velocity, pusher->v.origin);
- pusher->v.ltime += movetime;
+ VectorMA (pusher->v->origin, movetime, pusher->v->velocity, pusher->v->origin);
+ VectorMA (pusher->v->angles, movetime, pusher->v->avelocity, pusher->v->angles);
+ pusher->v->ltime += movetime;
SV_LinkEdict (pusher, false);
return;
default:
- Host_Error("SV_PushMove: unrecognized solid type %f\n", pusher->v.solid);
+ Host_Error("SV_PushMove: unrecognized solid type %f\n", pusher->v->solid);
}
- if (!pusher->v.velocity[0] && !pusher->v.velocity[1] && !pusher->v.velocity[2])
+ if (!pusher->v->velocity[0] && !pusher->v->velocity[1] && !pusher->v->velocity[2] && !pusher->v->avelocity[0] && !pusher->v->avelocity[1] && !pusher->v->avelocity[2])
{
- pusher->v.ltime += movetime;
+ pusher->v->ltime += movetime;
return;
}
-
- for (i=0 ; i<3 ; i++)
+ index = (int) pusher->v->modelindex;
+ if (index < 1 || index >= MAX_MODELS)
+ Host_Error("SV_PushMove: invalid modelindex %f\n", pusher->v->modelindex);
+ pushermodel = sv.models[index];
+
+ movetime2 = movetime;
+ VectorScale(pusher->v->velocity, movetime2, move1);
+ VectorScale(pusher->v->avelocity, movetime2, moveangle);
+ if (moveangle[0] || moveangle[2])
{
- move[i] = pusher->v.velocity[i] * movetime;
- mins[i] = pusher->v.absmin[i] + move[i];
- maxs[i] = pusher->v.absmax[i] + move[i];
+ for (i = 0;i < 3;i++)
+ {
+ if (move1[i] > 0)
+ {
+ mins[i] = pushermodel->rotatedmins[i] + pusher->v->origin[i] - 1;
+ maxs[i] = pushermodel->rotatedmaxs[i] + move1[i] + pusher->v->origin[i] + 1;
+ }
+ else
+ {
+ mins[i] = pushermodel->rotatedmins[i] + move1[i] + pusher->v->origin[i] - 1;
+ maxs[i] = pushermodel->rotatedmaxs[i] + pusher->v->origin[i] + 1;
+ }
+ }
}
+ else if (moveangle[1])
+ {
+ for (i = 0;i < 3;i++)
+ {
+ if (move1[i] > 0)
+ {
+ mins[i] = pushermodel->yawmins[i] + pusher->v->origin[i] - 1;
+ maxs[i] = pushermodel->yawmaxs[i] + move1[i] + pusher->v->origin[i] + 1;
+ }
+ else
+ {
+ mins[i] = pushermodel->yawmins[i] + move1[i] + pusher->v->origin[i] - 1;
+ maxs[i] = pushermodel->yawmaxs[i] + pusher->v->origin[i] + 1;
+ }
+ }
+ }
+ else
+ {
+ for (i = 0;i < 3;i++)
+ {
+ if (move1[i] > 0)
+ {
+ mins[i] = pushermodel->normalmins[i] + pusher->v->origin[i] - 1;
+ maxs[i] = pushermodel->normalmaxs[i] + move1[i] + pusher->v->origin[i] + 1;
+ }
+ else
+ {
+ mins[i] = pushermodel->normalmins[i] + move1[i] + pusher->v->origin[i] - 1;
+ maxs[i] = pushermodel->normalmaxs[i] + pusher->v->origin[i] + 1;
+ }
+ }
+ }
+
+ VectorNegate (moveangle, a);
+ AngleVectorsFLU (a, forward, left, up);
+
+ VectorCopy (pusher->v->origin, pushorig);
+ VectorCopy (pusher->v->angles, pushang);
+ pushltime = pusher->v->ltime;
- VectorCopy (pusher->v.origin, pushorig);
-
// move the pusher to it's final position
- VectorAdd (pusher->v.origin, move, pusher->v.origin);
- pusher->v.ltime += movetime;
+ VectorMA (pusher->v->origin, movetime, pusher->v->velocity, pusher->v->origin);
+ VectorMA (pusher->v->angles, movetime, pusher->v->avelocity, pusher->v->angles);
+ pusher->v->ltime += movetime;
SV_LinkEdict (pusher, false);
+ savesolid = pusher->v->solid;
// see if any solid entities are inside the final position
num_moved = 0;
check = NEXT_EDICT(sv.edicts);
for (e = 1;e < sv.num_edicts;e++, check = NEXT_EDICT(check))
{
- if (check->free)
+ if (check->e->free)
continue;
- if (check->v.movetype == MOVETYPE_PUSH
- || check->v.movetype == MOVETYPE_NONE
- || check->v.movetype == MOVETYPE_FOLLOW
- || check->v.movetype == MOVETYPE_NOCLIP)
+ if (check->v->movetype == MOVETYPE_PUSH
+ || check->v->movetype == MOVETYPE_NONE
+ || check->v->movetype == MOVETYPE_FOLLOW
+ || check->v->movetype == MOVETYPE_NOCLIP)
continue;
// if the entity is standing on the pusher, it will definitely be moved
- if (!(((int)check->v.flags & FL_ONGROUND) && PROG_TO_EDICT(check->v.groundentity) == pusher))
+ if (!(((int)check->v->flags & FL_ONGROUND) && PROG_TO_EDICT(check->v->groundentity) == pusher))
{
- if (check->v.absmin[0] >= maxs[0]
- || check->v.absmin[1] >= maxs[1]
- || check->v.absmin[2] >= maxs[2]
- || check->v.absmax[0] <= mins[0]
- || check->v.absmax[1] <= mins[1]
- || check->v.absmax[2] <= mins[2])
+ if (check->v->absmin[0] >= maxs[0]
+ || check->v->absmax[0] <= mins[0]
+ || check->v->absmin[1] >= maxs[1]
+ || check->v->absmax[1] <= mins[1]
+ || check->v->absmin[2] >= maxs[2]
+ || check->v->absmax[2] <= mins[2])
continue;
- // see if the ent's bbox is inside the pusher's final position
- if (!SV_TestEntityPosition (check))
+ trace = SV_ClipMoveToEntity (pusher, check->v->origin, check->v->mins, check->v->maxs, check->v->origin);
+ if (!trace.startsolid)
continue;
}
- // remove the onground flag for non-players
- if (check->v.movetype != MOVETYPE_WALK)
- check->v.flags = (int)check->v.flags & ~FL_ONGROUND;
-
- VectorCopy (check->v.origin, entorig);
- VectorCopy (check->v.origin, moved_from[num_moved]);
- moved_edict[num_moved] = check;
- num_moved++;
-
- // LordHavoc: pusher fixes (teleport train bug, etc)
- savesolid = pusher->v.solid;
- if (savesolid == SOLID_BSP || savesolid == SOLID_BBOX || savesolid == SOLID_SLIDEBOX)
+ if (forward[0] < 0.999f) // quick way to check if any rotation is used
{
- // try moving the contacted entity
- pusher->v.solid = SOLID_NOT;
- SV_PushEntity (check, move);
- pusher->v.solid = savesolid; // was SOLID_BSP
+ VectorSubtract (check->v->origin, pusher->v->origin, org);
+ org2[0] = DotProduct (org, forward);
+ org2[1] = DotProduct (org, left);
+ org2[2] = DotProduct (org, up);
+ VectorSubtract (org2, org, move);
+ VectorAdd (move, move1, move);
+ }
+ else
+ VectorCopy (move1, move);
+
+ // remove the onground flag for non-players
+ if (check->v->movetype != MOVETYPE_WALK)
+ check->v->flags = (int)check->v->flags & ~FL_ONGROUND;
- // if it is still inside the pusher, block
+ VectorCopy (check->v->origin, check->e->moved_from);
+ VectorCopy (check->v->angles, check->e->moved_fromangles);
+ sv.moved_edicts[num_moved++] = check;
+
+ // try moving the contacted entity
+ pusher->v->solid = SOLID_NOT;
+ trace = SV_PushEntity (check, move, moveangle);
+ pusher->v->solid = savesolid; // was SOLID_BSP
+
+ // if it is still inside the pusher, block
+ if (SV_TestEntityPosition (check))
+ {
+ // try moving the contacted entity a tiny bit further to account for precision errors
+ pusher->v->solid = SOLID_NOT;
+ VectorScale(move, 0.1, move);
+ trace = SV_PushEntity (check, move, vec3_origin);
+ pusher->v->solid = savesolid;
if (SV_TestEntityPosition (check))
- { // fail the move
- if (check->v.mins[0] == check->v.maxs[0])
+ {
+ // still inside pusher, so it's really blocked
+
+ // fail the move
+ if (check->v->mins[0] == check->v->maxs[0])
continue;
- if (check->v.solid == SOLID_NOT || check->v.solid == SOLID_TRIGGER)
- { // corpse
- check->v.mins[0] = check->v.mins[1] = 0;
- VectorCopy (check->v.mins, check->v.maxs);
+ if (check->v->solid == SOLID_NOT || check->v->solid == SOLID_TRIGGER)
+ {
+ // corpse
+ check->v->mins[0] = check->v->mins[1] = 0;
+ VectorCopy (check->v->mins, check->v->maxs);
continue;
}
-
- VectorCopy (entorig, check->v.origin);
- SV_LinkEdict (check, true);
- VectorCopy (pushorig, pusher->v.origin);
+ VectorCopy (pushorig, pusher->v->origin);
+ VectorCopy (pushang, pusher->v->angles);
+ pusher->v->ltime = pushltime;
SV_LinkEdict (pusher, false);
- pusher->v.ltime -= movetime;
+
+ // move back any entities we already moved
+ for (i = 0;i < num_moved;i++)
+ {
+ ed = sv.moved_edicts[i];
+ VectorCopy (ed->e->moved_from, ed->v->origin);
+ VectorCopy (ed->e->moved_fromangles, ed->v->angles);
+ SV_LinkEdict (ed, false);
+ }
// if the pusher has a "blocked" function, call it, otherwise just stay in place until the obstacle is gone
- if (pusher->v.blocked)
+ if (pusher->v->blocked)
{
pr_global_struct->self = EDICT_TO_PROG(pusher);
pr_global_struct->other = EDICT_TO_PROG(check);
- PR_ExecuteProgram (pusher->v.blocked, "");
- }
-
- // move back any entities we already moved
- num_moved--; // LordHavoc: pop off check, because it was already restored
- for (i=0 ; i<num_moved ; i++)
- {
- VectorCopy (moved_from[i], moved_edict[i]->v.origin);
- SV_LinkEdict (moved_edict[i], false);
+ PR_ExecuteProgram (pusher->v->blocked, "");
}
return;
- }
- }
- }
-
-
-}
-
-/*
-============
-SV_PushRotate
-
-============
-*/
-void SV_PushRotate (edict_t *pusher, float movetime)
-{
- int i, e;
- edict_t *check;
- vec3_t move, a, amove;
- vec3_t entorigin, entangles, pushorigin, pushangles;
- int num_moved;
- edict_t *moved_edict[MAX_EDICTS];
- vec3_t moved_from[MAX_EDICTS];
- vec3_t angled_from[MAX_EDICTS];
- vec3_t org, org2;
- vec3_t forward, right, up;
- float savesolid;
-
- switch ((int) pusher->v.solid)
- {
- // LordHavoc: valid pusher types
- case SOLID_BSP:
- case SOLID_BBOX:
- case SOLID_SLIDEBOX:
- case SOLID_CORPSE: // LordHavoc: this would be weird...
- break;
- // LordHavoc: no collisions
- case SOLID_NOT:
- case SOLID_TRIGGER:
- VectorMA (pusher->v.angles, movetime, pusher->v.avelocity, pusher->v.angles);
- pusher->v.ltime += movetime;
- SV_LinkEdict (pusher, false);
- return;
- default:
- Host_Error("SV_PushRotate: unrecognized solid type %f\n", pusher->v.solid);
- }
- if (!pusher->v.avelocity[0] && !pusher->v.avelocity[1] && !pusher->v.avelocity[2])
- {
- pusher->v.ltime += movetime;
- return;
- }
-
- for (i=0 ; i<3 ; i++)
- amove[i] = pusher->v.avelocity[i] * movetime;
-
- VectorNegate (amove, a);
- AngleVectors (a, forward, right, up);
-
- VectorCopy (pusher->v.origin, pushorigin);
- VectorCopy (pusher->v.angles, pushangles);
-
-// move the pusher to it's final position
-
- VectorAdd (pusher->v.angles, amove, pusher->v.angles);
- pusher->v.ltime += movetime;
- SV_LinkEdict (pusher, false);
-
-
-// see if any solid entities are inside the final position
- num_moved = 0;
- check = NEXT_EDICT(sv.edicts);
- for (e=1 ; e<sv.num_edicts ; e++, check = NEXT_EDICT(check))
- {
- if (check->free)
- continue;
- if (check->v.movetype == MOVETYPE_PUSH
- || check->v.movetype == MOVETYPE_NONE
- || check->v.movetype == MOVETYPE_FOLLOW
- || check->v.movetype == MOVETYPE_NOCLIP)
- continue;
-
- // if the entity is standing on the pusher, it will definately be moved
- if (!(((int)check->v.flags & FL_ONGROUND) && PROG_TO_EDICT(check->v.groundentity) == pusher))
- {
- if (check->v.absmin[0] >= pusher->v.absmax[0]
- || check->v.absmin[1] >= pusher->v.absmax[1]
- || check->v.absmin[2] >= pusher->v.absmax[2]
- || check->v.absmax[0] <= pusher->v.absmin[0]
- || check->v.absmax[1] <= pusher->v.absmin[1]
- || check->v.absmax[2] <= pusher->v.absmin[2])
- continue;
-
- // see if the ent's bbox is inside the pusher's final position
- if (!SV_TestEntityPosition (check))
- continue;
- }
-
- // remove the onground flag for non-players
- if (check->v.movetype != MOVETYPE_WALK)
- check->v.flags = (int)check->v.flags & ~FL_ONGROUND;
-
- VectorCopy (check->v.origin, entorigin);
- VectorCopy (check->v.origin, moved_from[num_moved]);
- VectorCopy (check->v.angles, entangles);
- VectorCopy (check->v.angles, angled_from[num_moved]);
- moved_edict[num_moved] = check;
- num_moved++;
-
- // calculate destination position
- VectorSubtract (check->v.origin, pusher->v.origin, org);
- org2[0] = DotProduct (org, forward);
- org2[1] = -DotProduct (org, right);
- org2[2] = DotProduct (org, up);
- VectorSubtract (org2, org, move);
-
- // try moving the contacted entity
- savesolid = pusher->v.solid; // LordHavoc: restore to correct solid type
- pusher->v.solid = SOLID_NOT;
- SV_PushEntity (check, move);
- pusher->v.solid = savesolid; // LordHavoc: restore to correct solid type
-
- VectorAdd (check->v.angles, amove, check->v.angles);
-
- // if it is still inside the pusher, block
- if (SV_TestEntityPosition (check))
- { // fail the move
- if (check->v.mins[0] == check->v.maxs[0])
- continue;
- if (check->v.solid == SOLID_NOT || check->v.solid == SOLID_TRIGGER)
- { // corpse
- check->v.mins[0] = check->v.mins[1] = 0;
- VectorCopy (check->v.mins, check->v.maxs);
- continue;
}
-
- VectorCopy (entorigin, check->v.origin);
- VectorCopy (entangles, check->v.angles);
- SV_LinkEdict (check, true);
-
- VectorCopy (pushorigin, pusher->v.origin);
- VectorCopy (pushangles, pusher->v.angles);
- SV_LinkEdict (pusher, false);
- pusher->v.ltime -= movetime;
-
- // if the pusher has a "blocked" function, call it, otherwise just stay in place until the obstacle is gone
- if (pusher->v.blocked)
- {
- pr_global_struct->self = EDICT_TO_PROG(pusher);
- pr_global_struct->other = EDICT_TO_PROG(check);
- PR_ExecuteProgram (pusher->v.blocked, "");
- }
-
- // move back any entities we already moved
- num_moved--; // LordHavoc: pop off check, because it was already restored
- for (i=0 ; i<num_moved ; i++)
- {
- VectorCopy (moved_from[i], moved_edict[i]->v.origin);
- VectorCopy (angled_from[i], moved_edict[i]->v.angles);
- SV_LinkEdict (moved_edict[i], false);
- }
- return;
}
}
}
*/
void SV_Physics_Pusher (edict_t *ent)
{
- float thinktime;
- float oldltime;
- float movetime;
-
- oldltime = ent->v.ltime;
-
- thinktime = ent->v.nextthink;
- if (thinktime < ent->v.ltime + sv.frametime)
+ float thinktime, oldltime, movetime;
+
+ oldltime = ent->v->ltime;
+
+ thinktime = ent->v->nextthink;
+ if (thinktime < ent->v->ltime + sv.frametime)
{
- movetime = thinktime - ent->v.ltime;
+ movetime = thinktime - ent->v->ltime;
if (movetime < 0)
movetime = 0;
}
movetime = sv.frametime;
if (movetime)
+ // advances ent->v->ltime if not blocked
+ SV_PushMove (ent, movetime);
+
+ if (thinktime > oldltime && thinktime <= ent->v->ltime)
{
- if (ent->v.avelocity[0] || ent->v.avelocity[1] || ent->v.avelocity[2])
- SV_PushRotate (ent, movetime);
- else
- SV_PushMove (ent, movetime); // advances ent->v.ltime if not blocked
- }
-
- if (thinktime > oldltime && thinktime <= ent->v.ltime)
- {
- ent->v.nextthink = 0;
+ ent->v->nextthink = 0;
pr_global_struct->time = sv.time;
pr_global_struct->self = EDICT_TO_PROG(ent);
pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
- PR_ExecuteProgram (ent->v.think, "NULL think function");
- if (ent->free)
- return;
+ PR_ExecuteProgram (ent->v->think, "NULL think function");
}
-
}
*/
void SV_CheckStuck (edict_t *ent)
{
- int i, j;
- int z;
- vec3_t org;
+ int i, j, z;
+ vec3_t org;
if (!SV_TestEntityPosition(ent))
{
- VectorCopy (ent->v.origin, ent->v.oldorigin);
+ VectorCopy (ent->v->origin, ent->v->oldorigin);
return;
}
- VectorCopy (ent->v.origin, org);
- VectorCopy (ent->v.oldorigin, ent->v.origin);
+ VectorCopy (ent->v->origin, org);
+ VectorCopy (ent->v->oldorigin, ent->v->origin);
if (!SV_TestEntityPosition(ent))
{
Con_DPrintf ("Unstuck.\n");
SV_LinkEdict (ent, true);
return;
}
-
+
for (z=0 ; z< 18 ; z++)
for (i=-1 ; i <= 1 ; i++)
for (j=-1 ; j <= 1 ; j++)
{
- ent->v.origin[0] = org[0] + i;
- ent->v.origin[1] = org[1] + j;
- ent->v.origin[2] = org[2] + z;
+ ent->v->origin[0] = org[0] + i;
+ ent->v->origin[1] = org[1] + j;
+ ent->v->origin[2] = org[2] + z;
if (!SV_TestEntityPosition(ent))
{
Con_DPrintf ("Unstuck.\n");
return;
}
}
-
- VectorCopy (org, ent->v.origin);
+
+ VectorCopy (org, ent->v->origin);
Con_DPrintf ("player is stuck.\n");
}
*/
qboolean SV_CheckWater (edict_t *ent)
{
- vec3_t point;
- int cont;
-
- point[0] = ent->v.origin[0];
- point[1] = ent->v.origin[1];
- point[2] = ent->v.origin[2] + ent->v.mins[2] + 1;
-
- ent->v.waterlevel = 0;
- ent->v.watertype = CONTENTS_EMPTY;
- cont = SV_PointContents (point);
+ int cont;
+ vec3_t point;
+
+ point[0] = ent->v->origin[0];
+ point[1] = ent->v->origin[1];
+ point[2] = ent->v->origin[2] + ent->v->mins[2] + 1;
+
+ ent->v->waterlevel = 0;
+ ent->v->watertype = CONTENTS_EMPTY;
+ cont = SV_PointQ1Contents(point);
if (cont <= CONTENTS_WATER)
{
- ent->v.watertype = cont;
- ent->v.waterlevel = 1;
- point[2] = ent->v.origin[2] + (ent->v.mins[2] + ent->v.maxs[2])*0.5;
- cont = SV_PointContents (point);
+ ent->v->watertype = cont;
+ ent->v->waterlevel = 1;
+ point[2] = ent->v->origin[2] + (ent->v->mins[2] + ent->v->maxs[2])*0.5;
+ cont = SV_PointQ1Contents(point);
if (cont <= CONTENTS_WATER)
{
- ent->v.waterlevel = 2;
- point[2] = ent->v.origin[2] + ent->v.view_ofs[2];
- cont = SV_PointContents (point);
+ ent->v->waterlevel = 2;
+ point[2] = ent->v->origin[2] + ent->v->view_ofs[2];
+ cont = SV_PointQ1Contents(point);
if (cont <= CONTENTS_WATER)
- ent->v.waterlevel = 3;
+ ent->v->waterlevel = 3;
}
}
-
- return ent->v.waterlevel > 1;
+
+ return ent->v->waterlevel > 1;
}
/*
============
*/
-void SV_WallFriction (edict_t *ent, trace_t *trace)
+void SV_WallFriction (edict_t *ent, float *stepnormal)
{
- vec3_t forward;
- float d, i;
- vec3_t into, side;
-
- AngleVectors (ent->v.v_angle, forward, NULL, NULL);
- d = DotProduct (trace->plane.normal, forward);
-
- d += 0.5;
- if (d >= 0)
- return;
-
-// cut the tangential velocity
- i = DotProduct (trace->plane.normal, ent->v.velocity);
- VectorScale (trace->plane.normal, i, into);
- VectorSubtract (ent->v.velocity, into, side);
-
- ent->v.velocity[0] = side[0] * (1 + d);
- ent->v.velocity[1] = side[1] * (1 + d);
+ float d, i;
+ vec3_t forward, into, side;
+
+ AngleVectors (ent->v->v_angle, forward, NULL, NULL);
+ if ((d = DotProduct (stepnormal, forward) + 0.5) < 0)
+ {
+ // cut the tangential velocity
+ i = DotProduct (stepnormal, ent->v->velocity);
+ VectorScale (stepnormal, i, into);
+ VectorSubtract (ent->v->velocity, into, side);
+ ent->v->velocity[0] = side[0] * (1 + d);
+ ent->v->velocity[1] = side[1] * (1 + d);
+ }
}
/*
*/
int SV_TryUnstick (edict_t *ent, vec3_t oldvel)
{
- int i;
- vec3_t oldorg;
- vec3_t dir;
- int clip;
- trace_t steptrace;
-
- VectorCopy (ent->v.origin, oldorg);
+ int i, clip;
+ vec3_t oldorg, dir;
+
+ VectorCopy (ent->v->origin, oldorg);
VectorClear (dir);
for (i=0 ; i<8 ; i++)
{
-// try pushing a little in an axial direction
+ // try pushing a little in an axial direction
switch (i)
{
- case 0: dir[0] = 2; dir[1] = 0; break;
- case 1: dir[0] = 0; dir[1] = 2; break;
- case 2: dir[0] = -2; dir[1] = 0; break;
- case 3: dir[0] = 0; dir[1] = -2; break;
- case 4: dir[0] = 2; dir[1] = 2; break;
- case 5: dir[0] = -2; dir[1] = 2; break;
- case 6: dir[0] = 2; dir[1] = -2; break;
- case 7: dir[0] = -2; dir[1] = -2; break;
+ case 0: dir[0] = 2; dir[1] = 0; break;
+ case 1: dir[0] = 0; dir[1] = 2; break;
+ case 2: dir[0] = -2; dir[1] = 0; break;
+ case 3: dir[0] = 0; dir[1] = -2; break;
+ case 4: dir[0] = 2; dir[1] = 2; break;
+ case 5: dir[0] = -2; dir[1] = 2; break;
+ case 6: dir[0] = 2; dir[1] = -2; break;
+ case 7: dir[0] = -2; dir[1] = -2; break;
}
-
- SV_PushEntity (ent, dir);
-// retry the original move
- ent->v.velocity[0] = oldvel[0];
- ent->v. velocity[1] = oldvel[1];
- ent->v. velocity[2] = 0;
- clip = SV_FlyMove (ent, 0.1, &steptrace);
+ SV_PushEntity (ent, dir, vec3_origin);
- if ( fabs(oldorg[1] - ent->v.origin[1]) > 4
- || fabs(oldorg[0] - ent->v.origin[0]) > 4 )
- {
-//Con_DPrintf ("unstuck!\n");
+ // retry the original move
+ ent->v->velocity[0] = oldvel[0];
+ ent->v->velocity[1] = oldvel[1];
+ ent->v->velocity[2] = 0;
+ clip = SV_FlyMove (ent, 0.1, NULL);
+
+ if (fabs(oldorg[1] - ent->v->origin[1]) > 4
+ || fabs(oldorg[0] - ent->v->origin[0]) > 4)
return clip;
- }
-
-// go back to the original pos and try again
- VectorCopy (oldorg, ent->v.origin);
+
+ // go back to the original pos and try again
+ VectorCopy (oldorg, ent->v->origin);
}
-
- VectorClear (ent->v.velocity);
- return 7; // still not moving
+
+ // still not moving
+ VectorClear (ent->v->velocity);
+ return 7;
}
/*
Only used by players
======================
*/
-#define STEPSIZE 18
void SV_WalkMove (edict_t *ent)
{
- vec3_t upmove, downmove;
- vec3_t oldorg, oldvel;
- vec3_t nosteporg, nostepvel;
- int clip;
- int oldonground;
- trace_t steptrace, downtrace;
-
-//
-// do a regular slide move unless it looks like you ran into a step
-//
- oldonground = (int)ent->v.flags & FL_ONGROUND;
- ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;
-
- VectorCopy (ent->v.origin, oldorg);
- VectorCopy (ent->v.velocity, oldvel);
-
- clip = SV_FlyMove (ent, sv.frametime, &steptrace);
+ int clip, oldonground;
+ vec3_t upmove, downmove, oldorg, oldvel, nosteporg, nostepvel, stepnormal;
+ trace_t downtrace;
+ // do a regular slide move unless it looks like you ran into a step
+ oldonground = (int)ent->v->flags & FL_ONGROUND;
+ ent->v->flags = (int)ent->v->flags & ~FL_ONGROUND;
+
+ VectorCopy (ent->v->origin, oldorg);
+ VectorCopy (ent->v->velocity, oldvel);
+
+ clip = SV_FlyMove (ent, sv.frametime, NULL);
+
+ // if move didn't block on a step, return
if ( !(clip & 2) )
- return; // move didn't block on a step
-
- if (!oldonground && ent->v.waterlevel == 0)
- return; // don't stair up while jumping
-
- if (ent->v.movetype != MOVETYPE_WALK)
- return; // gibbed by a trigger
-
- if (sv_nostep.value)
- return;
-
- if ( (int)sv_player->v.flags & FL_WATERJUMP )
return;
- VectorCopy (ent->v.origin, nosteporg);
- VectorCopy (ent->v.velocity, nostepvel);
+ if (ent->v->movetype != MOVETYPE_FLY)
+ {
+ if (!oldonground && ent->v->waterlevel == 0 && !sv_jumpstep.integer)
+ // don't stair up while jumping
+ return;
-//
-// try moving up and forward to go up a step
-//
- VectorCopy (oldorg, ent->v.origin); // back to start pos
+ if (ent->v->movetype != MOVETYPE_WALK)
+ // gibbed by a trigger
+ return;
+ }
- VectorClear (upmove);
- VectorClear (downmove);
- upmove[2] = STEPSIZE;
- downmove[2] = -STEPSIZE + oldvel[2]*sv.frametime;
+ if (sv_nostep.integer)
+ return;
-// move up
- SV_PushEntity (ent, upmove); // FIXME: don't link?
+ if ( (int)ent->v->flags & FL_WATERJUMP )
+ return;
-// move forward
- ent->v.velocity[0] = oldvel[0];
- ent->v. velocity[1] = oldvel[1];
- ent->v. velocity[2] = 0;
- clip = SV_FlyMove (ent, sv.frametime, &steptrace);
+ VectorCopy (ent->v->origin, nosteporg);
+ VectorCopy (ent->v->velocity, nostepvel);
-// check for stuckness, possibly due to the limited precision of floats
-// in the clipping hulls
- if (clip)
- {
- if ( fabs(oldorg[1] - ent->v.origin[1]) < 0.03125
- && fabs(oldorg[0] - ent->v.origin[0]) < 0.03125 )
- { // stepping up didn't make any progress
- clip = SV_TryUnstick (ent, oldvel);
- }
- }
-
-// extra friction based on view angle
- if ( clip & 2 )
- SV_WallFriction (ent, &steptrace);
+ // try moving up and forward to go up a step
+ // back to start pos
+ VectorCopy (oldorg, ent->v->origin);
-// move down
- downtrace = SV_PushEntity (ent, downmove); // FIXME: don't link?
+ VectorClear (upmove);
+ VectorClear (downmove);
+ upmove[2] = sv_stepheight.value;
+ downmove[2] = -sv_stepheight.value + oldvel[2]*sv.frametime;
+
+ // move up
+ // FIXME: don't link?
+ SV_PushEntity (ent, upmove, vec3_origin);
+
+ // move forward
+ ent->v->velocity[0] = oldvel[0];
+ ent->v->velocity[1] = oldvel[1];
+ ent->v->velocity[2] = 0;
+ clip = SV_FlyMove (ent, sv.frametime, stepnormal);
+ ent->v->velocity[2] += oldvel[2];
+
+ // check for stuckness, possibly due to the limited precision of floats
+ // in the clipping hulls
+ if (clip
+ && fabs(oldorg[1] - ent->v->origin[1]) < 0.03125
+ && fabs(oldorg[0] - ent->v->origin[0]) < 0.03125)
+ // stepping up didn't make any progress
+ clip = SV_TryUnstick (ent, oldvel);
+
+ // extra friction based on view angle
+ if (clip & 2 && sv_wallfriction.integer)
+ SV_WallFriction (ent, stepnormal);
+
+ // move down
+ // FIXME: don't link?
+ downtrace = SV_PushEntity (ent, downmove, vec3_origin);
if (downtrace.plane.normal[2] > 0.7)
{
- if (ent->v.solid == SOLID_BSP)
+ // LordHavoc: disabled this so you can walk on monsters/players
+ //if (ent->v->solid == SOLID_BSP)
{
- ent->v.flags = (int)ent->v.flags | FL_ONGROUND;
- ent->v.groundentity = EDICT_TO_PROG(downtrace.ent);
+ ent->v->flags = (int)ent->v->flags | FL_ONGROUND;
+ ent->v->groundentity = EDICT_TO_PROG(downtrace.ent);
}
}
else
{
-// if the push down didn't end up on good ground, use the move without
-// the step up. This happens near wall / slope combinations, and can
-// cause the player to hop up higher on a slope too steep to climb
- VectorCopy (nosteporg, ent->v.origin);
- VectorCopy (nostepvel, ent->v.velocity);
- }
-}
-
-
-/*
-================
-SV_Physics_Client
-
-Player character actions
-================
-*/
-void SV_Physics_Client (edict_t *ent, int num)
-{
- if ( ! svs.clients[num-1].active )
- return; // unconnected slot
-
-//
-// call standard client pre-think
-//
- pr_global_struct->time = sv.time;
- pr_global_struct->self = EDICT_TO_PROG(ent);
- PR_ExecuteProgram (pr_global_struct->PlayerPreThink, "QC function PlayerPreThink is missing");
-
-//
-// do a move
-//
- SV_CheckVelocity (ent);
-
-//
-// decide which move function to call
-//
- switch ((int)ent->v.movetype)
- {
- case MOVETYPE_NONE:
- if (!SV_RunThink (ent))
- return;
- break;
-
- case MOVETYPE_WALK:
- if (!SV_RunThink (ent))
- return;
- if (!SV_CheckWater (ent) && ! ((int)ent->v.flags & FL_WATERJUMP) )
- SV_AddGravity (ent);
- SV_CheckStuck (ent);
- SV_WalkMove (ent);
- break;
-
- case MOVETYPE_TOSS:
- case MOVETYPE_BOUNCE:
- SV_Physics_Toss (ent);
- break;
-
- case MOVETYPE_FLY:
- if (!SV_RunThink (ent))
- return;
- SV_CheckWater (ent);
- SV_FlyMove (ent, sv.frametime, NULL);
- break;
-
- case MOVETYPE_NOCLIP:
- if (!SV_RunThink (ent))
- return;
- SV_CheckWater (ent);
- VectorMA (ent->v.origin, sv.frametime, ent->v.velocity, ent->v.origin);
- break;
-
- default:
- Host_Error ("SV_Physics_client: bad movetype %i", (int)ent->v.movetype);
+ // if the push down didn't end up on good ground, use the move without
+ // the step up. This happens near wall / slope combinations, and can
+ // cause the player to hop up higher on a slope too steep to climb
+ VectorCopy (nosteporg, ent->v->origin);
+ VectorCopy (nostepvel, ent->v->velocity);
}
-
-//
-// call standard player post-think
-//
- SV_LinkEdict (ent, true);
-
- pr_global_struct->time = sv.time;
- pr_global_struct->self = EDICT_TO_PROG(ent);
- PR_ExecuteProgram (pr_global_struct->PlayerPostThink, "QC function PlayerPostThink is missing");
}
//============================================================================
-/*
-=============
-SV_Physics_None
-
-Non moving objects can only think
-=============
-*/
-void SV_Physics_None (edict_t *ent)
-{
-// regular thinking
- SV_RunThink (ent);
-}
-
/*
=============
SV_Physics_Follow
{
vec3_t vf, vr, vu, angles, v;
edict_t *e;
-// regular thinking
+
+ // regular thinking
if (!SV_RunThink (ent))
return;
+
// LordHavoc: implemented rotation on MOVETYPE_FOLLOW objects
- e = PROG_TO_EDICT(ent->v.aiment);
- if (e->v.angles[0] == ent->v.punchangle[0] && e->v.angles[1] == ent->v.punchangle[1] && e->v.angles[2] == ent->v.punchangle[2])
+ e = PROG_TO_EDICT(ent->v->aiment);
+ if (e->v->angles[0] == ent->v->punchangle[0] && e->v->angles[1] == ent->v->punchangle[1] && e->v->angles[2] == ent->v->punchangle[2])
{
// quick case for no rotation
- VectorAdd(e->v.origin, ent->v.view_ofs, ent->v.origin);
+ VectorAdd(e->v->origin, ent->v->view_ofs, ent->v->origin);
}
else
{
- angles[0] = -ent->v.punchangle[0];
- angles[1] = ent->v.punchangle[1];
- angles[2] = ent->v.punchangle[2];
+ angles[0] = -ent->v->punchangle[0];
+ angles[1] = ent->v->punchangle[1];
+ angles[2] = ent->v->punchangle[2];
AngleVectors (angles, vf, vr, vu);
- v[0] = ent->v.view_ofs[0] * vf[0] + ent->v.view_ofs[1] * vr[0] + ent->v.view_ofs[2] * vu[0];
- v[1] = ent->v.view_ofs[0] * vf[1] + ent->v.view_ofs[1] * vr[1] + ent->v.view_ofs[2] * vu[1];
- v[2] = ent->v.view_ofs[0] * vf[2] + ent->v.view_ofs[1] * vr[2] + ent->v.view_ofs[2] * vu[2];
- angles[0] = -e->v.angles[0];
- angles[1] = e->v.angles[1];
- angles[2] = e->v.angles[2];
+ v[0] = ent->v->view_ofs[0] * vf[0] + ent->v->view_ofs[1] * vr[0] + ent->v->view_ofs[2] * vu[0];
+ v[1] = ent->v->view_ofs[0] * vf[1] + ent->v->view_ofs[1] * vr[1] + ent->v->view_ofs[2] * vu[1];
+ v[2] = ent->v->view_ofs[0] * vf[2] + ent->v->view_ofs[1] * vr[2] + ent->v->view_ofs[2] * vu[2];
+ angles[0] = -e->v->angles[0];
+ angles[1] = e->v->angles[1];
+ angles[2] = e->v->angles[2];
AngleVectors (angles, vf, vr, vu);
- ent->v.origin[0] = v[0] * vf[0] + v[1] * vf[1] + v[2] * vf[2] + e->v.origin[0];
- ent->v.origin[1] = v[0] * vr[0] + v[1] * vr[1] + v[2] * vr[2] + e->v.origin[1];
- ent->v.origin[2] = v[0] * vu[0] + v[1] * vu[1] + v[2] * vu[2] + e->v.origin[2];
- /*
- ent->v.origin[0] = ent->v.view_ofs[0] * vf[0] + ent->v.view_ofs[0] * vf[1] + ent->v.view_ofs[0] * vf[2] + e->v.origin[0];
- ent->v.origin[1] = ent->v.view_ofs[1] * vr[0] + ent->v.view_ofs[1] * vr[1] + ent->v.view_ofs[1] * vr[2] + e->v.origin[1];
- ent->v.origin[2] = ent->v.view_ofs[2] * vu[0] + ent->v.view_ofs[2] * vu[1] + ent->v.view_ofs[2] * vu[2] + e->v.origin[2];
- */
+ ent->v->origin[0] = v[0] * vf[0] + v[1] * vf[1] + v[2] * vf[2] + e->v->origin[0];
+ ent->v->origin[1] = v[0] * vr[0] + v[1] * vr[1] + v[2] * vr[2] + e->v->origin[1];
+ ent->v->origin[2] = v[0] * vu[0] + v[1] * vu[1] + v[2] * vu[2] + e->v->origin[2];
}
- VectorAdd (e->v.angles, ent->v.v_angle, ent->v.angles);
-// VectorAdd (PROG_TO_EDICT(ent->v.aiment)->v.origin, ent->v.v_angle, ent->v.origin);
+ VectorAdd (e->v->angles, ent->v->v_angle, ent->v->angles);
SV_LinkEdict (ent, true);
}
-/*
-=============
-SV_Physics_Noclip
-
-A moving object that doesn't obey physics
-=============
-*/
-void SV_Physics_Noclip (edict_t *ent)
-{
-// regular thinking
- if (!SV_RunThink (ent))
- return;
-
- VectorMA (ent->v.angles, sv.frametime, ent->v.avelocity, ent->v.angles);
- VectorMA (ent->v.origin, sv.frametime, ent->v.velocity, ent->v.origin);
-
- SV_LinkEdict (ent, false);
-}
-
/*
==============================================================================
*/
void SV_CheckWaterTransition (edict_t *ent)
{
- int cont;
- cont = SV_PointContents (ent->v.origin);
- if (!ent->v.watertype)
- { // just spawned here
- ent->v.watertype = cont;
- ent->v.waterlevel = 1;
+ int cont;
+ cont = SV_PointQ1Contents(ent->v->origin);
+ if (!ent->v->watertype)
+ {
+ // just spawned here
+ ent->v->watertype = cont;
+ ent->v->waterlevel = 1;
return;
}
-
+
if (cont <= CONTENTS_WATER)
{
- if (ent->v.watertype == CONTENTS_EMPTY)
- { // just crossed into water
+ if (ent->v->watertype == CONTENTS_EMPTY && cont != CONTENTS_LAVA)
+ // just crossed into water
SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1);
- }
- ent->v.watertype = cont;
- ent->v.waterlevel = 1;
+
+ ent->v->watertype = cont;
+ ent->v->waterlevel = 1;
}
else
{
- if (ent->v.watertype != CONTENTS_EMPTY)
- { // just crossed into water
+ if (ent->v->watertype != CONTENTS_EMPTY && ent->v->watertype != CONTENTS_LAVA)
+ // just crossed into water
SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1);
- }
- ent->v.watertype = CONTENTS_EMPTY;
- ent->v.waterlevel = cont;
+
+ ent->v->watertype = CONTENTS_EMPTY;
+ ent->v->waterlevel = 0;
}
}
*/
void SV_Physics_Toss (edict_t *ent)
{
- trace_t trace;
- vec3_t move;
- float backoff;
+ trace_t trace;
+ vec3_t move;
+ edict_t *groundentity;
+
// regular thinking
if (!SV_RunThink (ent))
return;
// if onground, return without moving
- if ( ((int)ent->v.flags & FL_ONGROUND) )
- return;
+ if ((int)ent->v->flags & FL_ONGROUND)
+ {
+ if (ent->v->groundentity == 0)
+ return;
+ // if ent was supported by a brush model on previous frame,
+ // and groundentity is now freed, set groundentity to 0 (floating)
+ groundentity = PROG_TO_EDICT(ent->v->groundentity);
+ if (groundentity->v->solid == SOLID_BSP)
+ {
+ ent->e->suspendedinairflag = true;
+ return;
+ }
+ else if (ent->e->suspendedinairflag && groundentity->e->free)
+ {
+ // leave it suspended in the air
+ ent->v->groundentity = 0;
+ ent->e->suspendedinairflag = false;
+ return;
+ }
+ }
+ ent->e->suspendedinairflag = false;
SV_CheckVelocity (ent);
// add gravity
- if (ent->v.movetype != MOVETYPE_FLY
- && ent->v.movetype != MOVETYPE_BOUNCEMISSILE // LordHavoc: enabled MOVETYPE_BOUNCEMISSILE
- && ent->v.movetype != MOVETYPE_FLYMISSILE)
+ if (ent->v->movetype == MOVETYPE_TOSS || ent->v->movetype == MOVETYPE_BOUNCE)
SV_AddGravity (ent);
// move angles
- VectorMA (ent->v.angles, sv.frametime, ent->v.avelocity, ent->v.angles);
+ VectorMA (ent->v->angles, sv.frametime, ent->v->avelocity, ent->v->angles);
// move origin
- VectorScale (ent->v.velocity, sv.frametime, move);
- trace = SV_PushEntity (ent, move);
- if (trace.fraction == 1)
- return;
- if (ent->free)
+ VectorScale (ent->v->velocity, sv.frametime, move);
+ trace = SV_PushEntity (ent, move, vec3_origin);
+ if (ent->e->free)
return;
-
- if (ent->v.movetype == MOVETYPE_BOUNCE)
- backoff = 1.5;
- else if (ent->v.movetype == MOVETYPE_BOUNCEMISSILE)
- backoff = 2.0;
- else
- backoff = 1;
- ClipVelocity (ent->v.velocity, trace.plane.normal, ent->v.velocity, backoff);
-
-// stop if on ground
- if (trace.plane.normal[2] > 0.7)
- {
- if (ent->v.velocity[2] < 60 || (ent->v.movetype != MOVETYPE_BOUNCE && ent->v.movetype != MOVETYPE_BOUNCEMISSILE))
+ if (trace.fraction < 1)
+ {
+ if (ent->v->movetype == MOVETYPE_BOUNCEMISSILE)
+ {
+ ClipVelocity (ent->v->velocity, trace.plane.normal, ent->v->velocity, 2.0);
+ ent->v->flags = (int)ent->v->flags & ~FL_ONGROUND;
+ }
+ else if (ent->v->movetype == MOVETYPE_BOUNCE)
+ {
+ ClipVelocity (ent->v->velocity, trace.plane.normal, ent->v->velocity, 1.5);
+ // LordHavoc: fixed grenades not bouncing when fired down a slope
+ if (trace.plane.normal[2] > 0.7 && DotProduct(trace.plane.normal, ent->v->velocity) < 60)
+ {
+ ent->v->flags = (int)ent->v->flags | FL_ONGROUND;
+ ent->v->groundentity = EDICT_TO_PROG(trace.ent);
+ VectorClear (ent->v->velocity);
+ VectorClear (ent->v->avelocity);
+ }
+ else
+ ent->v->flags = (int)ent->v->flags & ~FL_ONGROUND;
+ }
+ else
{
- ent->v.flags = (int)ent->v.flags | FL_ONGROUND;
- ent->v.groundentity = EDICT_TO_PROG(trace.ent);
- VectorClear (ent->v.velocity);
- VectorClear (ent->v.avelocity);
+ ClipVelocity (ent->v->velocity, trace.plane.normal, ent->v->velocity, 1.0);
+ if (trace.plane.normal[2] > 0.7)
+ {
+ ent->v->flags = (int)ent->v->flags | FL_ONGROUND;
+ ent->v->groundentity = EDICT_TO_PROG(trace.ent);
+ VectorClear (ent->v->velocity);
+ VectorClear (ent->v->avelocity);
+ }
+ else
+ ent->v->flags = (int)ent->v->flags & ~FL_ONGROUND;
}
}
-
+
// check for in water
SV_CheckWaterTransition (ent);
}
*/
void SV_Physics_Step (edict_t *ent)
{
- qboolean hitsound;
-
-// freefall if not onground
- if ( ! ((int)ent->v.flags & (FL_ONGROUND | FL_FLY | FL_SWIM) ) )
+ // freefall if not onground/fly/swim
+ if (!((int)ent->v->flags & (FL_ONGROUND | FL_FLY | FL_SWIM)))
{
- if (ent->v.velocity[2] < sv_gravity.value*-0.1)
- hitsound = true;
- else
- hitsound = false;
+ int hitsound = ent->v->velocity[2] < sv_gravity.value * -0.1;
- SV_AddGravity (ent);
- SV_CheckVelocity (ent);
- SV_FlyMove (ent, sv.frametime, NULL);
- SV_LinkEdict (ent, true);
+ SV_AddGravity(ent);
+ SV_CheckVelocity(ent);
+ SV_FlyMove(ent, sv.frametime, NULL);
+ SV_LinkEdict(ent, false);
- if ( (int)ent->v.flags & FL_ONGROUND ) // just hit ground
- {
- if (hitsound)
- SV_StartSound (ent, 0, "demon/dland2.wav", 255, 1);
- }
+ // just hit ground
+ if (hitsound && (int)ent->v->flags & FL_ONGROUND)
+ SV_StartSound(ent, 0, "demon/dland2.wav", 255, 1);
}
// regular thinking
- SV_RunThink (ent);
-
- SV_CheckWaterTransition (ent);
+ SV_RunThink(ent);
+
+ SV_CheckWaterTransition(ent);
}
//============================================================================
================
*/
-extern dfunction_t *EndFrameQC;
void SV_Physics (void)
{
- int i;
- edict_t *ent;
+ int i;
+ edict_t *ent;
// let the progs know that a new frame has started
pr_global_struct->self = EDICT_TO_PROG(sv.edicts);
pr_global_struct->time = sv.time;
PR_ExecuteProgram (pr_global_struct->StartFrame, "QC function StartFrame is missing");
-//SV_CheckAllEnts ();
-
//
// treat each object in turn
//
ent = sv.edicts;
for (i=0 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent))
{
- if (ent->free)
+ if (ent->e->free)
continue;
if (pr_global_struct->force_retouch)
if (i > 0 && i <= svs.maxclients)
{
- SV_Physics_Client (ent, i);
- continue;
+ if (!svs.clients[i-1].spawned)
+ continue;
+ // connected slot
+ // call standard client pre-think
+ SV_CheckVelocity (ent);
+ pr_global_struct->time = sv.time;
+ pr_global_struct->self = EDICT_TO_PROG(ent);
+ PR_ExecuteProgram (pr_global_struct->PlayerPreThink, "QC function PlayerPreThink is missing");
+ SV_CheckVelocity (ent);
}
- switch ((int) ent->v.movetype)
+ // LordHavoc: merged client and normal entity physics
+ switch ((int) ent->v->movetype)
{
case MOVETYPE_PUSH:
SV_Physics_Pusher (ent);
break;
case MOVETYPE_NONE:
- SV_Physics_None (ent);
+ // LordHavoc: manually inlined the thinktime check here because MOVETYPE_NONE is used on so many objects
+ if (ent->v->nextthink > 0 && ent->v->nextthink <= sv.time + sv.frametime)
+ SV_RunThink (ent);
break;
case MOVETYPE_FOLLOW:
SV_Physics_Follow (ent);
break;
case MOVETYPE_NOCLIP:
- SV_Physics_Noclip (ent);
+ if (SV_RunThink(ent))
+ {
+ SV_CheckWater(ent);
+ VectorMA(ent->v->origin, sv.frametime, ent->v->velocity, ent->v->origin);
+ VectorMA(ent->v->angles, sv.frametime, ent->v->avelocity, ent->v->angles);
+ }
+ // relink normal entities here, players always get relinked so don't relink twice
+ if (!(i > 0 && i <= svs.maxclients))
+ SV_LinkEdict(ent, false);
break;
case MOVETYPE_STEP:
SV_Physics_Step (ent);
break;
- // LordHavoc: added support for MOVETYPE_WALK on normal entities! :)
case MOVETYPE_WALK:
if (SV_RunThink (ent))
{
- if (!SV_CheckWater (ent) && ! ((int)ent->v.flags & FL_WATERJUMP) )
+ if (!SV_CheckWater (ent) && ! ((int)ent->v->flags & FL_WATERJUMP) )
SV_AddGravity (ent);
SV_CheckStuck (ent);
SV_WalkMove (ent);
case MOVETYPE_TOSS:
case MOVETYPE_BOUNCE:
case MOVETYPE_BOUNCEMISSILE:
- case MOVETYPE_FLY:
case MOVETYPE_FLYMISSILE:
SV_Physics_Toss (ent);
break;
+ case MOVETYPE_FLY:
+ if (i > 0 && i <= svs.maxclients)
+ {
+ if (SV_RunThink (ent))
+ {
+ SV_CheckWater (ent);
+ SV_WalkMove (ent);
+ }
+ }
+ else
+ SV_Physics_Toss (ent);
+ break;
default:
- Host_Error ("SV_Physics: bad movetype %i", (int)ent->v.movetype);
+ Host_Error ("SV_Physics: bad movetype %i", (int)ent->v->movetype);
break;
}
+
+ if (i > 0 && i <= svs.maxclients && !ent->e->free)
+ {
+ SV_CheckVelocity (ent);
+
+ // call standard player post-think
+ SV_LinkEdict (ent, true);
+
+ SV_CheckVelocity (ent);
+
+ pr_global_struct->time = sv.time;
+ pr_global_struct->self = EDICT_TO_PROG(ent);
+ PR_ExecuteProgram (pr_global_struct->PlayerPostThink, "QC function PlayerPostThink is missing");
+ }
}
-
+
if (pr_global_struct->force_retouch)
- pr_global_struct->force_retouch--;
+ pr_global_struct->force_retouch--;
// LordHavoc: endframe support
if (EndFrameQC)
}
-trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore)
+trace_t SV_Trace_Toss (edict_t *tossent, edict_t *ignore)
{
int i;
- edict_t tempent, *tent;
- trace_t trace;
- vec3_t move;
- vec3_t end;
-
- memcpy(&tempent, ent, sizeof(edict_t));
+ float gravity, savesolid;
+ vec3_t move, end;
+ edict_t tempent, *tent;
+ entvars_t vars;
+ eval_t *val;
+ trace_t trace;
+
+ // copy the vars over
+ memcpy(&vars, tossent->v, sizeof(entvars_t));
+ // set up the temp entity to point to the copied vars
tent = &tempent;
+ tent->v = &vars;
+
+ savesolid = tossent->v->solid;
+ tossent->v->solid = SOLID_NOT;
+
+ // this has to fetch the field from the original edict, since our copy is truncated
+ val = GETEDICTFIELDVALUE(tossent, eval_gravity);
+ if (val != NULL && val->_float != 0)
+ gravity = val->_float;
+ else
+ gravity = 1.0;
+ gravity *= sv_gravity.value * 0.05;
for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
{
SV_CheckVelocity (tent);
- SV_AddGravity (tent);
- VectorMA (tent->v.angles, 0.05, tent->v.avelocity, tent->v.angles);
- VectorScale (tent->v.velocity, 0.05, move);
- VectorAdd (tent->v.origin, move, end);
- trace = SV_Move (tent->v.origin, tent->v.mins, tent->v.maxs, end, MOVE_NORMAL, tent);
- VectorCopy (trace.endpos, tent->v.origin);
-
- if (trace.ent)
+ tent->v->velocity[2] -= gravity;
+ VectorMA (tent->v->angles, 0.05, tent->v->avelocity, tent->v->angles);
+ VectorScale (tent->v->velocity, 0.05, move);
+ VectorAdd (tent->v->origin, move, end);
+ trace = SV_Move (tent->v->origin, tent->v->mins, tent->v->maxs, end, MOVE_NORMAL, tent);
+ VectorCopy (trace.endpos, tent->v->origin);
+
+ if (trace.fraction < 1 && trace.ent)
if (trace.ent != ignore)
break;
}
+ tossent->v->solid = savesolid;
trace.fraction = 0; // not relevant
return trace;
}
+