1
0
Fork 0
mirror of https://codeberg.org/spire/autoexec.git synced 2026-08-02 12:14:52 +02:00
autoexec/plugin/autoexec.sp

426 lines
11 KiB
SourcePawn

#pragma semicolon 1
#include <sourcemod>
#include <sdktools>
#include <tf2>
public Plugin:myinfo = {
name = "autoexec",
author = "Icewind",
description = "Automatically execute the right config for a map",
version = "0.4",
url = "https://spire.tf"
};
new StringMap:mapPrefixMap;
new StringMap:mapOverwriteMap;
new StringMap:mapTypeMap;
new StringMap:gameModeMap;
new StringMap:configOverwriteMap;
bool inAutoExec = false;
// size 4 so we can use team indexes
bool warned[4] = {false, false, false, false};
bool initialized = false;
new ConVar:CvarLeague = null;
new ConVar:CvarMode = null;
new ConVar:CvarAutoset = null;
new ConVar:CvarWhitelist = null;
public OnPluginStart() {
mapPrefixMap = new StringMap();
mapOverwriteMap = new StringMap();
mapTypeMap = new StringMap();
gameModeMap = new StringMap();
configOverwriteMap = new StringMap();
CvarLeague = CreateConVar("sm_autoexec_league", "ugc", "league to execute the configs for (ugc or etf2l)", FCVAR_PROTECTED);
CvarLeague.AddChangeHook(PersistLeague);
CvarMode = CreateConVar("sm_autoexec_mode", "9v9", "game mode to execute the config for (9v9, 6v6 or 4v4)", FCVAR_PROTECTED);
CvarMode.AddChangeHook(PersistGameMode);
CvarAutoset = CreateConVar("sm_autoexec_autoset", "true", "try to set league and mode when a config is manually loaded (true or false)", FCVAR_PROTECTED);
CvarWhitelist = FindConVar("mp_tournament_whitelist");
RegServerCmd("sm_autoexec", AutoExec, "Execute the config for the current map and select league and game mode");
RegServerCmd("sm_getexec", GetExec, "Get the name of the config for a specific map");
RegServerCmd("exec", HandleExecAction);
mapTypeMap.SetString("5cp", "standard");
mapPrefixMap.SetString("pl_", "stopwatch");
mapPrefixMap.SetString("cp_", "5cp");
mapPrefixMap.SetString("koth_", "koth");
mapPrefixMap.SetString("ctf_", "ctf");
configOverwriteMap.SetString("ultiduo_", "etf2l_ultiduo");
configOverwriteMap.SetString("bball_", "etf2l_bball");
configOverwriteMap.SetString("ctf_bball", "etf2l_bball");
mapOverwriteMap.SetString("cp_steel", "stopwatch");
mapOverwriteMap.SetString("cp_gravelpit", "stopwatch");
mapOverwriteMap.SetString("cp_hadal", "stopwatch");
mapOverwriteMap.SetString("cp_alloy", "stopwatch");
gameModeMap.SetString("9v9", "hl");
gameModeMap.SetString("6v6", "6v");
HookEvent("tournament_stateupdate", OnReadyUp, EventHookMode_Post);
}
public OnMapStart() {
CreateTimer(3.0, RestoreCfg);
}
public RestoreCfg() {
RestoreGameMode();
RestoreLeague();
ExecMapCfg();
initialized = true;
}
public ExecMapCfg() {
decl String:config[128];
decl String:map[128];
GetCurrentMap(map, sizeof(map));
GetConfig(map, config);
ExecCFG(config);
}
public Action:HandleExecAction(args) {
new String:cfg[128];
GetCmdArg(1, cfg, sizeof(cfg));
decl String:autoset[8];
GetConVarString(CvarAutoset, autoset, sizeof(autoset));
warned[2] = false;
warned[3] = false;
if (strncmp("true", autoset, sizeof(autoset)) != 0 || inAutoExec) {
return Plugin_Continue;
}
if (StrContains(cfg, "etf2l_") == 0) {
PrintToChatAll("Setting league to etf2l");
SetConVarString(CvarLeague, "etf2l");
}
if (StrContains(cfg, "ugc_") == 0) {
PrintToChatAll("Setting league to ugc");
SetConVarString(CvarLeague, "ugc");
}
if ((StrContains(cfg, "9v9_") > 0) || (StrContains(cfg, "hl_") > 0)) {
PrintToChatAll("Setting game mode to 9v9");
SetGameMode("9v9");
}
if (StrContains(cfg, "6v6_") > 0) {
PrintToChatAll("Setting game mode to 6v6");
SetGameMode("6v6");
}
if (StrContains(cfg, "6v_") > 0) {
PrintToChatAll("Setting game mode to 6v6");
SetGameMode("6v6");
}
if (StrContains(cfg, "4v4_") > 0) {
PrintToChatAll("Setting game mode to 4v4");
SetGameMode("4v4");
}
if (StrContains(cfg, "ultiduo") > 0) {
PrintToChatAll("Setting game mode to 2v2");
SetGameMode("2v2");
}
return Plugin_Continue;
}
public Action:GetExec(args) {
new String:map[128];
GetCmdArg(1, map, sizeof(map));
decl String:config[128];
GetConfig(map, config);
PrintToChatAll("Config: %s", config);
return Plugin_Handled;
}
public Action:AutoExec(args) {
decl String:config[128];
decl String:map[128];
GetCurrentMap(map, sizeof(map));
GetConfig(map, config);
ExecCFG(config);
return Plugin_Handled;
}
public PrefixSearch(StringMap:map, String:query[128], String:result[128]) {
new StringMapSnapshot:keys = map.Snapshot();
decl String:key[16];
new length = keys.Length;
bool found = false;
for (new i = 0; i < length; i++) {
keys.GetKey(i, key, sizeof(key));
if (strncmp(key, query, strlen(key)) == 0) {
found = true;
map.GetString(key, result, sizeof(result));
break;
}
}
CloseHandle(keys);
return found;
}
public GetConfig(String:map[128], String:config[128]) {
decl String:mapType[128];
decl String:league[8];
decl String:gamemode[8];
if (PrefixSearch(configOverwriteMap, map, config)) {
return;
}
GetLeague(league);
GetLeagueMapType(map, mapType, league);
GetGameMode(gamemode, league);
Format(config, sizeof(config), "%s_%s_%s", league, gamemode, mapType);
}
public GetLeague(String:league[8]) {
GetConVarString(CvarLeague, league, sizeof(league));
}
public GetGameMode(String:leagueGamemode[8], String:league[8]) {
decl String:gamemode[8];
GetConVarString(CvarMode, gamemode, sizeof(gamemode));
if (strncmp("ugc", league, strlen(league)) == 0) {
if (gameModeMap.GetString(gamemode, leagueGamemode, sizeof(leagueGamemode))) {
return;
}
}
leagueGamemode = gamemode;
}
public void SetGameMode(String:mode[8]) {
SetConVarString(CvarMode, mode);
}
public void PersistGameMode(ConVar convar, const char[] oldValue, const char[] newValue) {
if (!initialized) {
return;
}
File file = OpenFile("autoexec_gamemode", "w");
file.WriteString(newValue, -1);
file.Close();
}
public void RestoreGameMode() {
decl String:mode[8];
File file = OpenFile("autoexec_gamemode", "r");
if (file) {
file.ReadString(mode, 8, -1);
file.Close();
SetConVarString(CvarMode, mode);
}
}
public void PersistLeague(ConVar convar, const char[] oldValue, const char[] newValue) {
if (!initialized) {
return;
}
File file = OpenFile("autoexec_league", "w");
file.WriteString(newValue, -1);
file.Close();
}
public void RestoreLeague() {
decl String:league[8];
File file = OpenFile("autoexec_league", "r");
if (file) {
file.ReadString(league, 8, -1);
file.Close();
SetConVarString(CvarLeague, league);
}
}
public GetLeagueMapType(String:map[128], String:leagueMapType[128], String:league[8]) {
decl String:mapType[128];
GetMapType(map, mapType);
if (strncmp("ugc", league, strlen(league)) == 0) {
if (mapTypeMap.GetString(mapType, leagueMapType, sizeof(leagueMapType))) {
return;
}
}
leagueMapType = mapType;
}
public GetMapType(String:map[128], String:mapType[128]) {
if (PrefixSearch(mapOverwriteMap, map, mapType)) {
return;
}
if (!PrefixSearch(mapPrefixMap, map, mapType)) {
mapType = "5cp"; //fallback
}
return;
}
public ExecCFG(String:cfg[128]) {
decl String:command[256];
Format(command, sizeof(command), "exec %s", cfg);
// dont trigger autoset
inAutoExec = true;
ServerCommand(command, sizeof(command));
CreateTimer(1.0, clearInAutoExec); // give the config time to load before clearing
}
public Action clearInAutoExec(Handle timer) {
inAutoExec = false;
return Plugin_Continue;
}
public void OnReadyUp(Event event, const String:name[], bool:dontBroadcast) {
bool redReady = IsReady(2);
bool blueReady = IsReady(3);
CheckWhitelist();
if (redReady) {
CheckPlayerCount(2);
}
if (blueReady) {
CheckPlayerCount(3);
}
}
public void CheckPlayerCount(int team) {
int playerCount = GetTeamClientCount(team);
int otherPlayerCount = GetTeamClientCount(OtherTeam(team));
decl String:gameMode[8];
GetConVarString(CvarMode, gameMode, sizeof(gameMode));
int expected = ExpectedPlayerCount(gameMode);
if (playerCount != expected) {
decl String:expectedMode[8];
decl String:expectedModeOther[8];
ExpectedGameMode(playerCount, expectedMode);
ExpectedGameMode(otherPlayerCount, expectedModeOther);
bool gotExpectedMode = !(strncmp("unknown", expectedMode, sizeof(expectedMode)) == 0);
if (gotExpectedMode && strncmp(expectedMode, expectedModeOther, strlen(expectedMode)) == 0) {
PrintToChatAll("Switching config to %s", expectedMode);
SetGameMode(expectedMode);
ExecMapCfg();
CreateTimer(0.5, ReadyTeamTimer, team);
return;
}
}
if (expected != 0 && !warned[team]) {
if (playerCount != expected) {
warned[team] = true;
PrintToChatAll("Warning, config is set to %s but you readied up with %d players", gameMode, playerCount);
UnReadyTeam(team);
} else {
warned[team] = true;
}
}
}
public bool IsReady(int team) {
return GameRules_GetProp("m_bTeamReady", 1, .element = team) != 0;
}
public void ReadyTeamTimer(Handle _timer, int team) {
ReadyTeam(team);
}
public void ReadyTeam(int team) {
GameRules_SetProp("m_bTeamReady", 1, _ , team, true);
}
public void UnReadyTeam(int team) {
GameRules_SetProp("m_bTeamReady", 0, _ , team, true);
}
public void CheckWhitelist() {
decl String:whitelist[128];
GetConVarString(CvarWhitelist, whitelist, sizeof(whitelist));
decl String:expected[128];
GetExpectedWhitelist(expected);
if (strncmp(expected, whitelist, strlen(whitelist)) == 0) {
PrintToChatAll("Warning, incorrect whitelist loaded for game mode: %s", whitelist);
}
}
public GetExpectedWhitelist(String:whitelist[128]) {
decl String:league[8];
decl String:gamemode[8];
whitelist = "";
if (strncmp("ugc", league, strlen(league)) == 0) {
if (strncmp("9v9", gamemode, strlen(gamemode)) == 0) {
whitelist = "cfg/item_whitelist_ugc_HL.txt";
} else if (strncmp("6v6", gamemode, strlen(gamemode)) == 0) {
whitelist = "cfg/item_whitelist_ugc_6v6.txt";
}
} else if (strncmp("etf2l", league, strlen(league)) == 0) {
if (strncmp("9v9", gamemode, strlen(gamemode)) == 0) {
whitelist = "cfg/etf2l_whitelist_9v9.txt";
} else if (strncmp("6v6", gamemode, strlen(gamemode)) == 0) {
whitelist = "cfg/etf2l_whitelist_6v6.txt";
}
}
}
public int OtherTeam(int team) {
if (team == 2) {
return 3;
} else {
return 2;
}
}
public int ExpectedPlayerCount(String:gamemode[8]) {
if (strcmp(gamemode, "9v9") == 0) {
return 9;
} else if (strcmp(gamemode, "6v6") == 0) {
return 6;
} else if (strcmp(gamemode, "4v4") == 0) {
return 4;
} else if (strcmp(gamemode, "2v2") == 0) {
return 2;
} else {
return 0;
}
}
public void ExpectedGameMode(int count, String:mode[8]) {
if (count == 9 || count == 8) {
mode = "9v9";
} else if (count == 5 || count == 6) {
mode = "6v6";
} else if (count == 3 || count == 4) {
mode = "4v4";
} else if (count == 2) {
mode = "2v2";
} else {
mode = "unknown";
}
}