450 lines
18 KiB
Lua
450 lines
18 KiB
Lua
LUI.FlowManager.RegisterFenceGroup("MPMainMenu", {
|
|
"mp",
|
|
"mpInstall",
|
|
"onlineServices",
|
|
"onlineData",
|
|
"patch",
|
|
"exchange",
|
|
"playlists",
|
|
"dailyReward"
|
|
})
|
|
|
|
LUI.FlowManager.RequestSetStack("MPMainMenu", {
|
|
{ name = "MainLockoutMenu" },
|
|
{ name = "MainMenu" }
|
|
})
|
|
|
|
local HandleSplitscreenRefresh = function ()
|
|
if Engine.SplitscreenPlayerCount() > 0 then
|
|
local activeController = Engine.GetFirstActiveController()
|
|
if activeController and Engine.IsUserSignedIn(activeController) then
|
|
Engine.PLMRefreshData()
|
|
end
|
|
end
|
|
end
|
|
|
|
local HandleBackButton = function(f2_arg0, f2_arg1)
|
|
local f2_local0 = Engine.HasActiveLocalClient( f2_arg1.controller )
|
|
if f2_local0 then
|
|
f2_local0 = not Engine.IsActiveLocalClientPrimary( f2_arg1.controller )
|
|
end
|
|
if f2_local0 then
|
|
local f2_local1 = LUI.FlowManager.GetScopedData( f2_arg0 )
|
|
if f2_local1 and f2_local1.focusedPage and f2_local1.focusedPage > 2 then
|
|
f2_arg0:dispatchEventToRoot( {
|
|
name = "lobby_slide_left",
|
|
immediate = true
|
|
} )
|
|
end
|
|
elseif Lobby.IsNotAloneInPrivateParty() then
|
|
if Engine.IsXB3() then
|
|
LUI.FlowManager.RequestPopupMenu( f2_arg0, "RateLimitedLeaveCommonMPMainMenuPopup", true, f2_arg1.controller, false, {
|
|
menu = f2_arg0,
|
|
rateLimitIntervalMS = 5000,
|
|
rateLimitAttempts = 3
|
|
} )
|
|
else
|
|
LUI.FlowManager.RequestPopupMenu( f2_arg0, "LeaveCommonMPMainMenuPopup", true, f2_arg1.controller, false, {
|
|
menu = f2_arg0
|
|
} )
|
|
end
|
|
else
|
|
Lobby.LeaveCommonMPMainMenu( f2_arg0, f2_arg1.controller )
|
|
end
|
|
return true
|
|
end
|
|
|
|
local InitializeMainMenu = function(arg0, arg1)
|
|
local activeController = Engine.GetFirstActiveController()
|
|
if Engine.GetDvarBool("xblive_competitionmatch") then
|
|
Engine.SetDvarBool("xblive_competitionmatch", false)
|
|
Engine.Exec("set remove_mlg_rules 1")
|
|
end
|
|
Engine.ExecNow(MPConfig.default_xboxlive, activeController)
|
|
end
|
|
|
|
local UpdatePlayerData = function(arg0)
|
|
local postShipFlag = Engine.GetPlayerDataEx(arg0, CoD.StatsGroup.Ranked, "postShipFlags", 3)
|
|
if postShipFlag == nil or postShipFlag == false then
|
|
local archetypePreferences = {
|
|
{ "head", 1, "head_160", "head_287" },
|
|
{ "head", 3, "head_167", "head_294" },
|
|
{ "body", 1, "body_90", "body_217" },
|
|
{ "body", 3, "body_97", "body_224" }
|
|
}
|
|
|
|
for _, pref in ipairs(archetypePreferences) do
|
|
local currentValue = Engine.GetPlayerDataEx(arg0, CoD.StatsGroup.RankedLoadouts, "squadMembers", "archetypePreferences", pref[2], pref[1])
|
|
if currentValue ~= nil and currentValue == pref[3] then
|
|
Engine.SetPlayerDataEx(arg0, CoD.StatsGroup.RankedLoadouts, "squadMembers", "archetypePreferences", pref[2], pref[1], pref[4])
|
|
end
|
|
end
|
|
|
|
local headData = Engine.GetPlayerDataEx(arg0, CoD.StatsGroup.RankedLoadouts, "squadMembers", "head")
|
|
local bodyData = Engine.GetPlayerDataEx(arg0, CoD.StatsGroup.RankedLoadouts, "squadMembers", "body")
|
|
|
|
if headData ~= nil and (headData == 160 or headData == 167) then
|
|
Engine.SetPlayerDataEx(arg0, CoD.StatsGroup.RankedLoadouts, "squadMembers", "head", headData == 160 and 287 or 294)
|
|
end
|
|
if bodyData ~= nil and (bodyData == 90 or bodyData == 97) then
|
|
Engine.SetPlayerDataEx(arg0, CoD.StatsGroup.RankedLoadouts, "squadMembers", "body", bodyData == 90 and 217 or 224)
|
|
end
|
|
|
|
-- Same operation for private loadouts
|
|
for _, pref in ipairs(archetypePreferences) do
|
|
local currentValue = Engine.GetPlayerDataEx(arg0, CoD.StatsGroup.PrivateLoadouts, "squadMembers", "archetypePreferences", pref[2], pref[1])
|
|
if currentValue ~= nil and currentValue == pref[3] then
|
|
Engine.SetPlayerDataEx(arg0, CoD.StatsGroup.PrivateLoadouts, "squadMembers", "archetypePreferences", pref[2], pref[1], pref[4])
|
|
end
|
|
end
|
|
|
|
local privateHeadData = Engine.GetPlayerDataEx(arg0, CoD.StatsGroup.PrivateLoadouts, "squadMembers", "head")
|
|
local privateBodyData = Engine.GetPlayerDataEx(arg0, CoD.StatsGroup.PrivateLoadouts, "squadMembers", "body")
|
|
|
|
if privateHeadData ~= nil and (privateHeadData == 160 or privateHeadData == 167) then
|
|
Engine.SetPlayerDataEx(arg0, CoD.StatsGroup.PrivateLoadouts, "squadMembers", "head", privateHeadData == 160 and 287 or 294)
|
|
end
|
|
if privateBodyData ~= nil and (privateBodyData == 90 or privateBodyData == 97) then
|
|
Engine.SetPlayerDataEx(arg0, CoD.StatsGroup.PrivateLoadouts, "squadMembers", "body", privateBodyData == 90 and 217 or 224)
|
|
end
|
|
|
|
local characterHead = Engine.GetPlayerDataEx(arg0, CoD.StatsGroup.RankedLoadouts, "squadMembers", "head")
|
|
local characterBody = Engine.GetPlayerDataEx(arg0, CoD.StatsGroup.RankedLoadouts, "squadMembers", "body")
|
|
local characterSuper = Engine.GetPlayerDataEx(arg0, CoD.StatsGroup.RankedLoadouts, "squadMembers", "archetypeSuper")
|
|
local characterArchetype = Engine.GetPlayerDataEx(arg0, CoD.StatsGroup.RankedLoadouts, "squadMembers", "archetype")
|
|
|
|
if characterHead ~= nil and characterBody ~= nil then
|
|
FrontEndScene.SetCharacterModelsByIndex(FrontEndScene.ClientCharacters.Self, characterBody, characterHead)
|
|
end
|
|
|
|
if characterSuper ~= nil and characterArchetype ~= nil then
|
|
FrontEndScene.SetWeaponForSuper(FrontEndScene.ClientCharacters.Self, characterSuper, characterArchetype)
|
|
FrontEndScene.PlayIdleForSuper(FrontEndScene.ClientCharacters.Self, characterSuper, characterArchetype)
|
|
end
|
|
|
|
Engine.SetPlayerDataEx(arg0, CoD.StatsGroup.Ranked, "postShipFlags", 3, true)
|
|
Engine.ExecNow("uploadstats", arg0)
|
|
end
|
|
end
|
|
|
|
local LoadMainMenu = function(controller)
|
|
UpdatePlayerData(controller)
|
|
end
|
|
|
|
-- Function to set up the main menu for multiplayer
|
|
local SetupMainMenu = function(menu, controller)
|
|
-- Disable UI version display and online requirement
|
|
Engine.SetDvarString("ui_version_show", "0")
|
|
Engine.SetDvarBool("ui_onlineRequired", false)
|
|
|
|
-- Set up front end scene
|
|
FrontEndScene.CurrentMissionTeam = MissionDirector.InvalidTeamID
|
|
FrontEndScene.SetScene("mp_main")
|
|
|
|
-- Get controller index
|
|
local controllerIndex = controller and controller.controller or Engine.GetFirstActiveController()
|
|
|
|
-- Check title update requirement
|
|
CheckTURequirement(menu, controllerIndex)
|
|
|
|
-- Set up player character based on loadout data
|
|
local loadoutData = DataSources.alwaysLoaded.playerData.MP.rankedloadouts.squadMembers
|
|
local rigAnim = Cac.GetRigFrontEndProfileAnim(loadoutData.archetype:GetValue(controllerIndex))
|
|
FrontEndScene.SetCharacterModelsByIndex(
|
|
FrontEndScene.ClientCharacters.Profile,
|
|
loadoutData.body:GetValue(controllerIndex),
|
|
loadoutData.head:GetValue(controllerIndex)
|
|
)
|
|
ClientCharacter.SetCharacterWeapons(FrontEndScene.ClientCharacters.Profile, nil)
|
|
ClientCharacter.PlayCharacterAnim(FrontEndScene.ClientCharacters.Profile, rigAnim)
|
|
ClientCharacter.SetCharacterVisible(FrontEndScene.ClientCharacters.Profile, true)
|
|
|
|
-- Set up weapon visibility
|
|
ClientWeapon.SetWeaponIsViewModel(0, true)
|
|
ClientWeapon.SetWeaponVisible(0, false)
|
|
|
|
-- Initialize main menu
|
|
InitializeMainMenu(menu, controller)
|
|
|
|
-- Sync unlocks if enabled
|
|
if Engine.GetDvarBool("enable_unlock_sync") then
|
|
local unlockTypes = {}
|
|
for _, unlockType in pairs(AAR.UnlockTypes) do
|
|
table.insert(unlockTypes, unlockType)
|
|
end
|
|
Rewards.SyncUnlocks(controllerIndex, unlockTypes, #unlockTypes)
|
|
end
|
|
|
|
-- Start private party if not already in one
|
|
if not Lobby.IsInPrivateParty() then
|
|
Engine.ExecNow("xstartprivateparty", controllerIndex)
|
|
end
|
|
|
|
-- Handle events related to party and CRM (Customer Relationship Management)
|
|
menu:registerEventHandler("not_below_blocking_fence", function()
|
|
Engine.SetDvarBool("cg_mlg_gamebattles_match", false)
|
|
if not MLG.IsGameBattleMatch() then
|
|
Lobby.WakePrivateParty(controllerIndex)
|
|
end
|
|
end)
|
|
|
|
-- Set up party UI and CRM
|
|
Lobby.SetPartyUIRoot(PartyUIRoot.MAIN_MENU)
|
|
menu.nextLocation = CRM.locations.MP_MOTD
|
|
CRM.OpenNextCRMWindow(menu)
|
|
menu:addEventHandler("gain_focus", CRM.OpenNextCRMWindow)
|
|
menu:addEventHandler("restore_focus", CRM.OpenNextCRMWindow)
|
|
end
|
|
|
|
-- Post-load function to handle game battles and other settings
|
|
local PostLoadFunc = function(menu, controllerIndex, controller)
|
|
if GAMEBATTLES.ScheduleRefreshRequest then
|
|
GAMEBATTLES.ScheduleRefreshRequest = false
|
|
OpenGameBattlesLobby(controllerIndex)
|
|
else
|
|
local currentMatch = GAMEBATTLES.GetCurrentMatch(controllerIndex)
|
|
if currentMatch then
|
|
if GAMEBATTLES.MatchForfeitWinningTeamIndex ~= 0 then
|
|
GAMEBATTLES.ShowMatchForfeitPopup(controllerIndex, currentMatch, GAMEBATTLES.MatchForfeitWinningTeamIndex)
|
|
GAMEBATTLES.MatchForfeitWinningTeamIndex = 0
|
|
else
|
|
local victoryInfo, progressInfo = GAMEBATTLES.GetMatchProgressInfo(currentMatch)
|
|
if progressInfo then
|
|
local alliesWins, axisWins, matchVictory = GAMEBATTLES.GetMatchVictoryInfo(currentMatch)
|
|
if not matchVictory then
|
|
LUI.FlowManager.RequestPopupMenu(menu, "MLGGamebattlesMatchResultsPopup", false, controllerIndex, false, {
|
|
controllerIndex = controllerIndex,
|
|
gbMatch = currentMatch,
|
|
alliesWins = alliesWins,
|
|
axisWins = axisWins
|
|
})
|
|
end
|
|
else
|
|
local dsAcquisitionState = MLG.GetGameBattleDSAcquisitionState(controllerIndex)
|
|
if dsAcquisitionState == GAMEBATTLES.MLG_DS_ACQUISITION_STATE.COULD_NOT_ACQUIRE or dsAcquisitionState == GAMEBATTLES.MLG_DS_ACQUISITION_STATE.ACQUISITION_ERROR then
|
|
MLG.ResetGameBattleDSAcquisitionState()
|
|
LUI.FlowManager.RequestPopupMenu(menu, "MLGGamebattlesMatchCancelledPopup", false, controllerIndex, false, {
|
|
matchID = currentMatch.matchId
|
|
})
|
|
end
|
|
end
|
|
end
|
|
MLG.ResetGameBattleMatchId(controllerIndex)
|
|
end
|
|
end
|
|
|
|
-- Additional setup and event handling
|
|
assert(menu.bindButton)
|
|
menu.isSignInMenu = true
|
|
menu.bindButton:addEventHandler("button_secondary", HandleBackButton)
|
|
menu:addEventHandler("menu_create", SetupMainMenu)
|
|
|
|
-- Adjust UI elements based on various conditions
|
|
local adjustButtonDescription = function()
|
|
local _, top, _, bottom = menu.ButtonDescription:getLocalRect()
|
|
local buttonSpacing = menu.MPMainMenuButtons.buttonSpacing
|
|
menu.ButtonDescription:SetTop(top - buttonSpacing)
|
|
menu.ButtonDescription:SetBottom(bottom - buttonSpacing)
|
|
end
|
|
|
|
if not CONDITIONS.IsGameBattlesAllowed() then
|
|
adjustButtonDescription()
|
|
end
|
|
|
|
if not CODTV.IsCODTVEnabled() then
|
|
adjustButtonDescription()
|
|
end
|
|
|
|
if not CONDITIONS.IsStoreAllowed(menu) then
|
|
adjustButtonDescription()
|
|
end
|
|
|
|
if Engine.GetDvarFloat("r_filmGrainAtten") == 1 then
|
|
Engine.SetDvarFloat("r_filmGrainAtten", 0.25)
|
|
Engine.ExecNow("profile_setFilmGrain " .. tostring(0.25), controllerIndex)
|
|
end
|
|
|
|
-- Handle NAT type warning
|
|
local natType = Lobby.GetNATType()
|
|
if natType then
|
|
if natType == "NETWORK_STRICT" and not Engine.GetDvarBool("strict_nat_warning_viewed") then
|
|
LUI.FlowManager.RequestPopupMenu(menu, "strict_nat_warning", true, controllerIndex, false, data)
|
|
Engine.SetDvarBool("strict_nat_warning_viewed", true)
|
|
end
|
|
menu:processEvent({
|
|
name = "add_button_helper_text",
|
|
button_ref = "nat",
|
|
helper_text = Engine.Localize("NETWORK_YOURNATTYPE", natType),
|
|
side = "right",
|
|
clickable = false
|
|
})
|
|
end
|
|
|
|
Engine.SetDvarInt("lui_mc_numGamesFinishedInLobby", 0)
|
|
MissionDirector.PlayTeamMusic()
|
|
Engine.StopMenuVideo()
|
|
|
|
-- Handle trial license popup
|
|
local scopedData = LUI.FlowManager.GetScopedData(menu)
|
|
if CONDITIONS.IsTrialLicense() and not scopedData.trialPopupShown then
|
|
scopedData.trialPopupShown = true
|
|
LUI.FlowManager.RequestPopupMenu(menu, "TrialFullWindow", true, controllerIndex, false)
|
|
end
|
|
|
|
menu:addElement(Lobby.GetMPMapMaterialStreamer())
|
|
LoadMainMenu(controllerIndex)
|
|
end
|
|
|
|
function MPMainMenu(menu, controller)
|
|
local self = LUI.UIHorizontalNavigator.new()
|
|
self.id = "MPMainMenu"
|
|
|
|
-- Determine controller index
|
|
local controllerIndex = controller and controller.controllerIndex
|
|
if not controllerIndex and not Engine.InFrontend() then
|
|
controllerIndex = self:getRootController()
|
|
end
|
|
assert(controllerIndex)
|
|
|
|
-- Initialize the main menu
|
|
InitializeMainMenu(self, controllerIndex, controller)
|
|
self:playSound("menu_open")
|
|
|
|
-- Helper bar
|
|
local HelperBar = MenuBuilder.BuildRegisteredType("ButtonHelperBar", {
|
|
controllerIndex = controllerIndex
|
|
})
|
|
HelperBar.id = "HelperBar"
|
|
HelperBar:SetAnchorsAndPosition(0, 0, 1, 0, 0, 0, _1080p * -85, 0)
|
|
self:addElement(HelperBar)
|
|
self.HelperBar = HelperBar
|
|
|
|
-- Button description
|
|
local ButtonDescription = MenuBuilder.BuildRegisteredType("ButtonDescriptionText", {
|
|
controllerIndex = controllerIndex
|
|
})
|
|
ButtonDescription.id = "ButtonDescription"
|
|
ButtonDescription.Description:SetRight(_1080p * 415, 0)
|
|
ButtonDescription:SetAnchorsAndPosition(0, 1, 0, 1, _1080p * 130, _1080p * 645, _1080p * 594, _1080p * 694)
|
|
self:addElement(ButtonDescription)
|
|
self.ButtonDescription = ButtonDescription
|
|
|
|
-- Social feed
|
|
local SocialFeed = MenuBuilder.BuildRegisteredType("SocialFeed", {
|
|
controllerIndex = controllerIndex
|
|
})
|
|
SocialFeed.id = "SocialFeed"
|
|
SocialFeed:SetAnchorsAndPosition(0, 1, 0, 1, 0, _1080p * 1920, _1080p * 965, _1080p * 995)
|
|
self:addElement(SocialFeed)
|
|
self.SocialFeed = SocialFeed
|
|
|
|
-- Main menu buttons
|
|
local MPMainMenuButtons = MenuBuilder.BuildRegisteredType("MPMainMenuButtons", {
|
|
controllerIndex = controllerIndex
|
|
})
|
|
MPMainMenuButtons.id = "MPMainMenuButtons"
|
|
MPMainMenuButtons:SetAnchorsAndPosition(0, 1, 0, 1, _1080p * 130, _1080p * 630, _1080p * 360, _1080p * 564)
|
|
self:addElement(MPMainMenuButtons)
|
|
self.MPMainMenuButtons = MPMainMenuButtons
|
|
|
|
-- Friends widget
|
|
local FriendsElement = MenuBuilder.BuildRegisteredType("online_friends_widget", {
|
|
controllerIndex = controllerIndex
|
|
})
|
|
FriendsElement.id = "FriendsElement"
|
|
FriendsElement:SetFont(FONTS.GetFont(FONTS.Dev.File))
|
|
FriendsElement:SetAlignment(LUI.Alignment.Left)
|
|
FriendsElement:SetAnchorsAndPosition(0, 1, 0, 1, _1080p * 1420, _1080p * 1920, _1080p * 1026, _1080p * 1071)
|
|
self:addElement(FriendsElement)
|
|
self.FriendsElement = FriendsElement
|
|
|
|
-- Lobby members list
|
|
local LobbyMembers = MenuBuilder.BuildRegisteredType("LobbyMembers", {
|
|
controllerIndex = controllerIndex
|
|
})
|
|
LobbyMembers.id = "LobbyMembers"
|
|
LobbyMembers:SetAnchorsAndPosition(1, 0, 0, 1, _1080p * -700, 0, _1080p * 273, _1080p * 917)
|
|
self:addElement(LobbyMembers)
|
|
self.LobbyMembers = LobbyMembers
|
|
|
|
-- COD logo
|
|
local CODLogo = LUI.UIImage.new()
|
|
CODLogo.id = "CODLogo"
|
|
CODLogo:setImage(RegisterMaterial("cod_logo"), 0)
|
|
CODLogo:SetAnchorsAndPosition(0, 0, 0, 0, _1080p * 108, _1080p * -1272, _1080p * 120, _1080p * -825)
|
|
self:addElement(CODLogo)
|
|
self.CODLogo = CODLogo
|
|
|
|
-- Menu title
|
|
local MenuTitle = LUI.UIStyledText.new()
|
|
MenuTitle.id = "MenuTitle"
|
|
MenuTitle:setText(ToUpperCase(Engine.Localize("MENU_MULTIPLAYER")), 0)
|
|
MenuTitle:SetFontSize(50 * _1080p)
|
|
MenuTitle:SetFont(FONTS.GetFont(FONTS.MainMedium.File))
|
|
MenuTitle:SetAlignment(LUI.Alignment.Left)
|
|
MenuTitle:SetStartupDelay(1250)
|
|
MenuTitle:SetLineHoldTime(400)
|
|
MenuTitle:SetAnimMoveTime(300)
|
|
MenuTitle:SetEndDelay(1000)
|
|
MenuTitle:SetCrossfadeTime(500)
|
|
MenuTitle:SetAutoScrollStyle(LUI.UIStyledText.AutoScrollStyle.ScrollH)
|
|
MenuTitle:SetMaxVisibleLines(1)
|
|
MenuTitle:SetDecodeLetterLength(25)
|
|
MenuTitle:SetDecodeMaxRandChars(3)
|
|
MenuTitle:SetDecodeUpdatesPerLetter(4)
|
|
MenuTitle:SetAnchorsAndPosition(0, 1, 0, 1, _1080p * 130, _1080p * 660, _1080p * 296.5, _1080p * 346.5)
|
|
self:addElement(MenuTitle)
|
|
self.MenuTitle = MenuTitle
|
|
|
|
-- Double XP notifications
|
|
local DoubleXPNotifications = MenuBuilder.BuildRegisteredType("DoubleXPNotifications", {
|
|
controllerIndex = controllerIndex
|
|
})
|
|
DoubleXPNotifications.id = "DoubleXPNotifications"
|
|
DoubleXPNotifications:SetScale(-0.5, 0)
|
|
DoubleXPNotifications:SetAnchorsAndPosition(0.5, 0.5, 0, 1, _1080p * -370, _1080p * -114, _1080p * 104, _1080p * 232)
|
|
self:addElement(DoubleXPNotifications)
|
|
self.DoubleXPNotifications = DoubleXPNotifications
|
|
|
|
-- Button helper function
|
|
self.addButtonHelperFunction = function(arg0, arg1)
|
|
arg0:AddButtonHelperText({
|
|
helper_text = Engine.Localize("LUA_MENU_SELECT"),
|
|
button_ref = "button_primary",
|
|
side = "left",
|
|
clickable = true
|
|
})
|
|
arg0:AddButtonHelperText({
|
|
helper_text = Engine.Localize("MENU_BACK"),
|
|
button_ref = "button_secondary",
|
|
side = "left",
|
|
priority = 1,
|
|
clickable = true
|
|
})
|
|
arg0:AddButtonHelperText({
|
|
helper_text = Engine.Localize("LUA_MENU_OPTIONS_CAPS"),
|
|
button_ref = "button_start",
|
|
side = "left",
|
|
priority = 4,
|
|
clickable = true
|
|
})
|
|
end
|
|
|
|
self:addEventHandler("menu_create", self.addButtonHelperFunction)
|
|
|
|
-- Bind button handler
|
|
local bindButton = LUI.UIBindButton.new()
|
|
bindButton.id = "selfBindButton"
|
|
self:addElement(bindButton)
|
|
self.bindButton = bindButton
|
|
|
|
self.bindButton:addEventHandler("button_start", function(arg0, arg1)
|
|
ACTIONS.OpenMenu("OptionsMenu", true, arg1.controller or controllerIndex)
|
|
end)
|
|
|
|
PostLoadFunc(self, controllerIndex, controller)
|
|
return self
|
|
end
|
|
|
|
MenuBuilder.m_types["MPMainMenu"] = MPMainMenu
|
|
LUI.FlowManager.RegisterStackPushBehaviour( "MPMainMenu", PushFunc ) |