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 "qwsvdef.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_maxvelocity = {"sv_maxvelocity","2000"};
43
44 cvar_t sv_gravity = { "sv_gravity", "800"};
45 cvar_t sv_stopspeed = { "sv_stopspeed", "100"};
46 cvar_t sv_maxspeed = { "sv_maxspeed", "320"};
47 cvar_t sv_spectatormaxspeed = { "sv_spectatormaxspeed", "500"};
48 cvar_t sv_accelerate = { "sv_accelerate", "10"};
49 cvar_t sv_airaccelerate = { "sv_airaccelerate", "0.7"};
50 cvar_t sv_wateraccelerate = { "sv_wateraccelerate", "10"};
51 cvar_t sv_friction = { "sv_friction", "4"};
52 cvar_t sv_waterfriction = { "sv_waterfriction", "4"};
53
54
55 #define MOVE_EPSILON 0.01
56
57 void SV_Physics_Toss (edict_t *ent);
58
59 /*
60 ================
61 SV_CheckAllEnts
62 ================
63 */
SV_CheckAllEnts(void)64 void SV_CheckAllEnts (void)
65 {
66 int e;
67 edict_t *check;
68
69 // see if any solid entities are inside the final position
70 check = NEXT_EDICT(sv.edicts);
71 for (e=1 ; e<sv.num_edicts ; e++, check = NEXT_EDICT(check))
72 {
73 if (check->free)
74 continue;
75 if (check->v.movetype == MOVETYPE_PUSH
76 || check->v.movetype == MOVETYPE_NONE
77 || check->v.movetype == MOVETYPE_NOCLIP)
78 continue;
79
80 if (SV_TestEntityPosition (check))
81 Con_Printf ("entity in invalid position\n");
82 }
83 }
84
85 /*
86 ================
87 SV_CheckVelocity
88 ================
89 */
SV_CheckVelocity(edict_t * ent)90 void SV_CheckVelocity (edict_t *ent)
91 {
92 int i;
93
94 //
95 // bound velocity
96 //
97 for (i=0 ; i<3 ; i++)
98 {
99 if (IS_NAN(ent->v.velocity[i]))
100 {
101 Con_Printf ("Got a NaN velocity on %s\n", PR_GetString(ent->v.classname));
102 ent->v.velocity[i] = 0;
103 }
104 if (IS_NAN(ent->v.origin[i]))
105 {
106 Con_Printf ("Got a NaN origin on %s\n", PR_GetString(ent->v.classname));
107 ent->v.origin[i] = 0;
108 }
109 if (ent->v.velocity[i] > sv_maxvelocity.value)
110 ent->v.velocity[i] = sv_maxvelocity.value;
111 else if (ent->v.velocity[i] < -sv_maxvelocity.value)
112 ent->v.velocity[i] = -sv_maxvelocity.value;
113 }
114 }
115
116 /*
117 =============
118 SV_RunThink
119
120 Runs thinking code if time. There is some play in the exact time the think
121 function will be called, because it is called before any movement is done
122 in a frame. Not used for pushmove objects, because they must be exact.
123 Returns false if the entity removed itself.
124 =============
125 */
SV_RunThink(edict_t * ent)126 qboolean SV_RunThink (edict_t *ent)
127 {
128 float thinktime;
129
130 do
131 {
132 thinktime = ent->v.nextthink;
133 if (thinktime <= 0)
134 return true;
135 if (thinktime > sv.time + host_frametime)
136 return true;
137
138 if (thinktime < sv.time)
139 thinktime = sv.time; // don't let things stay in the past.
140 // it is possible to start that way
141 // by a trigger with a local time.
142 ent->v.nextthink = 0;
143 pr_global_struct->time = thinktime;
144 pr_global_struct->self = EDICT_TO_PROG(ent);
145 pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
146 PR_ExecuteProgram (ent->v.think);
147
148 if (ent->free)
149 return false;
150 } while (1);
151
152 return true;
153 }
154
155 /*
156 ==================
157 SV_Impact
158
159 Two entities have touched, so run their touch functions
160 ==================
161 */
SV_Impact(edict_t * e1,edict_t * e2)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
ClipVelocity(vec3_t in,vec3_t normal,vec3_t out,float overbounce)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
SV_FlyMove(edict_t * ent,float time,trace_t * steptrace)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 for (i=0 ; i<3 ; i++)
264 end[i] = ent->v.origin[i] + time_left * ent->v.velocity[i];
265
266 trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, false, ent);
267
268 if (trace.allsolid)
269 { // entity is trapped in another solid
270 VectorCopy (vec3_origin, ent->v.velocity);
271 return 3;
272 }
273
274 if (trace.fraction > 0)
275 { // actually covered some distance
276 VectorCopy (trace.endpos, ent->v.origin);
277 VectorCopy (ent->v.velocity, original_velocity);
278 numplanes = 0;
279 }
280
281 if (trace.fraction == 1)
282 break; // moved the entire distance
283
284 if (!trace.ent)
285 SV_Error ("SV_FlyMove: !trace.ent");
286
287 if (trace.plane.normal[2] > 0.7)
288 {
289 blocked |= 1; // floor
290 if (trace.ent->v.solid == SOLID_BSP)
291 {
292 ent->v.flags = (int)ent->v.flags | FL_ONGROUND;
293 ent->v.groundentity = EDICT_TO_PROG(trace.ent);
294 }
295 }
296 if (!trace.plane.normal[2])
297 {
298 blocked |= 2; // step
299 if (steptrace)
300 *steptrace = trace; // save for player extrafriction
301 }
302
303 //
304 // run the impact function
305 //
306 SV_Impact (ent, trace.ent);
307 if (ent->free)
308 break; // removed by the impact function
309
310
311 time_left -= time_left * trace.fraction;
312
313 // cliped to another plane
314 if (numplanes >= MAX_CLIP_PLANES)
315 { // this shouldn't really happen
316 VectorCopy (vec3_origin, ent->v.velocity);
317 return 3;
318 }
319
320 VectorCopy (trace.plane.normal, planes[numplanes]);
321 numplanes++;
322
323 //
324 // modify original_velocity so it parallels all of the clip planes
325 //
326 for (i=0 ; i<numplanes ; i++)
327 {
328 ClipVelocity (original_velocity, planes[i], new_velocity, 1);
329 for (j=0 ; j<numplanes ; j++)
330 if (j != i)
331 {
332 if (DotProduct (new_velocity, planes[j]) < 0)
333 break; // not ok
334 }
335 if (j == numplanes)
336 break;
337 }
338
339 if (i != numplanes)
340 { // go along this plane
341 VectorCopy (new_velocity, ent->v.velocity);
342 }
343 else
344 { // go along the crease
345 if (numplanes != 2)
346 {
347 // Con_Printf ("clip velocity, numplanes == %i\n",numplanes);
348 VectorCopy (vec3_origin, ent->v.velocity);
349 return 7;
350 }
351 CrossProduct (planes[0], planes[1], dir);
352 d = DotProduct (dir, ent->v.velocity);
353 VectorScale (dir, d, ent->v.velocity);
354 }
355
356 //
357 // if original velocity is against the original velocity, stop dead
358 // to avoid tiny occilations in sloping corners
359 //
360 if (DotProduct (ent->v.velocity, primal_velocity) <= 0)
361 {
362 VectorCopy (vec3_origin, ent->v.velocity);
363 return blocked;
364 }
365 }
366
367 return blocked;
368 }
369
370
371 /*
372 ============
373 SV_AddGravity
374
375 ============
376 */
SV_AddGravity(edict_t * ent,float scale)377 void SV_AddGravity (edict_t *ent, float scale)
378 {
379 ent->v.velocity[2] -= scale * movevars.gravity * host_frametime;
380 }
381
382 /*
383 ===============================================================================
384
385 PUSHMOVE
386
387 ===============================================================================
388 */
389
390 /*
391 ============
392 SV_PushEntity
393
394 Does not change the entities velocity at all
395 ============
396 */
SV_PushEntity(edict_t * ent,vec3_t push)397 trace_t SV_PushEntity (edict_t *ent, vec3_t push)
398 {
399 trace_t trace;
400 vec3_t end;
401
402 VectorAdd (ent->v.origin, push, end);
403
404 if (ent->v.movetype == MOVETYPE_FLYMISSILE)
405 trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_MISSILE, ent);
406 else if (ent->v.solid == SOLID_TRIGGER || ent->v.solid == SOLID_NOT)
407 // only clip against bmodels
408 trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NOMONSTERS, ent);
409 else
410 trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NORMAL, ent);
411
412 VectorCopy (trace.endpos, ent->v.origin);
413 SV_LinkEdict (ent, true);
414
415 if (trace.ent)
416 SV_Impact (ent, trace.ent);
417
418 return trace;
419 }
420
421
422 /*
423 ============
424 SV_Push
425
426 ============
427 */
SV_Push(edict_t * pusher,vec3_t move)428 qboolean SV_Push (edict_t *pusher, vec3_t move)
429 {
430 int i, e;
431 edict_t *check, *block;
432 vec3_t mins, maxs;
433 vec3_t pushorig;
434 int num_moved;
435 edict_t *moved_edict[MAX_EDICTS];
436 vec3_t moved_from[MAX_EDICTS];
437
438 for (i=0 ; i<3 ; i++)
439 {
440 mins[i] = pusher->v.absmin[i] + move[i];
441 maxs[i] = pusher->v.absmax[i] + move[i];
442 }
443
444 VectorCopy (pusher->v.origin, pushorig);
445
446 // move the pusher to it's final position
447
448 VectorAdd (pusher->v.origin, move, pusher->v.origin);
449 SV_LinkEdict (pusher, false);
450
451 // see if any solid entities are inside the final position
452 num_moved = 0;
453 check = NEXT_EDICT(sv.edicts);
454 for (e=1 ; e<sv.num_edicts ; e++, check = NEXT_EDICT(check))
455 {
456 if (check->free)
457 continue;
458 if (check->v.movetype == MOVETYPE_PUSH
459 || check->v.movetype == MOVETYPE_NONE
460 || check->v.movetype == MOVETYPE_NOCLIP)
461 continue;
462
463 pusher->v.solid = SOLID_NOT;
464 block = SV_TestEntityPosition (check);
465 pusher->v.solid = SOLID_BSP;
466 if (block)
467 continue;
468
469 // if the entity is standing on the pusher, it will definately be moved
470 if ( ! ( ((int)check->v.flags & FL_ONGROUND)
471 && PROG_TO_EDICT(check->v.groundentity) == pusher) )
472 {
473 if ( check->v.absmin[0] >= maxs[0]
474 || check->v.absmin[1] >= maxs[1]
475 || check->v.absmin[2] >= maxs[2]
476 || check->v.absmax[0] <= mins[0]
477 || check->v.absmax[1] <= mins[1]
478 || check->v.absmax[2] <= mins[2] )
479 continue;
480
481 // see if the ent's bbox is inside the pusher's final position
482 if (!SV_TestEntityPosition (check))
483 continue;
484 }
485
486 VectorCopy (check->v.origin, moved_from[num_moved]);
487 moved_edict[num_moved] = check;
488 num_moved++;
489
490 // try moving the contacted entity
491 VectorAdd (check->v.origin, move, check->v.origin);
492 block = SV_TestEntityPosition (check);
493 if (!block)
494 { // pushed ok
495 SV_LinkEdict (check, false);
496 continue;
497 }
498
499 // if it is ok to leave in the old position, do it
500 VectorSubtract (check->v.origin, move, check->v.origin);
501 block = SV_TestEntityPosition (check);
502 if (!block)
503 {
504 num_moved--;
505 continue;
506 }
507
508 // if it is still inside the pusher, block
509 if (check->v.mins[0] == check->v.maxs[0])
510 {
511 SV_LinkEdict (check, false);
512 continue;
513 }
514 if (check->v.solid == SOLID_NOT || check->v.solid == SOLID_TRIGGER)
515 { // corpse
516 check->v.mins[0] = check->v.mins[1] = 0;
517 VectorCopy (check->v.mins, check->v.maxs);
518 SV_LinkEdict (check, false);
519 continue;
520 }
521
522 VectorCopy (pushorig, pusher->v.origin);
523 SV_LinkEdict (pusher, false);
524
525 // if the pusher has a "blocked" function, call it
526 // otherwise, just stay in place until the obstacle is gone
527 if (pusher->v.blocked)
528 {
529 pr_global_struct->self = EDICT_TO_PROG(pusher);
530 pr_global_struct->other = EDICT_TO_PROG(check);
531 PR_ExecuteProgram (pusher->v.blocked);
532 }
533
534 // move back any entities we already moved
535 for (i=0 ; i<num_moved ; i++)
536 {
537 VectorCopy (moved_from[i], moved_edict[i]->v.origin);
538 SV_LinkEdict (moved_edict[i], false);
539 }
540 return false;
541 }
542
543 return true;
544 }
545
546 /*
547 ============
548 SV_PushMove
549
550 ============
551 */
SV_PushMove(edict_t * pusher,float movetime)552 void SV_PushMove (edict_t *pusher, float movetime)
553 {
554 int i;
555 vec3_t move;
556
557 if (!pusher->v.velocity[0] && !pusher->v.velocity[1] && !pusher->v.velocity[2])
558 {
559 pusher->v.ltime += movetime;
560 return;
561 }
562
563 for (i=0 ; i<3 ; i++)
564 move[i] = pusher->v.velocity[i] * movetime;
565
566 if (SV_Push (pusher, move))
567 pusher->v.ltime += movetime;
568 }
569
570
571 /*
572 ================
573 SV_Physics_Pusher
574
575 ================
576 */
SV_Physics_Pusher(edict_t * ent)577 void SV_Physics_Pusher (edict_t *ent)
578 {
579 float thinktime;
580 float oldltime;
581 float movetime;
582 vec3_t oldorg, move;
583 float l;
584
585 oldltime = ent->v.ltime;
586
587 thinktime = ent->v.nextthink;
588 if (thinktime < ent->v.ltime + host_frametime)
589 {
590 movetime = thinktime - ent->v.ltime;
591 if (movetime < 0)
592 movetime = 0;
593 }
594 else
595 movetime = host_frametime;
596
597 if (movetime)
598 {
599 SV_PushMove (ent, movetime); // advances ent->v.ltime if not blocked
600 }
601
602 if (thinktime > oldltime && thinktime <= ent->v.ltime)
603 {
604 VectorCopy (ent->v.origin, oldorg);
605 ent->v.nextthink = 0;
606 pr_global_struct->time = sv.time;
607 pr_global_struct->self = EDICT_TO_PROG(ent);
608 pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
609 PR_ExecuteProgram (ent->v.think);
610 if (ent->free)
611 return;
612 VectorSubtract (ent->v.origin, oldorg, move);
613
614 l = Length(move);
615 if (l > 1.0/64)
616 {
617 // Con_Printf ("**** snap: %f\n", Length (l));
618 VectorCopy (oldorg, ent->v.origin);
619 SV_Push (ent, move);
620 }
621
622 }
623
624 }
625
626
627 /*
628 =============
629 SV_Physics_None
630
631 Non moving objects can only think
632 =============
633 */
SV_Physics_None(edict_t * ent)634 void SV_Physics_None (edict_t *ent)
635 {
636 // regular thinking
637 SV_RunThink (ent);
638 }
639
640 /*
641 =============
642 SV_Physics_Noclip
643
644 A moving object that doesn't obey physics
645 =============
646 */
SV_Physics_Noclip(edict_t * ent)647 void SV_Physics_Noclip (edict_t *ent)
648 {
649 // regular thinking
650 if (!SV_RunThink (ent))
651 return;
652
653 VectorMA (ent->v.angles, host_frametime, ent->v.avelocity, ent->v.angles);
654 VectorMA (ent->v.origin, host_frametime, ent->v.velocity, ent->v.origin);
655
656 SV_LinkEdict (ent, false);
657 }
658
659 /*
660 ==============================================================================
661
662 TOSS / BOUNCE
663
664 ==============================================================================
665 */
666
667 /*
668 =============
669 SV_CheckWaterTransition
670
671 =============
672 */
SV_CheckWaterTransition(edict_t * ent)673 void SV_CheckWaterTransition (edict_t *ent)
674 {
675 int cont;
676
677 cont = SV_PointContents (ent->v.origin);
678 if (!ent->v.watertype)
679 { // just spawned here
680 ent->v.watertype = cont;
681 ent->v.waterlevel = 1;
682 return;
683 }
684
685 if (cont <= CONTENTS_WATER)
686 {
687 if (ent->v.watertype == CONTENTS_EMPTY)
688 { // just crossed into water
689 SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1);
690 }
691 ent->v.watertype = cont;
692 ent->v.waterlevel = 1;
693 }
694 else
695 {
696 if (ent->v.watertype != CONTENTS_EMPTY)
697 { // just crossed into water
698 SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1);
699 }
700 ent->v.watertype = CONTENTS_EMPTY;
701 ent->v.waterlevel = cont;
702 }
703 }
704
705 /*
706 =============
707 SV_Physics_Toss
708
709 Toss, bounce, and fly movement. When onground, do nothing.
710 =============
711 */
SV_Physics_Toss(edict_t * ent)712 void SV_Physics_Toss (edict_t *ent)
713 {
714 trace_t trace;
715 vec3_t move;
716 float backoff;
717
718 // regular thinking
719 if (!SV_RunThink (ent))
720 return;
721
722 if (ent->v.velocity[2] > 0)
723 ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;
724
725 // if onground, return without moving
726 if ( ((int)ent->v.flags & FL_ONGROUND) )
727 return;
728
729 SV_CheckVelocity (ent);
730
731 // add gravity
732 if (ent->v.movetype != MOVETYPE_FLY
733 && ent->v.movetype != MOVETYPE_FLYMISSILE)
734 SV_AddGravity (ent, 1.0);
735
736 // move angles
737 VectorMA (ent->v.angles, host_frametime, ent->v.avelocity, ent->v.angles);
738
739 // move origin
740 VectorScale (ent->v.velocity, host_frametime, move);
741 trace = SV_PushEntity (ent, move);
742 if (trace.fraction == 1)
743 return;
744 if (ent->free)
745 return;
746
747 if (ent->v.movetype == MOVETYPE_BOUNCE)
748 backoff = 1.5;
749 else
750 backoff = 1;
751
752 ClipVelocity (ent->v.velocity, trace.plane.normal, ent->v.velocity, backoff);
753
754 // stop if on ground
755 if (trace.plane.normal[2] > 0.7)
756 {
757 if (ent->v.velocity[2] < 60 || ent->v.movetype != MOVETYPE_BOUNCE )
758 {
759 ent->v.flags = (int)ent->v.flags | FL_ONGROUND;
760 ent->v.groundentity = EDICT_TO_PROG(trace.ent);
761 VectorCopy (vec3_origin, ent->v.velocity);
762 VectorCopy (vec3_origin, ent->v.avelocity);
763 }
764 }
765
766 // check for in water
767 SV_CheckWaterTransition (ent);
768 }
769
770 /*
771 ===============================================================================
772
773 STEPPING MOVEMENT
774
775 ===============================================================================
776 */
777
778 /*
779 =============
780 SV_Physics_Step
781
782 Monsters freefall when they don't have a ground entity, otherwise
783 all movement is done with discrete steps.
784
785 This is also used for objects that have become still on the ground, but
786 will fall if the floor is pulled out from under them.
787 FIXME: is this true?
788 =============
789 */
SV_Physics_Step(edict_t * ent)790 void SV_Physics_Step (edict_t *ent)
791 {
792 qboolean hitsound;
793
794 // frefall if not onground
795 if ( ! ((int)ent->v.flags & (FL_ONGROUND | FL_FLY | FL_SWIM) ) )
796 {
797 if (ent->v.velocity[2] < movevars.gravity*-0.1)
798 hitsound = true;
799 else
800 hitsound = false;
801
802 SV_AddGravity (ent, 1.0);
803 SV_CheckVelocity (ent);
804 SV_FlyMove (ent, host_frametime, NULL);
805 SV_LinkEdict (ent, true);
806
807 if ( (int)ent->v.flags & FL_ONGROUND ) // just hit ground
808 {
809 if (hitsound)
810 SV_StartSound (ent, 0, "demon/dland2.wav", 255, 1);
811 }
812 }
813
814 // regular thinking
815 SV_RunThink (ent);
816
817 SV_CheckWaterTransition (ent);
818 }
819
820 //============================================================================
821
SV_ProgStartFrame(void)822 void SV_ProgStartFrame (void)
823 {
824 // let the progs know that a new frame has started
825 pr_global_struct->self = EDICT_TO_PROG(sv.edicts);
826 pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
827 pr_global_struct->time = sv.time;
828 PR_ExecuteProgram (pr_global_struct->StartFrame);
829 }
830
831 /*
832 ================
833 SV_RunEntity
834
835 ================
836 */
SV_RunEntity(edict_t * ent)837 void SV_RunEntity (edict_t *ent)
838 {
839 if (ent->v.lastruntime == (float)realtime)
840 return;
841 ent->v.lastruntime = (float)realtime;
842
843 switch ( (int)ent->v.movetype)
844 {
845 case MOVETYPE_PUSH:
846 SV_Physics_Pusher (ent);
847 break;
848 case MOVETYPE_NONE:
849 SV_Physics_None (ent);
850 break;
851 case MOVETYPE_NOCLIP:
852 SV_Physics_Noclip (ent);
853 break;
854 case MOVETYPE_STEP:
855 SV_Physics_Step (ent);
856 break;
857 case MOVETYPE_TOSS:
858 case MOVETYPE_BOUNCE:
859 case MOVETYPE_FLY:
860 case MOVETYPE_FLYMISSILE:
861 SV_Physics_Toss (ent);
862 break;
863 default:
864 SV_Error ("SV_Physics: bad movetype %i", (int)ent->v.movetype);
865 }
866 }
867
868 /*
869 ================
870 SV_RunNewmis
871
872 ================
873 */
SV_RunNewmis(void)874 void SV_RunNewmis (void)
875 {
876 edict_t *ent;
877
878 if (!pr_global_struct->newmis)
879 return;
880 ent = PROG_TO_EDICT(pr_global_struct->newmis);
881 host_frametime = 0.05;
882 pr_global_struct->newmis = 0;
883
884 SV_RunEntity (ent);
885 }
886
887 /*
888 ================
889 SV_Physics
890
891 ================
892 */
SV_Physics(void)893 void SV_Physics (void)
894 {
895 int i;
896 edict_t *ent;
897 static double old_time;
898
899 // don't bother running a frame if sys_ticrate seconds haven't passed
900 host_frametime = realtime - old_time;
901 if (host_frametime < sv_mintic.value)
902 return;
903 if (host_frametime > sv_maxtic.value)
904 host_frametime = sv_maxtic.value;
905 old_time = realtime;
906
907 pr_global_struct->frametime = host_frametime;
908
909 SV_ProgStartFrame ();
910
911 //
912 // treat each object in turn
913 // even the world gets a chance to think
914 //
915 ent = sv.edicts;
916 for (i=0 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent))
917 {
918 if (ent->free)
919 continue;
920
921 if (pr_global_struct->force_retouch)
922 SV_LinkEdict (ent, true); // force retouch even for stationary
923
924 if (i > 0 && i <= MAX_CLIENTS)
925 continue; // clients are run directly from packets
926
927 SV_RunEntity (ent);
928 SV_RunNewmis ();
929 }
930
931 if (pr_global_struct->force_retouch)
932 pr_global_struct->force_retouch--;
933 }
934
SV_SetMoveVars(void)935 void SV_SetMoveVars(void)
936 {
937 movevars.gravity = sv_gravity.value;
938 movevars.stopspeed = sv_stopspeed.value;
939 movevars.maxspeed = sv_maxspeed.value;
940 movevars.spectatormaxspeed = sv_spectatormaxspeed.value;
941 movevars.accelerate = sv_accelerate.value;
942 movevars.airaccelerate = sv_airaccelerate.value;
943 movevars.wateraccelerate = sv_wateraccelerate.value;
944 movevars.friction = sv_friction.value;
945 movevars.waterfriction = sv_waterfriction.value;
946 movevars.entgravity = 1.0;
947 }
948