944 lines · 20.3 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <stdio.h>#include "../dat.h"#include "../fns.h" /*  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. onground is set for toss objects when they come to a complete rest.  it is set for steping or walking objects  doors, plats, etc are SOLID_BSP, and MOVETYPE_PUSHbonus items are SOLID_TRIGGER touch, and MOVETYPE_TOSScorpses are SOLID_NOT and MOVETYPE_TOSScrates are SOLID_BBOX and MOVETYPE_TOSSwalking monsters are SOLID_SLIDEBOX and MOVETYPE_STEPflying/floating monsters are SOLID_SLIDEBOX and MOVETYPE_FLY solid_edge items only clip against bsp models. */  /*============SV_TestEntityPosition ============*/edict_t	*SV_TestEntityPosition (edict_t *ent){	trace_t	trace;	int		mask; 	if (ent->clipmask)		mask = ent->clipmask;	else		mask = MASK_SOLID;	trace = gi.trace (ent->s.origin, ent->mins, ent->maxs, ent->s.origin, ent, mask);		if (trace.startsolid)		return g_edicts;			return NULL;}  /*================SV_CheckVelocity================*/void SV_CheckVelocity (edict_t *ent){	int		i; //// bound velocity//	for (i=0 ; i<3 ; i++)	{		if (ent->velocity[i] > sv_maxvelocity->value)			ent->velocity[i] = sv_maxvelocity->value;		else if (ent->velocity[i] < -sv_maxvelocity->value)			ent->velocity[i] = -sv_maxvelocity->value;	}} /*=============SV_RunThink Runs thinking code for this frame if necessary=============*/qboolean SV_RunThink (edict_t *ent){	float	thinktime; 	thinktime = ent->nextthink;	if (thinktime <= 0)		return true;	if (thinktime > level.time+0.001)		return true;		ent->nextthink = 0;	if (!ent->think)		gi.error ("NULL ent->think");	ent->think (ent); 	return false;} /*==================SV_Impact Two entities have touched, so run their touch functions==================*/void SV_Impact (edict_t *e1, trace_t *trace){	edict_t		*e2;//	cplane_t	backplane; 	e2 = trace->ent; 	if (e1->touch && e1->solid != SOLID_NOT)		e1->touch (e1, e2, &trace->plane, trace->surface);		if (e2->touch && e2->solid != SOLID_NOT)		e2->touch (e2, e1, NULL, NULL);}  /*==================ClipVelocity Slide off of the impacting objectreturns the blocked flags (1 = floor, 2 = step / wall)==================*/#define	STOP_EPSILON	0.1 int ClipVelocity (vec3_t in, vec3_t normal, vec3_t out, float overbounce){	float	backoff;	float	change;	int		i, blocked;		blocked = 0;	if (normal[2] > 0)		blocked |= 1;		// floor	if (!normal[2])		blocked |= 2;		// step		backoff = DotProduct (in, normal) * overbounce; 	for (i=0 ; i<3 ; i++)	{		change = normal[i]*backoff;		out[i] = in[i] - change;		if (out[i] > -STOP_EPSILON && out[i] < STOP_EPSILON)			out[i] = 0;	} 	return blocked;}  /*============SV_FlyMove The basic solid body movement clip that slides along multiple planesReturns the clipflags if the velocity was modified (hit something solid)1 = floor2 = wall / step4 = dead stop============*/#define	MAX_CLIP_PLANES	5int SV_FlyMove (edict_t *ent, float time, int mask){	edict_t		*hit;	int			bumpcount, numbumps;	vec3_t		dir;	float		d;	int			numplanes;	vec3_t		planes[MAX_CLIP_PLANES];	vec3_t		primal_velocity, original_velocity, new_velocity;	int			i, j;	trace_t		trace;	vec3_t		end;	float		time_left;	int			blocked;		numbumps = 4;		blocked = 0;	VectorCopy (ent->velocity, original_velocity);	VectorCopy (ent->velocity, primal_velocity);	numplanes = 0;		time_left = time; 	ent->groundentity = NULL;	for (bumpcount=0 ; bumpcount<numbumps ; bumpcount++)	{		for (i=0 ; i<3 ; i++)			end[i] = ent->s.origin[i] + time_left * ent->velocity[i]; 		trace = gi.trace (ent->s.origin, ent->mins, ent->maxs, end, ent, mask); 		if (trace.allsolid)		{	// entity is trapped in another solid			VectorCopy (vec3_origin, ent->velocity);			return 3;		} 		if (trace.fraction > 0)		{	// actually covered some distance			VectorCopy (trace.endpos, ent->s.origin);			VectorCopy (ent->velocity, original_velocity);			numplanes = 0;		} 		if (trace.fraction == 1)			 break;		// moved the entire distance 		hit = trace.ent; 		if (trace.plane.normal[2] > 0.7)		{			blocked |= 1;		// floor			if ( hit->solid == SOLID_BSP)			{				ent->groundentity = hit;				ent->groundentity_linkcount = hit->linkcount;			}		}		if (!trace.plane.normal[2])		{			blocked |= 2;		// step		} //// run the impact function//		SV_Impact (ent, &trace);		if (!ent->inuse)			break;		// removed by the impact function 				time_left -= time_left * trace.fraction;			// cliped to another plane		if (numplanes >= MAX_CLIP_PLANES)		{	// this shouldn't really happen			VectorCopy (vec3_origin, ent->velocity);			return 3;		} 		VectorCopy (trace.plane.normal, planes[numplanes]);		numplanes++; //// modify original_velocity so it parallels all of the clip planes//		for (i=0 ; i<numplanes ; i++)		{			ClipVelocity (original_velocity, planes[i], new_velocity, 1); 			for (j=0 ; j<numplanes ; j++)				if ((j != i) && !VectorCompare (planes[i], planes[j]))				{					if (DotProduct (new_velocity, planes[j]) < 0)						break;	// not ok				}			if (j == numplanes)				break;		}				if (i != numplanes)		{	// go along this plane			VectorCopy (new_velocity, ent->velocity);		}		else		{	// go along the crease			if (numplanes != 2)			{//				gi.dprintf ("clip velocity, numplanes == %i\n",numplanes);				VectorCopy (vec3_origin, ent->velocity);				return 7;			}			CrossProduct (planes[0], planes[1], dir);			d = DotProduct (dir, ent->velocity);			VectorScale (dir, d, ent->velocity);		} //// if original velocity is against the original velocity, stop dead// to avoid tiny occilations in sloping corners//		if (DotProduct (ent->velocity, primal_velocity) <= 0)		{			VectorCopy (vec3_origin, ent->velocity);			return blocked;		}	} 	return blocked;}  /*============SV_AddGravity ============*/void SV_AddGravity (edict_t *ent){	ent->velocity[2] -= ent->gravity * sv_gravity->value * FRAMETIME;} /*=============================================================================== PUSHMOVE ===============================================================================*/ /*============SV_PushEntity Does not change the entities velocity at all============*/trace_t SV_PushEntity (edict_t *ent, vec3_t push){	trace_t	trace;	vec3_t	start;	vec3_t	end;	int		mask; 	VectorCopy (ent->s.origin, start);	VectorAdd (start, push, end); retry:	if (ent->clipmask)		mask = ent->clipmask;	else		mask = MASK_SOLID; 	trace = gi.trace (start, ent->mins, ent->maxs, end, ent, mask);		VectorCopy (trace.endpos, ent->s.origin);	gi.linkentity (ent); 	if (trace.fraction != 1.0)	{		SV_Impact (ent, &trace); 		// if the pushed entity went away and the pusher is still there		if (!trace.ent->inuse && ent->inuse)		{			// move the pusher back and try again			VectorCopy (start, ent->s.origin);			gi.linkentity (ent);			goto retry;		}	} 	if (ent->inuse)		G_TouchTriggers (ent); 	return trace;}					  typedef struct{	edict_t	*ent;	vec3_t	origin;	vec3_t	angles;	float	deltayaw;} pushed_t;pushed_t	pushed[MAX_EDICTS], *pushed_p; edict_t	*obstacle; /*============SV_Push Objects need to be moved back on a failed push,otherwise riders would continue to slide.============*/qboolean SV_Push (edict_t *pusher, vec3_t move, vec3_t amove){	int			i, e;	edict_t		*check, *block;	vec3_t		mins, maxs;	pushed_t	*p;	vec3_t		org, org2, move2, forward, right, up; 	// clamp the move to 1/8 units, so the position will	// be accurate for client side prediction	for (i=0 ; i<3 ; i++)	{		float	temp;		temp = move[i]*8.0;		if (temp > 0.0)			temp += 0.5;		else			temp -= 0.5;		move[i] = 0.125 * (int)temp;	} 	// find the bounding box	for (i=0 ; i<3 ; i++)	{		mins[i] = pusher->absmin[i] + move[i];		maxs[i] = pusher->absmax[i] + move[i];	} // we need this for pushing things later	VectorSubtract (vec3_origin, amove, org);	AngleVectors (org, forward, right, up); // save the pusher's original position	pushed_p->ent = pusher;	VectorCopy (pusher->s.origin, pushed_p->origin);	VectorCopy (pusher->s.angles, pushed_p->angles);	if (pusher->client)		pushed_p->deltayaw = pusher->client->ps.pmove.delta_angles[YAW];	pushed_p++; // move the pusher to it's final position	VectorAdd (pusher->s.origin, move, pusher->s.origin);	VectorAdd (pusher->s.angles, amove, pusher->s.angles);	gi.linkentity (pusher); // see if any solid entities are inside the final position	check = g_edicts+1;	for (e = 1; e < globals.num_edicts; e++, check++)	{		if (!check->inuse)			continue;		if (check->movetype == MOVETYPE_PUSH		|| check->movetype == MOVETYPE_STOP		|| check->movetype == MOVETYPE_NONE		|| check->movetype == MOVETYPE_NOCLIP)			continue; 		if (!check->area.prev)			continue;		// not linked in anywhere 	// if the entity is standing on the pusher, it will definitely be moved		if (check->groundentity != pusher)		{			// see if the ent needs to be tested			if ( check->absmin[0] >= maxs[0]			|| check->absmin[1] >= maxs[1]			|| check->absmin[2] >= maxs[2]			|| check->absmax[0] <= mins[0]			|| check->absmax[1] <= mins[1]			|| check->absmax[2] <= mins[2] )				continue; 			// see if the ent's bbox is inside the pusher's final position			if (!SV_TestEntityPosition (check))				continue;		} 		if ((pusher->movetype == MOVETYPE_PUSH) || (check->groundentity == pusher))		{			// move this entity			pushed_p->ent = check;			VectorCopy (check->s.origin, pushed_p->origin);			VectorCopy (check->s.angles, pushed_p->angles);			pushed_p++; 			// try moving the contacted entity 			VectorAdd (check->s.origin, move, check->s.origin);			if (check->client)			{	// FIXME: doesn't rotate monsters?				check->client->ps.pmove.delta_angles[YAW] += amove[YAW];			} 			// figure movement due to the pusher's amove			VectorSubtract (check->s.origin, pusher->s.origin, org);			org2[0] = DotProduct (org, forward);			org2[1] = -DotProduct (org, right);			org2[2] = DotProduct (org, up);			VectorSubtract (org2, org, move2);			VectorAdd (check->s.origin, move2, check->s.origin); 			// may have pushed them off an edge			if (check->groundentity != pusher)				check->groundentity = NULL; 			block = SV_TestEntityPosition (check);			if (!block)			{	// pushed ok				gi.linkentity (check);				// impact?				continue;			} 			// if it is ok to leave in the old position, do it			// this is only relevent for riding entities, not pushed			// FIXME: this doesn't acount for rotation

Lines 1–500 of 944.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t