Ejemplo n.º 1
0
/*
 * @brief Shuts down the game module. This is called when the game is unloaded
 * (complements G_Init).
 */
void G_Shutdown(void) {

	gi.Print("  Game shutdown...\n");

#ifdef HAVE_MYSQL
	if(mysql != NULL)
	mysql_close(mysql); // and db
#endif

	gi.FreeTag(MEM_TAG_GAME_LEVEL);
	gi.FreeTag(MEM_TAG_GAME);
}
Ejemplo n.º 2
0
/*
 * G_ResetTeams
 */
void G_ResetTeams(void) {

	memset(&g_team_good, 0, sizeof(g_team_good));
	memset(&g_team_evil, 0, sizeof(g_team_evil));

	strcpy(g_team_good.name, "Good");
	gi.ConfigString(CS_TEAM_GOOD, g_team_good.name);

	strcpy(g_team_evil.name, "Evil");
	gi.ConfigString(CS_TEAM_EVIL, g_team_evil.name);

	strcpy(g_team_good.skin, "qforcer/blue");
	strcpy(g_team_evil.skin, "qforcer/red");
}
Ejemplo n.º 3
0
/*
 * G_BeginIntermission
 */
static void G_BeginIntermission(const char *map) {
	int i;
	g_edict_t *ent, *client;

	if (g_level.intermission_time)
		return; // already activated

	g_level.intermission_time = g_level.time;

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

		client = g_game.edicts + 1 + i;

		if (!client->in_use)
			continue;

		if (client->health <= 0)
			G_ClientRespawn(client, false);
	}

	// find an intermission spot
	ent = G_Find(NULL, FOFS(class_name), "info_player_intermission");
	if (!ent) { // map does not have an intermission point
		ent = G_Find(NULL, FOFS(class_name), "info_player_start");
		if (!ent)
			ent = G_Find(NULL, FOFS(class_name), "info_player_deathmatch");
	}

	VectorCopy(ent->s.origin, g_level.intermission_origin);
	VectorCopy(ent->s.angles, g_level.intermission_angle);

	// move all clients to the intermission point
	for (i = 0; i < sv_max_clients->integer; i++) {

		client = g_game.edicts + 1 + i;

		if (!client->in_use)
			continue;

		G_ClientToIntermission(client);
	}

	// play a dramatic sound effect
	gi.PositionedSound(g_level.intermission_origin, g_game.edicts,
			gi.SoundIndex("weapons/bfg/hit"), ATTN_NORM);

	// stay on same level if not provided
	g_level.changemap = map && *map ? map : g_level.name;
}
Ejemplo n.º 4
0
/*
 * G_CheckRoundLimit
 */
static void G_CheckRoundLimit() {
	int i;
	g_edict_t *ent;
	g_client_t *cl;

	if (g_level.round_num >= (unsigned int) g_level.round_limit) { // enforce round_limit
		gi.BroadcastPrint(PRINT_HIGH, "Roundlimit hit\n");
		G_EndLevel();
		return;
	}

	// or attempt to re-join previously active players
	for (i = 0; i < sv_max_clients->integer; i++) {
		if (!g_game.edicts[i + 1].in_use)
			continue;

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

		if (cl->persistent.round_num != g_level.round_num)
			continue; // they were intentionally spectating, skip them

		if (g_level.teams || g_level.ctf) { // rejoin a team
			if (cl->persistent.team)
				G_AddClientToTeam(ent, cl->persistent.team->name);
			else
				G_AddClientToTeam(ent, G_SmallestTeam()->name);
		} else
			// just rejoin the game
			cl->persistent.spectator = false;

		G_ClientRespawn(ent, false);
	}
}
Ejemplo n.º 5
0
/*
 * G_CheckRoundStart
 */
static void G_CheckRoundStart(void) {
	int i, g, e, clients;
	g_client_t *cl;

	if (!g_level.rounds)
		return;

	if (g_level.round_time)
		return;

	clients = g = e = 0;

	for (i = 0; i < sv_max_clients->integer; i++) {
		if (!g_game.edicts[i + 1].in_use)
			continue;

		cl = g_game.edicts[i + 1].client;

		if (cl->persistent.spectator)
			continue;

		clients++;

		if (g_level.teams)
			cl->persistent.team == &g_team_good ? g++ : e++;
	}

	if (clients < 2) // need at least 2 clients to trigger countdown
		return;

	if (g_level.teams && (!g || !e)) // need at least 1 player per team
		return;

	if ((int) g_level.teams == 2 && (g != e)) { // balanced teams required
		if (g_level.frame_num % 100 == 0)
			gi.BroadcastPrint(PRINT_HIGH,
					"Teams must be balanced for round to start\n");
		return;
	}

	gi.BroadcastPrint(PRINT_HIGH, "Round starting in 10 seconds...\n");
	g_level.round_time = g_level.time + 10.0;

	g_level.start_round = true;
}
Ejemplo n.º 6
0
/*
 * G_ExitLevel
 */
