Merge remote-tracking branch 'upstream/main' into favorites
This commit is contained in:
commit
9147501b8d
Binary file not shown.
@ -3,11 +3,9 @@
|
|||||||
#using scripts\shared\callbacks_shared;
|
#using scripts\shared\callbacks_shared;
|
||||||
#using scripts\shared\system_shared;
|
#using scripts\shared\system_shared;
|
||||||
|
|
||||||
#insert scripts\shared\shared.gsh;
|
|
||||||
|
|
||||||
#namespace serversettings;
|
#namespace serversettings;
|
||||||
|
|
||||||
REGISTER_SYSTEM( "serversettings", &__init__, undefined )
|
function autoexec __init__sytem__() { system::register("serversettings",&__init__,undefined,undefined); }
|
||||||
|
|
||||||
function __init__()
|
function __init__()
|
||||||
{
|
{
|
||||||
@ -18,28 +16,24 @@ function init()
|
|||||||
{
|
{
|
||||||
level.hostname = GetDvarString( "sv_hostname");
|
level.hostname = GetDvarString( "sv_hostname");
|
||||||
if(level.hostname == "")
|
if(level.hostname == "")
|
||||||
{
|
|
||||||
level.hostname = "CoDHost";
|
level.hostname = "CoDHost";
|
||||||
}
|
|
||||||
|
|
||||||
SetDvar("sv_hostname", level.hostname);
|
SetDvar("sv_hostname", level.hostname);
|
||||||
SetDvar("ui_hostname", level.hostname);
|
SetDvar("ui_hostname", level.hostname);
|
||||||
|
//makeDvarServerInfo("ui_hostname", "CoDHost");
|
||||||
|
|
||||||
level.motd = GetDvarString( "scr_motd" );
|
level.motd = GetDvarString( "scr_motd" );
|
||||||
if(level.motd == "")
|
if(level.motd == "")
|
||||||
{
|
|
||||||
level.motd = "";
|
level.motd = "";
|
||||||
}
|
|
||||||
SetDvar("scr_motd", level.motd);
|
SetDvar("scr_motd", level.motd);
|
||||||
SetDvar("ui_motd", level.motd);
|
SetDvar("ui_motd", level.motd);
|
||||||
|
//makeDvarServerInfo("ui_motd", "");
|
||||||
|
|
||||||
level.allowvote = GetDvarString( "g_allowvote" );
|
level.allowvote = GetDvarString( "g_allowvote" );
|
||||||
if(level.allowvote == "")
|
if(level.allowvote == "")
|
||||||
{
|
|
||||||
level.allowvote = "1";
|
level.allowvote = "1";
|
||||||
}
|
|
||||||
SetDvar("g_allowvote", level.allowvote);
|
SetDvar("g_allowvote", level.allowvote);
|
||||||
SetDvar("ui_allowvote", level.allowvote);
|
SetDvar("ui_allowvote", level.allowvote);
|
||||||
|
//makeDvarServerInfo("ui_allowvote", "1");
|
||||||
|
|
||||||
level.allow_teamchange = "1";
|
level.allow_teamchange = "1";
|
||||||
SetDvar("ui_allow_teamchange", level.allow_teamchange);
|
SetDvar("ui_allow_teamchange", level.allow_teamchange);
|
||||||
@ -47,6 +41,7 @@ function init()
|
|||||||
level.friendlyfire = GetGametypeSetting( "friendlyfiretype" );
|
level.friendlyfire = GetGametypeSetting( "friendlyfiretype" );
|
||||||
|
|
||||||
SetDvar("ui_friendlyfire", level.friendlyfire);
|
SetDvar("ui_friendlyfire", level.friendlyfire);
|
||||||
|
//makeDvarServerInfo("ui_friendlyfire", "0");
|
||||||
|
|
||||||
if(GetDvarString( "scr_mapsize") == "")
|
if(GetDvarString( "scr_mapsize") == "")
|
||||||
SetDvar("scr_mapsize", "64");
|
SetDvar("scr_mapsize", "64");
|
||||||
|
@ -2,9 +2,28 @@ if Engine.GetCurrentMap() ~= "core_frontend" then
|
|||||||
return
|
return
|
||||||
end
|
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",
|
stringRef = "STATS",
|
||||||
action = function(self, element, controller, param, menu)
|
action = function(self, element, controller, param, menu)
|
||||||
SetPerControllerTableProperty(controller, "disableGameSettingsOptions", true)
|
SetPerControllerTableProperty(controller, "disableGameSettingsOptions", true)
|
||||||
@ -31,17 +50,48 @@ CoD.LobbyButtons.SETTING_UP_BOTS = {
|
|||||||
customId = "btnSettingUpBots"
|
customId = "btnSettingUpBots"
|
||||||
}
|
}
|
||||||
|
|
||||||
CoD.LobbyButtons.MP_CUSTOM_SETUP_GAME = {
|
CoD.LobbyButtons.GameSettingsFlyoutArenas = {
|
||||||
stringRef = "MPUI_SETUP_GAME_CAPS",
|
stringRef = "MPUI_SETUP_GAME_CAPS",
|
||||||
action = OpenSetupGameMP,
|
action = function(self, element, controller, param, menu)
|
||||||
customId = "btnSetupGame",
|
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)
|
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
|
if menuId == LobbyData.UITargets.UI_MPLOBBYONLINE.id or menuId == LobbyData.UITargets.UI_ZMLOBBYONLINE.id then
|
||||||
utils.AddSpacer(buttonTable)
|
utils.AddSmallButton(controller, buttonTable, CoD.LobbyButtons.STATS)
|
||||||
utils.AddSmallButton(controller, buttonTable, CoD.LobbyButtons.MP_STATS)
|
|
||||||
end
|
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
|
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
|
end
|
||||||
|
|
||||||
if menuId == LobbyData.UITargets.UI_MPLOBBYONLINE.id then
|
if menuId == LobbyData.UITargets.UI_MPLOBBYONLINE.id then
|
||||||
shouldShowMapVote = true
|
shouldShowMapVote = enableLobbyMapVote
|
||||||
elseif menuId == LobbyData.UITargets.UI_MPLOBBYONLINEPUBLICGAME.id then
|
if enableLargeServerBrowserButton then
|
||||||
if shouldShowMapVote == true then
|
utils.AddLargeButton(controller, buttonTable, CoD.LobbyButtons.SERVER_BROWSER, 1)
|
||||||
shouldShowMapVote = false
|
|
||||||
--Enable map vote at start lobby
|
|
||||||
Engine.Exec(nil, "LobbyStopDemo")
|
|
||||||
end
|
end
|
||||||
utils.AddLargeButton(controller, buttonTable, CoD.LobbyButtons.MP_START_GAME, 1) --Launch match button
|
elseif menuId == LobbyData.UITargets.UI_MPLOBBYONLINEPUBLICGAME.id then
|
||||||
utils.AddSpacer(buttonTable, 1)
|
utils.RemoveButton(buttonTable, CoD.LobbyButtons.MP_PUBLIC_LOBBY_LEADERBOARD)
|
||||||
|
|
||||||
utils.AddSpacer(buttonTable)
|
utils.AddLargeButton(controller, buttonTable, CoD.LobbyButtons.MP_START_GAME, 1)
|
||||||
utils.AddSmallButton(controller, buttonTable, CoD.LobbyButtons.MP_CUSTOM_SETUP_GAME) --Setup game in public lobby
|
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
|
elseif menuId == LobbyData.UITargets.UI_MPLOBBYONLINEARENAGAME.id then
|
||||||
utils.AddSpacer(buttonTable)
|
utils.AddLargeButton(controller, buttonTable, CoD.LobbyButtons.MP_START_GAME, 1)
|
||||||
utils.AddSmallButton(controller, buttonTable, CoD.LobbyButtons.SETTING_UP_BOTS) --Bot setting button in public lobby
|
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
|
||||||
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
|
||||||
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)
|
local AddButton = function(controller, options, button, isLargeButton, index)
|
||||||
if button == nil then
|
if button == nil then
|
||||||
return
|
return
|
||||||
@ -125,5 +147,8 @@ return {
|
|||||||
AddButton = AddButton,
|
AddButton = AddButton,
|
||||||
AddLargeButton = AddLargeButton,
|
AddLargeButton = AddLargeButton,
|
||||||
AddSmallButton = AddSmallButton,
|
AddSmallButton = AddSmallButton,
|
||||||
AddSpacer = AddSpacer
|
AddSpacer = AddSpacer,
|
||||||
|
RemoveButton = RemoveButton,
|
||||||
|
RemoveSpaces = RemoveSpaces,
|
||||||
|
GetButtonIndex = GetButtonIndex
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
if not Engine.IsInGame() then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
-- Removed check for public matches to allow team change in ranked matches
|
-- Removed check for public matches to allow team change in ranked matches
|
||||||
CoD.IsTeamChangeAllowed = function()
|
CoD.IsTeamChangeAllowed = function()
|
||||||
@ -8,77 +11,17 @@ CoD.IsTeamChangeAllowed = function()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
DataSources.StartMenuGameOptions = ListHelper_SetupDataSource("StartMenuGameOptions", function (controller)
|
local getModeInfo = function()
|
||||||
local options = {}
|
local id = Engine.GetLobbyUIScreen()
|
||||||
if Engine.IsDemoPlaying() then
|
return LobbyData:UITargetFromId(id)
|
||||||
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
|
end
|
||||||
if Engine.IsDemoHighlightReelMode() then
|
|
||||||
table.insert(options, {models = {displayText = Engine.ToUpper(Engine.Localize("MENU_DEMO_CUSTOMIZE_HIGHLIGHT_REEL")), action = StartMenuOpenCustomizeHighlightReel, disabledFunction = IsCustomizeHighlightReelButtonDisabled}})
|
local getMaxClients = function()
|
||||||
|
local modeInfo = getModeInfo()
|
||||||
|
return modeInfo.maxClients
|
||||||
end
|
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
|
-- Set com_maxclients InGame so players can join via direct connect (default from lobbydata)
|
||||||
if Engine.IsDemoClipPlaying() then
|
Engine.SetDvar("com_maxclients", getMaxClients())
|
||||||
endDemoButtonText = Engine.ToUpper(Engine.Localize("MENU_END_CLIP"))
|
|
||||||
else
|
require("datasources_start_menu_game_options")
|
||||||
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)
|
|
||||||
|
@ -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
|
@ -20,7 +20,7 @@ DataSources.MPStatsSettings = DataSourceHelpers.ListSetup("MPStatsSettings", fun
|
|||||||
|
|
||||||
table.insert(optionsTable,
|
table.insert(optionsTable,
|
||||||
CoD.OptionsUtility.CreateDvarSettings(controller, "Unlock All Loot",
|
CoD.OptionsUtility.CreateDvarSettings(controller, "Unlock All Loot",
|
||||||
"Whether loot should be locked based on the player's stats or always unlocked.", "MPStatsSettings_unlock_loot",
|
"Unlocks all Black Market loot.", "MPStatsSettings_unlock_loot",
|
||||||
"cg_unlockall_loot", {
|
"cg_unlockall_loot", {
|
||||||
{
|
{
|
||||||
option = "MENU_DISABLED",
|
option = "MENU_DISABLED",
|
||||||
@ -47,6 +47,20 @@ DataSources.MPStatsSettings = DataSourceHelpers.ListSetup("MPStatsSettings", fun
|
|||||||
value = 1
|
value = 1
|
||||||
},
|
},
|
||||||
}, nil, updateDvar))
|
}, nil, updateDvar))
|
||||||
|
table.insert(optionsTable,
|
||||||
|
CoD.OptionsUtility.CreateDvarSettings(controller, "Unlock All Class Slots",
|
||||||
|
"Unlocks all create-a-class slots and sets.", "MPStatsSettings_unlockall_cac_slots",
|
||||||
|
"cg_unlockall_cac_slots", {
|
||||||
|
{
|
||||||
|
option = "MENU_DISABLED",
|
||||||
|
value = 0,
|
||||||
|
default = true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
option = "MENU_ENABLED",
|
||||||
|
value = 1
|
||||||
|
},
|
||||||
|
}, nil, updateDvar))
|
||||||
end
|
end
|
||||||
table.insert(optionsTable,
|
table.insert(optionsTable,
|
||||||
CoD.OptionsUtility.CreateDvarSettings(controller, "Unlock All Attachments",
|
CoD.OptionsUtility.CreateDvarSettings(controller, "Unlock All Attachments",
|
||||||
|
2
deps/curl
vendored
2
deps/curl
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 7ed010ce2192ae3e4d9663eaaa3a460f316b708b
|
Subproject commit 6b1e4dc6cdd2c1fc1730dc64aa5e2d82615e5993
|
2
deps/zlib
vendored
2
deps/zlib
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 5799c14c8526bf1aaa130c021982f831d155b46d
|
Subproject commit b8a8373ec195c8d286fe7e81e78b4a6d31bd859f
|
@ -2,6 +2,7 @@
|
|||||||
#include "loader/component_loader.hpp"
|
#include "loader/component_loader.hpp"
|
||||||
|
|
||||||
#include "auth.hpp"
|
#include "auth.hpp"
|
||||||
|
#include "party.hpp"
|
||||||
#include "command.hpp"
|
#include "command.hpp"
|
||||||
#include "network.hpp"
|
#include "network.hpp"
|
||||||
#include "scheduler.hpp"
|
#include "scheduler.hpp"
|
||||||
@ -24,6 +25,8 @@ namespace auth
|
|||||||
{
|
{
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
std::array<uint64_t, 18> client_xuids{};
|
||||||
|
|
||||||
std::string get_hdd_serial()
|
std::string get_hdd_serial()
|
||||||
{
|
{
|
||||||
DWORD serial{};
|
DWORD serial{};
|
||||||
@ -151,6 +154,59 @@ namespace auth
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void distribute_player_xuid(const game::netadr_t& target, const size_t player_index, const uint64_t xuid)
|
||||||
|
{
|
||||||
|
if (player_index >= 18)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
utils::byte_buffer buffer{};
|
||||||
|
buffer.write(static_cast<uint32_t>(player_index));
|
||||||
|
buffer.write(xuid);
|
||||||
|
|
||||||
|
game::foreach_connected_client([&](const game::client_s& client, const size_t index)
|
||||||
|
{
|
||||||
|
if (client.address.type != game::NA_BOT)
|
||||||
|
{
|
||||||
|
network::send(client.address, "playerXuid", buffer.get_buffer());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index != player_index && target.type != game::NA_BOT)
|
||||||
|
{
|
||||||
|
utils::byte_buffer current_buffer{};
|
||||||
|
current_buffer.write(static_cast<uint32_t>(index));
|
||||||
|
current_buffer.write(client.xuid);
|
||||||
|
|
||||||
|
network::send(target, "playerXuid", current_buffer.get_buffer());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_new_player(const game::netadr_t& target)
|
||||||
|
{
|
||||||
|
const command::params_sv params{};
|
||||||
|
if (params.size() < 2)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const utils::info_string info_string(params[1]);
|
||||||
|
const auto xuid = strtoull(info_string.get("xuid").data(), nullptr, 16);
|
||||||
|
|
||||||
|
size_t player_index = 18;
|
||||||
|
game::foreach_connected_client([&](game::client_s& client, const size_t index)
|
||||||
|
{
|
||||||
|
if (client.address == target)
|
||||||
|
{
|
||||||
|
client.xuid = xuid;
|
||||||
|
player_index = index;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
distribute_player_xuid(target, player_index, xuid);
|
||||||
|
}
|
||||||
|
|
||||||
void dispatch_connect_packet(const game::netadr_t& target, const std::string& data)
|
void dispatch_connect_packet(const game::netadr_t& target, const std::string& data)
|
||||||
{
|
{
|
||||||
utils::byte_buffer buffer(data);
|
utils::byte_buffer buffer(data);
|
||||||
@ -172,14 +228,7 @@ namespace auth
|
|||||||
profile_infos::add_and_distribute_profile_info(target, xuid, info);
|
profile_infos::add_and_distribute_profile_info(target, xuid, info);
|
||||||
|
|
||||||
game::SV_DirectConnect(target);
|
game::SV_DirectConnect(target);
|
||||||
|
handle_new_player(target);
|
||||||
game::foreach_connected_client([&](game::client_s& client)
|
|
||||||
{
|
|
||||||
if (client.address == target)
|
|
||||||
{
|
|
||||||
client.xuid = xuid;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void handle_connect_packet_fragment(const game::netadr_t& target, const network::data_view& data)
|
void handle_connect_packet_fragment(const game::netadr_t& target, const network::data_view& data)
|
||||||
@ -200,6 +249,30 @@ namespace auth
|
|||||||
}, scheduler::server);
|
}, scheduler::server);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void handle_player_xuid_packet(const game::netadr_t& target, const network::data_view& data)
|
||||||
|
{
|
||||||
|
if (game::is_server_running() || !party::is_host(target))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
utils::byte_buffer buffer(data);
|
||||||
|
|
||||||
|
const auto player_id = buffer.read<uint32_t>();
|
||||||
|
const auto xuid = buffer.read<uint64_t>();
|
||||||
|
|
||||||
|
if (player_id < client_xuids.size())
|
||||||
|
{
|
||||||
|
client_xuids[player_id] = xuid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void direct_connect_bots_stub(const game::netadr_t address)
|
||||||
|
{
|
||||||
|
game::SV_DirectConnect(address);
|
||||||
|
handle_new_player(address);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t get_guid()
|
uint64_t get_guid()
|
||||||
@ -217,6 +290,40 @@ namespace auth
|
|||||||
return guid;
|
return guid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t get_guid(const size_t client_num)
|
||||||
|
{
|
||||||
|
if (client_num >= 18)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!game::is_server_running())
|
||||||
|
{
|
||||||
|
return client_xuids[client_num];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t xuid = 0;
|
||||||
|
const auto callback = [&xuid](const game::client_s& client)
|
||||||
|
{
|
||||||
|
xuid = client.xuid;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!game::access_connected_client(client_num, callback))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return xuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear_stored_guids()
|
||||||
|
{
|
||||||
|
for (auto& xuid : client_xuids)
|
||||||
|
{
|
||||||
|
xuid = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct component final : generic_component
|
struct component final : generic_component
|
||||||
{
|
{
|
||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
@ -224,6 +331,10 @@ namespace auth
|
|||||||
// Skip connect handler
|
// Skip connect handler
|
||||||
utils::hook::set<uint8_t>(game::select(0x142253EFA, 0x14053714A), 0xEB);
|
utils::hook::set<uint8_t>(game::select(0x142253EFA, 0x14053714A), 0xEB);
|
||||||
network::on("connect", handle_connect_packet_fragment);
|
network::on("connect", handle_connect_packet_fragment);
|
||||||
|
network::on("playerXuid", handle_player_xuid_packet);
|
||||||
|
|
||||||
|
// Intercept SV_DirectConnect in SV_AddTestClient
|
||||||
|
utils::hook::call(game::select(0x1422490DC, 0x14052E582), direct_connect_bots_stub);
|
||||||
|
|
||||||
// Patch steam id bit check
|
// Patch steam id bit check
|
||||||
std::vector<std::pair<size_t, size_t>> patches{};
|
std::vector<std::pair<size_t, size_t>> patches{};
|
||||||
@ -271,6 +382,9 @@ namespace auth
|
|||||||
p(0x141EB74D2_g, 0x141EB7515_g); // ?
|
p(0x141EB74D2_g, 0x141EB7515_g); // ?
|
||||||
|
|
||||||
utils::hook::call(0x14134BF7D_g, send_connect_data_stub);
|
utils::hook::call(0x14134BF7D_g, send_connect_data_stub);
|
||||||
|
|
||||||
|
// Fix crash
|
||||||
|
utils::hook::nop(0x142249097_g, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& patch : patches)
|
for (const auto& patch : patches)
|
||||||
|
@ -3,4 +3,6 @@
|
|||||||
namespace auth
|
namespace auth
|
||||||
{
|
{
|
||||||
uint64_t get_guid();
|
uint64_t get_guid();
|
||||||
|
uint64_t get_guid(size_t client_num);
|
||||||
|
void clear_stored_guids();
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,10 @@
|
|||||||
|
|
||||||
#include "game/game.hpp"
|
#include "game/game.hpp"
|
||||||
|
|
||||||
|
#include "auth.hpp"
|
||||||
|
|
||||||
|
#include "steam/steam.hpp"
|
||||||
|
|
||||||
#include <utils/hook.hpp>
|
#include <utils/hook.hpp>
|
||||||
#include <utils/string.hpp>
|
#include <utils/string.hpp>
|
||||||
|
|
||||||
@ -10,8 +14,25 @@ namespace colors
|
|||||||
{
|
{
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
utils::hook::detour get_player_name_hook;
|
utils::hook::detour cl_get_client_name_hook;
|
||||||
utils::hook::detour get_gamer_tag_hook;
|
|
||||||
|
std::optional<int> get_color_for_xuid(const uint64_t xuid)
|
||||||
|
{
|
||||||
|
if (xuid == 0xCD02AF6448291209
|
||||||
|
|| xuid == 0x10F0C433E08E1357
|
||||||
|
|| xuid == 0x60E0FEFE42341715)
|
||||||
|
{
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<int> get_color_for_client(const int client_num)
|
||||||
|
{
|
||||||
|
const auto xuid = auth::get_guid(static_cast<size_t>(client_num));
|
||||||
|
return get_color_for_xuid(xuid);
|
||||||
|
}
|
||||||
|
|
||||||
template <size_t index>
|
template <size_t index>
|
||||||
void patch_color(const uint8_t r, const uint8_t g, const uint8_t b, const uint8_t a = 255)
|
void patch_color(const uint8_t r, const uint8_t g, const uint8_t b, const uint8_t a = 255)
|
||||||
@ -36,23 +57,39 @@ namespace colors
|
|||||||
utils::hook::copy(g_color_table + index * 4, color_float, sizeof(color_float));
|
utils::hook::copy(g_color_table + index * 4, color_float, sizeof(color_float));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*uint64_t get_player_name_stub(const uint64_t client, int client_num, char* buffer, const int size,
|
bool cl_get_client_name_stub(const int local_client_num, const int index, char* buf, const int size,
|
||||||
const bool has_clan_tag)
|
const bool add_clan_name)
|
||||||
{
|
{
|
||||||
const auto res = get_player_name_hook.invoke<uint64_t>(client, client_num, buffer, size, has_clan_tag);
|
const auto res = cl_get_client_name_hook.invoke<bool>(local_client_num, index, buf, size, add_clan_name);
|
||||||
|
|
||||||
if (_ReturnAddress() != reinterpret_cast<void*>(0x1406A7B56_g))
|
if (_ReturnAddress() == reinterpret_cast<void*>(0x1406A7B56_g))
|
||||||
{
|
{
|
||||||
const auto val = utils::string::va("^%d%s", rand() % 7, buffer);
|
return res;
|
||||||
strncpy_s(buffer, size, val, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
const auto color = get_color_for_client(index);
|
||||||
}*/
|
if (!color)
|
||||||
|
|
||||||
/*const char* get_gamer_tag_stub(const uint64_t num)
|
|
||||||
{
|
{
|
||||||
return utils::string::va("^3%s", get_gamer_tag_hook.invoke<const char*>(num));
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto val = utils::string::va("^%d%s", *color, buf);
|
||||||
|
utils::string::copy(buf, size, val);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*const char* get_gamer_tag_stub(const uint32_t num)
|
||||||
|
{
|
||||||
|
const auto color = get_color_for_xuid(steam::SteamUser()->GetSteamID().bits);
|
||||||
|
const auto name = reinterpret_cast<const char* (*)(uint32_t)>(0x141EC6E80)(num) + 8;
|
||||||
|
|
||||||
|
if (!color || num)
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return utils::string::va("^1%s", *color, name);
|
||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,8 +105,8 @@ namespace colors
|
|||||||
patch_color<6>(151, 80, 221); // 6 - Pink
|
patch_color<6>(151, 80, 221); // 6 - Pink
|
||||||
|
|
||||||
// Old addresses
|
// Old addresses
|
||||||
//get_player_name_hook.create(0x1413E3140_g, get_player_name_stub);
|
cl_get_client_name_hook.create(game::CL_GetClientName, cl_get_client_name_stub);
|
||||||
//get_gamer_tag_hook.create(0x141EC7370_g, get_gamer_tag_stub);
|
//utils::hook::jump(0x141EC72E0_g, get_gamer_tag_stub);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -9,9 +9,11 @@ namespace discord
|
|||||||
{
|
{
|
||||||
namespace
|
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{};
|
DiscordRichPresence discord_presence{};
|
||||||
ZeroMemory(&discord_presence, sizeof(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("bots", std::to_string(get_bot_count()));
|
||||||
info.set("sv_maxclients", std::to_string(get_max_client_count()));
|
info.set("sv_maxclients", std::to_string(get_max_client_count()));
|
||||||
info.set("protocol", std::to_string(PROTOCOL));
|
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("playmode", std::to_string(game::Com_SessionMode_GetMode()));
|
||||||
info.set("gamemode", std::to_string(Com_SessionMode_GetGameMode()));
|
info.set("gamemode", std::to_string(Com_SessionMode_GetGameMode()));
|
||||||
info.set("sv_running", std::to_string(game::is_server_running()));
|
info.set("sv_running", std::to_string(game::is_server_running()));
|
||||||
|
@ -17,6 +17,7 @@ namespace loot
|
|||||||
const game::dvar_t* dvar_cg_unlockall_camos_and_reticles;
|
const game::dvar_t* dvar_cg_unlockall_camos_and_reticles;
|
||||||
const game::dvar_t* dvar_cg_unlockall_calling_cards;
|
const game::dvar_t* dvar_cg_unlockall_calling_cards;
|
||||||
const game::dvar_t* dvar_cg_unlockall_specialists_outfits;
|
const game::dvar_t* dvar_cg_unlockall_specialists_outfits;
|
||||||
|
const game::dvar_t* dvar_cg_unlockall_cac_slots;
|
||||||
|
|
||||||
utils::hook::detour loot_getitemquantity_hook;
|
utils::hook::detour loot_getitemquantity_hook;
|
||||||
utils::hook::detour liveinventory_getitemquantity_hook;
|
utils::hook::detour liveinventory_getitemquantity_hook;
|
||||||
@ -30,6 +31,7 @@ namespace loot
|
|||||||
utils::hook::detour bg_unlockablescharactercustomizationitemlocked_hook;
|
utils::hook::detour bg_unlockablescharactercustomizationitemlocked_hook;
|
||||||
utils::hook::detour bg_emblemisentitlementbackgroundgranted_hook;
|
utils::hook::detour bg_emblemisentitlementbackgroundgranted_hook;
|
||||||
utils::hook::detour liveentitlements_isentitlementactiveforcontroller_hook;
|
utils::hook::detour liveentitlements_isentitlementactiveforcontroller_hook;
|
||||||
|
utils::hook::detour bg_unlockablesgetcustomclasscount_hook;
|
||||||
|
|
||||||
int loot_getitemquantity_stub(const game::ControllerIndex_t controller_index, const game::eModes mode, const int item_id)
|
int loot_getitemquantity_stub(const game::ControllerIndex_t controller_index, const game::eModes mode, const int item_id)
|
||||||
{
|
{
|
||||||
@ -48,19 +50,25 @@ namespace loot
|
|||||||
|
|
||||||
int liveinventory_getitemquantity_stub(const game::ControllerIndex_t controller_index, const int item_id)
|
int liveinventory_getitemquantity_stub(const game::ControllerIndex_t controller_index, const int item_id)
|
||||||
{
|
{
|
||||||
// Item id's for extra CaC slots, CWL camo's and paid specialist outfits
|
// Item id's for CWL camo's and paid specialist outfits
|
||||||
if (dvar_cg_unlockall_loot->current.value.enabled && (item_id == 99003 || item_id >= 99018 && item_id <= 99021 || item_id == 99025 ||
|
if (dvar_cg_unlockall_loot->current.value.enabled && (item_id == 99003 || item_id >= 99018 && item_id <= 99021 || item_id == 99025 ||
|
||||||
item_id >= 90047 && item_id <= 90064))
|
item_id >= 90047 && item_id <= 90064))
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Item id for extra CaC slots
|
||||||
|
if (dvar_cg_unlockall_cac_slots->current.value.enabled && item_id == 99003)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
return liveinventory_getitemquantity_hook.invoke<int>(controller_index, item_id);
|
return liveinventory_getitemquantity_hook.invoke<int>(controller_index, item_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool liveinventory_areextraslotspurchased_stub(const game::ControllerIndex_t controller_index)
|
bool liveinventory_areextraslotspurchased_stub(const game::ControllerIndex_t controller_index)
|
||||||
{
|
{
|
||||||
if (dvar_cg_unlockall_loot->current.value.enabled)
|
if (dvar_cg_unlockall_cac_slots->current.value.enabled)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -160,6 +168,16 @@ namespace loot
|
|||||||
|
|
||||||
return liveentitlements_isentitlementactiveforcontroller_hook.invoke<bool>(controllerIndex, incentiveId);
|
return liveentitlements_isentitlementactiveforcontroller_hook.invoke<bool>(controllerIndex, incentiveId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int bg_unlockablesgetcustomclasscount_stub(game::eModes mode, const game::ControllerIndex_t controllerIndex)
|
||||||
|
{
|
||||||
|
if (dvar_cg_unlockall_cac_slots->current.value.enabled)
|
||||||
|
{
|
||||||
|
return 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bg_unlockablesgetcustomclasscount_hook.invoke<int>(mode, controllerIndex);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct component final: client_component
|
struct component final: client_component
|
||||||
@ -172,6 +190,7 @@ namespace loot
|
|||||||
dvar_cg_unlockall_camos_and_reticles = game::register_dvar_bool("cg_unlockall_camos_and_reticles", false, game::DVAR_ARCHIVE, "Unlocks all camos and reticles");
|
dvar_cg_unlockall_camos_and_reticles = game::register_dvar_bool("cg_unlockall_camos_and_reticles", false, game::DVAR_ARCHIVE, "Unlocks all camos and reticles");
|
||||||
dvar_cg_unlockall_calling_cards = game::register_dvar_bool("cg_unlockall_calling_cards", false, game::DVAR_ARCHIVE, "Unlocks all calling cards");
|
dvar_cg_unlockall_calling_cards = game::register_dvar_bool("cg_unlockall_calling_cards", false, game::DVAR_ARCHIVE, "Unlocks all calling cards");
|
||||||
dvar_cg_unlockall_specialists_outfits = game::register_dvar_bool("cg_unlockall_specialists_outfits", false, game::DVAR_ARCHIVE, "Unlocks all specialists outfits");
|
dvar_cg_unlockall_specialists_outfits = game::register_dvar_bool("cg_unlockall_specialists_outfits", false, game::DVAR_ARCHIVE, "Unlocks all specialists outfits");
|
||||||
|
dvar_cg_unlockall_cac_slots = game::register_dvar_bool("cg_unlockall_cac_slots", false, game::DVAR_ARCHIVE, "Unlocks all Create a Class Slots");
|
||||||
|
|
||||||
loot_getitemquantity_hook.create(0x141E82C00_g, loot_getitemquantity_stub);
|
loot_getitemquantity_hook.create(0x141E82C00_g, loot_getitemquantity_stub);
|
||||||
liveinventory_getitemquantity_hook.create(0x141E09030_g, liveinventory_getitemquantity_stub);
|
liveinventory_getitemquantity_hook.create(0x141E09030_g, liveinventory_getitemquantity_stub);
|
||||||
@ -185,6 +204,7 @@ namespace loot
|
|||||||
bg_unlockablescharactercustomizationitemlocked_hook.create(0x1426A2030_g, bg_unlockablescharactercustomizationitemlocked_stub);
|
bg_unlockablescharactercustomizationitemlocked_hook.create(0x1426A2030_g, bg_unlockablescharactercustomizationitemlocked_stub);
|
||||||
bg_emblemisentitlementbackgroundgranted_hook.create(0x142667520_g, bg_emblemisentitlementbackgroundgranted_stub);
|
bg_emblemisentitlementbackgroundgranted_hook.create(0x142667520_g, bg_emblemisentitlementbackgroundgranted_stub);
|
||||||
liveentitlements_isentitlementactiveforcontroller_hook.create(0x141E124E0_g, liveentitlements_isentitlementactiveforcontroller_stub);
|
liveentitlements_isentitlementactiveforcontroller_hook.create(0x141E124E0_g, liveentitlements_isentitlementactiveforcontroller_stub);
|
||||||
|
bg_unlockablesgetcustomclasscount_hook.create(0x1426A5900_g, bg_unlockablesgetcustomclasscount_stub);
|
||||||
|
|
||||||
scheduler::once([]() {
|
scheduler::once([]() {
|
||||||
if (dvar_cg_unlockall_loot->current.value.enabled)
|
if (dvar_cg_unlockall_loot->current.value.enabled)
|
||||||
|
@ -163,7 +163,6 @@ namespace network
|
|||||||
: 0;
|
: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint64_t ret2()
|
uint64_t ret2()
|
||||||
{
|
{
|
||||||
return 2;
|
return 2;
|
||||||
@ -173,6 +172,15 @@ namespace network
|
|||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void com_error_oob_stub(const char* file, int line, int code, [[maybe_unused]] const char* fmt, const char* error)
|
||||||
|
{
|
||||||
|
char buffer[1024]{};
|
||||||
|
|
||||||
|
strncpy_s(buffer, error, _TRUNCATE);
|
||||||
|
|
||||||
|
game::Com_Error_(file, line, code, "%s", buffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void on(const std::string& command, const callback& callback)
|
void on(const std::string& command, const callback& callback)
|
||||||
@ -321,10 +329,21 @@ namespace network
|
|||||||
// NA_IP -> NA_RAWIP in NetAdr_ToString
|
// NA_IP -> NA_RAWIP in NetAdr_ToString
|
||||||
utils::hook::set<uint8_t>(game::select(0x142172ED4, 0x140515864), game::NA_RAWIP);
|
utils::hook::set<uint8_t>(game::select(0x142172ED4, 0x140515864), game::NA_RAWIP);
|
||||||
|
|
||||||
|
// Kill 'echo' OOB handler
|
||||||
|
utils::hook::set<uint8_t>(game::select(0x14134D0FB, 0x14018EE82), 0xEB);
|
||||||
|
|
||||||
if (game::is_server())
|
if (game::is_server())
|
||||||
{
|
{
|
||||||
// Remove restrictions for rcon commands
|
// Remove restrictions for rcon commands
|
||||||
utils::hook::call(0x140538D5C_g, &con_restricted_execute_buf_stub); // SVC_RemoteCommand
|
utils::hook::call(0x140538D5C_g, con_restricted_execute_buf_stub); // SVC_RemoteCommand
|
||||||
|
|
||||||
|
// Kill 'error' OOB handler on the dedi
|
||||||
|
utils::hook::nop(0x14018EF8B_g, 5);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Truncate error string to make sure there are no buffer overruns later
|
||||||
|
utils::hook::call(0x14134D206_g, com_error_oob_stub);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Fix that
|
// TODO: Fix that
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "game/game.hpp"
|
#include "game/game.hpp"
|
||||||
|
|
||||||
#include "party.hpp"
|
#include "party.hpp"
|
||||||
|
#include "auth.hpp"
|
||||||
#include "network.hpp"
|
#include "network.hpp"
|
||||||
#include "scheduler.hpp"
|
#include "scheduler.hpp"
|
||||||
#include "workshop.hpp"
|
#include "workshop.hpp"
|
||||||
@ -39,6 +40,8 @@ namespace party
|
|||||||
void connect_to_lobby(const game::netadr_t& addr, const std::string& mapname, const std::string& gamemode,
|
void connect_to_lobby(const game::netadr_t& addr, const std::string& mapname, const std::string& gamemode,
|
||||||
const std::string& usermap_id, const std::string& mod_id)
|
const std::string& usermap_id, const std::string& mod_id)
|
||||||
{
|
{
|
||||||
|
auth::clear_stored_guids();
|
||||||
|
|
||||||
workshop::load_mod_if_needed(usermap_id, mod_id);
|
workshop::load_mod_if_needed(usermap_id, mod_id);
|
||||||
|
|
||||||
game::XSESSION_INFO info{};
|
game::XSESSION_INFO info{};
|
||||||
@ -56,7 +59,8 @@ namespace party
|
|||||||
}
|
}
|
||||||
|
|
||||||
void connect_to_lobby_with_mode(const game::netadr_t& addr, const game::eModes mode, const std::string& mapname,
|
void connect_to_lobby_with_mode(const game::netadr_t& addr, const game::eModes mode, const std::string& mapname,
|
||||||
const std::string& gametype, const std::string& usermap_id, const std::string& mod_id,
|
const std::string& gametype, const std::string& usermap_id,
|
||||||
|
const std::string& mod_id,
|
||||||
const bool was_retried = false)
|
const bool was_retried = false)
|
||||||
{
|
{
|
||||||
if (game::Com_SessionMode_IsMode(mode))
|
if (game::Com_SessionMode_IsMode(mode))
|
||||||
@ -153,6 +157,14 @@ namespace party
|
|||||||
return;
|
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");
|
const auto gamename = info.get("gamename");
|
||||||
if (gamename != "T7"s)
|
if (gamename != "T7"s)
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <utils/info_string.hpp>
|
#include <utils/info_string.hpp>
|
||||||
|
|
||||||
|
#include "game/game.hpp"
|
||||||
|
|
||||||
namespace party
|
namespace party
|
||||||
{
|
{
|
||||||
using query_callback_func = void(bool success, const game::netadr_t& host, const ::utils::info_string& info, uint32_t ping);
|
using query_callback_func = void(bool success, const game::netadr_t& host, const ::utils::info_string& info, uint32_t ping);
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <game/game.hpp>
|
#include <game/game.hpp>
|
||||||
#include <game/utils.hpp>
|
#include <game/utils.hpp>
|
||||||
|
|
||||||
|
#include "network.hpp"
|
||||||
#include "scheduler.hpp"
|
#include "scheduler.hpp"
|
||||||
|
|
||||||
#include <utils/hook.hpp>
|
#include <utils/hook.hpp>
|
||||||
@ -12,6 +13,20 @@ namespace patches
|
|||||||
{
|
{
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
utils::hook::detour sv_execute_client_messages_hook;
|
||||||
|
|
||||||
|
void sv_execute_client_messages_stub(game::client_s* client, game::msg_t* msg)
|
||||||
|
{
|
||||||
|
if ((client->reliableSequence - client->reliableAcknowledge) < 0)
|
||||||
|
{
|
||||||
|
client->reliableAcknowledge = client->reliableSequence;
|
||||||
|
network::send(client->address, "error", "EXE_LOSTRELIABLECOMMANDS");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sv_execute_client_messages_hook.invoke<void>(client, msg);
|
||||||
|
}
|
||||||
|
|
||||||
void script_errors_stub(const char* file, int line, unsigned int code, const char* fmt, ...)
|
void script_errors_stub(const char* file, int line, unsigned int code, const char* fmt, ...)
|
||||||
{
|
{
|
||||||
char buffer[0x1000];
|
char buffer[0x1000];
|
||||||
@ -39,6 +54,9 @@ namespace patches
|
|||||||
utils::hook::set<uint8_t>(game::select(0x14224DBB4, 0x1405312A8), 3);
|
utils::hook::set<uint8_t>(game::select(0x14224DBB4, 0x1405312A8), 3);
|
||||||
utils::hook::set<uint8_t>(game::select(0x14224DF8C, 0x1405316DC), 3);
|
utils::hook::set<uint8_t>(game::select(0x14224DF8C, 0x1405316DC), 3);
|
||||||
|
|
||||||
|
// make sure client's reliableAck are not negative
|
||||||
|
sv_execute_client_messages_hook.create(game::select(0x14224A460, 0x14052F840), sv_execute_client_messages_stub);
|
||||||
|
|
||||||
scheduler::once([]
|
scheduler::once([]
|
||||||
{
|
{
|
||||||
game::register_dvar_string("password", "", game::DVAR_USERINFO, "password");
|
game::register_dvar_string("password", "", game::DVAR_USERINFO, "password");
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
#include "game/game.hpp"
|
#include "game/game.hpp"
|
||||||
|
|
||||||
#include <utils/string.hpp>
|
#include <utils/string.hpp>
|
||||||
|
#include <utils/concurrency.hpp>
|
||||||
#include <utils/hook.hpp>
|
#include <utils/hook.hpp>
|
||||||
#include <utils/io.hpp>
|
|
||||||
|
|
||||||
#include "network.hpp"
|
#include "network.hpp"
|
||||||
#include "scheduler.hpp"
|
#include "scheduler.hpp"
|
||||||
@ -222,11 +222,6 @@ namespace server_list
|
|||||||
}, scheduler::async, 200ms);
|
}, scheduler::async, 200ms);
|
||||||
|
|
||||||
lua_serverinfo_to_table_hook.create(0x141F1FD10_g, lua_serverinfo_to_table_stub);
|
lua_serverinfo_to_table_hook.create(0x141F1FD10_g, lua_serverinfo_to_table_stub);
|
||||||
|
|
||||||
scheduler::once([]
|
|
||||||
{
|
|
||||||
read_favorite_servers();
|
|
||||||
}, scheduler::main);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void pre_destroy() override
|
void pre_destroy() override
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define PROTOCOL 3
|
#define PROTOCOL 4
|
||||||
|
#define SUB_PROTOCOL 1
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
namespace game
|
namespace game
|
||||||
@ -1583,15 +1584,23 @@ namespace game
|
|||||||
int client_state;
|
int client_state;
|
||||||
char __pad0[0x28];
|
char __pad0[0x28];
|
||||||
netadr_t address;
|
netadr_t address;
|
||||||
char __pad1[0x5588];
|
char __pad1[20468];
|
||||||
|
int reliableSequence;
|
||||||
|
int reliableAcknowledge;
|
||||||
|
char __pad2[4];
|
||||||
|
int messageAcknowledge;
|
||||||
|
char gap_5040[1416];
|
||||||
uint64_t xuid;
|
uint64_t xuid;
|
||||||
char __pad2[0xB5D84];
|
char __pad3[0xB5D84];
|
||||||
int guid;
|
int guid;
|
||||||
char __pad3[0x8];
|
char __pad4[0x8];
|
||||||
bool bIsTestClient;
|
bool bIsTestClient;
|
||||||
char __pad4[0x29DAC];
|
char __pad5[3];
|
||||||
|
int serverId;
|
||||||
|
char __pad6[171432];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
static_assert(sizeof(client_s) == 0xE5110);
|
static_assert(sizeof(client_s) == 0xE5110);
|
||||||
|
|
||||||
|
@ -78,6 +78,8 @@ namespace game
|
|||||||
// G
|
// G
|
||||||
WEAK symbol<void()> G_ClearVehicleInputs{0x1423812E0, 0x1405C1200};
|
WEAK symbol<void()> G_ClearVehicleInputs{0x1423812E0, 0x1405C1200};
|
||||||
|
|
||||||
|
WEAK symbol<qboolean(void* ent)> StuckInClient{0x1415A8360, 0x14023BFE0};
|
||||||
|
|
||||||
// Live
|
// Live
|
||||||
WEAK symbol<bool(uint64_t, int*, bool)> Live_GetConnectivityInformation{0x141E0C380};
|
WEAK symbol<bool(uint64_t, int*, bool)> Live_GetConnectivityInformation{0x141E0C380};
|
||||||
|
|
||||||
|
@ -176,6 +176,30 @@ namespace game
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static bool access_client(T* client_states, const size_t index, const std::function<void(client_s&)>& callback)
|
||||||
|
{
|
||||||
|
if (!client_states || !callback)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index >= get_max_client_count())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& client = client_states[index];
|
||||||
|
if (client.client_state <= 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(client);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void foreach_client(const std::function<void(client_s&, size_t index)>& callback)
|
void foreach_client(const std::function<void(client_s&, size_t index)>& callback)
|
||||||
{
|
{
|
||||||
if (is_server())
|
if (is_server())
|
||||||
@ -214,4 +238,14 @@ namespace game
|
|||||||
callback(client);
|
callback(client);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool access_connected_client(const size_t index, const std::function<void(client_s&)>& callback)
|
||||||
|
{
|
||||||
|
if (is_server())
|
||||||
|
{
|
||||||
|
return access_client(*svs_clients, index, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
return access_client(*svs_clients_cl, index, callback);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,4 +24,6 @@ namespace game
|
|||||||
|
|
||||||
void foreach_connected_client(const std::function<void(client_s&, size_t index)>& callback);
|
void foreach_connected_client(const std::function<void(client_s&, size_t index)>& callback);
|
||||||
void foreach_connected_client(const std::function<void(client_s&)>& callback);
|
void foreach_connected_client(const std::function<void(client_s&)>& callback);
|
||||||
|
|
||||||
|
bool access_connected_client(size_t index, const std::function<void(client_s&)>& callback);
|
||||||
}
|
}
|
||||||
|
@ -65,6 +65,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <array>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
@ -34,6 +34,8 @@ namespace steam
|
|||||||
gameserveritem_t create_server_item(const game::netadr_t& address, const ::utils::info_string& info,
|
gameserveritem_t create_server_item(const game::netadr_t& address, const ::utils::info_string& info,
|
||||||
const uint32_t ping, const bool success)
|
const uint32_t ping, const bool success)
|
||||||
{
|
{
|
||||||
|
const auto sub_protocol = atoi(info.get("sub_protocol").data());
|
||||||
|
|
||||||
gameserveritem_t server{};
|
gameserveritem_t server{};
|
||||||
server.m_NetAdr.m_usConnectionPort = address.port;
|
server.m_NetAdr.m_usConnectionPort = address.port;
|
||||||
server.m_NetAdr.m_usQueryPort = address.port;
|
server.m_NetAdr.m_usQueryPort = address.port;
|
||||||
@ -44,7 +46,7 @@ namespace steam
|
|||||||
::utils::string::copy(server.m_szGameDir, "");
|
::utils::string::copy(server.m_szGameDir, "");
|
||||||
::utils::string::copy(server.m_szMap, info.get("mapname").data());
|
::utils::string::copy(server.m_szMap, info.get("mapname").data());
|
||||||
::utils::string::copy(server.m_szGameDescription, info.get("description").data());
|
::utils::string::copy(server.m_szGameDescription, info.get("description").data());
|
||||||
server.m_nAppID = 311210;
|
server.m_nAppID = (sub_protocol == SUB_PROTOCOL || sub_protocol == (SUB_PROTOCOL - 1)) ? 311210 : 0;
|
||||||
server.m_nPlayers = atoi(info.get("clients").data());
|
server.m_nPlayers = atoi(info.get("clients").data());
|
||||||
server.m_nMaxPlayers = atoi(info.get("sv_maxclients").data());
|
server.m_nMaxPlayers = atoi(info.get("sv_maxclients").data());
|
||||||
server.m_nBotPlayers = atoi(info.get("bots").data());
|
server.m_nBotPlayers = atoi(info.get("bots").data());
|
||||||
@ -289,11 +291,10 @@ namespace steam
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto servers_list = hRequest == favorites_request ? &favorites_servers : &internet_servers;
|
auto& servers_list = hRequest == favorites_request ? favorites_servers : internet_servers;
|
||||||
|
|
||||||
static thread_local gameserveritem_t server_item{};
|
static thread_local gameserveritem_t server_item{};
|
||||||
return servers_list->access<gameserveritem_t*>([iServer](const servers& s) -> gameserveritem_t*
|
return servers_list.access<gameserveritem_t*>([iServer](const servers& s) -> gameserveritem_t* {
|
||||||
{
|
|
||||||
if (iServer < 0 || static_cast<size_t>(iServer) >= s.size())
|
if (iServer < 0 || static_cast<size_t>(iServer) >= s.size())
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -324,8 +325,8 @@ namespace steam
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto servers_list = hRequest == favorites_request ? &favorites_servers : &internet_servers;
|
auto& servers_list = hRequest == favorites_request ? favorites_servers : internet_servers;
|
||||||
return servers_list->access<int>([](const servers& s)
|
return servers_list.access<int>([](const servers& s)
|
||||||
{
|
{
|
||||||
return static_cast<int>(s.size());
|
return static_cast<int>(s.size());
|
||||||
});
|
});
|
||||||
@ -339,8 +340,8 @@ namespace steam
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::optional<game::netadr_t> address{};
|
std::optional<game::netadr_t> address{};
|
||||||
auto servers_list = hRequest == favorites_request ? &favorites_servers : &internet_servers;
|
auto& servers_list = hRequest == favorites_request ? favorites_servers : internet_servers;
|
||||||
servers_list->access([&](const servers& s)
|
servers_list.access([&](const servers& s)
|
||||||
{
|
{
|
||||||
if (iServer < 0 || static_cast<size_t>(iServer) >= s.size())
|
if (iServer < 0 || static_cast<size_t>(iServer) >= s.size())
|
||||||
{
|
{
|
||||||
|
@ -200,7 +200,11 @@ namespace updater
|
|||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!utils::flags::has_flag("norelaunch"))
|
||||||
|
{
|
||||||
utils::nt::relaunch_self();
|
utils::nt::relaunch_self();
|
||||||
|
}
|
||||||
|
|
||||||
throw update_cancelled();
|
throw update_cancelled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,7 +229,20 @@ namespace utils::cryptography
|
|||||||
|
|
||||||
if (ecc_export(buffer, &length, type, &this->key_storage_) == CRYPT_OK)
|
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 "";
|
return "";
|
||||||
|
@ -31,6 +31,8 @@ namespace utils::cryptography
|
|||||||
|
|
||||||
std::string serialize(int type = PK_PRIVATE) const;
|
std::string serialize(int type = PK_PRIVATE) const;
|
||||||
|
|
||||||
|
std::string get_openssl() const;
|
||||||
|
|
||||||
void free();
|
void free();
|
||||||
|
|
||||||
bool operator==(key& key) const;
|
bool operator==(key& key) const;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user