1 .entity move_groundentity;
\r
2 .float move_suspendedinair;
\r
3 .float move_didgravity;
\r
5 void _Movetype_CheckVelocity() // SV_CheckVelocity
\r
9 float _Movetype_CheckWater() // SV_CheckWater
\r
14 void _Movetype_CheckWaterTransition() // SV_CheckWaterTransition
\r
18 void _Movetype_Impact(entity oth) // SV_Impact
\r
20 entity oldother, oldself;
\r
46 void _Movetype_LinkEdict_TouchAreaGrid() // SV_LinkEdict_TouchAreaGrid
\r
48 entity e, oldself, oldother;
\r
53 for(e = findradius(0.5 * (self.absmin + self.absmax), 0.5 * vlen(self.absmax - self.absmin)); e; e = e.chain)
\r
56 if(boxesoverlap(e.absmin, e.absmax, oldself.absmin, oldself.absmax))
\r
61 trace_allsolid = FALSE;
\r
62 trace_startsolid = FALSE;
\r
64 trace_inwater = FALSE;
\r
65 trace_inopen = TRUE;
\r
66 trace_endpos = e.origin;
\r
67 trace_plane_normal = '0 0 1';
\r
68 trace_plane_dist = 0;
\r
69 trace_ent = oldself;
\r
79 void _Movetype_LinkEdict(float touch_triggers) // SV_LinkEdict
\r
82 if(self.solid == SOLID_BSP)
\r
84 // TODO set the absolute bbox
\r
93 mi = mi + self.origin;
\r
94 ma = ma + self.origin;
\r
96 if(self.move_flags & FL_ITEM)
\r
119 _Movetype_LinkEdict_TouchAreaGrid();
\r
122 float _Movetype_TestEntityPosition(vector ofs) // SV_TestEntityPosition
\r
126 org = self.move_origin + ofs;
\r
128 cont = self.dphitcontentsmask;
\r
129 self.dphitcontentsmask = DPCONTENTS_SOLID;
\r
130 tracebox(self.move_origin, self.mins, self.maxs, self.move_origin, MOVE_NOMONSTERS, self);
\r
131 self.dphitcontentsmask = cont;
\r
133 if(trace_startsolid)
\r
136 if(vlen(trace_endpos - self.move_origin) > 0.0001)
\r
137 self.move_origin = trace_endpos;
\r
141 float _Movetype_UnstickEntity() // SV_UnstickEntity
\r
143 if(!_Movetype_TestEntityPosition('0 0 0'))
\r
145 if(!_Movetype_TestEntityPosition('-1 0 0')) goto success;
\r
146 if(!_Movetype_TestEntityPosition('1 0 0')) goto success;
\r
147 if(!_Movetype_TestEntityPosition('0 -1 0')) goto success;
\r
148 if(!_Movetype_TestEntityPosition('0 1 0')) goto success;
\r
149 if(!_Movetype_TestEntityPosition('-1 -1 0')) goto success;
\r
150 if(!_Movetype_TestEntityPosition('1 -1 0')) goto success;
\r
151 if(!_Movetype_TestEntityPosition('-1 1 0')) goto success;
\r
152 if(!_Movetype_TestEntityPosition('1 1 0')) goto success;
\r
154 for(i = 1; i <= 17; ++i)
\r
156 if(!_Movetype_TestEntityPosition('0 0 -1' * i)) goto success;
\r
157 if(!_Movetype_TestEntityPosition('0 0 1' * i)) goto success;
\r
159 dprint("Some entity is stuck\n");
\r
162 dprint("Unstuck some entity\n");
\r
163 _Movetype_LinkEdict(TRUE);
\r
167 vector _Movetype_ClipVelocity(vector vel, vector norm, float f) // SV_ClipVelocity
\r
169 vel = vel - ((vel * norm) * norm) * f;
\r
171 if(vel_x > -0.1 && vel_x < 0.1) vel_x = 0;
\r
172 if(vel_y > -0.1 && vel_y < 0.1) vel_y = 0;
\r
173 if(vel_z > -0.1 && vel_z < 0.1) vel_z = 0;
\r
178 void _Movetype_PushEntityTrace(vector push)
\r
183 end = self.move_origin + push;
\r
185 if(self.move_nomonsters)
\r
186 type = max(0, self.move_nomonsters);
\r
187 else if(self.move_movetype == MOVETYPE_FLYMISSILE)
\r
188 type = MOVE_MISSILE;
\r
189 else if(self.solid == SOLID_TRIGGER || self.solid == SOLID_NOT)
\r
190 type = MOVE_NOMONSTERS;
\r
192 type = MOVE_NORMAL;
\r
194 tracebox(self.move_origin, self.mins, self.maxs, end, type, self);
\r
197 float _Movetype_PushEntity(vector push, float failonstartsolid) // SV_PushEntity
\r
199 _Movetype_PushEntityTrace(push);
\r
201 if(trace_startsolid && failonstartsolid)
\r
202 return trace_fraction;
\r
204 self.move_origin = trace_endpos;
\r
206 if(trace_fraction < 1)
\r
207 if(self.solid >= SOLID_TRIGGER && (!(self.move_flags & FL_ONGROUND) || (self.move_groundentity != trace_ent)))
\r
208 _Movetype_Impact(trace_ent);
\r
210 return trace_fraction;
\r
213 #define MAX_CLIP_PLANES 5
\r
214 void _Movetype_Physics_Toss(float dt) // SV_Physics_Toss
\r
216 if(self.move_flags & FL_ONGROUND)
\r
218 if(self.move_velocity_z >= 1/32)
\r
219 self.move_flags &~= FL_ONGROUND;
\r
220 else if(!self.move_groundentity)
\r
222 else if(self.move_suspendedinair && wasfreed(self.move_groundentity))
\r
224 self.move_groundentity = world;
\r
229 self.move_suspendedinair = FALSE;
\r
231 _Movetype_CheckVelocity();
\r
233 if(self.move_movetype == MOVETYPE_BOUNCE || self.move_movetype == MOVETYPE_TOSS)
\r
235 self.move_didgravity = TRUE;
\r
237 self.move_velocity_z -= dt * self.gravity * getstatf(STAT_MOVEVARS_GRAVITY);
\r
239 self.move_velocity_z -= dt * getstatf(STAT_MOVEVARS_GRAVITY);
\r
242 self.move_angles = self.move_angles + self.move_avelocity * dt;
\r
244 float movetime, bump;
\r
246 for(bump = 0; bump < MAX_CLIP_PLANES && movetime > 0; ++bump)
\r
249 move = self.move_velocity * movetime;
\r
250 _Movetype_PushEntity(move, TRUE);
\r
254 if(trace_startsolid)
\r
256 _Movetype_UnstickEntity();
\r
257 _Movetype_PushEntity(move, FALSE);
\r
262 if(trace_fraction == 1)
\r
265 movetime *= 1 - min(1, trace_fraction);
\r
267 if(self.move_movetype == MOVETYPE_BOUNCEMISSILE)
\r
269 self.move_velocity = _Movetype_ClipVelocity(self.move_velocity, trace_plane_normal, 2.0);
\r
270 self.move_flags &~= FL_ONGROUND;
\r
272 else if(self.move_movetype == MOVETYPE_BOUNCE)
\r
274 float d, bouncefac, bouncestop;
\r
276 bouncefac = self.move_bounce_factor; if(!bouncefac) bouncefac = 0.5;
\r
277 bouncestop = self.move_bounce_stopspeed; if(!bouncestop) bouncestop = 60 / 800;
\r
279 bouncestop *= self.gravity * getstatf(STAT_MOVEVARS_GRAVITY);
\r
281 bouncestop *= getstatf(STAT_MOVEVARS_GRAVITY);
\r
283 self.move_velocity = _Movetype_ClipVelocity(self.move_velocity, trace_plane_normal, 1 + bouncefac);
\r
285 d = trace_plane_normal * self.move_velocity;
\r
286 if(trace_plane_normal_z > 0.7 && d < bouncestop && d > -bouncestop)
\r
288 self.move_flags |= FL_ONGROUND;
\r
289 self.move_groundentity = trace_ent;
\r
290 self.move_velocity = '0 0 0';
\r
291 self.move_avelocity = '0 0 0';
\r
294 self.move_flags &~= FL_ONGROUND;
\r
298 self.move_velocity = _Movetype_ClipVelocity(self.move_velocity, trace_plane_normal, 1.0);
\r
299 if(trace_plane_normal_z > 0.7)
\r
301 self.move_flags |= FL_ONGROUND;
\r
302 self.move_groundentity = trace_ent;
\r
303 if(trace_ent.solid == SOLID_BSP)
\r
304 self.move_suspendedinair = TRUE;
\r
305 self.move_velocity = '0 0 0';
\r
306 self.move_avelocity = '0 0 0';
\r
309 self.move_flags &~= FL_ONGROUND;
\r
312 // DP revision 8905 (just, WHY...)
\r
313 if(self.move_movetype == MOVETYPE_BOUNCEMISSILE)
\r
316 // DP revision 8918 (WHY...)
\r
317 if(self.move_flags & FL_ONGROUND)
\r
321 _Movetype_CheckWaterTransition();
\r
324 void _Movetype_Physics_Frame(float movedt)
\r
326 self.move_didgravity = FALSE;
\r
327 switch(self.move_movetype)
\r
329 case MOVETYPE_PUSH:
\r
330 case MOVETYPE_FAKEPUSH:
\r
331 error("SV_Physics_Pusher not implemented");
\r
333 case MOVETYPE_NONE:
\r
335 case MOVETYPE_FOLLOW:
\r
336 error("SV_Physics_Follow not implemented");
\r
338 case MOVETYPE_NOCLIP:
\r
339 _Movetype_CheckWater();
\r
340 self.move_origin = self.move_origin + ticrate * self.move_velocity;
\r
341 self.move_angles = self.move_angles + ticrate * self.move_avelocity;
\r
342 _Movetype_LinkEdict(FALSE);
\r
344 case MOVETYPE_STEP:
\r
345 error("SV_Physics_Step not implemented");
\r
347 case MOVETYPE_WALK:
\r
348 error("SV_Physics_Walk not implemented");
\r
350 case MOVETYPE_TOSS:
\r
351 case MOVETYPE_BOUNCE:
\r
352 case MOVETYPE_BOUNCEMISSILE:
\r
353 case MOVETYPE_FLYMISSILE:
\r
355 _Movetype_Physics_Toss(movedt);
\r
360 void Movetype_Physics_NoMatchServer() // optimized
\r
364 movedt = time - self.move_time;
\r
365 self.move_time = time;
\r
367 //self.move_didgravity = ((self.move_movetype == MOVETYPE_BOUNCE || self.move_movetype == MOVETYPE_TOSS) && !(self.move_flags & FL_ONGROUND));
\r
368 // we use the field as set by the last run of this
\r
370 _Movetype_Physics_Frame(movedt);
\r
374 self.avelocity = self.move_avelocity;
\r
375 self.velocity = self.move_velocity;
\r
376 self.angles = self.move_angles;
\r
377 setorigin(self, self.move_origin);
\r
380 void Movetype_Physics_MatchServer(float sloppy)
\r
382 Movetype_Physics_MatchTicrate(ticrate, sloppy);
\r
385 void Movetype_Physics_MatchTicrate(float tr, float sloppy) // SV_Physics_Entity
\r
387 float n, i, dt, movedt;
\r
391 Movetype_Physics_NoMatchServer();
\r
395 dt = time - self.move_time;
\r
398 n = max(0, floor(dt / tr));
\r
400 self.move_time += n * tr;
\r
402 //self.move_didgravity = ((self.move_movetype == MOVETYPE_BOUNCE || self.move_movetype == MOVETYPE_TOSS) && !(self.move_flags & FL_ONGROUND));
\r
403 // we use the field as set by the last run of this
\r
405 for(i = 0; i < n; ++i)
\r
407 _Movetype_Physics_Frame(movedt);
\r
412 self.avelocity = self.move_avelocity;
\r
414 if(dt > 0 && self.move_movetype != MOVETYPE_NONE && !(self.move_flags & FL_ONGROUND))
\r
416 // now continue the move from move_time to time
\r
417 self.velocity = self.move_velocity;
\r
418 if(self.move_didgravity)
\r
421 self.velocity_z -= dt * self.gravity * getstatf(STAT_MOVEVARS_GRAVITY);
\r
423 self.velocity_z -= dt * getstatf(STAT_MOVEVARS_GRAVITY);
\r
426 self.angles = self.move_angles + dt * self.avelocity;
\r
428 if(sloppy || self.movetype == MOVETYPE_NOCLIP)
\r
430 setorigin(self, self.move_origin + dt * self.velocity);
\r
434 _Movetype_PushEntityTrace(dt * self.velocity);
\r
435 if(!trace_startsolid)
\r
436 setorigin(self, trace_endpos);
\r
441 self.velocity = self.move_velocity;
\r
442 self.angles = self.move_angles;
\r
443 setorigin(self, self.move_origin);
\r