1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3 
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 
13 See the GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 
19 */
20 
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24 
25 #include "client.h"
26 
27 /*
28 ===================
29 CL_CheckPredictionError
30 ===================
31 */
CL_CheckPredictionError(void)32 void CL_CheckPredictionError (void)
33 {
34 	int		frame;
35 	int		delta[3];
36 	int		i;
37 	int		len;
38 
39 	if (!cl_predict->value || (cl.frame.playerstate.pmove.pm_flags & PMF_NO_PREDICTION))
40 		return;
41 
42 	// calculate the last usercmd_t we sent that the server has processed
43 	frame = cls.netchan.incoming_acknowledged;
44 	frame &= (CMD_BACKUP-1);
45 
46 	// compare what the server returned with what we had predicted it to be
47 	VectorSubtract (cl.frame.playerstate.pmove.origin, cl.predicted_origins[frame], delta);
48 
49 	// save the prediction error for interpolation
50 	len = abs(delta[0]) + abs(delta[1]) + abs(delta[2]);
51 	if (len > 640)	// 80 world units
52 	{	// a teleport or something
53 		VectorClear (cl.prediction_error);
54 	}
55 	else
56 	{
57 		if (cl_showmiss->value && (delta[0] || delta[1] || delta[2]) )
58 		{ // use sum of absolute differences from above, scaled to quake units
59 			Com_Printf("prediction miss: frame %i: %0.3f\n",
60 					cl.frame.serverframe, ((float)len)/8.0f );
61 		}
62 
63 		VectorCopy (cl.frame.playerstate.pmove.origin, cl.predicted_origins[frame]);
64 
65 		// save for error itnerpolation
66 		for (i=0 ; i<3 ; i++)
67 			cl.prediction_error[i] = delta[i]*0.125;
68 	}
69 }
70 
71 
72 /*
73 ====================
74 CL_ClipMoveToEntities
75 
76 ====================
77 */
CL_ClipMoveToEntities(vec3_t start,vec3_t mins,vec3_t maxs,vec3_t end,trace_t * tr)78 void CL_ClipMoveToEntities ( vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, trace_t *tr )
79 {
80 	int			i, x, zd, zu;
81 	trace_t		trace;
82 	int			headnode;
83 	float		*angles;
84 	entity_state_t	*ent;
85 	int			num;
86 	cmodel_t		*cmodel;
87 	vec3_t		bmins, bmaxs;
88 
89 	for (i=0 ; i<cl.frame.num_entities ; i++)
90 	{
91 		num = (cl.frame.parse_entities + i)&(MAX_PARSE_ENTITIES-1);
92 		ent = &cl_parse_entities[num];
93 
94 		if (!ent->solid)
95 			continue;
96 
97 		if (ent->number == cl.playernum+1)
98 			continue;
99 
100 		if (ent->solid == 31)
101 		{	// special value for bmodel
102 			cmodel = cl.model_clip[ent->modelindex];
103 			if (!cmodel)
104 				continue;
105 			headnode = cmodel->headnode;
106 			angles = ent->angles;
107 		}
108 		else
109 		{	// encoded bbox
110 			x = 8*(ent->solid & 31);
111 			zd = 8*((ent->solid>>5) & 31);
112 			zu = 8*((ent->solid>>10) & 63) - 32;
113 
114 			bmins[0] = bmins[1] = -x;
115 			bmaxs[0] = bmaxs[1] = x;
116 			bmins[2] = -zd;
117 			bmaxs[2] = zu;
118 
119 			headnode = CM_HeadnodeForBox (bmins, bmaxs);
120 			angles = vec3_origin;	// boxes don't rotate
121 		}
122 
123 		if (tr->allsolid)
124 			return;
125 
126 		trace = CM_TransformedBoxTrace (start, end,
127 			mins, maxs, headnode,  MASK_PLAYERSOLID,
128 			ent->origin, angles);
129 
130 		if (trace.allsolid || trace.startsolid ||
131 		trace.fraction < tr->fraction)
132 		{
133 			trace.ent = (struct edict_s *)ent;
134 		 	if (tr->startsolid)
135 			{
136 				*tr = trace;
137 				tr->startsolid = true;
138 			}
139 			else
140 				*tr = trace;
141 		}
142 		else if (trace.startsolid)
143 			tr->startsolid = true;
144 	}
145 }
146 
147 
148 /*
149 ================
150 CL_PMTrace
151 ================
152 */
CL_PMTrace(vec3_t start,vec3_t mins,vec3_t maxs,vec3_t end)153 trace_t		CL_PMTrace (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end)
154 {
155 	trace_t	t;
156 
157 	// check against world
158 	t = CM_BoxTrace (start, end, mins, maxs, 0, MASK_PLAYERSOLID);
159 	if (t.fraction < 1.0)
160 		t.ent = (struct edict_s *)1;
161 
162 	// check all other solid models
163 	CL_ClipMoveToEntities (start, mins, maxs, end, &t);
164 
165 	return t;
166 }
167 
CL_PMpointcontents(vec3_t point)168 int		CL_PMpointcontents (vec3_t point)
169 {
170 	int			i;
171 	entity_state_t	*ent;
172 	int			num;
173 	cmodel_t		*cmodel;
174 	int			contents;
175 
176 	contents = CM_PointContents (point, 0);
177 
178 	for (i=0 ; i<cl.frame.num_entities ; i++)
179 	{
180 		num = (cl.frame.parse_entities + i)&(MAX_PARSE_ENTITIES-1);
181 		ent = &cl_parse_entities[num];
182 
183 		if (ent->solid != 31) // special value for bmodel
184 			continue;
185 
186 		cmodel = cl.model_clip[ent->modelindex];
187 		if (!cmodel)
188 			continue;
189 
190 		contents |= CM_TransformedPointContents (point, cmodel->headnode, ent->origin, ent->angles);
191 	}
192 
193 	return contents;
194 }
195 
196 //Knightmare added- this can check using masks, good for checking surface flags
197 //   also checks for bmodels
198 /*
199 ================
200 CL_PMSurfaceTrace
201 ================
202 */
CL_PMSurfaceTrace(vec3_t start,vec3_t mins,vec3_t maxs,vec3_t end,int contentmask)203 trace_t CL_PMSurfaceTrace (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int contentmask)
204 {
205    trace_t   t;
206 
207    if (!mins)
208       mins = vec3_origin;
209    if (!maxs)
210       maxs = vec3_origin;
211 
212    // check against world
213    t = CM_BoxTrace (start, end, mins, maxs, 0, contentmask);
214    if (t.fraction < 1.0)
215       t.ent = (struct edict_s *)1;
216 
217    // check all other solid models
218    CL_ClipMoveToEntities (start, mins, maxs, end, &t);
219 
220    return t;
221 }
222 
223 
224 /*
225 =================
226 CL_PredictMovement
227 
228 Sets cl.predicted_origin and cl.predicted_angles
229 =================
230 */
CL_PredictMovement(void)231 void CL_PredictMovement (void)
232 {
233 	int			ack, current;
234 	int			frame;
235 	int			oldframe;
236 	usercmd_t	*cmd;
237 	pmove_t		pm;
238 	int			i;
239 	int			step;
240 	int			oldz;
241 
242 	if (cls.state != ca_active)
243 		return;
244 
245 	if (cl_paused->value)
246 		return;
247 
248 	if (!cl_predict->value || (cl.frame.playerstate.pmove.pm_flags & PMF_NO_PREDICTION))
249 	{	// just set angles
250 		for (i=0 ; i<3 ; i++)
251 		{
252 			cl.last_predicted_angles[i] = cl.predicted_angles[i] = cl.viewangles[i] + SHORT2ANGLE(cl.frame.playerstate.pmove.delta_angles[i]);
253 		}
254 		return;
255 	}
256 
257 	ack = cls.netchan.incoming_acknowledged;
258 	current = cls.netchan.outgoing_sequence;
259 
260 	// if we are too far out of date, just freeze
261 	if (current - ack >= CMD_BACKUP)
262 	{
263 		if (cl_showmiss->value)
264 			Com_Printf ("exceeded CMD_BACKUP\n");
265 		return;
266 	}
267 
268 	// copy current state to pmove
269 	memset (&pm, 0, sizeof(pm));
270 	pm.trace = CL_PMTrace;
271 	pm.pointcontents = CL_PMpointcontents;
272 
273 	pm_airaccelerate = atof(cl.configstrings[CS_AIRACCEL]);
274 
275 	pm.s = cl.frame.playerstate.pmove;
276 
277 //	SCR_DebugGraph (current - ack - 1, 0);
278 
279 	frame = 0;
280 
281 	// run frames
282 	while (++ack < current)
283 	{
284 		frame = ack & (CMD_BACKUP-1);
285 		cmd = &cl.cmds[frame];
286 
287 		pm.cmd = *cmd;
288 		Pmove (&pm);
289 
290 		// save for debug checking
291 		VectorCopy (pm.s.origin, cl.predicted_origins[frame]);
292 	}
293 
294 	oldframe = (ack-2) & (CMD_BACKUP-1);
295 	oldz = cl.predicted_origins[oldframe][2];
296 	step = pm.s.origin[2] - oldz;
297 	if (step > 63 && step < 160 && (pm.s.pm_flags & PMF_ON_GROUND) )
298 	{
299 		cl.predicted_step = step * 0.125;
300 		cl.predicted_step_time = cls.realtime - cls.frametime * 500;
301 	}
302 
303 
304 	// copy results out for rendering
305 	cl.predicted_origin[0] = pm.s.origin[0]*0.125;
306 	cl.predicted_origin[1] = pm.s.origin[1]*0.125;
307 	cl.predicted_origin[2] = pm.s.origin[2]*0.125;
308 
309 	cl.predicted_velocity[0] = pm.s.velocity[0]*0.125;
310 	cl.predicted_velocity[1] = pm.s.velocity[1]*0.125;
311 	cl.predicted_velocity[2] = pm.s.velocity[2]*0.125;
312 
313 	VectorCopy (pm.viewangles, cl.predicted_angles);
314 	VectorCopy (pm.viewangles, cl.last_predicted_angles);
315 }
316 
317 /*
318  =================
319  CL_Trace
320  =================
321 */
CL_Trace(vec3_t start,vec3_t mins,vec3_t maxs,vec3_t end,int skipNumber,int brushMask,qboolean brushOnly,int * entNumber)322 trace_t CL_Trace (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int skipNumber, int brushMask, qboolean brushOnly, int *entNumber){
323 
324 	trace_t			trace, tmp;
325 	entity_state_t	*ent;
326 	cmodel_t		*cmodel;
327 	vec3_t			bmins, bmaxs;
328 	int				i, xy, zd, zu, headNode, num;
329 
330 	// Check against world
331 	trace = CM_BoxTrace(start, end, mins, maxs, 0, brushMask);
332 	if (trace.fraction < 1.0){
333 		if (entNumber)
334 			*entNumber = 0;
335 
336 		trace.ent = (struct edict_s *)1;
337 	}
338 
339 	if (trace.allsolid || trace.fraction == 0.0)
340 		return trace;
341 
342 	// Check all other solid models
343 	for (i=0 ; i<cl.frame.num_entities ; i++)
344 	{
345 		num = (cl.frame.parse_entities + i)&(MAX_PARSE_ENTITIES-1);
346 		ent = &cl_parse_entities[num];
347 
348 		if (ent->number == skipNumber)
349 			continue;
350 
351 		if (ent->solid == 31){
352 			// Special value for brush model
353 			cmodel = cl.model_clip[ent->modelindex];
354 			if (!cmodel)
355 				continue;
356 
357 			tmp = CM_TransformedBoxTrace(start, end, mins, maxs, cmodel->headnode, brushMask, ent->origin, ent->angles);
358 		}
359 		else {
360 			if (brushOnly)
361 				continue;
362 
363 			// Encoded bounding box
364 			xy = 8 * (ent->solid & 31);
365 			zd = 8 * ((ent->solid >> 5) & 31);
366 			zu = 8 * ((ent->solid >> 10) & 63) - 32;
367 
368 			bmins[0] = bmins[1] = -xy;
369 			bmaxs[0] = bmaxs[1] = xy;
370 			bmins[2] = -zd;
371 			bmaxs[2] = zu;
372 
373 			headNode = CM_HeadnodeForBox (bmins, bmaxs);
374 			tmp = CM_TransformedBoxTrace(start, end, mins, maxs, headNode, brushMask, ent->origin, vec3_origin);
375 		}
376 
377 		if (tmp.allsolid || tmp.startsolid || tmp.fraction < trace.fraction){
378 			if (entNumber)
379 				*entNumber = ent->number;
380 
381 			tmp.ent = (struct edict_s *)ent;
382 			if (trace.startsolid){
383 				trace = tmp;
384 				trace.startsolid = true;
385 			}
386 			else
387 				trace = tmp;
388 		}
389 		else if (tmp.startsolid)
390 			trace.startsolid = true;
391 
392 		if (trace.allsolid)
393 			break;
394 	}
395 
396 	return trace;
397 }
398 
399 
400