Exemplo n.º 1
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();
}
Exemplo n.º 2
0
/*
 * G_RestartGame
 *
 * For normal games, this just means reset scores and respawn.
 * For match games, this means cancel the match and force everyone
 * to ready again.  Teams are only reset when teamz is true.
 */
static void G_RestartGame(boolean_t teamz) {
	int i;
	g_edict_t *ent;
	g_client_t *cl;

	if (g_level.match_time)
		g_level.match_num++;

	if (g_level.round_time)
		g_level.round_num++;

	for (i = 0; i < sv_max_clients->integer; i++) { // reset clients

		if (!g_game.edicts[i + 1].in_use)
			continue;

		ent = &g_game.edicts[i + 1];
		cl = ent->client;

		cl->persistent.ready = false; // back to warmup
		cl->persistent.score = 0;
		cl->persistent.captures = 0;

		if (teamz) // reset teams
			cl->persistent.team = NULL;

		// determine spectator or team affiliations

		if (g_level.match) {
			if (cl->persistent.match_num == g_level.match_num)
				cl->persistent.spectator = false;
			else
				cl->persistent.spectator = true;
		}

		else if (g_level.rounds) {
			if (cl->persistent.round_num == g_level.round_num)
				cl->persistent.spectator = false;
			else
				cl->persistent.spectator = true;
		}

		if (g_level.teams || g_level.ctf) {

			if (!cl->persistent.team) {
				if (g_auto_join->value)
					G_AddClientToTeam(ent, G_SmallestTeam()->name);
				else
					cl->persistent.spectator = true;
			}
		}

		G_ClientRespawn(ent, false);
	}

	G_ResetItems();

	g_level.match_time = g_level.round_time = 0;
	g_team_good.score = g_team_evil.score = 0;
	g_team_good.captures = g_team_evil.captures = 0;

	gi.BroadcastPrint(PRINT_HIGH, "Game restarted\n");
	gi.Sound(&g_game.edicts[0], gi.SoundIndex("world/teleport"), ATTN_NONE);
}