Merge remote-tracking branch 'upstream/main' into mods
This commit is contained in:
commit
89e1a6b91d
@ -2,9 +2,28 @@ if Engine.GetCurrentMap() ~= "core_frontend" then
|
||||
return
|
||||
end
|
||||
|
||||
local utils = require("utils")
|
||||
local enableLobbyMapVote = true -- toggle map vote in public lobby
|
||||
local enableLargeServerBrowserButton = true -- toggle large server browser button
|
||||
|
||||
CoD.LobbyButtons.MP_STATS = {
|
||||
local utils = require("utils")
|
||||
require("datasources_start_menu_tabs")
|
||||
require("datasources_change_map_categories")
|
||||
require("datasources_gamesettingsflyout_buttons")
|
||||
|
||||
CoD.LobbyButtons.MP_PUBLIC_MATCH = {
|
||||
stringRef = "MENU_PLAY_CAPS",
|
||||
action = NavigateToLobby_SelectionList,
|
||||
param = "MPLobbyOnline",
|
||||
customId = "btnPublicMatch",
|
||||
}
|
||||
|
||||
CoD.LobbyButtons.MP_FIND_MATCH = {
|
||||
stringRef = "MPUI_BASICTRAINING_CAPS",
|
||||
action = OpenFindMatch,
|
||||
customId = "btnFindMatch",
|
||||
}
|
||||
|
||||
CoD.LobbyButtons.STATS = {
|
||||
stringRef = "STATS",
|
||||
action = function(self, element, controller, param, menu)
|
||||
SetPerControllerTableProperty(controller, "disableGameSettingsOptions", true)
|
||||
@ -31,17 +50,48 @@ CoD.LobbyButtons.SETTING_UP_BOTS = {
|
||||
customId = "btnSettingUpBots"
|
||||
}
|
||||
|
||||
CoD.LobbyButtons.MP_CUSTOM_SETUP_GAME = {
|
||||
CoD.LobbyButtons.GameSettingsFlyoutArenas = {
|
||||
stringRef = "MPUI_SETUP_GAME_CAPS",
|
||||
action = OpenSetupGameMP,
|
||||
customId = "btnSetupGame",
|
||||
action = function(self, element, controller, param, menu)
|
||||
SetPerControllerTableProperty(controller, "disableGameSettingsOptions", true)
|
||||
OpenPopup(menu, "GameSettingsFlyoutMP", controller)
|
||||
end,
|
||||
customId = "btnGameSettingsFlyoutMP"
|
||||
}
|
||||
|
||||
local shouldShowMapVote = false
|
||||
CoD.LobbyButtons.GameSettingsFlyoutMP = {
|
||||
stringRef = "MPUI_SETUP_GAME_CAPS",
|
||||
action = function(self, element, controller, param, menu)
|
||||
SetPerControllerTableProperty(controller, "disableGameSettingsOptions", true)
|
||||
OpenPopup(menu, "GameSettingsFlyoutMPCustom", controller)
|
||||
end,
|
||||
customId = "btnGameSettingsFlyoutMPCustom"
|
||||
}
|
||||
|
||||
CoD.LobbyButtons.SERVER_BROWSER = {
|
||||
stringRef = "MENU_SERVER_BROWSER_CAPS",
|
||||
action = function(self, element, controller, param, menu)
|
||||
SetPerControllerTableProperty(controller, "disableGameSettingsOptions", true)
|
||||
OpenPopup(menu, "LobbyServerBrowserOnline", controller)
|
||||
end,
|
||||
customId = "btnDedicated"
|
||||
}
|
||||
|
||||
local shouldShowMapVote = enableLobbyMapVote
|
||||
local lobbyMapVote = function(lobbyMapVoteIsEnabled)
|
||||
if lobbyMapVoteIsEnabled == true then
|
||||
Engine.Exec(nil, "LobbyStopDemo")
|
||||
end
|
||||
end
|
||||
|
||||
local addCustomButtons = function(controller, menuId, buttonTable, isLeader)
|
||||
if menuId == LobbyData.UITargets.UI_MPLOBBYMAIN.id then
|
||||
utils.RemoveSpaces(buttonTable)
|
||||
utils.AddSpacer(buttonTable, utils.GetButtonIndex(buttonTable, CoD.LobbyButtons.THEATER_MP) - 1)
|
||||
end
|
||||
|
||||
if menuId == LobbyData.UITargets.UI_MPLOBBYONLINE.id or menuId == LobbyData.UITargets.UI_ZMLOBBYONLINE.id then
|
||||
utils.AddSpacer(buttonTable)
|
||||
utils.AddSmallButton(controller, buttonTable, CoD.LobbyButtons.MP_STATS)
|
||||
utils.AddSmallButton(controller, buttonTable, CoD.LobbyButtons.STATS)
|
||||
end
|
||||
|
||||
if menuId == LobbyData.UITargets.UI_MPLOBBYONLINE.id or menuId == LobbyData.UITargets.UI_ZMLOBBYONLINE.id or menuId == LobbyData.UITargets.UI_MPLOBBYMAIN.id or menuId == LobbyData.UITargets.UI_MPLOBBYLANGAME.id then
|
||||
@ -49,21 +99,34 @@ local addCustomButtons = function(controller, menuId, buttonTable, isLeader)
|
||||
end
|
||||
|
||||
if menuId == LobbyData.UITargets.UI_MPLOBBYONLINE.id then
|
||||
shouldShowMapVote = true
|
||||
elseif menuId == LobbyData.UITargets.UI_MPLOBBYONLINEPUBLICGAME.id then
|
||||
if shouldShowMapVote == true then
|
||||
shouldShowMapVote = false
|
||||
--Enable map vote at start lobby
|
||||
Engine.Exec(nil, "LobbyStopDemo")
|
||||
shouldShowMapVote = enableLobbyMapVote
|
||||
if enableLargeServerBrowserButton then
|
||||
utils.AddLargeButton(controller, buttonTable, CoD.LobbyButtons.SERVER_BROWSER, 1)
|
||||
end
|
||||
utils.AddLargeButton(controller, buttonTable, CoD.LobbyButtons.MP_START_GAME, 1) --Launch match button
|
||||
utils.AddSpacer(buttonTable, 1)
|
||||
elseif menuId == LobbyData.UITargets.UI_MPLOBBYONLINEPUBLICGAME.id then
|
||||
utils.RemoveButton(buttonTable, CoD.LobbyButtons.MP_PUBLIC_LOBBY_LEADERBOARD)
|
||||
|
||||
utils.AddSpacer(buttonTable)
|
||||
utils.AddSmallButton(controller, buttonTable, CoD.LobbyButtons.MP_CUSTOM_SETUP_GAME) --Setup game in public lobby
|
||||
utils.AddLargeButton(controller, buttonTable, CoD.LobbyButtons.MP_START_GAME, 1)
|
||||
utils.AddSmallButton(controller, buttonTable, CoD.LobbyButtons.GameSettingsFlyoutMP, 2)
|
||||
utils.AddSpacer(buttonTable, utils.GetButtonIndex(buttonTable, CoD.LobbyButtons.GameSettingsFlyoutMP))
|
||||
|
||||
lobbyMapVote(shouldShowMapVote)
|
||||
shouldShowMapVote = false
|
||||
elseif menuId == LobbyData.UITargets.UI_MPLOBBYONLINEARENAGAME.id then
|
||||
utils.AddSpacer(buttonTable)
|
||||
utils.AddSmallButton(controller, buttonTable, CoD.LobbyButtons.SETTING_UP_BOTS) --Bot setting button in public lobby
|
||||
utils.AddLargeButton(controller, buttonTable, CoD.LobbyButtons.MP_START_GAME, 1)
|
||||
utils.AddSmallButton(controller, buttonTable, CoD.LobbyButtons.GameSettingsFlyoutArenas, 2)
|
||||
|
||||
utils.AddSpacer(buttonTable, utils.GetButtonIndex(buttonTable, CoD.LobbyButtons.GameSettingsFlyoutArenas))
|
||||
end
|
||||
|
||||
if menuId == LobbyData.UITargets.UI_ZMLOBBYONLINE.id then
|
||||
utils.RemoveButton(buttonTable, CoD.LobbyButtons.THEATER_ZM)
|
||||
utils.AddLargeButton(controller, buttonTable, CoD.LobbyButtons.THEATER_ZM, #buttonTable + 1)
|
||||
|
||||
utils.RemoveSpaces(buttonTable)
|
||||
utils.AddSpacer(buttonTable, utils.GetButtonIndex(buttonTable, CoD.LobbyButtons.SERVER_BROWSER))
|
||||
utils.AddSpacer(buttonTable, utils.GetButtonIndex(buttonTable, CoD.LobbyButtons.ZM_BUBBLEGUM_BUFFS) - 1)
|
||||
utils.AddSpacer(buttonTable, utils.GetButtonIndex(buttonTable, CoD.LobbyButtons.STATS))
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -0,0 +1,96 @@
|
||||
local f0_local0 = function(f1_arg0, f1_arg1)
|
||||
if not CoD.useMouse then
|
||||
return
|
||||
else
|
||||
LUI.OverrideFunction_CallOriginalFirst(f1_arg0, "setState", function(element, controller)
|
||||
if IsSelfInState(f1_arg0, "SelectingMap") then
|
||||
f1_arg0.mapList:setMouseDisabled(false)
|
||||
f1_arg0.mapCategoriesList:setMouseDisabled(true)
|
||||
f1_arg0.m_categorySet = false
|
||||
else
|
||||
f1_arg0.mapList:setMouseDisabled(true)
|
||||
f1_arg0.mapCategoriesList:setMouseDisabled(false)
|
||||
end
|
||||
end)
|
||||
f1_arg0.mapList:setMouseDisabled(true)
|
||||
f1_arg0.mapList:registerEventHandler("leftclick_outside", function(element, event)
|
||||
if IsSelfInState(f1_arg0, "SelectingMap") and f1_arg0.m_categorySet then
|
||||
CoD.PCUtil.SimulateButtonPress(f1_arg1, Enum.LUIButton.LUI_KEY_XBB_PSCIRCLE)
|
||||
end
|
||||
f1_arg0.m_categorySet = true
|
||||
return true
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
local PostLoadFunc = function(f4_arg0, f4_arg1)
|
||||
f0_local0(f4_arg0, f4_arg1)
|
||||
end
|
||||
|
||||
local f0_local2 = 10000
|
||||
local f0_local3 = 10001
|
||||
local f0_local4 = function(f5_arg0)
|
||||
local f5_local0 = CoD.mapsTable[f5_arg0]
|
||||
if CoD.CONTENT_DLC6_INDEX <= f5_local0.dlc_pack or f5_arg0 == "mp_redwood_ice" or f5_arg0 == "mp_veiled_heyday" then
|
||||
return f0_local3
|
||||
elseif f5_local0.dlc_pack > 0 then
|
||||
return f0_local2
|
||||
else
|
||||
return f5_local0.dlc_pack
|
||||
end
|
||||
end
|
||||
|
||||
DataSources.ChangeMapCategories = DataSourceHelpers.ListSetup("ChangeMapCategories", function(f6_arg0)
|
||||
local f6_local0 = {}
|
||||
local f6_local1 = CoD.GetMapValue(Engine.DvarString(nil, "ui_mapname"), "dlc_pack", CoD.CONTENT_ORIGINAL_MAP_INDEX)
|
||||
local f6_local2 = function(f7_arg0, f7_arg1)
|
||||
return {
|
||||
models = {
|
||||
text = Engine.Localize("MPUI_MAP_CATEGORY_" .. f7_arg0 .. "_CAPS"),
|
||||
buttonText = Engine.Localize("MPUI_MAP_CATEGORY_" .. f7_arg0 .. "_CAPS"),
|
||||
image = "playlist_map",
|
||||
description = Engine.Localize("MPUI_MAP_CATEGORY_" .. f7_arg0 .. "_DESC")
|
||||
},
|
||||
properties = {
|
||||
category = f7_arg1,
|
||||
selectIndex = f6_local1 == f7_arg1
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
CoD.mapsTable = Engine.GetGDTMapsTable()
|
||||
local f6_local3 = function(f8_arg0)
|
||||
for f8_local3, f8_local4 in pairs(CoD.mapsTable) do
|
||||
if f8_local4.session_mode == CoD.gameModeEnum and f0_local4(f8_local3) == f8_arg0 and (ShowPurchasableMap(f6_arg0, f8_local3) or Engine.IsMapValid(f8_local3)) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
if CoD.isCampaign == true then
|
||||
table.insert(f6_local0, f6_local2("missions", CoD.CONTENT_ORIGINAL_MAP_INDEX))
|
||||
table.insert(f6_local0, f6_local2("dev", CoD.CONTENT_DEV_MAP_INDEX))
|
||||
else
|
||||
table.insert(f6_local0, f6_local2("standard", CoD.CONTENT_ORIGINAL_MAP_INDEX))
|
||||
if not Dvar.ui_execdemo:get() and f6_local3(f0_local2) then
|
||||
table.insert(f6_local0, f6_local2("dlc", f0_local2))
|
||||
end
|
||||
if not Dvar.ui_execdemo:get() and f6_local3(f0_local3) then
|
||||
table.insert(f6_local0, f6_local2("dlc_bonus", f0_local3))
|
||||
end
|
||||
if Mods_Enabled() then --and Engine.Mods_Lists_GetInfoEntries( LuaEnums.USERMAP_BASE_PATH, 0, Engine.Mods_Lists_GetInfoEntriesCount( LuaEnums.USERMAP_BASE_PATH ) ) ~= nil then
|
||||
local f9_local11 = Engine.Mods_Lists_GetInfoEntries(LuaEnums.USERMAP_BASE_PATH, 0,
|
||||
Engine.Mods_Lists_GetInfoEntriesCount(LuaEnums.USERMAP_BASE_PATH))
|
||||
if f9_local11 then
|
||||
for f9_local12 = 0, #f9_local11, 1 do
|
||||
local f9_local17 = f9_local11[f9_local12]
|
||||
if LUI.startswith(f9_local17.internalName, "mp_") then
|
||||
table.insert(f6_local0, f6_local2("mods", CoD.CONTENT_MODS_INDEX))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return f6_local0
|
||||
end, true)
|
@ -0,0 +1,260 @@
|
||||
local f0_local0 = function(f1_arg0, f1_arg1)
|
||||
if not CoD.useMouse then
|
||||
return
|
||||
else
|
||||
f1_arg0.Options:setHandleMouse(true)
|
||||
f1_arg0.Options:registerEventHandler("leftclick_outside", function(element, event)
|
||||
CoD.PCUtil.SimulateButtonPress(event.controller, Enum.LUIButton.LUI_KEY_XBB_PSCIRCLE)
|
||||
return true
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
local PostLoadFunc = function(f3_arg0, f3_arg1)
|
||||
f0_local0(f3_arg0, f3_arg1)
|
||||
f3_arg0.disableBlur = true
|
||||
f3_arg0.disablePopupOpenCloseAnim = true
|
||||
Engine.SetModelValue(Engine.CreateModel(Engine.GetGlobalModel(), "GameSettingsFlyoutOpen"), true)
|
||||
LUI.OverrideFunction_CallOriginalSecond(f3_arg0, "close", function(element)
|
||||
Engine.SetModelValue(Engine.CreateModel(Engine.GetGlobalModel(), "GameSettingsFlyoutOpen"), false)
|
||||
end)
|
||||
f3_arg0:registerEventHandler("occlusion_change", function(element, event)
|
||||
local f5_local0 = element:getParent()
|
||||
if f5_local0 then
|
||||
local f5_local1 = f5_local0:getFirstChild()
|
||||
while f5_local1 ~= nil do
|
||||
if f5_local1.menuName == "Lobby" then
|
||||
break
|
||||
end
|
||||
f5_local1 = f5_local1:getNextSibling()
|
||||
end
|
||||
if f5_local1 then
|
||||
if event.occluded == true then
|
||||
f5_local1:setAlpha(0)
|
||||
end
|
||||
f5_local1:setAlpha(1)
|
||||
end
|
||||
end
|
||||
element:OcclusionChange(event)
|
||||
end)
|
||||
f3_arg0:subscribeToModel(Engine.CreateModel(Engine.GetGlobalModel(), "lobbyRoot.lobbyNav", true), function(model)
|
||||
local f6_local0 = f3_arg0.occludedBy
|
||||
while f6_local0 do
|
||||
if f6_local0.occludedBy ~= nil then
|
||||
f6_local0 = f6_local0.occludedBy
|
||||
end
|
||||
while f6_local0 and f6_local0.menuName ~= "Lobby" do
|
||||
f6_local0 = GoBack(f6_local0, f3_arg1)
|
||||
end
|
||||
Engine.SendClientScriptNotify(f3_arg1, "menu_change" .. Engine.GetLocalClientNum(f3_arg1), "Main",
|
||||
"closeToMenu")
|
||||
return
|
||||
end
|
||||
GoBack(f3_arg0, f3_arg1)
|
||||
end, false)
|
||||
end
|
||||
|
||||
DataSources.GameSettingsFlyoutButtonsCustom = DataSourceHelpers.ListSetup("GameSettingsFlyoutButtonsCustom",
|
||||
function(f7_arg0)
|
||||
local f7_local0 = {
|
||||
{
|
||||
optionDisplay = "MPUI_CHANGE_MAP_CAPS",
|
||||
customId = "btnChangeMap",
|
||||
action = OpenChangeMap
|
||||
},
|
||||
-- {
|
||||
-- optionDisplay = "MPUI_CHANGE_GAME_MODE_CAPS",
|
||||
-- customId = "btnChangeGameMode",
|
||||
-- action = OpenChangeGameMode
|
||||
-- },
|
||||
{
|
||||
optionDisplay = "MENU_SETUP_BOTS_CAPS",
|
||||
customId = "btnSetupBots",
|
||||
action = OpenBotSettings
|
||||
},
|
||||
{
|
||||
optionDisplay = "MPUI_EDIT_GAME_RULES_CAPS",
|
||||
customId = "btnEditGameRules",
|
||||
action = OpenEditGameRules
|
||||
}
|
||||
}
|
||||
-- if CoD.isPC and IsServerBrowserEnabled() then
|
||||
-- table.insert( f7_local0, {
|
||||
-- optionDisplay = "PLATFORM_SERVER_SETTINGS_CAPS",
|
||||
-- customID = "btnServerSettings",
|
||||
-- action = OpenServerSettings
|
||||
-- } )
|
||||
-- end
|
||||
local f7_local1 = {}
|
||||
for f7_local5, f7_local6 in ipairs(f7_local0) do
|
||||
table.insert(f7_local1, {
|
||||
models = {
|
||||
displayText = Engine.Localize(f7_local6.optionDisplay),
|
||||
customId = f7_local6.customId,
|
||||
disabled = f7_local6.disabled
|
||||
},
|
||||
properties = {
|
||||
title = f7_local6.optionDisplay,
|
||||
desc = f7_local6.desc,
|
||||
action = f7_local6.action,
|
||||
actionParam = f7_local6.actionParam
|
||||
}
|
||||
})
|
||||
end
|
||||
return f7_local1
|
||||
end, nil, nil, nil)
|
||||
|
||||
LUI.createMenu.GameSettingsFlyoutMPCustom = function(controller)
|
||||
local self = CoD.Menu.NewForUIEditor("GameSettingsFlyoutMPCustom")
|
||||
if PreLoadFunc then
|
||||
PreLoadFunc(self, controller)
|
||||
end
|
||||
self.soundSet = "default"
|
||||
self:setOwner(controller)
|
||||
self:setLeftRight(true, true, 0, 0)
|
||||
self:setTopBottom(true, true, 0, 0)
|
||||
self:playSound("menu_open", controller)
|
||||
self.buttonModel = Engine.CreateModel(Engine.GetModelForController(controller), "GameSettingsFlyoutMP.buttonPrompts")
|
||||
self.anyChildUsesUpdateState = true
|
||||
|
||||
local Options = LUI.UIList.new(self, controller, -2, 0, nil, false, false, 0, 0, false, false)
|
||||
Options:makeFocusable()
|
||||
Options:setLeftRight(true, false, 243.43, 523.43)
|
||||
Options:setTopBottom(true, false, 177.56, 329.56)
|
||||
Options:setYRot(25)
|
||||
Options:setWidgetType(CoD.FE_List1ButtonLarge_PH)
|
||||
Options:setVerticalCount(3)
|
||||
Options:setSpacing(-2)
|
||||
Options:setDataSource("GameSettingsFlyoutButtonsCustom")
|
||||
Options:registerEventHandler("gain_focus", function(element, event)
|
||||
local f9_local0 = nil
|
||||
if element.gainFocus then
|
||||
f9_local0 = element:gainFocus(event)
|
||||
elseif element.super.gainFocus then
|
||||
f9_local0 = element.super:gainFocus(event)
|
||||
end
|
||||
CoD.Menu.UpdateButtonShownState(element, self, controller, Enum.LUIButton.LUI_KEY_XBA_PSCROSS)
|
||||
return f9_local0
|
||||
end)
|
||||
Options:registerEventHandler("lose_focus", function(element, event)
|
||||
local f10_local0 = nil
|
||||
if element.loseFocus then
|
||||
f10_local0 = element:loseFocus(event)
|
||||
elseif element.super.loseFocus then
|
||||
f10_local0 = element.super:loseFocus(event)
|
||||
end
|
||||
return f10_local0
|
||||
end)
|
||||
self:AddButtonCallbackFunction(Options, controller, Enum.LUIButton.LUI_KEY_XBA_PSCROSS, "ENTER",
|
||||
function(element, menu, controller, model)
|
||||
ProcessListAction(self, element, controller)
|
||||
return true
|
||||
end, function(element, menu, controller)
|
||||
CoD.Menu.SetButtonLabel(menu, Enum.LUIButton.LUI_KEY_XBA_PSCROSS, "MENU_SELECT")
|
||||
return true
|
||||
end, false)
|
||||
self:addElement(Options)
|
||||
self.Options = Options
|
||||
|
||||
self:mergeStateConditions({
|
||||
{
|
||||
stateName = "Local",
|
||||
condition = function(menu, element, event)
|
||||
return IsLobbyNetworkModeLAN()
|
||||
end
|
||||
}
|
||||
})
|
||||
self:subscribeToModel(Engine.GetModel(Engine.GetGlobalModel(), "lobbyRoot.lobbyNetworkMode"), function(model)
|
||||
local f14_local0 = self
|
||||
local f14_local1 = {
|
||||
controller = controller,
|
||||
name = "model_validation",
|
||||
modelValue = Engine.GetModelValue(model),
|
||||
modelName = "lobbyRoot.lobbyNetworkMode"
|
||||
}
|
||||
CoD.Menu.UpdateButtonShownState(f14_local0, self, controller, Enum.LUIButton.LUI_KEY_XBY_PSTRIANGLE)
|
||||
end)
|
||||
self:subscribeToModel(Engine.GetModel(Engine.GetGlobalModel(), "lobbyRoot.lobbyNav"), function(model)
|
||||
local f15_local0 = self
|
||||
local f15_local1 = {
|
||||
controller = controller,
|
||||
name = "model_validation",
|
||||
modelValue = Engine.GetModelValue(model),
|
||||
modelName = "lobbyRoot.lobbyNav"
|
||||
}
|
||||
CoD.Menu.UpdateButtonShownState(f15_local0, self, controller, Enum.LUIButton.LUI_KEY_XBY_PSTRIANGLE)
|
||||
end)
|
||||
self:AddButtonCallbackFunction(self, controller, Enum.LUIButton.LUI_KEY_XBB_PSCIRCLE, nil,
|
||||
function(element, menu, controller, model)
|
||||
GoBack(self, controller)
|
||||
ClearMenuSavedState(menu)
|
||||
return true
|
||||
end, function(element, menu, controller)
|
||||
CoD.Menu.SetButtonLabel(menu, Enum.LUIButton.LUI_KEY_XBB_PSCIRCLE, "")
|
||||
return false
|
||||
end, false)
|
||||
self:AddButtonCallbackFunction(self, controller, Enum.LUIButton.LUI_KEY_START, "M",
|
||||
function(element, menu, controller, model)
|
||||
GoBackAndOpenOverlayOnParent(self, "StartMenu_Main", controller)
|
||||
return true
|
||||
end, function(element, menu, controller)
|
||||
CoD.Menu.SetButtonLabel(menu, Enum.LUIButton.LUI_KEY_START, "MENU_MENU")
|
||||
return true
|
||||
end, false)
|
||||
self:AddButtonCallbackFunction(self, controller, Enum.LUIButton.LUI_KEY_XBY_PSTRIANGLE, "S",
|
||||
function(element, menu, controller, model)
|
||||
if not IsLAN() and not IsPlayerAGuest(controller) and IsPlayerAllowedToPlayOnline(controller) then
|
||||
GoBackAndOpenOverlayOnParent(self, "Social_Main", controller)
|
||||
return true
|
||||
else
|
||||
|
||||
end
|
||||
end, function(element, menu, controller)
|
||||
if not IsLAN() and not IsPlayerAGuest(controller) and IsPlayerAllowedToPlayOnline(controller) then
|
||||
CoD.Menu.SetButtonLabel(menu, Enum.LUIButton.LUI_KEY_XBY_PSTRIANGLE, "")
|
||||
return false
|
||||
else
|
||||
return false
|
||||
end
|
||||
end, false)
|
||||
self:AddButtonCallbackFunction(self, controller, Enum.LUIButton.LUI_KEY_LB, nil,
|
||||
function(element, menu, controller, model)
|
||||
SendButtonPressToOccludedMenu(menu, controller, model, Enum.LUIButton.LUI_KEY_LB)
|
||||
return true
|
||||
end, function(element, menu, controller)
|
||||
CoD.Menu.SetButtonLabel(menu, Enum.LUIButton.LUI_KEY_LB, "")
|
||||
return false
|
||||
end, false)
|
||||
self:AddButtonCallbackFunction(self, controller, Enum.LUIButton.LUI_KEY_RB, nil,
|
||||
function(element, menu, controller, model)
|
||||
SendButtonPressToOccludedMenu(menu, controller, model, Enum.LUIButton.LUI_KEY_RB)
|
||||
return true
|
||||
end, function(element, menu, controller)
|
||||
CoD.Menu.SetButtonLabel(menu, Enum.LUIButton.LUI_KEY_RB, "")
|
||||
return false
|
||||
end, false)
|
||||
Options.id = "Options"
|
||||
self:processEvent({
|
||||
name = "menu_loaded",
|
||||
controller = controller
|
||||
})
|
||||
self:processEvent({
|
||||
name = "update_state",
|
||||
menu = self
|
||||
})
|
||||
if not self:restoreState() then
|
||||
self.Options:processEvent({
|
||||
name = "gain_focus",
|
||||
controller = controller
|
||||
})
|
||||
end
|
||||
LUI.OverrideFunction_CallOriginalSecond(self, "close", function(element)
|
||||
element.Options:close()
|
||||
Engine.UnsubscribeAndFreeModel(Engine.GetModel(Engine.GetModelForController(controller),
|
||||
"GameSettingsFlyoutMP.buttonPrompts"))
|
||||
end)
|
||||
if PostLoadFunc then
|
||||
PostLoadFunc(self, controller)
|
||||
end
|
||||
return self
|
||||
end
|
217
data/ui_scripts/frontend_menus/datasources_start_menu_tabs.lua
Normal file
217
data/ui_scripts/frontend_menus/datasources_start_menu_tabs.lua
Normal file
@ -0,0 +1,217 @@
|
||||
DataSources.StartMenuTabs = ListHelper_SetupDataSource("StartMenuTabs", function(f44_arg0)
|
||||
local f44_local0 = {}
|
||||
table.insert(f44_local0, {
|
||||
models = {
|
||||
tabIcon = CoD.buttonStrings.shoulderl
|
||||
},
|
||||
properties = {
|
||||
m_mouseDisabled = true
|
||||
}
|
||||
})
|
||||
if Engine.IsDemoPlaying() then
|
||||
local f44_local1 = "CoD.StartMenu_GameOptions"
|
||||
if Engine.IsZombiesGame() then
|
||||
f44_local1 = "CoD.StartMenu_GameOptions_ZM"
|
||||
end
|
||||
table.insert(f44_local0, {
|
||||
models = {
|
||||
tabName = Engine.Localize("MENU_THEATER_CAPS"),
|
||||
tabWidget = f44_local1,
|
||||
tabIcon = ""
|
||||
},
|
||||
properties = {
|
||||
tabId = "gameOptions"
|
||||
}
|
||||
})
|
||||
elseif Engine.IsInGame() then
|
||||
if IsGameTypeDOA() and not InSafehouse() then
|
||||
table.insert(f44_local0, {
|
||||
models = {
|
||||
tabName = "DOA",
|
||||
tabWidget = "CoD.StartMenu_GameOptions_DOA",
|
||||
tabIcon = ""
|
||||
},
|
||||
properties = {
|
||||
tabId = "gameOptions"
|
||||
}
|
||||
})
|
||||
elseif CoD.isCampaign then
|
||||
table.insert(f44_local0, {
|
||||
models = {
|
||||
tabName = SessionModeToUnlocalizedSessionModeCaps(Engine.CurrentSessionMode()),
|
||||
tabWidget = "CoD.StartMenu_GameOptions_CP",
|
||||
tabIcon = ""
|
||||
},
|
||||
properties = {
|
||||
tabId = "gameOptions"
|
||||
}
|
||||
})
|
||||
if not Engine.IsCampaignModeZombies() then
|
||||
if CoD.isSafehouse and CoD.isOnlineGame() and not IsInTrainingSim(f44_arg0) and Dvar.ui_safehousebarracks:get() and not IsPlayerAGuest(f44_arg0) then
|
||||
table.insert(f44_local0, {
|
||||
models = {
|
||||
tabName = "CPUI_BARRACKS_CAPS",
|
||||
tabWidget = "CoD.CombatRecordCP_Contents",
|
||||
tabIcon = ""
|
||||
},
|
||||
properties = {
|
||||
tabId = "combatRecord"
|
||||
}
|
||||
})
|
||||
end
|
||||
if HighestMapReachedGreaterThan(f44_arg0, 1) or LUI.DEV ~= nil then
|
||||
table.insert(f44_local0, {
|
||||
models = {
|
||||
tabName = "CPUI_TACTICAL_MODE_CAPS",
|
||||
tabWidget = "CoD.StartMenu_TacticalMode",
|
||||
tabIcon = ""
|
||||
},
|
||||
properties = {
|
||||
tabId = "tacticalMode"
|
||||
}
|
||||
})
|
||||
end
|
||||
if not CoD.isSafehouse and not IsPlayerAGuest(f44_arg0) then
|
||||
table.insert(f44_local0, {
|
||||
models = {
|
||||
tabName = "CPUI_ACCOLADES",
|
||||
tabWidget = "CoD.MissionRecordVault_Challenges",
|
||||
tabIcon = ""
|
||||
},
|
||||
properties = {
|
||||
tabId = "accolades"
|
||||
}
|
||||
})
|
||||
end
|
||||
end
|
||||
elseif Engine.IsZombiesGame() then
|
||||
table.insert(f44_local0, {
|
||||
models = {
|
||||
tabName = SessionModeToUnlocalizedSessionModeCaps(Engine.CurrentSessionMode()),
|
||||
tabWidget = "CoD.StartMenu_GameOptions_ZM",
|
||||
tabIcon = ""
|
||||
},
|
||||
properties = {
|
||||
tabId = "gameOptions"
|
||||
}
|
||||
})
|
||||
else
|
||||
table.insert(f44_local0, {
|
||||
models = {
|
||||
tabName = SessionModeToUnlocalizedSessionModeCaps(Engine.CurrentSessionMode()),
|
||||
tabWidget = "CoD.StartMenu_GameOptions",
|
||||
tabIcon = ""
|
||||
},
|
||||
properties = {
|
||||
tabId = "gameOptions"
|
||||
}
|
||||
})
|
||||
end
|
||||
else
|
||||
if not IsPlayerAGuest(f44_arg0) then
|
||||
table.insert(f44_local0, {
|
||||
models = {
|
||||
tabName = "MENU_TAB_IDENTITY_CAPS",
|
||||
tabWidget = "CoD.StartMenu_Identity",
|
||||
tabIcon = ""
|
||||
},
|
||||
properties = {
|
||||
tabId = "identity",
|
||||
disabled = Dvar.ui_execdemo_gamescom:get()
|
||||
}
|
||||
})
|
||||
end
|
||||
if not IsLobbyNetworkModeLAN() and not Dvar.ui_execdemo:get() and not Engine.IsCampaignModeZombies() and not IsPlayerAGuest(f44_arg0) then
|
||||
table.insert(f44_local0, {
|
||||
models = {
|
||||
tabName = "MENU_TAB_CHALLENGES_CAPS",
|
||||
tabWidget = "CoD.StartMenu_Challenges",
|
||||
tabIcon = ""
|
||||
},
|
||||
properties = {
|
||||
tabId = "challenges"
|
||||
}
|
||||
})
|
||||
local f44_local1 = CoD.isPC
|
||||
if f44_local1 then
|
||||
f44_local1 = false --Mods_IsUsingMods()
|
||||
end
|
||||
table.insert(f44_local0, {
|
||||
models = {
|
||||
tabName = "MENU_TAB_BARRACKS_CAPS",
|
||||
tabWidget = "CoD.StartMenu_Barracks",
|
||||
tabIcon = "",
|
||||
disabled = f44_local1
|
||||
},
|
||||
properties = {
|
||||
tabId = "barracks"
|
||||
}
|
||||
})
|
||||
if CommunityOptionsEnabled() then
|
||||
local f44_local2 = CoD.perController[f44_arg0].openMediaTabAfterClosingGroups
|
||||
CoD.perController[f44_arg0].openMediaTabAfterClosingGroups = false
|
||||
table.insert(f44_local0, {
|
||||
models = {
|
||||
tabName = "MENU_TAB_MEDIA_CAPS",
|
||||
tabWidget = "CoD.StartMenu_Media",
|
||||
tabIcon = ""
|
||||
},
|
||||
properties = {
|
||||
tabId = "media",
|
||||
selectIndex = f44_local2
|
||||
}
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
if IsGameTypeDOA() and Engine.IsInGame() and not InSafehouse() then
|
||||
local f44_local1 = table.insert
|
||||
local f44_local2 = f44_local0
|
||||
local f44_local3 = {
|
||||
models = {
|
||||
tabName = "MENU_TAB_OPTIONS_CAPS",
|
||||
tabWidget = "CoD.StartMenu_Options_DOA",
|
||||
tabIcon = ""
|
||||
}
|
||||
}
|
||||
local f44_local4 = {
|
||||
tabId = "options"
|
||||
}
|
||||
local f44_local5 = Dvar.ui_execdemo:get()
|
||||
if f44_local5 then
|
||||
f44_local5 = not Engine.IsInGame()
|
||||
end
|
||||
f44_local4.selectIndex = f44_local5
|
||||
f44_local3.properties = f44_local4
|
||||
f44_local1(f44_local2, f44_local3)
|
||||
else
|
||||
local f44_local1 = table.insert
|
||||
local f44_local2 = f44_local0
|
||||
local f44_local3 = {
|
||||
models = {
|
||||
tabName = "MENU_TAB_OPTIONS_CAPS",
|
||||
tabWidget = "CoD.StartMenu_Options",
|
||||
tabIcon = ""
|
||||
}
|
||||
}
|
||||
local f44_local4 = {
|
||||
tabId = "options"
|
||||
}
|
||||
local f44_local5 = Dvar.ui_execdemo_gamescom:get()
|
||||
if f44_local5 then
|
||||
f44_local5 = not Engine.IsInGame()
|
||||
end
|
||||
f44_local4.selectIndex = f44_local5
|
||||
f44_local3.properties = f44_local4
|
||||
f44_local1(f44_local2, f44_local3)
|
||||
end
|
||||
table.insert(f44_local0, {
|
||||
models = {
|
||||
tabIcon = CoD.buttonStrings.shoulderr
|
||||
},
|
||||
properties = {
|
||||
m_mouseDisabled = true
|
||||
}
|
||||
})
|
||||
return f44_local0
|
||||
end, true)
|
@ -16,6 +16,28 @@ local SetButtonState = function(button, state)
|
||||
end
|
||||
end
|
||||
|
||||
local RemoveButton = function(buttonTable, button)
|
||||
for id, v in pairs(buttonTable) do
|
||||
if buttonTable[id].optionDisplay == button.stringRef then
|
||||
table.remove(buttonTable, id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local RemoveSpaces = function(buttonTable)
|
||||
for id, v in pairs(buttonTable) do
|
||||
buttonTable[id].isLastButtonInGroup = false
|
||||
end
|
||||
end
|
||||
|
||||
local GetButtonIndex = function(buttonTable, button)
|
||||
for id, v in pairs(buttonTable) do
|
||||
if buttonTable[id].optionDisplay == button.stringRef then
|
||||
return id
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local AddButton = function(controller, options, button, isLargeButton, index)
|
||||
if button == nil then
|
||||
return
|
||||
@ -125,5 +147,8 @@ return {
|
||||
AddButton = AddButton,
|
||||
AddLargeButton = AddLargeButton,
|
||||
AddSmallButton = AddSmallButton,
|
||||
AddSpacer = AddSpacer
|
||||
AddSpacer = AddSpacer,
|
||||
RemoveButton = RemoveButton,
|
||||
RemoveSpaces = RemoveSpaces,
|
||||
GetButtonIndex = GetButtonIndex
|
||||
}
|
||||
|
@ -1,84 +1,27 @@
|
||||
if not Engine.IsInGame() then
|
||||
return
|
||||
end
|
||||
|
||||
-- Removed check for public matches to allow team change in ranked matches
|
||||
CoD.IsTeamChangeAllowed = function()
|
||||
if Engine.GetGametypeSetting( "allowInGameTeamChange" ) == 1 then
|
||||
if Engine.GetGametypeSetting("allowInGameTeamChange") == 1 then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
DataSources.StartMenuGameOptions = ListHelper_SetupDataSource("StartMenuGameOptions", function (controller)
|
||||
local options = {}
|
||||
if Engine.IsDemoPlaying() then
|
||||
if not IsDemoRestrictedBasicMode() then
|
||||
table.insert(options, {models = {displayText = Engine.ToUpper(Engine.Localize("MENU_UPLOAD_CLIP", Engine.GetDemoSegmentCount())), action = StartMenuUploadClip, disabledFunction = IsUploadClipButtonDisabled}, properties = {hideHelpItemLabel = true}})
|
||||
end
|
||||
if Engine.IsDemoHighlightReelMode() then
|
||||
table.insert(options, {models = {displayText = Engine.ToUpper(Engine.Localize("MENU_DEMO_CUSTOMIZE_HIGHLIGHT_REEL")), action = StartMenuOpenCustomizeHighlightReel, disabledFunction = IsCustomizeHighlightReelButtonDisabled}})
|
||||
end
|
||||
table.insert(options, {models = {displayText = Engine.ToUpper(Engine.ToUpper(Engine.Localize("MENU_JUMP_TO_START"))), action = StartMenuJumpToStart, disabledFunction = IsJumpToStartButtonDisabled}, properties = {hideHelpItemLabel = true}})
|
||||
local endDemoButtonText = nil
|
||||
if Engine.IsDemoClipPlaying() then
|
||||
endDemoButtonText = Engine.ToUpper(Engine.Localize("MENU_END_CLIP"))
|
||||
else
|
||||
endDemoButtonText = Engine.ToUpper(Engine.Localize("MENU_END_FILM"))
|
||||
end
|
||||
table.insert(options, {models = {displayText = Engine.ToUpper(endDemoButtonText), action = StartMenuEndDemo}})
|
||||
elseif CoD.isCampaign then
|
||||
table.insert(options, {models = {displayText = "MENU_RESUMEGAME_CAPS", action = StartMenuGoBack_ListElement}})
|
||||
local inTrainingSim = CoD.SafeGetModelValue(Engine.GetModelForController(controller), "safehouse.inTrainingSim")
|
||||
if not inTrainingSim then
|
||||
inTrainingSim = 0
|
||||
end
|
||||
if Engine.IsLobbyHost(Enum.LobbyType.LOBBY_TYPE_GAME) then
|
||||
if not CoD.isSafehouse and controller == Engine.GetPrimaryController() then
|
||||
table.insert(options, {models = {displayText = "MENU_RESTART_MISSION_CAPS", action = RestartMission}})
|
||||
if LUI.DEV ~= nil then
|
||||
table.insert(options, {models = {displayText = "MENU_RESTART_CHECKPOINT_CAPS", action = RestartFromCheckpoint}})
|
||||
end
|
||||
end
|
||||
if controller == Engine.GetPrimaryController() then
|
||||
table.insert(options, {models = {displayText = "MENU_CHANGE_DIFFICULTY_CAPS", action = OpenDifficultySelect}})
|
||||
end
|
||||
if CoD.isSafehouse and inTrainingSim == 1 then
|
||||
table.insert(options, {models = {displayText = "MENU_END_TRAINING_SIM", action = EndTrainingSim}})
|
||||
elseif controller == Engine.GetPrimaryController() then
|
||||
if Engine.DvarBool(0, "ui_blocksaves") then
|
||||
table.insert(options, {models = {displayText = "MENU_EXIT_CAPS", action = SaveAndQuitGame}})
|
||||
else
|
||||
table.insert(options, {models = {displayText = "MENU_SAVE_AND_QUIT_CAPS", action = SaveAndQuitGame}})
|
||||
end
|
||||
end
|
||||
elseif CoD.isSafehouse and inTrainingSim == 1 then
|
||||
table.insert(options, {models = {displayText = "MENU_END_TRAINING_SIM", action = EndTrainingSim}})
|
||||
else
|
||||
table.insert(options, {models = {displayText = "MENU_LEAVE_PARTY_AND_EXIT_CAPS", action = QuitGame}})
|
||||
end
|
||||
elseif CoD.isMultiplayer then
|
||||
if Engine.Team(controller, "name") ~= "TEAM_SPECTATOR" and Engine.GetGametypeSetting("disableClassSelection") ~= 1 then
|
||||
table.insert(options, {models = {displayText = "MPUI_CHOOSE_CLASS_BUTTON_CAPS", action = ChooseClass}})
|
||||
end
|
||||
if not Engine.IsVisibilityBitSet(controller, Enum.UIVisibilityBit.BIT_ROUND_END_KILLCAM) and not Engine.IsVisibilityBitSet(controller, Enum.UIVisibilityBit.BIT_FINAL_KILLCAM) and CoD.IsTeamChangeAllowed() then
|
||||
table.insert(options, {models = {displayText = "MPUI_CHANGE_TEAM_BUTTON_CAPS", action = ChooseTeam}})
|
||||
end
|
||||
if controller == 0 then
|
||||
local endGameText = "MENU_QUIT_GAME_CAPS"
|
||||
if Engine.IsLobbyHost(Enum.LobbyType.LOBBY_TYPE_GAME) and not CoD.isOnlineGame() then
|
||||
endGameText = "MENU_END_GAME_CAPS"
|
||||
end
|
||||
table.insert(options, {models = {displayText = endGameText, action = QuitGame_MP}})
|
||||
end
|
||||
elseif CoD.isZombie then
|
||||
table.insert(options, {models = {displayText = "MENU_RESUMEGAME_CAPS", action = StartMenuGoBack_ListElement}})
|
||||
if Engine.IsLobbyHost(Enum.LobbyType.LOBBY_TYPE_GAME) and (not Engine.SessionModeIsMode(CoD.SESSIONMODE_SYSTEMLINK) or Engine.SessionModeIsMode(CoD.SESSIONMODE_OFFLINE)) then
|
||||
table.insert(options, {models = {displayText = "MENU_RESTART_LEVEL_CAPS", action = RestartGame}})
|
||||
end
|
||||
if Engine.IsLobbyHost(Enum.LobbyType.LOBBY_TYPE_GAME) == true then
|
||||
table.insert(options, {models = {displayText = "MENU_END_GAME_CAPS", action = QuitGame_MP}})
|
||||
else
|
||||
table.insert(options, {models = {displayText = "MENU_QUIT_GAME_CAPS", action = QuitGame_MP}})
|
||||
end
|
||||
end
|
||||
return options
|
||||
end, true)
|
||||
local getModeInfo = function()
|
||||
local id = Engine.GetLobbyUIScreen()
|
||||
return LobbyData:UITargetFromId(id)
|
||||
end
|
||||
|
||||
local getMaxClients = function()
|
||||
local modeInfo = getModeInfo()
|
||||
return modeInfo.maxClients
|
||||
end
|
||||
|
||||
-- Set com_maxclients InGame so players can join via direct connect (default from lobbydata)
|
||||
Engine.SetDvar("com_maxclients", getMaxClients())
|
||||
|
||||
require("datasources_start_menu_game_options")
|
||||
|
@ -0,0 +1,75 @@
|
||||
DataSources.StartMenuGameOptions = ListHelper_SetupDataSource("StartMenuGameOptions", function (controller)
|
||||
local options = {}
|
||||
if Engine.IsDemoPlaying() then
|
||||
if not IsDemoRestrictedBasicMode() then
|
||||
table.insert(options, {models = {displayText = Engine.ToUpper(Engine.Localize("MENU_UPLOAD_CLIP", Engine.GetDemoSegmentCount())), action = StartMenuUploadClip, disabledFunction = IsUploadClipButtonDisabled}, properties = {hideHelpItemLabel = true}})
|
||||
end
|
||||
if Engine.IsDemoHighlightReelMode() then
|
||||
table.insert(options, {models = {displayText = Engine.ToUpper(Engine.Localize("MENU_DEMO_CUSTOMIZE_HIGHLIGHT_REEL")), action = StartMenuOpenCustomizeHighlightReel, disabledFunction = IsCustomizeHighlightReelButtonDisabled}})
|
||||
end
|
||||
table.insert(options, {models = {displayText = Engine.ToUpper(Engine.ToUpper(Engine.Localize("MENU_JUMP_TO_START"))), action = StartMenuJumpToStart, disabledFunction = IsJumpToStartButtonDisabled}, properties = {hideHelpItemLabel = true}})
|
||||
local endDemoButtonText = nil
|
||||
if Engine.IsDemoClipPlaying() then
|
||||
endDemoButtonText = Engine.ToUpper(Engine.Localize("MENU_END_CLIP"))
|
||||
else
|
||||
endDemoButtonText = Engine.ToUpper(Engine.Localize("MENU_END_FILM"))
|
||||
end
|
||||
table.insert(options, {models = {displayText = Engine.ToUpper(endDemoButtonText), action = StartMenuEndDemo}})
|
||||
elseif CoD.isCampaign then
|
||||
table.insert(options, {models = {displayText = "MENU_RESUMEGAME_CAPS", action = StartMenuGoBack_ListElement}})
|
||||
local inTrainingSim = CoD.SafeGetModelValue(Engine.GetModelForController(controller), "safehouse.inTrainingSim")
|
||||
if not inTrainingSim then
|
||||
inTrainingSim = 0
|
||||
end
|
||||
if Engine.IsLobbyHost(Enum.LobbyType.LOBBY_TYPE_GAME) then
|
||||
if not CoD.isSafehouse and controller == Engine.GetPrimaryController() then
|
||||
table.insert(options, {models = {displayText = "MENU_RESTART_MISSION_CAPS", action = RestartMission}})
|
||||
if LUI.DEV ~= nil then
|
||||
table.insert(options, {models = {displayText = "MENU_RESTART_CHECKPOINT_CAPS", action = RestartFromCheckpoint}})
|
||||
end
|
||||
end
|
||||
if controller == Engine.GetPrimaryController() then
|
||||
table.insert(options, {models = {displayText = "MENU_CHANGE_DIFFICULTY_CAPS", action = OpenDifficultySelect}})
|
||||
end
|
||||
if CoD.isSafehouse and inTrainingSim == 1 then
|
||||
table.insert(options, {models = {displayText = "MENU_END_TRAINING_SIM", action = EndTrainingSim}})
|
||||
elseif controller == Engine.GetPrimaryController() then
|
||||
if Engine.DvarBool(0, "ui_blocksaves") then
|
||||
table.insert(options, {models = {displayText = "MENU_EXIT_CAPS", action = SaveAndQuitGame}})
|
||||
else
|
||||
table.insert(options, {models = {displayText = "MENU_SAVE_AND_QUIT_CAPS", action = SaveAndQuitGame}})
|
||||
end
|
||||
end
|
||||
elseif CoD.isSafehouse and inTrainingSim == 1 then
|
||||
table.insert(options, {models = {displayText = "MENU_END_TRAINING_SIM", action = EndTrainingSim}})
|
||||
else
|
||||
table.insert(options, {models = {displayText = "MENU_LEAVE_PARTY_AND_EXIT_CAPS", action = QuitGame}})
|
||||
end
|
||||
elseif CoD.isMultiplayer then
|
||||
if Engine.Team(controller, "name") ~= "TEAM_SPECTATOR" and Engine.GetGametypeSetting("disableClassSelection") ~= 1 then
|
||||
table.insert(options, {models = {displayText = "MPUI_CHOOSE_CLASS_BUTTON_CAPS", action = ChooseClass}})
|
||||
end
|
||||
if not Engine.IsVisibilityBitSet(controller, Enum.UIVisibilityBit.BIT_ROUND_END_KILLCAM) and not Engine.IsVisibilityBitSet(controller, Enum.UIVisibilityBit.BIT_FINAL_KILLCAM) and CoD.IsTeamChangeAllowed() then
|
||||
table.insert(options, {models = {displayText = "MPUI_CHANGE_TEAM_BUTTON_CAPS", action = ChooseTeam}})
|
||||
end
|
||||
if controller == 0 then
|
||||
local endGameText = "MENU_QUIT_GAME_CAPS"
|
||||
if Engine.IsLobbyHost(Enum.LobbyType.LOBBY_TYPE_GAME) and not CoD.isOnlineGame() then
|
||||
endGameText = "MENU_END_GAME_CAPS"
|
||||
end
|
||||
table.insert(options, {models = {displayText = endGameText, action = QuitGame_MP}})
|
||||
end
|
||||
elseif CoD.isZombie then
|
||||
table.insert(options, {models = {displayText = "MENU_RESUMEGAME_CAPS", action = StartMenuGoBack_ListElement}})
|
||||
if Engine.IsLobbyHost(Enum.LobbyType.LOBBY_TYPE_GAME) and (not Engine.SessionModeIsMode(CoD.SESSIONMODE_SYSTEMLINK) or Engine.SessionModeIsMode(CoD.SESSIONMODE_OFFLINE)) then
|
||||
table.insert(options, {models = {displayText = "MENU_RESTART_LEVEL_CAPS", action = RestartGame}})
|
||||
end
|
||||
if Engine.IsLobbyHost(Enum.LobbyType.LOBBY_TYPE_GAME) == true then
|
||||
table.insert(options, {models = {displayText = "MENU_END_GAME_CAPS", action = QuitGame_MP}})
|
||||
else
|
||||
table.insert(options, {models = {displayText = "MENU_QUIT_GAME_CAPS", action = QuitGame_MP}})
|
||||
end
|
||||
end
|
||||
table.insert(options, {models = {displayText = "QUIT TO DESKTOP", action = OpenPCQuit}})
|
||||
return options
|
||||
end, true)
|
34
data/ui_scripts/playlist/__init__.lua
Normal file
34
data/ui_scripts/playlist/__init__.lua
Normal file
@ -0,0 +1,34 @@
|
||||
if Engine.GetCurrentMap() ~= "core_frontend" then
|
||||
return
|
||||
end
|
||||
|
||||
if CoD.LobbyMember then
|
||||
local oldLobbyMember = CoD.LobbyMember.new
|
||||
function CoD.LobbyMember.new(menu, controller)
|
||||
local self = oldLobbyMember(menu, controller)
|
||||
|
||||
-- Hide the playlist count text
|
||||
if self.SearchingForPlayer then
|
||||
self.SearchingForPlayer:setAlpha(0)
|
||||
end
|
||||
if self.FEMemberBlurPanelContainer0 then
|
||||
self.FEMemberBlurPanelContainer0:setAlpha(0)
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
end
|
||||
|
||||
function IsLobbyStatusVisible()
|
||||
return false
|
||||
end
|
||||
|
||||
Engine.SetDvar("lobbyMigrate_Enabled", 0)
|
||||
Engine.SetDvar("lobbyTimerStatusVotingInterval", 11000)
|
||||
Engine.SetDvar("lobbyTimerStatusBeginInterval", 10)
|
||||
Engine.SetDvar("lobbyTimerStatusStartInterval", 10)
|
||||
Engine.SetDvar("lobbyTimerStatusPostGameInterval", 10)
|
||||
Engine.SetDvar("lobbyTimerStatusVotingInterval_Arena", 11000)
|
||||
|
||||
require("widget_playlist_match_settings_info")
|
||||
require("widget_playlist_category_match_settings_info")
|
@ -0,0 +1,15 @@
|
||||
if not CoD.playlistCategoryMatchSettingsInfo then
|
||||
return
|
||||
end
|
||||
|
||||
local oldPlaylistCategoryMatchSettingsInfo = CoD.playlistCategoryMatchSettingsInfo.new
|
||||
function CoD.playlistCategoryMatchSettingsInfo.new(menu, controller)
|
||||
local self = oldPlaylistCategoryMatchSettingsInfo(menu, controller)
|
||||
|
||||
-- Hide the playlist count text
|
||||
if self.playlistCount then
|
||||
self.playlistCount:setAlpha(0)
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
@ -0,0 +1,15 @@
|
||||
if not CoD.playlistMatchSettingsInfo then
|
||||
return
|
||||
end
|
||||
|
||||
local oldPlaylistMatchSettingsInfo = CoD.playlistMatchSettingsInfo.new
|
||||
function CoD.playlistMatchSettingsInfo.new(menu, controller)
|
||||
local self = oldPlaylistMatchSettingsInfo(menu, controller)
|
||||
|
||||
-- Hide the playlist count text
|
||||
if self.playlistCount then
|
||||
self.playlistCount:setAlpha(0)
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
2
deps/curl
vendored
2
deps/curl
vendored
@ -1 +1 @@
|
||||
Subproject commit 1c5ed24ee0e929a6f410fcc3729becfd2ee71211
|
||||
Subproject commit 6b1e4dc6cdd2c1fc1730dc64aa5e2d82615e5993
|
2
deps/zlib
vendored
2
deps/zlib
vendored
@ -1 +1 @@
|
||||
Subproject commit 66588683b36042154ad35140bf9fcbb60c5d573c
|
||||
Subproject commit b8a8373ec195c8d286fe7e81e78b4a6d31bd859f
|
@ -382,6 +382,9 @@ namespace auth
|
||||
p(0x141EB74D2_g, 0x141EB7515_g); // ?
|
||||
|
||||
utils::hook::call(0x14134BF7D_g, send_connect_data_stub);
|
||||
|
||||
// Fix crash
|
||||
utils::hook::nop(0x142249097_g, 5);
|
||||
}
|
||||
|
||||
for (const auto& patch : patches)
|
||||
|
@ -9,9 +9,11 @@ namespace discord
|
||||
{
|
||||
namespace
|
||||
{
|
||||
void ready(const DiscordUser* /*request*/)
|
||||
void ready(const DiscordUser* request)
|
||||
{
|
||||
printf("Discord: Ready\n");
|
||||
SetEnvironmentVariableA("discord_user", request->userId);
|
||||
|
||||
printf("Discord: Ready: %s - %s\n", request->userId, request->username);
|
||||
|
||||
DiscordRichPresence discord_presence{};
|
||||
ZeroMemory(&discord_presence, sizeof(discord_presence));
|
||||
|
@ -110,6 +110,7 @@ namespace getinfo
|
||||
info.set("bots", std::to_string(get_bot_count()));
|
||||
info.set("sv_maxclients", std::to_string(get_max_client_count()));
|
||||
info.set("protocol", std::to_string(PROTOCOL));
|
||||
info.set("sub_protocol", std::to_string(SUB_PROTOCOL));
|
||||
info.set("playmode", std::to_string(game::Com_SessionMode_GetMode()));
|
||||
info.set("gamemode", std::to_string(Com_SessionMode_GetGameMode()));
|
||||
info.set("sv_running", std::to_string(game::is_server_running()));
|
||||
|
@ -157,6 +157,14 @@ namespace party
|
||||
return;
|
||||
}
|
||||
|
||||
const auto sub_protocol = atoi(info.get("sub_protocol").data());
|
||||
if (sub_protocol != SUB_PROTOCOL && sub_protocol != (SUB_PROTOCOL - 1))
|
||||
{
|
||||
const auto str = "Invalid sub-protocol.";
|
||||
printf("%s\n", str);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto gamename = info.get("gamename");
|
||||
if (gamename != "T7"s)
|
||||
{
|
||||
|
@ -17,7 +17,7 @@ namespace patches
|
||||
|
||||
void sv_execute_client_messages_stub(game::client_s* client, game::msg_t* msg)
|
||||
{
|
||||
if (client->reliableAcknowledge < 0)
|
||||
if ((client->reliableSequence - client->reliableAcknowledge) < 0)
|
||||
{
|
||||
client->reliableAcknowledge = client->reliableSequence;
|
||||
network::send(client->address, "error", "EXE_LOSTRELIABLECOMMANDS");
|
||||
|
@ -1,164 +1,164 @@
|
||||
#include <std_include.hpp>
|
||||
#include "loader/component_loader.hpp"
|
||||
#include "server_list.hpp"
|
||||
|
||||
#include "game/game.hpp"
|
||||
|
||||
#include <utils/string.hpp>
|
||||
#include <utils/concurrency.hpp>
|
||||
#include <utils/hook.hpp>
|
||||
|
||||
#include "network.hpp"
|
||||
#include "scheduler.hpp"
|
||||
|
||||
namespace server_list
|
||||
{
|
||||
namespace
|
||||
{
|
||||
#include <std_include.hpp>
|
||||
#include "loader/component_loader.hpp"
|
||||
#include "server_list.hpp"
|
||||
|
||||
#include "game/game.hpp"
|
||||
|
||||
#include <utils/string.hpp>
|
||||
#include <utils/concurrency.hpp>
|
||||
#include <utils/hook.hpp>
|
||||
|
||||
#include "network.hpp"
|
||||
#include "scheduler.hpp"
|
||||
|
||||
namespace server_list
|
||||
{
|
||||
namespace
|
||||
{
|
||||
utils::hook::detour lua_serverinfo_to_table_hook;
|
||||
|
||||
struct state
|
||||
{
|
||||
game::netadr_t address{};
|
||||
bool requesting{false};
|
||||
std::chrono::high_resolution_clock::time_point query_start{};
|
||||
callback callback{};
|
||||
};
|
||||
|
||||
utils::concurrency::container<state> master_state;
|
||||
|
||||
void handle_server_list_response(const game::netadr_t& target,
|
||||
const network::data_view& data, state& s)
|
||||
{
|
||||
if (!s.requesting || s.address != target)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
s.requesting = false;
|
||||
const auto callback = std::move(s.callback);
|
||||
|
||||
std::optional<size_t> start{};
|
||||
|
||||
for (size_t i = 0; i + 6 < data.size(); ++i)
|
||||
{
|
||||
if (data[i + 6] == '\\')
|
||||
{
|
||||
start.emplace(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!start.has_value())
|
||||
{
|
||||
callback(true, {});
|
||||
return;
|
||||
}
|
||||
|
||||
std::unordered_set<game::netadr_t> result{};
|
||||
|
||||
for (auto i = start.value(); i + 6 < data.size(); i += 7)
|
||||
{
|
||||
if (data[i + 6] != '\\')
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
game::netadr_t address{};
|
||||
address.type = game::NA_RAWIP;
|
||||
address.localNetID = game::NS_CLIENT1;
|
||||
memcpy(&address.ipv4.a, data.data() + i + 0, 4);
|
||||
memcpy(&address.port, data.data() + i + 4, 2);
|
||||
address.port = ntohs(address.port);
|
||||
|
||||
result.emplace(address);
|
||||
}
|
||||
|
||||
callback(true, result);
|
||||
|
||||
struct state
|
||||
{
|
||||
game::netadr_t address{};
|
||||
bool requesting{false};
|
||||
std::chrono::high_resolution_clock::time_point query_start{};
|
||||
callback callback{};
|
||||
};
|
||||
|
||||
utils::concurrency::container<state> master_state;
|
||||
|
||||
void handle_server_list_response(const game::netadr_t& target,
|
||||
const network::data_view& data, state& s)
|
||||
{
|
||||
if (!s.requesting || s.address != target)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
s.requesting = false;
|
||||
const auto callback = std::move(s.callback);
|
||||
|
||||
std::optional<size_t> start{};
|
||||
|
||||
for (size_t i = 0; i + 6 < data.size(); ++i)
|
||||
{
|
||||
if (data[i + 6] == '\\')
|
||||
{
|
||||
start.emplace(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!start.has_value())
|
||||
{
|
||||
callback(true, {});
|
||||
return;
|
||||
}
|
||||
|
||||
std::unordered_set<game::netadr_t> result{};
|
||||
|
||||
for (auto i = start.value(); i + 6 < data.size(); i += 7)
|
||||
{
|
||||
if (data[i + 6] != '\\')
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
game::netadr_t address{};
|
||||
address.type = game::NA_RAWIP;
|
||||
address.localNetID = game::NS_CLIENT1;
|
||||
memcpy(&address.ipv4.a, data.data() + i + 0, 4);
|
||||
memcpy(&address.port, data.data() + i + 4, 2);
|
||||
address.port = ntohs(address.port);
|
||||
|
||||
result.emplace(address);
|
||||
}
|
||||
|
||||
callback(true, result);
|
||||
}
|
||||
|
||||
void lua_serverinfo_to_table_stub(game::hks::lua_State* state, game::ServerInfo serverInfo, int index)
|
||||
{
|
||||
{
|
||||
lua_serverinfo_to_table_hook.invoke(state, serverInfo, index);
|
||||
|
||||
if (state)
|
||||
{
|
||||
auto botCount = atoi(game::Info_ValueForKey(serverInfo.tags, "bots"));
|
||||
game::Lua_SetTableInt("botCount", botCount, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool get_master_server(game::netadr_t& address)
|
||||
{
|
||||
address = network::address_from_string("server.boiii.re:20810");
|
||||
return address.type != game::NA_BAD;
|
||||
}
|
||||
|
||||
void request_servers(callback callback)
|
||||
{
|
||||
master_state.access([&callback](state& s)
|
||||
{
|
||||
game::netadr_t addr{};
|
||||
if (!get_master_server(addr))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
s.requesting = true;
|
||||
s.address = addr;
|
||||
s.callback = std::move(callback);
|
||||
s.query_start = std::chrono::high_resolution_clock::now();
|
||||
|
||||
network::send(s.address, "getservers", utils::string::va("T7 %i full empty", PROTOCOL));
|
||||
});
|
||||
}
|
||||
|
||||
struct component final : client_component
|
||||
{
|
||||
void post_unpack() override
|
||||
{
|
||||
network::on("getServersResponse", [](const game::netadr_t& target, const network::data_view& data)
|
||||
{
|
||||
master_state.access([&](state& s)
|
||||
{
|
||||
handle_server_list_response(target, data, s);
|
||||
});
|
||||
});
|
||||
|
||||
scheduler::loop([]
|
||||
{
|
||||
master_state.access([](state& s)
|
||||
{
|
||||
if (!s.requesting)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto now = std::chrono::high_resolution_clock::now();
|
||||
if ((now - s.query_start) < 2s)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
s.requesting = false;
|
||||
s.callback(false, {});
|
||||
s.callback = {};
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool get_master_server(game::netadr_t& address)
|
||||
{
|
||||
address = network::address_from_string("server.boiii.re:20810");
|
||||
return address.type != game::NA_BAD;
|
||||
}
|
||||
|
||||
void request_servers(callback callback)
|
||||
{
|
||||
master_state.access([&callback](state& s)
|
||||
{
|
||||
game::netadr_t addr{};
|
||||
if (!get_master_server(addr))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
s.requesting = true;
|
||||
s.address = addr;
|
||||
s.callback = std::move(callback);
|
||||
s.query_start = std::chrono::high_resolution_clock::now();
|
||||
|
||||
network::send(s.address, "getservers", utils::string::va("T7 %i full empty", PROTOCOL));
|
||||
});
|
||||
}
|
||||
|
||||
struct component final : client_component
|
||||
{
|
||||
void post_unpack() override
|
||||
{
|
||||
network::on("getServersResponse", [](const game::netadr_t& target, const network::data_view& data)
|
||||
{
|
||||
master_state.access([&](state& s)
|
||||
{
|
||||
handle_server_list_response(target, data, s);
|
||||
});
|
||||
});
|
||||
|
||||
scheduler::loop([]
|
||||
{
|
||||
master_state.access([](state& s)
|
||||
{
|
||||
if (!s.requesting)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto now = std::chrono::high_resolution_clock::now();
|
||||
if ((now - s.query_start) < 2s)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
s.requesting = false;
|
||||
s.callback(false, {});
|
||||
s.callback = {};
|
||||
});
|
||||
}, scheduler::async, 200ms);
|
||||
|
||||
lua_serverinfo_to_table_hook.create(0x141F1FD10_g, lua_serverinfo_to_table_stub);
|
||||
}
|
||||
|
||||
void pre_destroy() override
|
||||
{
|
||||
master_state.access([](state& s)
|
||||
{
|
||||
s.requesting = false;
|
||||
s.callback = {};
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
REGISTER_COMPONENT(server_list::component)
|
||||
lua_serverinfo_to_table_hook.create(0x141F1FD10_g, lua_serverinfo_to_table_stub);
|
||||
}
|
||||
|
||||
void pre_destroy() override
|
||||
{
|
||||
master_state.access([](state& s)
|
||||
{
|
||||
s.requesting = false;
|
||||
s.callback = {};
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
REGISTER_COMPONENT(server_list::component)
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#define PROTOCOL 3
|
||||
#define PROTOCOL 5
|
||||
#define SUB_PROTOCOL 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace game
|
||||
|
@ -1,333 +1,345 @@
|
||||
#include <std_include.hpp>
|
||||
#include "../steam.hpp"
|
||||
|
||||
#include "game/game.hpp"
|
||||
|
||||
#include "component/party.hpp"
|
||||
#include "component/network.hpp"
|
||||
#include "component/server_list.hpp"
|
||||
|
||||
#include <utils/string.hpp>
|
||||
#include <utils/concurrency.hpp>
|
||||
|
||||
namespace steam
|
||||
{
|
||||
namespace
|
||||
{
|
||||
struct server
|
||||
{
|
||||
bool handled{false};
|
||||
game::netadr_t address{};
|
||||
gameserveritem_t server_item{};
|
||||
};
|
||||
|
||||
auto* const internet_request = reinterpret_cast<void*>(1);
|
||||
|
||||
using servers = std::vector<server>;
|
||||
|
||||
::utils::concurrency::container<servers> queried_servers{};
|
||||
std::atomic<matchmaking_server_list_response*> current_response{};
|
||||
|
||||
gameserveritem_t create_server_item(const game::netadr_t& address, const ::utils::info_string& info,
|
||||
const uint32_t ping, const bool success)
|
||||
{
|
||||
gameserveritem_t server{};
|
||||
server.m_NetAdr.m_usConnectionPort = address.port;
|
||||
server.m_NetAdr.m_usQueryPort = address.port;
|
||||
server.m_NetAdr.m_unIP = ntohl(address.addr);
|
||||
server.m_nPing = static_cast<int>(ping);
|
||||
server.m_bHadSuccessfulResponse = success;
|
||||
server.m_bDoNotRefresh = false;
|
||||
::utils::string::copy(server.m_szGameDir, "");
|
||||
::utils::string::copy(server.m_szMap, info.get("mapname").data());
|
||||
::utils::string::copy(server.m_szGameDescription, info.get("description").data());
|
||||
server.m_nAppID = 311210;
|
||||
server.m_nPlayers = atoi(info.get("clients").data());
|
||||
server.m_nMaxPlayers = atoi(info.get("sv_maxclients").data());
|
||||
server.m_nBotPlayers = atoi(info.get("bots").data());
|
||||
server.m_bPassword = info.get("isPrivate") == "1";
|
||||
server.m_bSecure = true;
|
||||
server.m_ulTimeLastPlayed = 0;
|
||||
server.m_nServerVersion = 1000;
|
||||
::utils::string::copy(server.m_szServerName, info.get("hostname").data());
|
||||
|
||||
const auto playmode = info.get("playmode");
|
||||
const auto mode = game::eModes(std::atoi(playmode.data()));
|
||||
|
||||
const auto* tags = ::utils::string::va(
|
||||
R"(\gametype\%s\dedicated\%s\ranked\false\hardcore\%s\zombies\%s\playerCount\%d\bots\%d\modName\%s\)",
|
||||
info.get("gametype").data(),
|
||||
#include <std_include.hpp>
|
||||
#include "../steam.hpp"
|
||||
|
||||
#include "game/game.hpp"
|
||||
|
||||
#include "component/party.hpp"
|
||||
#include "component/network.hpp"
|
||||
#include "component/server_list.hpp"
|
||||
|
||||
#include <utils/string.hpp>
|
||||
#include <utils/concurrency.hpp>
|
||||
|
||||
namespace steam
|
||||
{
|
||||
namespace
|
||||
{
|
||||
struct server
|
||||
{
|
||||
bool handled{false};
|
||||
game::netadr_t address{};
|
||||
gameserveritem_t server_item{};
|
||||
};
|
||||
|
||||
auto* const internet_request = reinterpret_cast<void*>(1);
|
||||
|
||||
using servers = std::vector<server>;
|
||||
|
||||
::utils::concurrency::container<servers> queried_servers{};
|
||||
std::atomic<matchmaking_server_list_response*> current_response{};
|
||||
|
||||
template <typename T>
|
||||
void copy_safe(T& dest, const char* in)
|
||||
{
|
||||
::utils::string::copy(dest, in);
|
||||
::utils::string::strip_material(dest, dest, std::extent<T>::value);
|
||||
}
|
||||
|
||||
gameserveritem_t create_server_item(const game::netadr_t& address, const ::utils::info_string& info,
|
||||
const uint32_t ping, const bool success)
|
||||
{
|
||||
const auto sub_protocol = atoi(info.get("sub_protocol").data());
|
||||
|
||||
gameserveritem_t server{};
|
||||
server.m_NetAdr.m_usConnectionPort = address.port;
|
||||
server.m_NetAdr.m_usQueryPort = address.port;
|
||||
server.m_NetAdr.m_unIP = ntohl(address.addr);
|
||||
server.m_nPing = static_cast<int>(ping);
|
||||
server.m_bHadSuccessfulResponse = success;
|
||||
server.m_bDoNotRefresh = false;
|
||||
|
||||
copy_safe(server.m_szGameDir, "");
|
||||
copy_safe(server.m_szMap, info.get("mapname").data());
|
||||
copy_safe(server.m_szGameDescription, info.get("description").data());
|
||||
|
||||
server.m_nAppID = (sub_protocol == SUB_PROTOCOL || sub_protocol == (SUB_PROTOCOL - 1)) ? 311210 : 0;
|
||||
server.m_nPlayers = atoi(info.get("clients").data());
|
||||
server.m_nMaxPlayers = atoi(info.get("sv_maxclients").data());
|
||||
server.m_nBotPlayers = atoi(info.get("bots").data());
|
||||
server.m_bPassword = info.get("isPrivate") == "1";
|
||||
server.m_bSecure = true;
|
||||
server.m_ulTimeLastPlayed = 0;
|
||||
server.m_nServerVersion = 1000;
|
||||
|
||||
copy_safe(server.m_szServerName, info.get("hostname").data());
|
||||
|
||||
const auto playmode = info.get("playmode");
|
||||
const auto mode = game::eModes(std::atoi(playmode.data()));
|
||||
|
||||
const auto* tags = ::utils::string::va(
|
||||
R"(\gametype\%s\dedicated\%s\ranked\false\hardcore\%s\zombies\%s\playerCount\%d\bots\%d\modName\%s\)",
|
||||
info.get("gametype").data(),
|
||||
info.get("dedicated") == "1" ? "true" : "false",
|
||||
info.get("hc") == "1" ? "true" : "false",
|
||||
info.get("hc") == "1" ? "true" : "false",
|
||||
mode == game::MODE_ZOMBIES ? "true" : "false",
|
||||
server.m_nPlayers,
|
||||
atoi(info.get("bots").data()),
|
||||
info.get("modName").data());
|
||||
|
||||
::utils::string::copy(server.m_szGameTags, tags);
|
||||
server.m_steamID.bits = strtoull(info.get("xuid").data(), nullptr, 16);
|
||||
|
||||
return server;
|
||||
}
|
||||
|
||||
void handle_server_respone(const bool success, const game::netadr_t& host, const ::utils::info_string& info,
|
||||
const uint32_t ping)
|
||||
{
|
||||
bool all_handled = false;
|
||||
std::optional<int> index{};
|
||||
queried_servers.access([&](servers& srvs)
|
||||
{
|
||||
size_t i = 0;
|
||||
for (; i < srvs.size(); ++i)
|
||||
{
|
||||
if (srvs[i].address == host)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i >= srvs.size())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
index = static_cast<int>(i);
|
||||
|
||||
auto& srv = srvs[i];
|
||||
srv.handled = true;
|
||||
srv.server_item = create_server_item(host, info, ping, success);
|
||||
|
||||
|
||||
for (const auto& entry : srvs)
|
||||
{
|
||||
if (!entry.handled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
all_handled = true;
|
||||
});
|
||||
|
||||
const auto res = current_response.load();
|
||||
if (!index || !res)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (success)
|
||||
{
|
||||
res->ServerResponded(internet_request, *index);
|
||||
}
|
||||
else
|
||||
{
|
||||
res->ServerFailedToRespond(internet_request, *index);
|
||||
}
|
||||
|
||||
if (all_handled)
|
||||
{
|
||||
res->RefreshComplete(internet_request, eServerResponded);
|
||||
}
|
||||
}
|
||||
|
||||
void ping_server(const game::netadr_t& server)
|
||||
{
|
||||
party::query_server(server, handle_server_respone);
|
||||
}
|
||||
}
|
||||
|
||||
void* matchmaking_servers::RequestInternetServerList(unsigned int iApp, void** ppchFilters, unsigned int nFilters,
|
||||
matchmaking_server_list_response* pRequestServersResponse)
|
||||
{
|
||||
current_response = pRequestServersResponse;
|
||||
|
||||
server_list::request_servers([](const bool success, const std::unordered_set<game::netadr_t>& s)
|
||||
{
|
||||
const auto res = current_response.load();
|
||||
if (!res)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!success)
|
||||
{
|
||||
res->RefreshComplete(internet_request, eServerFailedToRespond);
|
||||
return;
|
||||
}
|
||||
|
||||
if (s.empty())
|
||||
{
|
||||
res->RefreshComplete(internet_request, eNoServersListedOnMasterServer);
|
||||
return;
|
||||
}
|
||||
|
||||
queried_servers.access([&s](servers& srvs)
|
||||
{
|
||||
srvs = {};
|
||||
srvs.reserve(s.size());
|
||||
|
||||
for (auto& address : s)
|
||||
{
|
||||
server new_server{};
|
||||
new_server.address = address;
|
||||
new_server.server_item = create_server_item(address, {}, 0, false);
|
||||
|
||||
srvs.push_back(new_server);
|
||||
}
|
||||
});
|
||||
|
||||
for (auto& srv : s)
|
||||
{
|
||||
ping_server(srv);
|
||||
}
|
||||
});
|
||||
|
||||
return internet_request;
|
||||
}
|
||||
|
||||
void* matchmaking_servers::RequestLANServerList(unsigned int iApp,
|
||||
matchmaking_server_list_response* pRequestServersResponse)
|
||||
{
|
||||
return reinterpret_cast<void*>(2);
|
||||
}
|
||||
|
||||
void* matchmaking_servers::RequestFriendsServerList(unsigned int iApp, void** ppchFilters, unsigned int nFilters,
|
||||
matchmaking_server_list_response* pRequestServersResponse)
|
||||
{
|
||||
return reinterpret_cast<void*>(3);
|
||||
}
|
||||
|
||||
void* matchmaking_servers::RequestFavoritesServerList(unsigned int iApp, void** ppchFilters, unsigned int nFilters,
|
||||
matchmaking_server_list_response* pRequestServersResponse)
|
||||
{
|
||||
return reinterpret_cast<void*>(4);
|
||||
}
|
||||
|
||||
void* matchmaking_servers::RequestHistoryServerList(unsigned int iApp, void** ppchFilters, unsigned int nFilters,
|
||||
matchmaking_server_list_response* pRequestServersResponse)
|
||||
{
|
||||
return reinterpret_cast<void*>(5);
|
||||
}
|
||||
|
||||
void* matchmaking_servers::RequestSpectatorServerList(unsigned int iApp, void** ppchFilters, unsigned int nFilters,
|
||||
matchmaking_server_list_response* pRequestServersResponse)
|
||||
{
|
||||
return reinterpret_cast<void*>(6);
|
||||
}
|
||||
|
||||
void matchmaking_servers::ReleaseRequest(void* hServerListRequest)
|
||||
{
|
||||
if (internet_request == hServerListRequest)
|
||||
{
|
||||
current_response = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
gameserveritem_t* matchmaking_servers::GetServerDetails(void* hRequest, int iServer)
|
||||
{
|
||||
if (internet_request != hRequest)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static thread_local gameserveritem_t server_item{};
|
||||
return queried_servers.access<gameserveritem_t*>([iServer](const servers& s) -> gameserveritem_t*
|
||||
{
|
||||
if (iServer < 0 || static_cast<size_t>(iServer) >= s.size())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
server_item = s[iServer].server_item;
|
||||
return &server_item;
|
||||
});
|
||||
}
|
||||
|
||||
void matchmaking_servers::CancelQuery(void* hRequest)
|
||||
{
|
||||
}
|
||||
|
||||
void matchmaking_servers::RefreshQuery(void* hRequest)
|
||||
{
|
||||
}
|
||||
|
||||
bool matchmaking_servers::IsRefreshing(void* hRequest)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int matchmaking_servers::GetServerCount(void* hRequest)
|
||||
{
|
||||
if (internet_request != hRequest)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return queried_servers.access<int>([](const servers& s)
|
||||
{
|
||||
return static_cast<int>(s.size());
|
||||
});
|
||||
}
|
||||
|
||||
void matchmaking_servers::RefreshServer(void* hRequest, const int iServer)
|
||||
{
|
||||
if (internet_request != hRequest)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::optional<game::netadr_t> address{};
|
||||
queried_servers.access([&](const servers& s)
|
||||
{
|
||||
if (iServer < 0 || static_cast<size_t>(iServer) >= s.size())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
address = s[iServer].address;
|
||||
});
|
||||
|
||||
if (address)
|
||||
{
|
||||
ping_server(*address);
|
||||
}
|
||||
}
|
||||
|
||||
void* matchmaking_servers::PingServer(const unsigned int unIP, const unsigned short usPort,
|
||||
matchmaking_ping_response* pRequestServersResponse)
|
||||
{
|
||||
auto response = pRequestServersResponse;
|
||||
const auto addr = network::address_from_ip(htonl(unIP), usPort);
|
||||
|
||||
party::query_server(
|
||||
addr, [response](const bool success, const game::netadr_t& host, const ::utils::info_string& info,
|
||||
const uint32_t ping)
|
||||
{
|
||||
if (success)
|
||||
{
|
||||
auto server_item = create_server_item(host, info, ping, success);
|
||||
response->ServerResponded(server_item);
|
||||
}
|
||||
else
|
||||
{
|
||||
response->ServerFailedToRespond();
|
||||
}
|
||||
});
|
||||
|
||||
return reinterpret_cast<void*>(static_cast<uint64_t>(7 + rand()));
|
||||
}
|
||||
|
||||
int matchmaking_servers::PlayerDetails(unsigned int unIP, unsigned short usPort, void* pRequestServersResponse)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int matchmaking_servers::ServerRules(unsigned int unIP, unsigned short usPort, void* pRequestServersResponse)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void matchmaking_servers::CancelServerQuery(int hServerQuery)
|
||||
{
|
||||
}
|
||||
}
|
||||
info.get("modName").data());
|
||||
|
||||
copy_safe(server.m_szGameTags, tags);
|
||||
|
||||
server.m_steamID.bits = strtoull(info.get("xuid").data(), nullptr, 16);
|
||||
|
||||
return server;
|
||||
}
|
||||
|
||||
void handle_server_respone(const bool success, const game::netadr_t& host, const ::utils::info_string& info,
|
||||
const uint32_t ping)
|
||||
{
|
||||
bool all_handled = false;
|
||||
std::optional<int> index{};
|
||||
queried_servers.access([&](servers& srvs)
|
||||
{
|
||||
size_t i = 0;
|
||||
for (; i < srvs.size(); ++i)
|
||||
{
|
||||
if (srvs[i].address == host)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i >= srvs.size())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
index = static_cast<int>(i);
|
||||
|
||||
auto& srv = srvs[i];
|
||||
srv.handled = true;
|
||||
srv.server_item = create_server_item(host, info, ping, success);
|
||||
|
||||
|
||||
for (const auto& entry : srvs)
|
||||
{
|
||||
if (!entry.handled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
all_handled = true;
|
||||
});
|
||||
|
||||
const auto res = current_response.load();
|
||||
if (!index || !res)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (success)
|
||||
{
|
||||
res->ServerResponded(internet_request, *index);
|
||||
}
|
||||
else
|
||||
{
|
||||
res->ServerFailedToRespond(internet_request, *index);
|
||||
}
|
||||
|
||||
if (all_handled)
|
||||
{
|
||||
res->RefreshComplete(internet_request, eServerResponded);
|
||||
}
|
||||
}
|
||||
|
||||
void ping_server(const game::netadr_t& server)
|
||||
{
|
||||
party::query_server(server, handle_server_respone);
|
||||
}
|
||||
}
|
||||
|
||||
void* matchmaking_servers::RequestInternetServerList(unsigned int iApp, void** ppchFilters, unsigned int nFilters,
|
||||
matchmaking_server_list_response* pRequestServersResponse)
|
||||
{
|
||||
current_response = pRequestServersResponse;
|
||||
|
||||
server_list::request_servers([](const bool success, const std::unordered_set<game::netadr_t>& s)
|
||||
{
|
||||
const auto res = current_response.load();
|
||||
if (!res)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!success)
|
||||
{
|
||||
res->RefreshComplete(internet_request, eServerFailedToRespond);
|
||||
return;
|
||||
}
|
||||
|
||||
if (s.empty())
|
||||
{
|
||||
res->RefreshComplete(internet_request, eNoServersListedOnMasterServer);
|
||||
return;
|
||||
}
|
||||
|
||||
queried_servers.access([&s](servers& srvs)
|
||||
{
|
||||
srvs = {};
|
||||
srvs.reserve(s.size());
|
||||
|
||||
for (auto& address : s)
|
||||
{
|
||||
server new_server{};
|
||||
new_server.address = address;
|
||||
new_server.server_item = create_server_item(address, {}, 0, false);
|
||||
|
||||
srvs.push_back(new_server);
|
||||
}
|
||||
});
|
||||
|
||||
for (auto& srv : s)
|
||||
{
|
||||
ping_server(srv);
|
||||
}
|
||||
});
|
||||
|
||||
return internet_request;
|
||||
}
|
||||
|
||||
void* matchmaking_servers::RequestLANServerList(unsigned int iApp,
|
||||
matchmaking_server_list_response* pRequestServersResponse)
|
||||
{
|
||||
return reinterpret_cast<void*>(2);
|
||||
}
|
||||
|
||||
void* matchmaking_servers::RequestFriendsServerList(unsigned int iApp, void** ppchFilters, unsigned int nFilters,
|
||||
matchmaking_server_list_response* pRequestServersResponse)
|
||||
{
|
||||
return reinterpret_cast<void*>(3);
|
||||
}
|
||||
|
||||
void* matchmaking_servers::RequestFavoritesServerList(unsigned int iApp, void** ppchFilters, unsigned int nFilters,
|
||||
matchmaking_server_list_response* pRequestServersResponse)
|
||||
{
|
||||
return reinterpret_cast<void*>(4);
|
||||
}
|
||||
|
||||
void* matchmaking_servers::RequestHistoryServerList(unsigned int iApp, void** ppchFilters, unsigned int nFilters,
|
||||
matchmaking_server_list_response* pRequestServersResponse)
|
||||
{
|
||||
return reinterpret_cast<void*>(5);
|
||||
}
|
||||
|
||||
void* matchmaking_servers::RequestSpectatorServerList(unsigned int iApp, void** ppchFilters, unsigned int nFilters,
|
||||
matchmaking_server_list_response* pRequestServersResponse)
|
||||
{
|
||||
return reinterpret_cast<void*>(6);
|
||||
}
|
||||
|
||||
void matchmaking_servers::ReleaseRequest(void* hServerListRequest)
|
||||
{
|
||||
if (internet_request == hServerListRequest)
|
||||
{
|
||||
current_response = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
gameserveritem_t* matchmaking_servers::GetServerDetails(void* hRequest, int iServer)
|
||||
{
|
||||
if (internet_request != hRequest)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static thread_local gameserveritem_t server_item{};
|
||||
return queried_servers.access<gameserveritem_t*>([iServer](const servers& s) -> gameserveritem_t* {
|
||||
if (iServer < 0 || static_cast<size_t>(iServer) >= s.size())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
server_item = s[iServer].server_item;
|
||||
return &server_item;
|
||||
});
|
||||
}
|
||||
|
||||
void matchmaking_servers::CancelQuery(void* hRequest)
|
||||
{
|
||||
}
|
||||
|
||||
void matchmaking_servers::RefreshQuery(void* hRequest)
|
||||
{
|
||||
}
|
||||
|
||||
bool matchmaking_servers::IsRefreshing(void* hRequest)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int matchmaking_servers::GetServerCount(void* hRequest)
|
||||
{
|
||||
if (internet_request != hRequest)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return queried_servers.access<int>([](const servers& s)
|
||||
{
|
||||
return static_cast<int>(s.size());
|
||||
});
|
||||
}
|
||||
|
||||
void matchmaking_servers::RefreshServer(void* hRequest, const int iServer)
|
||||
{
|
||||
if (internet_request != hRequest)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::optional<game::netadr_t> address{};
|
||||
queried_servers.access([&](const servers& s)
|
||||
{
|
||||
if (iServer < 0 || static_cast<size_t>(iServer) >= s.size())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
address = s[iServer].address;
|
||||
});
|
||||
|
||||
if (address)
|
||||
{
|
||||
ping_server(*address);
|
||||
}
|
||||
}
|
||||
|
||||
void* matchmaking_servers::PingServer(const unsigned int unIP, const unsigned short usPort,
|
||||
matchmaking_ping_response* pRequestServersResponse)
|
||||
{
|
||||
auto response = pRequestServersResponse;
|
||||
const auto addr = network::address_from_ip(htonl(unIP), usPort);
|
||||
|
||||
party::query_server(
|
||||
addr, [response](const bool success, const game::netadr_t& host, const ::utils::info_string& info,
|
||||
const uint32_t ping)
|
||||
{
|
||||
if (success)
|
||||
{
|
||||
auto server_item = create_server_item(host, info, ping, success);
|
||||
response->ServerResponded(server_item);
|
||||
}
|
||||
else
|
||||
{
|
||||
response->ServerFailedToRespond();
|
||||
}
|
||||
});
|
||||
|
||||
return reinterpret_cast<void*>(static_cast<uint64_t>(7 + rand()));
|
||||
}
|
||||
|
||||
int matchmaking_servers::PlayerDetails(unsigned int unIP, unsigned short usPort, void* pRequestServersResponse)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int matchmaking_servers::ServerRules(unsigned int unIP, unsigned short usPort, void* pRequestServersResponse)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void matchmaking_servers::CancelServerQuery(int hServerQuery)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@ -229,7 +229,20 @@ namespace utils::cryptography
|
||||
|
||||
if (ecc_export(buffer, &length, type, &this->key_storage_) == CRYPT_OK)
|
||||
{
|
||||
return std::string(cs(buffer), length);
|
||||
return {cs(buffer), length};
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string ecc::key::get_openssl() const
|
||||
{
|
||||
uint8_t buffer[4096] = {0};
|
||||
unsigned long length = sizeof(buffer);
|
||||
|
||||
if (ecc_export_openssl(buffer, &length, PK_PUBLIC, &this->key_storage_) == CRYPT_OK)
|
||||
{
|
||||
return {cs(buffer), length};
|
||||
}
|
||||
|
||||
return "";
|
||||
|
@ -31,6 +31,8 @@ namespace utils::cryptography
|
||||
|
||||
std::string serialize(int type = PK_PRIVATE) const;
|
||||
|
||||
std::string get_openssl() const;
|
||||
|
||||
void free();
|
||||
|
||||
bool operator==(key& key) const;
|
||||
|
@ -1,7 +1,8 @@
|
||||
#include "string.hpp"
|
||||
#include <sstream>
|
||||
#include <cstdarg>
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstdarg>
|
||||
#include <sstream>
|
||||
|
||||
#include "nt.hpp"
|
||||
|
||||
@ -116,11 +117,12 @@ namespace utils::string
|
||||
|
||||
void strip(const char* in, char* out, size_t max)
|
||||
{
|
||||
assert(max);
|
||||
if (!in || !out) return;
|
||||
|
||||
max--;
|
||||
size_t current = 0;
|
||||
while (*in != 0 && current < max)
|
||||
while (*in != '\0' && current < max)
|
||||
{
|
||||
const auto color_index = (*(in + 1) - 48) >= 0xC ? 7 : (*(in + 1) - 48);
|
||||
|
||||
@ -141,6 +143,25 @@ namespace utils::string
|
||||
*out = '\0';
|
||||
}
|
||||
|
||||
void strip_material(const char* in, char* out, size_t max)
|
||||
{
|
||||
assert(max);
|
||||
if (!in || !out) return;
|
||||
|
||||
size_t i = 0;
|
||||
while (*in != '\0' && i < max - 1)
|
||||
{
|
||||
if (*in != '$' && *in != '{' && *in != '}')
|
||||
{
|
||||
*out++ = *in;
|
||||
i++;
|
||||
}
|
||||
in++;
|
||||
}
|
||||
|
||||
*out = '\0';
|
||||
}
|
||||
|
||||
std::string convert(const std::wstring& wstr)
|
||||
{
|
||||
std::string result;
|
||||
|
@ -91,6 +91,7 @@ namespace utils::string
|
||||
std::string get_clipboard_data();
|
||||
|
||||
void strip(const char* in, char* out, size_t max);
|
||||
void strip_material(const char* in, char* out, size_t max);
|
||||
|
||||
std::string convert(const std::wstring& wstr);
|
||||
std::wstring convert(const std::string& str);
|
||||
|
Loading…
Reference in New Issue
Block a user