diff --git a/.gitmodules b/.gitmodules index ea703b85..36040835 100644 --- a/.gitmodules +++ b/.gitmodules @@ -50,3 +50,6 @@ [submodule "sm_plugins/TF2-Dodgeball-Modified"] path = sm_plugins/TF2-Dodgeball-Modified url = https://github.com/Silorak/TF2-Dodgeball-Modified.git +[submodule "sm_plugins/mge"] + path = sm_plugins/mge + url = git@github.com:leighmacdonald/MGEMod.git diff --git a/requirements.yml b/requirements.yml index 7bb04928..7a14b360 100644 --- a/requirements.yml +++ b/requirements.yml @@ -6,6 +6,3 @@ collections: roles: - name: hadret.rsyslog - - name: githubixx.ansible_role_wireguard - src: https://github.com/githubixx/ansible-role-wireguard.git - version: 17.1.0 diff --git a/roles/sourcemod/files/addons/sourcemod/scripting/gbans.sp b/roles/sourcemod/files/addons/sourcemod/scripting/gbans.sp index 6a93b37f..f66bd9a7 100644 --- a/roles/sourcemod/files/addons/sourcemod/scripting/gbans.sp +++ b/roles/sourcemod/files/addons/sourcemod/scripting/gbans.sp @@ -28,7 +28,6 @@ bool LateLoaded; bool PlayerStatus[MAXPLAYERS + 1]; - public Plugin myinfo = { name = "gbans", @@ -38,6 +37,7 @@ public Plugin myinfo = url = "https://github.com/leighmacdonald/gbans", }; + public void OnPluginStart() { LoadTranslations("common.phrases.txt"); @@ -46,14 +46,17 @@ public void OnPluginStart() RegConsoleCmd("gb_help", onCmdHelp, "Get a list of gbans commands"); RegConsoleCmd("gb_mod", onCmdMod, "Ping a moderator"); RegConsoleCmd("mod", onCmdMod, "Ping a moderator"); + RegConsoleCmd("seed", onCmdSeed, "Send a seed request to discord"); + RegConsoleCmd("report", onCmdReport, "Report a player"); RegConsoleCmd("autoteam", onCmdAutoTeamAction); RegAdminCmd("gb_ban", onAdminCmdBan, ADMFLAG_BAN); RegAdminCmd("gb_reload", onAdminCmdReload, ADMFLAG_ROOT); + RegAdminCmd("gb_stv_record", Command_Record, ADMFLAG_KICK, "Starts a SourceTV demo"); RegAdminCmd("gb_stv_stoprecord", Command_StopRecord, ADMFLAG_KICK, "Stops the current SourceTV demo"); - + HookEvent("player_disconnect", Event_PlayerDisconnect, EventHookMode_Pre); HookEvent("player_connect_client", Event_PlayerConnect, EventHookMode_Pre); @@ -61,7 +64,7 @@ public void OnPluginStart() // Core settings gb_core_host = AutoExecConfig_CreateConVar("gb_core_host", "localhost", "Remote gbans host", FCVAR_NONE); - gb_core_port = AutoExecConfig_CreateConVar("gb_core_port", "6006", "Remote gbans port", FCVAR_NONE, true, 1.0, true, 65535.0); + gb_core_port = AutoExecConfig_CreateConVar("gb_core_port", "6006", "Remote gbans port", FCVAR_NONE, true, 1.0, true, 65535.0); gb_core_server_key = AutoExecConfig_CreateConVar("gb_core_server_key", "", "GBans server key used to authenticate with the service", FCVAR_NONE); // In Game Tweaks @@ -77,14 +80,14 @@ public void OnPluginStart() gb_stv_timestop = AutoExecConfig_CreateConVar("gb_stv_timestop", "-1", "Hour in the day to stop recording (0-23, -1 disables)", FCVAR_NONE); gb_stv_finishmap = AutoExecConfig_CreateConVar("gb_stv_finishmap", "1", "If 1, continue recording until the map ends", FCVAR_NONE, true, 0.0, true, 1.0); gb_stv_path = AutoExecConfig_CreateConVar("gb_stv_path", "stv_demos/active", "Path to store currently recording demos", FCVAR_NONE); - gb_stv_path_complete = AutoExecConfig_CreateConVar("gb_stv_path_complete", "stv_demos/complete", "Path to store complete demos", FCVAR_NONE); + gb_stv_path_complete = AutoExecConfig_CreateConVar("gb_stv_path_complete", "stv_demos/complete", "Path to store complete demos", FCVAR_NONE); AutoExecConfig_ExecuteFile(); AutoExecConfig_CleanFile(); //BuildPath(Path_SM, logFile, sizeof(logFile), "logs/gbans.log"); - if (LateLoaded) + if(LateLoaded) { AccountForLateLoading(); } @@ -92,26 +95,27 @@ public void OnPluginStart() reloadAdmins(true); } + stock void AccountForLateLoading() { char auth[30]; - for (int i = 1; i <= MaxClients; i++) + for(int i = 1; i <= MaxClients; i++) { - if (IsClientConnected(i) && !IsFakeClient(i)) + if(IsClientConnected(i) && !IsFakeClient(i)) { PlayerStatus[i] = false; } - if (IsClientInGame(i) && !IsFakeClient(i) && IsClientAuthorized(i) && GetClientAuthId(i, AuthId_Steam2, auth, sizeof(auth))) + if(IsClientInGame(i) && !IsFakeClient(i) && IsClientAuthorized(i) && GetClientAuthId(i, AuthId_Steam2, auth, sizeof auth)) { checkPlayer(i); } } } -public void OnConfigsExecuted() { - +public void OnConfigsExecuted() +{ gb_stv_minplayers.AddChangeHook(OnConVarChanged); gb_stv_ignorebots.AddChangeHook(OnConVarChanged); gb_stv_timestart.AddChangeHook(OnConVarChanged); @@ -120,7 +124,7 @@ public void OnConfigsExecuted() { char sPath[PLATFORM_MAX_PATH]; - gb_stv_path.GetString(sPath, sizeof(sPath)); + gb_stv_path.GetString(sPath, sizeof sPath); if(!DirExists(sPath)) { initDirectory(sPath); @@ -135,11 +139,11 @@ public void OnConfigsExecuted() { CreateTimer(300.0, Timer_CheckStatus, _, TIMER_REPEAT); - StopRecord(); + StopRecord(); if(!gStvMapChanged) { - // STV does not function until a map change has occurred. +// STV does not function until a map change has occurred. gbLog("Restarting map to enabled STV"); gStvMapChanged = true; char mapName[128]; @@ -148,11 +152,13 @@ public void OnConfigsExecuted() { } } + public void OnClientDisconnect_Post(int client) { CheckStatus(); } + public void OnMapEnd() { if(gIsRecording) @@ -162,15 +168,18 @@ public void OnMapEnd() } } -public void OnMapStart() { + +public void OnMapStart() +{ reloadAdmins(true); } + public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) { CreateNative("GB_BanClient", Native_GB_BanClient); LateLoaded = late; - + return APLRes_Success; } diff --git a/roles/sourcemod/files/addons/sourcemod/scripting/gbans/auth.sp b/roles/sourcemod/files/addons/sourcemod/scripting/gbans/auth.sp index 1f1c0bd1..ca5baa9b 100644 --- a/roles/sourcemod/files/addons/sourcemod/scripting/gbans/auth.sp +++ b/roles/sourcemod/files/addons/sourcemod/scripting/gbans/auth.sp @@ -42,7 +42,6 @@ void checkPlayer(int clientId) char clientAuth[64]; GetClientAuthId(clientId, AuthId_SteamID64, clientAuth, sizeof(clientAuth)); - JSONObject obj = new JSONObject(); obj.SetString("steam_id", clientAuth); obj.SetInt("client_id", clientId); @@ -61,44 +60,44 @@ void checkPlayer(int clientId) } -void onCheckResp(HTTPResponse response, any value) -{ +void onCheckResp(HTTPResponse response, any value) { gbLog("--- onCheckResp"); - if (response.Status != HTTPStatus_OK) { - LogError("Invalid check response code: %d", response.Status); - - return; - } - - JSONObject data = view_as(response.Data); - - char msg[256]; - data.GetString("msg", msg, sizeof msg); - int clientId = data.GetInt("client_id"); - int banType = data.GetInt("ban_type"); - - switch(banType) - { - case BSNoComm: { - if(!BaseComm_IsClientMuted(clientId)) { - BaseComm_SetClientMute(clientId, true); + switch (response.Status) { + case HTTPStatus_OK: + // good boi + return; + case HTTPStatus_Forbidden: { + JSONObject data = view_as(response.Data); + + char msg[256]; + data.GetString("msg", msg, sizeof msg); + int clientId = data.GetInt("client_id"); + int banType = data.GetInt("ban_type"); + + switch(banType) { + case BSNoComm: { + if(!BaseComm_IsClientMuted(clientId)) { + BaseComm_SetClientMute(clientId, true); + } + if(!BaseComm_IsClientGagged(clientId)){ + BaseComm_SetClientGag(clientId, true); + } + ReplyToCommand(clientId, "You are currently muted/gag, it will expire automatically"); + gbLog("Muted \"%L\" for an unfinished mute punishment.", clientId); } - if(!BaseComm_IsClientGagged(clientId)){ - BaseComm_SetClientGag(clientId, true); + case BSNetwork: { + KickClient(clientId, msg); + LogAction(0, clientId, "Kicked \"%L\" for a network block.", clientId); + } + case BSBanned: { + KickClient(clientId, msg); + LogAction(0, clientId, "Kicked \"%L\" for an unfinished ban.", clientId); } - ReplyToCommand(clientId, "You are currently muted/gag, it will expire automatically"); - gbLog("Muted \"%L\" for an unfinished mute punishment.", clientId); - } - case BSNetwork: - { - KickClient(clientId, msg); - LogAction(0, clientId, "Kicked \"%L\" for a network block.", clientId); - } - case BSBanned: - { - KickClient(clientId, msg); - LogAction(0, clientId, "Kicked \"%L\" for an unfinished ban.", clientId); } } - + default: { + LogError("Invalid check response code: %d", response.Status); + } + } } + diff --git a/roles/sourcemod/files/addons/sourcemod/scripting/gbans/commands.sp b/roles/sourcemod/files/addons/sourcemod/scripting/gbans/commands.sp index b9f00073..3a65c9d7 100644 --- a/roles/sourcemod/files/addons/sourcemod/scripting/gbans/commands.sp +++ b/roles/sourcemod/files/addons/sourcemod/scripting/gbans/commands.sp @@ -64,9 +64,7 @@ public Action onCmdMod(int clientId, int argc) return Plugin_Handled; } - -void onPingModRespReceived(HTTPResponse response, any clientId) -{ +void onPingModRespReceived(HTTPResponse response, any clientId) { if (response.Status != HTTPStatus_OK) { LogError("Invalid report response code: %d", response.Status); @@ -75,6 +73,45 @@ void onPingModRespReceived(HTTPResponse response, any clientId) ReplyToCommand(clientId, "Mods have been alerted, thanks!"); } +public Action onCmdSeed(int clientId, int argc) { + + ReplyToCommand(clientId, "Computering..."); + char auth_id[50]; + if(!GetClientAuthId(clientId, AuthId_Steam3, auth_id, sizeof auth_id, true)) + { + ReplyToCommand(clientId, "Failed to get auth_id of user: %d", clientId); + return Plugin_Continue; + } + + char url[1024]; + makeURL("/api/sm/seed", url, sizeof url); + StrCat(url, sizeof url, "?steam_id="); + StrCat(url, sizeof url, auth_id); + + + HTTPRequest request = new HTTPRequest(url); + addAuthHeader(request); + request.Get(onCmdSeedReceived, clientId); + + return Plugin_Handled; +} + +void onCmdSeedReceived(HTTPResponse response, any clientId) { + switch (response.Status) { + case HTTPStatus_TooManyRequests: { + ReplyToCommand(clientId, "Please wait before making new seed requests (5min cooldown)"); + return; + } + case HTTPStatus_OK: { + ReplyToCommand(clientId, "Mods have been alerted, thanks!"); + return; + } + default: { + ReplyToCommand(clientId, "Got invalid response code :("); + return; + } + } +} public Action onCmdHelp(int clientId, int argc) { diff --git a/roles/sourcemod/files/addons/sourcemod/scripting/gbans/globals.sp b/roles/sourcemod/files/addons/sourcemod/scripting/gbans/globals.sp index 2f018a84..40d21eb7 100644 --- a/roles/sourcemod/files/addons/sourcemod/scripting/gbans/globals.sp +++ b/roles/sourcemod/files/addons/sourcemod/scripting/gbans/globals.sp @@ -2,7 +2,7 @@ #pragma tabsize 4 #pragma newdecls required -#define PLUGIN_VERSION "0.7.33" +#define PLUGIN_VERSION "0.7.36" #define MAX_SCORES 256 diff --git a/roles/sourcemod/files/addons/sourcemod/scripting/mge.sp b/roles/sourcemod/files/addons/sourcemod/scripting/mge.sp index 9640558d..98d676ab 100644 --- a/roles/sourcemod/files/addons/sourcemod/scripting/mge.sp +++ b/roles/sourcemod/files/addons/sourcemod/scripting/mge.sp @@ -95,7 +95,6 @@ bool g_bBlockFallDamage, g_bAutoCvar; int - g_iDBDriver, g_iDefaultFragLimit, g_iAirshotHeight = 80; @@ -584,9 +583,9 @@ void OnProjectileTouch(int entity, int other) * * Called once a client is fully in-game, and authorized with Steam. * Client-specific variables are initialized here. - * + * * NOTE: This needs to not be here. This will break when steam is down, this probably has other issues as well - * + * * Most of this should be in OnClientPutInServer * -------------------------------------------------------------------------- */ public void OnClientPostAdminCheck(int client) @@ -623,7 +622,7 @@ public void OnClientPostAdminCheck(int client) GetClientAuthId(client, AuthId_Steam2, steamid_dirty, sizeof(steamid_dirty)); db.Escape(steamid_dirty, steamid, sizeof(steamid)); strcopy(g_sPlayerSteamID[client], 32, steamid); - Format(query, sizeof(query), "SELECT rating, hitblip, wins, losses FROM mgemod_stats WHERE steamid='%s' LIMIT 1", steamid); + Format(query, sizeof(query), "SELECT rating, hitblip, wins, losses FROM mgemod_stats WHERE steamid=text_to_steam64('%s')", steamid); db.Query(T_SQLQueryOnConnect, query, client); } } @@ -2191,17 +2190,17 @@ void CalcELO(int winner, int loser) int winner_team_slot = (g_iPlayerSlot[winner] > 2) ? (g_iPlayerSlot[winner] - 2) : g_iPlayerSlot[winner]; int loser_team_slot = (g_iPlayerSlot[loser] > 2) ? (g_iPlayerSlot[loser] - 2) : g_iPlayerSlot[loser]; - Format(query, sizeof(query), "INSERT INTO mgemod_duels (winner, loser, winnerscore, loserscore, winlimit, gametime, mapname, arenaname) VALUES ('%s', '%s', %i, %i, %i, %i, '%s', '%s')", + Format(query, sizeof(query), "INSERT INTO mgemod_duels (winner, loser, winnerscore, loserscore, winlimit, gametime, mapname, arenaname) VALUES (text_to_steam64('%s'), text_to_steam64('%s'), %i, %i, %i, %i, '%s', '%s')", g_sPlayerSteamID[winner], g_sPlayerSteamID[loser], g_iArenaScore[arena_index][winner_team_slot], g_iArenaScore[arena_index][loser_team_slot], g_iArenaFraglimit[arena_index], time, g_sMapName, g_sArenaName[arena_index]); db.Query(SQLErrorCheckCallback, query); //winner's stats - Format(query, sizeof(query), "UPDATE mgemod_stats SET rating=%i,wins=wins+1,lastplayed=%i WHERE steamid='%s'", + Format(query, sizeof(query), "UPDATE mgemod_stats SET rating=%i,wins=wins+1,lastplayed=%i WHERE steamid=text_to_steam64('%s')", g_iPlayerRating[winner], time, g_sPlayerSteamID[winner]); db.Query(SQLErrorCheckCallback, query); //loser's stats - Format(query, sizeof(query), "UPDATE mgemod_stats SET rating=%i,losses=losses+1,lastplayed=%i WHERE steamid='%s'", + Format(query, sizeof(query), "UPDATE mgemod_stats SET rating=%i,losses=losses+1,lastplayed=%i WHERE steamid=text_to_steam64('%s')", g_iPlayerRating[loser], time, g_sPlayerSteamID[loser]); db.Query(SQLErrorCheckCallback, query); } @@ -2247,29 +2246,27 @@ void CalcELO2(int winner, int winner2, int loser, int loser2) if (IsValidClient(loser2) && !g_bNoDisplayRating) MC_PrintToChat(loser2, "%t", "LostPoints", loserscore); - - Format(query, sizeof(query), "INSERT INTO mgemod_duels_2v2 (winner, winner2, loser, loser2, winnerscore, loserscore, winlimit, gametime, mapname, arenaname) VALUES ('%s', '%s', '%s', '%s', %i, %i, %i, %i, '%s', '%s')", + Format(query, sizeof(query), "INSERT INTO mgemod_duels_2v2 (winner, winner2, loser, loser2, winnerscore, loserscore, winlimit, gametime, mapname, arenaname) VALUES (text_to_steam64('%s'), text_to_steam64('%s'), text_to_steam64('%s'), text_to_steam64('%s'), %i, %i, %i, %i, '%s', '%s')", g_sPlayerSteamID[winner], g_sPlayerSteamID[winner2], g_sPlayerSteamID[loser], g_sPlayerSteamID[loser2], g_iArenaScore[arena_index][winner_team_slot], g_iArenaScore[arena_index][loser_team_slot], g_iArenaFraglimit[arena_index], time, g_sMapName, g_sArenaName[arena_index]); db.Query(SQLErrorCheckCallback, query); - //winner's stats - Format(query, sizeof(query), "UPDATE mgemod_stats SET rating=%i,wins=wins+1,lastplayed=%i WHERE steamid='%s'", + Format(query, sizeof(query), "UPDATE mgemod_stats SET rating=%i,wins=wins+1,lastplayed=%i WHERE steamid=text_to_steam64('%s')", g_iPlayerRating[winner], time, g_sPlayerSteamID[winner]); db.Query(SQLErrorCheckCallback, query); //winner's teammate stats - Format(query, sizeof(query), "UPDATE mgemod_stats SET rating=%i,wins=wins+1,lastplayed=%i WHERE steamid='%s'", + Format(query, sizeof(query), "UPDATE mgemod_stats SET rating=%i,wins=wins+1,lastplayed=%i WHERE steamid=text_to_steam64('%s')", g_iPlayerRating[winner2], time, g_sPlayerSteamID[winner2]); db.Query(SQLErrorCheckCallback, query); //loser's stats - Format(query, sizeof(query), "UPDATE mgemod_stats SET rating=%i,losses=losses+1,lastplayed=%i WHERE steamid='%s'", + Format(query, sizeof(query), "UPDATE mgemod_stats SET rating=%i,losses=losses+1,lastplayed=%i WHERE steamid=text_to_steam64('%s')", g_iPlayerRating[loser], time, g_sPlayerSteamID[loser]); db.Query(SQLErrorCheckCallback, query); //loser's teammate stats - Format(query, sizeof(query), "UPDATE mgemod_stats SET rating=%i,losses=losses+1,lastplayed=%i WHERE steamid='%s'", + Format(query, sizeof(query), "UPDATE mgemod_stats SET rating=%i,losses=losses+1,lastplayed=%i WHERE steamid=text_to_steam64('%s')", g_iPlayerRating[loser2], time, g_sPlayerSteamID[loser2]); db.Query(SQLErrorCheckCallback, query); } @@ -2304,134 +2301,127 @@ bool LoadSpawnPoints() int i; g_iArenaCount = 0; - for (int j = 0; j <= MAXARENAS; j++) - { + for (int j = 0; j <= MAXARENAS; j++) { g_iArenaSpawns[j] = 0; } - if (FileToKeyValues(kv, txtfile)) - { - if (KvGotoFirstSubKey(kv)) - { - do + if (!FileToKeyValues(kv, txtfile)) { + LogError("Error. Can't find cfg file"); + return false; + } + if (!KvGotoFirstSubKey(kv)) { + LogError("Error in cfg file."); + return false; + } + do { + KvGetSectionName(kv, kvmap, 64); + if (!StrEqual(g_sMapName, kvmap, false)) { + continue; + } + if (!KvGotoFirstSubKey(kv)) { + break; + } + do { + g_iArenaCount++; + KvGetSectionName(kv, g_sArenaOriginalName[g_iArenaCount], 64); + int id; + if (KvGetNameSymbol(kv, "1", id)) { - KvGetSectionName(kv, kvmap, 64); - if (StrEqual(g_sMapName, kvmap, false)) + char intstr[4]; + char intstr2[4]; + do { - if (KvGotoFirstSubKey(kv)) + g_iArenaSpawns[g_iArenaCount]++; + IntToString(g_iArenaSpawns[g_iArenaCount], intstr, sizeof(intstr)); + IntToString(g_iArenaSpawns[g_iArenaCount]+1, intstr2, sizeof(intstr2)); + KvGetString(kv, intstr, spawn, sizeof(spawn)); + count = ExplodeString(spawn, " ", spawnCo, 6, 16); + if (count==6) { - do + for (i=0; i<3; i++) { - g_iArenaCount++; - KvGetSectionName(kv, g_sArenaOriginalName[g_iArenaCount], 64); - int id; - if (KvGetNameSymbol(kv, "1", id)) - { - char intstr[4]; - char intstr2[4]; - do - { - g_iArenaSpawns[g_iArenaCount]++; - IntToString(g_iArenaSpawns[g_iArenaCount], intstr, sizeof(intstr)); - IntToString(g_iArenaSpawns[g_iArenaCount]+1, intstr2, sizeof(intstr2)); - KvGetString(kv, intstr, spawn, sizeof(spawn)); - count = ExplodeString(spawn, " ", spawnCo, 6, 16); - if (count==6) - { - for (i=0; i<3; i++) - { - g_fArenaSpawnOrigin[g_iArenaCount][g_iArenaSpawns[g_iArenaCount]][i] = StringToFloat(spawnCo[i]); - } - for (i=3; i<6; i++) - { - g_fArenaSpawnAngles[g_iArenaCount][g_iArenaSpawns[g_iArenaCount]][i-3] = StringToFloat(spawnCo[i]); - } - } else if(count==4) { - for (i=0; i<3; i++) - { - g_fArenaSpawnOrigin[g_iArenaCount][g_iArenaSpawns[g_iArenaCount]][i] = StringToFloat(spawnCo[i]); - } - g_fArenaSpawnAngles[g_iArenaCount][g_iArenaSpawns[g_iArenaCount]][0] = 0.0; - g_fArenaSpawnAngles[g_iArenaCount][g_iArenaSpawns[g_iArenaCount]][1] = StringToFloat(spawnCo[3]); - g_fArenaSpawnAngles[g_iArenaCount][g_iArenaSpawns[g_iArenaCount]][2] = 0.0; - } else { - SetFailState("Error in cfg file. Wrong number of parametrs (%d) on spawn <%i> in arena <%s>",count,g_iArenaSpawns[g_iArenaCount],g_sArenaOriginalName[g_iArenaCount]); - } - } while (KvGetNameSymbol(kv, intstr2, id)); - LogMessage("Loaded %d spawns on arena %s.",g_iArenaSpawns[g_iArenaCount], g_sArenaOriginalName[g_iArenaCount]); - } else { - LogError("Could not load spawns on arena %s.", g_sArenaOriginalName[g_iArenaCount]); - } - - if (KvGetNameSymbol(kv, "cap", id)) { - KvGetString(kv, "cap", g_sArenaCap[g_iArenaCount], 64); - g_bArenaHasCap[g_iArenaCount] = true; - - LogMessage("Found cap point on arena %s.", g_sArenaOriginalName[g_iArenaCount]); - } else { - g_bArenaHasCap[g_iArenaCount] = false; - } + g_fArenaSpawnOrigin[g_iArenaCount][g_iArenaSpawns[g_iArenaCount]][i] = StringToFloat(spawnCo[i]); + } + for (i=3; i<6; i++) + { + g_fArenaSpawnAngles[g_iArenaCount][g_iArenaSpawns[g_iArenaCount]][i-3] = StringToFloat(spawnCo[i]); + } + } else if(count==4) { + for (i=0; i<3; i++) + { + g_fArenaSpawnOrigin[g_iArenaCount][g_iArenaSpawns[g_iArenaCount]][i] = StringToFloat(spawnCo[i]); + } + g_fArenaSpawnAngles[g_iArenaCount][g_iArenaSpawns[g_iArenaCount]][0] = 0.0; + g_fArenaSpawnAngles[g_iArenaCount][g_iArenaSpawns[g_iArenaCount]][1] = StringToFloat(spawnCo[3]); + g_fArenaSpawnAngles[g_iArenaCount][g_iArenaSpawns[g_iArenaCount]][2] = 0.0; + } else { + SetFailState("Error in cfg file. Wrong number of parametrs (%d) on spawn <%i> in arena <%s>",count,g_iArenaSpawns[g_iArenaCount],g_sArenaOriginalName[g_iArenaCount]); + } + } while (KvGetNameSymbol(kv, intstr2, id)); + LogMessage("Loaded %d spawns on arena %s.",g_iArenaSpawns[g_iArenaCount], g_sArenaOriginalName[g_iArenaCount]); + } else { + LogError("Could not load spawns on arena %s.", g_sArenaOriginalName[g_iArenaCount]); + } - if (KvGetNameSymbol(kv, "cap_trigger", id)) { - KvGetString(kv, "cap_trigger", g_sArenaCapTrigger[g_iArenaCount], 64); - g_bArenaHasCapTrigger[g_iArenaCount] = true; - } + if (KvGetNameSymbol(kv, "cap", id)) { + KvGetString(kv, "cap", g_sArenaCap[g_iArenaCount], 64); + g_bArenaHasCap[g_iArenaCount] = true; - //optional parametrs - g_iArenaMgelimit[g_iArenaCount] = KvGetNum(kv, "fraglimit", g_iDefaultFragLimit); - g_iArenaCaplimit[g_iArenaCount] = KvGetNum(kv, "caplimit", g_iDefaultFragLimit); - g_iArenaMinRating[g_iArenaCount] = KvGetNum(kv, "minrating", -1); - g_iArenaMaxRating[g_iArenaCount] = KvGetNum(kv, "maxrating", -1); - g_bArenaMidair[g_iArenaCount] = KvGetNum(kv, "midair", 0) ? true : false ; - g_iArenaCdTime[g_iArenaCount] = KvGetNum(kv, "cdtime", DEFAULT_CDTIME); - g_bArenaMGE[g_iArenaCount] = KvGetNum(kv, "mge", 0) ? true : false ; - g_fArenaHPRatio[g_iArenaCount] = KvGetFloat(kv, "hpratio", 1.5); - g_bArenaEndif[g_iArenaCount] = KvGetNum(kv, "endif", 0) ? true : false ; - g_iArenaAirshotHeight[g_iArenaCount] = KvGetNum(kv, "airshotheight", 250); - g_bArenaBoostVectors[g_iArenaCount] = KvGetNum(kv, "boostvectors", 0) ? true : false ; - g_bArenaBBall[g_iArenaCount] = KvGetNum(kv, "bball", 0) ? true : false ; - g_bVisibleHoops[g_iArenaCount] = KvGetNum(kv, "vishoop", 0) ? true : false ; - g_iArenaEarlyLeave[g_iArenaCount] = KvGetNum(kv, "earlyleave", 0); - g_bArenaInfAmmo[g_iArenaCount] = KvGetNum(kv, "infammo", 1) ? true : false ; - g_bArenaShowHPToPlayers[g_iArenaCount] = KvGetNum(kv, "showhp", 1) ? true : false ; - g_fArenaMinSpawnDist[g_iArenaCount] = KvGetFloat(kv, "mindist", 100.0); - g_bFourPersonArena[g_iArenaCount] = KvGetNum(kv, "4player", 0) ? true : false; - g_bArenaAllowChange[g_iArenaCount] = KvGetNum(kv, "allowchange", 0) ? true : false; - g_bArenaAllowKoth[g_iArenaCount] = KvGetNum(kv, "allowkoth", 0) ? true : false; - g_bArenaKothTeamSpawn[g_iArenaCount] = KvGetNum(kv, "kothteamspawn", 0) ? true : false; - g_fArenaRespawnTime[g_iArenaCount] = KvGetFloat(kv, "respawntime", 0.1); - g_bArenaAmmomod[g_iArenaCount] = KvGetNum(kv, "ammomod", 0) ? true : false; - g_bArenaUltiduo[g_iArenaCount] = KvGetNum(kv, "ultiduo", 0) ? true : false; - g_bArenaKoth[g_iArenaCount] = KvGetNum(kv, "koth", 0) ? true : false; - g_bArenaTurris[g_iArenaCount] = KvGetNum(kv, "turris", 0) ? true : false; - g_iDefaultCapTime[g_iArenaCount] = KvGetNum(kv, "timer", 180); - //parsing allowed classes for current arena - char sAllowedClasses[128]; - KvGetString(kv, "classes", sAllowedClasses, sizeof(sAllowedClasses)); - LogMessage("%s classes: <%s>", g_sArenaOriginalName[g_iArenaCount], sAllowedClasses); - ParseAllowedClasses(sAllowedClasses,g_tfctArenaAllowedClasses[g_iArenaCount]); - g_iArenaFraglimit[g_iArenaCount] = g_iArenaMgelimit[g_iArenaCount]; - UpdateArenaName(g_iArenaCount); - } while (KvGotoNextKey(kv)); - } - break; - } - } while (KvGotoNextKey(kv)); - if (g_iArenaCount) - { - LogMessage("Loaded %d arenas. MGEMod enabled.",g_iArenaCount); - CloseHandle(kv); - return true; + LogMessage("Found cap point on arena %s.", g_sArenaOriginalName[g_iArenaCount]); } else { - CloseHandle(kv); - return false; + g_bArenaHasCap[g_iArenaCount] = false; } - } else { - LogError("Error in cfg file."); - return false; - } + + if (KvGetNameSymbol(kv, "cap_trigger", id)) { + KvGetString(kv, "cap_trigger", g_sArenaCapTrigger[g_iArenaCount], 64); + g_bArenaHasCapTrigger[g_iArenaCount] = true; + } + + //optional parametrs + g_iArenaMgelimit[g_iArenaCount] = KvGetNum(kv, "fraglimit", g_iDefaultFragLimit); + g_iArenaCaplimit[g_iArenaCount] = KvGetNum(kv, "caplimit", g_iDefaultFragLimit); + g_iArenaMinRating[g_iArenaCount] = KvGetNum(kv, "minrating", -1); + g_iArenaMaxRating[g_iArenaCount] = KvGetNum(kv, "maxrating", -1); + g_bArenaMidair[g_iArenaCount] = KvGetNum(kv, "midair", 0) ? true : false ; + g_iArenaCdTime[g_iArenaCount] = KvGetNum(kv, "cdtime", DEFAULT_CDTIME); + g_bArenaMGE[g_iArenaCount] = KvGetNum(kv, "mge", 0) ? true : false ; + g_fArenaHPRatio[g_iArenaCount] = KvGetFloat(kv, "hpratio", 1.5); + g_bArenaEndif[g_iArenaCount] = KvGetNum(kv, "endif", 0) ? true : false ; + g_iArenaAirshotHeight[g_iArenaCount] = KvGetNum(kv, "airshotheight", 250); + g_bArenaBoostVectors[g_iArenaCount] = KvGetNum(kv, "boostvectors", 0) ? true : false ; + g_bArenaBBall[g_iArenaCount] = KvGetNum(kv, "bball", 0) ? true : false ; + g_bVisibleHoops[g_iArenaCount] = KvGetNum(kv, "vishoop", 0) ? true : false ; + g_iArenaEarlyLeave[g_iArenaCount] = KvGetNum(kv, "earlyleave", 0); + g_bArenaInfAmmo[g_iArenaCount] = KvGetNum(kv, "infammo", 1) ? true : false ; + g_bArenaShowHPToPlayers[g_iArenaCount] = KvGetNum(kv, "showhp", 1) ? true : false ; + g_fArenaMinSpawnDist[g_iArenaCount] = KvGetFloat(kv, "mindist", 100.0); + g_bFourPersonArena[g_iArenaCount] = KvGetNum(kv, "4player", 0) ? true : false; + g_bArenaAllowChange[g_iArenaCount] = KvGetNum(kv, "allowchange", 0) ? true : false; + g_bArenaAllowKoth[g_iArenaCount] = KvGetNum(kv, "allowkoth", 0) ? true : false; + g_bArenaKothTeamSpawn[g_iArenaCount] = KvGetNum(kv, "kothteamspawn", 0) ? true : false; + g_fArenaRespawnTime[g_iArenaCount] = KvGetFloat(kv, "respawntime", 0.1); + g_bArenaAmmomod[g_iArenaCount] = KvGetNum(kv, "ammomod", 0) ? true : false; + g_bArenaUltiduo[g_iArenaCount] = KvGetNum(kv, "ultiduo", 0) ? true : false; + g_bArenaKoth[g_iArenaCount] = KvGetNum(kv, "koth", 0) ? true : false; + g_bArenaTurris[g_iArenaCount] = KvGetNum(kv, "turris", 0) ? true : false; + g_iDefaultCapTime[g_iArenaCount] = KvGetNum(kv, "timer", 180); + //parsing allowed classes for current arena + char sAllowedClasses[128]; + KvGetString(kv, "classes", sAllowedClasses, sizeof(sAllowedClasses)); + LogMessage("%s classes: <%s>", g_sArenaOriginalName[g_iArenaCount], sAllowedClasses); + ParseAllowedClasses(sAllowedClasses,g_tfctArenaAllowedClasses[g_iArenaCount]); + g_iArenaFraglimit[g_iArenaCount] = g_iArenaMgelimit[g_iArenaCount]; + UpdateArenaName(g_iArenaCount); + } while (KvGotoNextKey(kv)); + + } while (KvGotoNextKey(kv)); + + if (g_iArenaCount) { + LogMessage("Loaded %d arenas. MGEMod enabled.",g_iArenaCount); + CloseHandle(kv); + return true; } else { - LogError("Error. Can't find cfg file"); + CloseHandle(kv); return false; } } @@ -3824,30 +3814,42 @@ void PrepareSQL() // Opens the connection to the database, and creates the table char ident[16]; db.Driver.GetIdentifier(ident, sizeof(ident)); - if (StrEqual(ident, "mysql", false)) { - g_iDBDriver = DRIVER_MYSQL; - } else if (StrEqual(ident, "sqlite", false)) { - g_iDBDriver = DRIVER_SQLITE; - } else if (StrEqual(ident, "pgsql", false)) { - g_iDBDriver = DRIVER_POSTGRES; - } else { - SetFailState("Invalid database."); - } - - - // No indexes/pk? - if (g_iDBDriver == DRIVER_SQLITE || g_iDBDriver == DRIVER_POSTGRES) - { + if (StrEqual(ident, "sqlite", false)) { + // Untested. + db.Query(SQLErrorCheckCallback, "CREATE FUNCTION text_to_steam64(steamid TEXT) RETURNS TEXT AS BEGIN RETURN steam_id; END;"); db.Query(SQLErrorCheckCallback, "CREATE TABLE IF NOT EXISTS mgemod_stats (rating INTEGER, steamid TEXT, name TEXT, wins INTEGER, losses INTEGER, lastplayed INTEGER, hitblip INTEGER)"); db.Query(SQLErrorCheckCallback, "CREATE TABLE IF NOT EXISTS mgemod_duels (winner TEXT, loser TEXT, winnerscore INTEGER, loserscore INTEGER, winlimit INTEGER, gametime INTEGER, mapname TEXT, arenaname TEXT) "); db.Query(SQLErrorCheckCallback, "CREATE TABLE IF NOT EXISTS mgemod_duels_2v2 (winner TEXT, winner2 TEXT, loser TEXT, loser2 TEXT, winnerscore INTEGER, loserscore INTEGER, winlimit INTEGER, gametime INTEGER, mapname TEXT, arenaname TEXT) "); - } - else if (g_iDBDriver == DRIVER_MYSQL) - { + } else if (StrEqual(ident, "pgsql", false)) { + db.Query(SQLErrorCheckCallback, "CREATE OR REPLACE FUNCTION text_to_steam64(steam_id text) RETURNS bigint \ + LANGUAGE plpgsql as $func$ \ + DECLARE parts text[]; \ + BEGIN \ + if starts_with(steam_id, '76561') then return cast(steam_id as bigint); end if; \ + parts := regexp_matches(steam_id, '^STEAM_([0-5]):([0-1]):([0-9]+)$'); \ + return (cast(parts[3] as bigint) * 2) + 76561197960265728 + cast(parts[2] as bigint); \ + END ; $func$;"); + // Not currently using foreign keys since i don't want to diverge from the base mod schema too much and hard depend on other stuff. + // I, however, refuse to store steamids as text, so upstream may not want this. The other stored procs provide a dummy function so + // the actual queries can remain consistent across the drivers. + // TODO Use the native sm 64bit when its in production. + db.Query(SQLErrorCheckCallback, "CREATE TABLE IF NOT EXISTS mgemod_stats (rating INTEGER, steamid BIGINT, name TEXT, wins INTEGER, losses INTEGER, lastplayed INTEGER, hitblip INTEGER)"); + db.Query(SQLErrorCheckCallback, "CREATE TABLE IF NOT EXISTS mgemod_duels (duel_id serial, winner BIGINT, loser BIGINT, winnerscore INTEGER, loserscore INTEGER, winlimit INTEGER, gametime INTEGER, mapname TEXT, arenaname TEXT) "); + db.Query(SQLErrorCheckCallback, "CREATE TABLE IF NOT EXISTS mgemod_duels_2v2 (duel2_id serial, winner BIGINT, winner2 BIGINT, loser BIGINT, loser2 BIGINT, winnerscore INTEGER, loserscore INTEGER, winlimit INTEGER, gametime INTEGER, mapname TEXT, arenaname TEXT) "); + } else if (StrEqual(ident, "mysql", false)) { + // Untested. + db.Query(SQLErrorCheckCallback, "DELIMITER // CREATE PROCEDURE text_to_steam64( IN input_steam_id VARCHAR(255), OUT output_steam_id VARCHAR(255) ) BEGIN SET output_steam_id = input_steam_id; END //// DELIMITER ;"); db.Query(SQLErrorCheckCallback, "CREATE TABLE IF NOT EXISTS mgemod_stats (rating INT(4) NOT NULL, steamid VARCHAR(32) NOT NULL, name VARCHAR(64) NOT NULL, wins INT(4) NOT NULL, losses INT(4) NOT NULL, lastplayed INT(11) NOT NULL, hitblip INT(2) NOT NULL) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB "); db.Query(SQLErrorCheckCallback, "CREATE TABLE IF NOT EXISTS mgemod_duels (winner VARCHAR(32) NOT NULL, loser VARCHAR(32) NOT NULL, winnerscore INT(4) NOT NULL, loserscore INT(4) NOT NULL, winlimit INT(4) NOT NULL, gametime INT(11) NOT NULL, mapname VARCHAR(64) NOT NULL, arenaname VARCHAR(32) NOT NULL) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB "); db.Query(SQLErrorCheckCallback, "CREATE TABLE IF NOT EXISTS mgemod_duels_2v2 (winner VARCHAR(32) NOT NULL, winner2 VARCHAR(32) NOT NULL, loser VARCHAR(32) NOT NULL, loser2 VARCHAR(32) NOT NULL, winnerscore INT(4) NOT NULL, loserscore INT(4) NOT NULL, winlimit INT(4) NOT NULL, gametime INT(11) NOT NULL, mapname VARCHAR(64) NOT NULL, arenaname VARCHAR(32) NOT NULL) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB "); + } else { + SetFailState("Invalid database driver: %s.", ident); + return; } + + // There was no indexes/pk at all before except sqlite ROWID i guess..?, is there something im missing? + // Removed the `LIMIT 1` queries. + db.Query(SQLErrorCheckCallback, "CREATE UNIQUE INDEX IF NOT EXISTS mgemod_stats_uidx ON mgemod_stats (steamid)"); } void T_SQLQueryOnConnect(Database owner, DBResultSet hndl, const char[] error, any data) @@ -3877,11 +3879,11 @@ void T_SQLQueryOnConnect(Database owner, DBResultSet hndl, const char[] error, a g_bHitBlip[client] = hndl.FetchInt(1) == 1; g_iPlayerWins[client] = hndl.FetchInt(2); g_iPlayerLosses[client] = hndl.FetchInt(3); - - Format(query, sizeof(query), "UPDATE mgemod_stats SET name='%s' WHERE steamid='%s'", namesql, g_sPlayerSteamID[client]); + + Format(query, sizeof(query), "UPDATE mgemod_stats SET name='%s' WHERE steamid=text_to_steam64('%s')", namesql, g_sPlayerSteamID[client]); db.Query(SQLErrorCheckCallback, query); } else { - Format(query, sizeof(query), "INSERT INTO mgemod_stats (rating, steamid, name, wins, losses, lastplayed, hitblip) VALUES (1600, '%s', '%s', 0, 0, %i, 1)", g_sPlayerSteamID[client], namesql, GetTime()); + Format(query, sizeof(query), "INSERT INTO mgemod_stats (rating, steamid, name, wins, losses, lastplayed, hitblip) VALUES (1600, text_to_steam64('%s'), '%s', 0, 0, %i, 1)", g_sPlayerSteamID[client], namesql, GetTime()); db.Query(SQLErrorCheckCallback, query); g_iPlayerRating[client] = 1600; @@ -3997,7 +3999,7 @@ void SQLDbConnTest(Database owner, DBResultSet hndl, const char[] error, any dat GetClientAuthId(i, AuthId_Steam2, steamid_dirty, sizeof(steamid_dirty)); db.Escape(steamid_dirty, steamid, sizeof(steamid)); strcopy(g_sPlayerSteamID[i], 32, steamid); - Format(query, sizeof(query), "SELECT rating, hitblip, wins, losses FROM mgemod_stats WHERE steamid='%s' LIMIT 1", steamid); + Format(query, sizeof(query), "SELECT rating, hitblip, wins, losses FROM mgemod_stats WHERE steamid='%s'", steamid); db.Query(T_SQLQueryOnConnect, query, i); } } @@ -5007,7 +5009,7 @@ Action Timer_ResetPlayer(Handle timer, int userid) { ResetPlayer(client); } - + return Plugin_Continue; } @@ -5017,7 +5019,7 @@ Action Timer_ChangePlayerSpec(Handle timer, any player) { ChangeClientTeam(player, TEAM_SPEC); } - + return Plugin_Continue; } diff --git a/roles/sourcemod/files/addons/sourcemod/scripting/skipmotd.sp b/roles/sourcemod/files/addons/sourcemod/scripting/skipmotd.sp index a67ac3bf..4b214ff2 100644 --- a/roles/sourcemod/files/addons/sourcemod/scripting/skipmotd.sp +++ b/roles/sourcemod/files/addons/sourcemod/scripting/skipmotd.sp @@ -68,9 +68,9 @@ public OnPluginStart() CreateConVar("sm_nomotd_version", PLUGIN_VERSION, "No MOTD version", FCVAR_NOTIFY|FCVAR_SPONLY); noMotdCookie = RegClientCookie("no_motd", "No MOTD", CookieAccess_Protected); - randomTeamCookie = RegClientCookie("random_team", "No MOTD", CookieAccess_Protected); - randomClassCookie = RegClientCookie("random_class", "No MOTD", CookieAccess_Protected); - rememberClassCookie = RegClientCookie("remember_class", "No MOTD", CookieAccess_Protected); + randomTeamCookie = RegClientCookie("random_team", "Random Team", CookieAccess_Protected); + randomClassCookie = RegClientCookie("random_class", "Random Class", CookieAccess_Protected); + rememberClassCookie = RegClientCookie("remember_class", "Remember Class", CookieAccess_Protected); // Register sm_settings menus. These can't be unregistered(?) so if // cvars are changed after server startpu, the menu will be out of diff --git a/roles/srcds/files/maps/mge_bball_v2.bsp b/roles/srcds/files/maps/mge_bball_v2.bsp new file mode 100644 index 00000000..f3844604 Binary files /dev/null and b/roles/srcds/files/maps/mge_bball_v2.bsp differ diff --git a/roles/srcds/files/maps/mge_dueling_v1_fix1.bsp b/roles/srcds/files/maps/mge_dueling_v1_fix1.bsp new file mode 100644 index 00000000..00e31b92 Binary files /dev/null and b/roles/srcds/files/maps/mge_dueling_v1_fix1.bsp differ diff --git a/roles/srcds/files/maps/mge_oihguv_sucks_a12.bsp b/roles/srcds/files/maps/mge_oihguv_sucks_a12.bsp new file mode 100644 index 00000000..9d54e45a Binary files /dev/null and b/roles/srcds/files/maps/mge_oihguv_sucks_a12.bsp differ diff --git a/roles/srcds/files/maps/mge_oihguv_sucks_b5.bsp b/roles/srcds/files/maps/mge_oihguv_sucks_b5.bsp new file mode 100755 index 00000000..564e0387 Binary files /dev/null and b/roles/srcds/files/maps/mge_oihguv_sucks_b5.bsp differ diff --git a/roles/srcds/files/maps/mge_training_v8_beta4b.bsp b/roles/srcds/files/maps/mge_training_v8_beta4b.bsp new file mode 100644 index 00000000..3d534be6 Binary files /dev/null and b/roles/srcds/files/maps/mge_training_v8_beta4b.bsp differ diff --git a/roles/srcds/files/maps/mge_triumph_beta7_rc1.bsp b/roles/srcds/files/maps/mge_triumph_beta7_rc1.bsp new file mode 100644 index 00000000..606c884c Binary files /dev/null and b/roles/srcds/files/maps/mge_triumph_beta7_rc1.bsp differ diff --git a/roles/srcds/tasks/main.yml b/roles/srcds/tasks/main.yml index 131e98df..48efced3 100644 --- a/roles/srcds/tasks/main.yml +++ b/roles/srcds/tasks/main.yml @@ -429,6 +429,18 @@ loop_control: index_var: loop0 +- name: Generate /tf/cfg/sourcemod/mge.cfg + ansible.builtin.template: + src: mge.cfg.j2 + dest: ~/srcds-{{ item.server_name_short }}/tf/cfg/sourcemod/plugin.mge.cfg + mode: "0755" + when: item.config == "mge" + tags: + - game_config + loop: "{{ services }}" + loop_control: + index_var: loop0 + - name: Generate /tf/cfg/sourcemod/networktools.cfg ansible.builtin.template: src: networktools.cfg.j2 diff --git a/roles/srcds/templates/databases.cfg.j2 b/roles/srcds/templates/databases.cfg.j2 index 23eb323f..4ec51485 100644 --- a/roles/srcds/templates/databases.cfg.j2 +++ b/roles/srcds/templates/databases.cfg.j2 @@ -6,6 +6,17 @@ "database" "sourcemod-local" } + "mgemod" + { + "driver" "pgsql" + "host" "{{ sourcemod_db_host|default("localhost") }}" + "database" "{{ sourcemod_db_database|default("gbans") }}" + "user" "{{ sourcemod_db_username|default("sourcemod") }}" + "pass" "{{ sourcemod_db_password|default("sourcemod") }}" + //"timeout" "0" + "port" "{{ sourcemod_db_port|default(5432) }}" + } + "clientprefs" { "driver" "pgsql" diff --git a/roles/srcds/templates/mge.cfg.j2 b/roles/srcds/templates/mge.cfg.j2 new file mode 100644 index 00000000..bac6a97f --- /dev/null +++ b/roles/srcds/templates/mge.cfg.j2 @@ -0,0 +1,16 @@ +mgemod_fraglimit 3 +mgemod_allowed_classes "scout soldier pyro demoman heavy engineer medic sniper spy" +mgemod_blockdmg_fall 0 +mgemod_dbconfig mgemod +mgemod_stats 1 +mgemod_airshot_height 80 +mgemod_endif_force_x 1.1 +mgemod_endif_force_y 1.1 +mgemod_endif_force_z 2.15 +mgemod_autocvar 1 +mgemod_bball_particle_red player_intel_trail_red +mgemod_bball_particle_blue player_intel_trail_blue +mgemod_midair_hp 5 +mgemod_hide_rating 1 +mgemod_reconnect_interval 5 +mgemod_spawnfile "configs/mgemod_spawns.cfg" diff --git a/roles/srcds/templates/server.cfg.j2 b/roles/srcds/templates/server.cfg.j2 index c9156fd2..eab83c94 100644 --- a/roles/srcds/templates/server.cfg.j2 +++ b/roles/srcds/templates/server.cfg.j2 @@ -163,14 +163,6 @@ net_disconnect_reason 1 tf_fall_damage_disablespread 1 net_chan_limit_msec 160 -// Disable glow for the more "serious" servers running stopwatch -tf_spawn_glows_duration {% if item.config|default("all") == "stopwatch" %}0{% else %}10{% endif %} - -// Stopwatch switches -mp_match_end_at_timelimit {% if item.config|default("all") == "stopwatch" %}1{% else %}0{% endif %} - -sm_cvar gb_rules_round_time {% if item.config|default("all") == "stopwatch" %}300{% else %}-1{% endif %} - {% if item.config == 'pve' %} sm_cvar sm_danepve_respawn_bots_on_round_end 0 sm_cvar sm_danepve_max_playing_humans {{ item.human_count|default(16) }} @@ -195,7 +187,9 @@ ce_logreaderwaittime 120 sv_playerperfhistorycount 20 net_maxcleartime 0.001 -tf_dropped_weapon_lifetime "{% if item.config == 'pve' %}0{% else %}30{% endif %}" +{% if item.config == 'pve' %} +tf_dropped_weapon_lifetime 0 +{% endif %} sm_cvar sv_player_usercommand_timeout 1 @@ -232,3 +226,7 @@ mp_timelimit 0 mp_winlimit 0 mp_maxrounds 0 {% endif %} + +{% if item.config == 'mge' %} +exec mge.cfg +{% endif %} diff --git a/sm_plugins/mge b/sm_plugins/mge new file mode 160000 index 00000000..da8cefde --- /dev/null +++ b/sm_plugins/mge @@ -0,0 +1 @@ +Subproject commit da8cefde880b76fb466e543786b9f94972aaa676 diff --git a/sm_plugins_update.sh b/sm_plugins_update.sh index c870366e..c83ba6ef 100755 --- a/sm_plugins_update.sh +++ b/sm_plugins_update.sh @@ -1,8 +1,11 @@ #!/bin/env bash -ROOT=$(pwd) +ROOT=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) SM_ROOT=$ROOT/roles/sourcemod/files/addons/sourcemod SRC_ROOT="sm_plugins" +MGE_ROOT="$SRC_ROOT/mge" +MGE_BRANCH="pg" + DODGEBALL_ROOT="$SRC_ROOT/TF2-Dodgeball-Modified-UDL" DODGEBALL_BRANCH="master" @@ -47,6 +50,17 @@ HALLOWEENCOSMETICS_ROOT="$SRC_ROOT/HalloweenCosmeticEnabler" HALLOWEENCOSMETICS_BRANCH="master" # git submodule update --init --recursive +# +pushd $MGE_ROOT || exit +git fetch --all +git checkout $MGE_BRANCH +git pull +for d in 'configs' 'scripting' 'translations'; do + cp -rv addons/sourcemod/$d "$SM_ROOT" +done + +cp -rv maps/* "$ROOT"/roles/srcds/files/maps +popd || exit pushd $DODGEBALL_ROOT || exit git fetch --all