Skip to content

Commit

Permalink
Remove empty string and reply to user that last backup does not exist.
Browse files Browse the repository at this point in the history
Fix Coaching Command

It appears the regular coach command can only now be invoked if we are in warmup. So we want to check if we're in freeze time when allowing users to let us manually move them to the coaching position.

Add in coach tracking.

Add in basics for storing coaches in backup structure.

Still need to test backups, but it appears that joining the coach slot and reconnecting now forces you to coach if you had previously selected.

Fix Command_Stop wiping out the last backup CVAR.

Only drop a coach in if the coach values are empty, otherwise kick the player as we are at max capacity for the match.

Add in add coach command.

Convert auth to steam64 for coaches on add.

Add in logic to restore and move coach if in the global value.

Update coach targets based on join and .coach.

Only one person can coach per match, no more swapping.

Backups store coaches as well so this will be stored and updated on match restore.

Add in coaches_per_team config (default 2).

Update docs.

Change g_TeamCoaches to ArrayList like player auths.

Update teamjoin logic accordingly based on max coaches per team.

Equality check fix.

Length isn't zero indexed.

Rebase.

Add one more debug call for last backup file.

Add in check for stop command in debug.

Include a GoBack for the Coach KV pair.

Without this, the structure was incomplete and you would not be able to restore on first round.

Adjust Command_Stop to use local commands.

Removes an async call that is possibly cause some issues during a round restore.

Fix pausing after round restore if users have fixed timeouts.
  • Loading branch information
PhlexPlexico committed Jul 9, 2022
1 parent 92e0fb9 commit df5b2a7
Show file tree
Hide file tree
Showing 10 changed files with 196 additions and 14 deletions.
1 change: 1 addition & 0 deletions configs/get5/example_match.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
}

"players_per_team" "5"
"coaches_per_team" "2"
"min_players_to_ready" "1" // Minimum # of players a team must have to ready
"min_spectators_to_ready" "0" // How many spectators must be ready to begin.

Expand Down
1 change: 1 addition & 0 deletions configs/get5/example_match.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"matchid": "example_match",
"num_maps": 3,
"players_per_team": 1,
"coaches_per_team": 2,
"min_players_to_ready": 1,
"min_spectators_to_ready": 0,
"skip_veto": false,
Expand Down
1 change: 1 addition & 0 deletions configs/get5/scrim_template.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"scrim" "1"
"side_type" "never_knife"
"players_per_team" "5"
"coaches_per_team" "2"
"num_maps" "1"
"skip_veto" "1"

Expand Down
3 changes: 3 additions & 0 deletions documentation/docs/match_schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ match.
backup method, defaults to `0`.
- `matchtext`: Wraps `mp_teammatchstat_1`, you probably don't want to set this, in BoX series `mp_teamscore` cvars are
automatically set and take the place of the `mp_teammatchstat` cvars.
- `coaches`: Identical to the `players` tag, it's an optional list of Steam ID's for users who wish to coach a team.
You may also force player names here. This field is optional.

## Optional Values

