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 void _Movetype_Physics_Toss(float dt) // SV_Physics_Toss
215 if(self.move_flags & FL_ONGROUND)
217 if(self.velocity_z >= 1/32)
218 self.move_flags &~= FL_ONGROUND;
219 else if(!self.move_groundentity)
221 else if(self.move_suspendedinair && wasfreed(self.move_groundentity))
223 self.move_groundentity = world;
228 self.move_suspendedinair = FALSE;
230 _Movetype_CheckVelocity();
232 if(self.move_movetype == MOVETYPE_BOUNCE || self.move_movetype == MOVETYPE_TOSS)
234 self.move_didgravity = TRUE;
236 self.move_velocity_z -= dt * self.gravity * getstatf(STAT_MOVEVARS_GRAVITY);
238 self.move_velocity_z -= dt * getstatf(STAT_MOVEVARS_GRAVITY);
241 self.move_angles = self.move_angles + self.move_avelocity * dt;
244 move = self.move_velocity * dt;
246 _Movetype_PushEntity(move, TRUE);
252 _Movetype_UnstickEntity();
253 _Movetype_PushEntity(move, FALSE);
258 if(trace_fraction < 1)
260 if(self.move_movetype == MOVETYPE_BOUNCEMISSILE)
262 self.move_velocity = _Movetype_ClipVelocity(self.move_velocity, trace_plane_normal, 2.0);
263 self.move_flags &~= FL_ONGROUND;
265 else if(self.move_movetype == MOVETYPE_BOUNCE)
267 float d, bouncefac, bouncestop;
269 bouncefac = self.move_bounce_factor; if(!bouncefac) bouncefac = 0.5;
270 bouncestop = self.move_bounce_stopspeed; if(!bouncestop) bouncestop = 60;
272 self.move_velocity = _Movetype_ClipVelocity(self.move_velocity, trace_plane_normal, 1 + bouncefac);
274 d = trace_plane_normal * self.move_velocity;
275 if(trace_plane_normal_z > 0.7 && d < bouncestop && d > -bouncestop)
277 self.move_flags |= FL_ONGROUND;
278 self.move_groundentity = trace_ent;
279 self.move_velocity = '0 0 0';
280 self.move_avelocity = '0 0 0';
283 self.move_flags &~= FL_ONGROUND;
287 self.move_velocity = _Movetype_ClipVelocity(self.move_velocity, trace_plane_normal, 1.0);
288 if(trace_plane_normal_z > 0.7)
290 self.move_flags |= FL_ONGROUND;
291 self.move_groundentity = trace_ent;
292 if(trace_ent.solid == SOLID_BSP)
293 self.move_suspendedinair = TRUE;
294 self.move_velocity = '0 0 0';
295 self.move_avelocity = '0 0 0';
298 self.move_flags &~= FL_ONGROUND;
302 _Movetype_CheckWaterTransition();
305 void Movetype_Physics(float matchserver) // SV_Physics_Entity
307 float n, i, dt, movedt;
309 dt = time - self.move_time;
314 n = max(0, floor(dt / ticrate));
316 self.move_time += n * ticrate;
323 self.move_time = time;
326 //self.move_didgravity = ((self.move_movetype == MOVETYPE_BOUNCE || self.move_movetype == MOVETYPE_TOSS) && !(self.move_flags & FL_ONGROUND));
327 // we use the field as set by the last run of this
329 for(i = 0; i < n; ++i)
331 self.move_didgravity = FALSE;
332 switch(self.move_movetype)
335 case MOVETYPE_FAKEPUSH:
336 error("SV_Physics_Pusher not implemented");
340 case MOVETYPE_FOLLOW:
341 error("SV_Physics_Follow not implemented");
343 case MOVETYPE_NOCLIP:
344 _Movetype_CheckWater();
345 self.move_origin = self.move_origin + ticrate * self.move_velocity;
346 self.move_angles = self.move_angles + ticrate * self.move_avelocity;
347 _Movetype_LinkEdict(FALSE);
350 error("SV_Physics_Step not implemented");
353 error("SV_Physics_Walk not implemented");
356 case MOVETYPE_BOUNCE:
357 case MOVETYPE_BOUNCEMISSILE:
358 case MOVETYPE_FLYMISSILE:
360 _Movetype_Physics_Toss(movedt);
365 self.avelocity = self.move_avelocity;
367 if(dt > 0 && self.move_movetype != MOVETYPE_NONE)
369 // now continue the move from move_time to time
370 self.velocity = self.move_velocity;
371 if(self.move_didgravity)
374 self.velocity_z -= dt * self.gravity * getstatf(STAT_MOVEVARS_GRAVITY);
376 self.velocity_z -= dt * getstatf(STAT_MOVEVARS_GRAVITY);
379 self.angles = self.move_angles + dt * self.avelocity;
381 if(self.movetype != MOVETYPE_NOCLIP)
383 _Movetype_PushEntityTrace(dt * self.velocity);
384 if(!trace_startsolid)
385 self.origin = trace_endpos;
388 self.origin = self.move_origin + dt * self.velocity;
392 self.velocity = self.move_velocity;
393 self.angles = self.move_angles;
394 self.origin = self.move_origin;
398 setorigin(self, self.origin);