Spectator Free Move Through Entities


(ensiform) #1

ET uses this method:

void trap_TraceNoEnts( trace_t *results, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int passEntityNum, int contentmask ) {
	syscall( G_TRACE, results, start, mins, maxs, end, -2, contentmask );
}

is the -2 hard coded for passEntityNum somewhere in SV_ClipMoveToEntities? or is there some other way i can ignore all entities in the server module if i was to do something similar because -2 doesn’t seem to really do anything (at least for doors/and brush entitties). For JK3.


(Jaquboss) #2

-2 is world, -1 is none
try editing contentmask instead


(ensiform) #3

-2 may be world for ET but even in q3 engine I do not see where -2 would be parsed here:

/*
====================
SV_ClipMoveToEntities

====================
*/
void SV_ClipMoveToEntities( moveclip_t *clip ) {
	int			i, num;
	int			touchlist[MAX_GENTITIES];
	sharedEntity_t *touch;
	int			passOwnerNum;
	trace_t		trace;
	clipHandle_t	clipHandle;
	float		*origin, *angles;

	num = SV_AreaEntities( clip->boxmins, clip->boxmaxs, touchlist, MAX_GENTITIES);

	if ( clip->passEntityNum != ENTITYNUM_NONE ) {
		passOwnerNum = ( SV_GentityNum( clip->passEntityNum ) )->r.ownerNum;
		if ( passOwnerNum == ENTITYNUM_NONE ) {
			passOwnerNum = -1;
		}
	} else {
		passOwnerNum = -1;
	}

	for ( i=0 ; i<num ; i++ ) {
		if ( clip->trace.allsolid ) {
			return;
		}
		touch = SV_GentityNum( touchlist[i] );

		// see if we should ignore this entity
		if ( clip->passEntityNum != ENTITYNUM_NONE ) {
			if ( touchlist[i] == clip->passEntityNum ) {
				continue;	// don't clip against the pass entity
			}
			if ( touch->r.ownerNum == clip->passEntityNum ) {
				continue;	// don't clip against own missiles
			}
			if ( touch->r.ownerNum == passOwnerNum ) {
				continue;	// don't clip against other missiles from our owner
			}
		}

		// if it doesn't have any brushes of a type we
		// are looking for, ignore it
		if ( ! ( clip->contentmask & touch->r.contents ) ) {
			continue;
		}

		// might intersect, so do an exact clip
		clipHandle = SV_ClipHandleForEntity (touch);

		origin = touch->r.currentOrigin;
		angles = touch->r.currentAngles;


		if ( !touch->r.bmodel ) {
			angles = vec3_origin;	// boxes don't rotate
		}

		CM_TransformedBoxTrace ( &trace, (float *)clip->start, (float *)clip->end,
			(float *)clip->mins, (float *)clip->maxs, clipHandle,  clip->contentmask,
			origin, angles, clip->capsule);

		if ( trace.allsolid ) {
			clip->trace.allsolid = qtrue;
			trace.entityNum = touch->s.number;
		} else if ( trace.startsolid ) {
			clip->trace.startsolid = qtrue;
			trace.entityNum = touch->s.number;
		}

		if ( trace.fraction < clip->trace.fraction ) {
			qboolean	oldStart;

			// make sure we keep a startsolid from a previous trace
			oldStart = clip->trace.startsolid;

			trace.entityNum = touch->s.number;
			clip->trace = trace;
			clip->trace.startsolid |= oldStart;
		}
	}
}

but then again it might know -2 is the world somehow and the fact that JK2 and JK3 use a really old version of the q3 engine that the old rcon bug still exists among other things.


(ensiform) #4

okay so i hacked up another version of trap_Trace called trap_TraceSpec and it works flawlessly especially with CG_Trace_World in client. If a player doesn’t have the client they will only notice a slight lag in door but thats it and it may have just been due to my test server being crappy.

but:

typedef struct content_save_s {
	int entityNum;
	int contents;
} content_save_t;

content_save_t content_save[MAX_GENTITIES];

void trap_TraceSpec( trace_t *results, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int passEntityNum, int contentmask ) {
	static int i, j; //this gets called a lot, make it static
	static int reset;
	static int done;

	done = 0;
	j = 0; //count number of entities in the save array
	for ( i = 0; i < MAX_GENTITIES; i++ )
	{ // save contents and change as appropriate
		if ( i == passEntityNum ) continue;
		if ( i == ENTITYNUM_WORLD ) continue;
		if ( i == ENTITYNUM_NONE ) continue;
		if ( g_entities[i].r.contents )
		{ // there are some strange situations where contents can get over-written twice... sigh
			content_save[j].entityNum = i;
			content_save[j].contents = g_entities[i].r.contents;
			j++;
			g_entities[i].r.contents = 0;
		}
	}

	syscall( G_TRACE, results, start, mins, maxs, end, passEntityNum, contentmask, 0, 10 );

	//consider results
	while ( results->fraction < 1.0 || results->startsolid ) // add start solid test????
	{
		if (results->entityNum != ENTITYNUM_WORLD && results->entityNum != ENTITYNUM_NONE )
		{ // hit a real entity
			if ( g_entities[results->entityNum].r.contents )
			{ // there are some strange situations where contents can get over-written twice... sigh
				content_save[j].entityNum = results->entityNum;
				content_save[j].contents = g_entities[results->entityNum].r.contents;
				j++;
				g_entities[results->entityNum].r.contents = 0; // change contents of hit entity and run trace again
			}	
		}
		else
		{
			done = 1; // hit world or nothing so proceed...
		}			

		if ( done )
		{
			break; //while
		}
		syscall( G_TRACE, results, start, mins, maxs, end, passEntityNum, contentmask, 0, 10 );
	}

	// now reset all entity contents that have been saved
	for ( i = 0; i < j; i++ )
	{
		g_entities[content_save[i].entityNum].r.contents = content_save[i].contents;
	}
}

the extra 0, 10 in G_TRACE syscall is just some extra stuff for ghoul2 system.