Example #1
0
/**
 * @brief Find valid actor spawn fields for this player.
 * @note Already used spawn-point are not found because ent->type is changed in G_ClientTeamInfo.
 * @param[in] player The player to spawn the actors for.
 * @param[in] spawnType The type of spawn-point so search for (ET_ACTORSPAWN or ET_ACTOR2x2SPAWN)
 * @return A pointer to a found spawn point or NULL if nothing was found or on error.
 */
static edict_t *G_ClientGetFreeSpawnPoint (const player_t * player, int spawnType)
{
	edict_t *ent = NULL;

	/* Abort for non-spawnpoints */
	assert(spawnType == ET_ACTORSPAWN || spawnType == ET_ACTOR2x2SPAWN);

	if (level.randomSpawn) {
		edict_t *list[MAX_EDICTS];
		int count = 0;
		while ((ent = G_EdictsGetNext(ent)))
			if (ent->type == spawnType && player->pers.team == ent->team) {
				if (G_GetLivingActorFromPos(ent->pos))
					continue;
				list[count++] = ent;
			}

		if (count)
			return list[rand() % count];
	} else {
		while ((ent = G_EdictsGetNext(ent)))
			if (ent->type == spawnType && player->pers.team == ent->team) {
				if (G_GetLivingActorFromPos(ent->pos))
					continue;
				return ent;
			}
	}

	return NULL;
}
Example #2
0
/**
 * @brief Iterate through the entities that are in use
 * @note we can hopefully get rid of this function once we know when it makes sense
 * to iterate through entities that are NOT in use
 * @param lastEnt The entity found in the previous iteration; if nullptr, we start at the beginning
 */
Edict* G_EdictsGetNextInUse (Edict* lastEnt)
{
	Edict* ent = lastEnt;

	while ((ent = G_EdictsGetNext(ent))) {
		if (ent->inuse)
			break;
	}
	return ent;
}
Example #3
0
/**
 * @brief Searches the edict that has the given target as @c targetname set
 * @param target The target name of the edict that you are searching
 * @return @c NULL if no edict with the given target name was found, otherwise
 * the edict that has the targetname set you were looking for.
 */
edict_t *G_FindTargetEntity (const char *target)
{
    edict_t *ent = NULL;

    while ((ent = G_EdictsGetNext(ent))) {
        const char *n = ent->targetname;
        if (n && Q_streq(n, target))
            return ent;
    }

    return NULL;
}
Example #4
0
/**
 * @brief Find an entity that is not in use
 */
Edict* G_EdictsGetNewEdict (void)
{
	Edict* ent = nullptr;

	/* try to recycle an edict */
	while ((ent = G_EdictsGetNext(ent))) {
		if (!ent->inuse)
			return ent;
	}

	/* no unused edict found, create a new one */
	ent = &g_edicts[globals.num_edicts];
	globals.num_edicts++;
	if (globals.num_edicts > game.sv_maxentities)
		return nullptr;

	return ent;
}
Example #5
0
static void SVCmd_ListEdicts_f (void)
{
	Edict* ent = nullptr;
	int i = 0;
	Com_Printf("number | entnum | mapnum | type | inuse | pnum | team | size |  HP | state | classname      | model/ptl             | pos\n");
	while ((ent = G_EdictsGetNext(ent))) {
		char buf[128];
		const char* model;
		if (ent->type == ET_PARTICLE)
			model = ent->particle;
		else if (ent->model)
			model = ent->model;
		else
			model = "no mdl";
		Com_sprintf(buf, sizeof(buf), "#%5i | #%5i | #%5i | %4i | %5i | %4i | %4i | %4i | %3i | %5i | %14s | %21s | %i:%i:%i",
				i, ent->getIdNum(), ent->mapNum, ent->type, ent->inuse, ent->getPlayerNum(), ent->getTeam(), ent->fieldSize,
				ent->HP, ent->state, ent->classname, model, ent->pos[0], ent->pos[1], ent->pos[2]);
		Com_Printf("%s\n", buf);
		i++;
	}
}
Example #6
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;
	}
}