Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

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