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_movetype == MOVETYPE_FLYMISSILE)
187 else if(self.solid == SOLID_TRIGGER || self.solid == SOLID_NOT)
188 type = MOVE_NOMONSTERS;
192 tracebox(self.move_origin, self.mins, self.maxs, end, type, self);
195 float _Movetype_PushEntity(vector push, float failonstartsolid) // SV_PushEntity
197 _Movetype_PushEntityTrace(push);
199 if(trace_startsolid && failonstartsolid)
200 return trace_fraction;
202 self.move_origin = trace_endpos;
204 if(trace_fraction < 1)
205 if(self.solid >= SOLID_TRIGGER && (!(self.move_flags & FL_ONGROUND) || (self.move_groundentity != trace_ent)))
206 _Movetype_Impact(trace_ent);
208 return trace_fraction;
211 void _Movetype_Physics_Toss(float dt) // SV_Physics_Toss
213 if(self.move_flags & FL_ONGROUND)
215 if(self.velocity_z >= 1/32)
216 self.move_flags &~= FL_ONGROUND;
217 else if(!self.move_groundentity)
219 else if(self.move_suspendedinair && wasfreed(self.move_groundentity))
221 self.move_groundentity = world;
226 self.move_suspendedinair = FALSE;
228 _Movetype_CheckVelocity();
230 if(self.move_movetype == MOVETYPE_BOUNCE || self.move_movetype == MOVETYPE_TOSS)
232 self.move_didgravity = TRUE;
234 self.move_velocity_z -= dt * self.gravity * getstatf(STAT_MOVEVARS_GRAVITY);
236 self.move_velocity_z -= dt * getstatf(STAT_MOVEVARS_GRAVITY);
239 self.move_angles = self.move_angles + self.move_avelocity * dt;
242 move = self.move_velocity * dt;
244 _Movetype_PushEntity(move, TRUE);
250 _Movetype_UnstickEntity();
251 _Movetype_PushEntity(move, FALSE);
256 if(trace_fraction < 1)
258 if(self.move_movetype == MOVETYPE_BOUNCEMISSILE)
260 self.move_velocity = _Movetype_ClipVelocity(self.move_velocity, trace_plane_normal, 2.0);
261 self.move_flags &~= FL_ONGROUND;
263 else if(self.move_movetype == MOVETYPE_BOUNCE)
265 float d, bouncefac, bouncestop;
267 bouncefac = self.move_bounce_factor; if(!bouncefac) bouncefac = 0.5;
268 bouncestop = self.move_bounce_stopspeed; if(!bouncestop) bouncestop = 60;
270 self.move_velocity = _Movetype_ClipVelocity(self.move_velocity, trace_plane_normal, 1 + bouncefac);
272 d = trace_plane_normal * self.move_velocity;
273 if(trace_plane_normal_z > 0.7 && d < bouncestop && d > -bouncestop)
275 self.move_flags |= FL_ONGROUND;
276 self.move_groundentity = trace_ent;
277 self.move_velocity = '0 0 0';
278 self.move_avelocity = '0 0 0';
281 self.move_flags &~= FL_ONGROUND;
285 self.move_velocity = _Movetype_ClipVelocity(self.move_velocity, trace_plane_normal, 1.0);
286 if(trace_plane_normal_z > 0.7)
288 self.move_flags |= FL_ONGROUND;
289 self.move_groundentity = trace_ent;
290 if(trace_ent.solid == SOLID_BSP)
291 self.move_suspendedinair = TRUE;
292 self.move_velocity = '0 0 0';
293 self.move_avelocity = '0 0 0';
296 self.move_flags &~= FL_ONGROUND;
300 _Movetype_CheckWaterTransition();
303 void Movetype_Physics(float matchserver) // SV_Physics_Entity
305 float n, i, dt, movedt;
307 dt = time - self.move_time;
312 n = max(0, floor(dt / ticrate));
314 self.move_time += n * ticrate;
321 self.move_time = time;
324 //self.move_didgravity = ((self.move_movetype == MOVETYPE_BOUNCE || self.move_movetype == MOVETYPE_TOSS) && !(self.move_flags & FL_ONGROUND));
325 // we use the field as set by the last run of this
327 for(i = 0; i < n; ++i)
329 self.move_didgravity = FALSE;
330 switch(self.move_movetype)
333 case MOVETYPE_FAKEPUSH:
334 error("SV_Physics_Pusher not implemented");
338 case MOVETYPE_FOLLOW:
339 error("SV_Physics_Follow not implemented");
341 case MOVETYPE_NOCLIP:
342 _Movetype_CheckWater();
343 self.move_origin = self.move_origin + ticrate * self.move_velocity;
344 self.move_angles = self.move_angles + ticrate * self.move_avelocity;
345 _Movetype_LinkEdict(FALSE);
348 error("SV_Physics_Step not implemented");
351 error("SV_Physics_Walk not implemented");
354 case MOVETYPE_BOUNCE:
355 case MOVETYPE_BOUNCEMISSILE:
356 case MOVETYPE_FLYMISSILE:
358 _Movetype_Physics_Toss(movedt);
363 self.avelocity = self.move_avelocity;
365 if(dt > 0 && self.move_movetype != MOVETYPE_NONE)
367 // now continue the move from move_time to time
368 self.velocity = self.move_velocity;
369 if(self.move_didgravity)
372 self.velocity_z -= dt * self.gravity * getstatf(STAT_MOVEVARS_GRAVITY);
374 self.velocity_z -= dt * getstatf(STAT_MOVEVARS_GRAVITY);
377 self.angles = self.move_angles + dt * self.avelocity;
379 if(self.movetype != MOVETYPE_NOCLIP)
381 _Movetype_PushEntityTrace(dt * self.velocity);
382 if(!trace_startsolid)
383 self.origin = trace_endpos;
386 self.origin = self.move_origin + dt * self.velocity;
390 self.velocity = self.move_velocity;
391 self.angles = self.move_angles;
392 self.origin = self.move_origin;
396 setorigin(self, self.origin);