From c397db6a5778d0a38e982068d71086e05f249cab Mon Sep 17 00:00:00 2001 From: "(Jip) Willem Wijnia" Date: Sat, 30 Nov 2024 17:18:50 +0100 Subject: [PATCH 1/7] Expose player ratings and divisions to the session --- .../lobby/autolobby/AutolobbyController.lua | 45 ++++++++++++++++++- scripts/LaunchFAInstances.ps1 | 4 +- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/lua/ui/lobby/autolobby/AutolobbyController.lua b/lua/ui/lobby/autolobby/AutolobbyController.lua index 364fc8df4aa..bde40e8b14f 100644 --- a/lua/ui/lobby/autolobby/AutolobbyController.lua +++ b/lua/ui/lobby/autolobby/AutolobbyController.lua @@ -294,6 +294,44 @@ AutolobbyCommunications = Class(MohoLobbyMethods, AutolobbyServerCommunicationsC return 'Ready' end, + ---@param self UIAutolobbyCommunications + ---@param playerOptions UIAutolobbyPlayer[] + ---@return table + CreateRatingsTable = function(self, playerOptions) + ---@type table + local allRatings = {} + + for slot, options in pairs(playerOptions) do + if options.Human and options.PL then + allRatings[options.PlayerName] = options.PL + end + end + + return allRatings + end, + + ---@param self UIAutolobbyCommunications + ---@param playerOptions UIAutolobbyPlayer[] + ---@return table + CreateDivisionsTable = function(self, playerOptions) + ---@type table + local allDivisions = {} + + for slot, options in pairs(playerOptions) do + if options.Human and options.PL then + if options.DIV ~= "unlisted" then + local division = options.DIV + if options.SUBDIV and options.SUBDIV ~="" then + division = division .. ' ' .. options.SUBDIV + end + allDivisions[options.PlayerName]= division + end + end + end + + return allDivisions + end, + --- Verifies whether we can launch the game. ---@param self UIAutolobbyCommunications ---@param peerStatus UIAutolobbyStatus @@ -488,6 +526,11 @@ AutolobbyCommunications = Class(MohoLobbyMethods, AutolobbyServerCommunicationsC self:SendPlayerOptionToServer(ownerId, 'Faction', playerOptions.Faction) end + -- tuck them into the game options. By all means a hack, but + -- this way they are available in both the sim and the UI + self.GameOptions.Ratings = self:CreateRatingsTable(self.PlayerOptions) + self.GameOptions.Divisions = self:CreateDivisionsTable(self.PlayerOptions) + -- create game configuration local gameConfiguration = { GameMods = self.GameMods, @@ -496,7 +539,7 @@ AutolobbyCommunications = Class(MohoLobbyMethods, AutolobbyServerCommunicationsC Observers = {}, } - -- send it to all players and tell them to launch + -- send it to all players and tell them to launch with the configuration self:BroadcastData({ Type = "Launch", GameConfig = gameConfiguration }) self:LaunchGame(gameConfiguration) end diff --git a/scripts/LaunchFAInstances.ps1 b/scripts/LaunchFAInstances.ps1 index 8a22fca4a6e..4bbf86f2074 100644 --- a/scripts/LaunchFAInstances.ps1 +++ b/scripts/LaunchFAInstances.ps1 @@ -91,7 +91,7 @@ if ($players -eq 1) { $hostLogFile = "host_dev_1.log" $hostFaction = $factions | Get-Random $hostTeamArgument = Get-TeamArgument -instanceNumber 0 - $hostArguments = "/log $hostLogFile /showlog /hostgame $hostProtocol $port $hostPlayerName $gameName $map /startspot 1 /players $players /$hostFaction $hostTeamArgument $baseArguments" + $hostArguments = "/log $hostLogFile /showlog /hostgame $hostProtocol $port $hostPlayerName $gameName $map /startspot 1 /players $players /$hostFaction $hostTeamArgument $baseArguments /division HostDivision /subdivision 1" # Launch host game instance Launch-GameInstance -instanceNumber 1 -xPos 0 -yPos 0 -arguments $hostArguments @@ -107,7 +107,7 @@ if ($players -eq 1) { $clientPlayerName = "ClientPlayer_$($i + 1)" $clientFaction = $factions | Get-Random $clientTeamArgument = Get-TeamArgument -instanceNumber $i - $clientArguments = "/log $clientLogFile /joingame $hostProtocol localhost:$port $clientPlayerName /startspot $($i + 1) /players $players /$clientFaction $clientTeamArgument $baseArguments" + $clientArguments = "/log $clientLogFile /joingame $hostProtocol localhost:$port $clientPlayerName /startspot $($i + 1) /players $players /$clientFaction $clientTeamArgument $baseArguments /division Diamond /subdivision $($i + 1)" Launch-GameInstance -instanceNumber ($i + 1) -xPos $xPos -yPos $yPos -arguments $clientArguments } From d11609e9956c977dc1aa0807e3151eec4b1c2977 Mon Sep 17 00:00:00 2001 From: "(Jip) Willem Wijnia" Date: Sat, 30 Nov 2024 19:12:57 +0100 Subject: [PATCH 2/7] Update annotations --- engine/User/CLobby.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/engine/User/CLobby.lua b/engine/User/CLobby.lua index eb132bd52e1..a5c0099bdd6 100644 --- a/engine/User/CLobby.lua +++ b/engine/User/CLobby.lua @@ -43,6 +43,8 @@ local CLobby = {} ---@field Timeouts any # Read by the engine to determine the behavior of time outs. ---@field CivilianAlliance any # Read by the engine to determine the alliance towards civilians. ---@field GameSpeed any # Read by the engine to determine the behavior of game speed (adjustments). +---@field Ratings table +---@field Divisions table ---@class UILobbyLaunchGameModsConfiguration ---@field name string # Read by the engine, TODO From 1c6384b80043bd4ad474886f2dda7f647c6f1880 Mon Sep 17 00:00:00 2001 From: "(Jip) Willem Wijnia" Date: Thu, 5 Dec 2024 22:02:38 +0100 Subject: [PATCH 3/7] First attempt at implementing proper command line parsing --- changelog/snippets/fix.6569.md | 1 + .../lobby/autolobby/AutolobbyController.lua | 14 +- .../components/AutolobbyArguments.lua | 127 ++++++++++++++++++ 3 files changed, 136 insertions(+), 6 deletions(-) create mode 100644 changelog/snippets/fix.6569.md create mode 100644 lua/ui/lobby/autolobby/components/AutolobbyArguments.lua diff --git a/changelog/snippets/fix.6569.md b/changelog/snippets/fix.6569.md new file mode 100644 index 00000000000..6d32706c6b8 --- /dev/null +++ b/changelog/snippets/fix.6569.md @@ -0,0 +1 @@ +- (#6569) Fix the matchmaker lobby not passing ratings, divisions and clan tags to the session diff --git a/lua/ui/lobby/autolobby/AutolobbyController.lua b/lua/ui/lobby/autolobby/AutolobbyController.lua index bde40e8b14f..c1a17b28804 100644 --- a/lua/ui/lobby/autolobby/AutolobbyController.lua +++ b/lua/ui/lobby/autolobby/AutolobbyController.lua @@ -29,6 +29,8 @@ local DebugComponent = import("/lua/shared/components/DebugComponent.lua").Debug local AutolobbyServerCommunicationsComponent = import("/lua/ui/lobby/autolobby/components/AutolobbyServerCommunicationsComponent.lua") .AutolobbyServerCommunicationsComponent +local AutolobbyArgumentsComponent = import("/lua/ui/lobby/autolobby/components/AutolobbyArguments.lua").AutolobbyArgumentsComponent + local AutolobbyMessages = import("/lua/ui/lobby/autolobby/AutolobbyMessages.lua").AutolobbyMessages local AutolobbyEngineStrings = { @@ -86,7 +88,7 @@ local AutolobbyEngineStrings = { ---@field DesiredPeerId UILobbyPeerId --- Responsible for the behavior of the automated lobby. ----@class UIAutolobbyCommunications : moho.lobby_methods, DebugComponent, UIAutolobbyServerCommunicationsComponent +---@class UIAutolobbyCommunications : moho.lobby_methods, DebugComponent, UIAutolobbyServerCommunicationsComponent, UIAutolobbyArgumentsComponent ---@field Trash TrashBag ---@field LocalPeerId UILobbyPeerId # a number that is stringified ---@field LocalPlayerName string # nickname @@ -100,7 +102,7 @@ local AutolobbyEngineStrings = { ---@field LobbyParameters? UIAutolobbyParameters # Used for rejoining functionality ---@field HostParameters? UIAutolobbyHostParameters # Used for rejoining functionality ---@field JoinParameters? UIAutolobbyJoinParameters # Used for rejoining functionality -AutolobbyCommunications = Class(MohoLobbyMethods, AutolobbyServerCommunicationsComponent, DebugComponent) { +AutolobbyCommunications = Class(MohoLobbyMethods, AutolobbyServerCommunicationsComponent, AutolobbyArgumentsComponent, DebugComponent) { ---@param self UIAutolobbyCommunications __init = function(self) @@ -147,7 +149,7 @@ AutolobbyCommunications = Class(MohoLobbyMethods, AutolobbyServerCommunicationsC end -- retrieve team and start spot - info.Team = tonumber(GetCommandLineArg("/team", 1)[1]) + info.Team = self:GetCommandLineArgumentNumber("/team", -1) info.StartSpot = tonumber(GetCommandLineArg("/startspot", 1)[1]) or -1 -- TODO -- determine army color based on start location @@ -321,10 +323,10 @@ AutolobbyCommunications = Class(MohoLobbyMethods, AutolobbyServerCommunicationsC if options.Human and options.PL then if options.DIV ~= "unlisted" then local division = options.DIV - if options.SUBDIV and options.SUBDIV ~="" then + if options.SUBDIV and options.SUBDIV ~= "" then division = division .. ' ' .. options.SUBDIV end - allDivisions[options.PlayerName]= division + allDivisions[options.PlayerName] = division end end end @@ -526,7 +528,7 @@ AutolobbyCommunications = Class(MohoLobbyMethods, AutolobbyServerCommunicationsC self:SendPlayerOptionToServer(ownerId, 'Faction', playerOptions.Faction) end - -- tuck them into the game options. By all means a hack, but + -- tuck them into the game options. By all means a hack, but -- this way they are available in both the sim and the UI self.GameOptions.Ratings = self:CreateRatingsTable(self.PlayerOptions) self.GameOptions.Divisions = self:CreateDivisionsTable(self.PlayerOptions) diff --git a/lua/ui/lobby/autolobby/components/AutolobbyArguments.lua b/lua/ui/lobby/autolobby/components/AutolobbyArguments.lua new file mode 100644 index 00000000000..7fa0b764d78 --- /dev/null +++ b/lua/ui/lobby/autolobby/components/AutolobbyArguments.lua @@ -0,0 +1,127 @@ +--****************************************************************************************************** +--** Copyright (c) 2024 Willem 'Jip' Wijnia +--** +--** Permission is hereby granted, free of charge, to any person obtaining a copy +--** of this software and associated documentation files (the "Software"), to deal +--** in the Software without restriction, including without limitation the rights +--** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +--** copies of the Software, and to permit persons to whom the Software is +--** furnished to do so, subject to the following conditions: +--** +--** The above copyright notice and this permission notice shall be included in all +--** copies or substantial portions of the Software. +--** +--** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +--** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +--** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +--** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +--** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +--** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +--** SOFTWARE. +--****************************************************************************************************** + +--- A component that represent all the supported lobby <-> server communications. +---@class UIAutolobbyArgumentsComponent +AutolobbyArgumentsComponent = ClassSimple { + + --- Represent all valid command line arguments for the lobby + ArgumentKeys = { + ["/init"] = true, + ["/joincustom"] = true, + ["/gpgnet"] = true, + + -- related to player info + ["/clan"] = true, + ["/country"] = true, + ["/numgames"] = true, + + -- related to player settings + ["/team"] = true, + ["/uef"] = true, + ["/cybran"] = true, + ["/aeon"] = true, + ["/seraphim"] = true, + ["/startspot"] = true, + + -- related to rating + ["/deviation"] = true, + ["/mean"] = true, + + -- related to divisions + ["division"] = true, + ["/subdivision"] = true, + + -- related to game settings + ["/gameoptions"] = true, + ["/players"] = true, + }, + + --- Verifies that it is an expected command line argument + ---@param self UIAutolobbyArgumentsComponent | UIAutolobbyCommunications + ---@param option string + ---@return boolean + ValidCommandLineKey = function(self, option) + if not self.ArgumentKeys[option] then + self:DebugWarn("Unknown command line argument: ", option) + return false + end + + return true + end, + + --- Attempts to retrieve a string-like command line argument + ---@param self UIAutolobbyArgumentsComponent | UIAutolobbyCommunications + ---@param option string + ---@param default string + ---@return string + GetCommandLineArgumentString = function(self, option, default) + if not self:ValidCommandLineKey(option) then + return default + end + + -- try to get the first argument + local arguments = GetCommandLineArg(option, 1) + if arguments and (not option[ arg[1] ]) then + return arg[1] + end + + return default + end, + + --- Attempts to retrieve a number-like command line argument + ---@param self UIAutolobbyArgumentsComponent | UIAutolobbyCommunications + ---@param option string + ---@param default number + ---@return number + GetCommandLineArgumentNumber = function(self, option, default) + if not self:ValidCommandLineKey(option) then + return default + end + + -- try to get the first argument and parse it as a number + local arguments = GetCommandLineArg(option, 1) + if arguments and (not option[ arg[1] ]) then + local parsed = tonumber(arg[1]) + if parsed then + return parsed + else + self:DebugWarn("Failed to parse as a number: ", arg[1], " for key ", option) + return default + end + end + + return default + end, + + --- Attempts to retrieve a table-like command line argument + ---@param self UIAutolobbyArgumentsComponent | UIAutolobbyCommunications + ---@param option string + ---@return table + GetCommandLineArgumentArray = function(self, option) + if not self:ValidCommandLineKey(option) then + return {} + end + + return import("/lua/system/utils.lua").GetCommandLineArgTable(option) + end, +} From 28734caf609179eee09d5ee713b8634b681d428a Mon Sep 17 00:00:00 2001 From: "(Jip) Willem Wijnia" Date: Fri, 6 Dec 2024 16:37:19 +0100 Subject: [PATCH 4/7] Process remaining command line arguments --- lua/ui/lobby/autolobby/AutolobbyController.lua | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lua/ui/lobby/autolobby/AutolobbyController.lua b/lua/ui/lobby/autolobby/AutolobbyController.lua index c1a17b28804..e8dd17dbbb3 100644 --- a/lua/ui/lobby/autolobby/AutolobbyController.lua +++ b/lua/ui/lobby/autolobby/AutolobbyController.lua @@ -110,7 +110,7 @@ AutolobbyCommunications = Class(MohoLobbyMethods, AutolobbyServerCommunicationsC self.LocalPeerId = "-2" self.LocalPlayerName = "Charlie" - self.PlayerCount = tonumber(GetCommandLineArg("/players", 1)[1]) or 2 + self.PlayerCount = self:GetCommandLineArgumentNumber("/players", 2) self.HostID = "-2" self.GameMods = {} @@ -150,18 +150,18 @@ AutolobbyCommunications = Class(MohoLobbyMethods, AutolobbyServerCommunicationsC -- retrieve team and start spot info.Team = self:GetCommandLineArgumentNumber("/team", -1) - info.StartSpot = tonumber(GetCommandLineArg("/startspot", 1)[1]) or -1 -- TODO + info.StartSpot = self:GetCommandLineArgumentNumber("/startspot", -1) -- determine army color based on start location info.PlayerColor = GameColors.MapToWarmCold(info.StartSpot) info.ArmyColor = GameColors.MapToWarmCold(info.StartSpot) -- retrieve rating - info.DEV = tonumber(GetCommandLineArg("/deviation", 1)[1]) or 500 - info.MEAN = tonumber(GetCommandLineArg("/mean", 1)[1]) or 1500 - info.NG = tonumber(GetCommandLineArg("/numgames", 1)[1]) or 0 - info.DIV = (GetCommandLineArg("/division", 1)[1]) or "" - info.SUBDIV = (GetCommandLineArg("/subdivision", 1)[1]) or "" + info.DEV = self:GetCommandLineArgumentNumber("/deviation", 500) + info.MEAN = self:GetCommandLineArgumentNumber("/mean", 1500) + info.NG = self:GetCommandLineArgumentNumber("/numgames", 0) + info.DIV = self:GetCommandLineArgumentString("/division", "") + info.SUBDIV = self:GetCommandLineArgumentString("/subdivision", "") info.PL = math.floor(info.MEAN - 3 * info.DEV) return info @@ -195,7 +195,7 @@ AutolobbyCommunications = Class(MohoLobbyMethods, AutolobbyServerCommunicationsC } -- process game options from the command line - for name, value in Utils.GetCommandLineArgTable("/gameoptions") do + for name, value in self:GetCommandLineArgumentArray("/gameoptions") do if name and value then options[name] = value else From 8e2b159414680e2c1be02ab68909b82eb0f58765 Mon Sep 17 00:00:00 2001 From: "(Jip) Willem Wijnia" Date: Fri, 6 Dec 2024 16:58:11 +0100 Subject: [PATCH 5/7] Add support for clan tags --- scripts/LaunchFAInstances.ps1 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/LaunchFAInstances.ps1 b/scripts/LaunchFAInstances.ps1 index 4bbf86f2074..123faab0e14 100644 --- a/scripts/LaunchFAInstances.ps1 +++ b/scripts/LaunchFAInstances.ps1 @@ -34,6 +34,7 @@ $gameName = "MyGame" # Array of factions to choose from $factions = @("UEF", "Seraphim", "Cybran", "Aeon") +$clans = @("Yps", "Nom", "Cly", "Mad", "Gol", "Kur", "Row", "Jip", "Bal", "She") # Get the screen resolution (for placing and resizing the windows) Add-Type -AssemblyName System.Windows.Forms @@ -91,7 +92,7 @@ if ($players -eq 1) { $hostLogFile = "host_dev_1.log" $hostFaction = $factions | Get-Random $hostTeamArgument = Get-TeamArgument -instanceNumber 0 - $hostArguments = "/log $hostLogFile /showlog /hostgame $hostProtocol $port $hostPlayerName $gameName $map /startspot 1 /players $players /$hostFaction $hostTeamArgument $baseArguments /division HostDivision /subdivision 1" + $hostArguments = "/log $hostLogFile /showlog /hostgame $hostProtocol $port $hostPlayerName $gameName $map /startspot 1 /players $players /$hostFaction $hostTeamArgument $baseArguments /division HostDivision /subdivision 1 /clan $($clans | Get-Random)" # Launch host game instance Launch-GameInstance -instanceNumber 1 -xPos 0 -yPos 0 -arguments $hostArguments @@ -107,7 +108,7 @@ if ($players -eq 1) { $clientPlayerName = "ClientPlayer_$($i + 1)" $clientFaction = $factions | Get-Random $clientTeamArgument = Get-TeamArgument -instanceNumber $i - $clientArguments = "/log $clientLogFile /joingame $hostProtocol localhost:$port $clientPlayerName /startspot $($i + 1) /players $players /$clientFaction $clientTeamArgument $baseArguments /division Diamond /subdivision $($i + 1)" + $clientArguments = "/log $clientLogFile /joingame $hostProtocol localhost:$port $clientPlayerName /startspot $($i + 1) /players $players /$clientFaction $clientTeamArgument $baseArguments /division Diamond /subdivision $($i + 1) /clan $($clans | Get-Random)" Launch-GameInstance -instanceNumber ($i + 1) -xPos $xPos -yPos $yPos -arguments $clientArguments } From 89e8e7f952c09298f4679392c848347cd02c84ff Mon Sep 17 00:00:00 2001 From: lL1l1 <82986251+lL1l1@users.noreply.github.com> Date: Sun, 8 Dec 2024 18:07:16 -0800 Subject: [PATCH 6/7] Fix typo `arg` instad of `arguments` --- .../lobby/autolobby/components/AutolobbyArguments.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lua/ui/lobby/autolobby/components/AutolobbyArguments.lua b/lua/ui/lobby/autolobby/components/AutolobbyArguments.lua index 7fa0b764d78..c17f4fa4bd7 100644 --- a/lua/ui/lobby/autolobby/components/AutolobbyArguments.lua +++ b/lua/ui/lobby/autolobby/components/AutolobbyArguments.lua @@ -81,8 +81,8 @@ AutolobbyArgumentsComponent = ClassSimple { -- try to get the first argument local arguments = GetCommandLineArg(option, 1) - if arguments and (not option[ arg[1] ]) then - return arg[1] + if arguments and (not option[ arguments[1] ]) then + return arguments[1] end return default @@ -100,12 +100,12 @@ AutolobbyArgumentsComponent = ClassSimple { -- try to get the first argument and parse it as a number local arguments = GetCommandLineArg(option, 1) - if arguments and (not option[ arg[1] ]) then - local parsed = tonumber(arg[1]) + if arguments and (not option[ arguments[1] ]) then + local parsed = tonumber(arguments[1]) if parsed then return parsed else - self:DebugWarn("Failed to parse as a number: ", arg[1], " for key ", option) + self:DebugWarn("Failed to parse as a number: ", arguments[1], " for key ", option) return default end end From b28046562f66f80e215d27aa56d7facc654cfb27 Mon Sep 17 00:00:00 2001 From: lL1l1 <82986251+lL1l1@users.noreply.github.com> Date: Sun, 8 Dec 2024 18:25:08 -0800 Subject: [PATCH 7/7] Add clan tag support in lobby code previous commit was clan tags for the launch script --- lua/ui/lobby/autolobby/AutolobbyController.lua | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/lua/ui/lobby/autolobby/AutolobbyController.lua b/lua/ui/lobby/autolobby/AutolobbyController.lua index e8dd17dbbb3..180d2b652f3 100644 --- a/lua/ui/lobby/autolobby/AutolobbyController.lua +++ b/lua/ui/lobby/autolobby/AutolobbyController.lua @@ -64,6 +64,7 @@ local AutolobbyEngineStrings = { ---@field DIV string # Related to rating/divisions ---@field SUBDIV string # Related to rating/divisions ---@field PL number # Related to rating/divisions +---@field PlayerClan string ---@alias UIAutolobbyConnections boolean[][] ---@alias UIAutolobbyStatus UIPeerLaunchStatus[] @@ -163,6 +164,7 @@ AutolobbyCommunications = Class(MohoLobbyMethods, AutolobbyServerCommunicationsC info.DIV = self:GetCommandLineArgumentString("/division", "") info.SUBDIV = self:GetCommandLineArgumentString("/subdivision", "") info.PL = math.floor(info.MEAN - 3 * info.DEV) + info.PlayerClan = self:GetCommandLineArgumentString("/clan", "") return info end, @@ -334,6 +336,21 @@ AutolobbyCommunications = Class(MohoLobbyMethods, AutolobbyServerCommunicationsC return allDivisions end, + ---@param self UIAutolobbyCommunications + ---@param playerOptions UIAutolobbyPlayer[] + ---@return table + CreateClanTagsTable = function(self, playerOptions) + local allClanTags = {} + + for slot, options in pairs(playerOptions) do + if options.PlayerClan then + allClanTags[options.PlayerName] = options.PlayerClan + end + end + + return allClanTags + end, + --- Verifies whether we can launch the game. ---@param self UIAutolobbyCommunications ---@param peerStatus UIAutolobbyStatus @@ -532,6 +549,7 @@ AutolobbyCommunications = Class(MohoLobbyMethods, AutolobbyServerCommunicationsC -- this way they are available in both the sim and the UI self.GameOptions.Ratings = self:CreateRatingsTable(self.PlayerOptions) self.GameOptions.Divisions = self:CreateDivisionsTable(self.PlayerOptions) + self.GameOptions.ClanTags = self:CreateClanTagsTable(self.PlayerOptions) -- create game configuration local gameConfiguration = {