Home | History | Annotate | Download | only in WinQuake
      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 = CVAR4("sv_friction","4",false,true);
     43 cvar_t	sv_stopspeed = CVAR2("sv_stopspeed","100");
     44 cvar_t	sv_gravity = CVAR4("sv_gravity","800",false,true);
     45 cvar_t	sv_maxvelocity = CVAR2("sv_maxvelocity","2000");
     46 cvar_t	sv_nostep = CVAR2("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<sv.num_edicts ; e++, check = NEXT_EDICT(check))
     69 	{
     70 		if (check->free)
     71 			continue;
     72 		if (check->u.v.movetype == MOVETYPE_PUSH
     73 		|| check->u.v.movetype == MOVETYPE_NONE
     74 #ifdef QUAKE2
     75 		|| check->u.v.movetype == MOVETYPE_FOLLOW
     76 #endif
     77 		|| check->u.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->u.v.velocity[i]))
    100 		{
    101 			Con_Printf ("Got a NaN velocity on %s\n", pr_strings + ent->u.v.classname);
    102 			ent->u.v.velocity[i] = 0;
    103 		}
    104 		if (IS_NAN(ent->u.v.origin[i]))
    105 		{
    106 			Con_Printf ("Got a NaN origin on %s\n", pr_strings + ent->u.v.classname);
    107 			ent->u.v.origin[i] = 0;
    108 		}
    109 		if (ent->u.v.velocity[i] > sv_maxvelocity.value)
    110 			ent->u.v.velocity[i] = sv_maxvelocity.value;
    111 		else if (ent->u.v.velocity[i] < -sv_maxvelocity.value)
    112 			ent->u.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->u.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->u.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->u.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->u.v.touch && e1->u.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->u.v.touch);
    166 	}
    167 
    168 	if (e2->u.v.touch && e2->u.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->u.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->u.v.velocity, original_velocity);
    247 	VectorCopy (ent->u.v.velocity, primal_velocity);
    248 	numplanes = 0;
    249 
    250 	time_left = time;
    251 
    252 	for (bumpcount=0 ; bumpcount<numbumps ; bumpcount++)
    253 	{
    254 		if (!ent->u.v.velocity[0] && !ent->u.v.velocity[1] && !ent->u.v.velocity[2])
    255 			break;
    256 
    257 		for (i=0 ; i<3 ; i++)
    258 			end[i] = ent->u.v.origin[i] + time_left * ent->u.v.velocity[i];
    259 
    260 		trace = SV_Move (ent->u.v.origin, ent->u.v.mins, ent->u.v.maxs, end, false, ent);
    261 
    262 		if (trace.allsolid)
    263 		{	// entity is trapped in another solid
    264 			VectorCopy (vec3_origin, ent->u.v.velocity);
    265 			return 3;
    266 		}
    267 
    268 		if (trace.fraction > 0)
    269 		{	// actually covered some distance
    270 			VectorCopy (trace.endpos, ent->u.v.origin);
    271 			VectorCopy (ent->u.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->u.v.solid == SOLID_BSP)
    285 			{
    286 				ent->u.v.flags =	(int)ent->u.v.flags | FL_ONGROUND;
    287 				ent->u.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->u.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<numplanes ; i++)
    321 		{
    322 			ClipVelocity (original_velocity, planes[i], new_velocity, 1);
    323 			for (j=0 ; j<numplanes ; 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->u.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->u.v.velocity);
    343 				return 7;
    344 			}
    345 			CrossProduct (planes[0], planes[1], dir);
    346 			d = DotProduct (dir, ent->u.v.velocity);
    347 			VectorScale (dir, d, ent->u.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->u.v.velocity, primal_velocity) <= 0)
    355 		{
    356 			VectorCopy (vec3_origin, ent->u.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->u.v.gravity)
    377 		ent_gravity = ent->u.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->u.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->u.v.origin, push, end);
    414 
    415 	if (ent->u.v.movetype == MOVETYPE_FLYMISSILE)
    416 		trace = SV_Move (ent->u.v.origin, ent->u.v.mins, ent->u.v.maxs, end, MOVE_MISSILE, ent);
    417 	else if (ent->u.v.solid == SOLID_TRIGGER || ent->u.v.solid == SOLID_NOT)
    418 	// only clip against bmodels
    419 		trace = SV_Move (ent->u.v.origin, ent->u.v.mins, ent->u.v.maxs, end, MOVE_NOMONSTERS, ent);
    420 	else
    421 		trace = SV_Move (ent->u.v.origin, ent->u.v.mins, ent->u.v.maxs, end, MOVE_NORMAL, ent);
    422 
    423 	VectorCopy (trace.endpos, ent->u.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->u.v.velocity[0] && !pusher->u.v.velocity[1] && !pusher->u.v.velocity[2])
    450 	{
    451 		pusher->u.v.ltime += movetime;
    452 		return;
    453 	}
    454 
    455 	for (i=0 ; i<3 ; i++)
    456 	{
    457 		move[i] = pusher->u.v.velocity[i] * movetime;
    458 		mins[i] = pusher->u.v.absmin[i] + move[i];
    459 		maxs[i] = pusher->u.v.absmax[i] + move[i];
    460 	}
    461 
    462 	VectorCopy (pusher->u.v.origin, pushorig);
    463 
    464 // move the pusher to it's final position
    465 
    466 	VectorAdd (pusher->u.v.origin, move, pusher->u.v.origin);
    467 	pusher->u.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<sv.num_edicts ; e++, check = NEXT_EDICT(check))
    475 	{
    476 		if (check->free)
    477 			continue;
    478 		if (check->u.v.movetype == MOVETYPE_PUSH
    479 		|| check->u.v.movetype == MOVETYPE_NONE
    480 #ifdef QUAKE2
    481 		|| check->u.v.movetype == MOVETYPE_FOLLOW
    482 #endif
    483 		|| check->u.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->u.v.flags & FL_ONGROUND)
    488 		&& PROG_TO_EDICT(check->u.v.groundentity) == pusher) )
    489 		{
    490 			if ( check->u.v.absmin[0] >= maxs[0]
    491 			|| check->u.v.absmin[1] >= maxs[1]
    492 			|| check->u.v.absmin[2] >= maxs[2]
    493 			|| check->u.v.absmax[0] <= mins[0]
    494 			|| check->u.v.absmax[1] <= mins[1]
    495 			|| check->u.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->u.v.movetype != MOVETYPE_WALK)
    505 			check->u.v.flags = (int)check->u.v.flags & ~FL_ONGROUND;
    506 
    507 		VectorCopy (check->u.v.origin, entorig);
    508 		VectorCopy (check->u.v.origin, moved_from[num_moved]);
    509 		moved_edict[num_moved] = check;
    510 		num_moved++;
    511 
    512 		// try moving the contacted entity
    513 		pusher->u.v.solid = SOLID_NOT;
    514 		SV_PushEntity (check, move);
    515 		pusher->u.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->u.v.mins[0] == check->u.v.maxs[0])
    522 				continue;
    523 			if (check->u.v.solid == SOLID_NOT || check->u.v.solid == SOLID_TRIGGER)
    524 			{	// corpse
    525 				check->u.v.mins[0] = check->u.v.mins[1] = 0;
    526 				VectorCopy (check->u.v.mins, check->u.v.maxs);
    527 				continue;
    528 			}
    529 
    530 			VectorCopy (entorig, check->u.v.origin);
    531 			SV_LinkEdict (check, true);
    532 
    533 			VectorCopy (pushorig, pusher->u.v.origin);
    534 			SV_LinkEdict (pusher, false);
    535 			pusher->u.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->u.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->u.v.blocked);
    544 			}
    545 
    546 		// move back any entities we already moved
    547 			for (i=0 ; i<num_moved ; i++)
    548 			{
    549 				VectorCopy (moved_from[i], moved_edict[i]->u.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->u.v.avelocity[0] && !pusher->u.v.avelocity[1] && !pusher->u.v.avelocity[2])
    579 	{
    580 		pusher->u.v.ltime += movetime;
    581 		return;
    582 	}
    583 
    584 	for (i=0 ; i<3 ; i++)
    585 		amove[i] = pusher->u.v.avelocity[i] * movetime;
    586 
    587 	VectorSubtract (vec3_origin, amove, a);
    588 	AngleVectors (a, forward, right, up);
    589 
    590 	VectorCopy (pusher->u.v.angles, pushorig);
    591 
    592 // move the pusher to it's final position
    593 
    594 	VectorAdd (pusher->u.v.angles, amove, pusher->u.v.angles);
    595 	pusher->u.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<sv.num_edicts ; e++, check = NEXT_EDICT(check))
    603 	{
    604 		if (check->free)
    605 			continue;
    606 		if (check->u.v.movetype == MOVETYPE_PUSH
    607 		|| check->u.v.movetype == MOVETYPE_NONE
    608 		|| check->u.v.movetype == MOVETYPE_FOLLOW
    609 		|| check->u.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->u.v.flags & FL_ONGROUND)
    614 		&& PROG_TO_EDICT(check->u.v.groundentity) == pusher) )
    615 		{
    616 			if ( check->u.v.absmin[0] >= pusher->u.v.absmax[0]
    617 			|| check->u.v.absmin[1] >= pusher->u.v.absmax[1]
    618 			|| check->u.v.absmin[2] >= pusher->u.v.absmax[2]
    619 			|| check->u.v.absmax[0] <= pusher->u.v.absmin[0]
    620 			|| check->u.v.absmax[1] <= pusher->u.v.absmin[1]
    621 			|| check->u.v.absmax[2] <= pusher->u.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->u.v.movetype != MOVETYPE_WALK)
    631 			check->u.v.flags = (int)check->u.v.flags & ~FL_ONGROUND;
    632 
    633 		VectorCopy (check->u.v.origin, entorig);
    634 		VectorCopy (check->u.v.origin, moved_from[num_moved]);
    635 		moved_edict[num_moved] = check;
    636 		num_moved++;
    637 
    638 		// calculate destination position
    639 		VectorSubtract (check->u.v.origin, pusher->u.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->u.v.solid = SOLID_NOT;
    647 		SV_PushEntity (check, move);
    648 		pusher->u.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->u.v.mins[0] == check->u.v.maxs[0])
    655 				continue;
    656 			if (check->u.v.solid == SOLID_NOT || check->u.v.solid == SOLID_TRIGGER)
    657 			{	// corpse
    658 				check->u.v.mins[0] = check->u.v.mins[1] = 0;
    659 				VectorCopy (check->u.v.mins, check->u.v.maxs);
    660 				continue;
    661 			}
    662 
    663 			VectorCopy (entorig, check->u.v.origin);
    664 			SV_LinkEdict (check, true);
    665 
    666 			VectorCopy (pushorig, pusher->u.v.angles);
    667 			SV_LinkEdict (pusher, false);
    668 			pusher->u.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->u.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->u.v.blocked);
    677 			}
    678 
    679 		// move back any entities we already moved
    680 			for (i=0 ; i<num_moved ; i++)
    681 			{
    682 				VectorCopy (moved_from[i], moved_edict[i]->u.v.origin);
    683 				VectorSubtract (moved_edict[i]->u.v.angles, amove, moved_edict[i]->u.v.angles);
    684 				SV_LinkEdict (moved_edict[i], false);
    685 			}
    686 			return;
    687 		}
    688 		else
    689 		{
    690 			VectorAdd (check->u.v.angles, amove, check->u.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->u.v.ltime;
    711 
    712 	thinktime = ent->u.v.nextthink;
    713 	if (thinktime < ent->u.v.ltime + host_frametime)
    714 	{
    715 		movetime = thinktime - ent->u.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->u.v.avelocity[0] || ent->u.v.avelocity[1] || ent->u.v.avelocity[2])
    726 			SV_PushRotate (ent, movetime);
    727 		else
    728 #endif
    729 			SV_PushMove (ent, movetime);	// advances ent->u.v.ltime if not blocked
    730 	}
    731 
    732 	if (thinktime > oldltime && thinktime <= ent->u.v.ltime)
    733 	{
    734 		ent->u.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->u.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->u.v.origin, ent->u.v.oldorigin);
    771 		return;
    772 	}
    773 
    774 	VectorCopy (ent->u.v.origin, org);
    775 	VectorCopy (ent->u.v.oldorigin, ent->u.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->u.v.origin[0] = org[0] + i;
    788 				ent->u.v.origin[1] = org[1] + j;
    789 				ent->u.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->u.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->u.v.origin[0];
    817 	point[1] = ent->u.v.origin[1];
    818 	point[2] = ent->u.v.origin[2] + ent->u.v.mins[2] + 1;
    819 
    820 	ent->u.v.waterlevel = 0;
    821 	ent->u.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->u.v.watertype = cont;
    829 		ent->u.v.waterlevel = 1;
    830 		point[2] = ent->u.v.origin[2] + (ent->u.v.mins[2] + ent->u.v.maxs[2])*0.5;
    831 		cont = SV_PointContents (point);
    832 		if (cont <= CONTENTS_WATER)
    833 		{
    834 			ent->u.v.waterlevel = 2;
    835 			point[2] = ent->u.v.origin[2] + ent->u.v.view_ofs[2];
    836 			cont = SV_PointContents (point);
    837 			if (cont <= CONTENTS_WATER)
    838 				ent->u.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->u.v.basevelocity, 150.0*ent->u.v.waterlevel/3.0, current_table[CONTENTS_CURRENT_0 - truecont], ent->u.v.basevelocity);
    854 		}
    855 #endif
    856 	}
    857 
    858 	return ent->u.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->u.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->u.v.velocity);
    882 	VectorScale (trace->plane.normal, i, into);
    883 	VectorSubtract (ent->u.v.velocity, into, side);
    884 
    885 	ent->u.v.velocity[0] = side[0] * (1 + d);
    886 	ent->u.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->u.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->u.v.velocity[0] = oldvel[0];
    931 		ent->u.v. velocity[1] = oldvel[1];
    932 		ent->u.v. velocity[2] = 0;
    933 		clip = SV_FlyMove (ent, 0.1, &steptrace);
    934 
    935 		if ( fabs(oldorg[1] - ent->u.v.origin[1]) > 4
    936 		|| fabs(oldorg[0] - ent->u.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->u.v.origin);
    944 	}
    945 
    946 	VectorCopy (vec3_origin, ent->u.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->u.v.flags & FL_ONGROUND;
    971 	ent->u.v.flags = (int)ent->u.v.flags & ~FL_ONGROUND;
    972 
    973 	VectorCopy (ent->u.v.origin, oldorg);
    974 	VectorCopy (ent->u.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->u.v.waterlevel == 0)
    982 		return;		// don't stair up while jumping
    983 
    984 	if (ent->u.v.movetype != MOVETYPE_WALK)
    985 		return;		// gibbed by a trigger
    986 
    987 	if (sv_nostep.value)
    988 		return;
    989 
    990 	if ( (int)sv_player->u.v.flags & FL_WATERJUMP )
    991 		return;
    992 
    993 	VectorCopy (ent->u.v.origin, nosteporg);
    994 	VectorCopy (ent->u.v.velocity, nostepvel);
    995 
    996 //
    997 // try moving up and forward to go up a step
    998 //
    999 	VectorCopy (oldorg, ent->u.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->u.v.velocity[0] = oldvel[0];
   1011 	ent->u.v. velocity[1] = oldvel[1];
   1012 	ent->u.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->u.v.origin[1]) < 0.03125
   1020 		&& fabs(oldorg[0] - ent->u.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->u.v.solid == SOLID_BSP)
   1036 		{
   1037 			ent->u.v.flags =	(int)ent->u.v.flags | FL_ONGROUND;
   1038 			ent->u.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->u.v.origin);
   1047 		VectorCopy (nostepvel, ent->u.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->u.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->u.v.flags & FL_WATERJUMP) )
   1090 			SV_AddGravity (ent);
   1091 		SV_CheckStuck (ent);
   1092 #ifdef QUAKE2
   1093 		VectorAdd (ent->u.v.velocity, ent->u.v.basevelocity, ent->u.v.velocity);
   1094 #endif
   1095 		SV_WalkMove (ent);
   1096 
   1097 #ifdef QUAKE2
   1098 		VectorSubtract (ent->u.v.velocity, ent->u.v.basevelocity, ent->u.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->u.v.origin, host_frametime, ent->u.v.velocity, ent->u.v.origin);
   1117 		break;
   1118 
   1119 	default:
   1120 		Sys_Error ("SV_Physics_client: bad movetype %i", (int)ent->u.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->u.v.aiment)->u.v.origin, ent->u.v.v_angle, ent->u.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->u.v.angles, host_frametime, ent->u.v.avelocity, ent->u.v.angles);
   1179 	VectorMA (ent->u.v.origin, host_frametime, ent->u.v.velocity, ent->u.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->u.v.origin[0];
   1205 	point[1] = ent->u.v.origin[1];
   1206 	point[2] = ent->u.v.origin[2] + ent->u.v.mins[2] + 1;
   1207 	cont = SV_PointContents (point);
   1208 #else
   1209 	cont = SV_PointContents (ent->u.v.origin);
   1210 #endif
   1211 	if (!ent->u.v.watertype)
   1212 	{	// just spawned here
   1213 		ent->u.v.watertype = cont;
   1214 		ent->u.v.waterlevel = 1;
   1215 		return;
   1216 	}
   1217 
   1218 	if (cont <= CONTENTS_WATER)
   1219 	{
   1220 		if (ent->u.v.watertype == CONTENTS_EMPTY)
   1221 		{	// just crossed into water
   1222 			SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1);
   1223 		}
   1224 		ent->u.v.watertype = cont;
   1225 		ent->u.v.waterlevel = 1;
   1226 	}
   1227 	else
   1228 	{
   1229 		if (ent->u.v.watertype != CONTENTS_EMPTY)
   1230 		{	// just crossed into water
   1231 			SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1);
   1232 		}
   1233 		ent->u.v.watertype = CONTENTS_EMPTY;
   1234 		ent->u.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->u.v.groundentity);
   1254 	if ((int)groundentity->u.v.flags & FL_CONVEYOR)
   1255 		VectorScale(groundentity->u.v.movedir, groundentity->u.v.speed, ent->u.v.basevelocity);
   1256 	else
   1257 		VectorCopy(vec_origin, ent->u.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->u.v.velocity[2] > 0)
   1266 		ent->u.v.flags = (int)ent->u.v.flags & ~FL_ONGROUND;
   1267 
   1268 	if ( ((int)ent->u.v.flags & FL_ONGROUND) )
   1269 //@@
   1270 		if (VectorCompare(ent->u.v.basevelocity, vec_origin))
   1271 			return;
   1272 
   1273 	SV_CheckVelocity (ent);
   1274 
   1275 // add gravity
   1276 	if (! ((int)ent->u.v.flags & FL_ONGROUND)
   1277 		&& ent->u.v.movetype != MOVETYPE_FLY
   1278 		&& ent->u.v.movetype != MOVETYPE_BOUNCEMISSILE
   1279 		&& ent->u.v.movetype != MOVETYPE_FLYMISSILE)
   1280 			SV_AddGravity (ent);
   1281 
   1282 #else
   1283 // if onground, return without moving
   1284 	if ( ((int)ent->u.v.flags & FL_ONGROUND) )
   1285 		return;
   1286 
   1287 	SV_CheckVelocity (ent);
   1288 
   1289 // add gravity
   1290 	if (ent->u.v.movetype != MOVETYPE_FLY
   1291 	&& ent->u.v.movetype != MOVETYPE_FLYMISSILE)
   1292 		SV_AddGravity (ent);
   1293 #endif
   1294 
   1295 // move angles
   1296 	VectorMA (ent->u.v.angles, host_frametime, ent->u.v.avelocity, ent->u.v.angles);
   1297 
   1298 // move origin
   1299 #ifdef QUAKE2
   1300 	VectorAdd (ent->u.v.velocity, ent->u.v.basevelocity, ent->u.v.velocity);
   1301 #endif
   1302 	VectorScale (ent->u.v.velocity, host_frametime, move);
   1303 	trace = SV_PushEntity (ent, move);
   1304 #ifdef QUAKE2
   1305 	VectorSubtract (ent->u.v.velocity, ent->u.v.basevelocity, ent->u.v.velocity);
   1306 #endif
   1307 	if (trace.fraction == 1)
   1308 		return;
   1309 	if (ent->free)
   1310 		return;
   1311 
   1312 	if (ent->u.v.movetype == MOVETYPE_BOUNCE)
   1313 		backoff = 1.5;
   1314 #ifdef QUAKE2
   1315 	else if (ent->u.v.movetype == MOVETYPE_BOUNCEMISSILE)
   1316 		backoff = 2.0;
   1317 #endif
   1318 	else
   1319 		backoff = 1;
   1320 
   1321 	ClipVelocity (ent->u.v.velocity, trace.plane.normal, ent->u.v.velocity, backoff);
   1322 
   1323 // stop if on ground
   1324 	if (trace.plane.normal[2] > 0.7)
   1325 	{
   1326 #ifdef QUAKE2
   1327 		if (ent->u.v.velocity[2] < 60 || (ent->u.v.movetype != MOVETYPE_BOUNCE && ent->u.v.movetype != MOVETYPE_BOUNCEMISSILE))
   1328 #else
   1329 		if (ent->u.v.velocity[2] < 60 || ent->u.v.movetype != MOVETYPE_BOUNCE)
   1330 #endif
   1331 		{
   1332 			ent->u.v.flags = (int)ent->u.v.flags | FL_ONGROUND;
   1333 			ent->u.v.groundentity = EDICT_TO_PROG(trace.ent);
   1334 			VectorCopy (vec3_origin, ent->u.v.velocity);
   1335 			VectorCopy (vec3_origin, ent->u.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->u.v.groundentity);
   1374 	if ((int)groundentity->u.v.flags & FL_CONVEYOR)
   1375 		VectorScale(groundentity->u.v.movedir, groundentity->u.v.speed, ent->u.v.basevelocity);
   1376 	else
   1377 		VectorCopy(vec_origin, ent->u.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->u.v.flags & FL_ONGROUND;
   1386 //	ent->u.v.flags = (int)ent->u.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->u.v.flags & FL_FLY))
   1394 			if (!(((int)ent->u.v.flags & FL_SWIM) && (ent->u.v.waterlevel > 0)))
   1395 			{
   1396 				if (ent->u.v.velocity[2] < sv_gravity.value*-0.1)
   1397 					hitsound = true;
   1398 				if (!inwater)
   1399 					SV_AddGravity (ent);
   1400 			}
   1401 
   1402 	if (!VectorCompare(ent->u.v.velocity, vec_origin) || !VectorCompare(ent->u.v.basevelocity, vec_origin))
   1403 	{
   1404 		ent->u.v.flags = (int)ent->u.v.flags & ~FL_ONGROUND;
   1405 		// apply friction
   1406 		// let dead monsters who aren't completely onground slide
   1407 		if (wasonground)
   1408 			if (!(ent->u.v.health <= 0.0 && !SV_CheckBottom(ent)))
   1409 			{
   1410 				vel = ent->u.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->u.v.velocity, ent->u.v.basevelocity, ent->u.v.velocity);
   1429 		SV_FlyMove (ent, host_frametime, NULL);
   1430 		VectorSubtract (ent->u.v.velocity, ent->u.v.basevelocity, ent->u.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->u.v.origin, ent->u.v.mins, mins);
   1438 			VectorAdd (ent->u.v.origin, ent->u.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->u.v.flags = (int)ent->u.v.flags | FL_ONGROUND;
   1449 						break;
   1450 					}
   1451 				}
   1452 
   1453 		}
   1454 
   1455 		SV_LinkEdict (ent, true);
   1456 
   1457 		if ((int)ent->u.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->u.v.flags & (FL_ONGROUND | FL_FLY | FL_SWIM) ) )
   1474 	{
   1475 		if (ent->u.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->u.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<sv.num_edicts ; i++, ent = NEXT_EDICT(ent))
   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->u.v.movetype == MOVETYPE_PUSH)
   1537 			SV_Physics_Pusher (ent);
   1538 		else if (ent->u.v.movetype == MOVETYPE_NONE)
   1539 			SV_Physics_None (ent);
   1540 #ifdef QUAKE2
   1541 		else if (ent->u.v.movetype == MOVETYPE_FOLLOW)
   1542 			SV_Physics_Follow (ent);
   1543 #endif
   1544 		else if (ent->u.v.movetype == MOVETYPE_NOCLIP)
   1545 			SV_Physics_Noclip (ent);
   1546 		else if (ent->u.v.movetype == MOVETYPE_STEP)
   1547 			SV_Physics_Step (ent);
   1548 		else if (ent->u.v.movetype == MOVETYPE_TOSS
   1549 		|| ent->u.v.movetype == MOVETYPE_BOUNCE
   1550 #ifdef QUAKE2
   1551 		|| ent->u.v.movetype == MOVETYPE_BOUNCEMISSILE
   1552 #endif
   1553 		|| ent->u.v.movetype == MOVETYPE_FLY
   1554 		|| ent->u.v.movetype == MOVETYPE_FLYMISSILE)
   1555 			SV_Physics_Toss (ent);
   1556 		else
   1557 			Sys_Error ("SV_Physics: bad movetype %i", (int)ent->u.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->u.v.angles, host_frametime, tent->u.v.avelocity, tent->u.v.angles);
   1590 		VectorScale (tent->u.v.velocity, host_frametime, move);
   1591 		VectorAdd (tent->u.v.origin, move, end);
   1592 		trace = SV_Move (tent->u.v.origin, tent->u.v.mins, tent->u.v.maxs, end, MOVE_NORMAL, tent);
   1593 		VectorCopy (trace.endpos, tent->u.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->u.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
   1618