DarkPlaces
Game engine based on the Quake 1 engine by id Software, developed by LadyHavoc
 
sv_phys.c File Reference
#include "quakedef.h"
#include "prvm_cmds.h"
+ Include dependency graph for sv_phys.c:

Go to the source code of this file.

Macros

#define MAX_CLIP_PLANES   5
 
#define MOVE_EPSILON   0.01
 
#define STOP_EPSILON   0.1
 

Functions

static void ClipVelocity (prvm_vec3_t in, vec3_t normal, prvm_vec3_t out, prvm_vec_t overbounce)
 
static void RotateBBox (const vec3_t mins, const vec3_t maxs, const vec3_t angles, vec3_t rotatedmins, vec3_t rotatedmaxs)
 
static int SV_CheckContentsTransition (prvm_edict_t *ent, const int nContents)
 
void SV_CheckVelocity (prvm_edict_t *ent)
 
static qbool SV_CheckWater (prvm_edict_t *ent)
 
static void SV_CheckWaterTransition (prvm_edict_t *ent)
 
int SV_EntitiesInBox (const vec3_t mins, const vec3_t maxs, int maxedicts, prvm_edict_t **resultedicts)
 
static int SV_FlyMove (prvm_edict_t *ent, float time, qbool applygravity, float *stepnormal, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask, float stepheight)
 
int SV_GenericHitSuperContentsMask (const prvm_edict_t *passedict)
 calculates hitsupercontentsmask for a generic qc entity
 
int SV_GetPitchSign (prvm_prog_t *prog, prvm_edict_t *ent)
 
static float SV_Gravity (prvm_edict_t *ent)
 
static qbool SV_Impact (prvm_edict_t *e1, trace_t *trace)
 
void SV_LinkEdict (prvm_edict_t *ent)
 
void SV_LinkEdict_TouchAreaGrid (prvm_edict_t *ent)
 
void SV_LinkEdict_TouchAreaGrid_Call (prvm_edict_t *touch, prvm_edict_t *ent)
 
static qbool SV_NudgeOutOfSolid_PivotIsKnownGood (prvm_edict_t *ent, vec3_t pivot)
 
void SV_Physics (void)
 
static void SV_Physics_ClientEntity (prvm_edict_t *ent)
 
static void SV_Physics_ClientEntity_NoThink (prvm_edict_t *ent)
 
static void SV_Physics_ClientEntity_PostThink (prvm_edict_t *ent)
 
static void SV_Physics_ClientEntity_PreThink (prvm_edict_t *ent)
 
void SV_Physics_ClientMove (void)
 
static void SV_Physics_Entity (prvm_edict_t *ent)
 
static void SV_Physics_Follow (prvm_edict_t *ent)
 
static void SV_Physics_Pusher (prvm_edict_t *ent)
 
static void SV_Physics_Step (prvm_edict_t *ent)
 
void SV_Physics_Toss (prvm_edict_t *ent)
 
int SV_PointSuperContents (const vec3_t point)
 
static qbool SV_PushEntity (trace_t *trace, prvm_edict_t *ent, vec3_t push, qbool dotouch, qbool checkstuck)
 
static void SV_PushMove (prvm_edict_t *pusher, float movetime)
 
static qbool SV_RunThink (prvm_edict_t *ent)
 
trace_t SV_TraceBox (const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int type, prvm_edict_t *passedict, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask, float extend)
 traces a box move against worldmodel and all entities in the specified area
 
trace_t SV_TraceLine (const vec3_t start, const vec3_t end, int type, prvm_edict_t *passedict, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask, float extend)
 
