From: lordhavoc Date: Sun, 9 Jun 2002 00:30:10 +0000 (+0000) Subject: SV_PointContents removed (all calls replaced with Mod_PointInLeaf, which is faster) X-Git-Tag: RELEASE_0_2_0_RC1~472 X-Git-Url: https://git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=commitdiff_plain;h=08489c3f40fec505da1c0af823e388a5f53a1560 SV_PointContents removed (all calls replaced with Mod_PointInLeaf, which is faster) SV_HullPointContents removed (no longer needed) SV_TestEntityPosition now returns an int (true if in solid) rather than an edict_t * sv_jumpstep added - step up while airborn, for example when jumping sv_wallfriction added - to allow it to be turned off if desired fly and noclip movement for players is now more like swimming git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@1933 d7cf8633-e32d-0410-b094-e92efae38249 --- diff --git a/pr_cmds.c b/pr_cmds.c index 6042f097..85dbfcef 100644 --- a/pr_cmds.c +++ b/pr_cmds.c @@ -1443,7 +1443,7 @@ PF_pointcontents */ void PF_pointcontents (void) { - G_FLOAT(OFS_RETURN) = SV_PointContents (G_VECTOR(OFS_PARM0)); + G_FLOAT(OFS_RETURN) = Mod_PointInLeaf(G_VECTOR(OFS_PARM0), sv.worldmodel)->contents; } /* diff --git a/server.h b/server.h index 88813efc..a0d80b31 100644 --- a/server.h +++ b/server.h @@ -219,6 +219,8 @@ extern cvar_t sv_accelerate; extern cvar_t sv_idealpitchscale; extern cvar_t sv_aim; extern cvar_t sv_predict; +extern cvar_t sv_stepheight; +extern cvar_t sv_jumpstep; extern server_static_t svs; // persistant server info extern server_t sv; // local server diff --git a/sv_move.c b/sv_move.c index ffaa44a7..dd710970 100644 --- a/sv_move.c +++ b/sv_move.c @@ -21,8 +21,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" -#define STEPSIZE 18 - /* ============= SV_CheckBottom @@ -40,7 +38,7 @@ qboolean SV_CheckBottom (edict_t *ent) trace_t trace; int x, y; float mid, bottom; - + VectorAdd (ent->v.origin, ent->v.mins, mins); VectorAdd (ent->v.origin, ent->v.maxs, maxs); @@ -53,7 +51,7 @@ qboolean SV_CheckBottom (edict_t *ent) { start[0] = x ? maxs[0] : mins[0]; start[1] = y ? maxs[1] : mins[1]; - if (SV_PointContents (start) != CONTENTS_SOLID) + if (Mod_PointInLeaf(start, sv.worldmodel)->contents != CONTENTS_SOLID) goto realcheck; } @@ -66,29 +64,29 @@ realcheck: // check it for real... // start[2] = mins[2]; - + // the midpoint must be within 16 of the bottom start[0] = stop[0] = (mins[0] + maxs[0])*0.5; start[1] = stop[1] = (mins[1] + maxs[1])*0.5; - stop[2] = start[2] - 2*STEPSIZE; + stop[2] = start[2] - 2*sv_stepheight.value; trace = SV_Move (start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, ent); if (trace.fraction == 1.0) return false; mid = bottom = trace.endpos[2]; - -// the corners must be within 16 of the midpoint + +// the corners must be within 16 of the midpoint for (x=0 ; x<=1 ; x++) for (y=0 ; y<=1 ; y++) { start[0] = stop[0] = x ? maxs[0] : mins[0]; start[1] = stop[1] = y ? maxs[1] : mins[1]; - + trace = SV_Move (start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, ent); - + if (trace.fraction != 1.0 && trace.endpos[2] > bottom) bottom = trace.endpos[2]; - if (trace.fraction == 1.0 || mid - trace.endpos[2] > STEPSIZE) + if (trace.fraction == 1.0 || mid - trace.endpos[2] > sv_stepheight.value) return false; } @@ -140,7 +138,7 @@ qboolean SV_movestep (edict_t *ent, vec3_t move, qboolean relink) if (trace.fraction == 1) { VectorCopy(trace.endpos, traceendpos); - if ( ((int)ent->v.flags & FL_SWIM) && SV_PointContents(traceendpos) == CONTENTS_EMPTY ) + if ( ((int)ent->v.flags & FL_SWIM) && Mod_PointInLeaf(traceendpos, sv.worldmodel)->contents == CONTENTS_EMPTY ) return false; // swim monster left water VectorCopy (traceendpos, ent->v.origin); @@ -157,9 +155,9 @@ qboolean SV_movestep (edict_t *ent, vec3_t move, qboolean relink) } // push down from a step height above the wished position - neworg[2] += STEPSIZE; + neworg[2] += sv_stepheight.value; VectorCopy (neworg, end); - end[2] -= STEPSIZE*2; + end[2] -= sv_stepheight.value*2; trace = SV_Move (neworg, ent->v.mins, ent->v.maxs, end, MOVE_NORMAL, ent); @@ -168,7 +166,7 @@ qboolean SV_movestep (edict_t *ent, vec3_t move, qboolean relink) if (trace.startsolid) { - neworg[2] -= STEPSIZE; + neworg[2] -= sv_stepheight.value; trace = SV_Move (neworg, ent->v.mins, ent->v.maxs, end, MOVE_NORMAL, ent); if (trace.allsolid || trace.startsolid) return false; @@ -321,7 +319,7 @@ void SV_NewChaseDir (edict_t *actor, edict_t *enemy, float dist) d[2]=tdir; } - if (d[1]!=DI_NODIR && d[1]!=turnaround + if (d[1]!=DI_NODIR && d[1]!=turnaround && SV_StepDirection(actor, d[1], dist)) return; @@ -369,7 +367,7 @@ SV_CloseEnough qboolean SV_CloseEnough (edict_t *ent, edict_t *goal, float dist) { int i; - + for (i=0 ; i<3 ; i++) { if (goal->v.absmin[i] > ent->v.absmax[i] + dist) diff --git a/sv_phys.c b/sv_phys.c index 5d8db602..3f13b9cd 100644 --- a/sv_phys.c +++ b/sv_phys.c @@ -39,12 +39,14 @@ solid_edge items only clip against bsp models. */ -cvar_t sv_friction = {CVAR_NOTIFY, "sv_friction","4"}; -cvar_t sv_stopspeed = {0, "sv_stopspeed","100"}; -cvar_t sv_gravity = {CVAR_NOTIFY, "sv_gravity","800"}; -cvar_t sv_maxvelocity = {0, "sv_maxvelocity","2000"}; -cvar_t sv_nostep = {0, "sv_nostep","0"}; -cvar_t sv_stepheight = {0, "sv_stepheight", "18"}; +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"}; #define MOVE_EPSILON 0.01 @@ -53,6 +55,8 @@ void SV_Physics_Toss (edict_t *ent); void SV_Phys_Init (void) { Cvar_RegisterVariable(&sv_stepheight); + Cvar_RegisterVariable(&sv_jumpstep); + Cvar_RegisterVariable(&sv_wallfriction); } /* @@ -62,19 +66,19 @@ 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 ; efree) continue; if (check->v.movetype == MOVETYPE_PUSH - || check->v.movetype == MOVETYPE_NONE - || check->v.movetype == MOVETYPE_FOLLOW - || check->v.movetype == MOVETYPE_NOCLIP) + || check->v.movetype == MOVETYPE_NONE + || check->v.movetype == MOVETYPE_FOLLOW + || check->v.movetype == MOVETYPE_NOCLIP) continue; if (SV_TestEntityPosition (check)) @@ -89,8 +93,8 @@ SV_CheckVelocity */ void SV_CheckVelocity (edict_t *ent) { - int i; - float wishspeed; + int i; + float wishspeed; // // bound velocity @@ -132,16 +136,17 @@ Returns false if the entity removed itself. */ qboolean SV_RunThink (edict_t *ent) { - float thinktime; + float thinktime; 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. + thinktime = sv.time; + ent->v.nextthink = 0; pr_global_struct->time = thinktime; pr_global_struct->self = EDICT_TO_PROG(ent); @@ -159,7 +164,7 @@ Two entities have touched, so run their touch functions */ 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; @@ -192,25 +197,25 @@ Slide off of the impacting object returns the blocked flags (1 = floor, 2 = step / wall) ================== */ -#define STOP_EPSILON 0.1 - +#define STOP_EPSILON 0.1 int ClipVelocity (vec3_t in, vec3_t normal, vec3_t out, float overbounce) { - float backoff; - float change; - int i, blocked; + int i, blocked; + float backoff, change; blocked = 0; + // flag if it's a floor if (normal[2] > 0) - blocked |= 1; // floor + blocked |= 1; + // flag if it's a step if (!normal[2]) - blocked |= 2; // step + blocked |= 2; backoff = DotProduct (in, normal) * overbounce; - for (i=0 ; i<3 ; i++) + for (i = 0;i < 3;i++) { - change = normal[i]*backoff; + change = normal[i] * backoff; out[i] = in[i] - change; if (out[i] > -STOP_EPSILON && out[i] < STOP_EPSILON) out[i] = 0; @@ -233,20 +238,13 @@ If steptrace is not NULL, the trace of any vertical wall hit will be stored ============ */ // LordHavoc: increased from 5 to 20 -#define MAX_CLIP_PLANES 20 +#define MAX_CLIP_PLANES 20 int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace) { - 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, impact; + 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; numbumps = 4; @@ -276,14 +274,16 @@ int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace) } if (trace.fraction > 0) - { // actually covered some distance + { + // 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; // moved the entire distance + break; if (!trace.ent) Host_Error ("SV_FlyMove: !trace.ent"); @@ -303,31 +303,37 @@ int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace) if (trace.plane.normal[2] > 0.7) { - blocked |= 1; // floor + // 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]) { - blocked |= 2; // step + // step + blocked |= 2; + // save the trace for player extrafriction if (steptrace) - *steptrace = trace; // save for player extrafriction + *steptrace = trace; } -// -// run the impact function -// + // run the impact function if (impact) + { SV_Impact (ent, trace.ent); - if (ent->free) - break; // removed by the impact function + + // break if removed by the impact function + if (ent->free) + break; + } time_left -= time_left * trace.fraction; - // cliped to another plane + // clipped to another plane if (numplanes >= MAX_CLIP_PLANES) - { // this shouldn't really happen + { + // this shouldn't really happen VectorClear(ent->v.velocity); return 3; } @@ -335,28 +341,29 @@ int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace) VectorCopy (trace.plane.normal, planes[numplanes]); numplanes++; -// -// modify original_velocity so it parallels all of the clip planes -// + // modify original_velocity so it parallels all of the clip planes for (i=0 ; iv.velocity); } else - { // go along the crease + { + // go along the crease if (numplanes != 2) { VectorClear(ent->v.velocity); @@ -369,10 +376,8 @@ int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace) VectorScale (dir, d, ent->v.velocity); } -// -// if original velocity is against the original velocity, stop dead -// to avoid tiny occilations in sloping corners -// + // 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); @@ -392,9 +397,8 @@ SV_AddGravity */ 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) @@ -422,15 +426,15 @@ Does not change the entities velocity at all */ trace_t SV_PushEntity (edict_t *ent, vec3_t push, vec3_t pushangles) { - trace_t trace; - vec3_t end; + 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 + // 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); @@ -458,7 +462,7 @@ void SV_PushMove (edict_t *pusher, float movetime) int i, e, index; edict_t *check; float savesolid, movetime2, pushltime; - vec3_t mins, maxs, move, move1, moveangle, /*entorig, entang, */pushorig, pushang, a, forward, left, up, org, org2; + vec3_t mins, maxs, move, move1, moveangle, pushorig, pushang, a, forward, left, up, org, org2; int num_moved; edict_t *moved_edict[MAX_EDICTS]; vec3_t moved_from[MAX_EDICTS], moved_fromangles[MAX_EDICTS]; @@ -663,9 +667,7 @@ SV_Physics_Pusher */ void SV_Physics_Pusher (edict_t *ent) { - float thinktime; - float oldltime; - float movetime; + float thinktime, oldltime, movetime; oldltime = ent->v.ltime; @@ -680,7 +682,8 @@ void SV_Physics_Pusher (edict_t *ent) movetime = sv.frametime; if (movetime) - SV_PushMove (ent, movetime); // advances ent->v.ltime if not blocked + // advances ent->v.ltime if not blocked + SV_PushMove (ent, movetime); if (thinktime > oldltime && thinktime <= ent->v.ltime) { @@ -714,9 +717,8 @@ clipping hull. */ 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)) { @@ -747,7 +749,7 @@ void SV_CheckStuck (edict_t *ent) return; } } - + VectorCopy (org, ent->v.origin); Con_DPrintf ("player is stuck.\n"); } @@ -760,27 +762,27 @@ SV_CheckWater */ qboolean SV_CheckWater (edict_t *ent) { - vec3_t point; - int cont; + 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_PointContents (point); + cont = Mod_PointInLeaf(point, sv.worldmodel)->contents; 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); + cont = Mod_PointInLeaf(point, sv.worldmodel)->contents; if (cont <= CONTENTS_WATER) { ent->v.waterlevel = 2; point[2] = ent->v.origin[2] + ent->v.view_ofs[2]; - cont = SV_PointContents (point); + cont = Mod_PointInLeaf(point, sv.worldmodel)->contents; if (cont <= CONTENTS_WATER) ent->v.waterlevel = 3; } @@ -797,22 +799,21 @@ SV_WallFriction */ void SV_WallFriction (edict_t *ent, trace_t *trace) { - vec3_t forward; - float d, i; - vec3_t into, side; + float d, i; + vec3_t forward, 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 + // 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); } @@ -831,50 +832,47 @@ This is a hack, but in the interest of good gameplay... */ int SV_TryUnstick (edict_t *ent, vec3_t oldvel) { - int i; - vec3_t oldorg; - vec3_t dir; - int clip; - trace_t steptrace; + int i, clip; + vec3_t oldorg, dir; + trace_t steptrace; 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, vec3_origin); -// retry the original move + // 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); - if ( fabs(oldorg[1] - ent->v.origin[1]) > 4 - || fabs(oldorg[0] - ent->v.origin[0]) > 4 ) - { + 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 + // go back to the original pos and try again VectorCopy (oldorg, ent->v.origin); } - + + // still not moving VectorClear (ent->v.velocity); - return 7; // still not moving + return 7; } /* @@ -886,16 +884,11 @@ Only used by players */ 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; + int clip, oldonground; + vec3_t upmove, downmove, oldorg, oldvel, nosteporg, nostepvel; + trace_t steptrace, downtrace; -// -// do a regular slide move unless it looks like you ran into a step -// + // 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; @@ -904,14 +897,20 @@ void SV_WalkMove (edict_t *ent) clip = SV_FlyMove (ent, sv.frametime, &steptrace); + // if move didn't block on a step, return if ( !(clip & 2) ) - return; // move didn't block on a step + return; - if (!oldonground && ent->v.waterlevel == 0) - return; // don't stair up while jumping + if (ent->v.movetype != MOVETYPE_FLY) + { + if (!oldonground && ent->v.waterlevel == 0 && !sv_jumpstep.integer) + // don't stair up while jumping + return; - if (ent->v.movetype != MOVETYPE_WALK) - return; // gibbed by a trigger + if (ent->v.movetype != MOVETYPE_WALK) + // gibbed by a trigger + return; + } if (sv_nostep.integer) return; @@ -922,42 +921,43 @@ void SV_WalkMove (edict_t *ent) VectorCopy (ent->v.origin, nosteporg); VectorCopy (ent->v.velocity, nostepvel); -// -// try moving up and forward to go up a step -// - VectorCopy (oldorg, ent->v.origin); // back to start pos + // try moving up and forward to go up a step + // back to start pos + VectorCopy (oldorg, ent->v.origin); VectorClear (upmove); VectorClear (downmove); upmove[2] = sv_stepheight.value; downmove[2] = -sv_stepheight.value + oldvel[2]*sv.frametime; -// move up - SV_PushEntity (ent, upmove, vec3_origin); // FIXME: don't link? + // move up + // FIXME: don't link? + SV_PushEntity (ent, upmove, vec3_origin); -// move forward + // move forward ent->v.velocity[0] = oldvel[0]; - ent->v. velocity[1] = oldvel[1]; - ent->v. velocity[2] = 0; + ent->v.velocity[1] = oldvel[1]; + ent->v.velocity[2] = 0; clip = SV_FlyMove (ent, sv.frametime, &steptrace); - -// 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 ) + 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, &steptrace); -// move down - downtrace = SV_PushEntity (ent, downmove, vec3_origin); // FIXME: don't link? + // move down + // FIXME: don't link? + downtrace = SV_PushEntity (ent, downmove, vec3_origin); if (downtrace.plane.normal[2] > 0.7) { @@ -969,9 +969,9 @@ void SV_WalkMove (edict_t *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 + // 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); } @@ -1067,9 +1067,11 @@ void SV_Physics_Follow (edict_t *ent) { 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]) @@ -1107,7 +1109,7 @@ A moving object that doesn't obey physics */ void SV_Physics_Noclip (edict_t *ent) { -// regular thinking + // regular thinking if (!SV_RunThink (ent)) return; @@ -1134,9 +1136,10 @@ SV_CheckWaterTransition void SV_CheckWaterTransition (edict_t *ent) { int cont; - cont = SV_PointContents (ent->v.origin); + cont = Mod_PointInLeaf(ent->v.origin, sv.worldmodel)->contents; if (!ent->v.watertype) - { // just spawned here + { + // just spawned here ent->v.watertype = cont; ent->v.waterlevel = 1; return; @@ -1145,18 +1148,18 @@ void SV_CheckWaterTransition (edict_t *ent) if (cont <= CONTENTS_WATER) { if (ent->v.watertype == CONTENTS_EMPTY) - { // just crossed into water + // just crossed into water SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1); - } + ent->v.watertype = cont; ent->v.waterlevel = 1; } else { if (ent->v.watertype != CONTENTS_EMPTY) - { // just crossed into water + // just crossed into water SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1); - } + ent->v.watertype = CONTENTS_EMPTY; ent->v.waterlevel = cont; } @@ -1171,9 +1174,9 @@ Toss, bounce, and fly movement. When onground, do nothing. */ void SV_Physics_Toss (edict_t *ent) { - trace_t trace; - vec3_t move; - edict_t *groundentity; + trace_t trace; + vec3_t move; + edict_t *groundentity; // regular thinking if (!SV_RunThink (ent)) @@ -1283,7 +1286,7 @@ void SV_Physics_Step (edict_t *ent) { if (flags & FL_FLY) fall = false; - else if ((flags & FL_SWIM) && SV_PointContents(ent->v.origin) != CONTENTS_EMPTY) + else if ((flags & FL_SWIM) && Mod_PointInLeaf(ent->v.origin, sv.worldmodel)->contents != CONTENTS_EMPTY) fall = false; } if (fall && (flags & FL_ONGROUND) && ent->v.groundentity == 0) @@ -1330,8 +1333,8 @@ SV_Physics */ 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); @@ -1419,12 +1422,11 @@ void SV_Physics (void) 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; - float gravity, savesolid; - eval_t *val; + float gravity, savesolid; + vec3_t move, end; + edict_t tempent, *tent; + eval_t *val; + trace_t trace; memcpy(&tempent, tossent, sizeof(edict_t)); tent = &tempent; diff --git a/sv_user.c b/sv_user.c index 30a654a7..41fae363 100644 --- a/sv_user.c +++ b/sv_user.c @@ -21,28 +21,28 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" -edict_t *sv_player; +edict_t *sv_player; -cvar_t sv_edgefriction = {0, "edgefriction", "2"}; -cvar_t sv_predict = {0, "sv_predict", "1"}; -cvar_t sv_deltacompress = {0, "sv_deltacompress", "1"}; -cvar_t sv_idealpitchscale = {0, "sv_idealpitchscale","0.8"}; -cvar_t sv_maxspeed = {CVAR_NOTIFY, "sv_maxspeed", "320"}; -cvar_t sv_accelerate = {0, "sv_accelerate", "10"}; +cvar_t sv_edgefriction = {0, "edgefriction", "2"}; +cvar_t sv_predict = {0, "sv_predict", "1"}; +cvar_t sv_deltacompress = {0, "sv_deltacompress", "1"}; +cvar_t sv_idealpitchscale = {0, "sv_idealpitchscale","0.8"}; +cvar_t sv_maxspeed = {CVAR_NOTIFY, "sv_maxspeed", "320"}; +cvar_t sv_accelerate = {0, "sv_accelerate", "10"}; -static vec3_t forward, right, up; +static vec3_t forward, right, up; -vec3_t wishdir; -float wishspeed; +vec3_t wishdir; +float wishspeed; // world -float *angles; -float *origin; -float *velocity; +float *angles; +float *origin; +float *velocity; -qboolean onground; +qboolean onground; -usercmd_t cmd; +usercmd_t cmd; /* @@ -62,7 +62,7 @@ void SV_SetIdealPitch (void) if (!((int)sv_player->v.flags & FL_ONGROUND)) return; - + angleval = sv_player->v.angles[YAW] * M_PI*2 / 360; sinval = sin(angleval); cosval = cos(angleval); @@ -78,15 +78,17 @@ void SV_SetIdealPitch (void) bottom[2] = top[2] - 160; tr = SV_Move (top, vec3_origin, vec3_origin, bottom, MOVE_NOMONSTERS, sv_player); + // if looking at a wall, leave ideal the way is was if (tr.allsolid) - return; // looking at a wall, leave ideal the way is was + return; + // near a dropoff if (tr.fraction == 1) - return; // near a dropoff - + return; + z[i] = top[2] + tr.fraction*(bottom[2]-top[2]); } - + dir = 0; steps = 0; for (j=1 ; j -ON_EPSILON && step < ON_EPSILON) continue; + // mixed changes if (dir && ( step-dir > ON_EPSILON || step-dir < -ON_EPSILON ) ) - return; // mixed changes + return; - steps++; + steps++; dir = step; } - + if (!dir) { sv_player->v.idealpitch = 0; return; } - + if (steps < 2) return; sv_player->v.idealpitch = -dir * sv_idealpitchscale.value; @@ -122,19 +125,17 @@ SV_UserFriction */ void SV_UserFriction (void) { - float *vel; - float speed, newspeed, control; - vec3_t start, stop; - float friction; - trace_t trace; - + float *vel, speed, newspeed, control, friction; + vec3_t start, stop; + trace_t trace; + vel = velocity; - + speed = sqrt(vel[0]*vel[0] +vel[1]*vel[1]); if (!speed) return; -// if the leading edge is over a dropoff, increase friction + // if the leading edge is over a dropoff, increase friction start[0] = stop[0] = origin[0] + vel[0]/speed*16; start[1] = stop[1] = origin[1] + vel[1]/speed*16; start[2] = origin[2] + sv_player->v.mins[2]; @@ -147,7 +148,7 @@ void SV_UserFriction (void) else friction = sv_friction.value; -// apply friction + // apply friction control = speed < sv_stopspeed.value ? sv_stopspeed.value : speed; newspeed = speed - sv.frametime*control*friction; @@ -168,8 +169,8 @@ SV_Accelerate */ void SV_Accelerate (void) { - int i; - float addspeed, accelspeed, currentspeed; + int i; + float addspeed, accelspeed, currentspeed; currentspeed = DotProduct (velocity, wishdir); addspeed = wishspeed - currentspeed; @@ -178,16 +179,16 @@ void SV_Accelerate (void) accelspeed = sv_accelerate.value*sv.frametime*wishspeed; if (accelspeed > addspeed) accelspeed = addspeed; - + for (i=0 ; i<3 ; i++) - velocity[i] += accelspeed*wishdir[i]; + velocity[i] += accelspeed*wishdir[i]; } void SV_AirAccelerate (vec3_t wishveloc) { - int i; - float addspeed, wishspd, accelspeed, currentspeed; - + int i; + float addspeed, wishspd, accelspeed, currentspeed; + wishspd = VectorNormalizeLength (wishveloc); if (wishspd > 30) wishspd = 30; @@ -198,28 +199,28 @@ void SV_AirAccelerate (vec3_t wishveloc) accelspeed = sv_accelerate.value*wishspeed * sv.frametime; if (accelspeed > addspeed) accelspeed = addspeed; - + for (i=0 ; i<3 ; i++) - velocity[i] += accelspeed*wishveloc[i]; + velocity[i] += accelspeed*wishveloc[i]; } void DropPunchAngle (void) { - float len; - eval_t *val; - + float len; + eval_t *val; + len = VectorNormalizeLength (sv_player->v.punchangle); len -= 10*sv.frametime; if (len < 0) len = 0; VectorScale (sv_player->v.punchangle, len, sv_player->v.punchangle); - + if ((val = GETEDICTFIELDVALUE(sv_player, eval_punchvector))) { len = VectorNormalizeLength (val->vector); - + len -= 20*sv.frametime; if (len < 0) len = 0; @@ -227,6 +228,31 @@ void DropPunchAngle (void) } } +/* +=================== +SV_FreeMove +=================== +*/ +void SV_FreeMove (void) +{ + int i; + float wishspeed; + + AngleVectors (sv_player->v.v_angle, forward, right, up); + + for (i = 0; i < 3; i++) + velocity[i] = forward[i] * cmd.forwardmove + right[i] * cmd.sidemove; + + velocity[2] += cmd.upmove; + + wishspeed = VectorLength (velocity); + if (wishspeed > sv_maxspeed.value) + { + VectorScale (velocity, sv_maxspeed.value / wishspeed, velocity); + wishspeed = sv_maxspeed.value; + } +} + /* =================== SV_WaterMove @@ -235,13 +261,11 @@ SV_WaterMove */ void SV_WaterMove (void) { - int i; - vec3_t wishvel; - float speed, newspeed, wishspeed, addspeed, accelspeed, temp; + int i; + vec3_t wishvel; + float speed, newspeed, wishspeed, addspeed, accelspeed, temp; -// -// user intentions -// + // user intentions AngleVectors (sv_player->v.v_angle, forward, right, up); for (i=0 ; i<3 ; i++) @@ -261,9 +285,7 @@ void SV_WaterMove (void) } wishspeed *= 0.7; -// -// water friction -// + // water friction speed = VectorLength (velocity); if (speed) { @@ -275,10 +297,8 @@ void SV_WaterMove (void) } else newspeed = 0; - -// -// water acceleration -// + + // water acceleration if (!wishspeed) return; @@ -297,8 +317,7 @@ void SV_WaterMove (void) void SV_WaterJump (void) { - if (sv.time > sv_player->v.teleport_time - || !sv_player->v.waterlevel) + if (sv.time > sv_player->v.teleport_time || !sv_player->v.waterlevel) { sv_player->v.flags = (int)sv_player->v.flags & ~FL_WATERJUMP; sv_player->v.teleport_time = 0; @@ -316,9 +335,9 @@ SV_AirMove */ void SV_AirMove (void) { - int i; - vec3_t wishvel; - float fmove, smove, temp; + int i; + vec3_t wishvel; + float fmove, smove, temp; // LordHavoc: correct quake movement speed bug when looking up/down wishvel[0] = wishvel[2] = 0; @@ -327,18 +346,16 @@ void SV_AirMove (void) fmove = cmd.forwardmove; smove = cmd.sidemove; - + // hack to not let you back into teleporter if (sv.time < sv_player->v.teleport_time && fmove < 0) fmove = 0; - + for (i=0 ; i<3 ; i++) wishvel[i] = forward[i]*fmove + right[i]*smove; - if ( (int)sv_player->v.movetype != MOVETYPE_WALK) - wishvel[2] = cmd.upmove; - else - wishvel[2] = 0; + if ((int)sv_player->v.movetype != MOVETYPE_WALK) + wishvel[2] += cmd.upmove; VectorCopy (wishvel, wishdir); wishspeed = VectorNormalizeLength(wishdir); @@ -348,9 +365,10 @@ void SV_AirMove (void) VectorScale (wishvel, temp, wishvel); wishspeed = sv_maxspeed.value; } - - if ( sv_player->v.movetype == MOVETYPE_NOCLIP) - { // noclip + + if (sv_player->v.movetype == MOVETYPE_NOCLIP) + { + // noclip VectorCopy (wishvel, velocity); } else if ( onground ) @@ -359,7 +377,8 @@ void SV_AirMove (void) SV_Accelerate (); } else - { // not on ground, so little effect on velocity + { + // not on ground, so little effect on velocity SV_AirAccelerate (wishvel); } } @@ -374,30 +393,27 @@ the angle fields specify an exact angular motion in degrees */ void SV_ClientThink (void) { - vec3_t v_angle; + vec3_t v_angle; if (sv_player->v.movetype == MOVETYPE_NONE) return; - + onground = (int)sv_player->v.flags & FL_ONGROUND; origin = sv_player->v.origin; velocity = sv_player->v.velocity; DropPunchAngle (); - -// -// if dead, behave differently -// + + // if dead, behave differently if (sv_player->v.health <= 0) return; -// -// angles -// show 1/3 the pitch angle and all the roll angle + // angles + // show 1/3 the pitch angle and all the roll angle cmd = host_client->cmd; angles = sv_player->v.angles; - + VectorAdd (sv_player->v.v_angle, sv_player->v.punchangle, v_angle); angles[ROLL] = V_CalcRoll (sv_player->v.angles, sv_player->v.velocity)*4; if (!sv_player->v.fixangle) @@ -415,10 +431,18 @@ void SV_ClientThink (void) SV_WaterJump (); return; } -// -// walk -// - if ( (sv_player->v.waterlevel >= 2) && (sv_player->v.movetype != MOVETYPE_NOCLIP) ) + + // Player is (somehow) outside of the map, or flying, or noclipping + if (SV_TestEntityPosition (sv_player) + || sv_player->v.movetype == MOVETYPE_FLY + || sv_player->v.movetype == MOVETYPE_NOCLIP) + { + SV_FreeMove (); + return; + } + + // walk + if ((sv_player->v.waterlevel >= 2) && (sv_player->v.movetype != MOVETYPE_NOCLIP)) { SV_WaterMove (); return; @@ -435,32 +459,34 @@ SV_ReadClientMove */ void SV_ReadClientMove (usercmd_t *move) { - int i; - vec3_t angle; - int bits; - eval_t *val; - float total; + int i; + vec3_t angle; + int bits; + eval_t *val; + float total; -// read ping time + // read ping time host_client->ping_times[host_client->num_pings % NUM_PING_TIMES] = sv.time - MSG_ReadFloat (); host_client->num_pings++; for (i=0, total = 0;i < NUM_PING_TIMES;i++) total += host_client->ping_times[i]; - host_client->ping = total / NUM_PING_TIMES; // can be used for prediction + // can be used for prediction + host_client->ping = total / NUM_PING_TIMES; host_client->latency = 0; - if (sv_predict.integer && (svs.maxclients > 1) && (!sv.paused)) // if paused or a local game, don't predict + // if paused or a local game, don't predict + if (sv_predict.integer && (svs.maxclients > 1) && (!sv.paused)) host_client->latency = host_client->ping; if ((val = GETEDICTFIELDVALUE(host_client->edict, eval_ping))) val->_float = host_client->ping * 1000.0; -// read current angles + // read current angles // dpprotocol version 2 for (i = 0;i < 3;i++) angle[i] = MSG_ReadFloat (); VectorCopy (angle, host_client->edict->v.v_angle); -// read movement + // read movement move->forwardmove = MSG_ReadShort (); move->sidemove = MSG_ReadShort (); move->upmove = MSG_ReadShort (); @@ -471,7 +497,7 @@ void SV_ReadClientMove (usercmd_t *move) val->vector[2] = move->upmove; } -// read buttons + // read buttons bits = MSG_ReadByte (); host_client->edict->v.button0 = bits & 1; host_client->edict->v.button2 = (bits & 2)>>1; @@ -495,7 +521,7 @@ SV_ReadClientMessage Returns false if the client should be killed =================== */ -void SV_SendServerinfo (client_t *client); +extern void SV_SendServerinfo (client_t *client); qboolean SV_ReadClientMessage (void) { int ret; @@ -519,7 +545,8 @@ nextmsg: while (1) { if (!host_client->active) - return false; // a command caused an error + // a command caused an error + return false; if (msg_badread) { @@ -540,7 +567,8 @@ nextmsg: switch (cmd) { case -1: - goto nextmsg; // end of message + // end of message + goto nextmsg; default: Sys_Printf ("SV_ReadClientMessage: unknown command char %i\n", cmd); @@ -589,7 +617,8 @@ nextmsg: break; } } - } while (ret == 1); + } + while (ret == 1); return true; } @@ -602,29 +631,30 @@ SV_RunClients */ void SV_RunClients (void) { - int i; + int i; for (i=0, host_client = svs.clients ; iactive) continue; - + sv_player = host_client->edict; if (!SV_ReadClientMessage ()) { - SV_DropClient (false); // client misbehaved... + // client misbehaved... + SV_DropClient (false); continue; } if (!host_client->spawned) { - // clear client movement until a new packet is received + // clear client movement until a new packet is received memset (&host_client->cmd, 0, sizeof(host_client->cmd)); continue; } -// always pause in single player if in console or menus + // always pause in single player if in console or menus if (!sv.paused && (svs.maxclients > 1 || key_dest == key_game) ) { // LordHavoc: QuakeC replacement for SV_ClientThink (player movement) diff --git a/world.c b/world.c index 1ce1b73a..31dddb51 100644 --- a/world.c +++ b/world.c @@ -383,20 +383,6 @@ POINT TESTING IN HULLS =============================================================================== */ -/* -================== -SV_HullPointContents - -================== -*/ -int SV_HullPointContents (hull_t *hull, int num, vec3_t p) -{ - while (num >= 0) - num = hull->clipnodes[num].children[(hull->planes[hull->clipnodes[num].planenum].type < 3 ? p[hull->planes[hull->clipnodes[num].planenum].type] : DotProduct (hull->planes[hull->clipnodes[num].planenum].normal, p)) < hull->planes[hull->clipnodes[num].planenum].dist]; - - return num; -} - /* ============ SV_TestEntityPosition @@ -404,16 +390,9 @@ SV_TestEntityPosition This could be a lot more efficient... ============ */ -edict_t *SV_TestEntityPosition (edict_t *ent) +int SV_TestEntityPosition (edict_t *ent) { - trace_t trace; - - trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, ent->v.origin, MOVE_NORMAL, ent); - - if (trace.startsolid) - return sv.edicts; - - return NULL; + return SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, ent->v.origin, MOVE_NORMAL, ent).startsolid; } diff --git a/world.h b/world.h index 81c662ce..eaea6224 100644 --- a/world.h +++ b/world.h @@ -29,31 +29,22 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define MOVE_MISSILE 2 -void SV_ClearWorld (void); // called after the world model has been loaded, before linking any entities +void SV_ClearWorld (void); -void SV_UnlinkEdict (edict_t *ent); // call before removing an entity, and before trying to move one, // so it doesn't clip against itself -// flags ent->v.modified +void SV_UnlinkEdict (edict_t *ent); -void SV_LinkEdict (edict_t *ent, qboolean touch_triggers); // Needs to be called any time an entity changes origin, mins, maxs, or solid -// flags ent->v.modified // sets ent->v.absmin and ent->v.absmax // if touchtriggers, calls prog functions for the intersected triggers +void SV_LinkEdict (edict_t *ent, qboolean touch_triggers); -extern int SV_HullPointContents (hull_t *hull, int num, vec3_t p); -#define SV_PointContents(testpoint) SV_HullPointContents(&sv.worldmodel->hulls[0], 0, (testpoint)) -// returns the CONTENTS_* value from the world at the given point. -// does not check any entities at all -// the non-true version remaps the water current contents to content_water - -edict_t *SV_TestEntityPosition (edict_t *ent); +// returns true if the entity is in solid currently +int SV_TestEntityPosition (edict_t *ent); -trace_t SV_Move (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int type, edict_t *passedict); // mins and maxs are relative - // if the entire move stays in a solid volume, trace.allsolid will be set // if the starting point is in a solid, it will be allowed to move out @@ -63,6 +54,7 @@ trace_t SV_Move (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int type, e // shouldn't be considered solid objects // passedict is explicitly excluded from clipping checks (normally NULL) +trace_t SV_Move (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int type, edict_t *passedict); #endif