static void G_ExitLevel(void) {

	gi.AddCommandString(va("map %s\n", g_level.changemap));

	g_level.changemap = NULL;
	g_level.intermission_time = 0;

	G_EndClientFrames();
}
Ejemplo n.º 7
0
/*
 * Frees tags and closes frag_log.  This is called when the game is unloaded
 * (complements G_Init).
 */
void G_Shutdown(void) {

	gi.Print("  Game shutdown...\n");

	if (frag_log != NULL)
		gi.CloseFile(frag_log); // close frag_log

	if (chat_log != NULL)
		gi.CloseFile(chat_log); // and chat_log

#ifdef HAVE_MYSQL
	if(mysql != NULL)
		mysql_close(mysql); // and db
#endif

	gi.FreeTags(TAG_LEVEL);
	gi.FreeTags(TAG_GAME);
}
Ejemplo n.º 8
0
/*
 * G_CheckVote
 */
static void G_CheckVote(void) {
	int i, count = 0;

	if (!g_voting->value)
		return;

	if (g_level.vote_time == 0)
		return;

	if (g_level.time - g_level.vote_time > MAX_VOTE_TIME) {
		gi.BroadcastPrint(PRINT_HIGH, "Vote \"%s\" expired\n", g_level.vote_cmd);
		G_ResetVote();
		return;
	}

	for (i = 0; i < sv_max_clients->integer; i++) {
		if (!g_game.edicts[i + 1].in_use)
			continue;
		count++;
	}

	if (g_level.votes[VOTE_YES] >= count * VOTE_MAJORITY) { // vote passed

		gi.BroadcastPrint(PRINT_HIGH, "Vote \"%s\" passed\n", g_level.vote_cmd);

		if (!strncmp(g_level.vote_cmd, "map ", 4)) { // special case for map
			G_BeginIntermission(g_level.vote_cmd + 4);
		} else if (!strcmp(g_level.vote_cmd, "restart")) { // and restart
			G_RestartGame(false);
		} else if (!strncmp(g_level.vote_cmd, "mute ", 5)) { // and mute
			G_MuteClient(g_level.vote_cmd + 5, true);
		} else if (!strncmp(g_level.vote_cmd, "unmute ", 7)) {
			G_MuteClient(g_level.vote_cmd + 7, false);
		} else { // general case, just execute the command
			gi.AddCommandString(g_level.vote_cmd);
		}
		G_ResetVote();
	} else if (g_level.votes[VOTE_NO] >= count * VOTE_MAJORITY) { // vote failed
		gi.BroadcastPrint(PRINT_HIGH, "Vote \"%s\" failed\n", g_level.vote_cmd);
		G_ResetVote();
	}
}
Ejemplo n.º 9
0
/*
 * G_CheckMatchEnd
 */
static void G_CheckMatchEnd(void) {
	int i, g, e, clients;
	g_client_t *cl;

	if (!g_level.match)
		return;

	if (!g_level.match_time || g_level.match_time > g_level.time)
		return; // no match currently running

	g = e = clients = 0;
	for (i = 0; i < sv_max_clients->integer; i++) {
		if (!g_game.edicts[i + 1].in_use)
			continue;

		cl = g_game.edicts[i + 1].client;

		if (cl->persistent.spectator)
			continue;

		if (g_level.teams || g_level.ctf)
			cl->persistent.team == &g_team_good ? g++ : e++;

		clients++;
	}

	if (clients == 0) { // everyone left
		gi.BroadcastPrint(PRINT_HIGH, "No players left\n");
		g_level.match_time = 0;
		return;
	}

	if ((g_level.teams || g_level.ctf) && (!g || !e)) {
		gi.BroadcastPrint(PRINT_HIGH, "Not enough players left\n");
		g_level.match_time = 0;
		return;
	}
}
Ejemplo n.º 10
0
/*
 * G_ResetVote
 */
