2 #include "../physics.qh"
5 #include "../../dpdefs/csprogsdefs.qh"
6 #include "../../client/defs.qh"
9 #include "movetypes.qh"
10 #include "../../csqcmodellib/common.qh"
11 #include "../../server/t_items.qh"
14 #include "../../server/autocvars.qh"
17 void _Movetype_CheckVelocity() // SV_CheckVelocity
21 float _Movetype_CheckWater(entity ent) // SV_CheckWater
23 vector point = ent.move_origin;
24 point_z += (ent.mins_z + 1);
26 int nativecontents = pointcontents(point);
28 if(ent.move_watertype)
29 if(ent.move_watertype != nativecontents)
31 //dprintf("_Movetype_CheckWater(): Original: '%d', New: '%d'\n", ent.move_watertype, nativecontents);
32 if(ent.contentstransition)
33 ent.contentstransition(ent.move_watertype, nativecontents);
36 ent.move_waterlevel = 0;
37 ent.move_watertype = CONTENT_EMPTY;
39 int supercontents = Mod_Q1BSP_SuperContentsFromNativeContents(nativecontents);
40 if(supercontents & DPCONTENTS_LIQUIDSMASK)
42 ent.move_watertype = nativecontents;
43 ent.move_waterlevel = 1;
44 point_y = (ent.origin_y + ((ent.mins_z + ent.maxs_y) * 0.5));
45 if(Mod_Q1BSP_SuperContentsFromNativeContents(pointcontents(point)) & DPCONTENTS_LIQUIDSMASK)
47 ent.move_waterlevel = 2;
48 point_y = ent.origin_y + ent.view_ofs_y;
49 if(Mod_Q1BSP_SuperContentsFromNativeContents(pointcontents(point)) & DPCONTENTS_LIQUIDSMASK)
50 ent.move_waterlevel = 3;
54 return (ent.move_waterlevel > 1);
57 void _Movetype_CheckWaterTransition(entity ent) // SV_CheckWaterTransition
59 float contents = pointcontents(ent.move_origin);
61 if(!ent.move_watertype)
64 if(!autocvar_cl_gameplayfix_fixedcheckwatertransition)
66 ent.move_watertype = contents;
67 ent.move_waterlevel = 1;
71 else if(ent.move_watertype != contents)
73 //dprintf("_Movetype_CheckWaterTransition(): Origin: %s, Direct: '%d', Original: '%d', New: '%d'\n", vtos(ent.move_origin), pointcontents(ent.move_origin), ent.move_watertype, contents);
74 if(ent.contentstransition)
75 ent.contentstransition(ent.move_watertype, contents);
78 if(contents <= CONTENT_WATER)
80 ent.move_watertype = contents;
81 ent.move_waterlevel = 1;
85 ent.move_watertype = CONTENT_EMPTY;
86 ent.move_waterlevel = (autocvar_cl_gameplayfix_fixedcheckwatertransition ? 0 : contents);
90 void _Movetype_Impact(entity oth) // SV_Impact
92 entity oldother, oldself;
118 void _Movetype_LinkEdict_TouchAreaGrid() // SV_LinkEdict_TouchAreaGrid
120 entity e, oldself, oldother;
125 for(e = findradius(0.5 * (self.absmin + self.absmax), 0.5 * vlen(self.absmax - self.absmin)); e; e = e.chain)
128 if(boxesoverlap(e.absmin, e.absmax, oldself.absmin, oldself.absmax))
133 trace_allsolid = false;
134 trace_startsolid = false;
136 trace_inwater = false;
138 trace_endpos = e.origin;
139 trace_plane_normal = '0 0 1';
140 trace_plane_dist = 0;
151 void _Movetype_LinkEdict(float touch_triggers) // SV_LinkEdict
154 if(self.solid == SOLID_BSP)
156 // TODO set the absolute bbox
165 mi = mi + self.origin;
166 ma = ma + self.origin;
168 if(self.move_flags & FL_ITEM)
191 _Movetype_LinkEdict_TouchAreaGrid();
194 float _Movetype_TestEntityPosition(vector ofs) // SV_TestEntityPosition
197 org = self.move_origin + ofs;
199 int cont = self.dphitcontentsmask;
200 self.dphitcontentsmask = DPCONTENTS_SOLID;
201 tracebox(self.move_origin, self.mins, self.maxs, self.move_origin, MOVE_NOMONSTERS, self);
202 self.dphitcontentsmask = cont;
207 if(vlen(trace_endpos - self.move_origin) > 0.0001)
208 self.move_origin = trace_endpos;
212 float _Movetype_UnstickEntity() // SV_UnstickEntity
214 if(!_Movetype_TestEntityPosition('0 0 0'))
216 if(!_Movetype_TestEntityPosition('-1 0 0')) goto success;
217 if(!_Movetype_TestEntityPosition('1 0 0')) goto success;
218 if(!_Movetype_TestEntityPosition('0 -1 0')) goto success;
219 if(!_Movetype_TestEntityPosition('0 1 0')) goto success;
220 if(!_Movetype_TestEntityPosition('-1 -1 0')) goto success;
221 if(!_Movetype_TestEntityPosition('1 -1 0')) goto success;
222 if(!_Movetype_TestEntityPosition('-1 1 0')) goto success;
223 if(!_Movetype_TestEntityPosition('1 1 0')) goto success;
225 for(i = 1; i <= 17; ++i)
227 if(!_Movetype_TestEntityPosition('0 0 -1' * i)) goto success;
228 if(!_Movetype_TestEntityPosition('0 0 1' * i)) goto success;
230 dprintf("Can't unstick an entity (edict: %d, classname: %s, origin: %s)\n", num_for_edict(self), self.classname, vtos(self.move_origin));
233 dprintf("Sucessfully unstuck an entity (edict: %d, classname: %s, origin: %s)\n", num_for_edict(self), self.classname, vtos(self.move_origin));
234 _Movetype_LinkEdict(true);
238 vector _Movetype_ClipVelocity(vector vel, vector norm, float f) // SV_ClipVelocity
240 vel = vel - ((vel * norm) * norm) * f;
242 if(vel_x > -0.1 && vel_x < 0.1) vel_x = 0;
243 if(vel_y > -0.1 && vel_y < 0.1) vel_y = 0;
244 if(vel_z > -0.1 && vel_z < 0.1) vel_z = 0;
249 void _Movetype_PushEntityTrace(vector push)
254 end = self.move_origin + push;
256 if(self.move_nomonsters)
257 type = max(0, self.move_nomonsters);
258 else if(self.move_movetype == MOVETYPE_FLYMISSILE)
260 else if(self.solid == SOLID_TRIGGER || self.solid == SOLID_NOT)
261 type = MOVE_NOMONSTERS;
265 tracebox(self.move_origin, self.mins, self.maxs, end, type, self);
268 float _Movetype_PushEntity(vector push, float failonstartsolid) // SV_PushEntity
270 _Movetype_PushEntityTrace(push);
272 if(trace_startsolid && failonstartsolid)
273 return trace_fraction;
275 self.move_origin = trace_endpos;
277 if(trace_fraction < 1)
278 if(self.solid >= SOLID_TRIGGER && (!(self.move_flags & FL_ONGROUND) || (self.move_groundentity != trace_ent)))
279 _Movetype_Impact(trace_ent);
281 return trace_fraction;
287 // matrix version of makevectors, sets v_forward, v_right and v_up
288 void makevectors_matrix(vector myangles) // AngleVectorsFLU
290 float angle, sr, sp, sy, cr, cp, cy;
292 v_forward = v_right = v_up = '0 0 0';
294 angle = myangles_y * (M_PI*2 / 360);
297 angle = myangles_x * (M_PI*2 / 360);
310 angle = myangles_z * (M_PI*2 / 360);
315 v_right_x = sr*sp*cy+cr*-sy;
316 v_right_y = sr*sp*sy+cr*cy;
321 v_up_x = cr*sp*cy+-sr*-sy;
322 v_up_y = cr*sp*sy+-sr*cy;
344 void _Movetype_Physics_Frame(float movedt)
346 self.move_didgravity = -1;
347 switch(self.move_movetype)
350 case MOVETYPE_FAKEPUSH:
351 _Movetype_Physics_Pusher(movedt);
355 case MOVETYPE_FOLLOW:
356 error("SV_Physics_Follow not implemented");
358 case MOVETYPE_NOCLIP:
359 _Movetype_CheckWater(self);
360 self.move_origin = self.move_origin + TICRATE * self.move_velocity;
361 self.move_angles = self.move_angles + TICRATE * self.move_avelocity;
362 _Movetype_LinkEdict(false);
365 error("SV_Physics_Step not implemented");
368 error("SV_Physics_Walk not implemented");
371 case MOVETYPE_BOUNCE:
372 case MOVETYPE_BOUNCEMISSILE:
373 case MOVETYPE_FLYMISSILE:
375 _Movetype_Physics_Toss(movedt);
380 void Movetype_Physics_NoMatchServer() // optimized
384 movedt = time - self.move_time;
385 self.move_time = time;
387 _Movetype_Physics_Frame(movedt);
391 self.avelocity = self.move_avelocity;
392 self.velocity = self.move_velocity;
393 self.angles = self.move_angles;
394 setorigin(self, self.move_origin);
397 void Movetype_Physics_MatchServer(bool sloppy)
399 Movetype_Physics_MatchTicrate(TICRATE, sloppy);
402 void Movetype_Physics_MatchTicrate(float tr, bool sloppy) // SV_Physics_Entity
404 float n, i, dt, movedt;
408 Movetype_Physics_NoMatchServer();
412 dt = time - self.move_time;
415 n = max(0, floor(dt / tr));
417 self.move_time += n * tr;
419 if(!self.move_didgravity)
420 self.move_didgravity = ((self.move_movetype == MOVETYPE_BOUNCE || self.move_movetype == MOVETYPE_TOSS) && !(self.move_flags & FL_ONGROUND));
422 for(i = 0; i < n; ++i)
424 _Movetype_Physics_Frame(movedt);
429 self.avelocity = self.move_avelocity;
431 if(dt > 0 && self.move_movetype != MOVETYPE_NONE && !(self.move_flags & FL_ONGROUND))
433 // now continue the move from move_time to time
434 self.velocity = self.move_velocity;
436 if(self.move_didgravity > 0)
438 if(GRAVITY_UNAFFECTED_BY_TICRATE)
441 self.velocity_z -= 0.5 * dt * self.gravity * PHYS_GRAVITY;
443 self.velocity_z -= 0.5 * dt * PHYS_GRAVITY;
448 self.velocity_z -= dt * self.gravity * PHYS_GRAVITY;
450 self.velocity_z -= dt * PHYS_GRAVITY;
454 self.angles = self.move_angles + dt * self.avelocity;
456 if(sloppy || self.movetype == MOVETYPE_NOCLIP)
458 setorigin(self, self.move_origin + dt * self.velocity);
462 _Movetype_PushEntityTrace(dt * self.velocity);
463 if(!trace_startsolid)
464 setorigin(self, trace_endpos);
467 if(self.move_didgravity > 0)
469 if(GRAVITY_UNAFFECTED_BY_TICRATE)
472 self.velocity_z -= 0.5 * dt * self.gravity * PHYS_GRAVITY;
474 self.velocity_z -= 0.5 * dt * PHYS_GRAVITY;
480 self.velocity = self.move_velocity;
481 self.angles = self.move_angles;
482 setorigin(self, self.move_origin);