/* * 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); } }
/* * 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); }