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