Skip to content

Commit

Permalink
Fix problems with game going directly to live due to poorly timed swa…
Browse files Browse the repository at this point in the history
…p/stay commands (#880)
  • Loading branch information
nickdnk authored Sep 16, 2022
1 parent b22ce41 commit e9451ba
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 30 deletions.
13 changes: 9 additions & 4 deletions scripting/get5.sp
Original file line number Diff line number Diff line change
Expand Up @@ -669,7 +669,11 @@ static Action Timer_InfoMessages(Handle timer) {
g_MapChangePending && GetTvDelay() > 0) {
Get5_MessageToAll("%t", "WaitingForGOTVVetoInfoMessage");
} else if (g_GameState == Get5State_WaitingForKnifeRoundDecision) {
// Handle waiting for knife decision
if (g_KnifeWinnerTeam == Get5Team_None) {
return Plugin_Continue;
}
// Handle waiting for knife decision. Also check g_KnifeWinnerTeam as there is a small delay between
// selecting a side and the game state changing, during which this message should not be printed.
char formattedStayCommand[64];
FormatChatCommand(formattedStayCommand, sizeof(formattedStayCommand), "!stay");
char formattedSwapCommand[64];
Expand Down Expand Up @@ -1455,9 +1459,7 @@ static Action Event_RoundStart(Event event, const char[] name, bool dontBroadcas
}

// We cannot do this during warmup, as sending users into warmup post-knife triggers a round start
// event. We add an extra restart to clear lingering state from the knife round, such as the round
// indicator in the middle of the scoreboard not being reset. This also tightly couples the
// live-announcement to the actual live start.
// event.
if (!InWarmup()) {
if (g_GameState == Get5State_WaitingForKnifeRoundDecision) {
// Ensures that round end after knife sends players directly into warmup.
Expand All @@ -1471,6 +1473,9 @@ static Action Event_RoundStart(Event event, const char[] name, bool dontBroadcas
if (g_GameState == Get5State_GoingLive) {
LogDebug("Changed to live.");
ChangeState(Get5State_Live);
// We add an extra restart to clear lingering state from the knife round, such as the round
// indicator in the middle of the scoreboard not being reset. This also tightly couples the
// live-announcement to the actual live start.
RestartGame();
CreateTimer(3.0, Timer_MatchLive, _, TIMER_FLAG_NO_MAPCHANGE);
return; // Next round start will take care of below, such as writing backup.
Expand Down
39 changes: 19 additions & 20 deletions scripting/get5/goinglive.sp
Original file line number Diff line number Diff line change
@@ -1,41 +1,40 @@
void StartGoingLive() {
LogDebug("StartGoingLive");
ExecCfg(g_LiveCfgCvar);

Get5GoingLiveEvent liveEvent = new Get5GoingLiveEvent(g_MatchID, g_MapNumber);

LogDebug("Calling Get5_OnGoingLive()");

Call_StartForward(g_OnGoingLive);
Call_PushCell(liveEvent);
Call_Finish();

EventLogger_LogAndDeleteEvent(liveEvent);

ChangeState(Get5State_GoingLive);

// This ensures that we can send send the game to warmup and count down *even if* someone had put
// "mp_warmup_end", or something else that would mess up warmup, in their live config, which they
// shouldn't. But we can't be sure.
CreateTimer(1.0, Timer_GoToLiveAfterWarmupCountdown, _, TIMER_FLAG_NO_MAPCHANGE);
CreateTimer(1.0, Timer_GoToLive, _, TIMER_FLAG_NO_MAPCHANGE);
}

static Action Timer_GoToLiveAfterWarmupCountdown(Handle timer) {
if (g_GameState != Get5State_GoingLive) {
return Plugin_Handled; // super defensive race-condition check.
static Action Timer_GoToLive(Handle timer) {
if (g_GameState != Get5State_Warmup && g_GameState != Get5State_WaitingForKnifeRoundDecision) {
// super defensive race-condition check. These are the only two allowed states
// for this callback, so if the game had been canceled during this time, do nothing.
return;
}
// Always disable sv_cheats!
ServerCommand("sv_cheats 0");
// Ensure we're in warmup and counting down to live. Round_PreStart handles the rest.
int countdown = g_LiveCountdownTimeCvar.IntValue;
if (countdown < 5) {
countdown =
5; // ensures that a cvar countdown value of 0 does not leave the game forever in warmup.
// ensures that a cvar countdown value of 0 does not leave the game forever in warmup.
countdown = 5;
}
Get5_MessageToAll("%t", "MatchBeginInSecondsInfoMessage", countdown);
StartWarmup(countdown);
LogDebug("Started warmup countdown to live in %d seconds.", countdown);
return Plugin_Handled;

// Change state as we're now counting down to live from warmup.
ChangeState(Get5State_GoingLive);

// Going live event
Get5GoingLiveEvent liveEvent = new Get5GoingLiveEvent(g_MatchID, g_MapNumber);
LogDebug("Calling Get5_OnGoingLive()");
Call_StartForward(g_OnGoingLive);
Call_PushCell(liveEvent);
Call_Finish();
EventLogger_LogAndDeleteEvent(liveEvent);
}

Action Timer_MatchLive(Handle timer) {
Expand Down
9 changes: 5 additions & 4 deletions scripting/get5/kniferounds.sp
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,11 @@ static void EndKnifeRound(bool swap) {
}

static bool AwaitingKnifeDecision(int client) {
bool waiting = g_GameState == Get5State_WaitingForKnifeRoundDecision;
if (g_GameState != Get5State_WaitingForKnifeRoundDecision || g_KnifeWinnerTeam == Get5Team_None) {
return false;
}
bool onWinningTeam = IsPlayer(client) && GetClientMatchTeam(client) == g_KnifeWinnerTeam;
bool admin = (client == 0);
return waiting && (onWinningTeam || admin);
return onWinningTeam || (client == 0);
}

Action Command_Stay(int client, int args) {
Expand Down Expand Up @@ -152,7 +153,7 @@ Action Command_T(int client, int args) {

Action Timer_ForceKnifeDecision(Handle timer) {
g_KnifeDecisionTimer = INVALID_HANDLE;
if (g_GameState == Get5State_WaitingForKnifeRoundDecision) {
if (g_GameState == Get5State_WaitingForKnifeRoundDecision && g_KnifeWinnerTeam != Get5Team_None) {
Get5_MessageToAll("%t", "TeamLostTimeToDecideInfoMessage",
g_FormattedTeamNames[g_KnifeWinnerTeam]);
EndKnifeRound(false);
Expand Down
2 changes: 1 addition & 1 deletion scripting/get5/version.sp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#tryinclude "manual_version.sp"
#if !defined PLUGIN_VERSION
#define PLUGIN_VERSION "0.10.2-dev"
#define PLUGIN_VERSION "0.10.3-dev"
#endif

// This MUST be the latest version in x.y.z semver format followed by -dev.
Expand Down
2 changes: 1 addition & 1 deletion scripting/include/get5.inc
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ enum Get5State {
Get5State_Warmup, // setup done, waiting for players to ready up
Get5State_KnifeRound, // in the knife round
Get5State_WaitingForKnifeRoundDecision, // waiting for a .stay/.swap command after the knife
Get5State_GoingLive, // in the lo3 process
Get5State_GoingLive, // counting down to live
Get5State_Live, // the match is live
Get5State_PostGame, // postgame screen + waiting for GOTV to finish broadcast
};
Expand Down

0 comments on commit e9451ba

Please sign in to comment.