diff --git a/scripting/get5.sp b/scripting/get5.sp index 49eb84604..014ef4c45 100644 --- a/scripting/get5.sp +++ b/scripting/get5.sp @@ -50,6 +50,8 @@ /** ConVar handles **/ ConVar g_AllowTechPauseCvar; +ConVar g_MaxTechPauseTime; +ConVar g_MaxTechPauseCvar; ConVar g_AutoLoadConfigCvar; ConVar g_AutoReadyActivePlayers; ConVar g_BackupSystemEnabledCvar; @@ -166,6 +168,9 @@ bool g_TeamGivenStopCommand[MATCHTEAM_COUNT]; bool g_InExtendedPause; int g_TeamPauseTimeUsed[MATCHTEAM_COUNT]; int g_TeamPausesUsed[MATCHTEAM_COUNT]; +int g_TeamTechPausesUsed[MATCHTEAM_COUNT]; +int g_TechPausedTimeOverride[MATCHTEAM_COUNT]; +int g_TeamGivenTechPauseCommand[MATCHTEAM_COUNT]; int g_PauseTimeUsed = 0; int g_ReadyTimeWaitingUsed = 0; char g_DefaultTeamColors[][] = { @@ -262,6 +267,10 @@ public void OnPluginStart() { /** ConVars **/ g_AllowTechPauseCvar = CreateConVar("get5_allow_technical_pause", "1", "Whether or not technical pauses are allowed"); + g_MaxTechPauseTime = CreateConVar("get5_tech_pause_time", "0", + "Number of seconds before anyone can call unpause on a technical timeout, 0=unlimited"); + g_MaxTechPauseCvar = CreateConVar("get5_max_tech_pauses", "0", + "Number of technical pauses a team is allowed to have, 0=unlimited"); g_AutoLoadConfigCvar = CreateConVar("get5_autoload_config", "", "Name of a match config file to automatically load when the server loads"); @@ -653,6 +662,9 @@ public void OnMapStart() { g_TeamPauseTimeUsed[team] = 0; g_TeamPausesUsed[team] = 0; g_ReadyTimeWaitingUsed = 0; + g_TeamTechPausesUsed[team] = 0; + g_TechPausedTimeOverride[team] = 0; + g_TeamGivenTechPauseCommand[team] = false; } if (g_WaitingForRoundBackup) { diff --git a/scripting/get5/debug.sp b/scripting/get5/debug.sp index 25b1f37c3..466653bc7 100644 --- a/scripting/get5/debug.sp +++ b/scripting/get5/debug.sp @@ -133,7 +133,10 @@ static void AddGlobalStateInfo(File f) { f.WriteLine("g_TeamReadyOverride = %d", g_TeamReadyOverride[team]); f.WriteLine("g_TeamStartingSide = %d", g_TeamStartingSide[team]); f.WriteLine("g_TeamPauseTimeUsed = %d", g_TeamPauseTimeUsed[team]); + f.WriteLine("g_TechPausedTimeOverride = %d", g_TechPausedTimeOverride[team]); f.WriteLine("g_TeamPausesUsed = %d", g_TeamPausesUsed[team]); + f.WriteLine("g_TeamTechPausesUsed = %d", g_TeamTechPausesUsed[team]); + f.WriteLine("g_TeamGivenTechPauseCommand = %d", g_TeamGivenTechPauseCommand[team]); } } diff --git a/scripting/get5/matchconfig.sp b/scripting/get5/matchconfig.sp index c55fc6c6c..7cc618b16 100644 --- a/scripting/get5/matchconfig.sp +++ b/scripting/get5/matchconfig.sp @@ -24,6 +24,9 @@ stock bool LoadMatchConfig(const char[] config, bool restoreBackup = false) { g_TeamGivenStopCommand[team] = false; g_TeamPauseTimeUsed[team] = 0; g_TeamPausesUsed[team] = 0; + g_TeamTechPausesUsed[team] = 0; + g_TechPausedTimeOverride[team] = 0; + g_TeamGivenTechPauseCommand[team] = false; ClearArray(GetTeamAuths(team)); } diff --git a/scripting/get5/pausing.sp b/scripting/get5/pausing.sp index 4fc9e7b0f..6a603b380 100644 --- a/scripting/get5/pausing.sp +++ b/scripting/get5/pausing.sp @@ -23,6 +23,37 @@ public Action Command_TechPause(int client, int args) { } MatchTeam team = GetClientMatchTeam(client); + int maxTechPauses = g_MaxTechPauseCvar.IntValue; + + g_TeamReadyForUnpause[MatchTeam_Team1] = false; + g_TeamReadyForUnpause[MatchTeam_Team2] = false; + + // Only set these if we are a non-zero value. + if (maxTechPauses > 0 || g_MaxTechPauseTime.IntValue > 0) { + int timeLeft = g_MaxTechPauseTime.IntValue - g_TechPausedTimeOverride[team]; + // Don't allow more than one tech pause per time. + if (g_TeamGivenTechPauseCommand[MatchTeam_Team1] || g_TeamGivenTechPauseCommand[MatchTeam_Team2]) { + return Plugin_Handled; + } + if (maxTechPauses > 0 && g_TeamTechPausesUsed[team] >= maxTechPauses) { + Get5_MessageToAll("%t", "TechPauseNoTimeRemaining", g_FormattedTeamNames[team]); + return Plugin_Handled; + } else if (g_MaxTechPauseTime.IntValue > 0 && timeLeft <= 0) { + Get5_MessageToAll("%t", "TechPauseNoTimeRemaining", g_FormattedTeamNames[team]); + return Plugin_Handled; + } else { + g_TeamGivenTechPauseCommand[team] = true; + // Only create a new timer when the old one expires. + if (g_TechPausedTimeOverride[team] == 0) { + CreateTimer(1.0, Timer_TechPauseOverrideCheck, team, TIMER_REPEAT | TIMER_FLAG_NO_MAPCHANGE); + } + // Once we run out of time, subtract a tech pause used and reset the timer. + g_TeamTechPausesUsed[team]++; + int pausesLeft = maxTechPauses - g_TeamTechPausesUsed[team]; + Get5_MessageToAll("%t", "TechPausePausesRemaining", g_FormattedTeamNames[team], pausesLeft); + } + } + Pause(); EventLogger_PauseCommand(team, PauseType_Tech); LogDebug("Calling Get5_OnMatchPaused(team=%d, pauseReason=%d)", team, PauseType_Tech); @@ -128,6 +159,47 @@ public Action Command_Pause(int client, int args) { return Plugin_Handled; } +public Action Timer_TechPauseOverrideCheck(Handle timer, int data) { + MatchTeam team = view_as(data); + if (!Pauseable()) { + g_TechPausedTimeOverride[team] = 0; + g_TeamGivenTechPauseCommand[team] = false; + return Plugin_Stop; + } + + // Unlimited Tech Pause so no one can unpause unless both teams agree. + if (g_MaxTechPauseTime.IntValue <= 0) { + g_TechPausedTimeOverride[team] = 0; + return Plugin_Stop; + } + + int timeLeft = g_MaxTechPauseTime.IntValue - g_TechPausedTimeOverride[team]; + + if (InFreezeTime() && g_TeamGivenTechPauseCommand[team] && g_InExtendedPause && !g_TeamReadyForUnpause[team]) { + LogDebug("Adding tech time used. Current time = %d", g_TechPausedTimeOverride[team]); + g_TechPausedTimeOverride[team]++; + + // Every 30 seconds output a message with the time remaining before unpause. + if (timeLeft != 0) { + if (timeLeft >= 60 && timeLeft % 60 == 0) { + timeLeft = timeLeft / 60; + Get5_MessageToAll("%t", "TechPauseTimeRemainingMinutes", timeLeft); + } else if (timeLeft <= 30 && (timeLeft % 30 == 0 || timeLeft == 10)) { + Get5_MessageToAll("%t", "TechPauseTimeRemaining", timeLeft); + } + } + + if (timeLeft <= 0) { + Get5_MessageToAll("%t", "TechPauseRunoutInfoMessage"); + return Plugin_Stop; + } + } + + // Someone can call pause during a round and will set this timer. + // Keep running timer until we are paused. + return Plugin_Continue; +} + public Action Timer_UnpauseEventCheck(Handle timer, int data) { if (!Pauseable()) { g_PauseTimeUsed = 0; @@ -225,6 +297,34 @@ public Action Command_Unpause(int client, int args) { MatchTeam team = GetClientMatchTeam(client); g_TeamReadyForUnpause[team] = true; + // Get which team is currently tech paused. + MatchTeam pausedTeam = MatchTeam_TeamNone; + if (g_TeamGivenTechPauseCommand[MatchTeam_Team1]) { + pausedTeam = MatchTeam_Team1; + } else if (g_TeamGivenTechPauseCommand[MatchTeam_Team2]) { + pausedTeam = MatchTeam_Team2; + } + + if (g_InExtendedPause && g_MaxTechPauseTime.IntValue > 0) { + if (g_TechPausedTimeOverride[pausedTeam] >= g_MaxTechPauseTime.IntValue) { + Unpause(); + EventLogger_UnpauseCommand(team); + LogDebug("Calling Get5_OnMatchUnpaused(team=%d)", team); + Call_StartForward(g_OnMatchUnpaused); + Call_PushCell(team); + Call_Finish(); + if (IsPlayer(client)) { + Get5_MessageToAll("%t", "MatchUnpauseInfoMessage", client); + } + if (pausedTeam != MatchTeam_TeamNone) { + g_TeamGivenTechPauseCommand[pausedTeam] = false; + g_TechPausedTimeOverride[pausedTeam] = 0; + } + g_InExtendedPause = false; + return Plugin_Handled; + } + } + if (g_TeamReadyForUnpause[MatchTeam_Team1] && g_TeamReadyForUnpause[MatchTeam_Team2]) { Unpause(); EventLogger_UnpauseCommand(team); @@ -232,6 +332,9 @@ public Action Command_Unpause(int client, int args) { Call_StartForward(g_OnMatchUnpaused); Call_PushCell(team); Call_Finish(); + if (pausedTeam != MatchTeam_TeamNone) { + g_TeamGivenTechPauseCommand[pausedTeam] = false; + } if (IsPlayer(client)) { Get5_MessageToAll("%t", "MatchUnpauseInfoMessage", client); } diff --git a/translations/get5.phrases.txt b/translations/get5.phrases.txt index 53c5121cf..73f2ea3c7 100644 --- a/translations/get5.phrases.txt +++ b/translations/get5.phrases.txt @@ -121,6 +121,30 @@ "#format" "{1:s}" "en" "{1} has run out of pause time, unpausing the match." } + "TechPauseRunoutInfoMessage" + { + "en" "Grace period has expired for the technical pause, anyone may unpause now." + } + "TechPauseTimeRemaining" + { + "#format" "{1:d}" + "en" "{1} seconds remaining of tech pause time before anyone can resume." + } + "TechPauseTimeRemainingMinutes" + { + "#format" "{1:d}" + "en" "{1} minutes remaining of tech pause time before anyone can resume." + } + "TechPauseNoTimeRemaining" + { + "#format" "{1:s}" + "en" "Sorry, team {1} has no more tech pause time. Please use tactical pauses." + } + "TechPausePausesRemaining" + { + "#format" "{1:s},{2:d}" + "en" "Team {1} has {2} technical pauses remaining." + } "MatchUnpauseInfoMessage" { "#format" "{1:N}"