]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - sv_phys.c
removed unused tracercount
[xonotic/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 = {"sv_friction","4",false,true};
43 cvar_t  sv_stopspeed = {"sv_stopspeed","100"};
44 cvar_t  sv_gravity = {"sv_gravity","800",false,true};
45 cvar_t  sv_maxvelocity = {"sv_maxvelocity","2000"};
46 cvar_t  sv_nostep = {"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 + host_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);
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 #define MAX_CLIP_PLANES 5
238 int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace)
239 {
240         int                     bumpcount, numbumps;
241         vec3_t          dir;
242         float           d;
243         int                     numplanes;
244         vec3_t          planes[MAX_CLIP_PLANES];
245         vec3_t          primal_velocity, original_velocity, new_velocity;
246         int                     i, j;
247         trace_t         trace;
248         vec3_t          end;
249         float           time_left;
250         int                     blocked;
251         
252         numbumps = 4;
253         
254         blocked = 0;
255         VectorCopy (ent->v.velocity, original_velocity);
256         VectorCopy (ent->v.velocity, primal_velocity);
257         numplanes = 0;
258         
259         time_left = time;
260
261         for (bumpcount=0 ; bumpcount<numbumps ; bumpcount++)
262         {
263                 if (!ent->v.velocity[0] && !ent->v.velocity[1] && !ent->v.velocity[2])
264                         break;
265
266                 for (i=0 ; i<3 ; i++)
267                         end[i] = ent->v.origin[i] + time_left * ent->v.velocity[i];
268
269                 trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, false, ent);
270
271                 if (trace.allsolid)
272                 {       // entity is trapped in another solid
273                         VectorCopy (vec3_origin, ent->v.velocity);
274                         return 3;
275                 }
276
277                 if (trace.fraction > 0)
278                 {       // actually covered some distance
279                         VectorCopy (trace.endpos, ent->v.origin);
280                         VectorCopy (ent->v.velocity, original_velocity);
281                         numplanes = 0;
282                 }
283
284                 if (trace.fraction == 1)
285                          break;         // moved the entire distance
286
287                 if (!trace.ent)
288                         Host_Error ("SV_FlyMove: !trace.ent");
289
290                 if (trace.plane.normal[2] > 0.7)
291                 {
292                         blocked |= 1;           // floor
293                         if (trace.ent->v.solid == SOLID_BSP)
294                         {
295                                 ent->v.flags =  (int)ent->v.flags | FL_ONGROUND;
296                                 ent->v.groundentity = EDICT_TO_PROG(trace.ent);
297                         }
298                 }
299                 if (!trace.plane.normal[2])
300                 {
301                         blocked |= 2;           // step
302                         if (steptrace)
303                                 *steptrace = trace;     // save for player extrafriction
304                 }
305
306 //
307 // run the impact function
308 //
309                 SV_Impact (ent, trace.ent);
310                 if (ent->free)
311                         break;          // removed by the impact function
312
313                 
314                 time_left -= time_left * trace.fraction;
315                 
316         // cliped to another plane
317                 if (numplanes >= MAX_CLIP_PLANES)
318                 {       // this shouldn't really happen
319                         VectorCopy (vec3_origin, ent->v.velocity);
320                         return 3;
321                 }
322
323                 VectorCopy (trace.plane.normal, planes[numplanes]);
324                 numplanes++;
325
326 //
327 // modify original_velocity so it parallels all of the clip planes
328 //
329                 for (i=0 ; i<numplanes ; i++)
330                 {
331                         ClipVelocity (original_velocity, planes[i], new_velocity, 1);
332                         for (j=0 ; j<numplanes ; j++)
333                                 if (j != i)
334                                 {
335                                         if (DotProduct (new_velocity, planes[j]) < 0)
336                                                 break;  // not ok
337                                 }
338                         if (j == numplanes)
339                                 break;
340                 }
341                 
342                 if (i != numplanes)
343                 {       // go along this plane
344                         VectorCopy (new_velocity, ent->v.velocity);
345                 }
346                 else
347                 {       // go along the crease
348                         if (numplanes != 2)
349                         {
350 //                              Con_Printf ("clip velocity, numplanes == %i\n",numplanes);
351                                 VectorCopy (vec3_origin, ent->v.velocity);
352                                 return 7;
353                         }
354                         CrossProduct (planes[0], planes[1], dir);
355                         d = DotProduct (dir, ent->v.velocity);
356                         VectorScale (dir, d, ent->v.velocity);
357                 }
358
359 //
360 // if original velocity is against the original velocity, stop dead
361 // to avoid tiny occilations in sloping corners
362 //
363                 if (DotProduct (ent->v.velocity, primal_velocity) <= 0)
364                 {
365                         VectorCopy (vec3_origin, ent->v.velocity);
366                         return blocked;
367                 }
368         }
369
370         return blocked;
371 }
372
373
374 /*
375 ============
376 SV_AddGravity
377
378 ============
379 */
380 void SV_AddGravity (edict_t *ent)
381 {
382         float   ent_gravity;
383
384         eval_t  *val;
385
386         val = GETEDICTFIELDVALUE(ent, eval_gravity);
387         if (val!=0 && val->_float)
388                 ent_gravity = val->_float;
389         else
390                 ent_gravity = 1.0;
391         ent->v.velocity[2] -= ent_gravity * sv_gravity.value * host_frametime;
392 }
393
394
395 /*
396 ===============================================================================
397
398 PUSHMOVE
399
400 ===============================================================================
401 */
402
403 /*
404 ============
405 SV_PushEntity
406
407 Does not change the entities velocity at all
408 ============
409 */
410 trace_t SV_PushEntity (edict_t *ent, vec3_t push)
411 {
412         trace_t trace;
413         vec3_t  end;
414                 
415         VectorAdd (ent->v.origin, push, end);
416
417         if (ent->v.movetype == MOVETYPE_FLYMISSILE)
418                 trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_MISSILE, ent);
419         else if (ent->v.solid == SOLID_TRIGGER || ent->v.solid == SOLID_NOT)
420         // only clip against bmodels
421                 trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NOMONSTERS, ent);
422         else
423                 trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NORMAL, ent);       
424         
425         VectorCopy (trace.endpos, ent->v.origin);
426         SV_LinkEdict (ent, true);
427
428         if (trace.ent)
429                 SV_Impact (ent, trace.ent);             
430
431         return trace;
432 }                                       
433
434
435 /*
436 ============
437 SV_PushMove
438
439 ============
440 */
441 void SV_PushMove (edict_t *pusher, float movetime)
442 {
443         int                     i, e;
444         edict_t         *check;
445         vec3_t          mins, maxs, move;
446         vec3_t          entorig, pushorig;
447         int                     num_moved;
448         edict_t         *moved_edict[MAX_EDICTS];
449         vec3_t          moved_from[MAX_EDICTS];
450         float           savesolid;
451
452         if (!pusher->v.velocity[0] && !pusher->v.velocity[1] && !pusher->v.velocity[2])
453         {
454                 pusher->v.ltime += movetime;
455                 return;
456         }
457
458         for (i=0 ; i<3 ; i++)
459         {
460                 move[i] = pusher->v.velocity[i] * movetime;
461                 mins[i] = pusher->v.absmin[i] + move[i];
462                 maxs[i] = pusher->v.absmax[i] + move[i];
463         }
464
465         VectorCopy (pusher->v.origin, pushorig);
466         
467 // move the pusher to it's final position
468
469         VectorAdd (pusher->v.origin, move, pusher->v.origin);
470         pusher->v.ltime += movetime;
471         SV_LinkEdict (pusher, false);
472
473
474 // see if any solid entities are inside the final position
475         num_moved = 0;
476         check = NEXT_EDICT(sv.edicts);
477         for (e = 1;e < sv.num_edicts;e++, check = NEXT_EDICT(check))
478         {
479                 if (check->free)
480                         continue;
481                 if (check->v.movetype == MOVETYPE_PUSH
482                  || check->v.movetype == MOVETYPE_NONE
483                  || check->v.movetype == MOVETYPE_FOLLOW
484                  || check->v.movetype == MOVETYPE_NOCLIP)
485                         continue;
486
487                 // if the entity is standing on the pusher, it will definitely be moved
488                 if (!(((int)check->v.flags & FL_ONGROUND) && PROG_TO_EDICT(check->v.groundentity) == pusher))
489                 {
490                         if (check->v.absmin[0] >= maxs[0]
491                          || check->v.absmin[1] >= maxs[1]
492                          || check->v.absmin[2] >= maxs[2]
493                          || check->v.absmax[0] <= mins[0]
494                          || check->v.absmax[1] <= mins[1]
495                          || check->v.absmax[2] <= mins[2])
496                                 continue;
497
498                         // see if the ent's bbox is inside the pusher's final position
499                         if (!SV_TestEntityPosition (check))
500                                 continue;
501                 }
502
503                 // remove the onground flag for non-players
504                 if (check->v.movetype != MOVETYPE_WALK)
505                         check->v.flags = (int)check->v.flags & ~FL_ONGROUND;
506                 
507                 VectorCopy (check->v.origin, entorig);
508                 VectorCopy (check->v.origin, moved_from[num_moved]);
509                 moved_edict[num_moved] = check;
510                 num_moved++;
511
512                 // LordHavoc: pusher fixes (teleport train bug, etc)
513                 savesolid = pusher->v.solid;
514                 if (savesolid == SOLID_BSP || savesolid == SOLID_BBOX || savesolid == SOLID_SLIDEBOX)
515                 {
516                         // try moving the contacted entity
517                         pusher->v.solid = SOLID_NOT;
518                         SV_PushEntity (check, move);
519                         pusher->v.solid = savesolid; // was SOLID_BSP
520
521                         // if it is still inside the pusher, block
522                         if (SV_TestEntityPosition (check))
523                         {       // fail the move
524                                 if (check->v.mins[0] == check->v.maxs[0])
525                                         continue;
526                                 if (check->v.solid == SOLID_NOT || check->v.solid == SOLID_TRIGGER)
527                                 {       // corpse
528                                         check->v.mins[0] = check->v.mins[1] = 0;
529                                         VectorCopy (check->v.mins, check->v.maxs);
530                                         continue;
531                                 }
532                                 
533                                 VectorCopy (entorig, check->v.origin);
534                                 SV_LinkEdict (check, true);
535
536                                 VectorCopy (pushorig, pusher->v.origin);
537                                 SV_LinkEdict (pusher, false);
538                                 pusher->v.ltime -= movetime;
539
540                                 // if the pusher has a "blocked" function, call it
541                                 // otherwise, just stay in place until the obstacle is gone
542                                 if (pusher->v.blocked)
543                                 {
544                                         pr_global_struct->self = EDICT_TO_PROG(pusher);
545                                         pr_global_struct->other = EDICT_TO_PROG(check);
546                                         PR_ExecuteProgram (pusher->v.blocked);
547                                 }
548                                 
549                                 // move back any entities we already moved
550                                 for (i=0 ; i<num_moved ; i++)
551                                 {
552                                         VectorCopy (moved_from[i], moved_edict[i]->v.origin);
553                                         SV_LinkEdict (moved_edict[i], false);
554                                 }
555                                 return;
556                         }       
557                 }
558         }
559
560         
561 }
562
563 /*
564 ============
565 SV_PushRotate
566
567 ============
568 */
569 void SV_PushRotate (edict_t *pusher, float movetime)
570 {
571         int                     i, e;
572         edict_t         *check;
573         vec3_t          move, a, amove;
574         vec3_t          entorig, pushorig;
575         int                     num_moved;
576         edict_t         *moved_edict[MAX_EDICTS];
577         vec3_t          moved_from[MAX_EDICTS];
578         vec3_t          org, org2;
579         vec3_t          forward, right, up;
580         float           savesolid;
581
582         if (!pusher->v.avelocity[0] && !pusher->v.avelocity[1] && !pusher->v.avelocity[2])
583         {
584                 pusher->v.ltime += movetime;
585                 return;
586         }
587
588         for (i=0 ; i<3 ; i++)
589                 amove[i] = pusher->v.avelocity[i] * movetime;
590
591         VectorSubtract (vec3_origin, amove, a);
592         AngleVectors (a, forward, right, up);
593
594         VectorCopy (pusher->v.angles, pushorig);
595         
596 // move the pusher to it's final position
597
598         VectorAdd (pusher->v.angles, amove, pusher->v.angles);
599         pusher->v.ltime += movetime;
600         SV_LinkEdict (pusher, false);
601
602
603 // see if any solid entities are inside the final position
604         num_moved = 0;
605         check = NEXT_EDICT(sv.edicts);
606         for (e=1 ; e<sv.num_edicts ; e++, check = NEXT_EDICT(check))
607         {
608                 if (check->free)
609                         continue;
610                 if (check->v.movetype == MOVETYPE_PUSH
611                 || check->v.movetype == MOVETYPE_NONE
612                 || check->v.movetype == MOVETYPE_FOLLOW
613                 || check->v.movetype == MOVETYPE_NOCLIP)
614                         continue;
615
616         // if the entity is standing on the pusher, it will definately be moved
617                 if ( ! ( ((int)check->v.flags & FL_ONGROUND)
618                 && PROG_TO_EDICT(check->v.groundentity) == pusher) )
619                 {
620                         if ( check->v.absmin[0] >= pusher->v.absmax[0]
621                         || check->v.absmin[1] >= pusher->v.absmax[1]
622                         || check->v.absmin[2] >= pusher->v.absmax[2]
623                         || check->v.absmax[0] <= pusher->v.absmin[0]
624                         || check->v.absmax[1] <= pusher->v.absmin[1]
625                         || check->v.absmax[2] <= pusher->v.absmin[2] )
626                                 continue;
627
628                 // see if the ent's bbox is inside the pusher's final position
629                         if (!SV_TestEntityPosition (check))
630                                 continue;
631                 }
632
633         // remove the onground flag for non-players
634                 if (check->v.movetype != MOVETYPE_WALK)
635                         check->v.flags = (int)check->v.flags & ~FL_ONGROUND;
636                 
637                 VectorCopy (check->v.origin, entorig);
638                 VectorCopy (check->v.origin, moved_from[num_moved]);
639                 moved_edict[num_moved] = check;
640                 num_moved++;
641
642                 // calculate destination position
643                 VectorSubtract (check->v.origin, pusher->v.origin, org);
644                 org2[0] = DotProduct (org, forward);
645                 org2[1] = -DotProduct (org, right);
646                 org2[2] = DotProduct (org, up);
647                 VectorSubtract (org2, org, move);
648
649                 // try moving the contacted entity 
650                 savesolid = pusher->v.solid; // LordHavoc: restore to correct solid type
651                 pusher->v.solid = SOLID_NOT;
652                 SV_PushEntity (check, move);
653                 pusher->v.solid = savesolid; // LordHavoc: restore to correct solid type
654
655         // if it is still inside the pusher, block
656                 if (SV_TestEntityPosition (check))
657                 {       // fail the move
658                         if (check->v.mins[0] == check->v.maxs[0])
659                                 continue;
660                         if (check->v.solid == SOLID_NOT || check->v.solid == SOLID_TRIGGER)
661                         {       // corpse
662                                 check->v.mins[0] = check->v.mins[1] = 0;
663                                 VectorCopy (check->v.mins, check->v.maxs);
664                                 continue;
665                         }
666                         
667                         VectorCopy (entorig, check->v.origin);
668                         SV_LinkEdict (check, true);
669
670                         VectorCopy (pushorig, pusher->v.angles);
671                         SV_LinkEdict (pusher, false);
672                         pusher->v.ltime -= movetime;
673
674                         // if the pusher has a "blocked" function, call it
675                         // otherwise, just stay in place until the obstacle is gone
676                         if (pusher->v.blocked)
677                         {
678                                 pr_global_struct->self = EDICT_TO_PROG(pusher);
679                                 pr_global_struct->other = EDICT_TO_PROG(check);
680                                 PR_ExecuteProgram (pusher->v.blocked);
681                         }
682                         
683                 // move back any entities we already moved
684                         for (i=0 ; i<num_moved ; i++)
685                         {
686                                 VectorCopy (moved_from[i], moved_edict[i]->v.origin);
687                                 VectorSubtract (moved_edict[i]->v.angles, amove, moved_edict[i]->v.angles);
688                                 SV_LinkEdict (moved_edict[i], false);
689                         }
690                         return;
691                 }
692                 else
693                 {
694                         VectorAdd (check->v.angles, amove, check->v.angles);
695                 }
696         }
697
698         
699 }
700 //#endif
701
702 /*
703 ================
704 SV_Physics_Pusher
705
706 ================
707 */
708 void SV_Physics_Pusher (edict_t *ent)
709 {
710         float   thinktime;
711         float   oldltime;
712         float   movetime;
713
714         oldltime = ent->v.ltime;
715         
716         thinktime = ent->v.nextthink;
717         if (thinktime < ent->v.ltime + host_frametime)
718         {
719                 movetime = thinktime - ent->v.ltime;
720                 if (movetime < 0)
721                         movetime = 0;
722         }
723         else
724                 movetime = host_frametime;
725
726         if (movetime)
727         {
728                 if (ent->v.avelocity[0] || ent->v.avelocity[1] || ent->v.avelocity[2])
729                         SV_PushRotate (ent, movetime);
730                 else
731                         SV_PushMove (ent, movetime);    // advances ent->v.ltime if not blocked
732         }
733                 
734         if (thinktime > oldltime && thinktime <= ent->v.ltime)
735         {
736                 ent->v.nextthink = 0;
737                 pr_global_struct->time = sv.time;
738                 pr_global_struct->self = EDICT_TO_PROG(ent);
739                 pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
740                 PR_ExecuteProgram (ent->v.think);
741                 if (ent->free)
742                         return;
743         }
744
745 }
746
747
748 /*
749 ===============================================================================
750
751 CLIENT MOVEMENT
752
753 ===============================================================================
754 */
755
756 /*
757 =============
758 SV_CheckStuck
759
760 This is a big hack to try and fix the rare case of getting stuck in the world
761 clipping hull.
762 =============
763 */
764 void SV_CheckStuck (edict_t *ent)
765 {
766         int             i, j;
767         int             z;
768         vec3_t  org;
769
770         if (!SV_TestEntityPosition(ent))
771         {
772                 VectorCopy (ent->v.origin, ent->v.oldorigin);
773                 return;
774         }
775
776         VectorCopy (ent->v.origin, org);
777         VectorCopy (ent->v.oldorigin, ent->v.origin);
778         if (!SV_TestEntityPosition(ent))
779         {
780                 Con_DPrintf ("Unstuck.\n");
781                 SV_LinkEdict (ent, true);
782                 return;
783         }
784         
785         for (z=0 ; z< 18 ; z++)
786                 for (i=-1 ; i <= 1 ; i++)
787                         for (j=-1 ; j <= 1 ; j++)
788                         {
789                                 ent->v.origin[0] = org[0] + i;
790                                 ent->v.origin[1] = org[1] + j;
791                                 ent->v.origin[2] = org[2] + z;
792                                 if (!SV_TestEntityPosition(ent))
793                                 {
794                                         Con_DPrintf ("Unstuck.\n");
795                                         SV_LinkEdict (ent, true);
796                                         return;
797                                 }
798                         }
799                         
800         VectorCopy (org, ent->v.origin);
801         Con_DPrintf ("player is stuck.\n");
802 }
803
804
805 /*
806 =============
807 SV_CheckWater
808 =============
809 */
810 qboolean SV_CheckWater (edict_t *ent)
811 {
812         vec3_t  point;
813         int             cont;
814
815         point[0] = ent->v.origin[0];
816         point[1] = ent->v.origin[1];
817         point[2] = ent->v.origin[2] + ent->v.mins[2] + 1;       
818         
819         ent->v.waterlevel = 0;
820         ent->v.watertype = CONTENTS_EMPTY;
821         cont = SV_PointContents (point);
822         if (cont <= CONTENTS_WATER)
823         {
824                 ent->v.watertype = cont;
825                 ent->v.waterlevel = 1;
826                 point[2] = ent->v.origin[2] + (ent->v.mins[2] + ent->v.maxs[2])*0.5;
827                 cont = SV_PointContents (point);
828                 if (cont <= CONTENTS_WATER)
829                 {
830                         ent->v.waterlevel = 2;
831                         point[2] = ent->v.origin[2] + ent->v.view_ofs[2];
832                         cont = SV_PointContents (point);
833                         if (cont <= CONTENTS_WATER)
834                                 ent->v.waterlevel = 3;
835                 }
836         }
837         
838         return ent->v.waterlevel > 1;
839 }
840
841 /*
842 ============
843 SV_WallFriction
844
845 ============
846 */
847 void SV_WallFriction (edict_t *ent, trace_t *trace)
848 {
849         vec3_t          forward, right, up;
850         float           d, i;
851         vec3_t          into, side;
852         
853         AngleVectors (ent->v.v_angle, forward, right, up);
854         d = DotProduct (trace->plane.normal, forward);
855         
856         d += 0.5;
857         if (d >= 0)
858                 return;
859                 
860 // cut the tangential velocity
861         i = DotProduct (trace->plane.normal, ent->v.velocity);
862         VectorScale (trace->plane.normal, i, into);
863         VectorSubtract (ent->v.velocity, into, side);
864         
865         ent->v.velocity[0] = side[0] * (1 + d);
866         ent->v.velocity[1] = side[1] * (1 + d);
867 }
868
869 /*
870 =====================
871 SV_TryUnstick
872
873 Player has come to a dead stop, possibly due to the problem with limited
874 float precision at some angle joins in the BSP hull.
875
876 Try fixing by pushing one pixel in each direction.
877
878 This is a hack, but in the interest of good gameplay...
879 ======================
880 */
881 int SV_TryUnstick (edict_t *ent, vec3_t oldvel)
882 {
883         int             i;
884         vec3_t  oldorg;
885         vec3_t  dir;
886         int             clip;
887         trace_t steptrace;
888         
889         VectorCopy (ent->v.origin, oldorg);
890         VectorCopy (vec3_origin, dir);
891
892         for (i=0 ; i<8 ; i++)
893         {
894 // try pushing a little in an axial direction
895                 switch (i)
896                 {
897                         case 0: dir[0] = 2; dir[1] = 0; break;
898                         case 1: dir[0] = 0; dir[1] = 2; break;
899                         case 2: dir[0] = -2; dir[1] = 0; break;
900                         case 3: dir[0] = 0; dir[1] = -2; break;
901                         case 4: dir[0] = 2; dir[1] = 2; break;
902                         case 5: dir[0] = -2; dir[1] = 2; break;
903                         case 6: dir[0] = 2; dir[1] = -2; break;
904                         case 7: dir[0] = -2; dir[1] = -2; break;
905                 }
906                 
907                 SV_PushEntity (ent, dir);
908
909 // retry the original move
910                 ent->v.velocity[0] = oldvel[0];
911                 ent->v. velocity[1] = oldvel[1];
912                 ent->v. velocity[2] = 0;
913                 clip = SV_FlyMove (ent, 0.1, &steptrace);
914
915                 if ( fabs(oldorg[1] - ent->v.origin[1]) > 4
916                 || fabs(oldorg[0] - ent->v.origin[0]) > 4 )
917                 {
918 //Con_DPrintf ("unstuck!\n");
919                         return clip;
920                 }
921                         
922 // go back to the original pos and try again
923                 VectorCopy (oldorg, ent->v.origin);
924         }
925         
926         VectorCopy (vec3_origin, ent->v.velocity);
927         return 7;               // still not moving
928 }
929
930 /*
931 =====================
932 SV_WalkMove
933
934 Only used by players
935 ======================
936 */
937 #define STEPSIZE        18
938 void SV_WalkMove (edict_t *ent)
939 {
940         vec3_t          upmove, downmove;
941         vec3_t          oldorg, oldvel;
942         vec3_t          nosteporg, nostepvel;
943         int                     clip;
944         int                     oldonground;
945         trace_t         steptrace, downtrace;
946         
947 //
948 // do a regular slide move unless it looks like you ran into a step
949 //
950         oldonground = (int)ent->v.flags & FL_ONGROUND;
951         ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;
952         
953         VectorCopy (ent->v.origin, oldorg);
954         VectorCopy (ent->v.velocity, oldvel);
955         
956         clip = SV_FlyMove (ent, host_frametime, &steptrace);
957
958         if ( !(clip & 2) )
959                 return;         // move didn't block on a step
960
961         if (!oldonground && ent->v.waterlevel == 0)
962                 return;         // don't stair up while jumping
963         
964         if (ent->v.movetype != MOVETYPE_WALK)
965                 return;         // gibbed by a trigger
966         
967         if (sv_nostep.value)
968                 return;
969         
970         if ( (int)sv_player->v.flags & FL_WATERJUMP )
971                 return;
972
973         VectorCopy (ent->v.origin, nosteporg);
974         VectorCopy (ent->v.velocity, nostepvel);
975
976 //
977 // try moving up and forward to go up a step
978 //
979         VectorCopy (oldorg, ent->v.origin);     // back to start pos
980
981         VectorCopy (vec3_origin, upmove);
982         VectorCopy (vec3_origin, downmove);
983         upmove[2] = STEPSIZE;
984         downmove[2] = -STEPSIZE + oldvel[2]*host_frametime;
985
986 // move up
987         SV_PushEntity (ent, upmove);    // FIXME: don't link?
988
989 // move forward
990         ent->v.velocity[0] = oldvel[0];
991         ent->v. velocity[1] = oldvel[1];
992         ent->v. velocity[2] = 0;
993         clip = SV_FlyMove (ent, host_frametime, &steptrace);
994
995 // check for stuckness, possibly due to the limited precision of floats
996 // in the clipping hulls
997         if (clip)
998         {
999                 if ( fabs(oldorg[1] - ent->v.origin[1]) < 0.03125
1000                 && fabs(oldorg[0] - ent->v.origin[0]) < 0.03125 )
1001                 {       // stepping up didn't make any progress
1002                         clip = SV_TryUnstick (ent, oldvel);
1003                 }
1004         }
1005         
1006 // extra friction based on view angle
1007         if ( clip & 2 )
1008                 SV_WallFriction (ent, &steptrace);
1009
1010 // move down
1011         downtrace = SV_PushEntity (ent, downmove);      // FIXME: don't link?
1012
1013         if (downtrace.plane.normal[2] > 0.7)
1014         {
1015                 if (ent->v.solid == SOLID_BSP)
1016                 {
1017                         ent->v.flags =  (int)ent->v.flags | FL_ONGROUND;
1018                         ent->v.groundentity = EDICT_TO_PROG(downtrace.ent);
1019                 }
1020         }
1021         else
1022         {
1023 // if the push down didn't end up on good ground, use the move without
1024 // the step up.  This happens near wall / slope combinations, and can
1025 // cause the player to hop up higher on a slope too steep to climb      
1026                 VectorCopy (nosteporg, ent->v.origin);
1027                 VectorCopy (nostepvel, ent->v.velocity);
1028         }
1029 }
1030
1031
1032 /*
1033 ================
1034 SV_Physics_Client
1035
1036 Player character actions
1037 ================
1038 */
1039 void SV_Physics_Client (edict_t *ent, int num)
1040 {
1041         if ( ! svs.clients[num-1].active )
1042                 return;         // unconnected slot
1043
1044 //
1045 // call standard client pre-think
1046 //      
1047         pr_global_struct->time = sv.time;
1048         pr_global_struct->self = EDICT_TO_PROG(ent);
1049         PR_ExecuteProgram (pr_global_struct->PlayerPreThink);
1050         
1051 //
1052 // do a move
1053 //
1054         SV_CheckVelocity (ent);
1055
1056 //
1057 // decide which move function to call
1058 //
1059         switch ((int)ent->v.movetype)
1060         {
1061         case MOVETYPE_NONE:
1062                 if (!SV_RunThink (ent))
1063                         return;
1064                 break;
1065
1066         case MOVETYPE_WALK:
1067                 if (!SV_RunThink (ent))
1068                         return;
1069                 if (!SV_CheckWater (ent) && ! ((int)ent->v.flags & FL_WATERJUMP) )
1070                         SV_AddGravity (ent);
1071                 SV_CheckStuck (ent);
1072                 SV_WalkMove (ent);
1073                 break;
1074                 
1075         case MOVETYPE_TOSS:
1076         case MOVETYPE_BOUNCE:
1077                 SV_Physics_Toss (ent);
1078                 break;
1079
1080         case MOVETYPE_FLY:
1081                 if (!SV_RunThink (ent))
1082                         return;
1083                 SV_FlyMove (ent, host_frametime, NULL);
1084                 break;
1085                 
1086         case MOVETYPE_NOCLIP:
1087                 if (!SV_RunThink (ent))
1088                         return;
1089                 VectorMA (ent->v.origin, host_frametime, ent->v.velocity, ent->v.origin);
1090                 break;
1091                 
1092         default:
1093                 Host_Error ("SV_Physics_client: bad movetype %i", (int)ent->v.movetype);
1094         }
1095
1096 //
1097 // call standard player post-think
1098 //              
1099         SV_LinkEdict (ent, true);
1100
1101         pr_global_struct->time = sv.time;
1102         pr_global_struct->self = EDICT_TO_PROG(ent);
1103         PR_ExecuteProgram (pr_global_struct->PlayerPostThink);
1104 }
1105
1106 //============================================================================
1107
1108 /*
1109 =============
1110 SV_Physics_None
1111
1112 Non moving objects can only think
1113 =============
1114 */
1115 void SV_Physics_None (edict_t *ent)
1116 {
1117 // regular thinking
1118         SV_RunThink (ent);
1119 }
1120
1121 /*
1122 =============
1123 SV_Physics_Follow
1124
1125 Entities that are "stuck" to another entity
1126 =============
1127 */
1128 void SV_Physics_Follow (edict_t *ent)
1129 {
1130         vec3_t vf, vu, vr, angles;
1131         edict_t *e;
1132 // regular thinking
1133         SV_RunThink (ent);
1134         // LordHavoc: implemented rotation on MOVETYPE_FOLLOW objects
1135         e = PROG_TO_EDICT(ent->v.aiment);
1136         angles[0] = -e->v.angles[0];
1137         angles[1] = e->v.angles[1];
1138         angles[2] = e->v.angles[2];
1139         AngleVectors (angles, vf, vr, vu);
1140         VectorMA (e->v.origin, ent->v.view_ofs[0], vf, ent->v.origin);
1141         VectorMA (ent->v.origin, ent->v.view_ofs[1], vr, ent->v.origin);
1142         VectorMA (ent->v.origin, ent->v.view_ofs[2], vu, ent->v.origin);
1143         VectorAdd (e->v.angles, ent->v.v_angle, ent->v.angles);
1144 //      VectorAdd (PROG_TO_EDICT(ent->v.aiment)->v.origin, ent->v.v_angle, ent->v.origin);
1145         SV_LinkEdict (ent, true);
1146 }
1147
1148 /*
1149 =============
1150 SV_Physics_Noclip
1151
1152 A moving object that doesn't obey physics
1153 =============
1154 */
1155 void SV_Physics_Noclip (edict_t *ent)
1156 {
1157 // regular thinking
1158         if (!SV_RunThink (ent))
1159                 return;
1160         
1161         VectorMA (ent->v.angles, host_frametime, ent->v.avelocity, ent->v.angles);
1162         VectorMA (ent->v.origin, host_frametime, ent->v.velocity, ent->v.origin);
1163
1164         SV_LinkEdict (ent, false);
1165 }
1166
1167 /*
1168 ==============================================================================
1169
1170 TOSS / BOUNCE
1171
1172 ==============================================================================
1173 */
1174
1175 /*
1176 =============
1177 SV_CheckWaterTransition
1178
1179 =============
1180 */
1181 void SV_CheckWaterTransition (edict_t *ent)
1182 {
1183         int             cont;
1184         cont = SV_PointContents (ent->v.origin);
1185         if (!ent->v.watertype)
1186         {       // just spawned here
1187                 ent->v.watertype = cont;
1188                 ent->v.waterlevel = 1;
1189                 return;
1190         }
1191         
1192         if (cont <= CONTENTS_WATER)
1193         {
1194                 if (ent->v.watertype == CONTENTS_EMPTY)
1195                 {       // just crossed into water
1196                         SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1);
1197                 }               
1198                 ent->v.watertype = cont;
1199                 ent->v.waterlevel = 1;
1200         }
1201         else
1202         {
1203                 if (ent->v.watertype != CONTENTS_EMPTY)
1204                 {       // just crossed into water
1205                         SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1);
1206                 }               
1207                 ent->v.watertype = CONTENTS_EMPTY;
1208                 ent->v.waterlevel = cont;
1209         }
1210 }
1211
1212 /*
1213 =============
1214 SV_Physics_Toss
1215
1216 Toss, bounce, and fly movement.  When onground, do nothing.
1217 =============
1218 */
1219 void SV_Physics_Toss (edict_t *ent)
1220 {
1221         trace_t trace;
1222         vec3_t  move;
1223         float   backoff;
1224         // regular thinking
1225         if (!SV_RunThink (ent))
1226                 return;
1227
1228 // if onground, return without moving
1229         if ( ((int)ent->v.flags & FL_ONGROUND) )
1230                 return;
1231
1232         SV_CheckVelocity (ent);
1233
1234 // add gravity
1235         if (ent->v.movetype != MOVETYPE_FLY
1236         && ent->v.movetype != MOVETYPE_BOUNCEMISSILE // LordHavoc: enabled MOVETYPE_BOUNCEMISSILE
1237         && ent->v.movetype != MOVETYPE_FLYMISSILE)
1238                 SV_AddGravity (ent);
1239
1240 // move angles
1241         VectorMA (ent->v.angles, host_frametime, ent->v.avelocity, ent->v.angles);
1242
1243 // move origin
1244         VectorScale (ent->v.velocity, host_frametime, move);
1245         trace = SV_PushEntity (ent, move);
1246         if (trace.fraction == 1)
1247                 return;
1248         if (ent->free)
1249                 return;
1250         
1251         if (ent->v.movetype == MOVETYPE_BOUNCE)
1252                 backoff = 1.5;
1253         else if (ent->v.movetype == MOVETYPE_BOUNCEMISSILE)
1254                 backoff = 2.0;
1255         else
1256                 backoff = 1;
1257
1258         ClipVelocity (ent->v.velocity, trace.plane.normal, ent->v.velocity, backoff);
1259
1260 // stop if on ground
1261         if (trace.plane.normal[2] > 0.7)
1262         {               
1263                 if (ent->v.velocity[2] < 60 || (ent->v.movetype != MOVETYPE_BOUNCE && ent->v.movetype != MOVETYPE_BOUNCEMISSILE))
1264                 {
1265                         ent->v.flags = (int)ent->v.flags | FL_ONGROUND;
1266                         ent->v.groundentity = EDICT_TO_PROG(trace.ent);
1267                         VectorCopy (vec3_origin, ent->v.velocity);
1268                         VectorCopy (vec3_origin, ent->v.avelocity);
1269                 }
1270         }
1271         
1272 // check for in water
1273         SV_CheckWaterTransition (ent);
1274 }
1275
1276 /*
1277 ===============================================================================
1278
1279 STEPPING MOVEMENT
1280
1281 ===============================================================================
1282 */
1283
1284 /*
1285 =============
1286 SV_Physics_Step
1287
1288 Monsters freefall when they don't have a ground entity, otherwise
1289 all movement is done with discrete steps.
1290
1291 This is also used for objects that have become still on the ground, but
1292 will fall if the floor is pulled out from under them.
1293 =============
1294 */
1295 void SV_Physics_Step (edict_t *ent)
1296 {
1297         qboolean        hitsound;
1298
1299 // freefall if not onground
1300         if ( ! ((int)ent->v.flags & (FL_ONGROUND | FL_FLY | FL_SWIM) ) )
1301         {
1302                 if (ent->v.velocity[2] < sv_gravity.value*-0.1)
1303                         hitsound = true;
1304                 else
1305                         hitsound = false;
1306
1307                 SV_AddGravity (ent);
1308                 SV_CheckVelocity (ent);
1309                 SV_FlyMove (ent, host_frametime, NULL);
1310                 SV_LinkEdict (ent, true);
1311
1312                 if ( (int)ent->v.flags & FL_ONGROUND )  // just hit ground
1313                 {
1314                         if (hitsound)
1315                                 SV_StartSound (ent, 0, "demon/dland2.wav", 255, 1);
1316                 }
1317         }
1318
1319 // regular thinking
1320         SV_RunThink (ent);
1321         
1322         SV_CheckWaterTransition (ent);
1323 }
1324
1325 //============================================================================
1326
1327 /*
1328 ================
1329 SV_Physics
1330
1331 ================
1332 */
1333 extern dfunction_t *EndFrameQC;
1334 void SV_Physics (void)
1335 {
1336         int             i;
1337         edict_t *ent;
1338
1339 // let the progs know that a new frame has started
1340         pr_global_struct->self = EDICT_TO_PROG(sv.edicts);
1341         pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
1342         pr_global_struct->time = sv.time;
1343         PR_ExecuteProgram (pr_global_struct->StartFrame);
1344
1345 //SV_CheckAllEnts ();
1346
1347 //
1348 // treat each object in turn
1349 //
1350         ent = sv.edicts;
1351         for (i=0 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent))
1352         {
1353                 if (ent->free)
1354                         continue;
1355
1356                 if (pr_global_struct->force_retouch)
1357                 {
1358                         SV_LinkEdict (ent, true);       // force retouch even for stationary
1359                 }
1360
1361                 if (i > 0 && i <= svs.maxclients)
1362                         SV_Physics_Client (ent, i);
1363                 else if (ent->v.movetype == MOVETYPE_PUSH)
1364                         SV_Physics_Pusher (ent);
1365                 else if (ent->v.movetype == MOVETYPE_NONE)
1366                         SV_Physics_None (ent);
1367                 else if (ent->v.movetype == MOVETYPE_FOLLOW)
1368                         SV_Physics_Follow (ent);
1369                 else if (ent->v.movetype == MOVETYPE_NOCLIP)
1370                         SV_Physics_Noclip (ent);
1371                 else if (ent->v.movetype == MOVETYPE_STEP)
1372                         SV_Physics_Step (ent);
1373                 // LordHavoc: added support for MOVETYPE_WALK on normal entities! :)
1374                 else if (ent->v.movetype == MOVETYPE_WALK)
1375                 {
1376                         if (SV_RunThink (ent))
1377                         {
1378                                 if (!SV_CheckWater (ent) && ! ((int)ent->v.flags & FL_WATERJUMP) )
1379                                         SV_AddGravity (ent);
1380                                 SV_CheckStuck (ent);
1381                                 SV_WalkMove (ent);
1382                         }
1383                 }
1384                 else if (ent->v.movetype == MOVETYPE_TOSS 
1385                 || ent->v.movetype == MOVETYPE_BOUNCE
1386                 || ent->v.movetype == MOVETYPE_BOUNCEMISSILE
1387                 || ent->v.movetype == MOVETYPE_FLY
1388                 || ent->v.movetype == MOVETYPE_FLYMISSILE)
1389                         SV_Physics_Toss (ent);
1390                 else
1391                         Host_Error ("SV_Physics: bad movetype %i", (int)ent->v.movetype);                       
1392         }
1393         
1394         if (pr_global_struct->force_retouch)
1395                 pr_global_struct->force_retouch--;      
1396
1397         // LordHavoc: endframe support
1398         if (EndFrameQC)
1399         {
1400                 pr_global_struct->self = EDICT_TO_PROG(sv.edicts);
1401                 pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
1402                 pr_global_struct->time = sv.time;
1403                 PR_ExecuteProgram ((func_t)(EndFrameQC - pr_functions));
1404         }
1405
1406         sv.time += host_frametime;
1407 }
1408
1409
1410 trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore)
1411 {
1412         int i;
1413         edict_t tempent, *tent;
1414         trace_t trace;
1415         vec3_t  move;
1416         vec3_t  end;
1417         double  save_frametime;
1418
1419         save_frametime = host_frametime;
1420         host_frametime = 0.05;
1421
1422         memcpy(&tempent, ent, sizeof(edict_t));
1423         tent = &tempent;
1424
1425         for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
1426         {
1427                 SV_CheckVelocity (tent);
1428                 SV_AddGravity (tent);
1429                 VectorMA (tent->v.angles, host_frametime, tent->v.avelocity, tent->v.angles);
1430                 VectorScale (tent->v.velocity, host_frametime, move);
1431                 VectorAdd (tent->v.origin, move, end);
1432                 trace = SV_Move (tent->v.origin, tent->v.mins, tent->v.maxs, end, MOVE_NORMAL, tent);   
1433                 VectorCopy (trace.endpos, tent->v.origin);
1434
1435                 if (trace.ent)
1436                         if (trace.ent != ignore)
1437                                 break;
1438         }
1439         host_frametime = save_frametime;
1440         return trace;
1441 }