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 #include "client.h"
22
23
24 /*
25 ===================
26 CL_CheckPredictionError
27 ===================
28 */
CL_CheckPredictionError(void)29 void CL_CheckPredictionError (void)
30 {
31 int frame;
32 int delta[3];
33 int i;
34 int len;
35
36 if (!cl_predict->value || (cl.frame.playerstate.pmove.pm_flags & PMF_NO_PREDICTION))
37 return;
38
39 // calculate the last usercmd_t we sent that the server has processed
40 frame = cls.netchan.incoming_acknowledged;
41 frame &= (CMD_BACKUP-1);
42
43 // compare what the server returned with what we had predicted it to be
44 VectorSubtract (cl.frame.playerstate.pmove.origin, cl.predicted_origins[frame], delta);
45
46 // save the prediction error for interpolation
47 len = abs(delta[0]) + abs(delta[1]) + abs(delta[2]);
48 if (len > 640) // 80 world units
49 { // a teleport or something
50 VectorClear (cl.prediction_error);
51 }
52 else
53 {
54 if (cl_showmiss->value && (delta[0] || delta[1] || delta[2]) )
55 Com_Printf ("prediction miss on %i: %i\n", cl.frame.serverframe,
56 delta[0] + delta[1] + delta[2]);
57
58 VectorCopy (cl.frame.playerstate.pmove.origin, cl.predicted_origins[frame]);
59
60 // save for error itnerpolation
61 for (i=0 ; i<3 ; i++)
62 cl.prediction_error[i] = delta[i]*0.125;
63 }
64 }
65
66 /*
67 ====================
68 CL_ClipMoveToEntities
69
70 ====================
71 */
CL_ClipMoveToEntities(vec3_t start,vec3_t mins,vec3_t maxs,vec3_t end,trace_t * tr)72 void CL_ClipMoveToEntities ( vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, trace_t *tr )
73 {
74 int i, x, zd, zu;
75 trace_t trace;
76 int headnode;
77 float *angles;
78 entity_state_t *ent;
79 int num;
80 cmodel_t *cmodel;
81 vec3_t bmins, bmaxs;
82
83 for (i=0 ; i<cl.frame.num_entities ; i++)
84 {
85 num = (cl.frame.parse_entities + i)&(MAX_PARSE_ENTITIES-1);
86 ent = &cl_parse_entities[num];
87
88 if (!ent->solid)
89 continue;
90
91 if (ent->number == cl.playernum+1)
92 continue;
93
94 if (ent->solid == 31)
95 { // special value for bmodel
96 cmodel = cl.model_clip[ent->modelindex];
97 if (!cmodel)
98 continue;
99 headnode = cmodel->headnode;
100 angles = ent->angles;
101 }
102 else
103 { // encoded bbox
104
105 x = 8*(ent->solid & 31);
106 zd = 8*((ent->solid>>5) & 31);
107 zu = 8*((ent->solid>>10) & 63) - 32;
108
109 bmins[0] = bmins[1] = -x;
110 bmaxs[0] = bmaxs[1] = x;
111 bmins[2] = -zd;
112 bmaxs[2] = zu;
113
114 headnode = CM_HeadnodeForBox (bmins, bmaxs);
115 angles = vec3_origin; // boxes don't rotate
116 }
117
118 if (tr->allsolid)
119 return;
120
121 trace = CM_TransformedBoxTrace (start, end,
122 mins, maxs, headnode, MASK_PLAYERSOLID,
123 ent->origin, angles);
124
125 if (trace.allsolid || trace.startsolid ||
126 trace.fraction < tr->fraction)
127 {
128 trace.ent = (struct edict_s *)ent;
129 if (tr->startsolid)
130 {
131 *tr = trace;
132 tr->startsolid = true;
133 }
134 else
135 *tr = trace;
136 }
137 else if (trace.startsolid)
138 tr->startsolid = true;
139 }
140 }
141
142
143 /*
144 ================
145 CL_PMTrace
146 ================
147 */
CL_PMTrace(vec3_t start,vec3_t mins,vec3_t maxs,vec3_t end)148 trace_t CL_PMTrace (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end)
149 {
150 trace_t t;
151
152 // check against world
153 t = CM_BoxTrace (start, end, mins, maxs, 0, MASK_PLAYERSOLID);
154 if (t.fraction < 1.0)
155 t.ent = (struct edict_s *)1;
156
157 // check all other solid models
158 CL_ClipMoveToEntities (start, mins, maxs, end, &t);
159
160 return t;
161 }
162
CL_PMpointcontents(vec3_t point)163 int CL_PMpointcontents (vec3_t point)
164 {
165 int i;
166 entity_state_t *ent;
167 int num;
168 cmodel_t *cmodel;
169 int contents;
170
171 contents = CM_PointContents (point, 0);
172
173 for (i=0 ; i<cl.frame.num_entities ; i++)
174 {
175 num = (cl.frame.parse_entities + i)&(MAX_PARSE_ENTITIES-1);
176 ent = &cl_parse_entities[num];
177
178 if (ent->solid != 31) // special value for bmodel
179 continue;
180
181 cmodel = cl.model_clip[ent->modelindex];
182 if (!cmodel)
183 continue;
184
185 contents |= CM_TransformedPointContents (point, cmodel->headnode, ent->origin, ent->angles);
186 }
187
188 return contents;
189 }
190
191
192 /*
193 =================
194 CL_PredictMovement
195
196 Sets cl.predicted_origin and cl.predicted_angles
197 =================
198 */
CL_PredictMovement(void)199 void CL_PredictMovement (void)
200 {
201 int ack, current;
202 int frame;
203 int oldframe;
204 usercmd_t *cmd;
205 pmove_t pm;
206 int i;
207 int step;
208 int oldz;
209
210 if (cls.state != ca_active)
211 return;
212
213 if (cl_paused->value)
214 return;
215
216 if (!cl_predict->value || (cl.frame.playerstate.pmove.pm_flags & PMF_NO_PREDICTION))
217 { // just set angles
218 for (i=0 ; i<3 ; i++)
219 {
220 cl.predicted_angles[i] = cl.viewangles[i] + SHORT2ANGLE(cl.frame.playerstate.pmove.delta_angles[i]);
221 }
222 return;
223 }
224
225 ack = cls.netchan.incoming_acknowledged;
226 current = cls.netchan.outgoing_sequence;
227
228 // if we are too far out of date, just freeze
229 if (current - ack >= CMD_BACKUP)
230 {
231 if (cl_showmiss->value)
232 Com_Printf ("exceeded CMD_BACKUP\n");
233 return;
234 }
235
236 // copy current state to pmove
237 memset (&pm, 0, sizeof(pm));
238 pm.trace = CL_PMTrace;
239 pm.pointcontents = CL_PMpointcontents;
240
241 pm_airaccelerate = atof(cl.configstrings[CS_AIRACCEL]);
242
243 pm.s = cl.frame.playerstate.pmove;
244
245 // SCR_DebugGraph (current - ack - 1, 0);
246
247 frame = 0;
248
249 // run frames
250 while (++ack < current)
251 {
252 frame = ack & (CMD_BACKUP-1);
253 cmd = &cl.cmds[frame];
254
255 pm.cmd = *cmd;
256 Pmove (&pm);
257
258 // save for debug checking
259 VectorCopy (pm.s.origin, cl.predicted_origins[frame]);
260 }
261
262 oldframe = (ack-2) & (CMD_BACKUP-1);
263 oldz = cl.predicted_origins[oldframe][2];
264 step = pm.s.origin[2] - oldz;
265 if (step > 63 && step < 160 && (pm.s.pm_flags & PMF_ON_GROUND) )
266 {
267 cl.predicted_step = step * 0.125;
268 cl.predicted_step_time = cls.realtime - cls.frametime * 500;
269 }
270
271
272 // copy results out for rendering
273 cl.predicted_origin[0] = pm.s.origin[0]*0.125;
274 cl.predicted_origin[1] = pm.s.origin[1]*0.125;
275 cl.predicted_origin[2] = pm.s.origin[2]*0.125;
276
277 VectorCopy (pm.viewangles, cl.predicted_angles);
278 }
279