X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fserver%2Fcommand%2Fvote.qc;h=3367ef310c2e1eb5d97852b34964f1aa5188ab02;hb=613663cc624d93b575bbb2e1402ab673d94d02c7;hp=e94880c785164bf765deebbdf5eb77c56c5f2a75;hpb=64f02fb25661ce6301c0c4e30dfb3457dd2aa531;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/server/command/vote.qc b/qcsrc/server/command/vote.qc index e94880c78..3367ef310 100644 --- a/qcsrc/server/command/vote.qc +++ b/qcsrc/server/command/vote.qc @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -439,6 +440,8 @@ void ReadyRestart_force(bool is_fake_round_start) if(warmup_stage) game_starttime = time; // Warmup: No countdown in warmup + else if (autocvar_g_campaign) + game_starttime = time + 3; else game_starttime = time + RESTART_COUNTDOWN; // Go into match mode @@ -483,7 +486,13 @@ void ReadyRestart_force(bool is_fake_round_start) void ReadyRestart(bool forceWarmupEnd) { - if (MUTATOR_CALLHOOK(ReadyRestart_Deny) || intermission_running || race_completing) localcmd("restart\n"); + if (MUTATOR_CALLHOOK(ReadyRestart_Deny) || intermission_running || race_completing) + { + // NOTE: ReadyRestart support is mandatory in campaign + if (autocvar_g_campaign) + error("ReadyRestart must be supported in campaign mode!"); + localcmd("restart\n"); // if ReadyRestart is denied, restart the server + } else localcmd("\nsv_hook_readyrestart\n"); if(forceWarmupEnd || autocvar_g_campaign) @@ -494,21 +503,46 @@ void ReadyRestart(bool forceWarmupEnd) ReadyRestart_force(false); } -// Count the players who are ready and determine whether or not to restart the match +/* Count the players who are ready and determine whether or not to restart the match when: + * a player presses F4 server/command/cmd.qc ClientCommand_ready() + * a player switches from players to specs server/client.qc PutObserverInServer() + * a player joins (from specs or directly) server/client.qc PutPlayerInServer() + * a player disconnects server/client.qc ClientDisconnect() */ void ReadyCount() { + // cannot reset the game while a timeout is active or pending + if (timeout_status) return; + float ready_needed_factor, ready_needed_count; - float t_ready = 0, t_players = 0; + float t_players = 0; + readycount = 0; FOREACH_CLIENT(IS_REAL_CLIENT(it) && (IS_PLAYER(it) || INGAME_JOINED(it)), { ++t_players; - if (it.ready) ++t_ready; + if (it.ready) ++readycount; }); - readycount = t_ready; - Nagger_ReadyCounted(); + if (t_players < map_minplayers) // map_minplayers will only be set if g_warmup -1 at worldspawn + { + // TODO: handle player spectating/disconnecting during countdown + if (warmup_limit > 0) + warmup_limit = -1; + return; // don't ReadyRestart if players are ready but too few + } + else if (map_minplayers && warmup_limit <= 0) + { + // there's enough players now but we're still in infinite warmup + warmup_limit = cvar("g_warmup_limit"); + if (warmup_limit == 0) + warmup_limit = autocvar_timelimit * 60; + if (warmup_limit > 0) + game_starttime = time; + // implicit else: g_warmup -1 && g_warmup_limit -1 means + // warmup continues until enough players AND enough RUPs (no time limit) + } + ready_needed_factor = bound(0.5, cvar("g_warmup_majority_factor"), 0.999); ready_needed_count = floor(t_players * ready_needed_factor) + 1;