void G_ResetVote(void) {
	int i;

	for (i = 0; i < sv_max_clients->integer; i++) { //reset vote flags
		if (!g_game.edicts[i + 1].in_use)
			continue;
		g_game.edicts[i + 1].client->persistent.vote = VOTE_NO_OP;
	}

	gi.ConfigString(CS_VOTE, NULL);

	g_level.votes[0] = g_level.votes[1] = g_level.votes[2] = 0;
	g_level.vote_cmd[0] = 0;

	g_level.vote_time = 0;
}
Ejemplo n.º 11
0
/*
 * G_ParseMapList
 *
 * Populates a g_map_list_t from a text file.  See default/maps.lst
 */
static void G_ParseMapList(const char *file_name) {
	void *buf;
	const char *buffer;
	unsigned int i, j, k, l;
	const char *c;
	boolean_t map;
	g_map_list_elt_t *elt;

	G_InitMapList();

	if (gi.LoadFile(file_name, &buf) == -1) {
		gi.Print("Couldn't open %s\n", file_name);
		return;
	}

	buffer = (char *) buf;

	i = 0;
	map = false;
	while (true) {

		c = ParseToken(&buffer);

		if (*c == '\0')
			break;

		if (*c == '{')
			map = true;

		if (!map) // skip any whitespace between maps
			continue;

		elt = &g_map_list.maps[i];

		if (!strcmp(c, "name")) {
			strncpy(elt->name, ParseToken(&buffer), sizeof(elt->name) - 1);
			continue;
		}

		if (!strcmp(c, "title")) {
			strncpy(elt->title, ParseToken(&buffer), sizeof(elt->title) - 1);
			continue;
		}

		if (!strcmp(c, "sky")) {
			strncpy(elt->sky, ParseToken(&buffer), sizeof(elt->sky) - 1);
			continue;
		}

		if (!strcmp(c, "weather")) {
			strncpy(elt->weather, ParseToken(&buffer), sizeof(elt->weather) - 1);
			continue;
		}

		if (!strcmp(c, "gravity")) {
			elt->gravity = atoi(ParseToken(&buffer));
			continue;
		}

		if (!strcmp(c, "gameplay")) {
			elt->gameplay = G_GameplayByName(ParseToken(&buffer));
			continue;
		}

		if (!strcmp(c, "teams")) {
			elt->teams = strtoul(ParseToken(&buffer), NULL, 0);
			continue;
		}

		if (!strcmp(c, "ctf")) {
			elt->ctf = strtoul(ParseToken(&buffer), NULL, 0);
			continue;
		}

		if (!strcmp(c, "match")) {
			elt->match = strtoul(ParseToken(&buffer), NULL, 0);
			continue;
		}

		if (!strcmp(c, "rounds")) {
			elt->rounds = strtoul(ParseToken(&buffer), NULL, 0);
			continue;
		}

		if (!strcmp(c, "frag_limit")) {
			elt->frag_limit = strtoul(ParseToken(&buffer), NULL, 0);
			continue;
		}

		if (!strcmp(c, "round_limit")) {
			elt->round_limit = strtoul(ParseToken(&buffer), NULL, 0);
			continue;
		}

		if (!strcmp(c, "capture_limit")) {
			elt->capture_limit = strtoul(ParseToken(&buffer), NULL, 0);
			continue;
		}

		if (!strcmp(c, "time_limit")) {
			elt->time_limit = atof(ParseToken(&buffer));
			continue;
		}

		if (!strcmp(c, "give")) {
			strncpy(elt->give, ParseToken(&buffer), sizeof(elt->give) - 1);
			continue;
		}

		if (!strcmp(c, "music")) {
			strncpy(elt->music, ParseToken(&buffer), sizeof(elt->music) - 1);
			continue;
		}

		if (!strcmp(c, "weight")) {
			elt->weight = atof(ParseToken(&buffer));
			continue;
		}

		if (*c == '}') { // close it out
			map = false;

			/*printf("Loaded map %s:\n"
			 "title: %s\n"
			 "sky: %s\n"
			 "weather: %s\n"
			 "gravity: %d\n"
			 "gameplay: %ud\n"
			 "teams: %ud\n"
			 "ctf: %ud\n"
			 "match: %ud\n"
			 "rounds: %ud\n"
			 "frag_limit: %ud\n"
			 "round_limit: %ud\n"
			 "capture_limit: %ud\n"
			 "time_limit: %f\n"
			 "give: %s\n"
			 "music: %s\n"
			 "weight: %f\n",
			 map->name, map->title, map->sky, map->weather, map->gravity,
			 map->gameplay, map->teams, map->ctf, map->match, map->rounds,
			 map->frag_limit, map->round_limit, map->capture_limit,
			 map->time_limit, map->give, map->music, map->weight);*/

			// accumulate total weight
			g_map_list.total_weight += elt->weight;

			if (++i == MAX_MAP_LIST_ELTS)
				break;
		}
	}

	g_map_list.count = i;
	g_map_list.index = 0;

	gi.TagFree(buf);

	// thou shalt not divide by zero
	if (!g_map_list.total_weight)
		g_map_list.total_weight = 1.0;

	// compute the weighted index list
	for (i = 0, l = 0; i < g_map_list.count; i++) {

		elt = &g_map_list.maps[i];
		k = (elt->weight / g_map_list.total_weight) * MAP_LIST_WEIGHT;

		for (j = 0; j < k; j++)
			g_map_list.weighted_index[l++] = i;
	}
}
Ejemplo n.º 12
0
/*
 * G_CheckRules
 */
