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

Go to the source code of this file.

Macros

#define EPSILON   (1.0f / 32.0f)
 

Functions

unstickresult_t PHYS_NudgeOutOfSolid (prvm_prog_t *prog, prvm_edict_t *ent)
 
qbool PHYS_TestEntityPosition (prvm_prog_t *prog, prvm_edict_t *ent, vec3_t offset)
 
static trace_t PHYS_TraceBox (prvm_prog_t *prog, 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, qbool hitnetworkbrushmodels, qbool hitnetworkplayers, int *hitnetworkentity, qbool hitcsqcentities)
 
unstickresult_t PHYS_UnstickEntityReturnOffset (prvm_prog_t *prog, prvm_edict_t *ent, vec3_t offset)
 

Variables

static float unstickoffsets []
 

Macro Definition Documentation

◆ EPSILON

#define EPSILON   (1.0f / 32.0f)

Referenced by PHYS_TestEntityPosition().

Function Documentation

◆ PHYS_NudgeOutOfSolid()

unstickresult_t PHYS_NudgeOutOfSolid ( prvm_prog_t * prog,
prvm_edict_t * ent )

move an entity that is stuck out of the surface it is stuck in (can move large amounts) with consideration to the properties of the surface and support for multiple surfaces. returns 1 if it found a better place, 0 if it remains stuck, -1 if it wasn't stuck. Replaces PHYS_UnstickEntityReturnOffset() but falls back to it when using cliphulls.

Definition at line 136 of file phys.c.