trace_t SV_TracePoint (const vec3_t start, int type, prvm_edict_t *passedict, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
 
static qbool SV_UnstickEntity (prvm_edict_t *ent)
 
static void SV_WalkMove (prvm_edict_t *ent)
 
static void SV_WallFriction (prvm_edict_t *ent, float *stepnormal)
 

Macro Definition Documentation

◆ MAX_CLIP_PLANES

#define MAX_CLIP_PLANES   5

Definition at line 1149 of file sv_phys.c.

Referenced by SV_FlyMove().

◆ MOVE_EPSILON

#define MOVE_EPSILON   0.01

Definition at line 43 of file sv_phys.c.

◆ STOP_EPSILON

#define STOP_EPSILON   0.1

Definition at line 1119 of file sv_phys.c.

Referenced by ClipVelocity().

Function Documentation

◆ ClipVelocity()

static void ClipVelocity ( prvm_vec3_t in,
vec3_t normal,
prvm_vec3_t out,
prvm_vec_t overbounce )
static

Definition at line 1120 of file sv_phys.c.

1121{
1122 int i;
1123 float backoff;
1124
1125 backoff = -DotProduct (in, normal) * overbounce;
1126 VectorMA(in, backoff, normal, out);
1127
1128 for (i = 0;i < 3;i++)
1129 if (out[i] > -STOP_EPSILON && out[i] < STOP_EPSILON)
1130 out[i] = 0;
1131}
#define DotProduct(a, b)
Definition mathlib.h:98
#define VectorMA(a, scale, b, out)
Definition mathlib.h:114
int i
vec3 normal
#define STOP_EPSILON
Definition sv_phys.c:1119

References DotProduct, i, normal, STOP_EPSILON, and VectorMA.

Referenced by SV_FlyMove(), and SV_Physics_Toss().

◆ RotateBBox()

static void RotateBBox ( const vec3_t mins,
const vec3_t maxs,
const vec3_t angles,
vec3_t rotatedmins,
vec3_t rotatedmaxs )
static

Definition at line 767 of file sv_phys.c.

768{
769 vec3_t v, u;
770 matrix4x4_t m;
772
773 v[0] = mins[0]; v[1] = mins[1]; v[2] = mins[2]; Matrix4x4_Transform(&m, v, u);
774 VectorCopy(u, rotatedmins); VectorCopy(u, rotatedmaxs);
775 v[0] = maxs[0]; v[1] = mins[1]; v[2] = mins[2]; Matrix4x4_Transform(&m, v, u);
776 if(rotatedmins[0] > u[0]) { rotatedmins[0] = u[0]; } if(rotatedmins[1] > u[1]) { rotatedmins[1] = u[1]; } if(rotatedmins[2] > u[2]) { rotatedmins[2] = u[2]; }
777 if(rotatedmaxs[0] < u[0]) { rotatedmaxs[0] = u[0]; } if(rotatedmaxs[1] < u[1]) { rotatedmaxs[1] = u[1]; } if(rotatedmaxs[2] < u[2]) { rotatedmaxs[2] = u[2]; }
778 v[0] = mins[0]; v[1] = maxs[1]; v[2] = mins[2]; Matrix4x4_Transform(&m, v, u);
779 if(rotatedmins[0] > u[0]) { rotatedmins[0] = u[0]; } if(rotatedmins[1] > u[1]) { rotatedmins[1] = u[1]; } if(rotatedmins[2] > u[2]) { rotatedmins[2] = u[2]; }
780 if(rotatedmaxs[0] < u[0]) { rotatedmaxs[0] = u[0]; } if(rotatedmaxs[1] < u[1]) { rotatedmaxs[1] = u[1]; } if(rotatedmaxs[2] < u[2]) { rotatedmaxs[2] = u[2]; }
781 v[0] = maxs[0]; v[1] = maxs[1]; v[2] = mins[2]; Matrix4x4_Transform(&m, v, u);
782 if(rotatedmins[0] > u[0]) { rotatedmins[0] = u[0]; } if(rotatedmins[1] > u[1]) { rotatedmins[1] = u[1]; } if(rotatedmins[2] > u[2]) { rotatedmins[2] = u[2]; }
783 if(rotatedmaxs[0] < u[0]) { rotatedmaxs[0] = u[0]; } if(rotatedmaxs[1] < u[1]) { rotatedmaxs[1] = u[1]; } if(rotatedmaxs[2] < u[2]) { rotatedmaxs[2] = u[2]; }
784 v[0] = mins[0]; v[1] = mins[1]; v[2] = maxs[2]; Matrix4x4_Transform(&m, v, u);
785 if(rotatedmins[0] > u[0]) { rotatedmins[0] = u[0]; } if(rotatedmins[1] > u[1]) { rotatedmins[1] = u[1]; } if(rotatedmins[2] > u[2]) { rotatedmins[2] = u[2]; }
786 if(rotatedmaxs[0] < u[0]) { rotatedmaxs[0] = u[0]; } if(rotatedmaxs[1] < u[1]) { rotatedmaxs[1] = u[1]; } if(rotatedmaxs[2] < u[2]) { rotatedmaxs[2] = u[2]; }
787 v[0] = maxs[0]; v[1] = mins[1]; v[2] = maxs[2]; Matrix4x4_Transform(&m, v, u);
788 if(rotatedmins[0] > u[0]) { rotatedmins[0] = u[0]; } if(rotatedmins[1] > u[1]) { rotatedmins[1] = u[1]; } if(rotatedmins[2] > u[2]) { rotatedmins[2] = u[2]; }
789 if(rotatedmaxs[0] < u[0]) { rotatedmaxs[0] = u[0]; } if(rotatedmaxs[1] < u[1]) { rotatedmaxs[1] = u[1]; } if(rotatedmaxs[2] < u[2]) { rotatedmaxs[2] = u[2]; }
790 v[0] = mins[0]; v[1] = maxs[1]; v[2] = maxs[2]; Matrix4x4_Transform(&m, v, u);
791 if(rotatedmins[0] > u[0]) { rotatedmins[0] = u[0]; } if(rotatedmins[1] > u[1]) { rotatedmins[1] = u[1]; } if(rotatedmins[2] > u[2]) { rotatedmins[2] = u[2]; }
792 if(rotatedmaxs[0] < u[0]) { rotatedmaxs[0] = u[0]; } if(rotatedmaxs[1] < u[1]) { rotatedmaxs[1] = u[1]; } if(rotatedmaxs[2] < u[2]) { rotatedmaxs[2] = u[2]; }
793 v[0] = maxs[0]; v[1] = maxs[1]; v[2] = maxs[2]; Matrix4x4_Transform(&m, v, u);
794 if(rotatedmins[0] > u[0]) { rotatedmins[0] = u[0]; } if(rotatedmins[1] > u[1]) { rotatedmins[1] = u[1]; } if(rotatedmins[2] > u[2]) { rotatedmins[2] = u[2]; }
795 if(rotatedmaxs[0] < u[0]) { rotatedmaxs[0] = u[0]; } if(rotatedmaxs[1] < u[1]) { rotatedmaxs[1] = u[1]; } if(rotatedmaxs[2] < u[2]) { rotatedmaxs[2] = u[2]; }
796}
vector mins
vector maxs
vector angles
const GLdouble * v
Definition glquake.h:762
#define VectorCopy(in, out)
Definition mathlib.h:101
void Matrix4x4_Transform(const matrix4x4_t *in, const float v[3], float out[3])
Definition matrixlib.c:1657
void Matrix4x4_CreateFromQuakeEntity(matrix4x4_t *out, double x, double y, double z, double pitch, double yaw, double roll, double scale)
Definition matrixlib.c:715
vec_t vec3_t[3]
Definition qtypes.h:71
#define YAW
Definition qtypes.h:19
#define PITCH
Definition qtypes.h:16
#define ROLL
Definition qtypes.h:22

References angles, Matrix4x4_CreateFromQuakeEntity(), Matrix4x4_Transform(), maxs, mins, PITCH, ROLL, v, VectorCopy, and YAW.

Referenced by SV_LinkEdict().

◆ SV_CheckContentsTransition()

static int SV_CheckContentsTransition ( prvm_edict_t * ent,
const int nContents )
static

Definition at line 926 of file sv_phys.c.

927{
928 prvm_prog_t *prog = SVVM_prog;
929 int bValidFunctionCall;
930
931 // Default Valid Function Call to False
932 bValidFunctionCall = false;
933
934 if(PRVM_serveredictfloat(ent, watertype) != nContents)
935 { // Changed Contents
936 // Acquire Contents Transition Function from QC
937 if(PRVM_serveredictfunction(ent, contentstransition))
938 { // Valid Function; Execute
939 // Assign Valid Function
940 bValidFunctionCall = true;
941 // Prepare Parameters (Original Contents, New Contents)
942 // Original Contents
944 // New Contents
945 PRVM_G_FLOAT(OFS_PARM1) = nContents;
946 // Assign Self
948 // Set Time
950 // Execute VM Function
951 prog->ExecuteProgram(prog, PRVM_serveredictfunction(ent, contentstransition), "contentstransition: NULL function");
952 }
953 }
954
955 // Return if Function Call was Valid
956 return bValidFunctionCall;
957}
entity self
float time
#define OFS_PARM0
Definition pr_comp.h:34
#define OFS_PARM1
Definition pr_comp.h:35
float watertype
Definition progsdefs.qc:182
#define PRVM_serverglobaledict(fieldname)
Definition progsvm.h:180
#define PRVM_EDICT_TO_PROG(e)
Definition progsvm.h:875
#define PRVM_serverglobalfloat(fieldname)
Definition progsvm.h:177
#define PRVM_serveredictfloat(ed, fieldname)
Definition progsvm.h:172
#define PRVM_serveredictfunction(ed, fieldname)
Definition progsvm.h:176
#define PRVM_G_FLOAT(o)
Definition progsvm.h:882
#define SVVM_prog
Definition progsvm.h:766
server_t sv
local server
Definition sv_main.c:223
void(* ExecuteProgram)(struct prvm_prog_s *prog, func_t fnum, const char *errormessage)
pointer to one of the *VM_ExecuteProgram functions
Definition progsvm.h:749
double time
Definition server.h:76

References prvm_prog_t::ExecuteProgram, OFS_PARM0, OFS_PARM1, PRVM_EDICT_TO_PROG, PRVM_G_FLOAT, PRVM_serveredictfloat, PRVM_serveredictfunction, PRVM_serverglobaledict, PRVM_serverglobalfloat, self, sv, SVVM_prog, server_t::time, time, and watertype.

Referenced by SV_CheckWater(), and SV_CheckWaterTransition().

◆ SV_CheckVelocity()

void SV_CheckVelocity ( prvm_edict_t * ent)

Definition at line 965 of file sv_phys.c.

966{
967 prvm_prog_t *prog = SVVM_prog;
968 int i;
969 float wishspeed;
970
971//
972// bound velocity
973//
974 for (i=0 ; i<3 ; i++)
975 {
976 if (isnan(PRVM_serveredictvector(ent, velocity)[i]))
977 {
978 Con_Printf("Got a NaN velocity on entity #%i (%s)\n", PRVM_NUM_FOR_EDICT(ent), PRVM_GetString(prog, PRVM_serveredictstring(ent, classname)));
980 }
981 if (isnan(PRVM_serveredictvector(ent, origin)[i]))
982 {
983 Con_Printf("Got a NaN origin on entity #%i (%s)\n", PRVM_NUM_FOR_EDICT(ent), PRVM_GetString(prog, PRVM_serveredictstring(ent, classname)));
985 }
986 }
987
988 // LadyHavoc: a hack to ensure that the (rather silly) id1 quakec
989 // player_run/player_stand1 does not horribly malfunction if the
990 // velocity becomes a denormalized float
991 if (VectorLength2(PRVM_serveredictvector(ent, velocity)) < 0.0000001)
993
994 // LadyHavoc: max velocity fix, inspired by Maddes's source fixes, but this is faster
997 {
1002 }
1003}
void Con_Printf(const char *fmt,...)
Prints to all appropriate console targets.
Definition console.c:1514
string classname
vector velocity
vector origin
#define VectorClear(a)
Definition mathlib.h:97
#define VectorLength2(a)
Definition mathlib.h:110
float sqrt(float f)
#define PRVM_serveredictvector(ed, fieldname)
Definition progsvm.h:173
const char * PRVM_GetString(prvm_prog_t *prog, int num)
#define PRVM_NUM_FOR_EDICT(e)
Definition progsvm.h:870
#define PRVM_serveredictstring(ed, fieldname)
Definition progsvm.h:174
cvar_t sv_maxvelocity
Definition sv_main.c:143
float value
Definition cvar.h:74
static float wishspeed
Definition sv_user.c:306

References classname, Con_Printf(), DotProduct, i, origin, PRVM_GetString(), PRVM_NUM_FOR_EDICT, PRVM_serveredictstring, PRVM_serveredictvector, sqrt(), sv_maxvelocity, SVVM_prog, cvar_t::value, VectorClear, VectorLength2, velocity, and wishspeed.

Referenced by SV_Physics_ClientEntity(), SV_Physics_ClientEntity_PostThink(), SV_Physics_ClientEntity_PreThink(), SV_Physics_ClientMove(), SV_Physics_Step(), SV_Physics_Toss(), SV_PlayerPhysics(), SV_Trace_Toss(), and SV_WalkMove().

◆ SV_CheckWater()

static qbool SV_CheckWater ( prvm_edict_t * ent)
static

Definition at line 2012 of file sv_phys.c.

2013{
2014 prvm_prog_t *prog = SVVM_prog;
2015 int cont;
2016 int nNativeContents;
2017 vec3_t point;
2018
2019 point[0] = PRVM_serveredictvector(ent, origin)[0];
2020 point[1] = PRVM_serveredictvector(ent, origin)[1];
2021 point[2] = PRVM_serveredictvector(ent, origin)[2] + PRVM_serveredictvector(ent, mins)[2] + 1;
2022
2023 // DRESK - Support for Entity Contents Transition Event
2024 // NOTE: Some logic needed to be slightly re-ordered
2025 // to not affect performance and allow for the feature.
2026
2027 // Acquire Super Contents Prior to Resets
2028 cont = SV_PointSuperContents(point);
2029 // Acquire Native Contents Here
2030 nNativeContents = Mod_Q1BSP_NativeContentsFromSuperContents(cont);
2031
2032 // DRESK - Support for Entity Contents Transition Event
2034 // Entity did NOT Spawn; Check
2035 SV_CheckContentsTransition(ent, nNativeContents);
2036
2037
2040 cont = SV_PointSuperContents(point);
2041 if (cont & (SUPERCONTENTS_LIQUIDSMASK))
2042 {
2043 PRVM_serveredictfloat(ent, watertype) = nNativeContents;
2045 point[2] = PRVM_serveredictvector(ent, origin)[2] + (PRVM_serveredictvector(ent, mins)[2] + PRVM_serveredictvector(ent, maxs)[2])*0.5;
2047 {
2049 point[2] = PRVM_serveredictvector(ent, origin)[2] + PRVM_serveredictvector(ent, view_ofs)[2];
2052 }
2053 }
2054
2055 return PRVM_serveredictfloat(ent, waterlevel) > 1;
2056}
#define SUPERCONTENTS_LIQUIDSMASK
Definition bspfile.h:218
#define CONTENTS_EMPTY
Definition bspfile.h:133
int Mod_Q1BSP_NativeContentsFromSuperContents(int supercontents)
vector view_ofs
Definition progsdefs.qc:151
float waterlevel
Definition progsdefs.qc:181
int SV_PointSuperContents(const vec3_t point)
Definition sv_phys.c:611
static int SV_CheckContentsTransition(prvm_edict_t *ent, const int nContents)
Definition sv_phys.c:926

References CONTENTS_EMPTY, maxs, mins, Mod_Q1BSP_NativeContentsFromSuperContents(), origin, PRVM_serveredictfloat, PRVM_serveredictvector, SUPERCONTENTS_LIQUIDSMASK, SV_CheckContentsTransition(), SV_PointSuperContents(), SVVM_prog, view_ofs, waterlevel, and watertype.

Referenced by SV_Physics_ClientEntity(), SV_Physics_Entity(), and SV_WalkMove().

◆ SV_CheckWaterTransition()

static void SV_CheckWaterTransition ( prvm_edict_t * ent)
static

Definition at line 2410 of file sv_phys.c.

2411{
2412 vec3_t entorigin;
2413 prvm_prog_t *prog = SVVM_prog;
2414 // LadyHavoc: bugfixes in this function are keyed to the sv_gameplayfix_bugfixedcheckwatertransition cvar - if this cvar is 0 then all the original bugs should be reenabled for compatibility
2415 int cont;
2416 VectorCopy(PRVM_serveredictvector(ent, origin), entorigin);
2419 {
2420 // just spawned here
2422 {
2423 PRVM_serveredictfloat(ent, watertype) = cont;
2425 return;
2426 }
2427 }
2428 // DRESK - Support for Entity Contents Transition Event
2429 // NOTE: Call here BEFORE updating the watertype below,
2430 // and suppress watersplash sound if a valid function
2431 // call was made to allow for custom "splash" sounds.
2432 else if( !SV_CheckContentsTransition(ent, cont) )
2433 { // Contents Transition Function Invalid; Potentially Play Water Sound
2434 // check if the entity crossed into or out of water
2436 SV_StartSound (ent, 0, sv_sound_watersplash.string, 255, 1, false, 1.0f);
2437 }
2438
2439 if (cont <= CONTENTS_WATER)
2440 {
2441 PRVM_serveredictfloat(ent, watertype) = cont;
2443 }
2444 else
2445 {
2448 }
2449}
#define CONTENTS_SLIME
Definition bspfile.h:136
#define CONTENTS_WATER
Definition bspfile.h:135
void SV_StartSound(prvm_edict_t *entity, int channel, const char *sample, int volume, float attenuation, qbool reliable, float speed)
Definition sv_send.c:228
cvar_t sv_sound_watersplash
Definition sv_main.c:152
cvar_t sv_gameplayfix_fixedcheckwatertransition
Definition sv_main.c:132
int integer
Definition cvar.h:73
const char * string
Definition cvar.h:71

References CONTENTS_EMPTY, CONTENTS_SLIME, CONTENTS_WATER, cvar_t::integer, Mod_Q1BSP_NativeContentsFromSuperContents(), origin, PRVM_serveredictfloat, PRVM_serveredictvector, cvar_t::string, SV_CheckContentsTransition(), sv_gameplayfix_fixedcheckwatertransition, SV_PointSuperContents(), sv_sound_watersplash, SV_StartSound(), SVVM_prog, VectorCopy, waterlevel, and watertype.

Referenced by SV_Physics_ClientEntity(), SV_Physics_Entity(), and SV_Physics_Toss().

◆ SV_EntitiesInBox()

int SV_EntitiesInBox ( const vec3_t mins,
const vec3_t maxs,
int maxedicts,
prvm_edict_t ** resultedicts )

Definition at line 673 of file sv_phys.c.

674{
675 prvm_prog_t *prog = SVVM_prog;
676 vec3_t paddedmins, paddedmaxs;
677 if (maxedicts < 1 || resultedicts == NULL)
678 return 0;
679 // LadyHavoc: discovered this actually causes its own bugs (dm6 teleporters being too close to info_teleport_destination)
680 //VectorSet(paddedmins, mins[0] - 10, mins[1] - 10, mins[2] - 1);
681 //VectorSet(paddedmaxs, maxs[0] + 10, maxs[1] + 10, maxs[2] + 1);
682 VectorCopy(mins, paddedmins);
683 VectorCopy(maxs, paddedmaxs);
685 {
686 int numresultedicts = 0;
687 int edictindex;
688 prvm_edict_t *ed;
689 for (edictindex = 1;edictindex < prog->num_edicts;edictindex++)
690 {
691 ed = PRVM_EDICT_NUM(edictindex);
692 if (!ed->free && BoxesOverlap(PRVM_serveredictvector(ed, absmin), PRVM_serveredictvector(ed, absmax), paddedmins, paddedmaxs))
693 {
694 resultedicts[numresultedicts++] = ed;
695 if (numresultedicts == maxedicts)
696 break;
697 }
698 }
699 return numresultedicts;
700 }
701 else
702 return World_EntitiesInBox(&sv.world, paddedmins, paddedmaxs, maxedicts, resultedicts);
703}
vector absmax
vector absmin
#define BoxesOverlap(a, b, c, d)
Definition mathlib.h:122
#define PRVM_EDICT_NUM(n)
Definition progsvm.h:867
#define NULL
Definition qtypes.h:12
cvar_t sv_areadebug
Definition sv_main.c:164
qbool free
true if this edict is unused
Definition progsvm.h:93
int num_edicts
copies of some vars that were former read from sv
Definition progsvm.h:671
world_t world
collision culling data
Definition server.h:106
int World_EntitiesInBox(world_t *world, const vec3_t requestmins, const vec3_t requestmaxs, int maxlist, prvm_edict_t **list)
Definition world.c:188

References absmax, absmin, BoxesOverlap, prvm_edict_t::free, cvar_t::integer, maxs, mins, NULL, prvm_prog_t::num_edicts, PRVM_EDICT_NUM, PRVM_serveredictvector, sv, sv_areadebug, SVVM_prog, VectorCopy, server_t::world, and World_EntitiesInBox().

Referenced by SV_CanSeeBox(), SV_LinkEdict_TouchAreaGrid(), SV_PointSuperContents(), SV_PushMove(), SV_TraceBox(), SV_TraceLine(), SV_TracePoint(), VM_SV_findbox(), and VM_SV_findradius().

◆ SV_FlyMove()

static int SV_FlyMove ( prvm_edict_t * ent,
float time,
qbool applygravity,
float * stepnormal,
int hitsupercontentsmask,
int skipsupercontentsmask,
int skipmaterialflagsmask,
float stepheight )
static

Definition at line 1150 of file sv_phys.c.

1151{
1152 prvm_prog_t *prog = SVVM_prog;
1153 unsigned int i, j, numplanes, blocked, bumpcount;
1154 float d, time_left, gravity;
1155 vec3_t dir, push, planes[MAX_CLIP_PLANES];
1156 prvm_vec3_t primal_velocity, original_velocity, new_velocity, restore_velocity;
1157#if 0
1158 vec3_t end;
1159#endif
1160 trace_t trace;
1161 if (time <= 0)
1162 return 0;
1163 gravity = 0;
1164
1165 VectorCopy(PRVM_serveredictvector(ent, velocity), restore_velocity);
1166
1167 if(applygravity)
1168 {
1169 gravity = SV_Gravity(ent);
1170
1172 {
1174 PRVM_serveredictvector(ent, velocity)[2] -= gravity * 0.5f;
1175 else
1176 PRVM_serveredictvector(ent, velocity)[2] -= gravity;
1177 }
1178 }
1179
1180 blocked = 0;
1181 VectorCopy(PRVM_serveredictvector(ent, velocity), original_velocity);
1182 VectorCopy(PRVM_serveredictvector(ent, velocity), primal_velocity);
1183 numplanes = 0;
1184 time_left = time;
1185 for (bumpcount = 0;bumpcount < MAX_CLIP_PLANES;bumpcount++)
1186 {
1188 break;
1189
1190 VectorScale(PRVM_serveredictvector(ent, velocity), time_left, push);
1191 if(!SV_PushEntity(&trace, ent, push, sv_gameplayfix_impactbeforeonground.integer, true))
1192 {
1193 // we got teleported by a touch function
1194 // let's abort the move
1195 blocked |= 8;
1196 break;
1197 }
1198
1199 // this code is used by MOVETYPE_WALK and MOVETYPE_STEP and SV_UnstickEntity
1200 // abort move if we're stuck in the world (and didn't make it out)
1201 if (trace.worldstartsolid && trace.allsolid)
1202 {
1203 VectorCopy(restore_velocity, PRVM_serveredictvector(ent, velocity));
1204 return 3;
1205 }
1206
1207 if (trace.fraction == 1)
1208 break;
1209
1210 time_left *= 1 - trace.fraction;
1211
1212 if (trace.plane.normal[2])
1213 {
1214 if (trace.plane.normal[2] > 0.7)
1215 {
1216 // floor
1217 blocked |= 1;
1218
1219 if (!trace.ent)
1220 {
1221 Con_Printf ("SV_FlyMove: !trace.ent");
1222 trace.ent = prog->edicts;
1223 }
1224
1227 }
1228 }
1229 else if (stepheight)
1230 {
1231 // step - handle it immediately
1232 vec3_t org;
1233 vec3_t steppush;
1234 trace_t steptrace;
1235 trace_t steptrace2;
1236 trace_t steptrace3;
1237 //Con_Printf("step %f %f %f : ", PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2]);
1238 VectorSet(steppush, 0, 0, stepheight);
1239 VectorScale(PRVM_serveredictvector(ent, velocity), time_left, push);
1241 if(!SV_PushEntity(&steptrace, ent, steppush, false, true))
1242 {
1243 blocked |= 8;
1244 break;
1245 }
1246 //Con_Printf("%f %f %f : ", PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2]);
1247 if(!SV_PushEntity(&steptrace2, ent, push, false, true))
1248 {
1249 blocked |= 8;
1250 break;
1251 }
1252 //Con_Printf("%f %f %f : ", PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2]);
1253 VectorSet(steppush, 0, 0, org[2] - PRVM_serveredictvector(ent, origin)[2]);
1254 if(!SV_PushEntity(&steptrace3, ent, steppush, false, true))
1255 {
1256 blocked |= 8;
1257 break;
1258 }
1259 //Con_Printf("%f %f %f : ", PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2]);
1260 // accept the new position if it made some progress...
1261 // previously this checked if absolute distance >= 0.03125 which made stepping up unreliable
1262 if (PRVM_serveredictvector(ent, origin)[0] - org[0] || PRVM_serveredictvector(ent, origin)[1] - org[1])
1263 {
1264 //Con_Printf("accepted (delta %f %f %f)\n", PRVM_serveredictvector(ent, origin)[0] - org[0], PRVM_serveredictvector(ent, origin)[1] - org[1], PRVM_serveredictvector(ent, origin)[2] - org[2]);
1265 trace = steptrace2;
1267 time_left *= 1 - trace.fraction;
1268 numplanes = 0;
1269 continue;
1270 }
1271 else
1272 {
1273 //Con_Printf("REJECTED (delta %f %f %f)\n", PRVM_serveredictvector(ent, origin)[0] - org[0], PRVM_serveredictvector(ent, origin)[1] - org[1], PRVM_serveredictvector(ent, origin)[2] - org[2]);
1275 }
1276 }
1277 else
1278 {
1279 // step - return it to caller
1280 blocked |= 2;
1281 // save the trace for player extrafriction
1282 if (stepnormal)
1283 VectorCopy(trace.plane.normal, stepnormal);
1284 }
1285
1287 {
1288 // Unlike some other movetypes Quake's SV_FlyMove calls SV_Impact only after setting ONGROUND which id1 fiends rely on.
1289 // If we stepped up (sv_gameplayfix_stepmultipletimes) this will impact the steptrace2 plane instead of the original.
1290 if (PRVM_serveredictfloat(ent, solid) >= SOLID_TRIGGER && trace.ent)
1291 if (!SV_Impact(ent, &trace))
1292 {
1293 blocked |= 8;
1294 break;
1295 }
1296 if (ent->free)
1297 return blocked; // removed by the impact function
1298 }
1299
1300 if (trace.fraction >= 0.001)
1301 {
1302 // actually covered some distance
1303 VectorCopy(PRVM_serveredictvector(ent, velocity), original_velocity);
1304 numplanes = 0;
1305 }
1306
1307 // clipped to another plane
1308 if (numplanes >= MAX_CLIP_PLANES)
1309 {
1310 // this shouldn't really happen
1312 blocked = 3;
1313 break;
1314 }
1315
1316 /*
1317 for (i = 0;i < numplanes;i++)
1318 if (DotProduct(trace.plane.normal, planes[i]) > 0.99)
1319 break;
1320 if (i < numplanes)
1321 {
1322 VectorAdd(PRVM_serveredictvector(ent, velocity), trace.plane.normal, PRVM_serveredictvector(ent, velocity));
1323 continue;
1324 }
1325 */
1326
1327 VectorCopy(trace.plane.normal, planes[numplanes]);
1328 numplanes++;
1329
1330 // modify original_velocity so it parallels all of the clip planes
1331 for (i = 0;i < numplanes;i++)
1332 {
1333 ClipVelocity(original_velocity, planes[i], new_velocity, 1);
1334 for (j = 0;j < numplanes;j++)
1335 {
1336 if (j != i)
1337 {
1338 // not ok
1339 if (DotProduct(new_velocity, planes[j]) < 0)
1340 break;
1341 }
1342 }
1343 if (j == numplanes)
1344 break;
1345 }
1346
1347 if (i != numplanes)
1348 {
1349 // go along this plane
1350 VectorCopy(new_velocity, PRVM_serveredictvector(ent, velocity));
1351 }
1352 else
1353 {
1354 // go along the crease
1355 if (numplanes != 2)
1356 {
1358 blocked = 7;
1359 break;
1360 }
1361 CrossProduct(planes[0], planes[1], dir);
1362 // LadyHavoc: thanks to taniwha of QuakeForge for pointing out this fix for slowed falling in corners
1366 }
1367
1368 // if current velocity is against the original velocity,
1369 // stop dead to avoid tiny occilations in sloping corners
1370 if (DotProduct(PRVM_serveredictvector(ent, velocity), primal_velocity) <= 0)
1371 {
1373 break;
1374 }
1375 }
1376
1377 //Con_Printf("entity %i final: blocked %i velocity %f %f %f\n", ent - prog->edicts, blocked, PRVM_serveredictvector(ent, velocity)[0], PRVM_serveredictvector(ent, velocity)[1], PRVM_serveredictvector(ent, velocity)[2]);
1378
1379 /*
1380 if ((blocked & 1) == 0 && bumpcount > 1)
1381 {
1382 // LadyHavoc: fix the 'fall to your death in a wedge corner' glitch
1383 // flag ONGROUND if there's ground under it
1384 trace = SV_TraceBox(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, mins), PRVM_serveredictvector(ent, maxs), end, MOVE_NORMAL, ent, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
1385 }
1386 */
1387
1388 // LadyHavoc: this came from QW and allows you to get out of water more easily
1389 if (sv_gameplayfix_easierwaterjump.integer && ((int)PRVM_serveredictfloat(ent, flags) & FL_WATERJUMP) && !(blocked & 8))
1390 VectorCopy(primal_velocity, PRVM_serveredictvector(ent, velocity));
1391
1392 if(applygravity)
1393 {
1395 {
1397 PRVM_serveredictvector(ent, velocity)[2] -= gravity * 0.5f;
1398 }
1399 }
1400
1401 return blocked;
1402}
float flags
float solid
static int(ZEXPORT *qz_inflate)(z_stream *strm
#define VectorNormalize(v)
Definition mathlib.h:104
#define VectorSet(vec, x, y, z)
Definition mathlib.h:96
#define CrossProduct(a, b, out)
Definition mathlib.h:103
#define VectorScale(in, scale, out)
Definition mathlib.h:111
entity groundentity
Definition progsdefs.qc:134
#define PRVM_serveredictedict(ed, fieldname)
Definition progsvm.h:175
prvm_vec_t prvm_vec3_t[3]
Definition qtypes.h:63
#define FL_WATERJUMP
player jumping out of water
Definition server.h:368
cvar_t sv_gameplayfix_easierwaterjump
Definition sv_main.c:109
cvar_t sv_gameplayfix_impactbeforeonground
Definition sv_main.c:113
cvar_t sv_gameplayfix_nogravityonground
Definition sv_main.c:120
cvar_t sv_gameplayfix_gravityunaffectedbyticrate
Definition sv_main.c:111
#define FL_ONGROUND
Definition server.h:366
#define SOLID_TRIGGER
touch on edge, but not blocking
Definition server.h:333
vec2 dir
prvm_edict_t * edicts
Definition progsvm.h:680
void * ent
Definition collision.h:47
double fraction
Definition collision.h:40
qbool worldstartsolid
Definition collision.h:28
double endpos[3]
Definition collision.h:42
qbool allsolid
Definition collision.h:24
plane_t plane
Definition collision.h:44
#define MAX_CLIP_PLANES
Definition sv_phys.c:1149
static void ClipVelocity(prvm_vec3_t in, vec3_t normal, prvm_vec3_t out, prvm_vec_t overbounce)
Definition sv_phys.c:1120
static qbool SV_Impact(prvm_edict_t *e1, trace_t *trace)
Definition sv_phys.c:1050
static float SV_Gravity(prvm_edict_t *ent)
Definition sv_phys.c:1410
static qbool SV_PushEntity(trace_t *trace, prvm_edict_t *ent, vec3_t push, qbool dotouch, qbool checkstuck)
Definition sv_phys.c:1521
vec3_t normal
Definition collision.h:13

References trace_t::allsolid, ClipVelocity(), Con_Printf(), CrossProduct, dir, DotProduct, prvm_prog_t::edicts, trace_t::endpos, trace_t::ent, FL_ONGROUND, FL_WATERJUMP, flags, trace_t::fraction, prvm_edict_t::free, groundentity, i, int(), cvar_t::integer, MAX_CLIP_PLANES, plane_t::normal, origin, trace_t::plane, PRVM_EDICT_TO_PROG, PRVM_serveredictedict, PRVM_serveredictfloat, PRVM_serveredictvector, solid, SOLID_TRIGGER, sv_gameplayfix_easierwaterjump, sv_gameplayfix_gravityunaffectedbyticrate, sv_gameplayfix_impactbeforeonground, sv_gameplayfix_nogravityonground, SV_Gravity(), SV_Impact(), SV_PushEntity(), SVVM_prog, time, VectorClear, VectorCopy, VectorNormalize, VectorScale, VectorSet, velocity, and trace_t::worldstartsolid.

Referenced by SV_Physics_Step(), and SV_WalkMove().

◆ SV_GenericHitSuperContentsMask()

int SV_GenericHitSuperContentsMask ( const prvm_edict_t * passedict)

calculates hitsupercontentsmask for a generic qc entity

Definition at line 73 of file sv_phys.c.

74{
75 prvm_prog_t *prog = SVVM_prog;
76 if (passedict)
77 {
80 return dphitcontentsmask;
81 else if (PRVM_serveredictfloat(passedict, solid) == SOLID_SLIDEBOX)
82 {
83 if ((int)PRVM_serveredictfloat(passedict, flags) & FL_MONSTER)
85 else
87 }
88 else if (PRVM_serveredictfloat(passedict, solid) == SOLID_CORPSE)
90 else if (PRVM_serveredictfloat(passedict, solid) == SOLID_TRIGGER)
92 else
94 }
95 else
97}
#define SUPERCONTENTS_BODY
Definition bspfile.h:201
#define SUPERCONTENTS_MONSTERCLIP
Definition bspfile.h:205
#define SUPERCONTENTS_SOLID
Definition bspfile.h:196
#define SUPERCONTENTS_CORPSE
Definition bspfile.h:202
#define SUPERCONTENTS_PLAYERCLIP
Definition bspfile.h:204
float dphitcontentsmask
#define FL_MONSTER
movement is smoothed on the client side by step based interpolation
Definition server.h:362
#define SOLID_SLIDEBOX
touch on edge, but not an onground
Definition server.h:335
#define SOLID_CORPSE
same as SOLID_BBOX, except it behaves as SOLID_NOT against SOLID_SLIDEBOX objects (players/monsters)
Definition server.h:338

References dphitcontentsmask, FL_MONSTER, flags, int(), PRVM_serveredictfloat, solid, SOLID_CORPSE, SOLID_SLIDEBOX, SOLID_TRIGGER, SUPERCONTENTS_BODY, SUPERCONTENTS_CORPSE, SUPERCONTENTS_MONSTERCLIP, SUPERCONTENTS_PLAYERCLIP, SUPERCONTENTS_SOLID, and SVVM_prog.

Referenced by PHYS_NudgeOutOfSolid(), PHYS_TestEntityPosition(), SV_CheckBottom(), SV_movestep(), SV_NudgeOutOfSolid_PivotIsKnownGood(), SV_Physics_Step(), SV_PushEntity(), SV_PushMove(), SV_Trace_Toss(), SV_UserFriction(), SV_WalkMove(), VM_SV_tracebox(), and VM_SV_traceline().

◆ SV_GetPitchSign()

int SV_GetPitchSign ( prvm_prog_t * prog,
prvm_edict_t * ent )

Definition at line 47 of file sv_phys.c.

48{
50 if (
52 ?
53 model->type == mod_alias
54 :
55 (
56 (((unsigned char)PRVM_serveredictfloat(ent, pflags)) & PFLAGS_FULLDYNAMIC)
57 ||
58 ((gamemode == GAME_TENEBRAE) && ((unsigned int)PRVM_serveredictfloat(ent, effects) & (16 | 32)))
59 )
60 )
61 return -1;
62 return 1;
63}
gamemode_t gamemode
Definition com_game.c:26
@ GAME_TENEBRAE
full of evil hackery
Definition com_game.h:41
float effects
string model
float pflags
@ mod_alias
#define PFLAGS_FULLDYNAMIC
Definition protocol.h:108
model_t * SV_GetModelFromEdict(prvm_edict_t *ed)
Definition sv_main.c:1612

References effects, GAME_TENEBRAE, gamemode, mod_alias, model, pflags, PFLAGS_FULLDYNAMIC, PRVM_serveredictfloat, and SV_GetModelFromEdict().

Referenced by SV_CanSeeBox(), SV_GetEntityMatrix(), SV_TraceBox(), SV_TraceLine(), and SV_TracePoint().

◆ SV_Gravity()

static float SV_Gravity ( prvm_edict_t * ent)
static

Definition at line 1410 of file sv_phys.c.

1411{
1412 prvm_prog_t *prog = SVVM_prog;
1413 float ent_gravity;
1414
1415 ent_gravity = PRVM_serveredictfloat(ent, gravity);
1416 if (!ent_gravity)
1417 ent_gravity = 1.0f;
1418 return ent_gravity * sv_gravity.value * sv.frametime;
1419}
cvar_t sv_gravity
Definition sv_main.c:134
double frametime
Definition server.h:77

References server_t::frametime, PRVM_serveredictfloat, sv, sv_gravity, SVVM_prog, and cvar_t::value.

Referenced by SV_FlyMove(), and SV_Physics_Toss().

◆ SV_Impact()

static qbool SV_Impact ( prvm_edict_t * e1,
trace_t * trace )
static

Definition at line 1050 of file sv_phys.c.

1051{
1052 prvm_prog_t *prog = SVVM_prog;
1053 int restorevm_tempstringsbuf_cursize;
1054 int old_self, old_other;
1055 prvm_edict_t *e2 = (prvm_edict_t *)trace->ent;
1056
1057 e1->priv.required->mark = PRVM_EDICT_MARK_WAIT_FOR_SETORIGIN; // -2: setorigin running
1058
1059 old_self = PRVM_serverglobaledict(self);
1060 old_other = PRVM_serverglobaledict(other);
1061 restorevm_tempstringsbuf_cursize = prog->tempstringsbuf.cursize;
1062
1063 VM_SetTraceGlobals(prog, trace);
1064
1065 if (!e1->free && !e2->free && PRVM_serveredictfunction(e1, touch) && PRVM_serveredictfloat(e1, solid) != SOLID_NOT)
1066 {
1070 prog->ExecuteProgram(prog, PRVM_serveredictfunction(e1, touch), "QC function self.touch is missing");
1071 }
1072
1073 if (!e1->free && !e2->free && PRVM_serveredictfunction(e2, touch) && PRVM_serveredictfloat(e2, solid) != SOLID_NOT)
1074 {
1086 prog->ExecuteProgram(prog, PRVM_serveredictfunction(e2, touch), "QC function self.touch is missing");
1087 }
1088
1089 PRVM_serverglobaledict(self) = old_self;
1090 PRVM_serverglobaledict(other) = old_other;
1091 prog->tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize;
1092
1094 {
1095 e1->priv.required->mark = 0;
1096 return false;
1097 }
1099 {
1100 e1->priv.required->mark = 0;
1101 return true;
1102 }
1103 else
1104 {
1105 Con_Printf(CON_ERROR "The edict mark had been overwritten! Please debug this.\n");
1106 return true;
1107 }
1108}
#define CON_ERROR
Definition console.h:102
float trace_dphitcontents
entity trace_ent
entity other
float trace_dpstartcontents
string trace_dphittexturename
vector trace_endpos
float trace_dphitq3surfaceflags
vector trace_plane_normal
float trace_plane_dist
#define VectorNegate(a, b)
Definition mathlib.h:95
#define PRVM_EDICT_MARK_SETORIGIN_CAUGHT
Definition progsvm.h:79
#define PRVM_serverglobalstring(fieldname)
Definition progsvm.h:179
#define PRVM_EDICT_MARK_WAIT_FOR_SETORIGIN
Definition progsvm.h:78
#define PRVM_serverglobalvector(fieldname)
Definition progsvm.h:178
void VM_SetTraceGlobals(prvm_prog_t *prog, const trace_t *trace)
Definition prvm_cmds.c:5228
#define SOLID_NOT
no interaction with other objects
Definition server.h:332
int mark
mark for the leak detector
Definition progsvm.h:85
union prvm_edict_t::@29 priv
prvm_edict_private_t * required
Definition progsvm.h:101
vec_t dist
Definition collision.h:14

References CON_ERROR, Con_Printf(), sizebuf_t::cursize, plane_t::dist, trace_t::ent, prvm_prog_t::ExecuteProgram, prvm_edict_t::free, prvm_edict_private_t::mark, plane_t::normal, origin, other, trace_t::plane, prvm_edict_t::priv, PRVM_EDICT_MARK_SETORIGIN_CAUGHT, PRVM_EDICT_MARK_WAIT_FOR_SETORIGIN, PRVM_EDICT_TO_PROG, PRVM_serveredictfloat, PRVM_serveredictfunction, PRVM_serveredictvector, PRVM_serverglobaledict, PRVM_serverglobalfloat, PRVM_serverglobalstring, PRVM_serverglobalvector, prvm_edict_t::required, self, solid, SOLID_NOT, sv, SVVM_prog, prvm_prog_t::tempstringsbuf, server_t::time, time, trace_dphitcontents, trace_dphitq3surfaceflags, trace_dphittexturename, trace_dpstartcontents, trace_endpos, trace_ent, trace_plane_dist, trace_plane_normal, VectorCopy, VectorNegate, and VM_SetTraceGlobals().

Referenced by SV_FlyMove(), and SV_PushEntity().

◆ SV_LinkEdict()

void SV_LinkEdict ( prvm_edict_t * ent)

Needs to be called any time an entity changes origin, mins, maxs, or solid sets ent->v.absmin and ent->v.absmax call TouchAreaGrid as well to fire triggers that overlap the box

Definition at line 804 of file sv_phys.c.

805{
806 prvm_prog_t *prog = SVVM_prog;
807 model_t *model;
808 vec3_t mins, maxs, entmins, entmaxs, entangles;
809 int modelindex;
810
811 if (ent == prog->edicts)
812 return; // don't add the world
813
814 if (ent->free)
815 return;
816
819 {
820 Con_Printf("edict %i: SOLID_BSP with invalid modelindex!\n", PRVM_NUM_FOR_EDICT(ent));
821 modelindex = 0;
822 }
824
825 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
826 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time);
827 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
828
829// set the abs box
830
832 {
833 // TODO maybe should do this for rotating SOLID_BSP too? Would behave better with rotating doors
834 // TODO special handling for spheres?
835 VectorCopy(PRVM_serveredictvector(ent, mins), entmins);
836 VectorCopy(PRVM_serveredictvector(ent, maxs), entmaxs);
837 VectorCopy(PRVM_serveredictvector(ent, angles), entangles);
838 RotateBBox(entmins, entmaxs, entangles, mins, maxs);
841 }
842 else if (PRVM_serveredictfloat(ent, solid) == SOLID_BSP)
843 {
844 if (model != NULL)
845 {
846 if (!model->TraceBox)
847 Con_DPrintf("edict %i: SOLID_BSP with non-collidable model\n", PRVM_NUM_FOR_EDICT(ent));
848
850 {
851 VectorAdd(PRVM_serveredictvector(ent, origin), model->rotatedmins, mins);
852 VectorAdd(PRVM_serveredictvector(ent, origin), model->rotatedmaxs, maxs);
853 }
855 {
858 }
859 else
860 {
861 VectorAdd(PRVM_serveredictvector(ent, origin), model->normalmins, mins);
862 VectorAdd(PRVM_serveredictvector(ent, origin), model->normalmaxs, maxs);
863 }
864 }
865 else
866 {
867 // SOLID_BSP with no model is valid, mainly because some QC setup code does so temporarily
870 }
871 }
872 else
873 {
876 }
877
879 {
880 if ((int)PRVM_serveredictfloat(ent, flags) & FL_ITEM)
881 {
882 // to make items easier to pick up and allow them to be grabbed off
883 // of shelves, the abs sizes are expanded
884 mins[0] -= 15;
885 mins[1] -= 15;
886 mins[2] -= 1;
887 maxs[0] += 15;
888 maxs[1] += 15;
889 maxs[2] += 1;
890 }
891 else
892 {
893 // because movement is clipped an epsilon away from an actual edge,
894 // we must fully check even when bounding boxes don't quite touch
895 mins[0] -= 1;
896 mins[1] -= 1;
897 mins[2] -= 1;
898 maxs[0] += 1;
899 maxs[1] += 1;
900 maxs[2] += 1;
901 }
902 }
903
906
908}
void Con_DPrintf(const char *fmt,...)
A Con_Printf that only shows up if the "developer" cvar is set.
Definition console.c:1544
float movetype
float modelindex
vector avelocity
#define VectorAdd(a, b, out)
Definition mathlib.h:100
void VM_UpdateEdictSkeleton(prvm_prog_t *prog, prvm_edict_t *ed, const struct model_s *edmodel, const struct frameblend_s *frameblend)
void VM_GenerateFrameGroupBlend(prvm_prog_t *prog, struct framegroupblend_s *framegroupblend, const prvm_edict_t *ed)
void VM_FrameBlendFromFrameGroupBlend(struct frameblend_s *frameblend, const struct framegroupblend_s *framegroupblend, const struct model_s *model, double curtime)
#define MAX_MODELS
max number of models loaded at once (including during level transitions)
Definition qdefs.h:106
#define MOVETYPE_PHYSICS
indicates this object is physics controlled
Definition server.h:326
cvar_t sv_areagrid_link_SOLID_NOT
Definition sv_main.c:74
model_t * SV_GetModelByIndex(int modelindex)
Definition sv_main.c:1607
cvar_t sv_legacy_bbox_expand
Definition sv_main.c:139
#define FL_ITEM
Definition server.h:365
#define SOLID_BSP
bsp clip, touch on edge, block
Definition server.h:336
struct edict_engineprivate_s * server
FIXME: this server pointer really means world, not server (it is used by both server qc and client qc...
Definition progsvm.h:106
static void RotateBBox(const vec3_t mins, const vec3_t maxs, const vec3_t angles, vec3_t rotatedmins, vec3_t rotatedmaxs)
Definition sv_phys.c:767
void World_LinkEdict(world_t *world, prvm_edict_t *ent, const vec3_t mins, const vec3_t maxs, qbool link_solid_not)
Definition world.c:320

References absmax, absmin, angles, avelocity, Con_DPrintf(), Con_Printf(), prvm_prog_t::edicts, FL_ITEM, flags, prvm_edict_t::free, int(), cvar_t::integer, MAX_MODELS, maxs, mins, model, modelindex, movetype, MOVETYPE_PHYSICS, NULL, origin, prvm_edict_t::priv, PRVM_NUM_FOR_EDICT, PRVM_serveredictfloat, PRVM_serveredictvector, RotateBBox(), prvm_edict_t::server, solid, SOLID_BSP, sv, sv_areagrid_link_SOLID_NOT, SV_GetModelByIndex(), sv_legacy_bbox_expand, SVVM_prog, server_t::time, VectorAdd, VectorCopy, VM_FrameBlendFromFrameGroupBlend(), VM_GenerateFrameGroupBlend(), VM_UpdateEdictSkeleton(), server_t::world, and World_LinkEdict().

Referenced by PRVM_ED_LoadFromFile(), SetMinMaxSize(), SV_Ent_Create_f(), SV_Loadgame_f(), SV_movestep(), SV_Physics_ClientEntity(), SV_Physics_Entity(), SV_Physics_Follow(), SV_Physics_Step(), SV_PushEntity(), SV_PushMove(), SV_StepDirection(), SV_WalkMove(), SVVM_end_increase_edicts(), VM_nudgeoutofsolid(), VM_SV_copyentity(), VM_SV_droptofloor(), and VM_SV_setorigin().

◆ SV_LinkEdict_TouchAreaGrid()

void SV_LinkEdict_TouchAreaGrid ( prvm_edict_t * ent)

Definition at line 727 of file sv_phys.c.

728{
729 prvm_prog_t *prog = SVVM_prog;
730 int i, numtouchedicts, old_self, old_other;
731 prvm_edict_t *touch;
732 static prvm_edict_t *touchedicts[MAX_EDICTS];
733
734 if (ent == prog->edicts)
735 return; // don't add the world
736
737 if (ent->free)
738 return;
739
741 return;
742
743 // build a list of edicts to touch, because the link loop can be corrupted
744 // by IncreaseEdicts called during touch functions
745 numtouchedicts = SV_EntitiesInBox(ent->priv.server->areamins, ent->priv.server->areamaxs, MAX_EDICTS, touchedicts);
746 if (numtouchedicts > MAX_EDICTS)
747 {
748 // this never happens
749 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
750 numtouchedicts = MAX_EDICTS;
751 }
752
753 old_self = PRVM_serverglobaledict(self);
754 old_other = PRVM_serverglobaledict(other);
755 for (i = 0;i < numtouchedicts;i++)
756 {
757 touch = touchedicts[i];
758 if (touch != ent && (int)PRVM_serveredictfloat(touch, solid) == SOLID_TRIGGER && PRVM_serveredictfunction(touch, touch))
759 {
761 }
762 }
763 PRVM_serverglobaledict(self) = old_self;
764 PRVM_serverglobaledict(other) = old_other;
765}
#define MAX_EDICTS
max number of objects in game world at once (32768 protocol limit)
Definition qdefs.h:105
void SV_LinkEdict_TouchAreaGrid_Call(prvm_edict_t *touch, prvm_edict_t *ent)
Definition sv_phys.c:705
int SV_EntitiesInBox(const vec3_t mins, const vec3_t maxs, int maxedicts, prvm_edict_t **resultedicts)
Definition sv_phys.c:673

References Con_Printf(), prvm_prog_t::edicts, prvm_edict_t::free, i, MAX_EDICTS, other, prvm_edict_t::priv, PRVM_serveredictfloat, PRVM_serveredictfunction, PRVM_serverglobaledict, self, prvm_edict_t::server, solid, SOLID_NOT, SOLID_TRIGGER, SV_EntitiesInBox(), SV_LinkEdict_TouchAreaGrid_Call(), and SVVM_prog.

Referenced by SV_movestep(), SV_Physics(), SV_Physics_ClientEntity(), SV_Physics_Entity(), SV_Physics_Step(), SV_PushEntity(), SV_PushMove(), SV_StepDirection(), and SV_WalkMove().

◆ SV_LinkEdict_TouchAreaGrid_Call()

void SV_LinkEdict_TouchAreaGrid_Call ( prvm_edict_t * touch,
prvm_edict_t * ent )

Definition at line 705 of file sv_phys.c.

References prvm_prog_t::ExecuteProgram, origin, other, PRVM_EDICT_TO_PROG, PRVM_serveredictfunction, PRVM_serveredictvector, PRVM_serverglobaledict, PRVM_serverglobalfloat, PRVM_serverglobalstring, PRVM_serverglobalvector, self, sv, SVVM_prog, server_t::time, time, trace_allsolid, trace_dphitcontents, trace_dphitq3surfaceflags, trace_dphittexturename, trace_dpstartcontents, trace_endpos, trace_ent, trace_fraction, trace_inopen, trace_inwater, trace_plane_dist, trace_plane_normal, trace_startsolid, VectorCopy, and VectorSet.

Referenced by SV_LinkEdict_TouchAreaGrid().

◆ SV_NudgeOutOfSolid_PivotIsKnownGood()

static qbool SV_NudgeOutOfSolid_PivotIsKnownGood ( prvm_edict_t * ent,
vec3_t pivot )
static

Definition at line 1430 of file sv_phys.c.

1431{
1432 prvm_prog_t *prog = SVVM_prog;
1433 int bump;
1434 trace_t stucktrace;
1435 vec3_t stuckorigin;
1436 vec3_t stuckmins, stuckmaxs;
1437 vec3_t goodmins, goodmaxs;
1438 vec3_t testorigin;
1439 vec_t nudge;
1440 vec3_t move;
1441 VectorCopy(PRVM_serveredictvector(ent, origin), stuckorigin);
1442 VectorCopy(PRVM_serveredictvector(ent, mins), stuckmins);
1443 VectorCopy(PRVM_serveredictvector(ent, maxs), stuckmaxs);
1444 VectorCopy(pivot, goodmins);
1445 VectorCopy(pivot, goodmaxs);
1446 for (bump = 0;bump < 6;bump++)
1447 {
1448 int coord = 2-(bump >> 1);
1449 //int coord = (bump >> 1);
1450 int dir = (bump & 1);
1451 int subbump;
1452
1453 for(subbump = 0; ; ++subbump)
1454 {
1455 VectorCopy(stuckorigin, testorigin);
1456 if(dir)
1457 {
1458 // pushing maxs
1459 testorigin[coord] += stuckmaxs[coord] - goodmaxs[coord];
1460 }
1461 else
1462 {
1463 // pushing mins
1464 testorigin[coord] += stuckmins[coord] - goodmins[coord];
1465 }
1466
1467 stucktrace = SV_TraceBox(stuckorigin, goodmins, goodmaxs, testorigin, MOVE_NOMONSTERS, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value);
1468 if (stucktrace.bmodelstartsolid)
1469 {
1470 // BAD BAD, can't fix that
1471 return false;
1472 }
1473
1474 if (stucktrace.fraction >= 1)
1475 break; // it WORKS!
1476
1477 if(subbump >= 10)
1478 {
1479 // BAD BAD, can't fix that
1480 return false;
1481 }
1482
1483 // we hit something... let's move out of it
1484 VectorSubtract(stucktrace.endpos, testorigin, move);
1485 nudge = DotProduct(stucktrace.plane.normal, move) + 0.03125f; // FIXME cvar this constant
1486 VectorMA(stuckorigin, nudge, stucktrace.plane.normal, stuckorigin);
1487 }
1488 /*
1489 if(subbump > 0)
1490 Con_Printf("subbump: %d\n", subbump);
1491 */
1492
1493 if(dir)
1494 {
1495 // pushing maxs
1496 goodmaxs[coord] = stuckmaxs[coord];
1497 }
1498 else
1499 {
1500 // pushing mins
1501 goodmins[coord] = stuckmins[coord];
1502 }
1503 }
1504
1505 // WE WIN
1506 VectorCopy(stuckorigin, PRVM_serveredictvector(ent, origin));
1507
1508 return true;
1509}
cvar_t collision_extendmovelength
Definition collision.c:14
#define VectorSubtract(a, b, out)
Definition mathlib.h:99
float vec_t
Definition qtypes.h:68
qbool bmodelstartsolid
Definition collision.h:30
int SV_GenericHitSuperContentsMask(const prvm_edict_t *passedict)
calculates hitsupercontentsmask for a generic qc entity
Definition sv_phys.c:73
trace_t SV_TraceBox(const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int type, prvm_edict_t *passedict, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask, float extend)
traces a box move against worldmodel and all entities in the specified area
Definition sv_phys.c:414
#define MOVE_NOMONSTERS
Definition world.h:29

References trace_t::bmodelstartsolid, collision_extendmovelength, dir, DotProduct, trace_t::endpos, trace_t::fraction, maxs, mins, MOVE_NOMONSTERS, plane_t::normal, origin, trace_t::plane, PRVM_serveredictvector, SV_GenericHitSuperContentsMask(), SV_TraceBox(), SVVM_prog, cvar_t::value, VectorCopy, VectorMA, and VectorSubtract.

Referenced by SV_PushMove().

◆ SV_Physics()

void SV_Physics ( void )

Definition at line 3013 of file sv_phys.c.

3014{
3015 prvm_prog_t *prog = SVVM_prog;
3016 int i;
3017 prvm_edict_t *ent;
3018
3019 // free memory for resources that are no longer referenced
3021
3022// let the progs know that a new frame has started
3027 prog->ExecuteProgram(prog, PRVM_serverfunction(StartFrame), "QC function StartFrame is missing");
3028
3029#ifdef USEODE
3030 // run physics engine
3032#endif
3033
3034//
3035// treat each object in turn
3036//
3037
3038 // if force_retouch, relink all the entities
3040 for (i = 1, ent = PRVM_EDICT_NUM(i);i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
3041 if (!ent->free)
3042 SV_LinkEdict_TouchAreaGrid(ent); // force retouch even for stationary
3043
3045 {
3046 // run physics on the client entities in 3 stages
3047 for (i = 1, ent = PRVM_EDICT_NUM(i), host_client = svs.clients;i <= svs.maxclients;i++, ent = PRVM_NEXT_EDICT(ent), host_client++)
3048 if (!ent->free)
3050
3051 for (i = 1, ent = PRVM_EDICT_NUM(i), host_client = svs.clients;i <= svs.maxclients;i++, ent = PRVM_NEXT_EDICT(ent), host_client++)
3052 if (!ent->free)
3054
3055 for (i = 1, ent = PRVM_EDICT_NUM(i), host_client = svs.clients;i <= svs.maxclients;i++, ent = PRVM_NEXT_EDICT(ent), host_client++)
3056 if (!ent->free)
3058 }
3059 else
3060 {
3061 // run physics on the client entities
3062 for (i = 1, ent = PRVM_EDICT_NUM(i), host_client = svs.clients;i <= svs.maxclients;i++, ent = PRVM_NEXT_EDICT(ent), host_client++)
3063 {
3064 if (!ent->free)
3065 {
3069 }
3070 }
3071 }
3072
3073 // run physics on all the non-client entities
3075 {
3076 for (;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
3077 if (!ent->free)
3078 SV_Physics_Entity(ent);
3079 // make a second pass to see if any ents spawned this frame and make
3080 // sure they run their move/think
3082 for (i = svs.maxclients + 1, ent = PRVM_EDICT_NUM(i);i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
3083 if (!ent->priv.server->move && !ent->free)
3084 SV_Physics_Entity(ent);
3085 }
3086
3089
3090 // LadyHavoc: endframe support
3091 if (PRVM_serverfunction(EndFrame))
3092 {
3096 prog->ExecuteProgram(prog, PRVM_serverfunction(EndFrame), "QC function EndFrame is missing");
3097 }
3098
3099 // decrement prog->num_edicts if the highest number entities died
3100 for (;PRVM_ED_CanAlloc(prog, PRVM_EDICT_NUM(prog->num_edicts - 1));prog->num_edicts--);
3101
3103 sv.time += sv.frametime;
3104}
float frametime
#define max(A, B)
Definition mathlib.h:38
float force_retouch
Definition progsdefs.qc:19
#define PRVM_NEXT_EDICT(e)
Definition progsvm.h:873
void PRVM_GarbageCollection(prvm_prog_t *prog)
#define PRVM_serverfunction(funcname)
Definition progsvm.h:182
qbool PRVM_ED_CanAlloc(prvm_prog_t *prog, prvm_edict_t *e)
Definition prvm_edict.c:243
cvar_t sv_gameplayfix_delayprojectiles
Definition sv_main.c:106
cvar_t sv_gameplayfix_consistentplayerprethink
Definition sv_main.c:105
cvar_t sv_freezenonclients
Definition sv_main.c:102
server_static_t svs
persistant server info
Definition sv_main.c:224
client_t * host_client
Definition sv_main.c:29
struct client_s * clients
client slots
Definition server.h:30
int maxclients
number of svs.clients slots (updated by maxplayers command)
Definition server.h:28
static void SV_Physics_ClientEntity_PreThink(prvm_edict_t *ent)
Definition sv_phys.c:2853
static void SV_Physics_ClientEntity_PostThink(prvm_edict_t *ent)
Definition sv_phys.c:2882
static void SV_Physics_ClientEntity(prvm_edict_t *ent)
Definition sv_phys.c:2919
static void SV_Physics_Entity(prvm_edict_t *ent)
Definition sv_phys.c:2682
void SV_LinkEdict_TouchAreaGrid(prvm_edict_t *ent)
Definition sv_phys.c:727
void World_Physics_Frame(world_t *world, double frametime, double gravity)

References server_static_t::clients, prvm_prog_t::edicts, prvm_prog_t::ExecuteProgram, force_retouch, frametime, server_t::frametime, prvm_edict_t::free, host_client, i, cvar_t::integer, max, server_static_t::maxclients, prvm_prog_t::num_edicts, other, PRVM_ED_CanAlloc(), PRVM_EDICT_NUM, PRVM_EDICT_TO_PROG, PRVM_GarbageCollection(), PRVM_NEXT_EDICT, PRVM_serverfunction, PRVM_serverglobaledict, PRVM_serverglobalfloat, self, sv, sv_freezenonclients, sv_gameplayfix_consistentplayerprethink, sv_gameplayfix_delayprojectiles, sv_gravity, SV_LinkEdict_TouchAreaGrid(), SV_Physics_ClientEntity(), SV_Physics_ClientEntity_PostThink(), SV_Physics_ClientEntity_PreThink(), SV_Physics_Entity(), svs, SVVM_prog, server_t::time, time, cvar_t::value, server_t::world, and World_Physics_Frame().

Referenced by SV_Frame(), SV_SpawnServer(), and SV_ThreadFunc().

◆ SV_Physics_ClientEntity()

static void SV_Physics_ClientEntity ( prvm_edict_t * ent)
static

Definition at line 2919 of file sv_phys.c.

2920{
2921 prvm_prog_t *prog = SVVM_prog;
2922 // don't do physics on disconnected clients, FrikBot relies on this
2923 if (!host_client->begun)
2924 {
2925 memset(&host_client->cmd, 0, sizeof(host_client->cmd));
2926 return;
2927 }
2928
2929 // make sure the velocity is sane (not a NaN)
2930 SV_CheckVelocity(ent);
2931
2932 switch ((int) PRVM_serveredictfloat(ent, movetype))
2933 {
2934 case MOVETYPE_PUSH:
2935 case MOVETYPE_FAKEPUSH:
2936 SV_Physics_Pusher (ent);
2937 break;
2938 case MOVETYPE_NONE:
2939 // LadyHavoc: manually inlined the thinktime check here because MOVETYPE_NONE is used on so many objects
2941 SV_RunThink (ent);
2942 break;
2943 case MOVETYPE_FOLLOW:
2944 SV_RunThink (ent);
2945 if (host_client->clmovement_inputtimeout <= 0) // don't run physics here if running asynchronously
2946 SV_Physics_Follow (ent);
2947 break;
2948 case MOVETYPE_NOCLIP:
2949 SV_RunThink(ent);
2950 if (host_client->clmovement_inputtimeout <= 0) // don't run physics here if running asynchronously
2951 {
2952 SV_CheckWater(ent);
2955 }
2956 break;
2957 case MOVETYPE_STEP:
2958 if (host_client->clmovement_inputtimeout <= 0) // don't run physics here if running asynchronously
2959 SV_Physics_Step (ent);
2960 if (SV_RunThink(ent))
2961 if (ent->priv.server->waterposition_forceupdate || !VectorCompare(PRVM_serveredictvector(ent, origin), ent->priv.server->waterposition_origin))
2962 {
2963 ent->priv.server->waterposition_forceupdate = false;
2964 VectorCopy(PRVM_serveredictvector(ent, origin), ent->priv.server->waterposition_origin);
2966 }
2967 break;
2968 case MOVETYPE_WALK:
2969 SV_RunThink (ent);
2970 // don't run physics here if running asynchronously
2972 SV_WalkMove (ent);
2973 break;
2974 case MOVETYPE_TOSS:
2975 case MOVETYPE_BOUNCE:
2978 // regular thinking
2979 SV_RunThink (ent);
2980 if (host_client->clmovement_inputtimeout <= 0) // don't run physics here if running asynchronously
2981 SV_Physics_Toss (ent);
2982 break;
2983 case MOVETYPE_FLY:
2985 SV_RunThink (ent);
2986 if (host_client->clmovement_inputtimeout <= 0) // don't run physics here if running asynchronously
2987 SV_WalkMove (ent);
2988 break;
2989 case MOVETYPE_PHYSICS:
2990 SV_RunThink (ent);
2991 break;
2992 default:
2994 break;
2995 Con_Printf ("SV_Physics_ClientEntity: bad movetype %i\n", (int)PRVM_serveredictfloat(ent, movetype));
2996 break;
2997 }
2998
2999 SV_CheckVelocity (ent);
3000
3001 SV_LinkEdict(ent);
3003
3004 SV_CheckVelocity (ent);
3005}
float nextthink
#define VectorCompare(a, b)
Definition mathlib.h:113
#define MOVETYPE_FAKEPUSH
tenebrae's push that doesn't push
Definition server.h:325
#define MOVETYPE_TOSS
gravity
Definition server.h:318
#define MOVETYPE_NOCLIP
Definition server.h:320
#define MOVETYPE_BOUNCE
Definition server.h:322
#define MOVETYPE_WALK
gravity
Definition server.h:315
#define MOVETYPE_NONE
never moves
Definition server.h:312
#define MOVETYPE_FOLLOW
track movement of aiment
Definition server.h:324
#define MOVETYPE_BOUNCEMISSILE
bounce w/o gravity
Definition server.h:323
#define MOVETYPE_FLY
Definition server.h:317
#define MOVETYPE_USER_FIRST
user defined movetypes
Definition server.h:328
#define MOVETYPE_FLY_WORLDONLY
like MOVETYPE_FLY, but uses MOVE_WORLDONLY for all its traces; objects of this movetype better be SOL...
Definition server.h:327
#define MOVETYPE_PUSH
no clip to world, push and crush
Definition server.h:319
#define MOVETYPE_USER_LAST
Definition server.h:329
#define MOVETYPE_STEP
gravity, special edge handling, special step based client side interpolation
Definition server.h:316
#define MOVETYPE_FLYMISSILE
extra size to monsters
Definition server.h:321
float clmovement_inputtimeout
this is used by sv_clmovement_inputtimeout code
Definition server.h:229
qbool begun
false = don't send datagrams
Definition server.h:193
usercmd_t cmd
movement
Definition server.h:216
static void SV_Physics_Pusher(prvm_edict_t *ent)
Definition sv_phys.c:1908
static qbool SV_CheckWater(prvm_edict_t *ent)
Definition sv_phys.c:2012
static void SV_WalkMove(prvm_edict_t *ent)
Definition sv_phys.c:2152
static qbool SV_RunThink(prvm_edict_t *ent)
Definition sv_phys.c:1015
static void SV_Physics_Step(prvm_edict_t *ent)
Definition sv_phys.c:2615
void SV_Physics_Toss(prvm_edict_t *ent)
Definition sv_phys.c:2459
static void SV_Physics_Follow(prvm_edict_t *ent)
Definition sv_phys.c:2361
void SV_LinkEdict(prvm_edict_t *ent)
Definition sv_phys.c:804
void SV_CheckVelocity(prvm_edict_t *ent)
Definition sv_phys.c:965
static void SV_CheckWaterTransition(prvm_edict_t *ent)
Definition sv_phys.c:2410

References angles, avelocity, client_t::begun, client_t::clmovement_inputtimeout, client_t::cmd, Con_Printf(), server_t::frametime, host_client, movetype, MOVETYPE_BOUNCE, MOVETYPE_BOUNCEMISSILE, MOVETYPE_FAKEPUSH, MOVETYPE_FLY, MOVETYPE_FLY_WORLDONLY, MOVETYPE_FLYMISSILE, MOVETYPE_FOLLOW, MOVETYPE_NOCLIP, MOVETYPE_NONE, MOVETYPE_PHYSICS, MOVETYPE_PUSH, MOVETYPE_STEP, MOVETYPE_TOSS, MOVETYPE_USER_FIRST, MOVETYPE_USER_LAST, MOVETYPE_WALK, nextthink, origin, prvm_edict_t::priv, PRVM_serveredictfloat, PRVM_serveredictvector, prvm_edict_t::server, sv, SV_CheckVelocity(), SV_CheckWater(), SV_CheckWaterTransition(), SV_LinkEdict(), SV_LinkEdict_TouchAreaGrid(), SV_Physics_Follow(), SV_Physics_Pusher(), SV_Physics_Step(), SV_Physics_Toss(), SV_RunThink(), SV_WalkMove(), SVVM_prog, server_t::time, VectorCompare, VectorCopy, VectorMA, and velocity.

Referenced by SV_Physics().

◆ SV_Physics_ClientEntity_NoThink()

static void SV_Physics_ClientEntity_NoThink ( prvm_edict_t * ent)
static

Definition at line 2759 of file sv_phys.c.

2760{
2761 prvm_prog_t *prog = SVVM_prog;
2762
2763 // don't run think at all, that is done during server frames
2764 // instead, call the movetypes directly so they match client input
2765
2766 // This probably only makes sense for CSQC-networked (SendEntity field set) player entities
2767 switch ((int) PRVM_serveredictfloat(ent, movetype))
2768 {
2769 case MOVETYPE_PUSH:
2770 case MOVETYPE_FAKEPUSH:
2771 // push physics relies heavily on think times and calls, and so cannot be predicted currently
2772 Con_Printf ("SV_Physics_ClientEntity_NoThink: bad movetype %i\n", (int)PRVM_serveredictfloat(ent, movetype));
2773 break;
2774 case MOVETYPE_NONE:
2775 break;
2776 case MOVETYPE_FOLLOW:
2777 SV_Physics_Follow (ent);
2778 break;
2779 case MOVETYPE_NOCLIP:
2782 break;
2783 case MOVETYPE_STEP:
2784 SV_Physics_Step (ent);
2785 break;
2786 case MOVETYPE_WALK:
2787 SV_WalkMove (ent);
2788 break;
2789 case MOVETYPE_TOSS:
2790 case MOVETYPE_BOUNCE:
2793 SV_Physics_Toss (ent);
2794 break;
2795 case MOVETYPE_FLY:
2797 SV_WalkMove (ent);
2798 break;
2799 case MOVETYPE_PHYSICS:
2800 break;
2801 default:
2803 break;
2804 Con_Printf ("SV_Physics_ClientEntity_NoThink: bad movetype %i\n", (int)PRVM_serveredictfloat(ent, movetype));
2805 break;
2806 }
2807}

References angles, avelocity, Con_Printf(), server_t::frametime, movetype, MOVETYPE_BOUNCE, MOVETYPE_BOUNCEMISSILE, MOVETYPE_FAKEPUSH, MOVETYPE_FLY, MOVETYPE_FLY_WORLDONLY, MOVETYPE_FLYMISSILE, MOVETYPE_FOLLOW, MOVETYPE_NOCLIP, MOVETYPE_NONE, MOVETYPE_PHYSICS, MOVETYPE_PUSH, MOVETYPE_STEP, MOVETYPE_TOSS, MOVETYPE_USER_FIRST, MOVETYPE_USER_LAST, MOVETYPE_WALK, origin, PRVM_serveredictfloat, PRVM_serveredictvector, sv, SV_Physics_Follow(), SV_Physics_Step(), SV_Physics_Toss(), SV_WalkMove(), SVVM_prog, VectorMA, and velocity.

Referenced by SV_Physics_ClientMove().

◆ SV_Physics_ClientEntity_PostThink()

static void SV_Physics_ClientEntity_PostThink ( prvm_edict_t * ent)
static

Definition at line 2882 of file sv_phys.c.

2883{
2884 prvm_prog_t *prog = SVVM_prog;
2885 // don't do physics on disconnected clients, FrikBot relies on this
2886 if (!host_client->begun)
2887 return;
2888
2889 // make sure the velocity is sane (not a NaN)
2890 SV_CheckVelocity(ent);
2891
2892 // call standard player post-think
2895 prog->ExecuteProgram(prog, PRVM_serverfunction(PlayerPostThink), "QC function PlayerPostThink is missing");
2896
2897 // make sure the velocity is still sane (not a NaN)
2898 SV_CheckVelocity(ent);
2899
2901 {
2902 // angle fixing was requested by physics code...
2903 // so store the current angles for later use
2906
2907 // and clear fixangle for the next frame
2909 }
2910
2911 // decrement the countdown variable used to decide when to go back to
2912 // synchronous physics
2915 else
2917}
float fixangle
Definition progsdefs.qc:160
qbool fixangle_angles_set
Definition server.h:293
vec3_t fixangle_angles
Definition server.h:294

References angles, client_t::begun, client_t::clmovement_inputtimeout, prvm_prog_t::ExecuteProgram, fixangle, client_t::fixangle_angles, client_t::fixangle_angles_set, server_t::frametime, host_client, PRVM_EDICT_TO_PROG, PRVM_serveredictfloat, PRVM_serveredictvector, PRVM_serverfunction, PRVM_serverglobaledict, PRVM_serverglobalfloat, self, sv, SV_CheckVelocity(), SVVM_prog, server_t::time, time, and VectorCopy.

Referenced by SV_Physics().

◆ SV_Physics_ClientEntity_PreThink()

static void SV_Physics_ClientEntity_PreThink ( prvm_edict_t * ent)
static

Definition at line 2853 of file sv_phys.c.

2854{
2855 prvm_prog_t *prog = SVVM_prog;
2856 // don't do physics on disconnected clients, FrikBot relies on this
2857 if (!host_client->begun)
2858 return;
2859
2860 // make sure the velocity is sane (not a NaN)
2861 SV_CheckVelocity(ent);
2862
2863 // don't run physics here if running asynchronously
2865 {
2867 //host_client->cmd.time = max(host_client->cmd.time, sv.time);
2868 }
2869
2870 // make sure the velocity is still sane (not a NaN)
2871 SV_CheckVelocity(ent);
2872
2873 // call standard client pre-think
2876 prog->ExecuteProgram(prog, PRVM_serverfunction(PlayerPreThink), "QC function PlayerPreThink is missing");
2877
2878 // make sure the velocity is still sane (not a NaN)
2879 SV_CheckVelocity(ent);
2880}
void SV_PlayerPhysics(void)
Definition sv_user.c:571

References client_t::begun, client_t::clmovement_inputtimeout, prvm_prog_t::ExecuteProgram, host_client, PRVM_EDICT_TO_PROG, PRVM_serverfunction, PRVM_serverglobaledict, PRVM_serverglobalfloat, self, sv, SV_CheckVelocity(), SV_PlayerPhysics(), SVVM_prog, server_t::time, and time.

Referenced by SV_Physics().

◆ SV_Physics_ClientMove()

void SV_Physics_ClientMove ( void )

Definition at line 2810 of file sv_phys.c.

2811{
2812 prvm_prog_t *prog = SVVM_prog;
2813 prvm_edict_t *ent;
2814 ent = host_client->edict;
2815
2816 // call player physics, this needs the proper frametime
2819
2820 // call standard client pre-think, with frametime = 0
2824 prog->ExecuteProgram(prog, PRVM_serverfunction(PlayerPreThink), "QC function PlayerPreThink is missing");
2826
2827 // make sure the velocity is sane (not a NaN)
2828 SV_CheckVelocity(ent);
2829
2830 // perform movetype behaviour
2831 // note: will always be MOVETYPE_WALK if disableclientprediction = 0
2833
2834 // call standard player post-think, with frametime = 0
2838 prog->ExecuteProgram(prog, PRVM_serverfunction(PlayerPostThink), "QC function PlayerPostThink is missing");
2840
2842 {
2843 // angle fixing was requested by physics code...
2844 // so store the current angles for later use
2847
2848 // and clear fixangle for the next frame
2850 }
2851}
prvm_edict_t * edict
PRVM_EDICT_NUM(clientnum+1)
Definition server.h:221
static void SV_Physics_ClientEntity_NoThink(prvm_edict_t *ent)
Definition sv_phys.c:2759

References angles, client_t::edict, prvm_prog_t::ExecuteProgram, fixangle, client_t::fixangle_angles, client_t::fixangle_angles_set, frametime, server_t::frametime, host_client, PRVM_EDICT_TO_PROG, PRVM_serveredictfloat, PRVM_serveredictvector, PRVM_serverfunction, PRVM_serverglobaledict, PRVM_serverglobalfloat, self, sv, SV_CheckVelocity(), SV_Physics_ClientEntity_NoThink(), SV_PlayerPhysics(), SVVM_prog, server_t::time, time, and VectorCopy.

Referenced by SV_ExecuteClientMoves().

◆ SV_Physics_Entity()

static void SV_Physics_Entity ( prvm_edict_t * ent)
static

Definition at line 2682 of file sv_phys.c.

2683{
2684 prvm_prog_t *prog = SVVM_prog;
2685 // don't run think/move on newly spawned projectiles as it messes up
2686 // movement interpolation and rocket trails, and is inconsistent with
2687 // respect to entities spawned in the same frame
2688 // (if an ent spawns a higher numbered ent, it moves in the same frame,
2689 // but if it spawns a lower numbered ent, it doesn't - this never moves
2690 // ents in the first frame regardless)
2691 qbool runmove = ent->priv.server->move;
2692 ent->priv.server->move = true;
2693 if (!runmove && sv_gameplayfix_delayprojectiles.integer > 0)
2694 return;
2695 switch ((int) PRVM_serveredictfloat(ent, movetype))
2696 {
2697 case MOVETYPE_PUSH:
2698 case MOVETYPE_FAKEPUSH:
2699 SV_Physics_Pusher (ent);
2700 break;
2701 case MOVETYPE_NONE:
2702 // LadyHavoc: manually inlined the thinktime check here because MOVETYPE_NONE is used on so many objects
2704 SV_RunThink (ent);
2705 break;
2706 case MOVETYPE_FOLLOW:
2707 if(SV_RunThink(ent))
2708 SV_Physics_Follow (ent);
2709 break;
2710 case MOVETYPE_NOCLIP:
2711 if (SV_RunThink(ent))
2712 {
2713 SV_CheckWater(ent);
2716 }
2717 SV_LinkEdict(ent);
2718 break;
2719 case MOVETYPE_STEP:
2720 SV_Physics_Step (ent);
2721 // regular thinking
2722 if (SV_RunThink(ent))
2723 if (ent->priv.server->waterposition_forceupdate || !VectorCompare(PRVM_serveredictvector(ent, origin), ent->priv.server->waterposition_origin))
2724 {
2725 ent->priv.server->waterposition_forceupdate = false;
2726 VectorCopy(PRVM_serveredictvector(ent, origin), ent->priv.server->waterposition_origin);
2728 }
2729 break;
2730 case MOVETYPE_WALK:
2731 if (SV_RunThink (ent))
2732 SV_WalkMove (ent);
2733 break;
2734 case MOVETYPE_TOSS:
2735 case MOVETYPE_BOUNCE:
2738 case MOVETYPE_FLY:
2740 // regular thinking
2741 if (SV_RunThink (ent))
2742 SV_Physics_Toss (ent);
2743 break;
2744 case MOVETYPE_PHYSICS:
2745 if (SV_RunThink(ent))
2746 {
2747 SV_LinkEdict(ent);
2749 }
2750 break;
2751 default:
2753 break;
2754 Con_Printf ("SV_Physics: bad movetype %i\n", (int)PRVM_serveredictfloat(ent, movetype));
2755 break;
2756 }
2757}
bool qbool
Definition qtypes.h:9

References angles, avelocity, Con_Printf(), server_t::frametime, cvar_t::integer, movetype, MOVETYPE_BOUNCE, MOVETYPE_BOUNCEMISSILE, MOVETYPE_FAKEPUSH, MOVETYPE_FLY, MOVETYPE_FLY_WORLDONLY, MOVETYPE_FLYMISSILE, MOVETYPE_FOLLOW, MOVETYPE_NOCLIP, MOVETYPE_NONE, MOVETYPE_PHYSICS, MOVETYPE_PUSH, MOVETYPE_STEP, MOVETYPE_TOSS, MOVETYPE_USER_FIRST, MOVETYPE_USER_LAST, MOVETYPE_WALK, nextthink, origin, prvm_edict_t::priv, PRVM_serveredictfloat, PRVM_serveredictvector, prvm_edict_t::server, sv, SV_CheckWater(), SV_CheckWaterTransition(), sv_gameplayfix_delayprojectiles, SV_LinkEdict(), SV_LinkEdict_TouchAreaGrid(), SV_Physics_Follow(), SV_Physics_Pusher(), SV_Physics_Step(), SV_Physics_Toss(), SV_RunThink(), SV_WalkMove(), SVVM_prog, server_t::time, VectorCompare, VectorCopy, VectorMA, and velocity.

Referenced by SV_Physics().

◆ SV_Physics_Follow()

static void SV_Physics_Follow ( prvm_edict_t * ent)
static

Definition at line 2361 of file sv_phys.c.

2362{
2363 prvm_prog_t *prog = SVVM_prog;
2364 vec3_t vf, vr, vu, angles, v;
2365 prvm_edict_t *e;
2366
2367 // LadyHavoc: implemented rotation on MOVETYPE_FOLLOW objects
2370 {
2371 // quick case for no rotation
2373 }
2374 else
2375 {
2379 AngleVectors (angles, vf, vr, vu);
2380 v[0] = PRVM_serveredictvector(ent, view_ofs)[0] * vf[0] + PRVM_serveredictvector(ent, view_ofs)[1] * vr[0] + PRVM_serveredictvector(ent, view_ofs)[2] * vu[0];
2381 v[1] = PRVM_serveredictvector(ent, view_ofs)[0] * vf[1] + PRVM_serveredictvector(ent, view_ofs)[1] * vr[1] + PRVM_serveredictvector(ent, view_ofs)[2] * vu[1];
2382 v[2] = PRVM_serveredictvector(ent, view_ofs)[0] * vf[2] + PRVM_serveredictvector(ent, view_ofs)[1] * vr[2] + PRVM_serveredictvector(ent, view_ofs)[2] * vu[2];
2386 AngleVectors (angles, vf, vr, vu);
2387 PRVM_serveredictvector(ent, origin)[0] = v[0] * vf[0] + v[1] * vf[1] + v[2] * vf[2] + PRVM_serveredictvector(e, origin)[0];
2388 PRVM_serveredictvector(ent, origin)[1] = v[0] * vr[0] + v[1] * vr[1] + v[2] * vr[2] + PRVM_serveredictvector(e, origin)[1];
2389 PRVM_serveredictvector(ent, origin)[2] = v[0] * vu[0] + v[1] * vu[1] + v[2] * vu[2] + PRVM_serveredictvector(e, origin)[2];
2390 }
2392 SV_LinkEdict(ent);
2393 //SV_LinkEdict_TouchAreaGrid(ent);
2394}
void AngleVectors(const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
Definition mathlib.c:444
vector punchangle
Definition progsdefs.qc:117
vector v_angle
Definition progsdefs.qc:161
entity aiment
Definition progsdefs.qc:187
#define PRVM_PROG_TO_EDICT(n)
Definition progsvm.h:877

References aiment, angles, AngleVectors(), origin, PRVM_PROG_TO_EDICT, PRVM_serveredictedict, PRVM_serveredictvector, punchangle, SV_LinkEdict(), SVVM_prog, v, v_angle, VectorAdd, and view_ofs.

Referenced by SV_Physics_ClientEntity(), SV_Physics_ClientEntity_NoThink(), and SV_Physics_Entity().

◆ SV_Physics_Pusher()

static void SV_Physics_Pusher ( prvm_edict_t * ent)
static

Definition at line 1908 of file sv_phys.c.

1909{
1910 prvm_prog_t *prog = SVVM_prog;
1911 prvm_vec_t thinktime, oldltime, movetime;
1912
1913 oldltime = PRVM_serveredictfloat(ent, ltime);
1914
1915 thinktime = PRVM_serveredictfloat(ent, nextthink);
1916 if (thinktime < PRVM_serveredictfloat(ent, ltime) + sv.frametime)
1917 {
1918 movetime = thinktime - PRVM_serveredictfloat(ent, ltime);
1919 if (movetime < 0)
1920 movetime = 0;
1921 }
1922 else
1923 movetime = sv.frametime;
1924
1925 if (movetime)
1926 // advances PRVM_serveredictfloat(ent, ltime) if not blocked
1927 SV_PushMove (ent, movetime);
1928
1929 if (thinktime > oldltime && thinktime <= PRVM_serveredictfloat(ent, ltime))
1930 {
1935 prog->ExecuteProgram(prog, PRVM_serveredictfunction(ent, think), "QC function self.think is missing");
1936 }
1937}
float ltime
Definition progsdefs.qc:107
float prvm_vec_t
Definition qtypes.h:55
static void SV_PushMove(prvm_edict_t *pusher, float movetime)
Definition sv_phys.c:1593

References prvm_prog_t::edicts, prvm_prog_t::ExecuteProgram, server_t::frametime, ltime, nextthink, other, PRVM_EDICT_TO_PROG, PRVM_serveredictfloat, PRVM_serveredictfunction, PRVM_serverglobaledict, PRVM_serverglobalfloat, self, sv, SV_PushMove(), SVVM_prog, server_t::time, and time.

Referenced by SV_Physics_ClientEntity(), and SV_Physics_Entity().

◆ SV_Physics_Step()

static void SV_Physics_Step ( prvm_edict_t * ent)
static

Definition at line 2615 of file sv_phys.c.

2616{
2617 prvm_prog_t *prog = SVVM_prog;
2618 int flags = (int)PRVM_serveredictfloat(ent, flags);
2619
2620 // DRESK
2621 // Backup Velocity in the event that movetypesteplandevent is called,
2622 // to provide a parameter with the entity's velocity at impact.
2623 vec3_t backupVelocity;
2624 VectorCopy(PRVM_serveredictvector(ent, velocity), backupVelocity);
2625 // don't fall at all if fly/swim
2626 if (!(flags & (FL_FLY | FL_SWIM)))
2627 {
2628 if (flags & FL_ONGROUND)
2629 {
2630 // freefall if onground and moving upward
2631 // freefall if not standing on a world surface (it may be a lift or trap door)
2633 {
2635 SV_CheckVelocity(ent);
2636 SV_FlyMove(ent, sv.frametime, true, NULL, SV_GenericHitSuperContentsMask(ent), 0, 0, 0);
2637 SV_LinkEdict(ent);
2639 ent->priv.server->waterposition_forceupdate = true;
2640 }
2641 }
2642 else
2643 {
2644 // freefall if not onground
2645 int hitsound = PRVM_serveredictvector(ent, velocity)[2] < sv_gravity.value * -0.1;
2646
2647 SV_CheckVelocity(ent);
2648 SV_FlyMove(ent, sv.frametime, true, NULL, SV_GenericHitSuperContentsMask(ent), 0, 0, 0);
2649 SV_LinkEdict(ent);
2651
2652 // just hit ground
2653 if (hitsound && (int)PRVM_serveredictfloat(ent, flags) & FL_ONGROUND)
2654 {
2655 // DRESK - Check for Entity Land Event Function
2656 if(PRVM_serveredictfunction(ent, movetypesteplandevent))
2657 { // Valid Function; Execute
2658 // Prepare Parameters
2659 // Assign Velocity at Impact
2660 PRVM_G_VECTOR(OFS_PARM0)[0] = backupVelocity[0];
2661 PRVM_G_VECTOR(OFS_PARM0)[1] = backupVelocity[1];
2662 PRVM_G_VECTOR(OFS_PARM0)[2] = backupVelocity[2];
2663 // Assign Self
2665 // Set Time
2667 // Execute VM Function
2668 prog->ExecuteProgram(prog, PRVM_serveredictfunction(ent, movetypesteplandevent), "movetypesteplandevent: NULL function");
2669 }
2670 else
2671 // Check for Engine Landing Sound
2673 SV_StartSound(ent, 0, sv_sound_land.string, 255, 1, false, 1.0f);
2674 }
2675 ent->priv.server->waterposition_forceupdate = true;
2676 }
2677 }
2678}
#define PRVM_G_VECTOR(o)
Definition progsvm.h:886
#define FL_FLY
Definition server.h:357
cvar_t sv_sound_land
Definition sv_main.c:151
cvar_t sv_gameplayfix_upwardvelocityclearsongroundflag
Definition sv_main.c:127
#define FL_SWIM
Definition server.h:358
static int SV_FlyMove(prvm_edict_t *ent, float time, qbool applygravity, float *stepnormal, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask, float stepheight)
Definition sv_phys.c:1150

References prvm_prog_t::ExecuteProgram, FL_FLY, FL_ONGROUND, FL_SWIM, flags, server_t::frametime, int(), cvar_t::integer, NULL, OFS_PARM0, prvm_edict_t::priv, PRVM_EDICT_TO_PROG, PRVM_G_VECTOR, PRVM_serveredictfloat, PRVM_serveredictfunction, PRVM_serveredictvector, PRVM_serverglobaledict, PRVM_serverglobalfloat, self, prvm_edict_t::server, cvar_t::string, sv, SV_CheckVelocity(), SV_FlyMove(), sv_gameplayfix_upwardvelocityclearsongroundflag, SV_GenericHitSuperContentsMask(), sv_gravity, SV_LinkEdict(), SV_LinkEdict_TouchAreaGrid(), sv_sound_land, SV_StartSound(), SVVM_prog, server_t::time, time, cvar_t::value, VectorCopy, and velocity.

Referenced by SV_Physics_ClientEntity(), SV_Physics_ClientEntity_NoThink(), and SV_Physics_Entity().

◆ SV_Physics_Toss()

void SV_Physics_Toss ( prvm_edict_t * ent)

Definition at line 2459 of file sv_phys.c.

2460{
2461 prvm_prog_t *prog = SVVM_prog;
2462 trace_t trace;
2463 vec3_t move;
2464 vec_t movetime;
2465 int bump;
2467 float d, ent_gravity;
2468 float bouncefactor;
2469 float bouncestop;
2470
2471// if onground, return without moving
2472 if ((int)PRVM_serveredictfloat(ent, flags) & FL_ONGROUND)
2473 {
2476 {
2477 // don't stick to ground if onground and moving upward
2479 }
2481 {
2482 // we can trust FL_ONGROUND if groundentity is world because it never moves
2483 return;
2484 }
2485 else if (ent->priv.server->suspendedinairflag && groundentity->free)
2486 {
2487 // if ent was supported by a brush model on previous frame,
2488 // and groundentity is now freed, set groundentity to 0 (world)
2489 // which leaves it suspended in the air
2492 return;
2493 }
2494 else if (BoxesOverlap(ent->priv.server->cullmins, ent->priv.server->cullmaxs, groundentity->priv.server->cullmins, groundentity->priv.server->cullmaxs))
2495 {
2496 // don't slide if still touching the groundentity
2497 return;
2498 }
2499 }
2500 ent->priv.server->suspendedinairflag = false;
2501
2502 SV_CheckVelocity (ent);
2503
2504// add gravity
2507
2508// move angles
2510
2511 movetime = sv.frametime;
2512 for (bump = 0;bump < MAX_CLIP_PLANES && movetime > 0;bump++)
2513 {
2514 // move origin
2515 VectorScale(PRVM_serveredictvector(ent, velocity), movetime, move);
2516 // The buzzsaw traps in r2m6 and r2m7 use MOVETYPE_FLY and rely on moving while stuck in the world.
2517 // Quake movetypes checked allsolid only in SV_FlyMove().
2518 if(!SV_PushEntity(&trace, ent, move, true, PRVM_serveredictfloat(ent, movetype) != MOVETYPE_FLY))
2519 return; // teleported
2520 if (ent->free)
2521 return;
2522 if (trace.fraction == 1)
2523 break;
2524 movetime *= 1 - min(1, trace.fraction);
2525 switch((int)PRVM_serveredictfloat(ent, movetype))
2526 {
2529 if (!bouncefactor)
2530 bouncefactor = 1.0f;
2531
2533 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) & ~FL_ONGROUND;
2535 movetime = 0;
2536 break;
2537 case MOVETYPE_BOUNCE:
2539 if (!bouncefactor)
2540 bouncefactor = 0.5f;
2541
2543 if (!bouncestop)
2544 bouncestop = 60.0f / 800.0f;
2545
2547 ent_gravity = PRVM_serveredictfloat(ent, gravity);
2548 if (!ent_gravity)
2549 ent_gravity = 1.0f;
2550 // LadyHavoc: fixed grenades not bouncing when fired down a slope
2553 else
2554 d = PRVM_serveredictvector(ent, velocity)[2];
2555 if (trace.plane.normal[2] > 0.7 && d < sv_gravity.value * bouncestop * ent_gravity)
2556 {
2561 movetime = 0;
2562 }
2563 else
2564 {
2565 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) & ~FL_ONGROUND;
2567 movetime = 0;
2568 }
2569 break;
2570 default:
2572 if (trace.plane.normal[2] > 0.7)
2573 {
2577 ent->priv.server->suspendedinairflag = true;
2580 movetime = 0;
2581 }
2582 else
2583 {
2584 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) & ~FL_ONGROUND;
2586 movetime = 0;
2587 }
2588 break;
2589 }
2590 }
2591
2592// check for in water
2594}
float bouncefactor
float bouncestop
#define min(A, B)
Definition mathlib.h:37
float fabs(float f)
cvar_t sv_gameplayfix_noairborncorpse_allowsuspendeditems
Definition sv_main.c:116
cvar_t sv_gameplayfix_noairborncorpse
Definition sv_main.c:115
cvar_t sv_gameplayfix_slidemoveprojectiles
Definition sv_main.c:122
cvar_t sv_gameplayfix_grenadebouncedownslopes
Definition sv_main.c:112

References angles, avelocity, bouncefactor, bouncestop, BoxesOverlap, ClipVelocity(), DotProduct, trace_t::ent, fabs(), FL_ONGROUND, flags, trace_t::fraction, server_t::frametime, prvm_edict_t::free, groundentity, int(), cvar_t::integer, min, movetype, MOVETYPE_BOUNCE, MOVETYPE_BOUNCEMISSILE, MOVETYPE_FLY, MOVETYPE_TOSS, plane_t::normal, trace_t::plane, prvm_edict_t::priv, PRVM_EDICT_TO_PROG, PRVM_PROG_TO_EDICT, PRVM_serveredictedict, PRVM_serveredictfloat, PRVM_serveredictvector, prvm_edict_t::server, solid, SOLID_BSP, sv, SV_CheckVelocity(), SV_CheckWaterTransition(), sv_gameplayfix_grenadebouncedownslopes, sv_gameplayfix_noairborncorpse, sv_gameplayfix_noairborncorpse_allowsuspendeditems, sv_gameplayfix_slidemoveprojectiles, sv_gameplayfix_upwardvelocityclearsongroundflag, SV_Gravity(), sv_gravity, SV_PushEntity(), SVVM_prog, cvar_t::value, VectorClear, VectorMA, VectorScale, and velocity.

Referenced by SV_Physics_ClientEntity(), SV_Physics_ClientEntity_NoThink(), and SV_Physics_Entity().

◆ SV_PointSuperContents()

int SV_PointSuperContents ( const vec3_t point)

Definition at line 611 of file sv_phys.c.

612{
613 prvm_prog_t *prog = SVVM_prog;
614 int supercontents = 0;
615 int i;
616 prvm_edict_t *touch;
617 vec3_t transformed;
618 // matrices to transform into/out of other entity's space
619 matrix4x4_t matrix, imatrix;
620 // model of other entity
621 model_t *model;
622 int frame;
623 // list of entities to test for collisions
624 int numtouchedicts;
625 static prvm_edict_t *touchedicts[MAX_EDICTS];
626
627 // get world supercontents at this point
628 if (sv.worldmodel && sv.worldmodel->PointSuperContents)
629 supercontents = sv.worldmodel->PointSuperContents(sv.worldmodel, 0, point);
630
631 // if sv_gameplayfix_swiminbmodels is off we're done
633 return supercontents;
634
635 // get list of entities at this point
636 numtouchedicts = SV_EntitiesInBox(point, point, MAX_EDICTS, touchedicts);
637 if (numtouchedicts > MAX_EDICTS)
638 {
639 // this never happens
640 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
641 numtouchedicts = MAX_EDICTS;
642 }
643 for (i = 0;i < numtouchedicts;i++)
644 {
645 touch = touchedicts[i];
646
647 // we only care about SOLID_BSP for pointcontents
649 continue;
650
651 // might interact, so do an exact clip
653 if (!model || !model->PointSuperContents)
654 continue;
656 Matrix4x4_Invert_Simple(&imatrix, &matrix);
657 Matrix4x4_Transform(&imatrix, point, transformed);
659 supercontents |= model->PointSuperContents(model, bound(0, frame, (model->numframes - 1)), transformed);
660 }
661
662 return supercontents;
663}
float frame
#define bound(min, num, max)
Definition mathlib.h:34
void Matrix4x4_Invert_Simple(matrix4x4_t *out, const matrix4x4_t *in1)
Definition matrixlib.c:422
cvar_t sv_gameplayfix_swiminbmodels
Definition sv_main.c:126
struct model_s * worldmodel
Definition server.h:112

References angles, bound, Con_Printf(), frame, i, int(), cvar_t::integer, Matrix4x4_CreateFromQuakeEntity(), Matrix4x4_Invert_Simple(), Matrix4x4_Transform(), MAX_EDICTS, model, origin, PRVM_serveredictfloat, PRVM_serveredictvector, solid, SOLID_BSP, sv, SV_EntitiesInBox(), sv_gameplayfix_swiminbmodels, SV_GetModelFromEdict(), SVVM_prog, and server_t::worldmodel.

Referenced by PHYS_TestEntityPosition(), SV_CheckBottom(), SV_CheckWater(), SV_CheckWaterTransition(), SV_movestep(), and VM_SV_pointcontents().

◆ SV_PushEntity()

static qbool SV_PushEntity ( trace_t * trace,
prvm_edict_t * ent,
vec3_t push,
qbool dotouch,
qbool checkstuck )
static

Definition at line 1521 of file sv_phys.c.

1522{
1523 prvm_prog_t *prog = SVVM_prog;
1524 int solid;
1525 int movetype;
1526 int type;
1527 vec3_t mins, maxs;
1528 vec3_t start;
1529 vec3_t end;
1530
1535
1537 VectorAdd(start, push, end);
1538
1541 else if (movetype == MOVETYPE_FLY_WORLDONLY)
1543 else if (solid == SOLID_TRIGGER || solid == SOLID_NOT)
1544 type = MOVE_NOMONSTERS; // only clip against bmodels
1545 else
1546 type = MOVE_NORMAL;
1547
1549 if (trace->allsolid && checkstuck)
1550 {
1551 if (SV_UnstickEntity(ent))
1552 {
1554 VectorAdd(start, push, end);
1556 }
1557 // abort move if we're stuck in the world (and didn't make it out)
1558 else if (trace->worldstartsolid)
1559 return true;
1560 }
1561
1563 VectorCopy(trace->endpos, PRVM_serveredictvector(ent, oldorigin)); // for SV_UnstickEntity()
1564
1565 SV_LinkEdict(ent);
1566
1567#if 0
1568 if(!trace->startsolid)
1570 {
1571 Con_Printf("something eeeeevil happened\n");
1572 }
1573#endif
1574
1575 if (dotouch)
1576 {
1578
1580 return SV_Impact (ent, trace);
1581 }
1582
1583 return true;
1584}
vector oldorigin
GLenum type
Definition glquake.h:656
qbool startsolid
Definition collision.h:26
static qbool SV_UnstickEntity(prvm_edict_t *ent)
Definition sv_phys.c:1956
#define MOVE_MISSILE
Definition world.h:30
#define MOVE_WORLDONLY
Definition world.h:31
#define MOVE_NORMAL
Definition world.h:28

References trace_t::allsolid, collision_extendmovelength, Con_Printf(), trace_t::endpos, trace_t::ent, FL_ONGROUND, flags, groundentity, int(), maxs, mins, MOVE_MISSILE, MOVE_NOMONSTERS, MOVE_NORMAL, MOVE_WORLDONLY, movetype, MOVETYPE_FLY_WORLDONLY, MOVETYPE_FLYMISSILE, oldorigin, origin, PRVM_EDICT_TO_PROG, PRVM_serveredictedict, PRVM_serveredictfloat, PRVM_serveredictvector, solid, SOLID_NOT, SOLID_TRIGGER, trace_t::startsolid, SV_GenericHitSuperContentsMask(), SV_Impact(), SV_LinkEdict(), SV_LinkEdict_TouchAreaGrid(), SV_TraceBox(), SV_UnstickEntity(), SVVM_prog, type, cvar_t::value, VectorAdd, VectorCopy, and trace_t::worldstartsolid.

Referenced by SV_FlyMove(), SV_Physics_Toss(), SV_PushMove(), and SV_WalkMove().

◆ SV_PushMove()

static void SV_PushMove ( prvm_edict_t * pusher,
float movetime )
static

Definition at line 1593 of file sv_phys.c.

1594{
1595 prvm_prog_t *prog = SVVM_prog;
1596 int i, e, index;
1597 int pusherowner, pusherprog;
1598 int checkcontents;
1599 qbool rotated;
1600 float savesolid, movetime2, pushltime;
1601 vec3_t mins, maxs, move, move1, moveangle, pushorig, pushang, a, forward, left, up, org, pushermins, pushermaxs, checkorigin, checkmins, checkmaxs;
1602 int num_moved;
1603 int numcheckentities;
1604 static prvm_edict_t *checkentities[MAX_EDICTS];
1605 model_t *pushermodel;
1606 trace_t trace, trace2;
1607 matrix4x4_t pusherfinalmatrix, pusherfinalimatrix;
1608 static unsigned short moved_edicts[MAX_EDICTS];
1609 vec3_t pivot;
1610
1612 {
1613 PRVM_serveredictfloat(pusher, ltime) += movetime;
1614 return;
1615 }
1616
1617 switch ((int) PRVM_serveredictfloat(pusher, solid))
1618 {
1619 // LadyHavoc: valid pusher types
1620 case SOLID_BSP:
1621 case SOLID_BBOX:
1622 case SOLID_SLIDEBOX:
1623 case SOLID_CORPSE: // LadyHavoc: this would be weird...
1624 break;
1625 // LadyHavoc: no collisions
1626 case SOLID_NOT:
1627 case SOLID_TRIGGER:
1630 PRVM_serveredictvector(pusher, angles)[0] -= 360.0 * floor(PRVM_serveredictvector(pusher, angles)[0] * (1.0 / 360.0));
1631 PRVM_serveredictvector(pusher, angles)[1] -= 360.0 * floor(PRVM_serveredictvector(pusher, angles)[1] * (1.0 / 360.0));
1632 PRVM_serveredictvector(pusher, angles)[2] -= 360.0 * floor(PRVM_serveredictvector(pusher, angles)[2] * (1.0 / 360.0));
1633 PRVM_serveredictfloat(pusher, ltime) += movetime;
1634 SV_LinkEdict(pusher);
1635 return;
1636 default:
1637 Con_Printf("SV_PushMove: entity #%i, unrecognized solid type %f\n", PRVM_NUM_FOR_EDICT(pusher), PRVM_serveredictfloat(pusher, solid));
1638 return;
1639 }
1642 {
1643 Con_Printf("SV_PushMove: entity #%i has an invalid modelindex %f\n", PRVM_NUM_FOR_EDICT(pusher), PRVM_serveredictfloat(pusher, modelindex));
1644 return;
1645 }
1646 pushermodel = SV_GetModelByIndex(index);
1647 pusherowner = PRVM_serveredictedict(pusher, owner);
1648 pusherprog = PRVM_EDICT_TO_PROG(pusher);
1649
1651
1652 movetime2 = movetime;
1653 VectorScale(PRVM_serveredictvector(pusher, velocity), movetime2, move1);
1654 VectorScale(PRVM_serveredictvector(pusher, avelocity), movetime2, moveangle);
1655 if (moveangle[0] || moveangle[2])
1656 {
1657 for (i = 0;i < 3;i++)
1658 {
1659 if (move1[i] > 0)
1660 {
1661 mins[i] = pushermodel->rotatedmins[i] + PRVM_serveredictvector(pusher, origin)[i] - 1;
1662 maxs[i] = pushermodel->rotatedmaxs[i] + move1[i] + PRVM_serveredictvector(pusher, origin)[i] + 1;
1663 }
1664 else
1665 {
1666 mins[i] = pushermodel->rotatedmins[i] + move1[i] + PRVM_serveredictvector(pusher, origin)[i] - 1;
1667 maxs[i] = pushermodel->rotatedmaxs[i] + PRVM_serveredictvector(pusher, origin)[i] + 1;
1668 }
1669 }
1670 }
1671 else if (moveangle[1])
1672 {
1673 for (i = 0;i < 3;i++)
1674 {
1675 if (move1[i] > 0)
1676 {
1677 mins[i] = pushermodel->yawmins[i] + PRVM_serveredictvector(pusher, origin)[i] - 1;
1678 maxs[i] = pushermodel->yawmaxs[i] + move1[i] + PRVM_serveredictvector(pusher, origin)[i] + 1;
1679 }
1680 else
1681 {
1682 mins[i] = pushermodel->yawmins[i] + move1[i] + PRVM_serveredictvector(pusher, origin)[i] - 1;
1683 maxs[i] = pushermodel->yawmaxs[i] + PRVM_serveredictvector(pusher, origin)[i] + 1;
1684 }
1685 }
1686 }
1687 else
1688 {
1689 for (i = 0;i < 3;i++)
1690 {
1691 if (move1[i] > 0)
1692 {
1693 mins[i] = pushermodel->normalmins[i] + PRVM_serveredictvector(pusher, origin)[i] - 1;
1694 maxs[i] = pushermodel->normalmaxs[i] + move1[i] + PRVM_serveredictvector(pusher, origin)[i] + 1;
1695 }
1696 else
1697 {
1698 mins[i] = pushermodel->normalmins[i] + move1[i] + PRVM_serveredictvector(pusher, origin)[i] - 1;
1699 maxs[i] = pushermodel->normalmaxs[i] + PRVM_serveredictvector(pusher, origin)[i] + 1;
1700 }
1701 }
1702 }
1703
1704 VectorNegate (moveangle, a);
1705 AngleVectorsFLU (a, forward, left, up);
1706
1707 VectorCopy (PRVM_serveredictvector(pusher, origin), pushorig);
1708 VectorCopy (PRVM_serveredictvector(pusher, angles), pushang);
1709 pushltime = PRVM_serveredictfloat(pusher, ltime);
1710
1711// move the pusher to its final position
1712
1715 PRVM_serveredictfloat(pusher, ltime) += movetime;
1716 SV_LinkEdict(pusher);
1717
1718 pushermodel = SV_GetModelFromEdict(pusher);
1720 Matrix4x4_Invert_Simple(&pusherfinalimatrix, &pusherfinalmatrix);
1721
1722 savesolid = PRVM_serveredictfloat(pusher, solid);
1723
1724// see if any solid entities are inside the final position
1725 num_moved = 0;
1726
1727 if (PRVM_serveredictfloat(pusher, movetype) == MOVETYPE_FAKEPUSH) // Tenebrae's MOVETYPE_PUSH variant that doesn't push...
1728 numcheckentities = 0;
1729 else // MOVETYPE_PUSH
1730 numcheckentities = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, checkentities);
1731 for (e = 0;e < numcheckentities;e++)
1732 {
1733 prvm_edict_t *check = checkentities[e];
1735 switch(movetype)
1736 {
1737 case MOVETYPE_NONE:
1738 case MOVETYPE_PUSH:
1739 case MOVETYPE_FOLLOW:
1740 case MOVETYPE_NOCLIP:
1742 continue;
1743 default:
1744 break;
1745 }
1746
1747 if (PRVM_serveredictedict(check, owner) == pusherprog)
1748 continue;
1749
1750 if (pusherowner == PRVM_EDICT_TO_PROG(check))
1751 continue;
1752
1753 //Con_Printf("%i %s ", PRVM_NUM_FOR_EDICT(check), PRVM_GetString(PRVM_serveredictstring(check, classname)));
1754
1755 // tell any MOVETYPE_STEP entity that it may need to check for water transitions
1756 check->priv.server->waterposition_forceupdate = true;
1757
1758 checkcontents = SV_GenericHitSuperContentsMask(check);
1759
1760 // if the entity is standing on the pusher, it will definitely be moved
1761 // if the entity is not standing on the pusher, but is in the pusher's
1762 // final position, move it
1764 {
1765 VectorCopy(PRVM_serveredictvector(pusher, mins), pushermins);
1766 VectorCopy(PRVM_serveredictvector(pusher, maxs), pushermaxs);
1767 VectorCopy(PRVM_serveredictvector(check, origin), checkorigin);
1768 VectorCopy(PRVM_serveredictvector(check, mins), checkmins);
1769 VectorCopy(PRVM_serveredictvector(check, maxs), checkmaxs);
1770 Collision_ClipToGenericEntity(&trace, pushermodel, pusher->priv.server->frameblend, &pusher->priv.server->skeleton, pushermins, pushermaxs, SUPERCONTENTS_BODY, &pusherfinalmatrix, &pusherfinalimatrix, checkorigin, checkmins, checkmaxs, checkorigin, checkcontents, 0, 0, collision_extendmovelength.value);
1771 //trace = SV_TraceBox(PRVM_serveredictvector(check, origin), PRVM_serveredictvector(check, mins), PRVM_serveredictvector(check, maxs), PRVM_serveredictvector(check, origin), MOVE_NOMONSTERS, check, checkcontents);
1772 if (!trace.startsolid)
1773 {
1774 // Con_Printf("- not in solid\n");
1775 continue;
1776 }
1777 }
1778
1779 VectorLerp(PRVM_serveredictvector(check, mins), 0.5f, PRVM_serveredictvector(check, maxs), pivot);
1780 //VectorClear(pivot);
1781
1782 if (rotated)
1783 {
1784 vec3_t org2;
1786 VectorAdd (org, pivot, org);
1787 org2[0] = DotProduct (org, forward);
1788 org2[1] = DotProduct (org, left);
1789 org2[2] = DotProduct (org, up);
1790 VectorSubtract (org2, org, move);
1791 VectorAdd (move, move1, move);
1792 }
1793 else
1794 VectorCopy (move1, move);
1795
1796 //Con_Printf("- pushing %f %f %f\n", move[0], move[1], move[2]);
1797
1798 VectorCopy (PRVM_serveredictvector(check, origin), check->priv.server->moved_from);
1799 VectorCopy (PRVM_serveredictvector(check, angles), check->priv.server->moved_fromangles);
1800 moved_edicts[num_moved++] = PRVM_NUM_FOR_EDICT(check);
1801
1802 // physics objects need better collisions than this code can do
1804 {
1806 SV_LinkEdict(check);
1808 continue;
1809 }
1810
1811 // try moving the contacted entity
1813 if(!SV_PushEntity(&trace, check, move, true, true))
1814 {
1815 // entity "check" got teleported
1816 PRVM_serveredictvector(check, angles)[1] += trace.fraction * moveangle[1];
1817 PRVM_serveredictfloat(pusher, solid) = savesolid; // was SOLID_BSP
1818 continue; // pushed enough
1819 }
1820 // FIXME: turn players specially
1821 PRVM_serveredictvector(check, angles)[1] += trace.fraction * moveangle[1];
1822 PRVM_serveredictfloat(pusher, solid) = savesolid; // was SOLID_BSP
1823 //Con_Printf("%s:%d frac %f startsolid %d bmodelstartsolid %d allsolid %d\n", __FILE__, __LINE__, trace.fraction, trace.startsolid, trace.bmodelstartsolid, trace.allsolid);
1824
1825 // this trace.fraction < 1 check causes items to fall off of pushers
1826 // if they pass under or through a wall
1827 // the groundentity check causes items to fall off of ledges
1829 PRVM_serveredictfloat(check, flags) = (int)PRVM_serveredictfloat(check, flags) & ~FL_ONGROUND;
1830
1831 // if it is still inside the pusher, block
1832 VectorCopy(PRVM_serveredictvector(pusher, mins), pushermins);
1833 VectorCopy(PRVM_serveredictvector(pusher, maxs), pushermaxs);
1834 VectorCopy(PRVM_serveredictvector(check, origin), checkorigin);
1835 VectorCopy(PRVM_serveredictvector(check, mins), checkmins);
1836 VectorCopy(PRVM_serveredictvector(check, maxs), checkmaxs);
1837 Collision_ClipToGenericEntity(&trace, pushermodel, pusher->priv.server->frameblend, &pusher->priv.server->skeleton, pushermins, pushermaxs, SUPERCONTENTS_BODY, &pusherfinalmatrix, &pusherfinalimatrix, checkorigin, checkmins, checkmaxs, checkorigin, checkcontents, 0, 0, collision_extendmovelength.value);
1838 if (trace.startsolid)
1839 {
1840 vec3_t move2;
1841 if(SV_NudgeOutOfSolid_PivotIsKnownGood(check, pivot))
1842 {
1843 // hack to invoke all necessary movement triggers
1844 VectorClear(move2);
1845 if(!SV_PushEntity(&trace2, check, move2, true, true))
1846 {
1847 // entity "check" got teleported
1848 continue;
1849 }
1850 // we could fix it
1851 continue;
1852 }
1853
1854 // still inside pusher, so it's really blocked
1855
1856 // fail the move
1857 if (PRVM_serveredictvector(check, mins)[0] == PRVM_serveredictvector(check, maxs)[0])
1858 continue;
1860 {
1861 // corpse
1863 {
1864 // When sv_gameplayfix_nosquashentities is disabled, entity hitboxes will be squashed when
1865 // the entity is crushed by a mover, preventing it from being interacted with again
1866 PRVM_serveredictvector(check, mins)[0] = PRVM_serveredictvector(check, mins)[1] = 0;
1868 }
1869 continue;
1870 }
1871
1872 VectorCopy (pushorig, PRVM_serveredictvector(pusher, origin));
1873 VectorCopy (pushang, PRVM_serveredictvector(pusher, angles));
1874 PRVM_serveredictfloat(pusher, ltime) = pushltime;
1875 SV_LinkEdict(pusher);
1876
1877 // move back any entities we already moved
1878 for (i = 0;i < num_moved;i++)
1879 {
1880 prvm_edict_t *ed = PRVM_EDICT_NUM(moved_edicts[i]);
1881 VectorCopy (ed->priv.server->moved_from, PRVM_serveredictvector(ed, origin));
1882 VectorCopy (ed->priv.server->moved_fromangles, PRVM_serveredictvector(ed, angles));
1883 SV_LinkEdict(ed);
1884 }
1885
1886 // if the pusher has a "blocked" function, call it, otherwise just stay in place until the obstacle is gone
1887 if (PRVM_serveredictfunction(pusher, blocked))
1888 {
1892 prog->ExecuteProgram(prog, PRVM_serveredictfunction(pusher, blocked), "QC function self.blocked is missing");
1893 }
1894 break;
1895 }
1896 }
1897 PRVM_serveredictvector(pusher, angles)[0] -= 360.0 * floor(PRVM_serveredictvector(pusher, angles)[0] * (1.0 / 360.0));
1898 PRVM_serveredictvector(pusher, angles)[1] -= 360.0 * floor(PRVM_serveredictvector(pusher, angles)[1] * (1.0 / 360.0));
1899 PRVM_serveredictvector(pusher, angles)[2] -= 360.0 * floor(PRVM_serveredictvector(pusher, angles)[2] * (1.0 / 360.0));
1900}
void Collision_ClipToGenericEntity(trace_t *trace, model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, const vec3_t bodymins, const vec3_t bodymaxs, int bodysupercontents, matrix4x4_t *matrix, matrix4x4_t *inversematrix, const vec3_t tstart, const vec3_t mins, const vec3_t maxs, const vec3_t tend, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask, float extend)
Definition collision.c:1791
entity owner
GLuint index
Definition glquake.h:629
void AngleVectorsFLU(const vec3_t angles, vec3_t forward, vec3_t left, vec3_t up)
LadyHavoc: proper matrix version of AngleVectors.
Definition mathlib.c:498
#define VectorLerp(v1, lerp, v2, out)
Definition mathlib.h:120
float floor(float f)
#define SOLID_BBOX
touch on edge, block
Definition server.h:334
cvar_t sv_gameplayfix_nosquashentities
Definition sv_main.c:133
ret a
vec3_t rotatedmins
vec3_t yawmaxs
vec3_t rotatedmaxs
vec3_t normalmaxs
vec3_t yawmins
vec3_t normalmins
static qbool SV_NudgeOutOfSolid_PivotIsKnownGood(prvm_edict_t *ent, vec3_t pivot)
Definition sv_phys.c:1430
static vec3_t forward
Definition sv_user.c:305
static vec3_t up
Definition sv_user.c:305

References a, angles, AngleVectorsFLU(), avelocity, Collision_ClipToGenericEntity(), collision_extendmovelength, Con_Printf(), DotProduct, prvm_prog_t::ExecuteProgram, FL_ONGROUND, flags, floor(), forward, trace_t::fraction, groundentity, i, index, int(), cvar_t::integer, ltime, Matrix4x4_CreateFromQuakeEntity(), Matrix4x4_Invert_Simple(), MAX_EDICTS, MAX_MODELS, maxs, mins, modelindex, movetype, MOVETYPE_FAKEPUSH, MOVETYPE_FLY_WORLDONLY, MOVETYPE_FOLLOW, MOVETYPE_NOCLIP, MOVETYPE_NONE, MOVETYPE_PHYSICS, MOVETYPE_PUSH, MOVETYPE_WALK, model_t::normalmaxs, model_t::normalmins, origin, other, owner, prvm_edict_t::priv, PRVM_EDICT_NUM, PRVM_EDICT_TO_PROG, PRVM_NUM_FOR_EDICT, PRVM_PROG_TO_EDICT, PRVM_serveredictedict, PRVM_serveredictfloat, PRVM_serveredictfunction, PRVM_serveredictvector, PRVM_serverglobaledict, PRVM_serverglobalfloat, model_t::rotatedmaxs, model_t::rotatedmins, self, prvm_edict_t::server, solid, SOLID_BBOX, SOLID_BSP, SOLID_CORPSE, SOLID_NOT, SOLID_SLIDEBOX, SOLID_TRIGGER, trace_t::startsolid, SUPERCONTENTS_BODY, sv, SV_EntitiesInBox(), sv_gameplayfix_nosquashentities, SV_GenericHitSuperContentsMask(), SV_GetModelByIndex(), SV_GetModelFromEdict(), SV_LinkEdict(), SV_LinkEdict_TouchAreaGrid(), SV_NudgeOutOfSolid_PivotIsKnownGood(), SV_PushEntity(), SVVM_prog, server_t::time, time, up, cvar_t::value, VectorAdd, VectorClear, VectorCopy, VectorLength2, VectorLerp, VectorMA, VectorNegate, VectorScale, VectorSubtract, velocity, model_t::yawmaxs, and model_t::yawmins.

Referenced by SV_Physics_Pusher().

◆ SV_RunThink()

static qbool SV_RunThink ( prvm_edict_t * ent)
static

Definition at line 1015 of file sv_phys.c.

1016{
1017 prvm_prog_t *prog = SVVM_prog;
1018 int iterations;
1019
1020 // don't let things stay in the past.
1021 // it is possible to start that way by a trigger with a local time.
1023 return true;
1024
1025 for (iterations = 0;iterations < 128 && !ent->free;iterations++)
1026 {
1031 prog->ExecuteProgram(prog, PRVM_serveredictfunction(ent, think), "QC function self.think is missing");
1032 // mods often set nextthink to time to cause a think every frame,
1033 // we don't want to loop in that case, so exit if the new nextthink is
1034 // <= the time the qc was told, also exit if it is past the end of the
1035 // frame
1037 break;
1038 }
1039 return !ent->free;
1040}
cvar_t sv_gameplayfix_multiplethinksperframe
Definition sv_main.c:114

References prvm_prog_t::edicts, prvm_prog_t::ExecuteProgram, server_t::frametime, prvm_edict_t::free, cvar_t::integer, max, nextthink, other, PRVM_EDICT_TO_PROG, PRVM_serveredictfloat, PRVM_serveredictfunction, PRVM_serverglobaledict, PRVM_serverglobalfloat, self, sv, sv_gameplayfix_multiplethinksperframe, SVVM_prog, server_t::time, and time.

Referenced by SV_Physics_ClientEntity(), and SV_Physics_Entity().

◆ SV_TraceBox()

trace_t SV_TraceBox ( const vec3_t start,
const vec3_t mins,
const vec3_t maxs,
const vec3_t end,
int type,
prvm_edict_t * passedict,
int hitsupercontentsmask,
int skipsupercontentsmask,
int skipmaterialflagsmask,
float extend )

traces a box move against worldmodel and all entities in the specified area

Definition at line 414 of file sv_phys.c.

416{
417 prvm_prog_t *prog = SVVM_prog;
418 vec3_t hullmins, hullmaxs;
419 int i, bodysupercontents;
420 int passedictprog;
421 float pitchsign = 1;
422 qbool pointtrace;
423 prvm_edict_t *traceowner, *touch;
424 trace_t trace;
425 // temporary storage because prvm_vec_t may differ from vec_t
426 vec3_t touchmins, touchmaxs;
427 // bounding box of entire move area
428 vec3_t clipboxmins, clipboxmaxs;
429 // size of the moving object
430 vec3_t clipmins, clipmaxs;
431 // size when clipping against monsters
432 vec3_t clipmins2, clipmaxs2;
433 // start and end origin of move
434 vec3_t clipstart, clipend;
435 // trace results
436 trace_t cliptrace;
437 // matrices to transform into/out of other entity's space
438 matrix4x4_t matrix, imatrix;
439 // model of other entity
440 model_t *model;
441 // list of entities to test for collisions
442 int numtouchedicts;
443 static prvm_edict_t *touchedicts[MAX_EDICTS];
444 int clipgroup;
445 if (VectorCompare(mins, maxs))
446 {
447 vec3_t shiftstart, shiftend;
448 VectorAdd(start, mins, shiftstart);
449 VectorAdd(end, mins, shiftend);
450 if (VectorCompare(start, end))
451 trace = SV_TracePoint(shiftstart, type, passedict, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
452 else
453 trace = SV_TraceLine(shiftstart, shiftend, type, passedict, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask, extend);
454 VectorSubtract(trace.endpos, mins, trace.endpos);
455 return trace;
456 }
457
458 VectorCopy(start, clipstart);
459 VectorCopy(end, clipend);
460 VectorCopy(mins, clipmins);
461 VectorCopy(maxs, clipmaxs);
462 VectorCopy(mins, clipmins2);
463 VectorCopy(maxs, clipmaxs2);
464#if COLLISIONPARANOID >= 3
465 Con_Printf("move(%f %f %f,%f %f %f)", clipstart[0], clipstart[1], clipstart[2], clipend[0], clipend[1], clipend[2]);
466#endif
467
468 // clip to world
469 Collision_ClipToWorld(&cliptrace, sv.worldmodel, clipstart, clipmins, clipmaxs, clipend, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask, extend);
470 cliptrace.worldstartsolid = cliptrace.bmodelstartsolid = cliptrace.startsolid;
471 if (cliptrace.startsolid || cliptrace.fraction < 1)
472 cliptrace.ent = prog->edicts;
473 if (type == MOVE_WORLDONLY)
474 goto finished;
475
476 if (type == MOVE_MISSILE)
477 {
478 // LadyHavoc: modified this, was = -15, now -= 15
479 for (i = 0;i < 3;i++)
480 {
481 clipmins2[i] -= 15;
482 clipmaxs2[i] += 15;
483 }
484 }
485
486 // get adjusted box for bmodel collisions if the world is q1bsp or hlbsp
487 if (sv.worldmodel && sv.worldmodel->brush.RoundUpToHullSize)
488 sv.worldmodel->brush.RoundUpToHullSize(sv.worldmodel, clipmins, clipmaxs, hullmins, hullmaxs);
489 else
490 {
491 VectorCopy(clipmins, hullmins);
492 VectorCopy(clipmaxs, hullmaxs);
493 }
494
495 // create the bounding box of the entire move
496 for (i = 0;i < 3;i++)
497 {
498 clipboxmins[i] = min(clipstart[i], cliptrace.endpos[i]) + min(hullmins[i], clipmins2[i]) - 1;
499 clipboxmaxs[i] = max(clipstart[i], cliptrace.endpos[i]) + max(hullmaxs[i], clipmaxs2[i]) + 1;
500 }
501
502 // debug override to test against everything
504 {
505 clipboxmins[0] = clipboxmins[1] = clipboxmins[2] = (vec_t)-999999999;
506 clipboxmaxs[0] = clipboxmaxs[1] = clipboxmaxs[2] = (vec_t)999999999;
507 }
508
509 // if the passedict is world, make it NULL (to avoid two checks each time)
510 if (passedict == prog->edicts)
511 passedict = NULL;
512 // precalculate prog value for passedict for comparisons
513 passedictprog = PRVM_EDICT_TO_PROG(passedict);
514 // figure out whether this is a point trace for comparisons
515 pointtrace = VectorCompare(clipmins, clipmaxs);
516 // precalculate passedict's owner edict pointer for comparisons
517 traceowner = passedict ? PRVM_PROG_TO_EDICT(PRVM_serveredictedict(passedict, owner)) : 0;
518
519 clipgroup = passedict ? (int)PRVM_serveredictfloat(passedict, clipgroup) : 0;
520
521 // clip to entities
522 // because this uses World_EntitiestoBox, we know all entity boxes overlap
523 // the clip region, so we can skip culling checks in the loop below
524 numtouchedicts = SV_EntitiesInBox(clipboxmins, clipboxmaxs, MAX_EDICTS, touchedicts);
525 if (numtouchedicts > MAX_EDICTS)
526 {
527 // this never happens
528 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
529 numtouchedicts = MAX_EDICTS;
530 }
531 for (i = 0;i < numtouchedicts;i++)
532 {
533 touch = touchedicts[i];
534
536 continue;
538 continue;
539
540 if (passedict)
541 {
542 // don't clip against self
543 if (passedict == touch)
544 continue;
545 // don't clip owned entities against owner
546 if (traceowner == touch)
547 continue;
548 // don't clip owner against owned entities
549 if (passedictprog == PRVM_serveredictedict(touch, owner))
550 continue;
551 // don't clip against any entities in the same clipgroup (DP_RM_CLIPGROUP)
552 if (clipgroup && clipgroup == (int)PRVM_serveredictfloat(touch, clipgroup))
553 continue;
554 // don't clip points against points (they can't collide)
555 if (pointtrace && VectorCompare(PRVM_serveredictvector(touch, mins), PRVM_serveredictvector(touch, maxs)) && (type != MOVE_MISSILE || !((int)PRVM_serveredictfloat(touch, flags) & FL_MONSTER)))
556 continue;
557 }
558
560
561 // might interact, so do an exact clip
562 model = NULL;
563 if ((int) PRVM_serveredictfloat(touch, solid) == SOLID_BSP || type == MOVE_HITMODEL)
564 {
566 pitchsign = SV_GetPitchSign(prog, touch);
567 }
568 if (model)
570 else
572 Matrix4x4_Invert_Simple(&imatrix, &matrix);
573 VM_GenerateFrameGroupBlend(prog, touch->priv.server->framegroupblend, touch);
574 VM_FrameBlendFromFrameGroupBlend(touch->priv.server->frameblend, touch->priv.server->framegroupblend, model, sv.time);
575 VM_UpdateEdictSkeleton(prog, touch, model, touch->priv.server->frameblend);
576 VectorCopy(PRVM_serveredictvector(touch, mins), touchmins);
577 VectorCopy(PRVM_serveredictvector(touch, maxs), touchmaxs);
578 if (type == MOVE_MISSILE && (int)PRVM_serveredictfloat(touch, flags) & FL_MONSTER)
579 Collision_ClipToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, touchmins, touchmaxs, bodysupercontents, &matrix, &imatrix, clipstart, clipmins2, clipmaxs2, clipend, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask, extend);
580 else
581 Collision_ClipToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, touchmins, touchmaxs, bodysupercontents, &matrix, &imatrix, clipstart, clipmins, clipmaxs, clipend, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask, extend);
582
583 Collision_CombineTraces(&cliptrace, &trace, (void *)touch, PRVM_serveredictfloat(touch, solid) == SOLID_BSP);
584 }
585
586finished:
587 return cliptrace;
588}
void Collision_ClipToWorld(trace_t *trace, model_t *model, const vec3_t tstart, const vec3_t mins, const vec3_t maxs, const vec3_t tend, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask, float extend)
Definition collision.c:1834
void Collision_CombineTraces(trace_t *cliptrace, const trace_t *trace, void *touch, qbool isbmodel)
Definition collision.c:1914
float clipgroup
void Matrix4x4_CreateTranslate(matrix4x4_t *out, double x, double y, double z)
Definition matrixlib.c:584
cvar_t sv_debugmove
Definition sv_main.c:97
trace_t SV_TracePoint(const vec3_t start, int type, prvm_edict_t *passedict, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
Definition sv_phys.c:104
trace_t SV_TraceLine(const vec3_t start, const vec3_t end, int type, prvm_edict_t *passedict, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask, float extend)
Definition sv_phys.c:256
int SV_GetPitchSign(prvm_prog_t *prog, prvm_edict_t *ent)
Definition sv_phys.c:47
#define MOVE_HITMODEL
Definition world.h:32

References angles, trace_t::bmodelstartsolid, clipgroup, Collision_ClipToGenericEntity(), Collision_ClipToWorld(), Collision_CombineTraces(), Con_Printf(), prvm_prog_t::edicts, trace_t::endpos, trace_t::ent, FL_MONSTER, flags, trace_t::fraction, i, int(), cvar_t::integer, Matrix4x4_CreateFromQuakeEntity(), Matrix4x4_CreateTranslate(), Matrix4x4_Invert_Simple(), max, MAX_EDICTS, maxs, min, mins, model, MOVE_HITMODEL, MOVE_MISSILE, MOVE_NOMONSTERS, MOVE_WORLDONLY, NULL, origin, owner, prvm_edict_t::priv, PRVM_EDICT_TO_PROG, PRVM_PROG_TO_EDICT, PRVM_serveredictedict, PRVM_serveredictfloat, PRVM_serveredictvector, prvm_edict_t::server, solid, SOLID_BBOX, SOLID_BSP, SOLID_CORPSE, trace_t::startsolid, SUPERCONTENTS_BODY, SUPERCONTENTS_CORPSE, sv, sv_debugmove, SV_EntitiesInBox(), SV_GetModelFromEdict(), SV_GetPitchSign(), SV_TraceLine(), SV_TracePoint(), SVVM_prog, server_t::time, type, VectorAdd, VectorCompare, VectorCopy, VectorSubtract, VM_FrameBlendFromFrameGroupBlend(), VM_GenerateFrameGroupBlend(), VM_UpdateEdictSkeleton(), server_t::worldmodel, and trace_t::worldstartsolid.

Referenced by PHYS_TraceBox(), SV_movestep(), SV_NudgeOutOfSolid_PivotIsKnownGood(), SV_PushEntity(), SV_Trace_Toss(), SV_WalkMove(), VM_SV_droptofloor(), and VM_SV_tracebox().

◆ SV_TraceLine()

trace_t SV_TraceLine ( const vec3_t start,
const vec3_t end,
int type,
prvm_edict_t * passedict,
int hitsupercontentsmask,
int skipsupercontentsmask,
int skipmaterialflagsmask,
float extend )

Definition at line 256 of file sv_phys.c.

257{
258 prvm_prog_t *prog = SVVM_prog;
259 int i, bodysupercontents;
260 int passedictprog;
261 float pitchsign = 1;
262 prvm_edict_t *traceowner, *touch;
263 trace_t trace;
264 // temporary storage because prvm_vec_t may differ from vec_t
265 vec3_t touchmins, touchmaxs;
266 // bounding box of entire move area
267 vec3_t clipboxmins, clipboxmaxs;
268 // size when clipping against monsters
269 vec3_t clipmins2, clipmaxs2;
270 // start and end origin of move
271 vec3_t clipstart, clipend;
272 // trace results
273 trace_t cliptrace;
274 // matrices to transform into/out of other entity's space
275 matrix4x4_t matrix, imatrix;
276 // model of other entity
277 model_t *model;
278 // list of entities to test for collisions
279 int numtouchedicts;
280 static prvm_edict_t *touchedicts[MAX_EDICTS];
281 int clipgroup;
282 if (VectorCompare(start, end))
283 return SV_TracePoint(start, type, passedict, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
284
285 //return SV_TraceBox(start, vec3_origin, vec3_origin, end, type, passedict, hitsupercontentsmask);
286
287 VectorCopy(start, clipstart);
288 VectorCopy(end, clipend);
289 VectorClear(clipmins2);
290 VectorClear(clipmaxs2);
291#if COLLISIONPARANOID >= 3
292 Con_Printf("move(%f %f %f,%f %f %f)", clipstart[0], clipstart[1], clipstart[2], clipend[0], clipend[1], clipend[2]);
293#endif
294
295 // clip to world
296 Collision_ClipLineToWorld(&cliptrace, sv.worldmodel, clipstart, clipend, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask, extend, false);
297 cliptrace.worldstartsolid = cliptrace.bmodelstartsolid = cliptrace.startsolid;
298 if (cliptrace.startsolid || cliptrace.fraction < 1)
299 cliptrace.ent = prog->edicts;
300 if (type == MOVE_WORLDONLY)
301 goto finished;
302
303 if (type == MOVE_MISSILE)
304 {
305 // LadyHavoc: modified this, was = -15, now -= 15
306 for (i = 0;i < 3;i++)
307 {
308 clipmins2[i] -= 15;
309 clipmaxs2[i] += 15;
310 }
311 }
312
313 // create the bounding box of the entire move
314 for (i = 0;i < 3;i++)
315 {
316 clipboxmins[i] = min(clipstart[i], cliptrace.endpos[i]) + clipmins2[i] - 1;
317 clipboxmaxs[i] = max(clipstart[i], cliptrace.endpos[i]) + clipmaxs2[i] + 1;
318 }
319
320 // debug override to test against everything
322 {
323 clipboxmins[0] = clipboxmins[1] = clipboxmins[2] = (vec_t)-999999999;
324 clipboxmaxs[0] = clipboxmaxs[1] = clipboxmaxs[2] = (vec_t)999999999;
325 }
326
327 // if the passedict is world, make it NULL (to avoid two checks each time)
328 if (passedict == prog->edicts)
329 passedict = NULL;
330 // precalculate prog value for passedict for comparisons
331 passedictprog = PRVM_EDICT_TO_PROG(passedict);
332 // precalculate passedict's owner edict pointer for comparisons
333 traceowner = passedict ? PRVM_PROG_TO_EDICT(PRVM_serveredictedict(passedict, owner)) : 0;
334
335 clipgroup = passedict ? (int)PRVM_serveredictfloat(passedict, clipgroup) : 0;
336
337 // clip to entities
338 // because this uses World_EntitiestoBox, we know all entity boxes overlap
339 // the clip region, so we can skip culling checks in the loop below
340 numtouchedicts = SV_EntitiesInBox(clipboxmins, clipboxmaxs, MAX_EDICTS, touchedicts);
341 if (numtouchedicts > MAX_EDICTS)
342 {
343 // this never happens
344 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
345 numtouchedicts = MAX_EDICTS;
346 }
347 for (i = 0;i < numtouchedicts;i++)
348 {
349 touch = touchedicts[i];
350
352 continue;
354 continue;
355
356 if (passedict)
357 {
358 // don't clip against self
359 if (passedict == touch)
360 continue;
361 // don't clip owned entities against owner
362 if (traceowner == touch)
363 continue;
364 // don't clip owner against owned entities
365 if (passedictprog == PRVM_serveredictedict(touch, owner))
366 continue;
367 // don't clip against any entities in the same clipgroup (DP_RM_CLIPGROUP)
368 if (clipgroup && clipgroup == (int)PRVM_serveredictfloat(touch, clipgroup))
369 continue;
370 // don't clip points against points (they can't collide)
372 continue;
373 }
374
376
377 // might interact, so do an exact clip
378 model = NULL;
379 if ((int) PRVM_serveredictfloat(touch, solid) == SOLID_BSP || type == MOVE_HITMODEL)
380 {
382 pitchsign = SV_GetPitchSign(prog, touch);
383 }
384 if (model)
386 else
388 Matrix4x4_Invert_Simple(&imatrix, &matrix);
389 VM_GenerateFrameGroupBlend(prog, touch->priv.server->framegroupblend, touch);
390 VM_FrameBlendFromFrameGroupBlend(touch->priv.server->frameblend, touch->priv.server->framegroupblend, model, sv.time);
391 VM_UpdateEdictSkeleton(prog, touch, model, touch->priv.server->frameblend);
392 VectorCopy(PRVM_serveredictvector(touch, mins), touchmins);
393 VectorCopy(PRVM_serveredictvector(touch, maxs), touchmaxs);
394 if (type == MOVE_MISSILE && (int)PRVM_serveredictfloat(touch, flags) & FL_MONSTER)
395 Collision_ClipToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, touchmins, touchmaxs, bodysupercontents, &matrix, &imatrix, clipstart, clipmins2, clipmaxs2, clipend, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask, extend);
396 else
397 Collision_ClipLineToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, touchmins, touchmaxs, bodysupercontents, &matrix, &imatrix, clipstart, clipend, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask, extend, false);
398
399 Collision_CombineTraces(&cliptrace, &trace, (void *)touch, PRVM_serveredictfloat(touch, solid) == SOLID_BSP);
400 }
401
402finished:
403 return cliptrace;
404}
void Collision_ClipLineToWorld(trace_t *trace, model_t *model, const vec3_t tstart, const vec3_t tend, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask, float extend, qbool hitsurfaces)
Definition collision.c:1870
void Collision_ClipLineToGenericEntity(trace_t *trace, model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, const vec3_t bodymins, const vec3_t bodymaxs, int bodysupercontents, matrix4x4_t *matrix, matrix4x4_t *inversematrix, const vec3_t tstart, const vec3_t tend, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask, float extend, qbool hitsurfaces)
Definition collision.c:1844

References angles, trace_t::bmodelstartsolid, clipgroup, Collision_ClipLineToGenericEntity(), Collision_ClipLineToWorld(), Collision_ClipToGenericEntity(), Collision_CombineTraces(), Con_Printf(), prvm_prog_t::edicts, trace_t::endpos, trace_t::ent, FL_MONSTER, flags, trace_t::fraction, i, int(), cvar_t::integer, Matrix4x4_CreateFromQuakeEntity(), Matrix4x4_CreateTranslate(), Matrix4x4_Invert_Simple(), max, MAX_EDICTS, maxs, min, mins, model, MOVE_HITMODEL, MOVE_MISSILE, MOVE_NOMONSTERS, MOVE_WORLDONLY, NULL, origin, owner, prvm_edict_t::priv, PRVM_EDICT_TO_PROG, PRVM_PROG_TO_EDICT, PRVM_serveredictedict, PRVM_serveredictfloat, PRVM_serveredictvector, prvm_edict_t::server, solid, SOLID_BBOX, SOLID_BSP, SOLID_CORPSE, trace_t::startsolid, SUPERCONTENTS_BODY, SUPERCONTENTS_CORPSE, sv, sv_debugmove, SV_EntitiesInBox(), SV_GetModelFromEdict(), SV_GetPitchSign(), SV_TracePoint(), SVVM_prog, server_t::time, type, VectorClear, VectorCompare, VectorCopy, VM_FrameBlendFromFrameGroupBlend(), VM_GenerateFrameGroupBlend(), VM_UpdateEdictSkeleton(), server_t::worldmodel, and trace_t::worldstartsolid.

Referenced by Sbar_ShowFPS(), SV_CheckBottom(), SV_Ent_Create_f(), SV_Ent_Remove_f(), SV_SetIdealPitch(), SV_TraceBox(), SV_UserFriction(), VM_SV_aim(), VM_SV_droptofloor(), and VM_SV_traceline().

◆ SV_TracePoint()

trace_t SV_TracePoint ( const vec3_t start,
int type,
prvm_edict_t * passedict,
int hitsupercontentsmask,
int skipsupercontentsmask,
int skipmaterialflagsmask )

Definition at line 104 of file sv_phys.c.

105{
106 prvm_prog_t *prog = SVVM_prog;
107 int i, bodysupercontents;
108 int passedictprog;
109 float pitchsign = 1;
110 prvm_edict_t *traceowner, *touch;
111 trace_t trace;
112 // temporary storage because prvm_vec_t may differ from vec_t
113 vec3_t touchmins, touchmaxs;
114 // bounding box of entire move area
115 vec3_t clipboxmins, clipboxmaxs;
116 // size when clipping against monsters
117 vec3_t clipmins2, clipmaxs2;
118 // start and end origin of move
119 vec3_t clipstart;
120 // trace results
121 trace_t cliptrace;
122 // matrices to transform into/out of other entity's space
123 matrix4x4_t matrix, imatrix;
124 // model of other entity
125 model_t *model;
126 // list of entities to test for collisions
127 int numtouchedicts;
128 static prvm_edict_t *touchedicts[MAX_EDICTS];
129 int clipgroup;
130
131 //return SV_TraceBox(start, vec3_origin, vec3_origin, end, type, passedict, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
132
133 VectorCopy(start, clipstart);
134 VectorClear(clipmins2);
135 VectorClear(clipmaxs2);
136#if COLLISIONPARANOID >= 3
137 Con_Printf("move(%f %f %f)", clipstart[0], clipstart[1], clipstart[2]);
138#endif
139
140 // clip to world
141 Collision_ClipPointToWorld(&cliptrace, sv.worldmodel, clipstart, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
142 cliptrace.worldstartsolid = cliptrace.bmodelstartsolid = cliptrace.startsolid;
143 if (cliptrace.startsolid || cliptrace.fraction < 1)
144 cliptrace.ent = prog->edicts;
145 if (type == MOVE_WORLDONLY)
146 goto finished;
147
148 if (type == MOVE_MISSILE)
149 {
150 // LadyHavoc: modified this, was = -15, now -= 15
151 for (i = 0;i < 3;i++)
152 {
153 clipmins2[i] -= 15;
154 clipmaxs2[i] += 15;
155 }
156 }
157
158 // create the bounding box of the entire move
159 for (i = 0;i < 3;i++)
160 {
161 clipboxmins[i] = min(clipstart[i], cliptrace.endpos[i]) + clipmins2[i] - 1;
162 clipboxmaxs[i] = max(clipstart[i], cliptrace.endpos[i]) + clipmaxs2[i] + 1;
163 }
164
165 // debug override to test against everything
167 {
168 clipboxmins[0] = clipboxmins[1] = clipboxmins[2] = (vec_t)-999999999;
169 clipboxmaxs[0] = clipboxmaxs[1] = clipboxmaxs[2] = (vec_t)999999999;
170 }
171
172 // if the passedict is world, make it NULL (to avoid two checks each time)
173 if (passedict == prog->edicts)
174 passedict = NULL;
175 // precalculate prog value for passedict for comparisons
176 passedictprog = PRVM_EDICT_TO_PROG(passedict);
177 // precalculate passedict's owner edict pointer for comparisons
178 traceowner = passedict ? PRVM_PROG_TO_EDICT(PRVM_serveredictedict(passedict, owner)) : 0;
179
180 clipgroup = passedict ? (int)PRVM_serveredictfloat(passedict, clipgroup) : 0;
181
182 // clip to entities
183 // because this uses World_EntitiestoBox, we know all entity boxes overlap
184 // the clip region, so we can skip culling checks in the loop below
185 numtouchedicts = SV_EntitiesInBox(clipboxmins, clipboxmaxs, MAX_EDICTS, touchedicts);
186 if (numtouchedicts > MAX_EDICTS)
187 {
188 // this never happens
189 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
190 numtouchedicts = MAX_EDICTS;
191 }
192 for (i = 0;i < numtouchedicts;i++)
193 {
194 touch = touchedicts[i];
195
197 continue;
199 continue;
200
201 if (passedict)
202 {
203 // don't clip against self
204 if (passedict == touch)
205 continue;
206 // don't clip owned entities against owner
207 if (traceowner == touch)
208 continue;
209 // don't clip owner against owned entities
210 if (passedictprog == PRVM_serveredictedict(touch, owner))
211 continue;
212 // don't clip against any entities in the same clipgroup (DP_RM_CLIPGROUP)
213 if (clipgroup && clipgroup == (int)PRVM_serveredictfloat(touch, clipgroup))
214 continue;
215 // don't clip points against points (they can't collide)
217 continue;
218 }
219
221
222 // might interact, so do an exact clip
223 model = NULL;
224 if ((int) PRVM_serveredictfloat(touch, solid) == SOLID_BSP || type == MOVE_HITMODEL)
225 {
227 pitchsign = SV_GetPitchSign(prog, touch);
228 }
229 if (model)
231 else
233 Matrix4x4_Invert_Simple(&imatrix, &matrix);
234 VM_GenerateFrameGroupBlend(prog, touch->priv.server->framegroupblend, touch);
235 VM_FrameBlendFromFrameGroupBlend(touch->priv.server->frameblend, touch->priv.server->framegroupblend, model, sv.time);
236 VM_UpdateEdictSkeleton(prog, touch, model, touch->priv.server->frameblend);
237 VectorCopy(PRVM_serveredictvector(touch, mins), touchmins);
238 VectorCopy(PRVM_serveredictvector(touch, maxs), touchmaxs);
239 if (type == MOVE_MISSILE && (int)PRVM_serveredictfloat(touch, flags) & FL_MONSTER)
240 Collision_ClipToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, touchmins, touchmaxs, bodysupercontents, &matrix, &imatrix, clipstart, clipmins2, clipmaxs2, clipstart, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask, 0.0f);
241 else
242 Collision_ClipPointToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, touchmins, touchmaxs, bodysupercontents, &matrix, &imatrix, clipstart, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
243
244 Collision_CombineTraces(&cliptrace, &trace, (void *)touch, PRVM_serveredictfloat(touch, solid) == SOLID_BSP);
245 }
246
247finished:
248 return cliptrace;
249}
void Collision_ClipPointToWorld(trace_t *trace, model_t *model, const vec3_t start, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
Definition collision.c:1905
void Collision_ClipPointToGenericEntity(trace_t *trace, model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, const vec3_t bodymins, const vec3_t bodymaxs, int bodysupercontents, matrix4x4_t *matrix, matrix4x4_t *inversematrix, const vec3_t start, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
Definition collision.c:1883

References angles, trace_t::bmodelstartsolid, clipgroup, Collision_ClipPointToGenericEntity(), Collision_ClipPointToWorld(), Collision_ClipToGenericEntity(), Collision_CombineTraces(), Con_Printf(), prvm_prog_t::edicts, trace_t::endpos, trace_t::ent, FL_MONSTER, flags, trace_t::fraction, i, int(), cvar_t::integer, Matrix4x4_CreateFromQuakeEntity(), Matrix4x4_CreateTranslate(), Matrix4x4_Invert_Simple(), max, MAX_EDICTS, maxs, min, mins, model, MOVE_HITMODEL, MOVE_MISSILE, MOVE_NOMONSTERS, MOVE_WORLDONLY, NULL, origin, owner, prvm_edict_t::priv, PRVM_EDICT_TO_PROG, PRVM_PROG_TO_EDICT, PRVM_serveredictedict, PRVM_serveredictfloat, PRVM_serveredictvector, prvm_edict_t::server, solid, SOLID_BBOX, SOLID_BSP, SOLID_CORPSE, trace_t::startsolid, SUPERCONTENTS_BODY, SUPERCONTENTS_CORPSE, sv, sv_debugmove, SV_EntitiesInBox(), SV_GetModelFromEdict(), SV_GetPitchSign(), SVVM_prog, server_t::time, type, VectorClear, VectorCompare, VectorCopy, VM_FrameBlendFromFrameGroupBlend(), VM_GenerateFrameGroupBlend(), VM_UpdateEdictSkeleton(), server_t::worldmodel, and trace_t::worldstartsolid.

Referenced by SV_TraceBox(), and SV_TraceLine().

◆ SV_UnstickEntity()

static qbool SV_UnstickEntity ( prvm_edict_t * ent)
static

Definition at line 1956 of file sv_phys.c.

1957{
1958 prvm_prog_t *prog = SVVM_prog;
1959 vec3_t offset;
1960
1962 {
1964 switch (PHYS_NudgeOutOfSolid(prog, ent))
1965 {
1966 case UNSTICK_GOOD:
1967 return true;
1968 case UNSTICK_UNSTUCK:
1970 Con_DPrintf("NudgeOutOfSolid fixed stuck entity %i (classname \"%s\") with offset %f %f %f.\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(prog, PRVM_serveredictstring(ent, classname)), offset[0], offset[1], offset[2]);
1971 return true;
1972 case UNSTICK_STUCK:
1973 Con_DPrintf(CON_WARN "NudgeOutOfSolid couldn't fix stuck entity %i (classname \"%s\").\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(prog, PRVM_serveredictstring(ent, classname)));
1974 return false;
1975 default:
1976 Con_Printf("NudgeOutOfSolid returned a value outside its enum.\n");
1977 return false;
1978 }
1979 }
1980
1982 return false;
1983
1984 switch(PHYS_UnstickEntityReturnOffset(prog, ent, offset))
1985 {
1986 case UNSTICK_GOOD:
1987 return true;
1988 case UNSTICK_UNSTUCK:
1989 Con_DPrintf("Unstuck entity %i (classname \"%s\") with offset %f %f %f.\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(prog, PRVM_serveredictstring(ent, classname)), offset[0], offset[1], offset[2]);
1990 return true;
1991 case UNSTICK_STUCK:
1993 if (!PHYS_TestEntityPosition(prog, ent, offset))
1994 {
1995 Con_DPrintf("Unstuck entity %i (classname \"%s\") by restoring oldorigin.\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(prog, PRVM_serveredictstring(ent, classname)));
1996 return true;
1997 }
1998 Con_DPrintf(CON_WARN "Stuck entity %i (classname \"%s\").\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(prog, PRVM_serveredictstring(ent, classname)));
1999 return false;
2000 default:
2001 Con_Printf("UnstickEntityReturnOffset returned a value outside its enum.\n");
2002 return false;
2003 }
2004}
#define CON_WARN
Definition console.h:101
GLuint GLuint GLintptr offset
Definition glquake.h:632
unstickresult_t PHYS_UnstickEntityReturnOffset(prvm_prog_t *prog, prvm_edict_t *ent, vec3_t offset)
Definition phys.c:102
unstickresult_t PHYS_NudgeOutOfSolid(prvm_prog_t *prog, prvm_edict_t *ent)
Definition phys.c:136
qbool PHYS_TestEntityPosition(prvm_prog_t *prog, prvm_edict_t *ent, vec3_t offset)
Definition phys.c:24
@ UNSTICK_GOOD
didn't need to be unstuck
Definition phys.h:13
@ UNSTICK_STUCK
Definition phys.h:12
@ UNSTICK_UNSTUCK
Definition phys.h:14
cvar_t sv_gameplayfix_nudgeoutofsolid_separation
Definition sv_main.c:118
cvar_t sv_gameplayfix_unstickplayers
Definition sv_main.c:130
cvar_t sv_gameplayfix_nudgeoutofsolid
Definition sv_main.c:117
cvar_t sv_gameplayfix_unstickentities
Definition sv_main.c:131

References classname, Con_DPrintf(), Con_Printf(), CON_WARN, cvar_t::integer, server_static_t::maxclients, offset, oldorigin, origin, PHYS_NudgeOutOfSolid(), PHYS_TestEntityPosition(), PHYS_UnstickEntityReturnOffset(), PRVM_EDICT_TO_PROG, PRVM_GetString(), PRVM_NUM_FOR_EDICT, PRVM_serveredictstring, PRVM_serveredictvector, sv_gameplayfix_nudgeoutofsolid, sv_gameplayfix_nudgeoutofsolid_separation, sv_gameplayfix_unstickentities, sv_gameplayfix_unstickplayers, svs, SVVM_prog, UNSTICK_GOOD, UNSTICK_STUCK, UNSTICK_UNSTUCK, cvar_t::value, VectorCopy, and VectorSubtract.

Referenced by SV_PushEntity().

◆ SV_WalkMove()

static void SV_WalkMove ( prvm_edict_t * ent)
static

Definition at line 2152 of file sv_phys.c.

2153{
2154 prvm_prog_t *prog = SVVM_prog;
2155 int clip;
2156 int oldonground;
2157 //int originalmove_clip;
2158 int originalmove_flags;
2159 int originalmove_groundentity;
2160 int hitsupercontentsmask = SV_GenericHitSuperContentsMask(ent);
2161 int skipsupercontentsmask = 0;
2162 int skipmaterialflagsmask = 0;
2163 int type;
2164 vec3_t upmove, downmove, start_origin, start_velocity, stepnormal, originalmove_origin, originalmove_velocity, entmins, entmaxs;
2165 trace_t downtrace, trace;
2166 qbool applygravity;
2167
2168 // if frametime is 0 (due to client sending the same timestamp twice),
2169 // don't move
2170 if (sv.frametime <= 0)
2171 return;
2172
2173 applygravity = !SV_CheckWater (ent) && PRVM_serveredictfloat(ent, movetype) == MOVETYPE_WALK && ! ((int)PRVM_serveredictfloat(ent, flags) & FL_WATERJUMP);
2174
2175 SV_CheckVelocity(ent);
2176
2177 // do a regular slide move unless it looks like you ran into a step
2178 oldonground = (int)PRVM_serveredictfloat(ent, flags) & FL_ONGROUND;
2179
2180 VectorCopy (PRVM_serveredictvector(ent, origin), start_origin);
2181 VectorCopy (PRVM_serveredictvector(ent, velocity), start_velocity);
2182
2183 clip = SV_FlyMove (ent, sv.frametime, applygravity, NULL, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask, sv_gameplayfix_stepmultipletimes.integer ? sv_stepheight.value : 0);
2184
2186 if(!(clip & 1))
2187 {
2188 // only try this if there was no floor in the way in the trace (no,
2189 // this check seems to be not REALLY necessary, because if clip & 1,
2190 // our trace will hit that thing too)
2198 type = MOVE_NOMONSTERS; // only clip against bmodels
2199 else
2200 type = MOVE_NORMAL;
2201 VectorCopy(PRVM_serveredictvector(ent, mins), entmins);
2202 VectorCopy(PRVM_serveredictvector(ent, maxs), entmaxs);
2203 trace = SV_TraceBox(upmove, entmins, entmaxs, downmove, type, ent, SV_GenericHitSuperContentsMask(ent), skipsupercontentsmask, skipmaterialflagsmask, collision_extendmovelength.value);
2204 if(trace.fraction < 1 && trace.plane.normal[2] > 0.7)
2205 {
2206 clip |= 1; // but we HAVE found a floor
2207 // set groundentity so we get carried when walking onto a mover with sv_gameplayfix_nogravityonground
2209 }
2210 }
2211
2212 // if the move did not hit the ground at any point, we're not on ground
2213 if(!(clip & 1))
2214 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) & ~FL_ONGROUND;
2215
2216 SV_CheckVelocity(ent);
2217 SV_LinkEdict(ent);
2219
2220 if(clip & 8) // teleport
2221 return;
2222
2223 if ((int)PRVM_serveredictfloat(ent, flags) & FL_WATERJUMP)
2224 return;
2225
2226 if (sv_nostep.integer)
2227 return;
2228
2229 VectorCopy(PRVM_serveredictvector(ent, origin), originalmove_origin);
2230 VectorCopy(PRVM_serveredictvector(ent, velocity), originalmove_velocity);
2231 //originalmove_clip = clip;
2232 originalmove_flags = (int)PRVM_serveredictfloat(ent, flags);
2233 originalmove_groundentity = PRVM_serveredictedict(ent, groundentity);
2234
2235 // if move didn't block on a step, return
2236 if (clip & 2)
2237 {
2238 // if move was not trying to move into the step, return
2239 if (fabs(start_velocity[0]) < 0.03125 && fabs(start_velocity[1]) < 0.03125)
2240 return;
2241
2243 {
2244 // return if gibbed by a trigger
2246 return;
2247
2248 // return if attempting to jump while airborn (unless sv_jumpstep)
2249 if (!sv_jumpstep.integer)
2250 if (!oldonground && PRVM_serveredictfloat(ent, waterlevel) == 0)
2251 return;
2252 }
2253
2254 // try moving up and forward to go up a step
2255 // back to start pos
2256 VectorCopy (start_origin, PRVM_serveredictvector(ent, origin));
2257 VectorCopy (start_velocity, PRVM_serveredictvector(ent, velocity));
2258
2259 // move up
2260 VectorClear (upmove);
2261 upmove[2] = sv_stepheight.value;
2262 if(!SV_PushEntity(&trace, ent, upmove, true, true))
2263 {
2264 // we got teleported when upstepping... must abort the move
2265 return;
2266 }
2267
2268 // move forward
2269 PRVM_serveredictvector(ent, velocity)[2] = 0;
2270 clip = SV_FlyMove (ent, sv.frametime, applygravity, stepnormal, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask, 0);
2271 PRVM_serveredictvector(ent, velocity)[2] += start_velocity[2];
2272 if(clip & 8)
2273 {
2274 // we got teleported when upstepping... must abort the move
2275 // note that z velocity handling may not be what QC expects here, but we cannot help it
2276 return;
2277 }
2278
2279 SV_CheckVelocity(ent);
2280 SV_LinkEdict(ent);
2282
2283 // check for stuckness, possibly due to the limited precision of floats
2284 // in the clipping hulls
2285 if (clip
2286 && fabs(originalmove_origin[1] - PRVM_serveredictvector(ent, origin)[1]) < 0.03125
2287 && fabs(originalmove_origin[0] - PRVM_serveredictvector(ent, origin)[0]) < 0.03125)
2288 {
2289 //Con_Printf("wall\n");
2290 // stepping up didn't make any progress, revert to original move
2291 VectorCopy(originalmove_origin, PRVM_serveredictvector(ent, origin));
2292 VectorCopy(originalmove_velocity, PRVM_serveredictvector(ent, velocity));
2293 //clip = originalmove_clip;
2294 PRVM_serveredictfloat(ent, flags) = originalmove_flags;
2295 PRVM_serveredictedict(ent, groundentity) = originalmove_groundentity;
2296 // now try to unstick if needed
2297 //clip = SV_TryUnstick (ent, oldvel);
2298 return;
2299 }
2300
2301 //Con_Printf("step - ");
2302
2303 // extra friction based on view angle
2304 if (clip & 2 && sv_wallfriction.integer)
2305 SV_WallFriction (ent, stepnormal);
2306 }
2307 // don't do the down move if stepdown is disabled, moving upward, not in water, or the move started offground or ended onground
2308 else if (!sv_gameplayfix_stepdown.integer || PRVM_serveredictfloat(ent, waterlevel) >= 3 || start_velocity[2] >= (1.0 / 32.0) || !oldonground || ((int)PRVM_serveredictfloat(ent, flags) & FL_ONGROUND))
2309 return;
2310
2311 // move down
2312 VectorClear (downmove);
2313 downmove[2] = -sv_stepheight.value + start_velocity[2]*sv.frametime;
2314 if(!SV_PushEntity(&downtrace, ent, downmove, true, true))
2315 {
2316 // we got teleported when downstepping... must abort the move
2317 return;
2318 }
2319
2320 if (downtrace.fraction < 1 && downtrace.plane.normal[2] > 0.7)
2321 {
2322 // this has been disabled so that you can't jump when you are stepping
2323 // up while already jumping (also known as the Quake2 double jump bug)
2324#if 0
2325 // LadyHavoc: disabled this check so you can walk on monsters/players
2326 //if (PRVM_serveredictfloat(ent, solid) == SOLID_BSP)
2327 {
2328 //Con_Printf("onground\n");
2331 }
2332#endif
2333 }
2334 else
2335 {
2336 //Con_Printf("slope\n");
2337 // if the push down didn't end up on good ground, use the move without
2338 // the step up. This happens near wall / slope combinations, and can
2339 // cause the player to hop up higher on a slope too steep to climb
2340 VectorCopy(originalmove_origin, PRVM_serveredictvector(ent, origin));
2341 VectorCopy(originalmove_velocity, PRVM_serveredictvector(ent, velocity));
2342 //clip = originalmove_clip;
2343 PRVM_serveredictfloat(ent, flags) = originalmove_flags;
2344 PRVM_serveredictedict(ent, groundentity) = originalmove_groundentity;
2345 }
2346
2347 SV_CheckVelocity(ent);
2348 SV_LinkEdict(ent);
2350}
cvar_t sv_jumpstep
Definition sv_main.c:137
cvar_t sv_wallfriction
Definition sv_main.c:155
cvar_t sv_nostep
Definition sv_main.c:144
cvar_t sv_stepheight
Definition sv_main.c:153
cvar_t sv_gameplayfix_downtracesupportsongroundflag
Definition sv_main.c:128
cvar_t sv_gameplayfix_stepmultipletimes
Definition sv_main.c:124
cvar_t sv_gameplayfix_stepdown
Definition sv_main.c:123
static void SV_WallFriction(prvm_edict_t *ent, float *stepnormal)
Definition sv_phys.c:2064

References collision_extendmovelength, trace_t::ent, fabs(), FL_ONGROUND, FL_WATERJUMP, flags, trace_t::fraction, server_t::frametime, groundentity, int(), cvar_t::integer, maxs, mins, MOVE_MISSILE, MOVE_NOMONSTERS, MOVE_NORMAL, MOVE_WORLDONLY, movetype, MOVETYPE_FLY, MOVETYPE_FLY_WORLDONLY, MOVETYPE_FLYMISSILE, MOVETYPE_WALK, plane_t::normal, NULL, origin, trace_t::plane, PRVM_EDICT_TO_PROG, PRVM_serveredictedict, PRVM_serveredictfloat, PRVM_serveredictvector, solid, SOLID_NOT, SOLID_TRIGGER, sv, SV_CheckVelocity(), SV_CheckWater(), SV_FlyMove(), sv_gameplayfix_downtracesupportsongroundflag, sv_gameplayfix_stepdown, sv_gameplayfix_stepmultipletimes, SV_GenericHitSuperContentsMask(), sv_jumpstep, SV_LinkEdict(), SV_LinkEdict_TouchAreaGrid(), sv_nostep, SV_PushEntity(), sv_stepheight, SV_TraceBox(), SV_WallFriction(), sv_wallfriction, SVVM_prog, type, cvar_t::value, VectorClear, VectorCopy, VectorSet, velocity, and waterlevel.

Referenced by SV_Physics_ClientEntity(), SV_Physics_ClientEntity_NoThink(), and SV_Physics_Entity().

◆ SV_WallFriction()

static void SV_WallFriction ( prvm_edict_t * ent,
float * stepnormal )
static

Definition at line 2064 of file sv_phys.c.

2065{
2066 prvm_prog_t *prog = SVVM_prog;
2067 float d, i;
2068 vec3_t forward, into, side, v_angle;
2069
2072 if ((d = DotProduct (stepnormal, forward) + 0.5) < 0)
2073 {
2074 // cut the tangential velocity
2075 i = DotProduct (stepnormal, PRVM_serveredictvector(ent, velocity));
2076 VectorScale (stepnormal, i, into);
2078 PRVM_serveredictvector(ent, velocity)[0] = side[0] * (1 + d);
2079 PRVM_serveredictvector(ent, velocity)[1] = side[1] * (1 + d);
2080 }
2081}

References AngleVectors(), DotProduct, forward, i, NULL, PRVM_serveredictvector, SVVM_prog, v_angle, VectorCopy, VectorScale, VectorSubtract, and velocity.

Referenced by SV_WalkMove().