]> de.git.xonotic.org Git - voretournament/voretournament.git/blob - data/qcsrc/client/movetypes.qc
Get the swallow model working as intended. Adjustments still needed however
[voretournament/voretournament.git] / data / qcsrc / client / movetypes.qc
1 .entity move_groundentity;\r
2 .float move_suspendedinair;\r
3 .float move_didgravity;\r
4 \r
5 void _Movetype_CheckVelocity() // SV_CheckVelocity\r
6 {\r
7 }\r
8 \r
9 float _Movetype_CheckWater() // SV_CheckWater\r
10 {\r
11         return FALSE;\r
12 }\r
13 \r
14 void _Movetype_CheckWaterTransition() // SV_CheckWaterTransition\r
15 {\r
16 }\r
17 \r
18 void _Movetype_Impact(entity oth) // SV_Impact\r
19 {\r
20         entity oldother, oldself;\r
21 \r
22         oldself = self;\r
23         oldother = other;\r
24 \r
25         if(self.move_touch)\r
26         {\r
27                 other = oth;\r
28 \r
29                 self.move_touch();\r
30 \r
31                 other = oldother;\r
32         }\r
33 \r
34         if(oth.move_touch)\r
35         {\r
36                 other = self;\r
37                 self = oth;\r
38 \r
39                 self.move_touch();\r
40 \r
41                 self = oldself;\r
42                 other = oldother;\r
43         }\r
44 }\r
45 \r
46 void _Movetype_LinkEdict_TouchAreaGrid() // SV_LinkEdict_TouchAreaGrid\r
47 {\r
48         entity e, oldself, oldother;\r
49 \r
50         oldself = self;\r
51         oldother = other;\r
52 \r
53         for(e = findradius(0.5 * (self.absmin + self.absmax), 0.5 * vlen(self.absmax - self.absmin)); e; e = e.chain)\r
54         {\r
55                 if(e.move_touch)\r
56                 if(boxesoverlap(e.absmin, e.absmax, oldself.absmin, oldself.absmax))\r
57                 {\r
58                         self = e;\r
59                         other = oldself;\r
60 \r
61                         trace_allsolid = FALSE;\r
62                         trace_startsolid = FALSE;\r
63                         trace_fraction = 1;\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
70 \r
71                         e.move_touch();\r
72                 }\r
73         }\r
74 \r
75         other = oldother;\r
76         self = oldself;\r
77 }\r
78 \r
79 void _Movetype_LinkEdict(float touch_triggers) // SV_LinkEdict\r
80 {\r
81         vector mi, ma;\r
82         if(self.solid == SOLID_BSP)\r
83         {\r
84                 // TODO set the absolute bbox\r
85                 mi = self.mins;\r
86                 ma = self.maxs;\r
87         }\r
88         else\r
89         {\r
90                 mi = self.mins;\r
91                 ma = self.maxs;\r
92         }\r
93         mi = mi + self.origin;\r
94         ma = ma + self.origin;\r
95 \r
96         if(self.move_flags & FL_ITEM)\r
97         {\r
98                 mi_x -= 15;\r
99                 mi_y -= 15;\r
100                 mi_z -= 1;\r
101                 ma_x += 15;\r
102                 ma_y += 15;\r
103                 ma_z += 1;\r
104         }\r
105         else\r
106         {\r
107                 mi_x -= 1;\r
108                 mi_y -= 1;\r
109                 mi_z -= 1;\r
110                 ma_x += 1;\r
111                 ma_y += 1;\r
112                 ma_z += 1;\r
113         }\r
114 \r
115         self.absmin = mi;\r
116         self.absmax = ma;\r
117 \r
118         if(touch_triggers)\r
119                 _Movetype_LinkEdict_TouchAreaGrid();\r
120 }\r
121 \r
122 float _Movetype_TestEntityPosition(vector ofs) // SV_TestEntityPosition\r
123 {\r
124         vector org;\r
125         float cont;\r
126         org = self.move_origin + ofs;\r
127         \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
132 \r
133         if(trace_startsolid)\r
134                 return TRUE;\r
135 \r
136         if(vlen(trace_endpos - self.move_origin) > 0.0001)\r
137                 self.move_origin = trace_endpos;\r
138         return FALSE;\r
139 }\r
140 \r
141 float _Movetype_UnstickEntity() // SV_UnstickEntity\r
142 {\r
143         if(!_Movetype_TestEntityPosition('0 0 0'))\r
144                 return TRUE;\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
153         float i;\r
154         for(i = 1; i <= 17; ++i)\r
155         {\r
156                 if(!_Movetype_TestEntityPosition('0 0 -1' * i)) goto success;\r
157                 if(!_Movetype_TestEntityPosition('0 0 1' * i)) goto success;\r
158         }\r
159         dprint("Some entity is stuck\n");\r
160         return FALSE;\r
161 :success\r
162         dprint("Unstuck some entity\n");\r
163         _Movetype_LinkEdict(TRUE);\r
164         return TRUE;\r
165 }\r
166 \r
167 vector _Movetype_ClipVelocity(vector vel, vector norm, float f) // SV_ClipVelocity\r
168 {\r
169         vel = vel - ((vel * norm) * norm) * f;\r
170 \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
174 \r
175         return vel;\r
176 }\r
177 \r
178 void _Movetype_PushEntityTrace(vector push)\r
179 {\r
180         vector end;\r
181         float type;\r
182 \r
183         end = self.move_origin + push;\r
184 \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
191         else\r
192                 type = MOVE_NORMAL;\r
193 \r
194         tracebox(self.move_origin, self.mins, self.maxs, end, type, self);\r
195 }\r
196 \r
197 float _Movetype_PushEntity(vector push, float failonstartsolid) // SV_PushEntity\r
198 {\r
199         _Movetype_PushEntityTrace(push);\r
200 \r
201         if(trace_startsolid && failonstartsolid)\r
202                 return trace_fraction;\r
203 \r
204         self.move_origin = trace_endpos;\r
205 \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
209 \r
210         return trace_fraction;\r
211 }\r
212 \r
213 #define MAX_CLIP_PLANES 5\r
214 void _Movetype_Physics_Toss(float dt) // SV_Physics_Toss\r
215 {\r
216         if(self.move_flags & FL_ONGROUND)\r
217         {\r
218                 if(self.move_velocity_z >= 1/32)\r
219                         self.move_flags &~= FL_ONGROUND;\r
220                 else if(!self.move_groundentity)\r
221                         return;\r
222                 else if(self.move_suspendedinair && wasfreed(self.move_groundentity))\r
223                 {\r
224                         self.move_groundentity = world;\r
225                         return;\r
226                 }\r
227         }\r
228 \r
229         self.move_suspendedinair = FALSE;\r
230 \r
231         _Movetype_CheckVelocity();\r
232 \r
233         if(self.move_movetype == MOVETYPE_BOUNCE || self.move_movetype == MOVETYPE_TOSS)\r
234         {\r
235                 self.move_didgravity = TRUE;\r
236                 if(self.gravity)\r
237                         self.move_velocity_z -= dt * self.gravity * getstatf(STAT_MOVEVARS_GRAVITY);\r
238                 else\r
239                         self.move_velocity_z -= dt * getstatf(STAT_MOVEVARS_GRAVITY);\r
240         }\r
241 \r
242         self.move_angles = self.move_angles + self.move_avelocity * dt;\r
243 \r
244         float movetime, bump;\r
245         movetime = dt;\r
246         for(bump = 0; bump < MAX_CLIP_PLANES && movetime > 0; ++bump)\r
247         {\r
248                 vector move;\r
249                 move = self.move_velocity * movetime;\r
250                 _Movetype_PushEntity(move, TRUE);\r
251                 if(wasfreed(self))\r
252                         return;\r
253         \r
254                 if(trace_startsolid)\r
255                 {\r
256                         _Movetype_UnstickEntity();\r
257                         _Movetype_PushEntity(move, FALSE);\r
258                         if(wasfreed(self))\r
259                                 return;\r
260                 }\r
261 \r
262                 if(trace_fraction == 1)\r
263                         break;\r
264 \r
265                 movetime *= 1 - min(1, trace_fraction);\r
266 \r
267                 if(self.move_movetype == MOVETYPE_BOUNCEMISSILE)\r
268                 {\r
269                         self.move_velocity = _Movetype_ClipVelocity(self.move_velocity, trace_plane_normal, 2.0);\r
270                         self.move_flags &~= FL_ONGROUND;\r
271                 }\r
272                 else if(self.move_movetype == MOVETYPE_BOUNCE)\r
273                 {\r
274                         float d, bouncefac, bouncestop;\r
275 \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
278                         if(self.gravity)\r
279                                 bouncestop *= self.gravity * getstatf(STAT_MOVEVARS_GRAVITY);\r
280                         else\r
281                                 bouncestop *= getstatf(STAT_MOVEVARS_GRAVITY);\r
282 \r
283                         self.move_velocity = _Movetype_ClipVelocity(self.move_velocity, trace_plane_normal, 1 + bouncefac);\r
284 \r
285                         d = trace_plane_normal * self.move_velocity;\r
286                         if(trace_plane_normal_z > 0.7 && d < bouncestop && d > -bouncestop)\r
287                         {\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
292                         }\r
293                         else\r
294                                 self.move_flags &~= FL_ONGROUND;\r
295                 }\r
296                 else\r
297                 {\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
300                         {\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
307                         }\r
308                         else\r
309                                 self.move_flags &~= FL_ONGROUND;\r
310                 }\r
311 \r
312                 // DP revision 8905 (just, WHY...)\r
313                 if(self.move_movetype == MOVETYPE_BOUNCEMISSILE)\r
314                         break;\r
315 \r
316                 // DP revision 8918 (WHY...)\r
317                 if(self.move_flags & FL_ONGROUND)\r
318                         break;\r
319         }\r
320 \r
321         _Movetype_CheckWaterTransition();\r
322 }\r
323 \r
324 void _Movetype_Physics_Frame(float movedt)\r
325 {\r
326         self.move_didgravity = FALSE;\r
327         switch(self.move_movetype)\r
328         {\r
329                 case MOVETYPE_PUSH:\r
330                 case MOVETYPE_FAKEPUSH:\r
331                         error("SV_Physics_Pusher not implemented");\r
332                         break;\r
333                 case MOVETYPE_NONE:\r
334                         break;\r
335                 case MOVETYPE_FOLLOW:\r
336                         error("SV_Physics_Follow not implemented");\r
337                         break;\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
343                         break;\r
344                 case MOVETYPE_STEP:\r
345                         error("SV_Physics_Step not implemented");\r
346                         break;\r
347                 case MOVETYPE_WALK:\r
348                         error("SV_Physics_Walk not implemented");\r
349                         break;\r
350                 case MOVETYPE_TOSS:\r
351                 case MOVETYPE_BOUNCE:\r
352                 case MOVETYPE_BOUNCEMISSILE:\r
353                 case MOVETYPE_FLYMISSILE:\r
354                 case MOVETYPE_FLY:\r
355                         _Movetype_Physics_Toss(movedt);\r
356                         break;\r
357         }\r
358 }\r
359 \r
360 void Movetype_Physics_NoMatchServer() // optimized\r
361 {\r
362         float movedt;\r
363 \r
364         movedt = time - self.move_time;\r
365         self.move_time = time;\r
366 \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
369 \r
370         _Movetype_Physics_Frame(movedt);\r
371         if(wasfreed(self))\r
372                 return;\r
373 \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
378 }\r
379 \r
380 void Movetype_Physics_MatchServer(float sloppy)\r
381 {\r
382         Movetype_Physics_MatchTicrate(ticrate, sloppy);\r
383 }\r
384 \r
385 void Movetype_Physics_MatchTicrate(float tr, float sloppy) // SV_Physics_Entity\r
386 {\r
387         float n, i, dt, movedt;\r
388 \r
389         if(tr <= 0)\r
390         {\r
391                 Movetype_Physics_NoMatchServer();\r
392                 return;\r
393         }\r
394 \r
395         dt = time - self.move_time;\r
396 \r
397         movedt = tr;\r
398         n = max(0, floor(dt / tr));\r
399         dt -= n * tr;\r
400         self.move_time += n * tr;\r
401 \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
404 \r
405         for(i = 0; i < n; ++i)\r
406         {\r
407                 _Movetype_Physics_Frame(movedt);\r
408                 if(wasfreed(self))\r
409                         return;\r
410         }\r
411 \r
412         self.avelocity = self.move_avelocity;\r
413 \r
414         if(dt > 0 && self.move_movetype != MOVETYPE_NONE && !(self.move_flags & FL_ONGROUND))\r
415         {\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
419                 {\r
420                         if(self.gravity)\r
421                                 self.velocity_z -= dt * self.gravity * getstatf(STAT_MOVEVARS_GRAVITY);\r
422                         else\r
423                                 self.velocity_z -= dt * getstatf(STAT_MOVEVARS_GRAVITY);\r
424                 }\r
425 \r
426                 self.angles = self.move_angles + dt * self.avelocity;\r
427 \r
428                 if(sloppy || self.movetype == MOVETYPE_NOCLIP)\r
429                 {\r
430                         setorigin(self, self.move_origin + dt * self.velocity);\r
431                 }\r
432                 else\r
433                 {\r
434                         _Movetype_PushEntityTrace(dt * self.velocity);\r
435                         if(!trace_startsolid)\r
436                                 setorigin(self, trace_endpos);\r
437                 }\r
438         }\r
439         else\r
440         {\r
441                 self.velocity = self.move_velocity;\r
442                 self.angles = self.move_angles;\r
443                 setorigin(self, self.move_origin);\r
444         }\r
445 }\r