]> icculus.org git repositories - divverent/darkplaces.git/blob - sv_phys.c
qsockets are now dynamically allocated/freed, this drops memory use by about 2mb
[divverent/darkplaces.git] / sv_phys.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // sv_phys.c
21
22 #include "quakedef.h"
23
24 /*
25
26
27 pushmove objects do not obey gravity, and do not interact with each other or trigger fields, but block normal movement and push normal objects when they move.
28
29 onground is set for toss objects when they come to a complete rest.  it is set for steping or walking objects
30
31 doors, plats, etc are SOLID_BSP, and MOVETYPE_PUSH
32 bonus items are SOLID_TRIGGER touch, and MOVETYPE_TOSS
33 corpses are SOLID_NOT and MOVETYPE_TOSS
34 crates are SOLID_BBOX and MOVETYPE_TOSS
35 walking monsters are SOLID_SLIDEBOX and MOVETYPE_STEP
36 flying/floating monsters are SOLID_SLIDEBOX and MOVETYPE_FLY
37
38 solid_edge items only clip against bsp models.
39
40 */
41
42 cvar_t  sv_friction = {CVAR_NOTIFY, "sv_friction","4"};
43 cvar_t  sv_stopspeed = {0, "sv_stopspeed","100"};
44 cvar_t  sv_gravity = {CVAR_NOTIFY, "sv_gravity","800"};
45 cvar_t  sv_maxvelocity = {0, "sv_maxvelocity","2000"};
46 cvar_t  sv_nostep = {0, "sv_nostep","0"};
47
48 #define MOVE_EPSILON    0.01
49
50 void SV_Physics_Toss (edict_t *ent);
51
52 /*
53 ================
54 SV_CheckAllEnts
55 ================
56 */
57 void SV_CheckAllEnts (void)
58 {
59         int                     e;
60         edict_t         *check;
61
62 // see if any solid entities are inside the final position
63         check = NEXT_EDICT(sv.edicts);
64         for (e=1 ; e<sv.num_edicts ; e++, check = NEXT_EDICT(check))
65         {
66                 if (check->free)
67                         continue;
68                 if (check->v.movetype == MOVETYPE_PUSH
69                 || check->v.movetype == MOVETYPE_NONE
70                 || check->v.movetype == MOVETYPE_FOLLOW
71                 || check->v.movetype == MOVETYPE_NOCLIP)
72                         continue;
73
74                 if (SV_TestEntityPosition (check))
75                         Con_Printf ("entity in invalid position\n");
76         }
77 }
78
79 /*
80 ================
81 SV_CheckVelocity
82 ================
83 */
84 void SV_CheckVelocity (edict_t *ent)
85 {
86         int             i;
87         float   wishspeed;
88
89 //
90 // bound velocity
91 //
92         for (i=0 ; i<3 ; i++)
93         {
94                 if (IS_NAN(ent->v.velocity[i]))
95                 {
96                         Con_Printf ("Got a NaN velocity on %s\n", pr_strings + ent->v.classname);
97                         ent->v.velocity[i] = 0;
98                 }
99                 if (IS_NAN(ent->v.origin[i]))
100                 {
101                         Con_Printf ("Got a NaN origin on %s\n", pr_strings + ent->v.classname);
102                         ent->v.origin[i] = 0;
103                 }
104                 // LordHavoc: maxvelocity fix, see below
105 /*
106                 if (ent->v.velocity[i] > sv_maxvelocity.value)
107                         ent->v.velocity[i] = sv_maxvelocity.value;
108                 else if (ent->v.velocity[i] < -sv_maxvelocity.value)
109                         ent->v.velocity[i] = -sv_maxvelocity.value;
110 */
111         }
112
113         // LordHavoc: max velocity fix, inspired by Maddes's source fixes, but this is faster
114         wishspeed = DotProduct(ent->v.velocity, ent->v.velocity);
115         if (wishspeed > sv_maxvelocity.value * sv_maxvelocity.value)
116         {
117                 wishspeed = sv_maxvelocity.value / sqrt(wishspeed);
118                 ent->v.velocity[0] *= wishspeed;
119                 ent->v.velocity[1] *= wishspeed;
120                 ent->v.velocity[2] *= wishspeed;
121                 wishspeed = sv_maxvelocity.value;
122         }
123 }
124
125 /*
126 =============
127 SV_RunThink
128
129 Runs thinking code if time.  There is some play in the exact time the think
130 function will be called, because it is called before any movement is done
131 in a frame.  Not used for pushmove objects, because they must be exact.
132 Returns false if the entity removed itself.
133 =============
134 */
135 qboolean SV_RunThink (edict_t *ent)
136 {
137         float   thinktime;
138
139         thinktime = ent->v.nextthink;
140         if (thinktime <= 0 || thinktime > sv.time + sv.frametime)
141                 return true;
142                 
143         if (thinktime < sv.time)
144                 thinktime = sv.time;    // don't let things stay in the past.
145                                                                 // it is possible to start that way
146                                                                 // by a trigger with a local time.
147         ent->v.nextthink = 0;
148         pr_global_struct->time = thinktime;
149         pr_global_struct->self = EDICT_TO_PROG(ent);
150         pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
151         PR_ExecuteProgram (ent->v.think, "NULL think function");
152         return !ent->free;
153 }
154
155 /*
156 ==================
157 SV_Impact
158
159 Two entities have touched, so run their touch functions
160 ==================
161 */
162 void SV_Impact (edict_t *e1, edict_t *e2)
163 {
164         int             old_self, old_other;
165         
166         old_self = pr_global_struct->self;
167         old_other = pr_global_struct->other;
168         
169         pr_global_struct->time = sv.time;
170         if (e1->v.touch && e1->v.solid != SOLID_NOT)
171         {
172                 pr_global_struct->self = EDICT_TO_PROG(e1);
173                 pr_global_struct->other = EDICT_TO_PROG(e2);
174                 PR_ExecuteProgram (e1->v.touch, "");
175         }
176         
177         if (e2->v.touch && e2->v.solid != SOLID_NOT)
178         {
179                 pr_global_struct->self = EDICT_TO_PROG(e2);
180                 pr_global_struct->other = EDICT_TO_PROG(e1);
181                 PR_ExecuteProgram (e2->v.touch, "");
182         }
183
184         pr_global_struct->self = old_self;
185         pr_global_struct->other = old_other;
186 }
187
188
189 /*
190 ==================
191 ClipVelocity
192
193 Slide off of the impacting object
194 returns the blocked flags (1 = floor, 2 = step / wall)
195 ==================
196 */
197 #define STOP_EPSILON    0.1
198
199 int ClipVelocity (vec3_t in, vec3_t normal, vec3_t out, float overbounce)
200 {
201         float   backoff;
202         float   change;
203         int             i, blocked;
204         
205         blocked = 0;
206         if (normal[2] > 0)
207                 blocked |= 1;           // floor
208         if (!normal[2])
209                 blocked |= 2;           // step
210         
211         backoff = DotProduct (in, normal) * overbounce;
212
213         for (i=0 ; i<3 ; i++)
214         {
215                 change = normal[i]*backoff;
216                 out[i] = in[i] - change;
217                 if (out[i] > -STOP_EPSILON && out[i] < STOP_EPSILON)
218                         out[i] = 0;
219         }
220
221         return blocked;
222 }
223
224
225 /*
226 ============
227 SV_FlyMove
228
229 The basic solid body movement clip that slides along multiple planes
230 Returns the clipflags if the velocity was modified (hit something solid)
231 1 = floor
232 2 = wall / step
233 4 = dead stop
234 If steptrace is not NULL, the trace of any vertical wall hit will be stored
235 ============
236 */
237 // LordHavoc: increased from 5 to 20, to partially fix angled corner sticking
238 // (example - start.bsp hall to e4, leading to the pool there are two
239 //  angled corners, which you could get stuck on, now they are just a one
240 //  frame hiccup)
241 #define MAX_CLIP_PLANES 20
242 int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace)
243 {
244         int                     bumpcount, numbumps;
245         vec3_t          dir;
246         float           d;
247         int                     numplanes;
248         vec3_t          planes[MAX_CLIP_PLANES];
249         vec3_t          primal_velocity, original_velocity, new_velocity;
250         int                     i, j;
251         trace_t         trace;
252         vec3_t          end;
253         float           time_left;
254         int                     blocked;
255         
256         numbumps = 4;
257         
258         blocked = 0;
259         VectorCopy (ent->v.velocity, original_velocity);
260         VectorCopy (ent->v.velocity, primal_velocity);
261         numplanes = 0;
262         
263         time_left = time;
264
265         for (bumpcount=0 ; bumpcount<numbumps ; bumpcount++)
266         {
267                 if (!ent->v.velocity[0] && !ent->v.velocity[1] && !ent->v.velocity[2])
268                         break;
269
270                 for (i=0 ; i<3 ; i++)
271                         end[i] = ent->v.origin[i] + time_left * ent->v.velocity[i];
272
273                 trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NORMAL, ent);
274
275                 if (trace.allsolid)
276                 {       // entity is trapped in another solid
277                         VectorClear(ent->v.velocity);
278                         return 3;
279                 }
280
281                 if (trace.fraction > 0)
282                 {       // actually covered some distance
283                         VectorCopy (trace.endpos, ent->v.origin);
284                         VectorCopy (ent->v.velocity, original_velocity);
285                         numplanes = 0;
286                 }
287
288                 if (trace.fraction == 1)
289                          break;         // moved the entire distance
290
291                 if (!trace.ent)
292                         Host_Error ("SV_FlyMove: !trace.ent");
293
294                 if (trace.plane.normal[2] > 0.7)
295                 {
296                         blocked |= 1;           // floor
297                         if (trace.ent->v.solid == SOLID_BSP)
298                         {
299                                 ent->v.flags =  (int)ent->v.flags | FL_ONGROUND;
300                                 ent->v.groundentity = EDICT_TO_PROG(trace.ent);
301                         }
302                 }
303                 if (!trace.plane.normal[2])
304                 {
305                         blocked |= 2;           // step
306                         if (steptrace)
307                                 *steptrace = trace;     // save for player extrafriction
308                 }
309
310 //
311 // run the impact function
312 //
313                 SV_Impact (ent, trace.ent);
314                 if (ent->free)
315                         break;          // removed by the impact function
316
317                 
318                 time_left -= time_left * trace.fraction;
319                 
320         // cliped to another plane
321                 if (numplanes >= MAX_CLIP_PLANES)
322                 {       // this shouldn't really happen
323                         VectorClear(ent->v.velocity);
324                         return 3;
325                 }
326
327                 VectorCopy (trace.plane.normal, planes[numplanes]);
328                 numplanes++;
329
330 //
331 // modify original_velocity so it parallels all of the clip planes
332 //
333                 for (i=0 ; i<numplanes ; i++)
334                 {
335                         ClipVelocity (original_velocity, planes[i], new_velocity, 1);
336                         for (j=0 ; j<numplanes ; j++)
337                                 if (j != i)
338                                 {
339                                         if (DotProduct (new_velocity, planes[j]) < 0)
340                                                 break;  // not ok
341                                 }
342                         if (j == numplanes)
343                                 break;
344                 }
345                 
346                 if (i != numplanes)
347                 {       // go along this plane
348                         VectorCopy (new_velocity, ent->v.velocity);
349                 }
350                 else
351                 {       // go along the crease
352                         if (numplanes != 2)
353                         {
354 //                              Con_Printf ("clip velocity, numplanes == %i\n",numplanes);
355                                 VectorClear(ent->v.velocity);
356                                 return 7;
357                         }
358                         CrossProduct (planes[0], planes[1], dir);
359                         // LordHavoc: thanks to taniwha of QuakeForge for pointing out this fix for slowed falling in corners
360                         VectorNormalize(dir);
361                         d = DotProduct (dir, ent->v.velocity);
362                         VectorScale (dir, d, ent->v.velocity);
363                 }
364
365 //
366 // if original velocity is against the original velocity, stop dead
367 // to avoid tiny occilations in sloping corners
368 //
369                 if (DotProduct (ent->v.velocity, primal_velocity) <= 0)
370                 {
371                         VectorClear(ent->v.velocity);
372                         return blocked;
373                 }
374         }
375
376         return blocked;
377 }
378
379
380 /*
381 ============
382 SV_AddGravity
383
384 ============
385 */
386 void SV_AddGravity (edict_t *ent)
387 {
388         float   ent_gravity;
389
390         eval_t  *val;
391
392         val = GETEDICTFIELDVALUE(ent, eval_gravity);
393         if (val!=0 && val->_float)
394                 ent_gravity = val->_float;
395         else
396                 ent_gravity = 1.0;
397         ent->v.velocity[2] -= ent_gravity * sv_gravity.value * sv.frametime;
398 }
399
400
401 /*
402 ===============================================================================
403
404 PUSHMOVE
405
406 ===============================================================================
407 */
408
409 /*
410 ============
411 SV_PushEntity
412
413 Does not change the entities velocity at all
414 ============
415 */
416 trace_t SV_PushEntity (edict_t *ent, vec3_t push)
417 {
418         trace_t trace;
419         vec3_t  end;
420                 
421         VectorAdd (ent->v.origin, push, end);
422
423         if (ent->v.movetype == MOVETYPE_FLYMISSILE)
424                 trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_MISSILE, ent);
425         else if (ent->v.solid == SOLID_TRIGGER || ent->v.solid == SOLID_NOT)
426         // only clip against bmodels
427                 trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NOMONSTERS, ent);
428         else
429                 trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NORMAL, ent);       
430         
431         VectorCopy (trace.endpos, ent->v.origin);
432         SV_LinkEdict (ent, true);
433
434         if (trace.ent)
435                 SV_Impact (ent, trace.ent);             
436
437         return trace;
438 }                                       
439
440
441 /*
442 ============
443 SV_PushMove
444
445 ============
446 */
447 void SV_PushMove (edict_t *pusher, float movetime)
448 {
449         int                     i, e;
450         edict_t         *check;
451         vec3_t          mins, maxs, move;
452         vec3_t          entorig, pushorig;
453         int                     num_moved;
454         edict_t         *moved_edict[MAX_EDICTS];
455         vec3_t          moved_from[MAX_EDICTS];
456         float           savesolid;
457
458         switch ((int) pusher->v.solid)
459         {
460         // LordHavoc: valid pusher types
461         case SOLID_BSP:
462         case SOLID_BBOX:
463         case SOLID_SLIDEBOX:
464         case SOLID_CORPSE: // LordHavoc: this would be weird...
465                 break;
466         // LordHavoc: no collisions
467         case SOLID_NOT:
468         case SOLID_TRIGGER:
469                 VectorMA (pusher->v.origin, movetime, pusher->v.velocity, pusher->v.origin);
470                 pusher->v.ltime += movetime;
471                 SV_LinkEdict (pusher, false);
472                 return;
473         default:
474                 Host_Error("SV_PushMove: unrecognized solid type %f\n", pusher->v.solid);
475         }
476         if (!pusher->v.velocity[0] && !pusher->v.velocity[1] && !pusher->v.velocity[2])
477         {
478                 pusher->v.ltime += movetime;
479                 return;
480         }
481
482         for (i=0 ; i<3 ; i++)
483         {
484                 move[i] = pusher->v.velocity[i] * movetime;
485                 mins[i] = pusher->v.absmin[i] + move[i];
486                 maxs[i] = pusher->v.absmax[i] + move[i];
487         }
488
489         VectorCopy (pusher->v.origin, pushorig);
490         
491 // move the pusher to it's final position
492
493         VectorAdd (pusher->v.origin, move, pusher->v.origin);
494         pusher->v.ltime += movetime;
495         SV_LinkEdict (pusher, false);
496
497
498 // see if any solid entities are inside the final position
499         num_moved = 0;
500         check = NEXT_EDICT(sv.edicts);
501         for (e = 1;e < sv.num_edicts;e++, check = NEXT_EDICT(check))
502         {
503                 if (check->free)
504                         continue;
505                 if (check->v.movetype == MOVETYPE_PUSH
506                  || check->v.movetype == MOVETYPE_NONE
507                  || check->v.movetype == MOVETYPE_FOLLOW
508                  || check->v.movetype == MOVETYPE_NOCLIP)
509                         continue;
510
511                 // if the entity is standing on the pusher, it will definitely be moved
512                 if (!(((int)check->v.flags & FL_ONGROUND) && PROG_TO_EDICT(check->v.groundentity) == pusher))
513                 {
514                         if (check->v.absmin[0] >= maxs[0]
515                          || check->v.absmin[1] >= maxs[1]
516                          || check->v.absmin[2] >= maxs[2]
517                          || check->v.absmax[0] <= mins[0]
518                          || check->v.absmax[1] <= mins[1]
519                          || check->v.absmax[2] <= mins[2])
520                                 continue;
521
522                         // see if the ent's bbox is inside the pusher's final position
523                         if (!SV_TestEntityPosition (check))
524                                 continue;
525                 }
526
527                 // remove the onground flag for non-players
528                 if (check->v.movetype != MOVETYPE_WALK)
529                         check->v.flags = (int)check->v.flags & ~FL_ONGROUND;
530                 
531                 VectorCopy (check->v.origin, entorig);
532                 VectorCopy (check->v.origin, moved_from[num_moved]);
533                 moved_edict[num_moved] = check;
534                 num_moved++;
535
536                 // LordHavoc: pusher fixes (teleport train bug, etc)
537                 savesolid = pusher->v.solid;
538                 if (savesolid == SOLID_BSP || savesolid == SOLID_BBOX || savesolid == SOLID_SLIDEBOX)
539                 {
540                         // try moving the contacted entity
541                         pusher->v.solid = SOLID_NOT;
542                         SV_PushEntity (check, move);
543                         pusher->v.solid = savesolid; // was SOLID_BSP
544
545                         // if it is still inside the pusher, block
546                         if (SV_TestEntityPosition (check))
547                         {       // fail the move
548                                 if (check->v.mins[0] == check->v.maxs[0])
549                                         continue;
550                                 if (check->v.solid == SOLID_NOT || check->v.solid == SOLID_TRIGGER)
551                                 {       // corpse
552                                         check->v.mins[0] = check->v.mins[1] = 0;
553                                         VectorCopy (check->v.mins, check->v.maxs);
554                                         continue;
555                                 }
556                                 
557                                 VectorCopy (entorig, check->v.origin);
558                                 SV_LinkEdict (check, true);
559
560                                 VectorCopy (pushorig, pusher->v.origin);
561                                 SV_LinkEdict (pusher, false);
562                                 pusher->v.ltime -= movetime;
563
564                                 // if the pusher has a "blocked" function, call it, otherwise just stay in place until the obstacle is gone
565                                 if (pusher->v.blocked)
566                                 {
567                                         pr_global_struct->self = EDICT_TO_PROG(pusher);
568                                         pr_global_struct->other = EDICT_TO_PROG(check);
569                                         PR_ExecuteProgram (pusher->v.blocked, "");
570                                 }
571                                 
572                                 // move back any entities we already moved
573                                 num_moved--; // LordHavoc: pop off check, because it was already restored
574                                 for (i=0 ; i<num_moved ; i++)
575                                 {
576                                         VectorCopy (moved_from[i], moved_edict[i]->v.origin);
577                                         SV_LinkEdict (moved_edict[i], false);
578                                 }
579                                 return;
580                         }       
581                 }
582         }
583
584         
585 }
586
587 /*
588 ============
589 SV_PushRotate
590
591 ============
592 */
593 void SV_PushRotate (edict_t *pusher, float movetime)
594 {
595         int                     i, e;
596         edict_t         *check;
597         vec3_t          move, a, amove;
598         vec3_t          entorigin, entangles, pushorigin, pushangles;
599         int                     num_moved;
600         edict_t         *moved_edict[MAX_EDICTS];
601         vec3_t          moved_from[MAX_EDICTS];
602         vec3_t          angled_from[MAX_EDICTS];
603         vec3_t          org, org2;
604         vec3_t          forward, right, up;
605         float           savesolid;
606
607         switch ((int) pusher->v.solid)
608         {
609         // LordHavoc: valid pusher types
610         case SOLID_BSP:
611         case SOLID_BBOX:
612         case SOLID_SLIDEBOX:
613         case SOLID_CORPSE: // LordHavoc: this would be weird...
614                 break;
615         // LordHavoc: no collisions
616         case SOLID_NOT:
617         case SOLID_TRIGGER:
618                 VectorMA (pusher->v.angles, movetime, pusher->v.avelocity, pusher->v.angles);
619                 pusher->v.ltime += movetime;
620                 SV_LinkEdict (pusher, false);
621                 return;
622         default:
623                 Host_Error("SV_PushRotate: unrecognized solid type %f\n", pusher->v.solid);
624         }
625         if (!pusher->v.avelocity[0] && !pusher->v.avelocity[1] && !pusher->v.avelocity[2])
626         {
627                 pusher->v.ltime += movetime;
628                 return;
629         }
630
631         for (i=0 ; i<3 ; i++)
632                 amove[i] = pusher->v.avelocity[i] * movetime;
633
634         VectorNegate (amove, a);
635         AngleVectors (a, forward, right, up);
636
637         VectorCopy (pusher->v.origin, pushorigin);
638         VectorCopy (pusher->v.angles, pushangles);
639         
640 // move the pusher to it's final position
641
642         VectorAdd (pusher->v.angles, amove, pusher->v.angles);
643         pusher->v.ltime += movetime;
644         SV_LinkEdict (pusher, false);
645
646
647 // see if any solid entities are inside the final position
648         num_moved = 0;
649         check = NEXT_EDICT(sv.edicts);
650         for (e=1 ; e<sv.num_edicts ; e++, check = NEXT_EDICT(check))
651         {
652                 if (check->free)
653                         continue;
654                 if (check->v.movetype == MOVETYPE_PUSH
655                  || check->v.movetype == MOVETYPE_NONE
656                  || check->v.movetype == MOVETYPE_FOLLOW
657                  || check->v.movetype == MOVETYPE_NOCLIP)
658                         continue;
659
660         // if the entity is standing on the pusher, it will definately be moved
661                 if (!(((int)check->v.flags & FL_ONGROUND) && PROG_TO_EDICT(check->v.groundentity) == pusher))
662                 {
663                         if (check->v.absmin[0] >= pusher->v.absmax[0]
664                          || check->v.absmin[1] >= pusher->v.absmax[1]
665                          || check->v.absmin[2] >= pusher->v.absmax[2]
666                          || check->v.absmax[0] <= pusher->v.absmin[0]
667                          || check->v.absmax[1] <= pusher->v.absmin[1]
668                          || check->v.absmax[2] <= pusher->v.absmin[2])
669                                 continue;
670
671                 // see if the ent's bbox is inside the pusher's final position
672                         if (!SV_TestEntityPosition (check))
673                                 continue;
674                 }
675
676         // remove the onground flag for non-players
677                 if (check->v.movetype != MOVETYPE_WALK)
678                         check->v.flags = (int)check->v.flags & ~FL_ONGROUND;
679                 
680                 VectorCopy (check->v.origin, entorigin);
681                 VectorCopy (check->v.origin, moved_from[num_moved]);
682                 VectorCopy (check->v.angles, entangles);
683                 VectorCopy (check->v.angles, angled_from[num_moved]);
684                 moved_edict[num_moved] = check;
685                 num_moved++;
686
687                 // calculate destination position
688                 VectorSubtract (check->v.origin, pusher->v.origin, org);
689                 org2[0] = DotProduct (org, forward);
690                 org2[1] = -DotProduct (org, right);
691                 org2[2] = DotProduct (org, up);
692                 VectorSubtract (org2, org, move);
693
694                 // try moving the contacted entity 
695                 savesolid = pusher->v.solid; // LordHavoc: restore to correct solid type
696                 pusher->v.solid = SOLID_NOT;
697                 SV_PushEntity (check, move);
698                 pusher->v.solid = savesolid; // LordHavoc: restore to correct solid type
699
700                 VectorAdd (check->v.angles, amove, check->v.angles);
701
702         // if it is still inside the pusher, block
703                 if (SV_TestEntityPosition (check))
704                 {       // fail the move
705                         if (check->v.mins[0] == check->v.maxs[0])
706                                 continue;
707                         if (check->v.solid == SOLID_NOT || check->v.solid == SOLID_TRIGGER)
708                         {       // corpse
709                                 check->v.mins[0] = check->v.mins[1] = 0;
710                                 VectorCopy (check->v.mins, check->v.maxs);
711                                 continue;
712                         }
713                         
714                         VectorCopy (entorigin, check->v.origin);
715                         VectorCopy (entangles, check->v.angles);
716                         SV_LinkEdict (check, true);
717
718                         VectorCopy (pushorigin, pusher->v.origin);
719                         VectorCopy (pushangles, pusher->v.angles);
720                         SV_LinkEdict (pusher, false);
721                         pusher->v.ltime -= movetime;
722
723                         // if the pusher has a "blocked" function, call it, otherwise just stay in place until the obstacle is gone
724                         if (pusher->v.blocked)
725                         {
726                                 pr_global_struct->self = EDICT_TO_PROG(pusher);
727                                 pr_global_struct->other = EDICT_TO_PROG(check);
728                                 PR_ExecuteProgram (pusher->v.blocked, "");
729                         }
730                         
731                 // move back any entities we already moved
732                         num_moved--; // LordHavoc: pop off check, because it was already restored
733                         for (i=0 ; i<num_moved ; i++)
734                         {
735                                 VectorCopy (moved_from[i], moved_edict[i]->v.origin);
736                                 VectorCopy (angled_from[i], moved_edict[i]->v.angles);
737                                 SV_LinkEdict (moved_edict[i], false);
738                         }
739                         return;
740                 }
741         }
742 }
743
744 /*
745 ================
746 SV_Physics_Pusher
747
748 ================
749 */
750 void SV_Physics_Pusher (edict_t *ent)
751 {
752         float   thinktime;
753         float   oldltime;
754         float   movetime;
755
756         oldltime = ent->v.ltime;
757         
758         thinktime = ent->v.nextthink;
759         if (thinktime < ent->v.ltime + sv.frametime)
760         {
761                 movetime = thinktime - ent->v.ltime;
762                 if (movetime < 0)
763                         movetime = 0;
764         }
765         else
766                 movetime = sv.frametime;
767
768         if (movetime)
769         {
770                 if (ent->v.avelocity[0] || ent->v.avelocity[1] || ent->v.avelocity[2])
771                         SV_PushRotate (ent, movetime);
772                 else
773                         SV_PushMove (ent, movetime);    // advances ent->v.ltime if not blocked
774         }
775                 
776         if (thinktime > oldltime && thinktime <= ent->v.ltime)
777         {
778                 ent->v.nextthink = 0;
779                 pr_global_struct->time = sv.time;
780                 pr_global_struct->self = EDICT_TO_PROG(ent);
781                 pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
782                 PR_ExecuteProgram (ent->v.think, "NULL think function");
783                 if (ent->free)
784                         return;
785         }
786
787 }
788
789
790 /*
791 ===============================================================================
792
793 CLIENT MOVEMENT
794
795 ===============================================================================
796 */
797
798 /*
799 =============
800 SV_CheckStuck
801
802 This is a big hack to try and fix the rare case of getting stuck in the world
803 clipping hull.
804 =============
805 */
806 void SV_CheckStuck (edict_t *ent)
807 {
808         int             i, j;
809         int             z;
810         vec3_t  org;
811
812         if (!SV_TestEntityPosition(ent))
813         {
814                 VectorCopy (ent->v.origin, ent->v.oldorigin);
815                 return;
816         }
817
818         VectorCopy (ent->v.origin, org);
819         VectorCopy (ent->v.oldorigin, ent->v.origin);
820         if (!SV_TestEntityPosition(ent))
821         {
822                 Con_DPrintf ("Unstuck.\n");
823                 SV_LinkEdict (ent, true);
824                 return;
825         }
826         
827         for (z=0 ; z< 18 ; z++)
828                 for (i=-1 ; i <= 1 ; i++)
829                         for (j=-1 ; j <= 1 ; j++)
830                         {
831                                 ent->v.origin[0] = org[0] + i;
832                                 ent->v.origin[1] = org[1] + j;
833                                 ent->v.origin[2] = org[2] + z;
834                                 if (!SV_TestEntityPosition(ent))
835                                 {
836                                         Con_DPrintf ("Unstuck.\n");
837                                         SV_LinkEdict (ent, true);
838                                         return;
839                                 }
840                         }
841                         
842         VectorCopy (org, ent->v.origin);
843         Con_DPrintf ("player is stuck.\n");
844 }
845
846
847 /*
848 =============
849 SV_CheckWater
850 =============
851 */
852 qboolean SV_CheckWater (edict_t *ent)
853 {
854         vec3_t  point;
855         int             cont;
856
857         point[0] = ent->v.origin[0];
858         point[1] = ent->v.origin[1];
859         point[2] = ent->v.origin[2] + ent->v.mins[2] + 1;       
860         
861         ent->v.waterlevel = 0;
862         ent->v.watertype = CONTENTS_EMPTY;
863         cont = SV_PointContents (point);
864         if (cont <= CONTENTS_WATER)
865         {
866                 ent->v.watertype = cont;
867                 ent->v.waterlevel = 1;
868                 point[2] = ent->v.origin[2] + (ent->v.mins[2] + ent->v.maxs[2])*0.5;
869                 cont = SV_PointContents (point);
870                 if (cont <= CONTENTS_WATER)
871                 {
872                         ent->v.waterlevel = 2;
873                         point[2] = ent->v.origin[2] + ent->v.view_ofs[2];
874                         cont = SV_PointContents (point);
875                         if (cont <= CONTENTS_WATER)
876                                 ent->v.waterlevel = 3;
877                 }
878         }
879         
880         return ent->v.waterlevel > 1;
881 }
882
883 /*
884 ============
885 SV_WallFriction
886
887 ============
888 */
889 void SV_WallFriction (edict_t *ent, trace_t *trace)
890 {
891         vec3_t          forward;
892         float           d, i;
893         vec3_t          into, side;
894         
895         AngleVectors (ent->v.v_angle, forward, NULL, NULL);
896         d = DotProduct (trace->plane.normal, forward);
897         
898         d += 0.5;
899         if (d >= 0)
900                 return;
901                 
902 // cut the tangential velocity
903         i = DotProduct (trace->plane.normal, ent->v.velocity);
904         VectorScale (trace->plane.normal, i, into);
905         VectorSubtract (ent->v.velocity, into, side);
906         
907         ent->v.velocity[0] = side[0] * (1 + d);
908         ent->v.velocity[1] = side[1] * (1 + d);
909 }
910
911 /*
912 =====================
913 SV_TryUnstick
914
915 Player has come to a dead stop, possibly due to the problem with limited
916 float precision at some angle joins in the BSP hull.
917
918 Try fixing by pushing one pixel in each direction.
919
920 This is a hack, but in the interest of good gameplay...
921 ======================
922 */
923 int SV_TryUnstick (edict_t *ent, vec3_t oldvel)
924 {
925         int             i;
926         vec3_t  oldorg;
927         vec3_t  dir;
928         int             clip;
929         trace_t steptrace;
930         
931         VectorCopy (ent->v.origin, oldorg);
932         VectorClear (dir);
933
934         for (i=0 ; i<8 ; i++)
935         {
936 // try pushing a little in an axial direction
937                 switch (i)
938                 {
939                         case 0: dir[0] = 2; dir[1] = 0; break;
940                         case 1: dir[0] = 0; dir[1] = 2; break;
941                         case 2: dir[0] = -2; dir[1] = 0; break;
942                         case 3: dir[0] = 0; dir[1] = -2; break;
943                         case 4: dir[0] = 2; dir[1] = 2; break;
944                         case 5: dir[0] = -2; dir[1] = 2; break;
945                         case 6: dir[0] = 2; dir[1] = -2; break;
946                         case 7: dir[0] = -2; dir[1] = -2; break;
947                 }
948                 
949                 SV_PushEntity (ent, dir);
950
951 // retry the original move
952                 ent->v.velocity[0] = oldvel[0];
953                 ent->v.velocity[1] = oldvel[1];
954                 ent->v.velocity[2] = 0;
955                 clip = SV_FlyMove (ent, 0.1, &steptrace);
956
957                 if ( fabs(oldorg[1] - ent->v.origin[1]) > 4
958                 || fabs(oldorg[0] - ent->v.origin[0]) > 4 )
959                 {
960 //Con_DPrintf ("unstuck!\n");
961                         return clip;
962                 }
963                         
964 // go back to the original pos and try again
965                 VectorCopy (oldorg, ent->v.origin);
966         }
967         
968         VectorClear (ent->v.velocity);
969         return 7;               // still not moving
970 }
971
972 /*
973 =====================
974 SV_WalkMove
975
976 Only used by players
977 ======================
978 */
979 #define STEPSIZE        18
980 void SV_WalkMove (edict_t *ent)
981 {
982         vec3_t          upmove, downmove;
983         vec3_t          oldorg, oldvel;
984         vec3_t          nosteporg, nostepvel;
985         int                     clip;
986         int                     oldonground;
987         trace_t         steptrace, downtrace;
988         
989 //
990 // do a regular slide move unless it looks like you ran into a step
991 //
992         oldonground = (int)ent->v.flags & FL_ONGROUND;
993         ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;
994         
995         VectorCopy (ent->v.origin, oldorg);
996         VectorCopy (ent->v.velocity, oldvel);
997         
998         clip = SV_FlyMove (ent, sv.frametime, &steptrace);
999
1000         if ( !(clip & 2) )
1001                 return;         // move didn't block on a step
1002
1003         if (!oldonground && ent->v.waterlevel == 0)
1004                 return;         // don't stair up while jumping
1005         
1006         if (ent->v.movetype != MOVETYPE_WALK)
1007                 return;         // gibbed by a trigger
1008         
1009         if (sv_nostep.integer)
1010                 return;
1011         
1012         if ( (int)sv_player->v.flags & FL_WATERJUMP )
1013                 return;
1014
1015         VectorCopy (ent->v.origin, nosteporg);
1016         VectorCopy (ent->v.velocity, nostepvel);
1017
1018 //
1019 // try moving up and forward to go up a step
1020 //
1021         VectorCopy (oldorg, ent->v.origin);     // back to start pos
1022
1023         VectorClear (upmove);
1024         VectorClear (downmove);
1025         upmove[2] = STEPSIZE;
1026         downmove[2] = -STEPSIZE + oldvel[2]*sv.frametime;
1027
1028 // move up
1029         SV_PushEntity (ent, upmove);    // FIXME: don't link?
1030
1031 // move forward
1032         ent->v.velocity[0] = oldvel[0];
1033         ent->v. velocity[1] = oldvel[1];
1034         ent->v. velocity[2] = 0;
1035         clip = SV_FlyMove (ent, sv.frametime, &steptrace);
1036
1037 // check for stuckness, possibly due to the limited precision of floats
1038 // in the clipping hulls
1039         if (clip)
1040         {
1041                 if ( fabs(oldorg[1] - ent->v.origin[1]) < 0.03125
1042                 && fabs(oldorg[0] - ent->v.origin[0]) < 0.03125 )
1043                 {       // stepping up didn't make any progress
1044                         clip = SV_TryUnstick (ent, oldvel);
1045                 }
1046         }
1047         
1048 // extra friction based on view angle
1049         if ( clip & 2 )
1050                 SV_WallFriction (ent, &steptrace);
1051
1052 // move down
1053         downtrace = SV_PushEntity (ent, downmove);      // FIXME: don't link?
1054
1055         if (downtrace.plane.normal[2] > 0.7)
1056         {
1057                 if (ent->v.solid == SOLID_BSP)
1058                 {
1059                         ent->v.flags =  (int)ent->v.flags | FL_ONGROUND;
1060                         ent->v.groundentity = EDICT_TO_PROG(downtrace.ent);
1061                 }
1062         }
1063         else
1064         {
1065 // if the push down didn't end up on good ground, use the move without
1066 // the step up.  This happens near wall / slope combinations, and can
1067 // cause the player to hop up higher on a slope too steep to climb      
1068                 VectorCopy (nosteporg, ent->v.origin);
1069                 VectorCopy (nostepvel, ent->v.velocity);
1070         }
1071 }
1072
1073
1074 /*
1075 ================
1076 SV_Physics_Client
1077
1078 Player character actions
1079 ================
1080 */
1081 void SV_Physics_Client (edict_t *ent, int num)
1082 {
1083         if ( ! svs.clients[num-1].active )
1084                 return;         // unconnected slot
1085
1086 //
1087 // call standard client pre-think
1088 //      
1089         pr_global_struct->time = sv.time;
1090         pr_global_struct->self = EDICT_TO_PROG(ent);
1091         PR_ExecuteProgram (pr_global_struct->PlayerPreThink, "QC function PlayerPreThink is missing");
1092         
1093 //
1094 // do a move
1095 //
1096         SV_CheckVelocity (ent);
1097
1098 //
1099 // decide which move function to call
1100 //
1101         switch ((int)ent->v.movetype)
1102         {
1103         case MOVETYPE_NONE:
1104                 if (!SV_RunThink (ent))
1105                         return;
1106                 break;
1107
1108         case MOVETYPE_WALK:
1109                 if (!SV_RunThink (ent))
1110                         return;
1111                 if (!SV_CheckWater (ent) && ! ((int)ent->v.flags & FL_WATERJUMP) )
1112                         SV_AddGravity (ent);
1113                 SV_CheckStuck (ent);
1114                 SV_WalkMove (ent);
1115                 break;
1116                 
1117         case MOVETYPE_TOSS:
1118         case MOVETYPE_BOUNCE:
1119                 SV_Physics_Toss (ent);
1120                 break;
1121
1122         case MOVETYPE_FLY:
1123                 if (!SV_RunThink (ent))
1124                         return;
1125                 SV_CheckWater (ent);
1126                 SV_FlyMove (ent, sv.frametime, NULL);
1127                 break;
1128                 
1129         case MOVETYPE_NOCLIP:
1130                 if (!SV_RunThink (ent))
1131                         return;
1132                 SV_CheckWater (ent);
1133                 VectorMA (ent->v.origin, sv.frametime, ent->v.velocity, ent->v.origin);
1134                 break;
1135                 
1136         default:
1137                 Host_Error ("SV_Physics_client: bad movetype %i", (int)ent->v.movetype);
1138         }
1139
1140 //
1141 // call standard player post-think
1142 //              
1143         SV_LinkEdict (ent, true);
1144
1145         pr_global_struct->time = sv.time;
1146         pr_global_struct->self = EDICT_TO_PROG(ent);
1147         PR_ExecuteProgram (pr_global_struct->PlayerPostThink, "QC function PlayerPostThink is missing");
1148 }
1149
1150 //============================================================================
1151
1152 /*
1153 =============
1154 SV_Physics_None
1155
1156 Non moving objects can only think
1157 =============
1158 */
1159 // LordHavoc: inlined manually because it was a real time waster
1160 /*
1161 void SV_Physics_None (edict_t *ent)
1162 {
1163 // regular thinking
1164         SV_RunThink (ent);
1165 }
1166 */
1167
1168 /*
1169 =============
1170 SV_Physics_Follow
1171
1172 Entities that are "stuck" to another entity
1173 =============
1174 */
1175 void SV_Physics_Follow (edict_t *ent)
1176 {
1177         vec3_t vf, vr, vu, angles, v;
1178         edict_t *e;
1179 // regular thinking
1180         if (!SV_RunThink (ent))
1181                 return;
1182         // LordHavoc: implemented rotation on MOVETYPE_FOLLOW objects
1183         e = PROG_TO_EDICT(ent->v.aiment);
1184         if (e->v.angles[0] == ent->v.punchangle[0] && e->v.angles[1] == ent->v.punchangle[1] && e->v.angles[2] == ent->v.punchangle[2])
1185         {
1186                 // quick case for no rotation
1187                 VectorAdd(e->v.origin, ent->v.view_ofs, ent->v.origin);
1188         }
1189         else
1190         {
1191                 angles[0] = -ent->v.punchangle[0];
1192                 angles[1] =  ent->v.punchangle[1];
1193                 angles[2] =  ent->v.punchangle[2];
1194                 AngleVectors (angles, vf, vr, vu);
1195                 v[0] = ent->v.view_ofs[0] * vf[0] + ent->v.view_ofs[1] * vr[0] + ent->v.view_ofs[2] * vu[0];
1196                 v[1] = ent->v.view_ofs[0] * vf[1] + ent->v.view_ofs[1] * vr[1] + ent->v.view_ofs[2] * vu[1];
1197                 v[2] = ent->v.view_ofs[0] * vf[2] + ent->v.view_ofs[1] * vr[2] + ent->v.view_ofs[2] * vu[2];
1198                 angles[0] = -e->v.angles[0];
1199                 angles[1] =  e->v.angles[1];
1200                 angles[2] =  e->v.angles[2];
1201                 AngleVectors (angles, vf, vr, vu);
1202                 ent->v.origin[0] = v[0] * vf[0] + v[1] * vf[1] + v[2] * vf[2] + e->v.origin[0];
1203                 ent->v.origin[1] = v[0] * vr[0] + v[1] * vr[1] + v[2] * vr[2] + e->v.origin[1];
1204                 ent->v.origin[2] = v[0] * vu[0] + v[1] * vu[1] + v[2] * vu[2] + e->v.origin[2];
1205                 /*
1206                 ent->v.origin[0] = ent->v.view_ofs[0] * vf[0] + ent->v.view_ofs[0] * vf[1] + ent->v.view_ofs[0] * vf[2] + e->v.origin[0];
1207                 ent->v.origin[1] = ent->v.view_ofs[1] * vr[0] + ent->v.view_ofs[1] * vr[1] + ent->v.view_ofs[1] * vr[2] + e->v.origin[1];
1208                 ent->v.origin[2] = ent->v.view_ofs[2] * vu[0] + ent->v.view_ofs[2] * vu[1] + ent->v.view_ofs[2] * vu[2] + e->v.origin[2];
1209                 */
1210         }
1211         VectorAdd (e->v.angles, ent->v.v_angle, ent->v.angles);
1212 //      VectorAdd (PROG_TO_EDICT(ent->v.aiment)->v.origin, ent->v.v_angle, ent->v.origin);
1213         SV_LinkEdict (ent, true);
1214 }
1215
1216 /*
1217 =============
1218 SV_Physics_Noclip
1219
1220 A moving object that doesn't obey physics
1221 =============
1222 */
1223 void SV_Physics_Noclip (edict_t *ent)
1224 {
1225 // regular thinking
1226         if (!SV_RunThink (ent))
1227                 return;
1228         
1229         VectorMA (ent->v.angles, sv.frametime, ent->v.avelocity, ent->v.angles);
1230         VectorMA (ent->v.origin, sv.frametime, ent->v.velocity, ent->v.origin);
1231
1232         SV_LinkEdict (ent, false);
1233 }
1234
1235 /*
1236 ==============================================================================
1237
1238 TOSS / BOUNCE
1239
1240 ==============================================================================
1241 */
1242
1243 /*
1244 =============
1245 SV_CheckWaterTransition
1246
1247 =============
1248 */
1249 void SV_CheckWaterTransition (edict_t *ent)
1250 {
1251         int             cont;
1252         cont = SV_PointContents (ent->v.origin);
1253         if (!ent->v.watertype)
1254         {       // just spawned here
1255                 ent->v.watertype = cont;
1256                 ent->v.waterlevel = 1;
1257                 return;
1258         }
1259         
1260         if (cont <= CONTENTS_WATER)
1261         {
1262                 if (ent->v.watertype == CONTENTS_EMPTY)
1263                 {       // just crossed into water
1264                         SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1);
1265                 }               
1266                 ent->v.watertype = cont;
1267                 ent->v.waterlevel = 1;
1268         }
1269         else
1270         {
1271                 if (ent->v.watertype != CONTENTS_EMPTY)
1272                 {       // just crossed into water
1273                         SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1);
1274                 }               
1275                 ent->v.watertype = CONTENTS_EMPTY;
1276                 ent->v.waterlevel = cont;
1277         }
1278 }
1279
1280 /*
1281 =============
1282 SV_Physics_Toss
1283
1284 Toss, bounce, and fly movement.  When onground, do nothing.
1285 =============
1286 */
1287 void SV_Physics_Toss (edict_t *ent)
1288 {
1289         trace_t trace;
1290         vec3_t  move;
1291         float   backoff;
1292         edict_t *groundentity;
1293         // regular thinking
1294         if (!SV_RunThink (ent))
1295                 return;
1296
1297 // if onground, return without moving
1298         if ( ((int)ent->v.flags & FL_ONGROUND) )
1299         {
1300                 // LordHavoc: fall if the groundentity was removed
1301                 if (ent->v.groundentity)
1302                 {
1303                         groundentity = PROG_TO_EDICT(ent->v.groundentity);
1304                         if (groundentity && groundentity->v.solid != SOLID_NOT && groundentity->v.solid != SOLID_TRIGGER)
1305                                 return;
1306                 }
1307         }
1308         ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;
1309
1310         SV_CheckVelocity (ent);
1311
1312 // add gravity
1313         if (ent->v.movetype != MOVETYPE_FLY
1314         && ent->v.movetype != MOVETYPE_BOUNCEMISSILE // LordHavoc: enabled MOVETYPE_BOUNCEMISSILE
1315         && ent->v.movetype != MOVETYPE_FLYMISSILE)
1316                 SV_AddGravity (ent);
1317
1318 // move angles
1319         VectorMA (ent->v.angles, sv.frametime, ent->v.avelocity, ent->v.angles);
1320
1321 // move origin
1322         VectorScale (ent->v.velocity, sv.frametime, move);
1323         trace = SV_PushEntity (ent, move);
1324         if (trace.fraction == 1)
1325                 return;
1326         if (ent->free)
1327                 return;
1328
1329         if (ent->v.movetype == MOVETYPE_BOUNCE)
1330                 backoff = 1.5;
1331         else if (ent->v.movetype == MOVETYPE_BOUNCEMISSILE)
1332                 backoff = 2.0;
1333         else
1334                 backoff = 1;
1335
1336         ClipVelocity (ent->v.velocity, trace.plane.normal, ent->v.velocity, backoff);
1337
1338 // stop if on ground
1339         if (trace.plane.normal[2] > 0.7)
1340         {
1341                 // LordHavoc: fixed grenades not bouncing when fired down a slope
1342                 if (fabs(ent->v.velocity[2]) < 60 || (ent->v.movetype != MOVETYPE_BOUNCE && ent->v.movetype != MOVETYPE_BOUNCEMISSILE))
1343                 //if (ent->v.velocity[2] < 60 || (ent->v.movetype != MOVETYPE_BOUNCE && ent->v.movetype != MOVETYPE_BOUNCEMISSILE))
1344                 {
1345                         ent->v.flags = (int)ent->v.flags | FL_ONGROUND;
1346                         ent->v.groundentity = EDICT_TO_PROG(trace.ent);
1347                         VectorClear (ent->v.velocity);
1348                         VectorClear (ent->v.avelocity);
1349                 }
1350                 else
1351                         ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;
1352         }
1353         else
1354                 ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;
1355
1356 // check for in water
1357         SV_CheckWaterTransition (ent);
1358 }
1359
1360 /*
1361 ===============================================================================
1362
1363 STEPPING MOVEMENT
1364
1365 ===============================================================================
1366 */
1367
1368 /*
1369 =============
1370 SV_Physics_Step
1371
1372 Monsters freefall when they don't have a ground entity, otherwise
1373 all movement is done with discrete steps.
1374
1375 This is also used for objects that have become still on the ground, but
1376 will fall if the floor is pulled out from under them.
1377 =============
1378 */
1379 void SV_Physics_Step (edict_t *ent)
1380 {
1381         qboolean        hitsound;
1382
1383 // freefall if not onground
1384         if ( ! ((int)ent->v.flags & (FL_ONGROUND | FL_FLY | FL_SWIM) ) )
1385         {
1386                 if (ent->v.velocity[2] < sv_gravity.value*-0.1)
1387                         hitsound = true;
1388                 else
1389                         hitsound = false;
1390
1391                 SV_AddGravity (ent);
1392                 SV_CheckVelocity (ent);
1393                 SV_FlyMove (ent, sv.frametime, NULL);
1394                 SV_LinkEdict (ent, true);
1395
1396                 if ( (int)ent->v.flags & FL_ONGROUND )  // just hit ground
1397                 {
1398                         if (hitsound)
1399                                 SV_StartSound (ent, 0, "demon/dland2.wav", 255, 1);
1400                 }
1401         }
1402
1403 // regular thinking
1404         SV_RunThink (ent);
1405         
1406         SV_CheckWaterTransition (ent);
1407 }
1408
1409 //============================================================================
1410
1411 /*
1412 ================
1413 SV_Physics
1414
1415 ================
1416 */
1417 void SV_Physics (void)
1418 {
1419         int             i;
1420         edict_t *ent;
1421
1422 // let the progs know that a new frame has started
1423         pr_global_struct->self = EDICT_TO_PROG(sv.edicts);
1424         pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
1425         pr_global_struct->time = sv.time;
1426         PR_ExecuteProgram (pr_global_struct->StartFrame, "QC function StartFrame is missing");
1427
1428 //SV_CheckAllEnts ();
1429
1430 //
1431 // treat each object in turn
1432 //
1433         ent = sv.edicts;
1434         for (i=0 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent))
1435         {
1436                 if (ent->free)
1437                         continue;
1438
1439                 if (pr_global_struct->force_retouch)
1440                         SV_LinkEdict (ent, true);       // force retouch even for stationary
1441
1442                 if (i > 0 && i <= svs.maxclients)
1443                 {
1444                         SV_Physics_Client (ent, i);
1445                         continue;
1446                 }
1447
1448                 switch ((int) ent->v.movetype)
1449                 {
1450                 case MOVETYPE_PUSH:
1451                         SV_Physics_Pusher (ent);
1452                         break;
1453                 case MOVETYPE_NONE:
1454 //                      SV_Physics_None (ent);
1455                         // LordHavoc: manually inlined the thinktime check here because MOVETYPE_NONE is used on so many objects
1456                         if (ent->v.nextthink > 0 && ent->v.nextthink <= sv.time + sv.frametime)
1457                                 SV_RunThink (ent);
1458                         break;
1459                 case MOVETYPE_FOLLOW:
1460                         SV_Physics_Follow (ent);
1461                         break;
1462                 case MOVETYPE_NOCLIP:
1463                         SV_Physics_Noclip (ent);
1464                         break;
1465                 case MOVETYPE_STEP:
1466                         SV_Physics_Step (ent);
1467                         break;
1468                 // LordHavoc: added support for MOVETYPE_WALK on normal entities! :)
1469                 case MOVETYPE_WALK:
1470                         if (SV_RunThink (ent))
1471                         {
1472                                 if (!SV_CheckWater (ent) && ! ((int)ent->v.flags & FL_WATERJUMP) )
1473                                         SV_AddGravity (ent);
1474                                 SV_CheckStuck (ent);
1475                                 SV_WalkMove (ent);
1476                                 SV_LinkEdict (ent, true);
1477                         }
1478                         break;
1479                 case MOVETYPE_TOSS:
1480                 case MOVETYPE_BOUNCE:
1481                 case MOVETYPE_BOUNCEMISSILE:
1482                 case MOVETYPE_FLY:
1483                 case MOVETYPE_FLYMISSILE:
1484                         SV_Physics_Toss (ent);
1485                         break;
1486                 default:
1487                         Host_Error ("SV_Physics: bad movetype %i", (int)ent->v.movetype);
1488                         break;
1489                 }
1490         }
1491         
1492         if (pr_global_struct->force_retouch)
1493                 pr_global_struct->force_retouch--;      
1494
1495         // LordHavoc: endframe support
1496         if (EndFrameQC)
1497         {
1498                 pr_global_struct->self = EDICT_TO_PROG(sv.edicts);
1499                 pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
1500                 pr_global_struct->time = sv.time;
1501                 PR_ExecuteProgram ((func_t)(EndFrameQC - pr_functions), "");
1502         }
1503
1504         sv.time += sv.frametime;
1505 }
1506
1507
1508 trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore)
1509 {
1510         int i;
1511         edict_t tempent, *tent;
1512         trace_t trace;
1513         vec3_t  move;
1514         vec3_t  end;
1515
1516         memcpy(&tempent, ent, sizeof(edict_t));
1517         tent = &tempent;
1518
1519         for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
1520         {
1521                 SV_CheckVelocity (tent);
1522                 SV_AddGravity (tent);
1523                 VectorMA (tent->v.angles, 0.05, tent->v.avelocity, tent->v.angles);
1524                 VectorScale (tent->v.velocity, 0.05, move);
1525                 VectorAdd (tent->v.origin, move, end);
1526                 trace = SV_Move (tent->v.origin, tent->v.mins, tent->v.maxs, end, MOVE_NORMAL, tent);   
1527                 VectorCopy (trace.endpos, tent->v.origin);
1528
1529                 if (trace.ent)
1530                         if (trace.ent != ignore)
1531                                 break;
1532         }
1533         trace.fraction = 0; // not relevant
1534         return trace;
1535 }