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