137{
138 int bump, pass;
139 trace_t stucktrace;
140 vec3_t testorigin, targetorigin;
141 vec3_t stuckmins, stuckmaxs;
142 vec_t separation;
143 model_t *worldmodel;
144
145 if (prog == SVVM_prog)
146 {
147 worldmodel = sv.worldmodel;
149 }
150 else if (prog == CLVM_prog)
151 {
152 worldmodel = cl.worldmodel;
154 }
155 else
156 Sys_Error("PHYS_NudgeOutOfSolid: cannot be called from %s VM\n", prog->name);
157
158 VectorCopy(PRVM_serveredictvector(ent, mins), stuckmins);
159 VectorCopy(PRVM_serveredictvector(ent, maxs), stuckmaxs);
160 if (worldmodel && worldmodel->TraceBox != Mod_CollisionBIH_TraceBox)
161 {
162 separation = 0.0f; // when using hulls, it can not be enlarged
163
164 // FIXME: Mod_Q1BSP_TraceBox() doesn't support startdepth and startdepthnormal
165 return PHYS_UnstickEntityReturnOffset(prog, ent, testorigin); // fallback
166 }
167 else
168 {
169 stuckmins[0] -= separation;
170 stuckmins[1] -= separation;
171 stuckmins[2] -= separation;
172 stuckmaxs[0] += separation;
173 stuckmaxs[1] += separation;
174 stuckmaxs[2] += separation;
175 }
176
177 // first pass we try to get it out of brush entities
178 // second pass we try to get it out of world only (can't win them all)
179 for (pass = 0;pass < 2;pass++)
180 {
181 VectorCopy(PRVM_serveredictvector(ent, origin), testorigin);
182 for (bump = 0;bump < 10;bump++)
183 {
184 stucktrace = PHYS_TraceBox(prog, testorigin, stuckmins, stuckmaxs, testorigin, pass ? MOVE_WORLDONLY : MOVE_NOMONSTERS, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value, pass ? false : true, false, NULL, false);
185
186 // Separation compared here to ensure a good location will be recognised reliably.
187 if (-stucktrace.startdepth <= separation
188 || (!stucktrace.bmodelstartsolid && !stucktrace.worldstartsolid)
189 || (pass && !stucktrace.worldstartsolid))
190 {
191 // found a good location, use it
192 VectorCopy(testorigin, PRVM_serveredictvector(ent, origin));
193 return bump || pass ? UNSTICK_UNSTUCK : UNSTICK_GOOD;
194 }
195
196 VectorMA(testorigin, -stucktrace.startdepth, stucktrace.startdepthnormal, targetorigin);
197 // Trace to targetorigin so we don't set it out of the world in complex cases.
198 stucktrace = PHYS_TraceBox(prog, testorigin, stuckmins, stuckmaxs, targetorigin, pass ? MOVE_WORLDONLY : MOVE_NOMONSTERS, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value, pass ? false : true, false, NULL, false);
199 if (stucktrace.fraction)
200 VectorCopy(stucktrace.endpos, testorigin);
201 else
202 break; // Can't move it so no point doing more iterations on this pass.
203 }
204 }
205 return UNSTICK_STUCK;
206}
cvar_t cl_gameplayfix_nudgeoutofsolid_separation
Definition cl_main.c:113
client_state_t cl
Definition cl_main.c:117
cvar_t collision_extendmovelength
Definition collision.c:14
vector mins
vector maxs
vector origin
#define VectorCopy(in, out)
Definition mathlib.h:101
#define VectorMA(a, scale, b, out)
Definition mathlib.h:114
void Mod_CollisionBIH_TraceBox(model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
static trace_t PHYS_TraceBox(prvm_prog_t *prog, 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, qbool hitnetworkbrushmodels, qbool hitnetworkplayers, int *hitnetworkentity, qbool hitcsqcentities)
Definition phys.c:10
unstickresult_t PHYS_UnstickEntityReturnOffset(prvm_prog_t *prog, prvm_edict_t *ent, vec3_t offset)
Definition phys.c:102
@ UNSTICK_GOOD
didn't need to be unstuck
Definition phys.h:13
@ UNSTICK_STUCK
Definition phys.h:12
@ UNSTICK_UNSTUCK
Definition phys.h:14
#define CLVM_prog
Definition progsvm.h:767
#define PRVM_serveredictvector(ed, fieldname)
Definition progsvm.h:173
#define SVVM_prog
Definition progsvm.h:766
#define NULL
Definition qtypes.h:12
float vec_t
Definition qtypes.h:68
vec_t vec3_t[3]
Definition qtypes.h:71
server_t sv
local server
Definition sv_main.c:223
cvar_t sv_gameplayfix_nudgeoutofsolid_separation
Definition sv_main.c:118
int SV_GenericHitSuperContentsMask(const prvm_edict_t *edict)
calculates hitsupercontentsmask for a generic qc entity
Definition sv_phys.c:73
struct model_s * worldmodel
Definition client.h:934
float value
Definition cvar.h:74
void(* TraceBox)(struct model_s *model, const struct frameblend_s *frameblend, const struct skeleton_s *skeleton, struct trace_s *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
const char * name
name of the prog, e.g. "Server", "Client" or "Menu" (used for text output)
Definition progsvm.h:700
struct model_s * worldmodel
Definition server.h:112
qbool bmodelstartsolid
Definition collision.h:30
double startdepthnormal[3]
Definition collision.h:69
double fraction
Definition collision.h:40
qbool worldstartsolid
Definition collision.h:28
double endpos[3]
Definition collision.h:42
double startdepth
Definition collision.h:68
void Sys_Error(const char *error,...) DP_FUNC_PRINTF(1) DP_FUNC_NORETURN
Causes the entire program to exit ASAP.
Definition sys_shared.c:724
#define MOVE_WORLDONLY
Definition world.h:31
#define MOVE_NOMONSTERS
Definition world.h:29

References trace_t::bmodelstartsolid, cl, cl_gameplayfix_nudgeoutofsolid_separation, CLVM_prog, collision_extendmovelength, trace_t::endpos, trace_t::fraction, maxs, mins, Mod_CollisionBIH_TraceBox(), MOVE_NOMONSTERS, MOVE_WORLDONLY, prvm_prog_t::name, NULL, origin, PHYS_TraceBox(), PHYS_UnstickEntityReturnOffset(), PRVM_serveredictvector, trace_t::startdepth, trace_t::startdepthnormal, sv, sv_gameplayfix_nudgeoutofsolid_separation, SV_GenericHitSuperContentsMask(), SVVM_prog, Sys_Error(), model_t::TraceBox, UNSTICK_GOOD, UNSTICK_STUCK, UNSTICK_UNSTUCK, cvar_t::value, VectorCopy, VectorMA, client_state_t::worldmodel, server_t::worldmodel, and trace_t::worldstartsolid.

Referenced by SV_UnstickEntity(), VM_nudgeoutofsolid(), and VM_SV_droptofloor().

◆ PHYS_TestEntityPosition()

qbool PHYS_TestEntityPosition ( prvm_prog_t * prog,
prvm_edict_t * ent,
vec3_t offset )

Definition at line 24 of file phys.c.

25{
26 int hitsupercontentsmask = SV_GenericHitSuperContentsMask(ent);
27 int skipsupercontentsmask = 0;
28 int skipmaterialflagsmask = 0;
29 vec3_t org, entorigin, entmins, entmaxs;
30 trace_t trace;
31
36 trace = PHYS_TraceBox(prog, org, entmins, entmaxs, entorigin, ((PRVM_serveredictfloat(ent, movetype) == MOVETYPE_FLY_WORLDONLY) ? MOVE_WORLDONLY : MOVE_NOMONSTERS), ent, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask, collision_extendmovelength.value, true, false, NULL, false);
37 if (trace.startsupercontents & hitsupercontentsmask)
38 return true;
39 else
40 {
41 if (sv.worldmodel->brushq1.numclipnodes && !VectorCompare(PRVM_serveredictvector(ent, mins), PRVM_serveredictvector(ent, maxs)))
42 {
43 // q1bsp/hlbsp use hulls and if the entity does not exactly match
44 // a hull size it is incorrectly tested, so this code tries to
45 // 'fix' it slightly...
46 // FIXME: this breaks entities larger than the hull size
47 int i;
48 vec3_t v, m1, m2, s;
49 VectorAdd(org, entmins, m1);
50 VectorAdd(org, entmaxs, m2);
51 VectorSubtract(m2, m1, s);
52#define EPSILON (1.0f / 32.0f)
53 if (s[0] >= EPSILON*2) {m1[0] += EPSILON;m2[0] -= EPSILON;}
54 if (s[1] >= EPSILON*2) {m1[1] += EPSILON;m2[1] -= EPSILON;}
55 if (s[2] >= EPSILON*2) {m1[2] += EPSILON;m2[2] -= EPSILON;}
56 for (i = 0;i < 8;i++)
57 {
58 v[0] = (i & 1) ? m2[0] : m1[0];
59 v[1] = (i & 2) ? m2[1] : m1[1];
60 v[2] = (i & 4) ? m2[2] : m1[2];
61 if (SV_PointSuperContents(v) & hitsupercontentsmask)
62 return true;
63 }
64 }
65 }
66 // if the trace found a better position for the entity, move it there
67 if (VectorDistance2(trace.endpos, PRVM_serveredictvector(ent, origin)) >= 0.0001)
68 {
69#if 0
70 // please switch back to this code when trace.endpos sometimes being in solid bug is fixed
72#else
73 // verify if the endpos is REALLY outside solid
74 VectorCopy(trace.endpos, org);
75 trace = PHYS_TraceBox(prog, org, entmins, entmaxs, org, MOVE_NOMONSTERS, ent, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask, collision_extendmovelength.value, true, false, NULL, false);
76 if(trace.startsolid)
77 Con_Printf("PHYS_TestEntityPosition: trace.endpos detected to be in solid. NOT using it.\n");
78 else
80#endif
81 }
82 return false;
83}
void Con_Printf(const char *fmt,...)
Prints to all appropriate console targets.
Definition console.c:1514
float movetype
const GLdouble * v
Definition glquake.h:762
GLuint GLuint GLintptr offset
Definition glquake.h:632
#define VectorDistance2(a, b)
Definition mathlib.h:107
#define VectorSubtract(a, b, out)
Definition mathlib.h:99
#define VectorCompare(a, b)
Definition mathlib.h:113
#define VectorAdd(a, b, out)
Definition mathlib.h:100
#define EPSILON
#define PRVM_serveredictfloat(ed, fieldname)
Definition progsvm.h:172
int i
#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
int SV_PointSuperContents(const vec3_t point)
Definition sv_phys.c:611
int startsupercontents
Definition collision.h:56
qbool startsolid
Definition collision.h:26

References collision_extendmovelength, Con_Printf(), trace_t::endpos, EPSILON, i, maxs, mins, MOVE_NOMONSTERS, MOVE_WORLDONLY, movetype, MOVETYPE_FLY_WORLDONLY, NULL, offset, origin, PHYS_TraceBox(), PRVM_serveredictfloat, PRVM_serveredictvector, trace_t::startsolid, trace_t::startsupercontents, sv, SV_GenericHitSuperContentsMask(), SV_PointSuperContents(), v, cvar_t::value, VectorAdd, VectorCompare, VectorCopy, VectorDistance2, VectorSubtract, and server_t::worldmodel.

Referenced by PHYS_UnstickEntityReturnOffset(), and SV_UnstickEntity().

◆ PHYS_TraceBox()

static trace_t PHYS_TraceBox ( prvm_prog_t * prog,
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,
qbool hitnetworkbrushmodels,
qbool hitnetworkplayers,
int * hitnetworkentity,
qbool hitcsqcentities )
inlinestatic

Definition at line 10 of file phys.c.

11{
12 return (prog == SVVM_prog)
13 ? SV_TraceBox(start, mins, maxs, end, type, passedict, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask, extend)
14 : CL_TraceBox(start, mins, maxs, end, type, passedict, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask, extend, hitnetworkbrushmodels, hitnetworkplayers, hitnetworkentity, hitcsqcentities);
15}
trace_t CL_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, qbool hitnetworkbrushmodels, qbool hitnetworkplayers, int *hitnetworkentity, qbool hitcsqcentities)
GLenum type
Definition glquake.h:656
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

References CL_TraceBox(), maxs, mins, SV_TraceBox(), SVVM_prog, and type.

Referenced by PHYS_NudgeOutOfSolid(), and PHYS_TestEntityPosition().

◆ PHYS_UnstickEntityReturnOffset()

unstickresult_t PHYS_UnstickEntityReturnOffset ( prvm_prog_t * prog,
prvm_edict_t * ent,
vec3_t offset )

move an entity that is stuck by small amounts in various directions to try to nudge it back into the collision hull returns 1 if it found a better place, 0 if it remains stuck, -1 if it wasn't stuck. Replaces SV_TryUnstick() and SV_CheckStuck() which in Quake applied to players only.

Definition at line 102 of file phys.c.

103{
104 int i, maxunstick;
105
106 // if not stuck in a bmodel, just return
107 if (!PHYS_TestEntityPosition(prog, ent, vec3_origin))
108 return UNSTICK_GOOD;
109
110 for (i = 0;i < (int)(sizeof(unstickoffsets) / sizeof(unstickoffsets[0]));i += 3)
111 {
112 if (!PHYS_TestEntityPosition(prog, ent, unstickoffsets + i))
113 {
115 return UNSTICK_UNSTUCK;
116 }
117 }
118
119 maxunstick = (int) ((PRVM_serveredictvector(ent, maxs)[2] - PRVM_serveredictvector(ent, mins)[2]) * 0.36);
120 // magic number 0.36 allows unsticking by up to 17 units with the largest supported bbox
121
122 for(i = 2; i <= maxunstick; ++i)
123 {
125 offset[2] = -i;
126 if (!PHYS_TestEntityPosition(prog, ent, offset))
127 return UNSTICK_UNSTUCK;
128 offset[2] = i;
129 if (!PHYS_TestEntityPosition(prog, ent, offset))
130 return UNSTICK_UNSTUCK;
131 }
132
133 return UNSTICK_STUCK;
134}
static int(ZEXPORT *qz_inflate)(z_stream *strm
vec3_t vec3_origin
Definition mathlib.c:26
#define VectorClear(a)
Definition mathlib.h:97
static float unstickoffsets[]
Definition phys.c:85
qbool PHYS_TestEntityPosition(prvm_prog_t *prog, prvm_edict_t *ent, vec3_t offset)
Definition phys.c:24

References i, int(), maxs, mins, offset, PHYS_TestEntityPosition(), PRVM_serveredictvector, UNSTICK_GOOD, UNSTICK_STUCK, UNSTICK_UNSTUCK, unstickoffsets, vec3_origin, VectorClear, and VectorCopy.

Referenced by PHYS_NudgeOutOfSolid(), and SV_UnstickEntity().

Variable Documentation

◆ unstickoffsets

float unstickoffsets[]
static
Initial value:
=
{
0, 0, -1,
0, 0, 1,
-1, 0, 0,
1, 0, 0,
0, -1, 0,
0, 1, 0,
-1, -1, 0,
1, -1, 0,
-1, 1, 0,
1, 1, 0,
}

Definition at line 85 of file phys.c.

86{
87 // poutting -/+z changes first as they are least weird
88 0, 0, -1,
89 0, 0, 1,
90 // x or y changes
91 -1, 0, 0,
92 1, 0, 0,
93 0, -1, 0,
94 0, 1, 0,
95 // x and y changes
96 -1, -1, 0,
97 1, -1, 0,
98 -1, 1, 0,
99 1, 1, 0,
100};

Referenced by PHYS_UnstickEntityReturnOffset().