Example #1
0
/**
 * @brief Test if point is "visible" from team.
 * @param[in] team A team to test.
 * @param[in] point A point to check.
 * @return true if point is "visible"
 */
static bool G_TeamPointVis (int team, const vec3_t point)
{
	Edict *from = nullptr;
	vec3_t eye;

	/* test if point is visible from team */
	while ((from = G_EdictsGetNextLivingActorOfTeam(from, team))) {
		if (G_FrustumVis(from, point)) {
			/* get viewers eye height */
			G_ActorGetEyeVector(from, eye);

			/* line of sight */
			if (!G_TestLine(eye, point)) {
				const float distance = VectorDist(from->origin, point);
				bool blocked = false;
				/* check visibility in the smoke */
				if (distance >= UNIT_SIZE) {
					Edict *e = nullptr;
					while ((e = G_EdictsGetNextInUse(e))) {
						if (G_IsSmoke(e) && RayIntersectAABB(eye, point, e->absmin, e->absmax)) {
								blocked = true;
								break;
						}
					}
				}
				if (!blocked)
					return true;
			}
		}
	}

	/* not visible */
	return false;
}
Example #2
0
/**
 * @brief tests for smoke interference
 * @param[in] from The point to check visibility from
 * @param[in] check The edict to check visibility to
 * @return true if @c check is invisible from @c from (smoke is in the way), false otherwise.
 */
bool G_SmokeVis (const vec3_t from, const Edict* check)
{
	const float distance = VectorDist(check->origin, from);
	/* units that are very close are visible in the smoke */
	if (distance > UNIT_SIZE * 1.5f) {
		Edict* e = nullptr;

		while ((e = G_EdictsGetNextInUse(e))) {
			if (G_IsSmoke(e)) {
				if (RayIntersectAABB(from, check->absBox.mins, e->absBox)
				 || RayIntersectAABB(from, check->absBox.maxs, e->absBox)) {
					return true;
				}
			}
		}
	}
	return false;
}
Example #3
0
/**
 * @brief calculate how much check is "visible" from @c from
 * @param[in] from The world coordinate to check from
 * @param[in] ent The source edict of the check
 * @param[in] check The edict to check how good (or if at all) it is visible
 * @param[in] full Perform a full check in different directions. If this is
 * @c false the actor is fully visible if one vis check returned @c true. With
 * @c true this function can also return a value != 0.0 and != 1.0. Try to only
 * use @c true if you really need the full check. Full checks are of course
 * more expensive.
 * @return a value between 0.0 and 1.0 which reflects the visibility from 0
 * to 100 percent
 * @note This call isn't cheap - try to do this only if you really need the
 * visibility check or the statement whether one particular actor see another
 * particular actor.
 * @sa CL_ActorVis
 */
float G_ActorVis (const vec3_t from, const edict_t *ent, const edict_t *check, bool full)
{
	vec3_t test, dir;
	float delta;
	int i, n;
	const float distance = VectorDist(check->origin, ent->origin);

	/* units that are very close are visible in the smoke */
	if (distance > UNIT_SIZE * 1.5f) {
		vec3_t eyeEnt;
		edict_t *e = NULL;

		G_ActorGetEyeVector(ent, eyeEnt);

		while ((e = G_EdictsGetNext(e))) {
			if (G_IsSmoke(e)) {
				if (RayIntersectAABB(eyeEnt, check->absmin, e->absmin, e->absmax)
				 || RayIntersectAABB(eyeEnt, check->absmax, e->absmin, e->absmax)) {
					return ACTOR_VIS_0;
				}
			}
		}
	}

	/* start on eye height */
	VectorCopy(check->origin, test);
	if (G_IsDead(check)) {
		test[2] += PLAYER_DEAD;
		delta = 0;
	} else if (G_IsCrouched(check)) {
		test[2] += PLAYER_CROUCH - 2;
		delta = (PLAYER_CROUCH - PLAYER_MIN) / 2 - 2;
	} else {
		test[2] += PLAYER_STAND;
		delta = (PLAYER_STAND - PLAYER_MIN) / 2 - 2;
	}

	/* side shifting -> better checks */
	dir[0] = from[1] - check->origin[1];
	dir[1] = check->origin[0] - from[0];
	dir[2] = 0;
	VectorNormalizeFast(dir);
	VectorMA(test, -7, dir, test);

	/* do 3 tests */
	n = 0;
	for (i = 0; i < 3; i++) {
		if (!G_LineVis(from, test)) {
			if (full)
				n++;
			else
				return ACTOR_VIS_100;
		}

		/* look further down or stop */
		if (!delta) {
			if (n > 0)
				return ACTOR_VIS_100;
			else
				return ACTOR_VIS_0;
		}
		VectorMA(test, 7, dir, test);
		test[2] -= delta;
	}

	/* return factor */
	switch (n) {
	case 0:
		return ACTOR_VIS_0;
	case 1:
		return ACTOR_VIS_10;
	case 2:
		return ACTOR_VIS_50;
	default:
		return ACTOR_VIS_100;
	}
}