Expand All @@ -39,6 +41,7 @@ match.
gets the side choice, "never_knife" means "team1" is always on CT first, and "always_knife" means there is always a
knife round.
- `players_per_team`: Maximum players per team (doesn't include a coach spot, default: 5).
- `coaches_per_team`: Maximum coaches per team (default: 2).
- `min_players_to_ready`: Minimum players a team needs to be able to ready up (default: 1).
- `favored_percentage_team1`: Wrapper for the servers `mp_teamprediction_pct`.
- `favored_percentage_text` Wrapper for the servers `mp_teamprediction_txt`.
Expand Down
21 changes: 16 additions & 5 deletions scripting/get5.sp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ bool g_BO2Match = false;
char g_MatchID[MATCH_ID_LENGTH];
ArrayList g_MapPoolList = null;
ArrayList g_TeamAuths[MATCHTEAM_COUNT];
ArrayList g_TeamCoaches[MATCHTEAM_COUNT];
StringMap g_PlayerNames;
char g_TeamNames[MATCHTEAM_COUNT][MAX_CVAR_LENGTH];
char g_TeamTags[MATCHTEAM_COUNT][MAX_CVAR_LENGTH];
Expand All @@ -113,6 +114,7 @@ char g_MatchTitle[MAX_CVAR_LENGTH];
int g_FavoredTeamPercentage = 0;
char g_FavoredTeamText[MAX_CVAR_LENGTH];
int g_PlayersPerTeam = 5;
int g_CoachesPerTeam = 2;
int g_MinPlayersToReady = 1;
int g_MinSpectatorsToReady = 0;
bool g_SkipVeto = false;
Expand Down Expand Up @@ -414,6 +416,8 @@ public void OnPluginStart() {
RegAdminCmd("get5_endmatch", Command_EndMatch, ADMFLAG_CHANGEMAP, "Force ends the current match");
RegAdminCmd("get5_addplayer", Command_AddPlayer, ADMFLAG_CHANGEMAP,
"Adds a steamid to a match team");
RegAdminCmd("get5_addcoach", Command_AddCoach, ADMFLAG_CHANGEMAP,
"Adds a steamid to a match teams coach slot");
RegAdminCmd("get5_removeplayer", Command_RemovePlayer, ADMFLAG_CHANGEMAP,
"Removes a steamid from a match team");
RegAdminCmd("get5_addkickedplayer", Command_AddKickedPlayer, ADMFLAG_CHANGEMAP,
Expand Down Expand Up @@ -483,6 +487,8 @@ public void OnPluginStart() {

for (int i = 0; i < sizeof(g_TeamAuths); i++) {
g_TeamAuths[i] = new ArrayList(AUTH_LENGTH);
// Same length.
g_TeamCoaches[i] = new ArrayList(AUTH_LENGTH);
}
g_PlayerNames = new StringMap();

Expand Down Expand Up @@ -959,12 +965,17 @@ public void RestoreLastRound(int client) {

char lastBackup[PLATFORM_MAX_PATH];
g_LastGet5BackupCvar.GetString(lastBackup, sizeof(lastBackup));
if (RestoreFromBackup(lastBackup)) {
Get5_MessageToAll("%t", "BackupLoadedInfoMessage", lastBackup);
// Fix the last backup cvar since it gets reset.
g_LastGet5BackupCvar.SetString(lastBackup);
if (!StrEqual(lastBackup, "")) {
if (RestoreFromBackup(lastBackup)) {
Get5_MessageToAll("%t", "BackupLoadedInfoMessage", lastBackup);
// Fix the last backup cvar since it gets reset.
g_LastGet5BackupCvar.SetString(lastBackup);
} else {
ReplyToCommand(client, "Failed to load backup %s - check error logs", lastBackup);
}
//ServerCommand("get5_loadbackup \"%s\"", lastBackup);
} else {
ReplyToCommand(client, "Failed to load backup %s - check error logs", lastBackup);
ReplyToCommand(client, "Failed to load backup, as previous round backup does not exist.");
}
}

Expand Down
4 changes: 4 additions & 0 deletions scripting/get5/debug.sp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ static void AddGlobalStateInfo(File f) {

f.WriteLine("g_MatchTitle = %s", g_MatchTitle);
f.WriteLine("g_PlayersPerTeam = %d", g_PlayersPerTeam);
f.WriteLine("g_CoachesPerTeam = %d", g_CoachesPerTeam);
f.WriteLine("g_MinPlayersToReady = %d", g_MinPlayersToReady);
f.WriteLine("g_MinSpectatorsToReady = %d", g_MinSpectatorsToReady);
f.WriteLine("g_SkipVeto = %d", g_SkipVeto);
Expand Down Expand Up @@ -137,6 +138,8 @@ static void AddGlobalStateInfo(File f) {
f.WriteLine("g_TeamPausesUsed = %d", g_TeamPausesUsed[team]);
f.WriteLine("g_TeamTechPausesUsed = %d", g_TeamTechPausesUsed[team]);
f.WriteLine("g_TeamGivenTechPauseCommand = %d", g_TeamGivenTechPauseCommand[team]);
f.WriteLine("g_TeamGivenStopCommand = %d", g_TeamGivenStopCommand[team]);
WriteArrayList(f, "g_TeamCoaches", g_TeamCoaches[team]);
}
}

Expand All @@ -155,6 +158,7 @@ static void AddInterestingCvars(File f) {
WriteCvarString(f, "get5_pausing_enabled");
WriteCvarString(f, "get5_reset_pauses_each_half");
WriteCvarString(f, "get5_web_api_url");
WriteCvarString(f, "get5_last_backup_file");
WriteCvarString(f, "mp_freezetime");
WriteCvarString(f, "mp_halftime");
WriteCvarString(f, "mp_halftime_duration");
Expand Down
72 changes: 72 additions & 0 deletions scripting/get5/matchconfig.sp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#define CONFIG_MATCHID_DEFAULT "matchid"
#define CONFIG_MATCHTITLE_DEFAULT "Map {MAPNUMBER} of {MAXMAPS}"
#define CONFIG_PLAYERSPERTEAM_DEFAULT 5
#define CONFIG_COACHESPERTEAM_DEFAULT 2
#define CONFIG_MINPLAYERSTOREADY_DEFAULT 0
#define CONFIG_MINSPECTATORSTOREADY_DEFAULT 0
#define CONFIG_SPECTATORSNAME_DEFAULT "casters"
Expand Down Expand Up @@ -32,6 +33,7 @@ stock bool LoadMatchConfig(const char[] config, bool restoreBackup = false) {
}
g_TechPausedTimeOverride[team] = 0;
g_TeamGivenTechPauseCommand[team] = false;
ClearArray(GetTeamCoaches(team));
ClearArray(GetTeamAuths(team));
}

Expand Down Expand Up @@ -274,6 +276,7 @@ public void WriteMatchToKv(KeyValues kv) {
kv.SetNum("bo2_series", g_BO2Match);
kv.SetNum("skip_veto", g_SkipVeto);
kv.SetNum("players_per_team", g_PlayersPerTeam);
kv.SetNum("coaches_per_team", g_CoachesPerTeam);
kv.SetNum("min_players_to_ready", g_MinPlayersToReady);
kv.SetNum("min_spectators_to_ready", g_MinSpectatorsToReady);
kv.SetString("match_title", g_MatchTitle);
Expand Down Expand Up @@ -335,6 +338,15 @@ static void AddTeamBackupData(KeyValues kv, MatchTeam team) {
kv.SetString("flag", g_TeamFlags[team]);
kv.SetString("logo", g_TeamLogos[team]);
kv.SetString("matchtext", g_TeamMatchTexts[team]);
kv.JumpToKey("coaches", true);
for (int i = 0; i < GetTeamCoaches(team).Length; i++) {
GetTeamCoaches(team).GetString(i, auth, sizeof(auth));
if (!g_PlayerNames.GetString(auth, name, sizeof(name))) {
strcopy(name, sizeof(name), KEYVALUE_STRING_PLACEHOLDER);
}
kv.SetString(auth, KEYVALUE_STRING_PLACEHOLDER);
}
kv.GoBack();
}
}

Expand All @@ -343,6 +355,7 @@ static bool LoadMatchFromKv(KeyValues kv) {
g_InScrimMode = kv.GetNum("scrim") != 0;
kv.GetString("match_title", g_MatchTitle, sizeof(g_MatchTitle), CONFIG_MATCHTITLE_DEFAULT);
g_PlayersPerTeam = kv.GetNum("players_per_team", CONFIG_PLAYERSPERTEAM_DEFAULT);
g_CoachesPerTeam = kv.GetNum("coaches_per_team", CONFIG_COACHESPERTEAM_DEFAULT);
g_MinPlayersToReady = kv.GetNum("min_players_to_ready", CONFIG_MINPLAYERSTOREADY_DEFAULT);
g_MinSpectatorsToReady =
kv.GetNum("min_spectators_to_ready", CONFIG_MINSPECTATORSTOREADY_DEFAULT);
Expand Down Expand Up @@ -454,6 +467,8 @@ static bool LoadMatchFromJson(JSON_Object json) {

g_PlayersPerTeam =
json_object_get_int_safe(json, "players_per_team", CONFIG_PLAYERSPERTEAM_DEFAULT);
g_CoachesPerTeam =
json_object_get_int_safe(json, "coaches_per_team", CONFIG_COACHESPERTEAM_DEFAULT);
g_MinPlayersToReady =
json_object_get_int_safe(json, "min_players_to_ready", CONFIG_MINPLAYERSTOREADY_DEFAULT);
g_MinSpectatorsToReady = json_object_get_int_safe(json, "min_spectators_to_ready",
Expand Down Expand Up @@ -574,7 +589,11 @@ static void LoadTeamDataJson(JSON_Object json, MatchTeam matchTeam) {
if (StrEqual(fromfile, "")) {
// TODO: this needs to support both an array and a dictionary
// For now, it only supports an array
JSON_Object coaches = json.GetObject("coaches");
AddJsonAuthsToList(json, "players", GetTeamAuths(matchTeam), AUTH_LENGTH);
if (coaches != null) {
AddJsonAuthsToList(json, "coaches", GetTeamCoaches(matchTeam), AUTH_LENGTH);
}
json_object_get_string_safe(json, "name", g_TeamNames[matchTeam], MAX_CVAR_LENGTH);
json_object_get_string_safe(json, "tag", g_TeamTags[matchTeam], MAX_CVAR_LENGTH);
json_object_get_string_safe(json, "flag", g_TeamFlags[matchTeam], MAX_CVAR_LENGTH);
Expand Down Expand Up @@ -603,6 +622,10 @@ static void LoadTeamData(KeyValues kv, MatchTeam matchTeam) {

if (StrEqual(fromfile, "")) {
AddSubsectionAuthsToList(kv, "players", GetTeamAuths(matchTeam), AUTH_LENGTH);
if (kv.JumpToKey("coaches")) {
AddSubsectionAuthsToList(kv, "coaches", GetTeamCoaches(matchTeam), AUTH_LENGTH);
kv.GoBack();
}
kv.GetString("name", g_TeamNames[matchTeam], MAX_CVAR_LENGTH, "");
kv.GetString("tag", g_TeamTags[matchTeam], MAX_CVAR_LENGTH, "");
kv.GetString("flag", g_TeamFlags[matchTeam], MAX_CVAR_LENGTH, "");
Expand Down Expand Up @@ -815,6 +838,55 @@ public Action Command_AddPlayer(int client, int args) {
return Plugin_Handled;
}

public Action Command_AddCoach(int client, int args) {
if (g_GameState == Get5State_None) {
ReplyToCommand(client, "Cannot change coach targets when there is no match to modify");
return Plugin_Handled;
} else if (!g_CoachingEnabledCvar.BoolValue) {
ReplyToCommand(client, "Cannot change coach targets if coaching is disabled.");
return Plugin_Handled;
}

char auth[AUTH_LENGTH];
char steam64[AUTH_LENGTH];
char teamString[32];
char name[MAX_NAME_LENGTH];
if (args >= 2 && GetCmdArg(1, auth, sizeof(auth)) &&
GetCmdArg(2, teamString, sizeof(teamString))) {
if (args >= 3) {
GetCmdArg(3, name, sizeof(name));
}

MatchTeam team = MatchTeam_TeamNone;
if (StrEqual(teamString, "team1")) {
team = MatchTeam_Team1;
} else if (StrEqual(teamString, "team2")) {
team = MatchTeam_Team2;
} else {
ReplyToCommand(client, "Unknown team: must be one of team1 or team2");
return Plugin_Handled;
}

if (GetTeamCoaches(team).Length == g_CoachesPerTeam) {
ReplyToCommand(client, "Coach Spots are full for team %s", teamString);
return Plugin_Handled;
}

if(!ConvertAuthToSteam64(auth, steam64)) {
return Plugin_Handled;
}

if (AddCoachToTeam(auth, team, name)) {
ReplyToCommand(client, "Successfully added player %s to coach team %s", auth, teamString);
} else {
ReplyToCommand(client, "Player %s is already in a coaching position on a team.", auth);
}
} else {
ReplyToCommand(client, "Usage: get5_addcoach <auth> <team1|team2> [name]");
}
return Plugin_Handled;
}

public Action Command_AddKickedPlayer(int client, int args) {
if (g_GameState == Get5State_None) {
ReplyToCommand(client, "Cannot change player lists when there is no match to modify");
Expand Down
2 changes: 2 additions & 0 deletions scripting/get5/pausing.sp
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,8 @@ public Action Command_Unpause(int client, int args) {
return Plugin_Handled;
}

// Check to see if we have a timeout that is timed. Otherwise, we need to
// continue for unpausing. New pause type to avoid match restores failing.
if (g_FixedPauseTimeCvar.BoolValue && g_PauseType == PauseType_Tactical) {
return Plugin_Handled;
}
Expand Down
Loading

0 comments on commit df5b2a7

Please sign in to comment.