static void G_CheckRules(void) {
	int i, seconds;
	g_client_t *cl;

	if (g_level.intermission_time)
		return;

	// match mode, no match, or countdown underway
	g_level.warmup = g_level.match && (!g_level.match_time
			|| g_level.match_time > g_level.time);

	// arena mode, no round, or countdown underway
	g_level.warmup |= g_level.rounds && (!g_level.round_time
			|| g_level.round_time > g_level.time);

	if (g_level.start_match && g_level.time >= g_level.match_time) { // players have readied, begin match
		g_level.start_match = false;
		g_level.warmup = false;

		for (i = 0; i < sv_max_clients->integer; i++) {
			if (!g_game.edicts[i + 1].in_use)
				continue;
			G_ClientRespawn(&g_game.edicts[i + 1], false);
		}

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

	if (g_level.start_round && g_level.time >= g_level.round_time) { // pre-game expired, begin round
		g_level.start_round = false;
		g_level.warmup = false;

		for (i = 0; i < sv_max_clients->integer; i++) {
			if (!g_game.edicts[i + 1].in_use)
				continue;
			G_ClientRespawn(&g_game.edicts[i + 1], false);
		}

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

	seconds = g_level.time;

	if (g_level.rounds) {
		if (g_level.round_time > g_level.time) // round about to start, show pre-game countdown
			seconds = g_level.round_time - g_level.time;
		else if (g_level.round_time)
			seconds = g_level.time - g_level.round_time; // round started, count up
		else
			seconds = -1;
	} else if (g_level.match) {
		if (g_level.match_time > g_level.time) // match about to start, show pre-game countdown
			seconds = g_level.match_time - g_level.time;
		else if (g_level.match_time) {
			if (g_level.time_limit) // count down to time_limit
				seconds = g_level.match_time + g_level.time_limit * 60
						- g_level.time;
			else
				seconds = g_level.time - g_level.match_time; // count up
		} else
			seconds = -1;
	}

	if (g_level.time_limit) { // check time_limit
		float t = g_level.time;

		if (g_level.match) // for matches
			t = g_level.time - g_level.match_time;
		else if (g_level.rounds) // and for rounds
			t = g_level.time - g_level.round_time;

		if (t >= g_level.time_limit * 60) {
			gi.BroadcastPrint(PRINT_HIGH, "Timelimit hit\n");
			G_EndLevel();
			return;
		}
		seconds = g_level.time_limit * 60 - t; // count down
	}

	if (g_level.frame_num % gi.frame_rate == 0) // send time updates once per second
		gi.ConfigString(CS_TIME,
				(g_level.warmup ? "Warmup" : G_FormatTime(seconds)));

	if (!g_level.ctf && g_level.frag_limit) { // check frag_limit

		if (g_level.teams) { // check team scores
			if (g_team_good.score >= g_level.frag_limit ||
					g_team_evil.score >= g_level.frag_limit) {
				gi.BroadcastPrint(PRINT_HIGH, "Fraglimit hit\n");
				G_EndLevel();
				return;
			}
		} else { // or individual scores
			for (i = 0; i < sv_max_clients->integer; i++) {
				cl = g_game.clients + i;
				if (!g_game.edicts[i + 1].in_use)
					continue;

				if (cl->persistent.score >= g_level.frag_limit) {
					gi.BroadcastPrint(PRINT_HIGH, "Fraglimit hit\n");
					G_EndLevel();
					return;
				}
			}
		}
	}

	if (g_level.ctf && g_level.capture_limit) { // check capture limit

		if (g_team_good.captures >= g_level.capture_limit || g_team_evil.captures
				>= g_level.capture_limit) {
			gi.BroadcastPrint(PRINT_HIGH, "Capturelimit hit\n");
			G_EndLevel();
			return;
		}
	}

	if (g_gameplay->modified) { // change gameplay, fix items, respawn clients
		g_gameplay->modified = false;

		g_level.gameplay = G_GameplayByName(g_gameplay->string);
		gi.ConfigString(CS_GAMEPLAY, va("%d", g_level.gameplay));

		G_RestartGame(false); // reset all clients

		gi.BroadcastPrint(PRINT_HIGH, "Gameplay has changed to %s\n",
				G_GameplayName(g_level.gameplay));
	}

	if (g_gravity->modified) { // send gravity config string
		g_gravity->modified = false;

		g_level.gravity = g_gravity->integer;
		gi.ConfigString(CS_GRAVITY, va("%d", g_level.gravity));
	}

	if (g_teams->modified) { // reset teams, scores
		g_teams->modified = false;

		g_level.teams = g_teams->integer;
		gi.ConfigString(CS_TEAMS, va("%d", g_level.teams));

		gi.BroadcastPrint(PRINT_HIGH, "Teams have been %s\n",
				g_level.teams ? "enabled" : "disabled");

		G_RestartGame(true);
	}

	if (g_ctf->modified) { // reset teams, scores
		g_ctf->modified = false;

		g_level.ctf = g_ctf->integer;
		gi.ConfigString(CS_CTF, va("%d", g_level.ctf));

		gi.BroadcastPrint(PRINT_HIGH, "CTF has been %s\n",
				g_level.ctf ? "enabled" : "disabled");

		G_RestartGame(true);
	}

	if (g_match->modified) { // reset scores
		g_match->modified = false;

		g_level.match = g_match->integer;
		gi.ConfigString(CS_MATCH, va("%d", g_level.match));

		g_level.warmup = g_level.match; // toggle warmup

		gi.BroadcastPrint(PRINT_HIGH, "Match has been %s\n",
				g_level.match ? "enabled" : "disabled");

		G_RestartGame(false);
	}

	if (g_rounds->modified) { // reset scores
		g_rounds->modified = false;

		g_level.rounds = g_rounds->integer;
		gi.ConfigString(CS_ROUNDS, va("%d", g_level.rounds));

		g_level.warmup = g_level.rounds; // toggle warmup

		gi.BroadcastPrint(PRINT_HIGH, "Rounds have been %s\n",
				g_level.rounds ? "enabled" : "disabled");

		G_RestartGame(false);
	}

	if (g_cheats->modified) { // notify when cheats changes
		g_cheats->modified = false;

		gi.BroadcastPrint(PRINT_HIGH, "Cheats have been %s\n",
				g_cheats->integer ? "enabled" : "disabled");
	}

	if (g_frag_limit->modified) {
		g_frag_limit->modified = false;
		g_level.frag_limit = g_frag_limit->integer;

		gi.BroadcastPrint(PRINT_HIGH, "Fraglimit has been changed to %d\n",
				g_level.frag_limit);
	}

	if (g_round_limit->modified) {
		g_round_limit->modified = false;
		g_level.round_limit = g_round_limit->integer;

		gi.BroadcastPrint(PRINT_HIGH, "Roundlimit has been changed to %d\n",
				g_level.round_limit);
	}

	if (g_capture_limit->modified) {
		g_capture_limit->modified = false;
		g_level.capture_limit = g_capture_limit->integer;

		gi.BroadcastPrint(PRINT_HIGH, "Capturelimit has been changed to %d\n",
				g_level.capture_limit);
	}

	if (g_time_limit->modified) {
		g_time_limit->modified = false;
		g_level.time_limit = g_time_limit->value;

		gi.BroadcastPrint(PRINT_HIGH, "Timelimit has been changed to %d\n",
				(int) g_level.time_limit);
	}
}
Ejemplo n.º 13
0
/*
 * G_CheckRoundEnd
 */
static void G_CheckRoundEnd(void) {
	unsigned int i, g, e, clients;
	int j;
	g_edict_t *winner;
	g_client_t *cl;

	if (!g_level.rounds)
		return;

	if (!g_level.round_time || g_level.round_time > g_level.time)
		return; // no round currently running

	winner = NULL;
	g = e = clients = 0;
	for (j = 0; j < sv_max_clients->integer; j++) {
		if (!g_game.edicts[j + 1].in_use)
			continue;

		cl = g_game.edicts[j + 1].client;

		if (cl->persistent.spectator) // true spectator, or dead
			continue;

		winner = &g_game.edicts[j + 1];

		if (g_level.teams)
			cl->persistent.team == &g_team_good ? g++ : e++;

		clients++;
	}

	if (clients == 0) { // corner case where everyone was fragged
		gi.BroadcastPrint(PRINT_HIGH, "Tie!\n");
		g_level.round_time = 0;
		G_CheckRoundLimit();
		return;
	}

	if (g_level.teams || g_level.ctf) { // teams rounds continue if each team has a player
		if (g > 0 && e > 0)
			return;
	} else if (clients > 1) // ffa continues if two players are alive
		return;

	// allow enemy projectiles to expire before declaring a winner
	for (i = 0; i < ge.num_edicts; i++) {
		if (!g_game.edicts[i + 1].in_use)
			continue;

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

		if (!(cl = g_game.edicts[i + 1].owner->client))
			continue;

		if (g_level.teams || g_level.ctf) {
			if (cl->persistent.team != winner->client->persistent.team)
				return;
		} else {
			if (g_game.edicts[i + 1].owner != winner)
				return;
		}
	}

	// we have a winner
	gi.BroadcastPrint(
			PRINT_HIGH,
			"%s wins!\n",
			(g_level.teams || g_level.ctf ? winner->client->persistent.team->name
					: winner->client->persistent.net_name));

	g_level.round_time = 0;

	G_CheckRoundLimit();
}
Ejemplo n.º 14
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);
}
Ejemplo n.º 15
0
/*
 * G_Init
 *
 * This will be called when the game module is first loaded.
 */
