bring sv_phys.c closer to being mergable. I've temporarily(?) disabled

Maddes' max velocity `fix' (yeah, it's physicly correct, but...). I'll
probably cvar it.
This commit is contained in:
Bill Currie 2002-02-22 05:28:17 +00:00
parent 80723fdec7
commit 96d3a997c9
7 changed files with 590 additions and 597 deletions

View file

@ -39,7 +39,7 @@ typedef struct
float dist; float dist;
} plane_t; } plane_t;
typedef struct typedef struct trace_s
{ {
qboolean allsolid; // if true, plane is not valid qboolean allsolid; // if true, plane is not valid
qboolean startsolid; // if true, the initial point was in a solid area qboolean startsolid; // if true, the initial point was in a solid area

View file

@ -253,6 +253,13 @@ void SV_AddClientToServer (struct qsocket_s *ret);
void SV_ClientPrintf (const char *fmt, ...) __attribute__((format(printf,1,2))); void SV_ClientPrintf (const char *fmt, ...) __attribute__((format(printf,1,2)));
void SV_BroadcastPrintf (const char *fmt, ...) __attribute__((format(printf,1,2))); void SV_BroadcastPrintf (const char *fmt, ...) __attribute__((format(printf,1,2)));
struct trace_s SV_PushEntity (edict_t *ent, vec3_t push);
int SV_FlyMove (edict_t *ent, float time, struct trace_s *steptrace);
void SV_CheckVelocity (edict_t *ent);
qboolean SV_RunThink (edict_t *ent);
void SV_AddGravity (edict_t *ent);
void SV_Physics_Toss (edict_t *ent);
void SV_Physics_Client (edict_t *ent, int num);
void SV_Physics (void); void SV_Physics (void);
qboolean SV_CheckBottom (edict_t *ent); qboolean SV_CheckBottom (edict_t *ent);

View file

@ -97,7 +97,7 @@ client_sources= cl_cam.c cl_cmd.c cl_demo.c cl_input.c cl_main.c cl_screen.c \
locs.c sbar.c locs.c sbar.c
server_sources= host.c host_cmd.c pr_cmds.c sv_cvar.c sv_main.c \ server_sources= host.c host_cmd.c pr_cmds.c sv_cvar.c sv_main.c \
sv_move.c sv_phys.c sv_progs.c sv_user.c sv_move.c sv_cl_phys.c sv_phys.c sv_progs.c sv_user.c
combined_sources= \ combined_sources= \
$(common_sources) $(client_sources) $(server_sources) $(common_sources) $(client_sources) $(server_sources)

376
nq/source/sv_cl_phys.c Normal file
View file

@ -0,0 +1,376 @@
/*
sv_phys.c
@description@
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
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.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
*/
static const char rcsid[] =
"$Id$";
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "QF/console.h"
#include "QF/cvar.h"
#include "QF/sys.h"
#include "host.h"
#include "server.h"
#include "sv_progs.h"
#include "world.h"
#define sv_frametime host_frametime
// CLIENT MOVEMENT ============================================================
/*
SV_CheckStuck
This is a big hack to try and fix the rare case of getting stuck in the world
clipping hull.
*/
void
SV_CheckStuck (edict_t *ent)
{
int i, j, z;
vec3_t org;
if (!SV_TestEntityPosition (ent)) {
VectorCopy (SVvector (ent, origin), SVvector (ent, oldorigin));
return;
}
VectorCopy (SVvector (ent, origin), org);
VectorCopy (SVvector (ent, oldorigin), SVvector (ent, 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++) {
SVvector (ent, origin)[0] = org[0] + i;
SVvector (ent, origin)[1] = org[1] + j;
SVvector (ent, origin)[2] = org[2] + z;
if (!SV_TestEntityPosition (ent)) {
Con_DPrintf ("Unstuck.\n");
SV_LinkEdict (ent, true);
return;
}
}
VectorCopy (org, SVvector (ent, origin));
Con_DPrintf ("player is stuck.\n");
}
qboolean
SV_CheckWater (edict_t *ent)
{
int cont;
vec3_t point;
point[0] = SVvector (ent, origin)[0];
point[1] = SVvector (ent, origin)[1];
point[2] = SVvector (ent, origin)[2] + SVvector (ent, mins)[2] + 1;
SVfloat (ent, waterlevel) = 0;
SVfloat (ent, watertype) = CONTENTS_EMPTY;
cont = SV_PointContents (point);
if (cont <= CONTENTS_WATER) {
SVfloat (ent, watertype) = cont;
SVfloat (ent, waterlevel) = 1;
point[2] = SVvector (ent, origin)[2] + (SVvector (ent, mins)[2] +
SVvector (ent, maxs)[2]) * 0.5;
cont = SV_PointContents (point);
if (cont <= CONTENTS_WATER) {
SVfloat (ent, waterlevel) = 2;
point[2] = SVvector (ent, origin)[2] + SVvector (ent, view_ofs)[2];
cont = SV_PointContents (point);
if (cont <= CONTENTS_WATER)
SVfloat (ent, waterlevel) = 3;
}
}
return SVfloat (ent, waterlevel) > 1;
}
void
SV_WallFriction (edict_t *ent, trace_t *trace)
{
float d, i;
vec3_t forward, right, up, into, side;
AngleVectors (SVvector (ent, v_angle), forward, right, up);
d = DotProduct (trace->plane.normal, forward);
d += 0.5;
if (d >= 0)
return;
// cut the tangential velocity
i = DotProduct (trace->plane.normal, SVvector (ent, velocity));
VectorScale (trace->plane.normal, i, into);
VectorSubtract (SVvector (ent, velocity), into, side);
SVvector (ent, velocity)[0] = side[0] * (1 + d);
SVvector (ent, velocity)[1] = side[1] * (1 + d);
}
/*
SV_TryUnstick
Player has come to a dead stop, possibly due to the problem with limited
float precision at some angle joins in the BSP hull.
Try fixing by pushing one pixel in each direction.
This is a hack, but in the interest of good gameplay...
*/
int
SV_TryUnstick (edict_t *ent, vec3_t oldvel)
{
int i, clip;
vec3_t dir, oldorg;
trace_t steptrace;
VectorCopy (SVvector (ent, origin), oldorg);
VectorCopy (vec3_origin, dir);
for (i = 0; i < 8; i++) {
// 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;
}
SV_PushEntity (ent, dir);
// retry the original move
SVvector (ent, velocity)[0] = oldvel[0];
SVvector (ent, velocity)[1] = oldvel[1];
SVvector (ent, velocity)[2] = 0;
clip = SV_FlyMove (ent, 0.1, &steptrace);
if (fabs (oldorg[1] - SVvector (ent, origin)[1]) > 4
|| fabs (oldorg[0] - SVvector (ent, origin)[0]) > 4) {
// Con_DPrintf ("unstuck!\n");
return clip;
}
// go back to the original pos and try again
VectorCopy (oldorg, SVvector (ent, origin));
}
VectorCopy (vec3_origin, SVvector (ent, velocity));
return 7; // still not moving
}
#define STEPSIZE 18
/*
SV_WalkMove
Only used by players
*/
void
SV_WalkMove (edict_t *ent)
{
int clip, oldonground;
vec3_t upmove, downmove, nosteporg, nostepvel, oldorg, oldvel;
trace_t steptrace, downtrace;
// do a regular slide move unless it looks like you ran into a step
oldonground = (int) SVfloat (ent, flags) & FL_ONGROUND;
SVfloat (ent, flags) = (int) SVfloat (ent, flags) & ~FL_ONGROUND;
VectorCopy (SVvector (ent, origin), oldorg);
VectorCopy (SVvector (ent, velocity), oldvel);
clip = SV_FlyMove (ent, sv_frametime, &steptrace);
if (!(clip & 2))
return; // move didn't block on a step
if (!oldonground && SVfloat (ent, waterlevel) == 0)
return; // don't stair up while jumping
if (SVfloat (ent, movetype) != MOVETYPE_WALK)
return; // gibbed by a trigger
if (sv_nostep->int_val)
return;
if ((int) SVfloat (sv_player, flags) & FL_WATERJUMP)
return;
VectorCopy (SVvector (ent, origin), nosteporg);
VectorCopy (SVvector (ent, velocity), nostepvel);
// try moving up and forward to go up a step
VectorCopy (oldorg, SVvector (ent, origin)); // back to start pos
VectorCopy (vec3_origin, upmove);
VectorCopy (vec3_origin, downmove);
upmove[2] = STEPSIZE;
downmove[2] = -STEPSIZE + oldvel[2] * sv_frametime;
// move up
SV_PushEntity (ent, upmove); // FIXME: don't link?
// move forward
SVvector (ent, velocity)[0] = oldvel[0];
SVvector (ent, velocity)[1] = oldvel[1];
SVvector (ent, 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] - SVvector (ent, origin)[1]) < 0.03125
&& fabs (oldorg[0] - SVvector (ent, 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);
// move down
downtrace = SV_PushEntity (ent, downmove); // FIXME: don't link?
if (downtrace.plane.normal[2] > 0.7) {
if (SVfloat (ent, solid) == SOLID_BSP) {
SVfloat (ent, flags) = (int) SVfloat (ent, flags) | FL_ONGROUND;
SVfloat (ent, groundentity) = EDICT_TO_PROG (&sv_pr_state,
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, SVvector (ent, origin));
VectorCopy (nostepvel, SVvector (ent, 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
*sv_globals.time = sv.time;
*sv_globals.self = EDICT_TO_PROG (&sv_pr_state, ent);
PR_ExecuteProgram (&sv_pr_state,
sv_funcs.PlayerPreThink);
// do a move
SV_CheckVelocity (ent);
// decide which move function to call
switch ((int) SVfloat (ent, movetype)) {
case MOVETYPE_NONE:
if (!SV_RunThink (ent))
return;
break;
case MOVETYPE_WALK:
if (!SV_RunThink (ent))
return;
if (!SV_CheckWater (ent) && !((int) SVfloat (ent, 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_FlyMove (ent, sv_frametime, NULL);
break;
case MOVETYPE_NOCLIP:
if (!SV_RunThink (ent))
return;
VectorMA (SVvector (ent, origin), sv_frametime, SVvector (ent, velocity),
SVvector (ent, origin));
break;
default:
Sys_Error ("SV_Physics_client: bad movetype %i",
(int) SVfloat (ent, movetype));
}
// call standard player post-think
SV_LinkEdict (ent, true);
*sv_globals.time = sv.time;
*sv_globals.self = EDICT_TO_PROG (&sv_pr_state, ent);
PR_ExecuteProgram (&sv_pr_state,
sv_funcs.PlayerPostThink);
}

View file

@ -40,6 +40,8 @@ static const char rcsid[] =
#include "sv_progs.h" #include "sv_progs.h"
#include "world.h" #include "world.h"
#define sv_frametime host_frametime
/* /*
pushmove objects do not obey gravity, and do not interact with each pushmove objects do not obey gravity, and do not interact with each
other or trigger fields, but block normal movement and push normal other or trigger fields, but block normal movement and push normal
@ -93,6 +95,9 @@ SV_CheckAllEnts (void)
void void
SV_CheckVelocity (edict_t *ent) SV_CheckVelocity (edict_t *ent)
{ {
#if 0
float wishspeed;
#endif
int i; int i;
// bound velocity // bound velocity
@ -109,11 +114,20 @@ SV_CheckVelocity (edict_t *ent)
classname))); classname)));
SVvector (ent, origin)[i] = 0; SVvector (ent, origin)[i] = 0;
} }
#if 1
if (SVvector (ent, velocity)[i] > sv_maxvelocity->value) if (SVvector (ent, velocity)[i] > sv_maxvelocity->value)
SVvector (ent, velocity)[i] = sv_maxvelocity->value; SVvector (ent, velocity)[i] = sv_maxvelocity->value;
else if (SVvector (ent, velocity)[i] < -sv_maxvelocity->value) else if (SVvector (ent, velocity)[i] < -sv_maxvelocity->value)
SVvector (ent, velocity)[i] = -sv_maxvelocity->value; SVvector (ent, velocity)[i] = -sv_maxvelocity->value;
#endif
} }
#if 0
wishspeed = Length (SVvector (ent, velocity));
if (wishspeed > sv_maxvelocity->value) {
VectorScale (SVvector (ent, velocity), sv_maxvelocity->value /
wishspeed, SVvector (ent, velocity));
}
#endif
} }
/* /*
@ -129,20 +143,26 @@ SV_RunThink (edict_t *ent)
{ {
float thinktime; float thinktime;
thinktime = SVfloat (ent, nextthink); do {
if (thinktime <= 0 || thinktime > sv.time + host_frametime) thinktime = SVfloat (ent, nextthink);
return true; if (thinktime <= 0 || thinktime > sv.time + sv_frametime)
return true;
if (thinktime < sv.time) if (thinktime < sv.time)
thinktime = sv.time; // don't let things stay in the past. thinktime = sv.time; // don't let things stay in the past.
// it is possible to start that way // it is possible to start that way
// by a trigger with a local time. // by a trigger with a local time.
SVfloat (ent, nextthink) = 0; SVfloat (ent, nextthink) = 0;
*sv_globals.time = thinktime; *sv_globals.time = thinktime;
*sv_globals.self = EDICT_TO_PROG (&sv_pr_state, ent); *sv_globals.self = EDICT_TO_PROG (&sv_pr_state, ent);
*sv_globals.other = EDICT_TO_PROG (&sv_pr_state, sv.edicts); *sv_globals.other = EDICT_TO_PROG (&sv_pr_state, sv.edicts);
PR_ExecuteProgram (&sv_pr_state, SVfunc (ent, think)); PR_ExecuteProgram (&sv_pr_state, SVfunc (ent, think));
return !ent->free;
if (ent->free)
return false;
} while (0);
return true;
} }
/* /*
@ -343,7 +363,7 @@ SV_AddGravity (edict_t *ent)
ent_gravity = val->float_var; ent_gravity = val->float_var;
else else
ent_gravity = 1.0; ent_gravity = 1.0;
SVvector (ent, velocity)[2] -= ent_gravity * sv_gravity->value * host_frametime; SVvector (ent, velocity)[2] -= ent_gravity * sv_gravity->value * sv_frametime;
} }
/* PUSHMOVE */ /* PUSHMOVE */
@ -382,32 +402,24 @@ SV_PushEntity (edict_t *ent, vec3_t push)
return trace; return trace;
} }
void qboolean
SV_PushMove (edict_t *pusher, float movetime) SV_Push (edict_t *pusher, vec3_t move)
{ {
int i, e, num_moved; float solid_save;
int num_moved, i, e;
edict_t *check, *block; edict_t *check, *block;
edict_t *moved_edict[MAX_EDICTS]; edict_t *moved_edict[MAX_EDICTS];
vec3_t entorig, pushorig, mins, maxs, move; vec3_t entorig;
vec3_t mins, maxs, pushorig;
vec3_t moved_from[MAX_EDICTS]; vec3_t moved_from[MAX_EDICTS];
if (!SVvector (pusher, velocity)[0] && !SVvector (pusher, velocity)[1] VectorAdd (SVvector (pusher, absmin), move, mins);
&& !SVvector (pusher, velocity)[2]) { VectorAdd (SVvector (pusher, absmax), move, maxs);
SVfloat (pusher, ltime) += movetime;
return;
}
for (i = 0; i < 3; i++) {
move[i] = SVvector (pusher, velocity)[i] * movetime;
mins[i] = SVvector (pusher, absmin)[i] + move[i];
maxs[i] = SVvector (pusher, absmax)[i] + move[i];
}
VectorCopy (SVvector (pusher, origin), pushorig); VectorCopy (SVvector (pusher, origin), pushorig);
// move the pusher to it's final position // move the pusher to it's final position
VectorAdd (SVvector (pusher, origin), move, SVvector (pusher, origin)); VectorAdd (SVvector (pusher, origin), move, SVvector (pusher, origin));
SVfloat (pusher, ltime) += movetime;
SV_LinkEdict (pusher, false); SV_LinkEdict (pusher, false);
// see if any solid entities are inside the final position // see if any solid entities are inside the final position
@ -426,6 +438,7 @@ SV_PushMove (edict_t *pusher, float movetime)
if (!(((int) SVfloat (check, flags) & FL_ONGROUND) if (!(((int) SVfloat (check, flags) & FL_ONGROUND)
&& PROG_TO_EDICT (&sv_pr_state, && PROG_TO_EDICT (&sv_pr_state,
SVentity (check, groundentity)) == pusher)) { SVentity (check, groundentity)) == pusher)) {
// check is NOT standing on pusher
if (SVvector (check, absmin)[0] >= maxs[0] if (SVvector (check, absmin)[0] >= maxs[0]
|| SVvector (check, absmin)[1] >= maxs[1] || SVvector (check, absmin)[1] >= maxs[1]
|| SVvector (check, absmin)[2] >= maxs[2] || SVvector (check, absmin)[2] >= maxs[2]
@ -448,49 +461,64 @@ SV_PushMove (edict_t *pusher, float movetime)
moved_edict[num_moved] = check; moved_edict[num_moved] = check;
num_moved++; num_moved++;
// try moving the contacted entity // try moving the contacted entity
solid_save = SVfloat (pusher, solid);
SVfloat (pusher, solid) = SOLID_NOT; SVfloat (pusher, solid) = SOLID_NOT;
SV_PushEntity (check, move); SV_PushEntity (check, move);
SVfloat (pusher, solid) = SOLID_BSP; SVfloat (pusher, solid) = solid_save;
// if it is still inside the pusher, block
block = SV_TestEntityPosition (check); block = SV_TestEntityPosition (check);
if (block) { // fail the move if (!block) {
if (SVvector (check, mins)[0] == SVvector (check, maxs)[0]) continue;
continue;
if (SVfloat (check, solid) == SOLID_NOT || SVfloat (check, solid)
== SOLID_TRIGGER) { // corpse
SVvector (check, mins)[0] = SVvector (check, mins)[1] = 0;
VectorCopy (SVvector (check, mins), SVvector (check, maxs));
continue;
}
VectorCopy (entorig, SVvector (check, origin));
SV_LinkEdict (check, true);
VectorCopy (pushorig, SVvector (pusher, origin));
SV_LinkEdict (pusher, false);
SVfloat (pusher, ltime) -= movetime;
// if the pusher has a "blocked" function, call it
// otherwise, just stay in place until the obstacle is gone
if (SVfunc (pusher, blocked)) {
*sv_globals.self =
EDICT_TO_PROG (&sv_pr_state, pusher);
*sv_globals.other =
EDICT_TO_PROG (&sv_pr_state, check);
PR_ExecuteProgram (&sv_pr_state, SVfunc (pusher, blocked));
}
// move back any entities we already moved
for (i = 0; i < num_moved; i++) {
VectorCopy (moved_from[i], SVvector (moved_edict[i], origin));
SV_LinkEdict (moved_edict[i], false);
}
return;
} }
// if it is still inside the pusher, block
if (SVvector (check, mins)[0] == SVvector (check, maxs)[0]) {
continue;
}
if (SVfloat (check, solid) == SOLID_NOT
|| SVfloat (check, solid) == SOLID_TRIGGER) { // corpse
SVvector (check, mins)[0] = SVvector (check, mins)[1] = 0;
VectorCopy (SVvector (check, mins), SVvector (check, maxs));
continue;
}
VectorCopy (entorig, SVvector (check, origin));
SV_LinkEdict (check, true);
VectorCopy (pushorig, SVvector (pusher, origin));
SV_LinkEdict (pusher, false);
// if the pusher has a "blocked" function, call it
// otherwise, just stay in place until the obstacle is gone
if (SVfunc (pusher, blocked)) {
*sv_globals.self = EDICT_TO_PROG (&sv_pr_state, pusher);
*sv_globals.other = EDICT_TO_PROG (&sv_pr_state, check);
PR_ExecuteProgram (&sv_pr_state, SVfunc (pusher, blocked));
}
// move back any entities we already moved
for (i = 0; i < num_moved; i++) {
VectorCopy (moved_from[i], SVvector (moved_edict[i], origin));
SV_LinkEdict (moved_edict[i], false);
}
return false;
}
return true;
}
void
SV_PushMove (edict_t *pusher, float movetime)
{
vec3_t move;
if (VectorIsZero (SVvector (pusher, velocity))) {
SVfloat (pusher, ltime) += movetime;
return;
} }
VectorScale (SVvector (pusher, velocity), movetime, move);
if (SV_Push (pusher, move))
SVfloat (pusher, ltime) += movetime;
} }
void void
@ -501,12 +529,12 @@ SV_Physics_Pusher (edict_t *ent)
oldltime = SVfloat (ent, ltime); oldltime = SVfloat (ent, ltime);
thinktime = SVfloat (ent, nextthink); thinktime = SVfloat (ent, nextthink);
if (thinktime < SVfloat (ent, ltime) + host_frametime) { if (thinktime < SVfloat (ent, ltime) + sv_frametime) {
movetime = thinktime - SVfloat (ent, ltime); movetime = thinktime - SVfloat (ent, ltime);
if (movetime < 0) if (movetime < 0)
movetime = 0; movetime = 0;
} else } else
movetime = host_frametime; movetime = sv_frametime;
if (movetime) { if (movetime) {
SV_PushMove (ent, movetime); // advances SVfloat (ent, ltime) if not SV_PushMove (ent, movetime); // advances SVfloat (ent, ltime) if not
@ -525,338 +553,6 @@ SV_Physics_Pusher (edict_t *ent)
} }
// CLIENT MOVEMENT ============================================================
/*
SV_CheckStuck
This is a big hack to try and fix the rare case of getting stuck in the world
clipping hull.
*/
void
SV_CheckStuck (edict_t *ent)
{
int i, j, z;
vec3_t org;
if (!SV_TestEntityPosition (ent)) {
VectorCopy (SVvector (ent, origin), SVvector (ent, oldorigin));
return;
}
VectorCopy (SVvector (ent, origin), org);
VectorCopy (SVvector (ent, oldorigin), SVvector (ent, 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++) {
SVvector (ent, origin)[0] = org[0] + i;
SVvector (ent, origin)[1] = org[1] + j;
SVvector (ent, origin)[2] = org[2] + z;
if (!SV_TestEntityPosition (ent)) {
Con_DPrintf ("Unstuck.\n");
SV_LinkEdict (ent, true);
return;
}
}
VectorCopy (org, SVvector (ent, origin));
Con_DPrintf ("player is stuck.\n");
}
qboolean
SV_CheckWater (edict_t *ent)
{
int cont;
vec3_t point;
point[0] = SVvector (ent, origin)[0];
point[1] = SVvector (ent, origin)[1];
point[2] = SVvector (ent, origin)[2] + SVvector (ent, mins)[2] + 1;
SVfloat (ent, waterlevel) = 0;
SVfloat (ent, watertype) = CONTENTS_EMPTY;
cont = SV_PointContents (point);
if (cont <= CONTENTS_WATER) {
SVfloat (ent, watertype) = cont;
SVfloat (ent, waterlevel) = 1;
point[2] = SVvector (ent, origin)[2] + (SVvector (ent, mins)[2] +
SVvector (ent, maxs)[2]) * 0.5;
cont = SV_PointContents (point);
if (cont <= CONTENTS_WATER) {
SVfloat (ent, waterlevel) = 2;
point[2] = SVvector (ent, origin)[2] + SVvector (ent, view_ofs)[2];
cont = SV_PointContents (point);
if (cont <= CONTENTS_WATER)
SVfloat (ent, waterlevel) = 3;
}
}
return SVfloat (ent, waterlevel) > 1;
}
void
SV_WallFriction (edict_t *ent, trace_t *trace)
{
float d, i;
vec3_t forward, right, up, into, side;
AngleVectors (SVvector (ent, v_angle), forward, right, up);
d = DotProduct (trace->plane.normal, forward);
d += 0.5;
if (d >= 0)
return;
// cut the tangential velocity
i = DotProduct (trace->plane.normal, SVvector (ent, velocity));
VectorScale (trace->plane.normal, i, into);
VectorSubtract (SVvector (ent, velocity), into, side);
SVvector (ent, velocity)[0] = side[0] * (1 + d);
SVvector (ent, velocity)[1] = side[1] * (1 + d);
}
/*
SV_TryUnstick
Player has come to a dead stop, possibly due to the problem with limited
float precision at some angle joins in the BSP hull.
Try fixing by pushing one pixel in each direction.
This is a hack, but in the interest of good gameplay...
*/
int
SV_TryUnstick (edict_t *ent, vec3_t oldvel)
{
int i, clip;
vec3_t dir, oldorg;
trace_t steptrace;
VectorCopy (SVvector (ent, origin), oldorg);
VectorCopy (vec3_origin, dir);
for (i = 0; i < 8; i++) {
// 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;
}
SV_PushEntity (ent, dir);
// retry the original move
SVvector (ent, velocity)[0] = oldvel[0];
SVvector (ent, velocity)[1] = oldvel[1];
SVvector (ent, velocity)[2] = 0;
clip = SV_FlyMove (ent, 0.1, &steptrace);
if (fabs (oldorg[1] - SVvector (ent, origin)[1]) > 4
|| fabs (oldorg[0] - SVvector (ent, origin)[0]) > 4) {
// Con_DPrintf ("unstuck!\n");
return clip;
}
// go back to the original pos and try again
VectorCopy (oldorg, SVvector (ent, origin));
}
VectorCopy (vec3_origin, SVvector (ent, velocity));
return 7; // still not moving
}
#define STEPSIZE 18
/*
SV_WalkMove
Only used by players
*/
void
SV_WalkMove (edict_t *ent)
{
int clip, oldonground;
vec3_t upmove, downmove, nosteporg, nostepvel, oldorg, oldvel;
trace_t steptrace, downtrace;
// do a regular slide move unless it looks like you ran into a step
oldonground = (int) SVfloat (ent, flags) & FL_ONGROUND;
SVfloat (ent, flags) = (int) SVfloat (ent, flags) & ~FL_ONGROUND;
VectorCopy (SVvector (ent, origin), oldorg);
VectorCopy (SVvector (ent, velocity), oldvel);
clip = SV_FlyMove (ent, host_frametime, &steptrace);
if (!(clip & 2))
return; // move didn't block on a step
if (!oldonground && SVfloat (ent, waterlevel) == 0)
return; // don't stair up while jumping
if (SVfloat (ent, movetype) != MOVETYPE_WALK)
return; // gibbed by a trigger
if (sv_nostep->int_val)
return;
if ((int) SVfloat (sv_player, flags) & FL_WATERJUMP)
return;
VectorCopy (SVvector (ent, origin), nosteporg);
VectorCopy (SVvector (ent, velocity), nostepvel);
// try moving up and forward to go up a step
VectorCopy (oldorg, SVvector (ent, origin)); // back to start pos
VectorCopy (vec3_origin, upmove);
VectorCopy (vec3_origin, downmove);
upmove[2] = STEPSIZE;
downmove[2] = -STEPSIZE + oldvel[2] * host_frametime;
// move up
SV_PushEntity (ent, upmove); // FIXME: don't link?
// move forward
SVvector (ent, velocity)[0] = oldvel[0];
SVvector (ent, velocity)[1] = oldvel[1];
SVvector (ent, velocity)[2] = 0;
clip = SV_FlyMove (ent, host_frametime, &steptrace);
// check for stuckness, possibly due to the limited precision of floats
// in the clipping hulls
if (clip) {
if (fabs (oldorg[1] - SVvector (ent, origin)[1]) < 0.03125
&& fabs (oldorg[0] - SVvector (ent, 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);
// move down
downtrace = SV_PushEntity (ent, downmove); // FIXME: don't link?
if (downtrace.plane.normal[2] > 0.7) {
if (SVfloat (ent, solid) == SOLID_BSP) {
SVfloat (ent, flags) = (int) SVfloat (ent, flags) | FL_ONGROUND;
SVfloat (ent, groundentity) = EDICT_TO_PROG (&sv_pr_state,
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, SVvector (ent, origin));
VectorCopy (nostepvel, SVvector (ent, 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
*sv_globals.time = sv.time;
*sv_globals.self = EDICT_TO_PROG (&sv_pr_state, ent);
PR_ExecuteProgram (&sv_pr_state,
sv_funcs.PlayerPreThink);
// do a move
SV_CheckVelocity (ent);
// decide which move function to call
switch ((int) SVfloat (ent, movetype)) {
case MOVETYPE_NONE:
if (!SV_RunThink (ent))
return;
break;
case MOVETYPE_WALK:
if (!SV_RunThink (ent))
return;
if (!SV_CheckWater (ent) && !((int) SVfloat (ent, 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_FlyMove (ent, host_frametime, NULL);
break;
case MOVETYPE_NOCLIP:
if (!SV_RunThink (ent))
return;
VectorMA (SVvector (ent, origin), host_frametime, SVvector (ent, velocity),
SVvector (ent, origin));
break;
default:
Sys_Error ("SV_Physics_client: bad movetype %i",
(int) SVfloat (ent, movetype));
}
// call standard player post-think
SV_LinkEdict (ent, true);
*sv_globals.time = sv.time;
*sv_globals.self = EDICT_TO_PROG (&sv_pr_state, ent);
PR_ExecuteProgram (&sv_pr_state,
sv_funcs.PlayerPostThink);
}
/* /*
SV_Physics_None SV_Physics_None
@ -882,9 +578,9 @@ SV_Physics_Noclip (edict_t *ent)
if (!SV_RunThink (ent)) if (!SV_RunThink (ent))
return; return;
VectorMA (SVvector (ent, angles), host_frametime, VectorMA (SVvector (ent, angles), sv_frametime,
SVvector (ent, avelocity), SVvector (ent, angles)); SVvector (ent, avelocity), SVvector (ent, angles));
VectorMA (SVvector (ent, origin), host_frametime, SVvector (ent, velocity), VectorMA (SVvector (ent, origin), sv_frametime, SVvector (ent, velocity),
SVvector (ent, origin)); SVvector (ent, origin));
SV_LinkEdict (ent, false); SV_LinkEdict (ent, false);
@ -950,11 +646,11 @@ SV_Physics_Toss (edict_t *ent)
SV_AddGravity (ent); SV_AddGravity (ent);
// move angles // move angles
VectorMA (SVvector (ent, angles), host_frametime, VectorMA (SVvector (ent, angles), sv_frametime,
SVvector (ent, avelocity), SVvector (ent, angles)); SVvector (ent, avelocity), SVvector (ent, angles));
// move origin // move origin
VectorScale (SVvector (ent, velocity), host_frametime, move); VectorScale (SVvector (ent, velocity), sv_frametime, move);
trace = SV_PushEntity (ent, move); trace = SV_PushEntity (ent, move);
if (trace.fraction == 1) if (trace.fraction == 1)
return; return;
@ -1009,7 +705,7 @@ SV_Physics_Step (edict_t *ent)
SV_AddGravity (ent); SV_AddGravity (ent);
SV_CheckVelocity (ent); SV_CheckVelocity (ent);
SV_FlyMove (ent, host_frametime, NULL); SV_FlyMove (ent, sv_frametime, NULL);
SV_LinkEdict (ent, true); SV_LinkEdict (ent, true);
if ((int) SVfloat (ent, flags) & FL_ONGROUND) // just hit ground if ((int) SVfloat (ent, flags) & FL_ONGROUND) // just hit ground
@ -1025,22 +721,53 @@ SV_Physics_Step (edict_t *ent)
} }
void void
SV_Physics (void) SV_ProgStartFrame (void)
{ {
int i;
edict_t *ent;
// let the progs know that a new frame has started // let the progs know that a new frame has started
*sv_globals.self = *sv_globals.self = EDICT_TO_PROG (&sv_pr_state, sv.edicts);
EDICT_TO_PROG (&sv_pr_state, sv.edicts); *sv_globals.other = EDICT_TO_PROG (&sv_pr_state, sv.edicts);
*sv_globals.other =
EDICT_TO_PROG (&sv_pr_state, sv.edicts);
*sv_globals.time = sv.time; *sv_globals.time = sv.time;
PR_ExecuteProgram (&sv_pr_state, sv_funcs.StartFrame); PR_ExecuteProgram (&sv_pr_state, sv_funcs.StartFrame);
}
// SV_CheckAllEnts (); void
SV_RunEntity (edict_t *ent)
{
switch ((int) SVfloat (ent, movetype)) {
case MOVETYPE_PUSH:
SV_Physics_Pusher (ent);
break;
case MOVETYPE_NONE:
SV_Physics_None (ent);
break;
case MOVETYPE_NOCLIP:
SV_Physics_Noclip (ent);
break;
case MOVETYPE_STEP:
SV_Physics_Step (ent);
break;
case MOVETYPE_TOSS:
case MOVETYPE_BOUNCE:
case MOVETYPE_FLY:
case MOVETYPE_FLYMISSILE:
SV_Physics_Toss (ent);
break;
default:
Sys_Error ("SV_Physics: bad movetype %i",
(int) SVfloat (ent, movetype));
}
}
void
SV_Physics (void)
{
edict_t *ent;
int i;
SV_ProgStartFrame ();
// treat each object in turn // treat each object in turn
// even the world gets a chance to think
ent = sv.edicts; ent = sv.edicts;
for (i = 0; i < sv.num_edicts; i++, ent = NEXT_EDICT (&sv_pr_state, ent)) { for (i = 0; i < sv.num_edicts; i++, ent = NEXT_EDICT (&sv_pr_state, ent)) {
if (ent->free) if (ent->free)
@ -1050,28 +777,15 @@ SV_Physics (void)
SV_LinkEdict (ent, true); // force retouch even for stationary SV_LinkEdict (ent, true); // force retouch even for stationary
} }
if (i > 0 && i <= svs.maxclients) if (i > 0 && i <= svs.maxclients) {
SV_Physics_Client (ent, i); SV_Physics_Client (ent, i);
else if (SVfloat (ent, movetype) == MOVETYPE_PUSH) continue;
SV_Physics_Pusher (ent); }
else if (SVfloat (ent, movetype) == MOVETYPE_NONE) SV_RunEntity (ent);
SV_Physics_None (ent);
else if (SVfloat (ent, movetype) == MOVETYPE_NOCLIP)
SV_Physics_Noclip (ent);
else if (SVfloat (ent, movetype) == MOVETYPE_STEP)
SV_Physics_Step (ent);
else if (SVfloat (ent, movetype) == MOVETYPE_TOSS
|| SVfloat (ent, movetype) == MOVETYPE_BOUNCE
|| SVfloat (ent, movetype) == MOVETYPE_FLY
|| SVfloat (ent, movetype) == MOVETYPE_FLYMISSILE)
SV_Physics_Toss (ent);
else
Sys_Error ("SV_Physics: bad movetype %i",
(int) SVfloat (ent, movetype));
} }
if (*sv_globals.force_retouch) if (*sv_globals.force_retouch)
(*sv_globals.force_retouch)--; (*sv_globals.force_retouch)--;
sv.time += host_frametime; sv.time += sv_frametime;
} }

View file

@ -483,7 +483,7 @@ void SV_FlushSignon (void);
void SV_ProgStartFrame (void); void SV_ProgStartFrame (void);
void SV_Physics (void); void SV_Physics (void);
void SV_CheckVelocity (struct edict_s *ent); void SV_CheckVelocity (struct edict_s *ent);
void SV_AddGravity (struct edict_s *ent, float scale); void SV_AddGravity (struct edict_s *ent);
qboolean SV_RunThink (struct edict_s *ent); qboolean SV_RunThink (struct edict_s *ent);
void SV_Physics_Toss (struct edict_s *ent); void SV_Physics_Toss (struct edict_s *ent);
void SV_RunNewmis (void); void SV_RunNewmis (void);

View file

@ -31,6 +31,7 @@ static const char rcsid[] =
# include "config.h" # include "config.h"
#endif #endif
#include "QF/console.h"
#include "QF/cvar.h" #include "QF/cvar.h"
#include "QF/sys.h" #include "QF/sys.h"
@ -90,39 +91,46 @@ SV_CheckAllEnts (void)
continue; continue;
if (SV_TestEntityPosition (check)) if (SV_TestEntityPosition (check))
SV_Printf ("entity in invalid position\n"); Con_Printf ("entity in invalid position\n");
} }
} }
void void
SV_CheckVelocity (edict_t *ent) SV_CheckVelocity (edict_t *ent)
{ {
float wishspeed; // 1999-10-18 SV_MAXVELOCITY fix by Maddes #if 0
float wishspeed;
#endif
int i; int i;
// bound velocity // bound velocity
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
if (IS_NAN (SVvector (ent, velocity)[i])) { if (IS_NAN (SVvector (ent, velocity)[i])) {
SV_Printf ("Got a NaN velocity on %s\n", Con_Printf ("Got a NaN velocity on %s\n",
PR_GetString (&sv_pr_state, SVstring (ent, PR_GetString (&sv_pr_state, SVstring (ent,
classname))); classname)));
SVvector (ent, velocity)[i] = 0; SVvector (ent, velocity)[i] = 0;
} }
if (IS_NAN (SVvector (ent, origin)[i])) { if (IS_NAN (SVvector (ent, origin)[i])) {
SV_Printf ("Got a NaN origin on %s\n", Con_Printf ("Got a NaN origin on %s\n",
PR_GetString (&sv_pr_state, SVstring (ent, PR_GetString (&sv_pr_state, SVstring (ent,
classname))); classname)));
SVvector (ent, origin)[i] = 0; SVvector (ent, origin)[i] = 0;
} }
#if 1
if (SVvector (ent, velocity)[i] > sv_maxvelocity->value)
SVvector (ent, velocity)[i] = sv_maxvelocity->value;
else if (SVvector (ent, velocity)[i] < -sv_maxvelocity->value)
SVvector (ent, velocity)[i] = -sv_maxvelocity->value;
#endif
} }
#if 0
// 1999-10-18 SV_MAXVELOCITY fix by Maddes start
wishspeed = Length (SVvector (ent, velocity)); wishspeed = Length (SVvector (ent, velocity));
if (wishspeed > sv_maxvelocity->value) { if (wishspeed > sv_maxvelocity->value) {
VectorScale (SVvector (ent, velocity), sv_maxvelocity->value / VectorScale (SVvector (ent, velocity), sv_maxvelocity->value /
wishspeed, SVvector (ent, velocity)); wishspeed, SVvector (ent, velocity));
} }
// 1999-10-18 SV_MAXVELOCITY fix by Maddes end #endif
} }
/* /*
@ -277,8 +285,7 @@ SV_FlyMove (edict_t *ent, float time, trace_t *steptrace)
if (trace.plane.normal[2] > 0.7) { if (trace.plane.normal[2] > 0.7) {
blocked |= 1; // floor blocked |= 1; // floor
if ((SVfloat (trace.ent, solid) == SOLID_BSP) if (SVfloat (trace.ent, solid) == SOLID_BSP) {
|| (SVfloat (trace.ent, movetype) == MOVETYPE_PPUSH)) {
SVfloat (ent, flags) = (int) SVfloat (ent, flags) | SVfloat (ent, flags) = (int) SVfloat (ent, flags) |
FL_ONGROUND; FL_ONGROUND;
SVentity (ent, groundentity) = EDICT_TO_PROG (&sv_pr_state, SVentity (ent, groundentity) = EDICT_TO_PROG (&sv_pr_state,
@ -343,9 +350,9 @@ SV_FlyMove (edict_t *ent, float time, trace_t *steptrace)
} }
void void
SV_AddGravity (edict_t *ent, float scale) SV_AddGravity (edict_t *ent)
{ {
SVvector (ent, velocity)[2] -= scale * movevars.gravity * sv_frametime; SVvector (ent, velocity)[2] -= movevars.gravity * sv_frametime;
} }
/* PUSHMOVE */ /* PUSHMOVE */
@ -387,17 +394,15 @@ SV_PushEntity (edict_t *ent, vec3_t push)
qboolean qboolean
SV_Push (edict_t *pusher, vec3_t move) SV_Push (edict_t *pusher, vec3_t move)
{ {
float solid_save; // for Lord Havoc's SOLID_BSP fix --KB float solid_save;
int num_moved, i, e; int num_moved, i, e;
edict_t *check, *block; edict_t *check, *block;
edict_t *moved_edict[MAX_EDICTS]; edict_t *moved_edict[MAX_EDICTS];
vec3_t mins, maxs, pushorig; vec3_t mins, maxs, pushorig;
vec3_t moved_from[MAX_EDICTS]; vec3_t moved_from[MAX_EDICTS];
for (i = 0; i < 3; i++) { VectorAdd (SVvector (pusher, absmin), move, mins);
mins[i] = SVvector (pusher, absmin)[i] + move[i]; VectorAdd (SVvector (pusher, absmax), move, maxs);
maxs[i] = SVvector (pusher, absmax)[i] + move[i];
}
VectorCopy (SVvector (pusher, origin), pushorig); VectorCopy (SVvector (pusher, origin), pushorig);
@ -408,28 +413,27 @@ SV_Push (edict_t *pusher, vec3_t move)
// see if any solid entities are inside the final position // see if any solid entities are inside the final position
num_moved = 0; num_moved = 0;
check = NEXT_EDICT (&sv_pr_state, sv.edicts); check = NEXT_EDICT (&sv_pr_state, sv.edicts);
for (e = 1; e < sv.num_edicts; e++, check = NEXT_EDICT (&sv_pr_state, for (e = 1; e < sv.num_edicts;
check)) { e++, check = NEXT_EDICT (&sv_pr_state, check)) {
if (check->free) if (check->free)
continue; continue;
if (SVfloat (check, movetype) == MOVETYPE_PUSH if (SVfloat (check, movetype) == MOVETYPE_PUSH
|| SVfloat (check, movetype) == MOVETYPE_NONE || SVfloat (check, movetype) == MOVETYPE_NONE
|| SVfloat (check, movetype) == MOVETYPE_PPUSH || SVfloat (check, movetype) == MOVETYPE_NOCLIP)
|| SVfloat (check, movetype) == MOVETYPE_NOCLIP) continue; continue;
// Don't assume SOLID_BSP ! --KB
solid_save = SVfloat (pusher, solid); solid_save = SVfloat (pusher, solid);
SVfloat (pusher, solid) = SOLID_NOT; SVfloat (pusher, solid) = SOLID_NOT;
block = SV_TestEntityPosition (check); block = SV_TestEntityPosition (check);
// SVfloat (pusher, solid) = SOLID_BSP;
SVfloat (pusher, solid) = solid_save; SVfloat (pusher, solid) = solid_save;
if (block) if (block)
continue; continue;
// if the entity is standing on the pusher, it will definately be moved // if the entity is standing on the pusher, it will definately be moved
if (!(((int) SVfloat (check, flags) & FL_ONGROUND) if (!(((int) SVfloat (check, flags) & FL_ONGROUND)
&& PROG_TO_EDICT (&sv_pr_state, SVentity (check, groundentity)) && PROG_TO_EDICT (&sv_pr_state,
== pusher)) { SVentity (check, groundentity)) == pusher)) {
// check is NOT standing on pusher
if (SVvector (check, absmin)[0] >= maxs[0] if (SVvector (check, absmin)[0] >= maxs[0]
|| SVvector (check, absmin)[1] >= maxs[1] || SVvector (check, absmin)[1] >= maxs[1]
|| SVvector (check, absmin)[2] >= maxs[2] || SVvector (check, absmin)[2] >= maxs[2]
@ -455,8 +459,8 @@ SV_Push (edict_t *pusher, vec3_t move)
continue; continue;
} }
// if it is ok to leave in the old position, do it // if it is ok to leave in the old position, do it
VectorSubtract (SVvector (check, origin), move, SVvector (check, VectorSubtract (SVvector (check, origin), move,
origin)); SVvector (check, origin));
block = SV_TestEntityPosition (check); block = SV_TestEntityPosition (check);
if (!block) { if (!block) {
num_moved--; num_moved--;
@ -467,8 +471,8 @@ SV_Push (edict_t *pusher, vec3_t move)
SV_LinkEdict (check, false); SV_LinkEdict (check, false);
continue; continue;
} }
if (SVfloat (check, solid) == SOLID_NOT || SVfloat (check, solid) == if (SVfloat (check, solid) == SOLID_NOT
SOLID_TRIGGER) { // corpse || SVfloat (check, solid) == SOLID_TRIGGER) { // corpse
SVvector (check, mins)[0] = SVvector (check, mins)[1] = 0; SVvector (check, mins)[0] = SVvector (check, mins)[1] = 0;
VectorCopy (SVvector (check, mins), SVvector (check, maxs)); VectorCopy (SVvector (check, mins), SVvector (check, maxs));
SV_LinkEdict (check, false); SV_LinkEdict (check, false);
@ -492,14 +496,12 @@ SV_Push (edict_t *pusher, vec3_t move)
} }
return false; return false;
} }
return true; return true;
} }
void void
SV_PushMove (edict_t *pusher, float movetime) SV_PushMove (edict_t *pusher, float movetime)
{ {
int i;
vec3_t move; vec3_t move;
if (VectorIsZero (SVvector (pusher, velocity))) { if (VectorIsZero (SVvector (pusher, velocity))) {
@ -507,8 +509,7 @@ SV_PushMove (edict_t *pusher, float movetime)
return; return;
} }
for (i = 0; i < 3; i++) VectorScale (SVvector (pusher, velocity), movetime, move);
move[i] = SVvector (pusher, velocity)[i] * movetime;
if (SV_Push (pusher, move)) if (SV_Push (pusher, move))
SVfloat (pusher, ltime) += movetime; SVfloat (pusher, ltime) += movetime;
@ -517,7 +518,8 @@ SV_PushMove (edict_t *pusher, float movetime)
void void
SV_Physics_Pusher (edict_t *ent) SV_Physics_Pusher (edict_t *ent)
{ {
float movetime, oldltime, thinktime, l; float movetime, oldltime, thinktime;
float l;
vec3_t oldorg, move; vec3_t oldorg, move;
oldltime = SVfloat (ent, ltime); oldltime = SVfloat (ent, ltime);
@ -548,7 +550,7 @@ SV_Physics_Pusher (edict_t *ent)
l = Length (move); l = Length (move);
if (l > 1.0 / 64) { if (l > 1.0 / 64) {
// SV_Printf ("**** snap: %f\n", Length (l)); // Con_Printf ("**** snap: %f\n", Length (l));
VectorCopy (oldorg, SVvector (ent, origin)); VectorCopy (oldorg, SVvector (ent, origin));
SV_Push (ent, move); SV_Push (ent, move);
} }
@ -648,7 +650,7 @@ SV_Physics_Toss (edict_t *ent)
// add gravity // add gravity
if (SVfloat (ent, movetype) != MOVETYPE_FLY if (SVfloat (ent, movetype) != MOVETYPE_FLY
&& SVfloat (ent, movetype) != MOVETYPE_FLYMISSILE) && SVfloat (ent, movetype) != MOVETYPE_FLYMISSILE)
SV_AddGravity (ent, 1.0); SV_AddGravity (ent);
// move angles // move angles
VectorMA (SVvector (ent, angles), sv_frametime, VectorMA (SVvector (ent, angles), sv_frametime,
@ -709,7 +711,7 @@ SV_Physics_Step (edict_t *ent)
else else
hitsound = false; hitsound = false;
SV_AddGravity (ent, 1.0); SV_AddGravity (ent);
SV_CheckVelocity (ent); SV_CheckVelocity (ent);
SV_FlyMove (ent, sv_frametime, NULL); SV_FlyMove (ent, sv_frametime, NULL);
SV_LinkEdict (ent, true); SV_LinkEdict (ent, true);
@ -726,110 +728,6 @@ SV_Physics_Step (edict_t *ent)
SV_CheckWaterTransition (ent); SV_CheckWaterTransition (ent);
} }
void
SV_PPushMove (edict_t *pusher, float movetime) // player push
{
int oldsolid, e, i;
edict_t *check;
trace_t trace;
vec3_t maxs, mins, move;
SV_CheckVelocity (pusher);
for (i = 0; i < 3; i++) {
move[i] = SVvector (pusher, velocity)[i] * movetime;
mins[i] = SVvector (pusher, absmin)[i] + move[i];
maxs[i] = SVvector (pusher, absmax)[i] + move[i];
}
VectorCopy (SVvector (pusher, origin), SVvector (pusher, oldorigin)); // Backup origin
trace =
SV_Move (SVvector (pusher, origin), SVvector (pusher, mins), SVvector (pusher, maxs), move,
MOVE_NOMONSTERS, pusher);
if (trace.fraction == 1) {
VectorCopy (SVvector (pusher, origin), SVvector (pusher, oldorigin));
// Revert
return;
}
VectorAdd (SVvector (pusher, origin), move, SVvector (pusher, origin));
// Move
SV_LinkEdict (pusher, false);
SVfloat (pusher, ltime) += movetime;
oldsolid = SVfloat (pusher, solid);
check = NEXT_EDICT (&sv_pr_state, sv.edicts);
for (e = 1; e < sv.num_edicts; e++, check = NEXT_EDICT (&sv_pr_state,
check)) {
if (check->free) // What entity?
continue;
// Stage 1: Is it in contact with me?
if (!SV_TestEntityPosition (check)) // Nope
continue;
// Stage 2: Is it a player we can push?
if (SVfloat (check, movetype) == MOVETYPE_WALK) {
SV_Printf ("Pusher encountered a player\n"); // Yes!@#!@
SVfloat (pusher, solid) = SOLID_NOT;
SV_PushEntity (check, move);
SVfloat (pusher, solid) = oldsolid;
continue;
}
// Stage 3: No.. Is it something that blocks us?
if (SVvector (check, mins)[0] == SVvector (check, maxs)[0])
continue;
if (SVfloat (check, solid) == SOLID_NOT || SVfloat (check, solid) ==
SOLID_TRIGGER)
continue;
// Stage 4: Yes, it must be. Fail the move.
VectorCopy (SVvector (pusher, origin), SVvector (pusher, oldorigin));
// Revert
if (SVfunc (pusher, blocked)) { // Blocked func?
*sv_globals.self = EDICT_TO_PROG (&sv_pr_state, pusher);
*sv_globals.other = EDICT_TO_PROG (&sv_pr_state, check);
PR_ExecuteProgram (&sv_pr_state, SVfunc (pusher, blocked));
}
return;
}
}
void
SV_Physics_PPusher (edict_t *ent)
{
float movetime, oldltime, thinktime;
// float l;
oldltime = SVfloat (ent, ltime);
thinktime = SVfloat (ent, nextthink);
if (thinktime < SVfloat (ent, ltime) + sv_frametime) {
movetime = thinktime - SVfloat (ent, ltime);
if (movetime < 0)
movetime = 0;
} else
movetime = sv_frametime;
// if (movetime)
// {
SV_PPushMove (ent, 0.0009); // advances SVfloat (ent, ltime) if not blocked
// }
if (thinktime > oldltime && thinktime <= SVfloat (ent, ltime)) {
SVfloat (ent, nextthink) = 0;
*sv_globals.time = sv.time;
*sv_globals.self = EDICT_TO_PROG (&sv_pr_state, ent);
*sv_globals.other = EDICT_TO_PROG (&sv_pr_state, sv.edicts);
PR_ExecuteProgram (&sv_pr_state, SVfunc (ent, think));
if (ent->free)
return;
}
}
void void
SV_ProgStartFrame (void) SV_ProgStartFrame (void)
{ {
@ -848,30 +746,27 @@ SV_RunEntity (edict_t *ent)
SVfloat (ent, lastruntime) = (float) realtime; SVfloat (ent, lastruntime) = (float) realtime;
switch ((int) SVfloat (ent, movetype)) { switch ((int) SVfloat (ent, movetype)) {
case MOVETYPE_PUSH: case MOVETYPE_PUSH:
SV_Physics_Pusher (ent); SV_Physics_Pusher (ent);
break; break;
case MOVETYPE_PPUSH: case MOVETYPE_NONE:
SV_Physics_PPusher (ent); SV_Physics_None (ent);
break; break;
case MOVETYPE_NONE: case MOVETYPE_NOCLIP:
SV_Physics_None (ent); SV_Physics_Noclip (ent);
break; break;
case MOVETYPE_NOCLIP: case MOVETYPE_STEP:
SV_Physics_Noclip (ent); SV_Physics_Step (ent);
break; break;
case MOVETYPE_STEP: case MOVETYPE_TOSS:
SV_Physics_Step (ent); case MOVETYPE_BOUNCE:
break; case MOVETYPE_FLY:
case MOVETYPE_TOSS: case MOVETYPE_FLYMISSILE:
case MOVETYPE_BOUNCE: SV_Physics_Toss (ent);
case MOVETYPE_FLY: break;
case MOVETYPE_FLYMISSILE: default:
SV_Physics_Toss (ent); Sys_Error ("SV_Physics: bad movetype %i",
break; (int) SVfloat (ent, movetype));
default:
Sys_Error ("SV_Physics: bad movetype %i", (int) SVfloat (ent,
movetype));
} }
} }
@ -915,8 +810,9 @@ SV_Physics (void)
if (ent->free) if (ent->free)
continue; continue;
if (*sv_globals.force_retouch) if (*sv_globals.force_retouch) {
SV_LinkEdict (ent, true); // force retouch even for stationary SV_LinkEdict (ent, true); // force retouch even for stationary
}
if (i > 0 && i <= MAX_CLIENTS) if (i > 0 && i <= MAX_CLIENTS)
continue; // clients are run directly from packets continue; // clients are run directly from packets