Beispiel #1
0
/**
 * @brief Clips the specified trace to other entities in its area. This is the basis of all
 * collision and interaction for the server. Tread carefully.
 */
static void Sv_ClipTraceToEntities(sv_trace_t *trace) {
	g_entity_t *e[MAX_ENTITIES];

	const size_t len = Sv_BoxEntities(trace->box_mins, trace->box_maxs, e, lengthof(e), BOX_COLLIDE);

	for (size_t i = 0; i < len; i++) {
		g_entity_t *ent = e[i];

		if (trace->skip) { // see if we can skip it

			if (ent == trace->skip) {
				continue;    // explicitly (ourselves)
			}

			if (ent->owner == trace->skip) {
				continue;    // or via ownership (we own it)
			}

			if (trace->skip->owner) {

				if (ent == trace->skip->owner) {
					continue;    // which is bidirectional (inverse of previous case)
				}

				if (ent->owner == trace->skip->owner) {
					continue;    // and commutative (we are both owned by the same)
				}
			}

			// triggers only clip to the world (while other entities can occupy triggers)
			if (trace->skip->solid == SOLID_TRIGGER) {

				if (ent->solid != SOLID_BSP) {
					continue;
				}
			}
		}

		const int32_t head_node = Sv_HullForEntity(ent);
		if (head_node != -1) {

			const sv_entity_t *sent = &sv.entities[NUM_FOR_ENTITY(ent)];

			const cm_trace_t tr = Cm_TransformedBoxTrace(
			                          trace->start, trace->end, trace->mins, trace->maxs, head_node, trace->contents,
			                          &sent->matrix, &sent->inverse_matrix);

			// check for a full or partial intersection
			if (tr.all_solid || tr.fraction < trace->trace.fraction) {

				trace->trace = tr;
				trace->trace.ent = ent;

				if (tr.all_solid) { // we were actually blocked
					return;
				}
			}
		}
	}
}
Beispiel #2
0
/*
 * Sv_PointContents
 *
 * Returns the contents mask for the specified point.  This includes world
 * contents as well as contents for any entities this point intersects.
 */
int Sv_PointContents(vec3_t point) {
	g_edict_t *touched[MAX_EDICTS];
	int i, contents, num;

	// get base contents from world
	contents = Cm_PointContents(point, sv.models[1]->head_node);

	// as well as contents from all intersected entities
	num = Sv_AreaEdicts(point, point, touched, MAX_EDICTS, AREA_SOLID);

	for (i = 0; i < num; i++) {

		const g_edict_t *touch = touched[i];
		const vec_t *angles;

		// might intersect, so do an exact clip
		const int head_node = Sv_HullForEntity(touch);

		if (touch->solid == SOLID_BSP) // bsp models can rotate
			angles = touch->s.angles;
		else
			angles = vec3_origin;

		contents |= Cm_TransformedPointContents(point, head_node,
				touch->s.origin, angles);
	}

	return contents;
}
Beispiel #3
0
/**
 * @brief Returns the contents mask for the specified point. This includes world
 * contents as well as contents for any solid entities this point intersects.
 */
int32_t Sv_PointContents(const vec3_t point) {
	g_entity_t *entities[MAX_ENTITIES];

	// get base contents from world
	int32_t contents = Cm_PointContents(point, 0);

	// as well as contents from all intersected entities
	const size_t len = Sv_BoxEntities(point, point, entities, lengthof(entities), BOX_COLLIDE);

	// iterate the area entities, checking each one for an intersection
	for (size_t i = 0; i < len; i++) {
		const g_entity_t *ent = entities[i];

		const int32_t head_node = Sv_HullForEntity(ent);
		if (head_node != -1) {

			const sv_entity_t *sent = &sv.entities[NUM_FOR_ENTITY(ent)];
			contents |= Cm_TransformedPointContents(point, head_node, &sent->inverse_matrix);
		}
	}

	return contents;
}
Beispiel #4
0
/*
 * Sv_ClipTraceToEntities
 *
 * Clips the specified trace to other entities in its area.  This is the basis
 * of ALL collision and interaction for the server.  Tread carefully.
 */
static void Sv_ClipTraceToEntities(sv_trace_t *trace) {
	g_edict_t *touched[MAX_EDICTS];
	vec_t *angles;
	c_trace_t tr;
	int i, num, head_node;

	// first resolve the entities found within our desired trace
	num = Sv_AreaEdicts(trace->box_mins, trace->box_maxs, touched, MAX_EDICTS,
			AREA_SOLID);

	// then iterate them, determining if they have any bearing on our trace
	for (i = 0; i < num; i++) {

		g_edict_t *touch = touched[i];

		if (touch->solid == SOLID_NOT) // can't actually touch us
			continue;

		if (trace->skip) { // see if we can skip it

			if (touch == trace->skip)
				continue; // explicitly (ourselves)

			if (touch->owner == trace->skip)
				continue; // or via ownership (we own it)

			if (trace->skip->owner) {

				if (touch == trace->skip->owner)
					continue; // which is bi-directional (inverse of previous case)

				if (touch->owner == trace->skip->owner)
					continue; // and communitive (we are both owned by the same)
			}
		}

		// we couldn't skip it, so trace to it and see if we hit
		head_node = Sv_HullForEntity(touch);

		if (touch->solid == SOLID_BSP) // bsp entities can rotate
			angles = touch->s.angles;
		else
			angles = vec3_origin;

		// perform the trace against this particular entity
		tr = Cm_TransformedBoxTrace(trace->start, trace->end, trace->mins,
				trace->maxs, head_node, trace->contentmask, touch->s.origin,
				angles);

		// check for a full or partial intersection
		if (tr.all_solid || tr.start_solid || tr.fraction
				< trace->trace.fraction) {

			trace->trace = tr;
			trace->trace.ent = touch;

			if (trace->trace.all_solid) // we were actually blocked
				return;
		}
	}
}