void G_Init(void) {

	gi.Print("  Game initialization...\n");

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

	gi.Cvar("game_name", GAME_NAME, CVAR_SERVER_INFO | CVAR_NO_SET, NULL);
	gi.Cvar("game_date", __DATE__, CVAR_SERVER_INFO | CVAR_NO_SET, NULL);

	g_auto_join = gi.Cvar("g_auto_join", "1", CVAR_SERVER_INFO, NULL);
	g_capture_limit = gi.Cvar("g_capture_limit", "8", CVAR_SERVER_INFO, NULL);
	g_chat_log = gi.Cvar("g_chat_log", "0", 0, NULL);
	g_cheats = gi.Cvar("g_cheats", "0", CVAR_SERVER_INFO, NULL);
	g_ctf = gi.Cvar("g_ctf", "0", CVAR_SERVER_INFO, NULL);
	g_frag_limit = gi.Cvar("g_frag_limit", "30", CVAR_SERVER_INFO, NULL);
	g_frag_log = gi.Cvar("g_frag_log", "0", 0, NULL);
	g_friendly_fire = gi.Cvar("g_friendly_fire", "1", CVAR_SERVER_INFO, NULL);
	g_gameplay = gi.Cvar("g_gameplay", "0", CVAR_SERVER_INFO, NULL);
	g_gravity = gi.Cvar("g_gravity", "800", CVAR_SERVER_INFO, NULL);
	g_match = gi.Cvar("g_match", "0", CVAR_SERVER_INFO, NULL);
	g_max_entities = gi.Cvar("g_max_entities", "1024", CVAR_LATCH, NULL);
	g_mysql = gi.Cvar("g_mysql", "0", 0, NULL);
	g_mysql_db = gi.Cvar("g_mysql_db", "quake2world", 0, NULL);
	g_mysql_host = gi.Cvar("g_mysql_host", "localhost", 0, NULL);
	g_mysql_password = gi.Cvar("g_mysql_password", "", 0, NULL);
	g_mysql_user = gi.Cvar("g_mysql_user", "quake2world", 0, NULL);
	g_player_projectile = gi.Cvar("g_player_projectile", "1", CVAR_SERVER_INFO,
			NULL);
	g_random_map = gi.Cvar("g_random_map", "0", 0, NULL);
	g_round_limit = gi.Cvar("g_round_limit", "30", CVAR_SERVER_INFO, NULL);
	g_rounds = gi.Cvar("g_rounds", "0", CVAR_SERVER_INFO, NULL);
	g_spawn_farthest = gi.Cvar("g_spawn_farthest", "0", CVAR_SERVER_INFO, NULL);
	g_teams = gi.Cvar("g_teams", "0", CVAR_SERVER_INFO, NULL);
	g_time_limit = gi.Cvar("g_time_limit", "20", CVAR_SERVER_INFO, NULL);
	g_voting = gi.Cvar("g_voting", "1", CVAR_SERVER_INFO, "Activates voting");

	password = gi.Cvar("password", "", CVAR_USER_INFO, NULL);

	sv_max_clients = gi.Cvar("sv_max_clients", "8",
			CVAR_SERVER_INFO | CVAR_LATCH, NULL);
	dedicated = gi.Cvar("dedicated", "0", CVAR_NO_SET, NULL);

	if (g_frag_log->value)
		gi.OpenFile("frag_log.log", &frag_log, FILE_APPEND);

	if (g_chat_log->value)
		gi.OpenFile("chat_log.log", &chat_log, FILE_APPEND);

#ifdef HAVE_MYSQL
	if(g_mysql->value) { //init database

		mysql = mysql_init(NULL);

		mysql_real_connect(mysql, g_mysql_host->string,
				g_mysql_user->string, g_mysql_password->string,
				g_mysql_db->string, 0, NULL, 0
		);

		if(mysql != NULL)
		gi.Print("    MySQL connection to %s/%s", g_mysql_host->string,
				g_mysql_user->string);
	}
#endif

	G_ParseMapList("maps.lst");

	G_InitItems();

	// initialize entities and clients for this game
	g_game.edicts = gi.TagMalloc(g_max_entities->integer * sizeof(g_edict_t),
			TAG_GAME);
	g_game.clients = gi.TagMalloc(sv_max_clients->integer * sizeof(g_client_t),
			TAG_GAME);

	ge.edicts = g_game.edicts;
	ge.max_edicts = g_max_entities->integer;
	ge.num_edicts = sv_max_clients->integer + 1;

	// set these to false to avoid spurious game restarts and alerts on init
	g_gameplay->modified = g_teams->modified = g_match->modified
			= g_rounds->modified = g_ctf->modified = g_cheats->modified
					= g_frag_limit->modified = g_round_limit->modified
							= g_capture_limit->modified
									= g_time_limit->modified = false;

	gi.Print("  Game initialized.\n");
}
Ejemplo n.º 16
0
/*
 * @brief This will be called when the game module is first loaded.
 */
