Пример #1
0
/**
 * @brief Creates an effect trail for the specified entity.
 */
static void G_trigger_push_Effect(g_entity_t *self) {

	g_entity_t *ent = G_AllocEntity();

	VectorAdd(self->mins, self->maxs, ent->s.origin);
	VectorScale(ent->s.origin, 0.5, ent->s.origin);

	ent->locals.move_type = MOVE_TYPE_NONE;
	ent->s.trail = TRAIL_TELEPORTER;

	gi.LinkEntity(ent);
}
Пример #2
0
/**
 * @brief Creates a server's entity / program execution context by
 * parsing textual entity definitions out of an ent file.
 */
void G_SpawnEntities(const char *name, const char *entities) {

	gi.FreeTag(MEM_TAG_GAME_LEVEL);

	memset(&g_level, 0, sizeof(g_level));

	g_strlcpy(g_level.name, name, sizeof(g_level.name));

	// see if we have bots to keep
	if (aix) {
		g_game.ai_fill_slots = 0;
		g_game.ai_left_to_spawn = 0;

		if (g_ai_max_clients->integer) {
			if (g_ai_max_clients->integer == -1) {
				g_game.ai_fill_slots = sv_max_clients->integer;
			} else {
				g_game.ai_fill_slots = Clamp(g_ai_max_clients->integer, 0, sv_max_clients->integer);
			}

			g_game.ai_left_to_spawn = g_game.ai_fill_slots;
			g_ai_max_clients->modified = false;
		} else {
			for (int32_t i = 0; i < sv_max_clients->integer; i++) {
				if (g_game.entities[i + 1].client && g_game.entities[i + 1].client->ai) {
					g_game.ai_left_to_spawn++;
				}
			}
		}
	}
	
	memset(g_game.entities, 0, g_max_entities->value * sizeof(g_entity_t));
	memset(g_game.clients, 0, sv_max_clients->value * sizeof(g_client_t));

	for (int32_t i = 0; i < sv_max_clients->integer; i++) {
		g_game.entities[i + 1].client = g_game.clients + i;
	}

	ge.num_entities = sv_max_clients->integer + 1;

	g_entity_t *ent = NULL;

	gchar **inhibit = g_strsplit(g_inhibit->string, " ", -1);
	int32_t inhibited = 0;
	
	parser_t parser;
	char tok[MAX_QPATH];
	Parse_Init(&parser, entities, PARSER_NO_COMMENTS);

	// parse the entity definition string
	while (true) {

		if (!Parse_Token(&parser, PARSE_DEFAULT, tok, sizeof(tok))) {
			break;
		}

		if (tok[0] != '{') {
			gi.Error("Found \"%s\" when expecting \"{\"", tok);
		}

		if (ent == NULL) {
			ent = g_game.entities;
		} else {
			ent = G_AllocEntity();
		}

		G_ParseEntity(&parser, ent);

		if (ent != g_game.entities) {

			// enforce entity inhibiting
			for (size_t i = 0; i < g_strv_length(inhibit); i++) {
				if (g_strcmp0(ent->class_name, inhibit[i]) == 0) {
					G_FreeEntity(ent);
					inhibited++;
					continue;
				}
			}

			// handle legacy spawn flags
			if (ent->locals.spawn_flags & SF_NOT_DEATHMATCH) {
				G_FreeEntity(ent);
				inhibited++;
				continue;
			}

			// strip away unsupported flags
			ent->locals.spawn_flags &= ~(SF_NOT_EASY | SF_NOT_MEDIUM | SF_NOT_HARD | SF_NOT_COOP);
		}

		if (!G_SpawnEntity(ent)) {
			G_FreeEntity(ent);
			inhibited++;
		}
	}

	g_strfreev(inhibit);

	gi.Debug("%i entities inhibited\n", inhibited);

	G_InitMedia();

	G_InitEntityTeams();

	G_CheckHook();

	G_CheckTechs();

	G_ResetTeams();

	G_InitSpawnPoints();

	G_ResetSpawnPoints();

	G_ResetVote();

	G_ResetItems();
}
Пример #3
0
/*
 * @brief Search for all entities that the specified entity targets, and call their
 * use functions. Set their activator to our activator. Print our message,
 * if set, to the activator.
 */
void G_UseTargets(g_entity_t *ent, g_entity_t *activator) {
	g_entity_t *t;

	// check for a delay
	if (ent->locals.delay) {
		// create a temp object to fire at a later time
		t = G_AllocEntity(__func__);
		t->locals.next_think = g_level.time + ent->locals.delay * 1000;
		t->locals.Think = G_UseTargets_Delay;
		t->locals.activator = activator;
		if (!activator)
			gi.Debug("No activator for %s\n", etos(ent));
		t->locals.message = ent->locals.message;
		t->locals.target = ent->locals.target;
		t->locals.kill_target = ent->locals.kill_target;
		return;
	}

	// print the message
	if ((ent->locals.message) && activator->client) {
		gi.WriteByte(SV_CMD_CENTER_PRINT);
		gi.WriteString(ent->locals.message);
		gi.Unicast(activator, true);

		if (ent->locals.noise_index)
			gi.Sound(activator, ent->locals.noise_index, ATTEN_NORM);
		else
			gi.Sound(activator, gi.SoundIndex("misc/chat"), ATTEN_NORM);
	}

	// kill kill_targets
	if (ent->locals.kill_target) {
		t = NULL;
		while ((t = G_Find(t, LOFS(target_name), ent->locals.kill_target))) {
			G_FreeEntity(t);
			if (!ent->in_use) {
				gi.Debug("%s was removed while using kill_targets\n", etos(ent));
				return;
			}
		}
	}

	// doors fire area portals in a specific way
	const _Bool is_door = g_str_has_prefix(ent->class_name, "func_door");

	// fire targets
	if (ent->locals.target) {
		t = NULL;
		while ((t = G_Find(t, LOFS(target_name), ent->locals.target))) {

			if (is_door && !g_strcmp0(t->class_name, "func_areaportal")) {
				continue;
			}

			if (t == ent) {
				gi.Debug("%s tried to use itself\n", etos(ent));
				continue;
			}

			if (t->locals.Use) {
				t->locals.Use(t, ent, activator);
				if (!ent->in_use) { // see if our target freed us
					gi.Debug("%s was removed while using targets\n", etos(ent));
					break;
				}
			}
		}
	}
}