Пример #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;
				}
			}
		}
	}
}
Пример #2
0
/*
 * @brief Clips the specified trace to other solid entities in the frame.
 */
static void Cl_ClipTraceToEntities(cl_trace_t *trace) {

	for (uint16_t i = 0; i < cl.frame.num_entities; i++) {

		const uint32_t snum = (cl.frame.entity_state + i) & ENTITY_STATE_MASK;
		const entity_state_t *s = &cl.entity_states[snum];

		if (s->solid < SOLID_BOX)
			continue;

		if (s->number == trace->skip)
			continue;

		if (s->number == cl.client_num + 1)
			continue;

		const int32_t head_node = Cl_HullForEntity(s);
		const cl_entity_t *ent = &cl.entities[s->number];

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

		if (tr.start_solid || tr.fraction < trace->trace.fraction) {
			trace->trace = tr;
			trace->trace.ent = (struct g_entity_s *) (intptr_t) s->number;

			if (tr.start_solid)
				return;
		}
	}
}
Пример #3
0
/*
 * Cl_ClipMoveToEntities
 */
static void Cl_ClipMoveToEntities(vec3_t start, vec3_t mins, vec3_t maxs,
		vec3_t end, c_trace_t *tr) {
	int i;
	c_trace_t trace;
	int head_node;
	const float *angles;
	vec3_t bmins, bmaxs;

	for (i = 0; i < cl.frame.num_entities; i++) {
		const int num = (cl.frame.entity_state + i) & ENTITY_STATE_MASK;
		const entity_state_t *ent = &cl.entity_states[num];

		if (!ent->solid)
			continue;

		if (ent->number == cl.player_num + 1)
			continue;

		if (ent->solid == 31) { // special value for bmodel
			const c_model_t *model = cl.model_clip[ent->model1];
			if (!model)
				continue;
			head_node = model->head_node;
			angles = ent->angles;
		} else { // encoded bbox
			const int x = 8 * (ent->solid & 31);
			const int zd = 8 * ((ent->solid >> 5) & 31);
			const int zu = 8 * ((ent->solid >> 10) & 63) - 32;

			bmins[0] = bmins[1] = -x;
			bmaxs[0] = bmaxs[1] = x;
			bmins[2] = -zd;
			bmaxs[2] = zu;

			head_node = Cm_HeadnodeForBox(bmins, bmaxs);
			angles = vec3_origin; // boxes don't rotate
		}

		trace = Cm_TransformedBoxTrace(start, end, mins, maxs, head_node,
				MASK_PLAYER_SOLID, ent->origin, angles);

		if (trace.start_solid || trace.fraction < tr->fraction) {
			trace.ent = (struct g_edict_s *) ent;
			*tr = trace;
		}
	}
}
Пример #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;
		}
	}
}