void G_Init(void) {

	gi.Print("  Game initialization...\n");

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

	gi.Cvar("game_name", GAME_NAME, CVAR_SERVER_INFO | CVAR_NO_SET, NULL);
	gi.Cvar("game_date", __DATE__, CVAR_SERVER_INFO | CVAR_NO_SET, NULL);

	g_ammo_respawn_time = gi.Cvar("g_ammo_respawn_time", "20.0", CVAR_SERVER_INFO,
			"Ammo respawn interval in seconds");
	g_auto_join = gi.Cvar("g_auto_join", "1", CVAR_SERVER_INFO,
			"Automatically assigns players to teams");
	g_capture_limit = gi.Cvar("g_capture_limit", "8", CVAR_SERVER_INFO,
			"The capture limit per level");
	g_cheats = gi.Cvar("g_cheats", "0", CVAR_SERVER_INFO, NULL);
	g_ctf = gi.Cvar("g_ctf", "0", CVAR_SERVER_INFO, "Enables capture the flag gameplay");
	g_frag_limit = gi.Cvar("g_frag_limit", "30", CVAR_SERVER_INFO, "The frag limit per level");
	g_friendly_fire = gi.Cvar("g_friendly_fire", "1", CVAR_SERVER_INFO, "Enables friendly fire");
	g_gameplay = gi.Cvar("g_gameplay", "0", CVAR_SERVER_INFO,
			"Selects deathmatch, arena, or instagib combat");
	g_gravity = gi.Cvar("g_gravity", "800", CVAR_SERVER_INFO, NULL);
	g_match = gi.Cvar("g_match", "0", CVAR_SERVER_INFO,
			"Enables match play requiring players to ready");
	g_max_entities = gi.Cvar("g_max_entities", "1024", CVAR_LATCH, NULL);
	g_motd = gi.Cvar("g_motd", "", CVAR_SERVER_INFO,
			"Message of the day, shown to clients on initial connect");
	g_mysql = gi.Cvar("g_mysql", "0", 0, NULL);
	g_mysql_db = gi.Cvar("g_mysql_db", "quake2world", 0, NULL);
	g_mysql_host = gi.Cvar("g_mysql_host", "localhost", 0, NULL);
	g_mysql_password = gi.Cvar("g_mysql_password", "", 0, NULL);
	g_mysql_user = gi.Cvar("g_mysql_user", "quake2world", 0, NULL);
	g_password = gi.Cvar("g_password", "", CVAR_USER_INFO, "The server password");
	g_player_projectile = gi.Cvar("g_player_projectile", "1.0", CVAR_SERVER_INFO,
			"Scales player velocity to projectiles");
	g_random_map = gi.Cvar("g_random_map", "0", 0, "Enables map shuffling");
	g_respawn_protection = gi.Cvar("g_respawn_protection", "0.0", 0,
			"Respawn protection in seconds");
	g_round_limit = gi.Cvar("g_round_limit", "30", CVAR_SERVER_INFO,
			"The number of rounds to run per level");
	g_rounds = gi.Cvar("g_rounds", "0", CVAR_SERVER_INFO,
			"Enables rounds-based play, where last player standing wins");
	g_show_attacker_stats = gi.Cvar("g_show_attacker_stats", "1", CVAR_SERVER_INFO, NULL);
	g_spawn_farthest = gi.Cvar("g_spawn_farthest", "1", CVAR_SERVER_INFO, NULL);
	g_spectator_chat = gi.Cvar("g_spectator_chat", "1", CVAR_SERVER_INFO,
			"If enabled, spectators can only talk to other spectators");
	g_teams = gi.Cvar("g_teams", "0", CVAR_SERVER_INFO, "Enables teams-based play");
	g_time_limit = gi.Cvar("g_time_limit", "20.0", CVAR_SERVER_INFO,
			"The time limit per level in minutes");
	g_voting = gi.Cvar("g_voting", "1", CVAR_SERVER_INFO, "Activates voting");
	g_weapon_respawn_time = gi.Cvar("g_weapon_respawn_time", "5.0", CVAR_SERVER_INFO,
			"Weapon respawn interval in seconds");

	sv_max_clients = gi.Cvar("sv_max_clients", "8", CVAR_SERVER_INFO | CVAR_LATCH, NULL);
	sv_hostname = gi.Cvar("sv_hostname", "Quake2World", CVAR_SERVER_INFO, NULL);
	dedicated = gi.Cvar("dedicated", "0", CVAR_NO_SET, NULL);

#ifdef HAVE_MYSQL
	if(g_mysql->value) { //init database

		mysql = mysql_init(NULL);

		mysql_real_connect(mysql, g_mysql_host->string,
				g_mysql_user->string, g_mysql_password->string,
				g_mysql_db->string, 0, NULL, 0
		);

		if(mysql != NULL)
		gi.Print("    MySQL connection to %s/%s", g_mysql_host->string,
				g_mysql_user->string);
	}
#endif

	G_ParseMapList("maps.lst");

	// initialize entities and clients for this game
	g_game.edicts = gi.Malloc(g_max_entities->integer * sizeof(g_edict_t), MEM_TAG_GAME);
	g_game.clients = gi.Malloc(sv_max_clients->integer * sizeof(g_client_t), MEM_TAG_GAME);

	ge.edicts = g_game.edicts;
	ge.max_edicts = g_max_entities->integer;
	ge.num_edicts = sv_max_clients->integer + 1;

	G_Ai_Init(); // initialize the AI

	// set these to false to avoid spurious game restarts and alerts on init
	g_gameplay->modified = g_teams->modified = g_match->modified = g_rounds->modified
			= g_ctf->modified = g_cheats->modified = g_frag_limit->modified
					= g_round_limit->modified = g_capture_limit->modified = g_time_limit->modified
							= false;

	gi.Print("  Game initialized\n");
}