feat: fastdl, mod menus (#291)
* fastdl init * ui_scripting fixes * fastfile loading changes * delete test ui script * add mod select button * Create iw7mod_code_post_gfx.ff * fastdl progress * fix download * remove debug print
This commit is contained in:
parent
131196cd7a
commit
7835bb0477
@ -1,188 +1,4 @@
|
||||
local f0_local0 = function ( f1_arg0, f1_arg1 )
|
||||
Engine.Exec( "xblive_privatematch 0" )
|
||||
utils.cp.AliensUtils.AliensRunConfig( f1_arg1.controller )
|
||||
LUI.FlowManager.RequestAddMenu( "SystemLinkMenu", false, f1_arg1.controller, false, {}, true )
|
||||
end
|
||||
|
||||
local f0_local1 = function ( f2_arg0, f2_arg1 )
|
||||
f0_local0( f2_arg0, f2_arg1 )
|
||||
end
|
||||
|
||||
local f0_local2 = function ( f3_arg0, f3_arg1 )
|
||||
Engine.Exec( MPConfig.default_xboxlive, f3_arg1.controller )
|
||||
Engine.SetDvarBool( "xblive_privatematch", true )
|
||||
SetIsAliensSolo( true )
|
||||
Engine.SetDvarInt( "party_maxplayers", 1 )
|
||||
Engine.Exec( "xstartprivatematch" )
|
||||
LUI.FlowManager.RequestAddMenu( "CPPrivateMatchMenu", false, f3_arg1.controller, false, {
|
||||
showPlayNowButton = true,
|
||||
isPublicMatch = false
|
||||
} )
|
||||
end
|
||||
|
||||
local f0_local3 = function ( f4_arg0, f4_arg1 )
|
||||
Engine.Exec( MPConfig.default_xboxlive, f4_arg1.controller )
|
||||
Engine.SetDvarBool( "xblive_privatematch", true )
|
||||
SetIsAliensSolo( false )
|
||||
Engine.Exec( "xstartprivatematch" )
|
||||
LUI.FlowManager.RequestAddMenu( "CPPrivateMatchMenu", false, f4_arg1.controller, false, {
|
||||
showPlayNowButton = true,
|
||||
isPublicMatch = false
|
||||
} )
|
||||
end
|
||||
|
||||
local f0_local4 = function ( f5_arg0, f5_arg1, f5_arg2 )
|
||||
assert( f5_arg0.PublicMatch )
|
||||
assert( f5_arg0.SoloMatch )
|
||||
assert( f5_arg0.CustomMatch )
|
||||
local f5_local0 = LUI.DataSourceInGlobalModel.new( "frontEnd.lobby.areWeGameHost" )
|
||||
local f5_local1 = DataSources.frontEnd.lobby.memberCount
|
||||
local f5_local2 = function ()
|
||||
return Lobby.IsInPrivateParty() and not Lobby.IsPrivatePartyHost()
|
||||
end
|
||||
|
||||
local f5_local3 = function ()
|
||||
local f7_local0 = f5_local2()
|
||||
f5_arg0.PublicMatch:SetButtonDisabled( f7_local0 )
|
||||
f5_arg0.CustomMatch:SetButtonDisabled( f7_local0 )
|
||||
end
|
||||
|
||||
f5_arg0:SubscribeToModel( f5_local0:GetModel( f5_arg1 ), f5_local3 )
|
||||
f5_arg0:SubscribeToModel( f5_local1:GetModel( f5_arg1 ), f5_local3 )
|
||||
f5_arg0:SubscribeToModel( DataSources.frontEnd.lobby.isSolo:GetModel( f5_arg1 ), function ()
|
||||
local f8_local0 = DataSources.frontEnd.lobby.isSolo:GetValue( f5_arg1 )
|
||||
if f8_local0 ~= nil then
|
||||
f5_arg0.SoloMatch:SetButtonDisabled( not f8_local0 )
|
||||
end
|
||||
end )
|
||||
f5_arg0.PublicMatch:addEventHandler( "button_action", f0_local1 )
|
||||
f5_arg0.SoloMatch:addEventHandler( "button_action", f0_local2 )
|
||||
f5_arg0.Loadout:addEventHandler( "button_action", function ( f9_arg0, f9_arg1 )
|
||||
LUI.FlowManager.RequestAddMenu( "CPLoadoutMenu", true, f9_arg1.controller )
|
||||
end )
|
||||
f5_arg0.Barracks:addEventHandler( "button_action", function ( f10_arg0, f10_arg1 )
|
||||
LUI.FlowManager.RequestAddMenu( "Headquarters", true, f10_arg1.controller )
|
||||
end )
|
||||
f5_arg0.Armory:addEventHandler( "button_action", function ( f11_arg0, f11_arg1 )
|
||||
if not Engine.IsUserAGuest( f11_arg1.controller ) then
|
||||
ACTIONS.OpenMenu( "Armory", true, f11_arg1.controller )
|
||||
end
|
||||
end )
|
||||
f5_arg0.CustomMatch:addEventHandler( "button_action", f0_local3 )
|
||||
f5_arg0.ContractsButton:addEventHandler( "button_action", function ( f12_arg0, f12_arg1 )
|
||||
ACTIONS.OpenMenu( "ContractMenu", true, f12_arg1.controller or f5_arg1 )
|
||||
end )
|
||||
end
|
||||
|
||||
function CPMainMenuButtons( menu, controller )
|
||||
local VNavigator = LUI.UIVerticalNavigator.new()
|
||||
VNavigator:SetAnchorsAndPosition( 0, 1, 0, 1, 0, 500 * _1080p, 0, 400 * _1080p )
|
||||
VNavigator.id = "CPMainMenuButtons"
|
||||
local f14_local1 = controller and controller.controllerIndex
|
||||
if not f14_local1 and not Engine.InFrontend() then
|
||||
f14_local1 = VNavigator:getRootController()
|
||||
end
|
||||
assert( f14_local1 )
|
||||
local f14_local2 = VNavigator
|
||||
local ButtonDescription = nil
|
||||
|
||||
ButtonDescription = MenuBuilder.BuildRegisteredType( "ButtonDescriptionText", {
|
||||
controllerIndex = f14_local1
|
||||
} )
|
||||
ButtonDescription.id = "ButtonDescription"
|
||||
ButtonDescription:SetRGBFromTable( SWATCHES.genericButton.textDisabled, 0 )
|
||||
ButtonDescription.Description:SetRight( _1080p * 415, 0 )
|
||||
ButtonDescription:SetAnchorsAndPosition( 0, 0, 0, 1, 0, 0, _1080p * 336, _1080p * 394 )
|
||||
VNavigator:addElement( ButtonDescription )
|
||||
VNavigator.ButtonDescription = ButtonDescription
|
||||
|
||||
local PublicMatch = nil
|
||||
|
||||
PublicMatch = MenuBuilder.BuildRegisteredType( "MenuButton", {
|
||||
controllerIndex = f14_local1
|
||||
} )
|
||||
PublicMatch.id = "PublicMatch"
|
||||
PublicMatch.buttonDescription = "Browse for Custom Servers"
|
||||
PublicMatch.Text:setText( ToUpperCase( "Server Browser" ), 0 )
|
||||
PublicMatch:SetAnchorsAndPosition( 0, 1, 0, 1, 0, _1080p * 340, 0, _1080p * 30 )
|
||||
VNavigator:addElement( PublicMatch )
|
||||
VNavigator.PublicMatch = PublicMatch
|
||||
|
||||
local SoloMatch = nil
|
||||
|
||||
SoloMatch = MenuBuilder.BuildRegisteredType( "MenuButton", {
|
||||
controllerIndex = f14_local1
|
||||
} )
|
||||
SoloMatch.id = "SoloMatch"
|
||||
SoloMatch.buttonDescription = Engine.Localize( "LUA_MENU_ZM_SOLO_MATCH_DESC" )
|
||||
SoloMatch.Text:setText( ToUpperCase( Engine.Localize( "LUA_MENU_SOLO_MATCH_CAPS" ) ), 0 )
|
||||
SoloMatch:SetAnchorsAndPosition( 0, 1, 0, 1, 0, _1080p * 340, _1080p * 40, _1080p * 70 )
|
||||
VNavigator:addElement( SoloMatch )
|
||||
VNavigator.SoloMatch = SoloMatch
|
||||
|
||||
local CustomMatch = nil
|
||||
|
||||
CustomMatch = MenuBuilder.BuildRegisteredType( "MenuButton", {
|
||||
controllerIndex = f14_local1
|
||||
} )
|
||||
CustomMatch.id = "CustomMatch"
|
||||
CustomMatch.buttonDescription = Engine.Localize( "LUA_MENU_ZM_CUSTOM_MATCH_DESC" )
|
||||
CustomMatch.Text:setText( ToUpperCase( Engine.Localize( "LUA_MENU_CUSTOM_GAME_CAPS" ) ), 0 )
|
||||
CustomMatch:SetAnchorsAndPosition( 0, 1, 0, 1, 0, _1080p * 340, _1080p * 80, _1080p * 110 )
|
||||
VNavigator:addElement( CustomMatch )
|
||||
VNavigator.CustomMatch = CustomMatch
|
||||
|
||||
local Loadout = nil
|
||||
|
||||
Loadout = MenuBuilder.BuildRegisteredType( "MenuButton", {
|
||||
controllerIndex = f14_local1
|
||||
} )
|
||||
Loadout.id = "Loadout"
|
||||
Loadout.buttonDescription = Engine.Localize( "LUA_MENU_ZM_LOADOUT_DESC" )
|
||||
Loadout.Text:setText( Engine.Localize( "LUA_MENU_ZM_LOADOUT_CAPS" ), 0 )
|
||||
Loadout:SetAnchorsAndPosition( 0, 1, 0, 1, 0, _1080p * 340, _1080p * 120, _1080p * 150 )
|
||||
VNavigator:addElement( Loadout )
|
||||
VNavigator.Loadout = Loadout
|
||||
|
||||
local Barracks = nil
|
||||
|
||||
Barracks = MenuBuilder.BuildRegisteredType( "MenuButton", {
|
||||
controllerIndex = f14_local1
|
||||
} )
|
||||
Barracks.id = "Barracks"
|
||||
Barracks.buttonDescription = Engine.Localize( "LUA_MENU_ZM_BARRACKS_DESC" )
|
||||
Barracks.Text:setText( ToUpperCase( Engine.Localize( "LUA_MENU_ZM_BARRACKS_CAPS" ) ), 0 )
|
||||
Barracks:SetAnchorsAndPosition( 0, 1, 0, 1, 0, _1080p * 340, _1080p * 160, _1080p * 190 )
|
||||
VNavigator:addElement( Barracks )
|
||||
VNavigator.Barracks = Barracks
|
||||
|
||||
local Armory = nil
|
||||
|
||||
Armory = MenuBuilder.BuildRegisteredType( "MenuButton", {
|
||||
controllerIndex = f14_local1
|
||||
} )
|
||||
Armory.id = "Armory"
|
||||
Armory.buttonDescription = Engine.Localize( "LUA_MENU_ZM_SURVIVAL_DEPOT_DESC" )
|
||||
Armory.Text:setText( ToUpperCase( Engine.Localize( "LUA_MENU_ZM_SURVIVAL_DEPOT" ) ), 0 )
|
||||
Armory:SetAnchorsAndPosition( 0, 1, 0, 1, 0, _1080p * 340, _1080p * 200, _1080p * 230 )
|
||||
VNavigator:addElement( Armory )
|
||||
VNavigator.Armory = Armory
|
||||
|
||||
local ContractsButton = nil
|
||||
|
||||
ContractsButton = MenuBuilder.BuildRegisteredType( "ContractsButtonCP", {
|
||||
controllerIndex = f14_local1
|
||||
} )
|
||||
ContractsButton.id = "ContractsButton"
|
||||
ContractsButton:SetAnchorsAndPosition( 0, 1, 0, 1, 0, _1080p * 340, _1080p * 240, _1080p * 300 )
|
||||
VNavigator:addElement( ContractsButton )
|
||||
VNavigator.ContractsButton = ContractsButton
|
||||
|
||||
f0_local4( VNavigator, f14_local1, controller )
|
||||
return VNavigator
|
||||
end
|
||||
|
||||
CPMainMenu_original = MenuBuilder.m_types["CPMainMenu"]
|
||||
local CPMainMenu_original = MenuBuilder.m_types["CPMainMenu"]
|
||||
function CPMainMenuStub( menu, controller )
|
||||
ret = CPMainMenu_original( menu, controller )
|
||||
|
||||
@ -193,5 +9,3 @@ function CPMainMenuStub( menu, controller )
|
||||
end
|
||||
|
||||
MenuBuilder.m_types["CPMainMenu"] = CPMainMenuStub
|
||||
|
||||
MenuBuilder.m_types["CPMainMenuButtons"] = CPMainMenuButtons
|
201
data/cdata/ui_scripts/MainMenu/CPMainMenuButtons.lua
Normal file
201
data/cdata/ui_scripts/MainMenu/CPMainMenuButtons.lua
Normal file
@ -0,0 +1,201 @@
|
||||
local f0_local0 = function ( f1_arg0, f1_arg1 )
|
||||
Engine.Exec( "xblive_privatematch 0" )
|
||||
utils.cp.AliensUtils.AliensRunConfig( f1_arg1.controller )
|
||||
LUI.FlowManager.RequestAddMenu( "SystemLinkMenu", false, f1_arg1.controller, false, {}, true )
|
||||
end
|
||||
|
||||
local f0_local1 = function ( f2_arg0, f2_arg1 )
|
||||
f0_local0( f2_arg0, f2_arg1 )
|
||||
end
|
||||
|
||||
local f0_local2 = function ( f3_arg0, f3_arg1 )
|
||||
Engine.Exec( MPConfig.default_xboxlive, f3_arg1.controller )
|
||||
Engine.SetDvarBool( "xblive_privatematch", true )
|
||||
SetIsAliensSolo( true )
|
||||
Engine.SetDvarInt( "party_maxplayers", 1 )
|
||||
Engine.Exec( "xstartprivatematch" )
|
||||
LUI.FlowManager.RequestAddMenu( "CPPrivateMatchMenu", false, f3_arg1.controller, false, {
|
||||
showPlayNowButton = true,
|
||||
isPublicMatch = false
|
||||
} )
|
||||
end
|
||||
|
||||
local f0_local3 = function ( f4_arg0, f4_arg1 )
|
||||
Engine.Exec( MPConfig.default_xboxlive, f4_arg1.controller )
|
||||
Engine.SetDvarBool( "xblive_privatematch", true )
|
||||
SetIsAliensSolo( false )
|
||||
Engine.Exec( "xstartprivatematch" )
|
||||
LUI.FlowManager.RequestAddMenu( "CPPrivateMatchMenu", false, f4_arg1.controller, false, {
|
||||
showPlayNowButton = true,
|
||||
isPublicMatch = false
|
||||
} )
|
||||
end
|
||||
|
||||
local f0_local4 = function ( f5_arg0, f5_arg1, f5_arg2 )
|
||||
assert( f5_arg0.PublicMatch )
|
||||
assert( f5_arg0.SoloMatch )
|
||||
assert( f5_arg0.CustomMatch )
|
||||
local f5_local0 = LUI.DataSourceInGlobalModel.new( "frontEnd.lobby.areWeGameHost" )
|
||||
local f5_local1 = DataSources.frontEnd.lobby.memberCount
|
||||
local f5_local2 = function ()
|
||||
return Lobby.IsInPrivateParty() and not Lobby.IsPrivatePartyHost()
|
||||
end
|
||||
|
||||
local f5_local3 = function ()
|
||||
local f7_local0 = f5_local2()
|
||||
f5_arg0.PublicMatch:SetButtonDisabled( f7_local0 )
|
||||
f5_arg0.CustomMatch:SetButtonDisabled( f7_local0 )
|
||||
end
|
||||
|
||||
f5_arg0:SubscribeToModel( f5_local0:GetModel( f5_arg1 ), f5_local3 )
|
||||
f5_arg0:SubscribeToModel( f5_local1:GetModel( f5_arg1 ), f5_local3 )
|
||||
f5_arg0:SubscribeToModel( DataSources.frontEnd.lobby.isSolo:GetModel( f5_arg1 ), function ()
|
||||
local f8_local0 = DataSources.frontEnd.lobby.isSolo:GetValue( f5_arg1 )
|
||||
if f8_local0 ~= nil then
|
||||
f5_arg0.SoloMatch:SetButtonDisabled( not f8_local0 )
|
||||
end
|
||||
end )
|
||||
f5_arg0.PublicMatch:addEventHandler( "button_action", f0_local1 )
|
||||
f5_arg0.SoloMatch:addEventHandler( "button_action", f0_local2 )
|
||||
f5_arg0.Loadout:addEventHandler( "button_action", function ( f9_arg0, f9_arg1 )
|
||||
LUI.FlowManager.RequestAddMenu( "CPLoadoutMenu", true, f9_arg1.controller )
|
||||
end )
|
||||
f5_arg0.Barracks:addEventHandler( "button_action", function ( f10_arg0, f10_arg1 )
|
||||
LUI.FlowManager.RequestAddMenu( "Headquarters", true, f10_arg1.controller )
|
||||
end )
|
||||
f5_arg0.Armory:addEventHandler( "button_action", function ( f11_arg0, f11_arg1 )
|
||||
if not Engine.IsUserAGuest( f11_arg1.controller ) then
|
||||
ACTIONS.OpenMenu( "Armory", true, f11_arg1.controller )
|
||||
end
|
||||
end )
|
||||
f5_arg0.CustomMatch:addEventHandler( "button_action", f0_local3 )
|
||||
f5_arg0.ContractsButton:addEventHandler( "button_action", function ( f12_arg0, f12_arg1 )
|
||||
ACTIONS.OpenMenu( "ContractMenu", true, f12_arg1.controller or f5_arg1 )
|
||||
end )
|
||||
|
||||
f5_arg0.ModsButton:addEventHandler( "button_action", function ( arg0, arg1 )
|
||||
LUI.FlowManager.RequestAddMenu( "ModSelectMenu", true, arg1.controller, false )
|
||||
end )
|
||||
end
|
||||
|
||||
function CPMainMenuButtons( menu, controller )
|
||||
local VNavigator = LUI.UIVerticalNavigator.new()
|
||||
VNavigator:SetAnchorsAndPosition( 0, 1, 0, 1, 0, 500 * _1080p, 0, 400 * _1080p )
|
||||
VNavigator.id = "CPMainMenuButtons"
|
||||
local f14_local1 = controller and controller.controllerIndex
|
||||
if not f14_local1 and not Engine.InFrontend() then
|
||||
f14_local1 = VNavigator:getRootController()
|
||||
end
|
||||
assert( f14_local1 )
|
||||
local f14_local2 = VNavigator
|
||||
local ButtonDescription = nil
|
||||
|
||||
ButtonDescription = MenuBuilder.BuildRegisteredType( "ButtonDescriptionText", {
|
||||
controllerIndex = f14_local1
|
||||
} )
|
||||
ButtonDescription.id = "ButtonDescription"
|
||||
ButtonDescription:SetRGBFromTable( SWATCHES.genericButton.textDisabled, 0 )
|
||||
ButtonDescription.Description:SetRight( _1080p * 415, 0 )
|
||||
ButtonDescription:SetAnchorsAndPosition( 0, 0, 0, 1, 0, 0, _1080p * 336, _1080p * 394 )
|
||||
VNavigator:addElement( ButtonDescription )
|
||||
VNavigator.ButtonDescription = ButtonDescription
|
||||
|
||||
local PublicMatch = nil
|
||||
|
||||
PublicMatch = MenuBuilder.BuildRegisteredType( "MenuButton", {
|
||||
controllerIndex = f14_local1
|
||||
} )
|
||||
PublicMatch.id = "PublicMatch"
|
||||
PublicMatch.buttonDescription = "Browse for Custom Servers"
|
||||
PublicMatch.Text:setText( ToUpperCase( "Server Browser" ), 0 )
|
||||
PublicMatch:SetAnchorsAndPosition( 0, 1, 0, 1, 0, _1080p * 340, 0, _1080p * 30 )
|
||||
VNavigator:addElement( PublicMatch )
|
||||
VNavigator.PublicMatch = PublicMatch
|
||||
|
||||
local SoloMatch = nil
|
||||
|
||||
SoloMatch = MenuBuilder.BuildRegisteredType( "MenuButton", {
|
||||
controllerIndex = f14_local1
|
||||
} )
|
||||
SoloMatch.id = "SoloMatch"
|
||||
SoloMatch.buttonDescription = Engine.Localize( "LUA_MENU_ZM_SOLO_MATCH_DESC" )
|
||||
SoloMatch.Text:setText( ToUpperCase( Engine.Localize( "LUA_MENU_SOLO_MATCH_CAPS" ) ), 0 )
|
||||
SoloMatch:SetAnchorsAndPosition( 0, 1, 0, 1, 0, _1080p * 340, _1080p * 40, _1080p * 70 )
|
||||
VNavigator:addElement( SoloMatch )
|
||||
VNavigator.SoloMatch = SoloMatch
|
||||
|
||||
local CustomMatch = nil
|
||||
|
||||
CustomMatch = MenuBuilder.BuildRegisteredType( "MenuButton", {
|
||||
controllerIndex = f14_local1
|
||||
} )
|
||||
CustomMatch.id = "CustomMatch"
|
||||
CustomMatch.buttonDescription = Engine.Localize( "LUA_MENU_ZM_CUSTOM_MATCH_DESC" )
|
||||
CustomMatch.Text:setText( ToUpperCase( Engine.Localize( "LUA_MENU_CUSTOM_GAME_CAPS" ) ), 0 )
|
||||
CustomMatch:SetAnchorsAndPosition( 0, 1, 0, 1, 0, _1080p * 340, _1080p * 80, _1080p * 110 )
|
||||
VNavigator:addElement( CustomMatch )
|
||||
VNavigator.CustomMatch = CustomMatch
|
||||
|
||||
local Loadout = nil
|
||||
|
||||
Loadout = MenuBuilder.BuildRegisteredType( "MenuButton", {
|
||||
controllerIndex = f14_local1
|
||||
} )
|
||||
Loadout.id = "Loadout"
|
||||
Loadout.buttonDescription = Engine.Localize( "LUA_MENU_ZM_LOADOUT_DESC" )
|
||||
Loadout.Text:setText( Engine.Localize( "LUA_MENU_ZM_LOADOUT_CAPS" ), 0 )
|
||||
Loadout:SetAnchorsAndPosition( 0, 1, 0, 1, 0, _1080p * 340, _1080p * 120, _1080p * 150 )
|
||||
VNavigator:addElement( Loadout )
|
||||
VNavigator.Loadout = Loadout
|
||||
|
||||
local Barracks = nil
|
||||
|
||||
Barracks = MenuBuilder.BuildRegisteredType( "MenuButton", {
|
||||
controllerIndex = f14_local1
|
||||
} )
|
||||
Barracks.id = "Barracks"
|
||||
Barracks.buttonDescription = Engine.Localize( "LUA_MENU_ZM_BARRACKS_DESC" )
|
||||
Barracks.Text:setText( ToUpperCase( Engine.Localize( "LUA_MENU_ZM_BARRACKS_CAPS" ) ), 0 )
|
||||
Barracks:SetAnchorsAndPosition( 0, 1, 0, 1, 0, _1080p * 340, _1080p * 160, _1080p * 190 )
|
||||
VNavigator:addElement( Barracks )
|
||||
VNavigator.Barracks = Barracks
|
||||
|
||||
local Armory = nil
|
||||
|
||||
Armory = MenuBuilder.BuildRegisteredType( "MenuButton", {
|
||||
controllerIndex = f14_local1
|
||||
} )
|
||||
Armory.id = "Armory"
|
||||
Armory.buttonDescription = Engine.Localize( "LUA_MENU_ZM_SURVIVAL_DEPOT_DESC" )
|
||||
Armory.Text:setText( ToUpperCase( Engine.Localize( "LUA_MENU_ZM_SURVIVAL_DEPOT" ) ), 0 )
|
||||
Armory:SetAnchorsAndPosition( 0, 1, 0, 1, 0, _1080p * 340, _1080p * 200, _1080p * 230 )
|
||||
VNavigator:addElement( Armory )
|
||||
VNavigator.Armory = Armory
|
||||
|
||||
local ModsButton = nil
|
||||
|
||||
ModsButton = MenuBuilder.BuildRegisteredType( "MenuButton", {
|
||||
controllerIndex = f14_local1
|
||||
} )
|
||||
ModsButton.id = "ModsButton"
|
||||
ModsButton.buttonDescription = Engine.Localize( "LUA_MENU_MODS_DESC" )
|
||||
ModsButton.Text:setText( ToUpperCase( Engine.Localize( "LUA_MENU_MODS_CAPS" ) ), 0 )
|
||||
ModsButton:SetAnchorsAndPosition( 0, 1, 0, 1, 0, _1080p * 340, _1080p * 240, _1080p * 270 )
|
||||
VNavigator:addElement( ModsButton )
|
||||
VNavigator.ModsButton = ModsButton
|
||||
|
||||
local ContractsButton = nil
|
||||
|
||||
ContractsButton = MenuBuilder.BuildRegisteredType( "ContractsButtonCP", {
|
||||
controllerIndex = f14_local1
|
||||
} )
|
||||
ContractsButton.id = "ContractsButton"
|
||||
ContractsButton:SetAnchorsAndPosition( 0, 1, 0, 1, 0, _1080p * 340, _1080p * 280, _1080p * 340 )
|
||||
VNavigator:addElement( ContractsButton )
|
||||
VNavigator.ContractsButton = ContractsButton
|
||||
|
||||
f0_local4( VNavigator, f14_local1, controller )
|
||||
return VNavigator
|
||||
end
|
||||
|
||||
MenuBuilder.m_types["CPMainMenuButtons"] = CPMainMenuButtons
|
178
data/cdata/ui_scripts/MainMenu/CampaignMenuButtons.lua
Normal file
178
data/cdata/ui_scripts/MainMenu/CampaignMenuButtons.lua
Normal file
@ -0,0 +1,178 @@
|
||||
local f0_local1 = function ( f2_arg0 )
|
||||
f2_arg0.ResumeButton:SetButtonDisabled( not Engine.CanResumeGame( f2_arg0._controllerIndex ) )
|
||||
if not CONDITIONS.IsTrialLicense( f2_arg0 ) then
|
||||
local f2_local0 = f2_arg0.MissionSelectButton
|
||||
local f2_local1 = f2_local0
|
||||
f2_local0 = f2_local0.SetButtonDisabled
|
||||
local f2_local2 = Engine.IsTrialLicense()
|
||||
if not f2_local2 then
|
||||
if not Engine.IsDevelopmentBuild() and not Engine.GetDvarBool( "mis_cheat" ) then
|
||||
f2_local2 = not f0_local0( f2_arg0._controllerIndex )
|
||||
else
|
||||
f2_local2 = false
|
||||
end
|
||||
end
|
||||
f2_local0( f2_local1, f2_local2 )
|
||||
end
|
||||
end
|
||||
|
||||
local f0_local2 = function ( f3_arg0, f3_arg1 )
|
||||
LUI.FlowManager.RequestPopupMenu( nil, "FakeLoadingScreenOverlay", true, 0, false, {
|
||||
onLoadCompleteFunc = function ()
|
||||
Engine.SetDvarString( "ui_char_museum_mode", "credits_1" )
|
||||
Engine.Exec( "profile_difficultyLoad" )
|
||||
Engine.Exec( "profile_specialistModeLoad" )
|
||||
Engine.Exec( "profile_yoloModeLoad" )
|
||||
Engine.Exec( "loadgame_continue" )
|
||||
Engine.Exec( "updategamerprofile" )
|
||||
end
|
||||
} )
|
||||
LUI.FlowManager.RequestLeaveMenu( f3_arg0 )
|
||||
end
|
||||
|
||||
local f0_local3 = function ( f5_arg0, f5_arg1 )
|
||||
LUI.FlowManager.RequestPopupMenu( nil, "FakeLoadingScreenOverlay", true, 0, false, {
|
||||
onLoadCompleteFunc = function ()
|
||||
Engine.Exec( "set ui_play_credits 1; map shipcrib_epilogue" )
|
||||
end
|
||||
} )
|
||||
end
|
||||
|
||||
--MenuBuilder.registerType( "ResumeGamePopup", function ( f7_arg0, f7_arg1 )
|
||||
-- return MenuBuilder.BuildRegisteredType( "PopupYesNo", {
|
||||
-- message = Engine.Localize( "@MENU_RESUMEGAME_Q" ),
|
||||
-- yesAction = f0_local2
|
||||
-- } )
|
||||
--end )
|
||||
local f0_local4 = function ( f8_arg0, f8_arg1, f8_arg2 )
|
||||
assert( f8_arg0.ResumeButton )
|
||||
assert( f8_arg0.NewButton )
|
||||
assert( f8_arg0.CreditsButton )
|
||||
if not CONDITIONS.IsTrialLicense( f8_arg0 ) then
|
||||
assert( f8_arg0.MissionSelectButton )
|
||||
end
|
||||
f8_arg0._controllerIndex = f8_arg1
|
||||
f8_arg0.ResumeButton:addEventHandler( "button_action", function ( f9_arg0, f9_arg1 )
|
||||
Engine.SetDvarString( "start", "" )
|
||||
LUI.FlowManager.RequestPopupMenu( f9_arg0, "ResumeGamePopup", false, f9_arg1.controller, false )
|
||||
end )
|
||||
f8_arg0.NewButton:addEventHandler( "button_action", function ( f10_arg0, f10_arg1 )
|
||||
Engine.SetDvarString( "start", "" )
|
||||
if Engine.CanResumeGame( f8_arg1 ) then
|
||||
LUI.FlowManager.RequestPopupMenu( f8_arg0, "overwrite_warning_menu", true, f10_arg1.controller )
|
||||
else
|
||||
LUI.FlowManager.RequestPopupMenu( f8_arg0, "popmenu_autosave_warning", true, f10_arg1.controller )
|
||||
end
|
||||
end )
|
||||
if not CONDITIONS.IsTrialLicense( f8_arg0 ) then
|
||||
f8_arg0.MissionSelectButton:addEventHandler( "button_action", function ( f11_arg0, f11_arg1 )
|
||||
Engine.SetDvarString( "start", "" )
|
||||
LUI.FlowManager.RequestAddMenu( "LevelSelectMenu", true, f11_arg1.controller, false )
|
||||
end )
|
||||
end
|
||||
f8_arg0.CreditsButton:addEventHandler( "button_action", f0_local3 )
|
||||
f0_local1( f8_arg0 )
|
||||
f8_arg0:addEventHandler( "update_save_game_available_complete", f0_local1 )
|
||||
if Engine.GetDvarFloat( "r_filmGrainAtten" ) == 0.25 then
|
||||
Engine.SetDvarFloat( "r_filmGrainAtten", 1 )
|
||||
Engine.ExecNow( "profile_setFilmGrain " .. tostring( 1 ), f8_arg1 )
|
||||
end
|
||||
|
||||
f8_arg0.ModsButton:addEventHandler( "button_action", function ( arg0, arg1 )
|
||||
LUI.FlowManager.RequestAddMenu( "ModSelectMenu", true, arg1.controller, false )
|
||||
end )
|
||||
end
|
||||
|
||||
function CampaignMenuButtons( menu, controller )
|
||||
local self = LUI.UIVerticalList.new()
|
||||
self:SetAnchorsAndPosition( 0, 1, 0, 1, 0, 500 * _1080p, 0, 440 * _1080p )
|
||||
self.id = "CampaignMenuButtons"
|
||||
local f12_local1 = controller and controller.controllerIndex
|
||||
if not f12_local1 and not Engine.InFrontend() then
|
||||
f12_local1 = self:getRootController()
|
||||
end
|
||||
assert( f12_local1 )
|
||||
local f12_local2 = self
|
||||
self:SetSpacing( 10 * _1080p )
|
||||
local ResumeButton = nil
|
||||
|
||||
ResumeButton = MenuBuilder.BuildRegisteredType( "MenuButton", {
|
||||
controllerIndex = f12_local1
|
||||
} )
|
||||
ResumeButton.id = "ResumeButton"
|
||||
ResumeButton.buttonDescription = Engine.Localize( "LUA_MENU_RESUME_GAME_DESC" )
|
||||
ResumeButton.Text:setText( Engine.Localize( "MENU_RESUMEGAME_CAPS" ), 0 )
|
||||
ResumeButton:SetAnchorsAndPosition( 0, 1, 0, 1, 0, _1080p * 500, 0, _1080p * 30 )
|
||||
self:addElement( ResumeButton )
|
||||
self.ResumeButton = ResumeButton
|
||||
|
||||
local NewButton = nil
|
||||
|
||||
NewButton = MenuBuilder.BuildRegisteredType( "MenuButton", {
|
||||
controllerIndex = f12_local1
|
||||
} )
|
||||
NewButton.id = "NewButton"
|
||||
NewButton.buttonDescription = Engine.Localize( "LUA_MENU_NEW_GAME_DESC" )
|
||||
NewButton.Text:setText( Engine.Localize( "MENU_NEWGAME_CAPS" ), 0 )
|
||||
NewButton:SetAnchorsAndPosition( 0, 1, 0, 1, 0, _1080p * 500, _1080p * 40, _1080p * 70 )
|
||||
self:addElement( NewButton )
|
||||
self.NewButton = NewButton
|
||||
|
||||
local f12_local5 = nil
|
||||
if not CONDITIONS.IsTrialLicense( self ) then
|
||||
f12_local5 = MenuBuilder.BuildRegisteredType( "MenuButton", {
|
||||
controllerIndex = f12_local1
|
||||
} )
|
||||
f12_local5.id = "MissionSelectButton"
|
||||
if not CONDITIONS.IsTrialLicense( self ) then
|
||||
|
||||
else
|
||||
|
||||
end
|
||||
if not CONDITIONS.IsTrialLicense( self ) then
|
||||
f12_local5.buttonDescription = Engine.Localize( "LUA_MENU_MISSION_SELECT_DESC" )
|
||||
end
|
||||
f12_local5.Text:setText( Engine.Localize( "MENU_MISSION_SELECT_CAPS" ), 0 )
|
||||
f12_local5:SetAnchorsAndPosition( 0, 1, 0, 1, 0, _1080p * 500, _1080p * 80, _1080p * 110 )
|
||||
self:addElement( f12_local5 )
|
||||
self.MissionSelectButton = f12_local5
|
||||
end
|
||||
local CreditsButton = nil
|
||||
|
||||
CreditsButton = MenuBuilder.BuildRegisteredType( "MenuButton", {
|
||||
controllerIndex = f12_local1
|
||||
} )
|
||||
CreditsButton.id = "CreditsButton"
|
||||
CreditsButton.buttonDescription = Engine.Localize( "LUA_MENU_CREDITS_DESC" )
|
||||
CreditsButton.Text:setText( ToUpperCase( Engine.Localize( "MENU_SP_CREDITS_CAPS" ) ), 0 )
|
||||
CreditsButton:SetAnchorsAndPosition( 0, 1, 0, 1, 0, _1080p * 500, _1080p * 120, _1080p * 150 )
|
||||
self:addElement( CreditsButton )
|
||||
self.CreditsButton = CreditsButton
|
||||
|
||||
local ModsButton = nil
|
||||
|
||||
ModsButton = MenuBuilder.BuildRegisteredType( "MenuButton", {
|
||||
controllerIndex = f12_local1
|
||||
} )
|
||||
ModsButton.id = "ModsButton"
|
||||
ModsButton.buttonDescription = Engine.Localize( "LUA_MENU_MODS_DESC" )
|
||||
ModsButton.Text:setText( ToUpperCase( Engine.Localize( "LUA_MENU_MODS_CAPS" ) ), 0 )
|
||||
ModsButton:SetAnchorsAndPosition( 0, 1, 0, 1, 0, _1080p * 500, _1080p * 160, _1080p * 190 )
|
||||
self:addElement( ModsButton )
|
||||
self.ModsButton = ModsButton
|
||||
|
||||
local ButtonDescription = nil
|
||||
|
||||
ButtonDescription = MenuBuilder.BuildRegisteredType( "ButtonDescriptionText", {
|
||||
controllerIndex = f12_local1
|
||||
} )
|
||||
ButtonDescription.id = "ButtonDescription"
|
||||
ButtonDescription:SetAnchorsAndPosition( 0, 1, 0, 1, 0, _1080p * 504, _1080p * 200, _1080p * 300 )
|
||||
self:addElement( ButtonDescription )
|
||||
self.ButtonDescription = ButtonDescription
|
||||
|
||||
f0_local4( self, f12_local1, controller )
|
||||
return self
|
||||
end
|
||||
|
||||
MenuBuilder.m_types["CampaignMenuButtons"] = CampaignMenuButtons
|
206
data/cdata/ui_scripts/MainMenu/MPMainMenuButtons.lua
Normal file
206
data/cdata/ui_scripts/MainMenu/MPMainMenuButtons.lua
Normal file
@ -0,0 +1,206 @@
|
||||
local buttonSpacing = 40
|
||||
local f0_local1 = 10
|
||||
local f0_local2 = function ( f1_arg0, f1_arg1, f1_arg2 )
|
||||
if 0 < f1_arg2 then
|
||||
local f1_local0, f1_local1, f1_local2, f1_local3 = f1_arg0:getLocalRect()
|
||||
local f1_local4 = f1_local3 - f1_local1
|
||||
f1_arg0:SetTop( f1_local1 - (f1_local4 + f1_arg1) * f1_arg2 )
|
||||
f1_arg0:SetBottom( f1_local3 - (f1_local4 + f1_arg1) * f1_arg2 )
|
||||
end
|
||||
end
|
||||
|
||||
local f0_local3 = function ( f2_arg0, f2_arg1, f2_arg2 )
|
||||
assert( f2_arg0.ConquestButton )
|
||||
if CONDITIONS.IsStoreAllowed( f2_arg0 ) then
|
||||
assert( f2_arg0.StoreButton )
|
||||
end
|
||||
local f2_local0 = not CONDITIONS.IsTrialLicense( f2_arg0 )
|
||||
if f2_local0 then
|
||||
assert( f2_arg0.CustomGameButton )
|
||||
end
|
||||
f2_arg0.buttonSpacing = _1080p * buttonSpacing
|
||||
local f2_local1 = function ()
|
||||
return Lobby.IsInPrivateParty() and not Lobby.IsPrivatePartyHost()
|
||||
end
|
||||
|
||||
local f2_local2 = function ()
|
||||
local f4_local0 = f2_local1()
|
||||
f2_arg0.ConquestButton:SetButtonDisabled( f4_local0 )
|
||||
if f2_arg0.MLGGameBattlesButton ~= nil then
|
||||
f2_arg0.MLGGameBattlesButton:SetButtonDisabled( f4_local0 )
|
||||
end
|
||||
if f2_local0 then
|
||||
f2_arg0.CustomGameButton:SetButtonDisabled( f4_local0 )
|
||||
end
|
||||
end
|
||||
|
||||
local f2_local3 = LUI.DataSourceInGlobalModel.new( "frontEnd.lobby.areWeGameHost" )
|
||||
local f2_local4 = DataSources.frontEnd.lobby.memberCount
|
||||
f2_arg0:SubscribeToModel( f2_local3:GetModel( f2_arg1 ), f2_local2 )
|
||||
f2_arg0:SubscribeToModel( f2_local4:GetModel( f2_arg1 ), f2_local2 )
|
||||
f2_arg0.ConquestButton:addEventHandler( "button_action", function ( f5_arg0, f5_arg1 )
|
||||
Engine.SetDvarBool( "cg_mlg_gamebattles_match", false )
|
||||
local f5_local0 = function ()
|
||||
LUI.FlowManager.RequestAddMenu( "Missions", false, f5_arg1.controller, false, {}, true )
|
||||
end
|
||||
|
||||
if not Onboarding:BeginFlow( Onboarding.RigTutorial, f2_arg1 ) then
|
||||
f5_local0()
|
||||
else
|
||||
LUI.FlowManager.RequestPopupMenu( nil, "MPFullScreenVideoOverlay", true, f2_arg1, nil, {
|
||||
videoRef = "mp_wolverines_mission_commander",
|
||||
allowSkip = true,
|
||||
doIntroFadeOut = false,
|
||||
doIntroFadeIn = false,
|
||||
doOutroFadeIn = true,
|
||||
doOutroFadeOut = true,
|
||||
fadeColor = COLORS.black
|
||||
}, nil, true, true )
|
||||
local f5_local1 = f2_arg0:Wait( 500 )
|
||||
f5_local1.onComplete = f5_local0
|
||||
end
|
||||
end )
|
||||
if CONDITIONS.IsGameBattlesAllowed( f2_arg0 ) then
|
||||
f2_arg0.MLGGameBattlesButton:addEventHandler( "button_action", function ( f7_arg0, f7_arg1 )
|
||||
if Engine.GetDvarBool( "splitscreen" ) then
|
||||
LUI.FlowManager.RequestPopupMenu( f2_arg0, "MLGGamebattlesSplitscreenPopup", true, f7_arg1.controller, false, {
|
||||
controllerIndex = f2_arg1
|
||||
} )
|
||||
elseif Lobby.IsNotAloneInPrivateParty() then
|
||||
LUI.FlowManager.RequestPopupMenu( f2_arg0, "DisbandPartyEnterGameBattlesLobbyPopup", true, f7_arg1.controller, false, {
|
||||
controllerIndex = f2_arg1
|
||||
} )
|
||||
else
|
||||
OpenGameBattlesLobby( f7_arg1.controller )
|
||||
end
|
||||
end )
|
||||
end
|
||||
if f2_local0 then
|
||||
f2_arg0.CustomGameButton:addEventHandler( "button_action", function ( f8_arg0, f8_arg1 )
|
||||
OpenPrivateMatchLobby( f8_arg1 )
|
||||
end )
|
||||
end
|
||||
|
||||
f2_arg0.ModsButton:addEventHandler( "button_action", function ( arg0, arg1 )
|
||||
LUI.FlowManager.RequestAddMenu( "ModSelectMenu", true, arg1.controller, false )
|
||||
end )
|
||||
|
||||
if CONDITIONS.IsStoreAllowed( f2_arg0 ) then
|
||||
f2_arg0.StoreButton:addEventHandler( "button_action", function ( f9_arg0, f9_arg1 )
|
||||
local f9_local0 = STORE.GoToStore
|
||||
local f9_local1 = f9_arg1.controller
|
||||
local f9_local2 = f9_arg0:GetCurrentMenu()
|
||||
f9_local0( f9_local1, f9_local2.id, f9_arg0.id )
|
||||
end )
|
||||
end
|
||||
local f2_local5 = _1080p * f0_local1
|
||||
local f2_local6 = 0
|
||||
if f2_arg0.MLGGameBattlesButton == nil then
|
||||
f2_local6 = 1
|
||||
end
|
||||
if f2_arg0.CustomGameButton then
|
||||
f0_local2( f2_arg0.CustomGameButton, f2_local5, f2_local6 )
|
||||
else
|
||||
f2_local6 = f2_local6 + 1
|
||||
end
|
||||
if f2_arg0.ModsButton then
|
||||
f0_local2( f2_arg0.ModsButton, f2_local5, f2_local6 )
|
||||
else
|
||||
f2_local6 = f2_local6 + 1
|
||||
end
|
||||
if CONDITIONS.IsStoreAllowed( f2_arg0 ) then
|
||||
f0_local2( f2_arg0.StoreButton, f2_local5, f2_local6 )
|
||||
else
|
||||
f2_local6 = f2_local6 + 1
|
||||
end
|
||||
if f2_arg0.StoreButton then
|
||||
f2_arg0.StoreButton:SetButtonDescription( STORE.GetStoreDescription() )
|
||||
if CONDITIONS.IsTrialLicense() then
|
||||
f2_arg0.StoreButton.Text:setText( ToUpperCase( Engine.Localize( "LUA_MENU_BUY_NOW" ) ) )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function MPMainMenuButtons( menu, controller )
|
||||
local self = LUI.UIVerticalNavigator.new()
|
||||
self:SetAnchorsAndPosition( 0, 1, 0, 1, 0, 500 * _1080p, 0, 190 * _1080p )
|
||||
self.id = "MPMainMenuButtons"
|
||||
local f11_local1 = controller and controller.controllerIndex
|
||||
if not f11_local1 and not Engine.InFrontend() then
|
||||
f11_local1 = self:getRootController()
|
||||
end
|
||||
assert( f11_local1 )
|
||||
local ConquestButton = nil
|
||||
|
||||
ConquestButton = MenuBuilder.BuildRegisteredType( "MenuButton", {
|
||||
controllerIndex = f11_local1
|
||||
} )
|
||||
ConquestButton.id = "ConquestButton"
|
||||
ConquestButton.buttonDescription = Engine.Localize( "LUA_MENU_PUBLIC_MATCH_DESC" )
|
||||
ConquestButton.Text:setText( Engine.Localize( "LUA_MENU_PUBLIC_MATCH_CAPS" ), 0 )
|
||||
ConquestButton:SetAnchorsAndPosition( 0, 1, 0, 1, 0, _1080p * 500, 0, _1080p * 30 )
|
||||
self:addElement( ConquestButton )
|
||||
self.ConquestButton = ConquestButton
|
||||
|
||||
local MLGGameBattlesButton = nil
|
||||
if CONDITIONS.IsGameBattlesAllowed( self ) then
|
||||
MLGGameBattlesButton = MenuBuilder.BuildRegisteredType( "MenuButton", {
|
||||
controllerIndex = f11_local1
|
||||
} )
|
||||
MLGGameBattlesButton.id = "MLGGameBattlesButton"
|
||||
if CONDITIONS.IsGameBattlesAllowed( self ) then
|
||||
|
||||
else
|
||||
|
||||
end
|
||||
if CONDITIONS.IsGameBattlesAllowed( self ) then
|
||||
MLGGameBattlesButton.buttonDescription = Engine.Localize( "LUA_MENU_MLG_GAMEBATTLES_DESC" )
|
||||
end
|
||||
MLGGameBattlesButton.Text:setText( Engine.Localize( "LUA_MENU_MLG_GAMEBATTLES_CAPS" ), 0 )
|
||||
MLGGameBattlesButton:SetAnchorsAndPosition( 0, 1, 0, 1, 0, _1080p * 500, _1080p * 40, _1080p * 70 )
|
||||
self:addElement( MLGGameBattlesButton )
|
||||
self.MLGGameBattlesButton = MLGGameBattlesButton
|
||||
end
|
||||
|
||||
local CustomGameButton = nil
|
||||
|
||||
CustomGameButton = MenuBuilder.BuildRegisteredType( "MenuButton", {
|
||||
controllerIndex = f11_local1
|
||||
} )
|
||||
CustomGameButton.id = "CustomGameButton"
|
||||
CustomGameButton.buttonDescription = Engine.Localize( "LUA_MENU_CUSTOM_GAME_DESC" )
|
||||
CustomGameButton.Text:setText( Engine.Localize( "LUA_MENU_CUSTOM_GAME_CAPS" ), 0 )
|
||||
CustomGameButton:SetAnchorsAndPosition( 0, 1, 0, 1, 0, _1080p * 500, _1080p * 80, _1080p * 110 )
|
||||
self:addElement( CustomGameButton )
|
||||
self.CustomGameButton = CustomGameButton
|
||||
|
||||
local ModsButton = nil
|
||||
|
||||
ModsButton = MenuBuilder.BuildRegisteredType( "MenuButton", {
|
||||
controllerIndex = f11_local1
|
||||
} )
|
||||
ModsButton.id = "ModsButton"
|
||||
ModsButton.buttonDescription = Engine.Localize( "LUA_MENU_MODS_DESC" )
|
||||
ModsButton.Text:setText( ToUpperCase( Engine.Localize( "LUA_MENU_MODS_CAPS" ) ), 0 )
|
||||
ModsButton:SetAnchorsAndPosition( 0, 1, 0, 1, 0, _1080p * 500, _1080p * 120, _1080p * 150 )
|
||||
self:addElement( ModsButton )
|
||||
self.ModsButton = ModsButton
|
||||
|
||||
local f11_local6 = nil
|
||||
if CONDITIONS.IsStoreAllowed( self ) then
|
||||
f11_local6 = MenuBuilder.BuildRegisteredType( "MenuButton", {
|
||||
controllerIndex = f11_local1
|
||||
} )
|
||||
f11_local6.id = "StoreButton"
|
||||
f11_local6.buttonDescription = Engine.Localize( "LUA_MENU_STORE_DESC" )
|
||||
f11_local6.Text:setText( Engine.Localize( "LUA_MENU_STORE_CAPS" ), 0 )
|
||||
f11_local6:SetAnchorsAndPosition( 0, 1, 0, 1, 0, _1080p * 500, _1080p * 160, _1080p * 190 )
|
||||
self:addElement( f11_local6 )
|
||||
self.StoreButton = f11_local6
|
||||
end
|
||||
|
||||
f0_local3( self, f11_local1, controller )
|
||||
return self
|
||||
end
|
||||
|
||||
MenuBuilder.m_types["MPMainMenuButtons"] = MPMainMenuButtons
|
@ -1,2 +1,5 @@
|
||||
require("MPMainMenu")
|
||||
require("CampaignMenuButtons")
|
||||
require("CPMainMenu")
|
||||
require("CPMainMenuButtons")
|
||||
require("MissionsVerticalLayout")
|
||||
require("MPMainMenuButtons")
|
40
data/cdata/ui_scripts/Mods/ModDownload.lua
Normal file
40
data/cdata/ui_scripts/Mods/ModDownload.lua
Normal file
@ -0,0 +1,40 @@
|
||||
function ModDownloadCancel( arg0, arg1 )
|
||||
download.abort()
|
||||
LUI.FlowManager.RequestLeaveMenu( arg0 )
|
||||
end
|
||||
|
||||
function ModDownloadPopup( arg0, arg1 )
|
||||
local popup = MenuBuilder.BuildRegisteredType( "FenceDialogPopup", {
|
||||
message = "Downloading files...",
|
||||
controllerIndex = arg1.controllerIndex,
|
||||
onCancel = ModDownloadCancel
|
||||
} )
|
||||
popup.id = "ModDownloadPopup"
|
||||
|
||||
local file = ""
|
||||
|
||||
popup:registerEventHandler("mod_download_set_file", function(element, event)
|
||||
file = event.request.name
|
||||
popup.Message:setText(string.format("Downloading %s...", file))
|
||||
end)
|
||||
|
||||
popup:registerEventHandler("mod_download_progress", function(element, event)
|
||||
popup.Message:setText(string.format("Downloading %s (%i%%)...", file, math.floor(event.fraction * 100)))
|
||||
end)
|
||||
|
||||
popup:registerEventHandler("mod_download_done", function()
|
||||
LUI.FlowManager.RequestLeaveMenu(popup)
|
||||
end)
|
||||
|
||||
return popup
|
||||
end
|
||||
|
||||
MenuBuilder.registerType( "ModDownloadPopup", ModDownloadPopup )
|
||||
|
||||
local function reg_func()
|
||||
Engine.GetLuiRoot():registerEventHandler("mod_download_start", function(element, event)
|
||||
LUI.FlowManager.RequestPopupMenu( element, "ModDownloadPopup", true, event.controller, false )
|
||||
end)
|
||||
end
|
||||
|
||||
scheduler.once(reg_func)
|
223
data/cdata/ui_scripts/Mods/ModSelectButton.lua
Normal file
223
data/cdata/ui_scripts/Mods/ModSelectButton.lua
Normal file
@ -0,0 +1,223 @@
|
||||
local function PostLoadFunc( f1_arg0, f1_arg1, f1_arg2 )
|
||||
assert( f1_arg0.GenericButton )
|
||||
|
||||
f1_arg0.GenericButton:addEventHandler( "button_action", function ( f3_arg0, f3_arg1 )
|
||||
local f3_local0 = f1_arg0:GetDataSource()
|
||||
f3_local0.buttonOnClickFunction( f3_arg0, f3_arg1 )
|
||||
end )
|
||||
f1_arg0.GenericButton:addEventHandler( "button_over", function ( f4_arg0, f4_arg1 )
|
||||
local f4_local0 = f1_arg0:GetDataSource()
|
||||
f4_local0.buttonOnHoverFunction( f4_arg0, f4_arg1 )
|
||||
f4_local0 = f1_arg0:GetDataSource()
|
||||
f4_local0 = f4_local0.levelName
|
||||
end )
|
||||
f1_arg0.GenericButton:addEventHandler( "button_up", function ( f5_arg0, f5_arg1 )
|
||||
local f5_local0 = f1_arg0:GetDataSource()
|
||||
f5_local0.buttonOnHoverFunction( f5_arg0, f5_arg1 )
|
||||
f5_local0 = f1_arg0:GetDataSource()
|
||||
f5_local0 = f5_local0.levelName
|
||||
end )
|
||||
f1_arg0:registerEventHandler( "grid_anim", function ( element, event )
|
||||
element:SetAlpha( event.value )
|
||||
end )
|
||||
assert( f1_arg0.MainMissionIcon )
|
||||
assert( f1_arg0.SAIcon )
|
||||
assert( f1_arg0.JAIcon )
|
||||
f1_arg0:SubscribeToDataSourceThroughElement( f1_arg0, nil, function ()
|
||||
local f7_local0 = f1_arg0:GetDataSource()
|
||||
f7_local0 = f7_local0.levelName
|
||||
end )
|
||||
end
|
||||
|
||||
function ModSelectButton( menu, controller )
|
||||
local self = LUI.UIButton.new()
|
||||
self:SetAnchorsAndPosition( 0, 1, 0, 1, 0, 500 * _1080p, 0, 30 * _1080p )
|
||||
self.id = "ModSelectButton"
|
||||
self._animationSets = {}
|
||||
self._sequences = {}
|
||||
local f8_local1 = controller and controller.controllerIndex
|
||||
if not f8_local1 and not Engine.InFrontend() then
|
||||
f8_local1 = self:getRootController()
|
||||
end
|
||||
assert( f8_local1 )
|
||||
local f8_local2 = self
|
||||
local GenericButton = nil
|
||||
|
||||
GenericButton = MenuBuilder.BuildRegisteredType( "GenericButton", {
|
||||
controllerIndex = f8_local1
|
||||
} )
|
||||
GenericButton.id = "GenericButton"
|
||||
GenericButton:SetAlpha( 0, 0 )
|
||||
GenericButton:SetAnchorsAndPosition( 0, 1, 0, 0, 0, _1080p * 500, 0, 0 )
|
||||
GenericButton:SubscribeToModelThroughElement( self, "buttonLabel", function ()
|
||||
local f9_local0 = self:GetDataSource()
|
||||
f9_local0 = f9_local0.buttonLabel:GetValue( f8_local1 )
|
||||
if f9_local0 ~= nil then
|
||||
GenericButton.Text:setText( LocalizeString( ToUpperCase( f9_local0 ) ), 0 )
|
||||
end
|
||||
end )
|
||||
self:addElement( GenericButton )
|
||||
self.GenericButton = GenericButton
|
||||
|
||||
local GenericListButtonBackground = nil
|
||||
|
||||
GenericListButtonBackground = MenuBuilder.BuildRegisteredType( "GenericListArrowButtonBackground", {
|
||||
controllerIndex = f8_local1
|
||||
} )
|
||||
GenericListButtonBackground.id = "GenericListButtonBackground"
|
||||
GenericListButtonBackground:SetAnchorsAndPosition( 0, 0, 0, 0, 0, 0, 0, 0 )
|
||||
self:addElement( GenericListButtonBackground )
|
||||
self.GenericListButtonBackground = GenericListButtonBackground
|
||||
|
||||
local Text = nil
|
||||
|
||||
Text = LUI.UIStyledText.new()
|
||||
Text.id = "Text"
|
||||
Text:SetRGBFromInt( 14277081, 0 )
|
||||
Text:SetFontSize( 22 * _1080p )
|
||||
Text:SetFont( FONTS.GetFont( FONTS.MainMedium.File ) )
|
||||
Text:SetAlignment( LUI.Alignment.Left )
|
||||
Text:SetStartupDelay( 2000 )
|
||||
Text:SetLineHoldTime( 400 )
|
||||
Text:SetAnimMoveTime( 300 )
|
||||
Text:SetEndDelay( 1500 )
|
||||
Text:SetCrossfadeTime( 750 )
|
||||
Text:SetAutoScrollStyle( LUI.UIStyledText.AutoScrollStyle.ScrollH )
|
||||
Text:SetMaxVisibleLines( 1 )
|
||||
Text:SetOutlineRGBFromInt( 0, 0 )
|
||||
Text:SetAnchorsAndPosition( 0, 0, 0.5, 0.5, _1080p * 44, _1080p * -41, _1080p * -11, _1080p * 11 )
|
||||
Text:SubscribeToModelThroughElement( self, "buttonLabel", function ()
|
||||
local f10_local0 = self:GetDataSource()
|
||||
f10_local0 = f10_local0.buttonLabel:GetValue( f8_local1 )
|
||||
if f10_local0 ~= nil then
|
||||
Text:setText( LocalizeString( ToUpperCase( f10_local0 ) ), 0 )
|
||||
end
|
||||
end )
|
||||
self:addElement( Text )
|
||||
self.Text = Text
|
||||
|
||||
local Lock = nil
|
||||
|
||||
Lock = LUI.UIImage.new()
|
||||
Lock.id = "Lock"
|
||||
Lock:SetRGBFromTable( SWATCHES.genericButton.textDisabled, 0 )
|
||||
Lock:SetAlpha( 0, 0 )
|
||||
Lock:setImage( RegisterMaterial( "icon_slot_locked" ), 0 )
|
||||
Lock:SetAnchorsAndPosition( 1, 0, 0.5, 0.5, _1080p * -32, _1080p * -6, _1080p * -12, _1080p * 14 )
|
||||
self:addElement( Lock )
|
||||
self.Lock = Lock
|
||||
|
||||
self._animationSets.DefaultAnimationSet = function ()
|
||||
self._sequences.DefaultSequence = function ()
|
||||
|
||||
end
|
||||
|
||||
Text:RegisterAnimationSequence( "ButtonOver", {
|
||||
{
|
||||
function ()
|
||||
return self.Text:SetRGBFromInt( 0, 0 )
|
||||
end
|
||||
},
|
||||
{
|
||||
function ()
|
||||
return self.Text:SetAlpha( 1, 0 )
|
||||
end
|
||||
}
|
||||
} )
|
||||
Lock:RegisterAnimationSequence( "ButtonOver", {
|
||||
{
|
||||
function ()
|
||||
return self.Lock:SetAlpha( 0, 0 )
|
||||
end
|
||||
},
|
||||
{
|
||||
function ()
|
||||
return self.Lock:SetRGBFromTable( SWATCHES.genericButton.textDisabled, 0 )
|
||||
end
|
||||
}
|
||||
} )
|
||||
self._sequences.ButtonOver = function ()
|
||||
Text:AnimateSequence( "ButtonOver" )
|
||||
Lock:AnimateSequence( "ButtonOver" )
|
||||
end
|
||||
|
||||
Text:RegisterAnimationSequence( "ButtonUp", {
|
||||
{
|
||||
function ()
|
||||
return self.Text:SetRGBFromInt( 14277081, 0 )
|
||||
end
|
||||
}
|
||||
} )
|
||||
Lock:RegisterAnimationSequence( "ButtonUp", {
|
||||
{
|
||||
function ()
|
||||
return self.Lock:SetAlpha( 0, 0 )
|
||||
end
|
||||
}
|
||||
} )
|
||||
self._sequences.ButtonUp = function ()
|
||||
Text:AnimateSequence( "ButtonUp" )
|
||||
Lock:AnimateSequence( "ButtonUp" )
|
||||
end
|
||||
|
||||
Text:RegisterAnimationSequence( "ButtonOverDisabled", {
|
||||
{
|
||||
function ()
|
||||
return self.Text:SetRGBFromInt( 0, 0 )
|
||||
end
|
||||
},
|
||||
{
|
||||
function ()
|
||||
return self.Text:SetAlpha( 1, 0 )
|
||||
end
|
||||
}
|
||||
} )
|
||||
Lock:RegisterAnimationSequence( "ButtonOverDisabled", {
|
||||
{
|
||||
function ()
|
||||
return self.Lock:SetAlpha( 1, 0 )
|
||||
end
|
||||
},
|
||||
{
|
||||
function ()
|
||||
return self.Lock:SetRGBFromInt( 0, 0 )
|
||||
end
|
||||
}
|
||||
} )
|
||||
self._sequences.ButtonOverDisabled = function ()
|
||||
Text:AnimateSequence( "ButtonOverDisabled" )
|
||||
Lock:AnimateSequence( "ButtonOverDisabled" )
|
||||
end
|
||||
|
||||
Text:RegisterAnimationSequence( "ButtonUpDisabled", {
|
||||
{
|
||||
function ()
|
||||
return self.Text:SetRGBFromInt( 14277081, 0 )
|
||||
end
|
||||
}
|
||||
} )
|
||||
Lock:RegisterAnimationSequence( "ButtonUpDisabled", {
|
||||
{
|
||||
function ()
|
||||
return self.Lock:SetAlpha( 1, 0 )
|
||||
end
|
||||
},
|
||||
{
|
||||
function ()
|
||||
return self.Lock:SetRGBFromInt( 12566463, 0 )
|
||||
end
|
||||
}
|
||||
} )
|
||||
self._sequences.ButtonUpDisabled = function ()
|
||||
Text:AnimateSequence( "ButtonUpDisabled" )
|
||||
Lock:AnimateSequence( "ButtonUpDisabled" )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
self._animationSets.DefaultAnimationSet()
|
||||
PostLoadFunc( self, f8_local1, controller )
|
||||
return self
|
||||
end
|
||||
|
||||
MenuBuilder.registerType( "ModSelectButton", ModSelectButton )
|
317
data/cdata/ui_scripts/Mods/ModSelectMenu.lua
Normal file
317
data/cdata/ui_scripts/Mods/ModSelectMenu.lua
Normal file
@ -0,0 +1,317 @@
|
||||
local f0_local0 = "frontEnd.ModSelect"
|
||||
f0_local1 = function ()
|
||||
WipeGlobalModelsAtPath( f0_local0 )
|
||||
end
|
||||
|
||||
local function getmodname(path)
|
||||
local name = path
|
||||
local desc = Engine.Localize("LUA_MENU_MOD_DESC_DEFAULT", name)
|
||||
|
||||
return name, desc
|
||||
end
|
||||
|
||||
local function set_mod( modname )
|
||||
Engine.SetDvarString( "fs_game", modname )
|
||||
Engine.Exec( "vid_restart" )
|
||||
end
|
||||
|
||||
local unload_mod = function( arg0, arg1 )
|
||||
set_mod( "" )
|
||||
end
|
||||
|
||||
local f0_local4 = function ( f4_arg0, f4_arg1 )
|
||||
LUI.FlowManager.RequestLeaveMenu( f4_arg0 )
|
||||
end
|
||||
|
||||
local f0_local8 = function ( f8_arg0, f8_arg1 )
|
||||
local f8_local0 = LUI.FlowManager.GetScopedData( f8_arg0 )
|
||||
if not f8_local0.currentLabel then
|
||||
f8_local0.currentLabel = ""
|
||||
end
|
||||
if not f8_local0.currentDesc then
|
||||
f8_local0.currentDesc = ""
|
||||
end
|
||||
f8_arg0:processEvent( {
|
||||
name = "menu_refresh"
|
||||
} )
|
||||
local f8_local2 = f8_arg0:GetCurrentMenu()
|
||||
assert( f8_local2.ModInfoTitle )
|
||||
f8_local2.ModInfoTitle:setText( f8_local0.currentLabel )
|
||||
assert( f8_local2.ModInfoText )
|
||||
f8_local2.ModInfoText:setText( f8_local0.currentDesc )
|
||||
end
|
||||
|
||||
local f0_local9 = function ( f9_arg0, f9_arg1, f9_arg2 )
|
||||
set_mod( f9_arg2 )
|
||||
end
|
||||
|
||||
local f0_local10 = function ( f11_arg0, f11_arg1, f11_arg2 )
|
||||
local f11_local0 = LUI.FlowManager.GetScopedData( f11_arg0 )
|
||||
f11_local0.currentLabel = f11_arg2.buttonLabel
|
||||
f11_local0.currentName = f11_arg2.modName
|
||||
f11_local0.currentDesc = f11_arg2.objectiveText
|
||||
f0_local8( f11_arg0, f11_arg1 )
|
||||
Engine.PlaySound( CoD.SFX.SPMinimap )
|
||||
end
|
||||
|
||||
local f0_local12 = function ( f13_arg0, f13_arg1 )
|
||||
local f13_local0 = {}
|
||||
local mods = io.listfiles("mods/")
|
||||
for i = 1, #mods do
|
||||
local name, desc = getmodname(mods[i])
|
||||
f13_local0[#f13_local0 + 1] = {
|
||||
buttonLabel = ToUpperCase(name),
|
||||
modName = name,
|
||||
objectiveText = desc,
|
||||
}
|
||||
end
|
||||
local f13_local1 = LUI.DataSourceFromList.new( #f13_local0 )
|
||||
f13_local1.MakeDataSourceAtIndex = function ( f14_arg0, f14_arg1, f14_arg2 )
|
||||
return {
|
||||
buttonLabel = LUI.DataSourceInGlobalModel.new( f0_local0 .. ".mods." .. f14_arg1, f13_local0[f14_arg1 + 1].buttonLabel ),
|
||||
buttonOnClickFunction = function ( f15_arg0, f15_arg1 )
|
||||
f0_local9( f15_arg0, f15_arg1, f13_local0[f14_arg1 + 1].modName )
|
||||
end
|
||||
,
|
||||
buttonOnHoverFunction = function ( f16_arg0, f16_arg1 )
|
||||
f0_local10( f16_arg0, f16_arg1, f13_local0[f14_arg1 + 1] )
|
||||
end
|
||||
,
|
||||
modName = f13_local0[f14_arg1 + 1].modName
|
||||
}
|
||||
end
|
||||
|
||||
assert( f13_arg0.ModSelectionList )
|
||||
f13_arg0.ModSelectionList:SetGridDataSource( f13_local1, f13_arg1 )
|
||||
end
|
||||
|
||||
local function PostLoadFunc( f17_arg0, f17_arg1, f17_arg2 )
|
||||
assert( f17_arg0.bindButton )
|
||||
f17_arg0.bindButton:addEventHandler( "button_secondary", f0_local4 )
|
||||
|
||||
local fs_game = Engine.GetDvarString( "fs_game" )
|
||||
if fs_game ~= "" then
|
||||
f17_arg0.LoadedModName:setText( "^3Loaded mod^7: " .. fs_game )
|
||||
f17_arg0.bindButton:addEventHandler( "button_alt2", unload_mod )
|
||||
else
|
||||
f17_arg0.LoadedModName:setText( "" )
|
||||
end
|
||||
|
||||
--f17_arg0:addEventHandler( "menu_create", f0_local3 )
|
||||
f0_local12( f17_arg0, f17_arg1 )
|
||||
f17_arg0:addEventHandler( "gain_focus", function ( f18_arg0, f18_arg1 )
|
||||
local f18_local0 = f18_arg0.ModSelectionList
|
||||
local f18_local1 = f18_local0:GetContentOffset( LUI.DIRECTION.vertical )
|
||||
f18_local0:SetFocusedPosition( {
|
||||
x = 0,
|
||||
y = f18_local1
|
||||
}, true )
|
||||
local f18_local2 = f18_local0:GetElementAtPosition( 0, f18_local1 )
|
||||
if f18_local2 then
|
||||
f18_local2:processEvent( {
|
||||
name = "gain_focus",
|
||||
controllerIndex = f17_arg1
|
||||
} )
|
||||
end
|
||||
end )
|
||||
end
|
||||
|
||||
function ModSelectMenu( menu, controller )
|
||||
local self = LUI.UIElement.new()
|
||||
self.id = "ModSelectMenu"
|
||||
|
||||
local f20_local1 = controller and controller.controllerIndex
|
||||
if not f20_local1 and not Engine.InFrontend() then
|
||||
f20_local1 = self:getRootController()
|
||||
end
|
||||
assert( f20_local1 )
|
||||
|
||||
self:playSound( "menu_open" )
|
||||
|
||||
if Engine.IsSingleplayer() then
|
||||
local Background = nil
|
||||
|
||||
Background = LUI.UIImage.new()
|
||||
Background.id = "Background"
|
||||
Background:setImage( RegisterMaterial( "sp_frontend_bink_background" ), 0 )
|
||||
self:addElement( Background )
|
||||
self.Background = Background
|
||||
|
||||
local Bink = nil
|
||||
|
||||
Bink = LUI.UIImage.new()
|
||||
Bink.id = "Bink"
|
||||
Bink:setImage( RegisterMaterial( "cinematic" ), 0 )
|
||||
self:addElement( Bink )
|
||||
self.Bink = Bink
|
||||
end
|
||||
|
||||
local ButtonHelperBar = nil
|
||||
|
||||
ButtonHelperBar = MenuBuilder.BuildRegisteredType( "ButtonHelperBar", {
|
||||
controllerIndex = f61_local1
|
||||
} )
|
||||
ButtonHelperBar.id = "ButtonHelperBar"
|
||||
ButtonHelperBar:SetAnchorsAndPosition( 0, 0, 1, 0, 0, 0, _1080p * -85, 0 )
|
||||
self:addElement( ButtonHelperBar )
|
||||
self.ButtonHelperBar = ButtonHelperBar
|
||||
|
||||
MenuTitle = MenuBuilder.BuildRegisteredType( "MenuTitle", {
|
||||
controllerIndex = f61_local1
|
||||
} )
|
||||
MenuTitle.id = "MenuTitle"
|
||||
MenuTitle.MenuTitle:setText( ToUpperCase( Engine.Localize( "LUA_MENU_MODS" ) ), 0 )
|
||||
--MenuTitle.MenuTitle:setText( ToUpperCase( "Mods" ), 0 )
|
||||
MenuTitle.MenuBreadcrumbs:setText( ToUpperCase( "" ), 0 )
|
||||
MenuTitle.Icon:SetTop( _1080p * -28.5, 0 )
|
||||
MenuTitle.Icon:SetBottom( _1080p * 61.5, 0 )
|
||||
MenuTitle:SetAnchorsAndPosition( 0, 1, 0, 1, _1080p * 96, _1080p * 1056, _1080p * 54, _1080p * 134 )
|
||||
self:addElement( MenuTitle )
|
||||
self.MenuTitle = MenuTitle
|
||||
|
||||
local ModInfoTitle = nil
|
||||
|
||||
ModInfoTitle = LUI.UIStyledText.new()
|
||||
ModInfoTitle.id = "ModInfoTitle"
|
||||
ModInfoTitle:setText( "", 0 )
|
||||
ModInfoTitle:SetFontSize( 30 * _1080p )
|
||||
ModInfoTitle:SetFont( FONTS.GetFont( FONTS.MainMedium.File ) )
|
||||
ModInfoTitle:SetAlignment( LUI.Alignment.Left )
|
||||
ModInfoTitle:SetStartupDelay( 2000 )
|
||||
ModInfoTitle:SetLineHoldTime( 400 )
|
||||
ModInfoTitle:SetAnimMoveTime( 300 )
|
||||
ModInfoTitle:SetEndDelay( 1500 )
|
||||
ModInfoTitle:SetCrossfadeTime( 750 )
|
||||
ModInfoTitle:SetAutoScrollStyle( LUI.UIStyledText.AutoScrollStyle.ScrollH )
|
||||
ModInfoTitle:SetMaxVisibleLines( 1 )
|
||||
ModInfoTitle:SetDecodeLetterLength( 15 )
|
||||
ModInfoTitle:SetDecodeMaxRandChars( 6 )
|
||||
ModInfoTitle:SetDecodeUpdatesPerLetter( 4 )
|
||||
ModInfoTitle:SetAnchorsAndPosition( 0, 1, 0, 1, _1080p * 1254, _1080p * 1824, _1080p * 216, _1080p * 246 )
|
||||
self:addElement( ModInfoTitle )
|
||||
self.ModInfoTitle = ModInfoTitle
|
||||
|
||||
local ModInfoText = nil
|
||||
|
||||
ModInfoText = LUI.UIStyledText.new()
|
||||
ModInfoText.id = "ModInfoText"
|
||||
ModInfoText:setText( "", 0 )
|
||||
ModInfoText:SetFontSize( 20 * _1080p )
|
||||
ModInfoText:SetFont( FONTS.GetFont( FONTS.MainCondensed.File ) )
|
||||
ModInfoText:SetAlignment( LUI.Alignment.Left )
|
||||
ModInfoText:SetAnchorsAndPosition( 0, 1, 0, 1, _1080p * 1254, _1080p * 1824, _1080p * 248, _1080p * 268 )
|
||||
self:addElement( ModInfoText )
|
||||
self.ModInfoText = ModInfoText
|
||||
|
||||
local ModSelectionList = nil
|
||||
|
||||
ModSelectionList = LUI.UIDataSourceGrid.new( nil, {
|
||||
maxVisibleColumns = 1,
|
||||
maxVisibleRows = 17,
|
||||
controllerIndex = f20_local1,
|
||||
buildChild = function ()
|
||||
return MenuBuilder.BuildRegisteredType( "ModSelectButton", {
|
||||
controllerIndex = f20_local1
|
||||
} )
|
||||
end,
|
||||
wrapX = true,
|
||||
wrapY = true,
|
||||
spacingX = _1080p * 10,
|
||||
spacingY = _1080p * 10,
|
||||
columnWidth = _1080p * 500,
|
||||
rowHeight = _1080p * 30,
|
||||
scrollingThresholdX = 1,
|
||||
scrollingThresholdY = 1,
|
||||
adjustSizeToContent = false,
|
||||
horizontalAlignment = LUI.Alignment.Left,
|
||||
verticalAlignment = LUI.Alignment.Top,
|
||||
springCoefficient = 600,
|
||||
maxVelocity = 5000
|
||||
} )
|
||||
ModSelectionList.id = "ModSelectionList"
|
||||
ModSelectionList:setUseStencil( false )
|
||||
ModSelectionList:SetAnchorsAndPosition( 0, 1, 0, 1, _1080p * 130, _1080p * 630, _1080p * 216, _1080p * 886 )
|
||||
self:addElement( ModSelectionList )
|
||||
self.ModSelectionList = ModSelectionList
|
||||
|
||||
local ArrowUp = nil
|
||||
|
||||
ArrowUp = MenuBuilder.BuildRegisteredType( "ArrowUp", {
|
||||
controllerIndex = f20_local1
|
||||
} )
|
||||
ArrowUp.id = "ArrowUp"
|
||||
ArrowUp:SetAnchorsAndPosition( 0, 1, 0, 1, _1080p * 452.5, _1080p * 472.5, _1080p * 887, _1080p * 927 )
|
||||
self:addElement( ArrowUp )
|
||||
self.ArrowUp = ArrowUp
|
||||
|
||||
local ArrowDown = nil
|
||||
|
||||
ArrowDown = MenuBuilder.BuildRegisteredType( "ArrowDown", {
|
||||
controllerIndex = f20_local1
|
||||
} )
|
||||
ArrowDown.id = "ArrowDown"
|
||||
ArrowDown:SetAnchorsAndPosition( 0, 1, 0, 1, _1080p * 287.5, _1080p * 307.5, _1080p * 886, _1080p * 926 )
|
||||
self:addElement( ArrowDown )
|
||||
self.ArrowDown = ArrowDown
|
||||
|
||||
local ListCount = nil
|
||||
|
||||
ListCount = LUI.UIText.new()
|
||||
ListCount.id = "ListCount"
|
||||
ListCount:setText( "1/15", 0 )
|
||||
ListCount:SetFontSize( 24 * _1080p )
|
||||
ListCount:SetFont( FONTS.GetFont( FONTS.MainMedium.File ) )
|
||||
ListCount:SetAlignment( LUI.Alignment.Center )
|
||||
ListCount:SetAnchorsAndPosition( 0, 1, 0, 1, _1080p * 307.5, _1080p * 452.5, _1080p * 894, _1080p * 918 )
|
||||
self:addElement( ListCount )
|
||||
self.ListCount = ListCount
|
||||
|
||||
local LoadedModName = nil
|
||||
|
||||
LoadedModName = LUI.UIText.new()
|
||||
LoadedModName.id = "LoadedModName"
|
||||
LoadedModName:setText( "LOADED MOD NAME", 0 )
|
||||
LoadedModName:SetFontSize( 20 * _1080p )
|
||||
LoadedModName:SetFont( FONTS.GetFont( FONTS.MainBold.File ) )
|
||||
LoadedModName:SetAlignment( LUI.Alignment.Left )
|
||||
LoadedModName:SetAnchorsAndPosition( 0, 1, 0, 1, _1080p * 130, _1080p * 630, _1080p * 942, _1080p * 966 )
|
||||
self:addElement( LoadedModName )
|
||||
self.LoadedModName = LoadedModName
|
||||
|
||||
ModSelectionList:AddArrow( ArrowUp )
|
||||
ModSelectionList:AddArrow( ArrowDown )
|
||||
ModSelectionList:AddItemNumbers( ListCount )
|
||||
|
||||
self.addButtonHelperFunction = function ( arg0, arg1 )
|
||||
arg0:AddButtonHelperText( {
|
||||
helper_text = Engine.Localize( "MENU_BACK" ),
|
||||
button_ref = "button_secondary",
|
||||
side = "left",
|
||||
clickable = true
|
||||
} )
|
||||
local fs_game = Engine.GetDvarString( "fs_game" )
|
||||
if fs_game ~= "" then
|
||||
arg0:AddButtonHelperText( {
|
||||
helper_text = Engine.Localize( "LUA_MENU_UNLOAD" ),
|
||||
button_ref = "button_alt2",
|
||||
side = "left",
|
||||
clickable = true
|
||||
} )
|
||||
end
|
||||
end
|
||||
|
||||
self:addEventHandler( "menu_create", self.addButtonHelperFunction )
|
||||
|
||||
local bindButton = LUI.UIBindButton.new()
|
||||
bindButton.id = "selfBindButton"
|
||||
self:addElement( bindButton )
|
||||
self.bindButton = bindButton
|
||||
|
||||
PostLoadFunc( self, f20_local1, controller )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
MenuBuilder.registerType( "ModSelectMenu", ModSelectMenu )
|
||||
LUI.FlowManager.RegisterStackPushBehaviour( "ModSelectMenu", PushFunc )
|
||||
LUI.FlowManager.RegisterStackPopBehaviour( "ModSelectMenu", f0_local1 )
|
6
data/cdata/ui_scripts/Mods/__init__.lua
Normal file
6
data/cdata/ui_scripts/Mods/__init__.lua
Normal file
@ -0,0 +1,6 @@
|
||||
require( "ModSelectButton" )
|
||||
require( "ModSelectMenu" )
|
||||
|
||||
if (Engine.InFrontend()) then
|
||||
require("ModDownload")
|
||||
end
|
@ -1 +0,0 @@
|
||||
print("test")
|
BIN
data/cdata/zone/iw7mod_code_post_gfx.ff
Normal file
BIN
data/cdata/zone/iw7mod_code_post_gfx.ff
Normal file
Binary file not shown.
@ -439,7 +439,7 @@ namespace command
|
||||
client_command_mp_hook.create(0x140B105D0, &client_command_mp);
|
||||
client_command_sp_hook.create(0x140483130, &client_command_sp);
|
||||
|
||||
parse_commandline_hook.create(0x140F2F67B, parse_commandline);
|
||||
parse_commandline_hook.create(0x140C039F0, parse_commandline); // SL_Init
|
||||
|
||||
add_commands();
|
||||
}
|
||||
|
254
src/client/component/download.cpp
Normal file
254
src/client/component/download.cpp
Normal file
@ -0,0 +1,254 @@
|
||||
#include <std_include.hpp>
|
||||
#include "loader/component_loader.hpp"
|
||||
|
||||
#include "download.hpp"
|
||||
#include "console/console.hpp"
|
||||
#include "scheduler.hpp"
|
||||
#include "party.hpp"
|
||||
|
||||
#include "game/ui_scripting/execution.hpp"
|
||||
|
||||
#include "utils/hash.hpp"
|
||||
|
||||
#include <utils/concurrency.hpp>
|
||||
#include <utils/http.hpp>
|
||||
#include <utils/io.hpp>
|
||||
#include <utils/cryptography.hpp>
|
||||
|
||||
namespace download
|
||||
{
|
||||
namespace
|
||||
{
|
||||
struct globals_t
|
||||
{
|
||||
bool abort{};
|
||||
bool active{};
|
||||
};
|
||||
|
||||
std::atomic_bool kill_downloads = false;
|
||||
utils::concurrency::container<globals_t> globals;
|
||||
|
||||
bool download_aborted()
|
||||
{
|
||||
if (kill_downloads)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return globals.access<bool>([](globals_t& globals_)
|
||||
{
|
||||
return globals_.abort;
|
||||
});
|
||||
}
|
||||
|
||||
void mark_unactive()
|
||||
{
|
||||
globals.access([](globals_t& globals_)
|
||||
{
|
||||
globals_.active = false;
|
||||
});
|
||||
}
|
||||
|
||||
void mark_active()
|
||||
{
|
||||
globals.access([](globals_t& globals_)
|
||||
{
|
||||
globals_.active = true;
|
||||
});
|
||||
}
|
||||
|
||||
bool download_active()
|
||||
{
|
||||
return globals.access<bool>([](globals_t& globals_)
|
||||
{
|
||||
return globals_.active;
|
||||
});
|
||||
}
|
||||
|
||||
auto last_update = std::chrono::high_resolution_clock::now();
|
||||
int progress_callback(size_t total, size_t progress)
|
||||
{
|
||||
const auto now = std::chrono::high_resolution_clock::now();
|
||||
if (now - last_update > 20ms)
|
||||
{
|
||||
last_update = std::chrono::high_resolution_clock::now();
|
||||
auto fraction = 0.f;
|
||||
if (total > 0)
|
||||
{
|
||||
fraction = static_cast<float>(static_cast<double>(progress) /
|
||||
static_cast<double>(total));
|
||||
}
|
||||
|
||||
scheduler::once([=]
|
||||
{
|
||||
ui_scripting::notify("mod_download_progress",
|
||||
{
|
||||
{"fraction", fraction},
|
||||
});
|
||||
}, scheduler::pipeline::lui);
|
||||
}
|
||||
|
||||
//console::debug("Download progress: %lli/%lli\n", progress, total);
|
||||
if (download_aborted())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void menu_error(const std::string& error)
|
||||
{
|
||||
throw std::runtime_error(error);
|
||||
}
|
||||
}
|
||||
|
||||
void start_download(const game::netadr_s& target, const utils::info_string& info, const std::vector<file_t>& files)
|
||||
{
|
||||
if (download_active())
|
||||
{
|
||||
scheduler::schedule([=]
|
||||
{
|
||||
if (!download_active())
|
||||
{
|
||||
start_download(target, info, files);
|
||||
return scheduler::cond_end;
|
||||
}
|
||||
|
||||
return scheduler::cond_continue;
|
||||
}, scheduler::pipeline::main);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
globals.access([&](globals_t& globals_)
|
||||
{
|
||||
globals_ = {};
|
||||
});
|
||||
|
||||
const auto base = info.get("sv_wwwBaseUrl");
|
||||
if (base.empty())
|
||||
{
|
||||
menu_error("Download failed: Server doesn't have 'sv_wwwBaseUrl' dvar set.");
|
||||
return;
|
||||
}
|
||||
|
||||
scheduler::once([]
|
||||
{
|
||||
ui_scripting::notify("mod_download_start", {});
|
||||
}, scheduler::pipeline::lui);
|
||||
|
||||
scheduler::once([=]
|
||||
{
|
||||
{
|
||||
const auto _0 = gsl::finally(&mark_unactive);
|
||||
mark_active();
|
||||
|
||||
if (download_aborted())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto& file : files)
|
||||
{
|
||||
scheduler::once([=]
|
||||
{
|
||||
const ui_scripting::table data_table{};
|
||||
data_table.set("name", file.name.data());
|
||||
|
||||
ui_scripting::notify("mod_download_set_file",
|
||||
{
|
||||
{"request", data_table}
|
||||
});
|
||||
}, scheduler::pipeline::lui);
|
||||
|
||||
const auto url = utils::string::va("%s/%s", base.data(), file.name.data());
|
||||
console::debug("Downloading %s from %s: %s\n", file.name.data(), base.data(), url);
|
||||
auto data = utils::http::get_data(url, {}, {}, &progress_callback);
|
||||
if (!data.has_value())
|
||||
{
|
||||
menu_error(utils::string::va("Download failed: An unknown error occurred when getting data from '%s', please try again.", url));
|
||||
return;
|
||||
}
|
||||
|
||||
if (download_aborted())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto& result = data.value();
|
||||
if (result.code != CURLE_OK)
|
||||
{
|
||||
if (result.code == CURLE_COULDNT_CONNECT)
|
||||
{
|
||||
menu_error(utils::string::va("Download failed: Couldn't connect to server '%s' (%i)\n",
|
||||
url, result.code));
|
||||
return;
|
||||
}
|
||||
|
||||
menu_error(utils::string::va("Download failed: %s (%i)\n",
|
||||
curl_easy_strerror(result.code), result.code));
|
||||
return;
|
||||
}
|
||||
|
||||
if (result.response_code >= 400)
|
||||
{
|
||||
menu_error(utils::string::va("Download failed: Server returned bad response code (%i)\n",
|
||||
result.response_code));
|
||||
return;
|
||||
}
|
||||
|
||||
const auto hash = utils::hash::get_buffer_hash(result.buffer, file.name);
|
||||
if (hash != file.hash)
|
||||
{
|
||||
menu_error(utils::string::va("Download failed: File hash doesn't match the server's (%s: %s != %s)\n",
|
||||
file.name.data(), hash.data(), file.hash.data()));
|
||||
return;
|
||||
}
|
||||
|
||||
utils::io::write_file(file.name, result.buffer, false);
|
||||
}
|
||||
}
|
||||
|
||||
scheduler::once([]
|
||||
{
|
||||
ui_scripting::notify("mod_download_done", {});
|
||||
}, scheduler::pipeline::lui);
|
||||
|
||||
scheduler::once([target]
|
||||
{
|
||||
party::connect(target);
|
||||
}, scheduler::pipeline::main);
|
||||
}, scheduler::pipeline::async);
|
||||
}
|
||||
|
||||
void stop_download()
|
||||
{
|
||||
if (!download_active())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
globals.access([&](globals_t& globals_)
|
||||
{
|
||||
globals_.abort = true;
|
||||
});
|
||||
|
||||
scheduler::once([]
|
||||
{
|
||||
ui_scripting::notify("mod_download_done", {});
|
||||
game::shared::menu_error("Download failed: Aborted");
|
||||
}, scheduler::pipeline::lui);
|
||||
}
|
||||
|
||||
class component final : public component_interface
|
||||
{
|
||||
public:
|
||||
void pre_destroy() override
|
||||
{
|
||||
kill_downloads = true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
REGISTER_COMPONENT(download::component)
|
17
src/client/component/download.hpp
Normal file
17
src/client/component/download.hpp
Normal file
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include "game/game.hpp"
|
||||
|
||||
#include <utils/info_string.hpp>
|
||||
|
||||
namespace download
|
||||
{
|
||||
struct file_t
|
||||
{
|
||||
std::string name;
|
||||
std::string hash;
|
||||
};
|
||||
|
||||
void start_download(const game::netadr_s& target, const utils::info_string& info, const std::vector<file_t>& files);
|
||||
void stop_download();
|
||||
}
|
@ -175,21 +175,6 @@ namespace fastfiles
|
||||
}
|
||||
|
||||
void load_fastfiles1_stub(game::XZoneInfo* zoneInfo, unsigned int zoneCount, game::DBSyncMode syncMode)
|
||||
{
|
||||
std::vector<game::XZoneInfo> data;
|
||||
merge(&data, zoneInfo, zoneCount);
|
||||
|
||||
// mod is loaded on map start
|
||||
|
||||
if (fastfiles::exists("mod"))
|
||||
{
|
||||
data.push_back({ "mod", game::DB_ZONE_GAME | game::DB_ZONE_CUSTOM, 0 });
|
||||
}
|
||||
|
||||
game::DB_LoadXAssets(data.data(), static_cast<std::uint32_t>(data.size()), syncMode);
|
||||
}
|
||||
|
||||
void load_fastfiles2_stub(game::XZoneInfo* zoneInfo, unsigned int zoneCount, game::DBSyncMode syncMode)
|
||||
{
|
||||
std::vector<game::XZoneInfo> data;
|
||||
merge(&data, zoneInfo, zoneCount);
|
||||
@ -222,6 +207,26 @@ namespace fastfiles
|
||||
add_zone("iw7mod_ui_mp", game::DB_ZONE_UI | game::DB_ZONE_CUSTOM, 0);
|
||||
}
|
||||
|
||||
add_zone("mod", game::DB_ZONE_GLOBAL_TIER1 | game::DB_ZONE_CUSTOM, 1);
|
||||
|
||||
game::DB_LoadXAssets(data.data(), static_cast<std::uint32_t>(data.size()), syncMode);
|
||||
}
|
||||
|
||||
void load_fastfiles2_stub(game::XZoneInfo* zoneInfo, unsigned int zoneCount, game::DBSyncMode syncMode)
|
||||
{
|
||||
std::vector<game::XZoneInfo> data;
|
||||
merge(&data, zoneInfo, zoneCount);
|
||||
|
||||
const auto add_zone = [&](const char* name)
|
||||
{
|
||||
if (fastfiles::exists(name))
|
||||
{
|
||||
data.push_back({ name, game::DB_ZONE_PERMANENT | game::DB_ZONE_CUSTOM, 0 });
|
||||
}
|
||||
};
|
||||
|
||||
add_zone("iw7mod_code_post_gfx");
|
||||
|
||||
game::DB_LoadXAssets(data.data(), static_cast<std::uint32_t>(data.size()), syncMode);
|
||||
}
|
||||
}
|
||||
@ -326,10 +331,10 @@ namespace fastfiles
|
||||
sys_createfile_hook.create(game::Sys_CreateFile, sys_create_file_stub);
|
||||
|
||||
// Add custom zones in fastfiles load
|
||||
// (level specific) (mod)
|
||||
utils::hook::call(0x1403B9E9F, load_fastfiles1_stub);
|
||||
// (global,common)
|
||||
utils::hook::call(0x1405ADB63, load_fastfiles2_stub);
|
||||
utils::hook::call(0x1405ADB63, load_fastfiles1_stub);
|
||||
// (code_post_gfx)
|
||||
utils::hook::call(0x140E0624B, load_fastfiles2_stub);
|
||||
|
||||
command::add("loadzone", [](const command::params& params)
|
||||
{
|
||||
|
@ -13,24 +13,72 @@
|
||||
#include "profile_infos.hpp"
|
||||
#include "scheduler.hpp"
|
||||
#include "server_list.hpp"
|
||||
#include "download.hpp"
|
||||
|
||||
#include "utils/hash.hpp"
|
||||
|
||||
#include <utils/string.hpp>
|
||||
#include <utils/info_string.hpp>
|
||||
#include <utils/hook.hpp>
|
||||
#include <utils/cryptography.hpp>
|
||||
#include <utils/io.hpp>
|
||||
|
||||
namespace party
|
||||
{
|
||||
namespace
|
||||
{
|
||||
/*struct moddl_file
|
||||
std::string get_dvar_string(const std::string& dvar)
|
||||
{
|
||||
auto* dvar_value = game::Dvar_FindVar(dvar.data());
|
||||
if (dvar_value && dvar_value->current.string)
|
||||
{
|
||||
return dvar_value->current.string;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
int get_dvar_int(const std::string& dvar)
|
||||
{
|
||||
auto* dvar_value = game::Dvar_FindVar(dvar.data());
|
||||
if (dvar_value && dvar_value->current.integer)
|
||||
{
|
||||
return dvar_value->current.integer;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool get_dvar_bool(const std::string& dvar)
|
||||
{
|
||||
auto* dvar_value = game::Dvar_FindVar(dvar.data());
|
||||
if (dvar_value && dvar_value->current.enabled)
|
||||
{
|
||||
return dvar_value->current.enabled;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
namespace mods
|
||||
{
|
||||
void set_mod(const std::string& path, bool [[maybe_unused]] change_fs_game = false)
|
||||
{
|
||||
game::Dvar_SetFromStringByName("fs_game", path.data(), game::DvarSetSource::DVAR_SOURCE_INTERNAL);
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
struct fastdl_file
|
||||
{
|
||||
std::string extension;
|
||||
std::string name;
|
||||
bool optional;
|
||||
};
|
||||
|
||||
std::vector<moddl_file> mod_files =
|
||||
std::vector<fastdl_file> mod_files =
|
||||
{
|
||||
{".ff", "mod_hash", false},
|
||||
};
|
||||
@ -137,7 +185,108 @@ namespace party
|
||||
}
|
||||
|
||||
return needs_restart;
|
||||
}
|
||||
|
||||
/*std::string get_whitelist_json_path()
|
||||
{
|
||||
return (utils::properties::get_appdata_path() / "whitelist.json").generic_string();
|
||||
}
|
||||
|
||||
nlohmann::json get_whitelist_json_object()
|
||||
{
|
||||
std::string data;
|
||||
if (!utils::io::read_file(get_whitelist_json_path(), &data))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nlohmann::json obj;
|
||||
try
|
||||
{
|
||||
obj = nlohmann::json::parse(data.data());
|
||||
}
|
||||
catch (const nlohmann::json::parse_error& ex)
|
||||
{
|
||||
game::shared::menu_error(utils::string::va("%s\n", ex.what()));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
std::string target_ip_to_string(const game::netadr_s& target)
|
||||
{
|
||||
return utils::string::va("%i.%i.%i.%i",
|
||||
static_cast<int>(saved_info_response.host.ip[0]),
|
||||
static_cast<int>(saved_info_response.host.ip[1]),
|
||||
static_cast<int>(saved_info_response.host.ip[2]),
|
||||
static_cast<int>(saved_info_response.host.ip[3]));
|
||||
}
|
||||
|
||||
bool should_user_confirm(const game::netadr_s& target)
|
||||
{
|
||||
nlohmann::json obj = get_whitelist_json_object();
|
||||
if (obj != nullptr)
|
||||
{
|
||||
const auto target_ip = target_ip_to_string(target);
|
||||
for (const auto& [key, value] : obj.items())
|
||||
{
|
||||
if (value.is_string() && value.get<std::string>() == target_ip)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//close_joining_popups();
|
||||
command::execute("lui_open_popup popup_confirmdownload", false);
|
||||
|
||||
return true;
|
||||
}*/
|
||||
|
||||
bool needs_vid_restart = false;
|
||||
|
||||
bool download_files(const game::netadr_s& target, const utils::info_string& info, bool allow_download)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::vector<download::file_t> files{};
|
||||
|
||||
const auto needs_restart = check_download_mod(info, files);
|
||||
needs_vid_restart = needs_vid_restart || needs_restart;
|
||||
|
||||
if (files.size() > 0)
|
||||
{
|
||||
if (!allow_download/* && should_user_confirm(target)*/)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
download::stop_download();
|
||||
download::start_download(target, info, files);
|
||||
return true;
|
||||
}
|
||||
else if (needs_restart || needs_vid_restart)
|
||||
{
|
||||
command::execute("vid_restart");
|
||||
needs_vid_restart = false;
|
||||
scheduler::once([=]()
|
||||
{
|
||||
//mods::read_stats();
|
||||
connect(target);
|
||||
}, scheduler::pipeline::main);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
command::execute("luiLeaveMenu AcceptingInvite", true);
|
||||
game::shared::menu_error(e.what());
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
@ -217,39 +366,6 @@ namespace party
|
||||
false);
|
||||
}
|
||||
|
||||
std::string get_dvar_string(const std::string& dvar)
|
||||
{
|
||||
auto* dvar_value = game::Dvar_FindVar(dvar.data());
|
||||
if (dvar_value && dvar_value->current.string)
|
||||
{
|
||||
return dvar_value->current.string;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
int get_dvar_int(const std::string& dvar)
|
||||
{
|
||||
auto* dvar_value = game::Dvar_FindVar(dvar.data());
|
||||
if (dvar_value && dvar_value->current.integer)
|
||||
{
|
||||
return dvar_value->current.integer;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool get_dvar_bool(const std::string& dvar)
|
||||
{
|
||||
auto* dvar_value = game::Dvar_FindVar(dvar.data());
|
||||
if (dvar_value && dvar_value->current.enabled)
|
||||
{
|
||||
return dvar_value->current.enabled;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void com_gamestart_beginclient_stub(const char* mapname, const char* gametype, char a3)
|
||||
{
|
||||
if (preloaded_map)
|
||||
@ -284,6 +400,13 @@ namespace party
|
||||
{
|
||||
profile_infos::xuid::clear_xuids();
|
||||
|
||||
hash_cache.clear();
|
||||
|
||||
if (game::environment::is_dedi())
|
||||
{
|
||||
generate_hashes(map);
|
||||
}
|
||||
|
||||
preloaded_map = map_is_preloaded;
|
||||
sv_start_map_for_party_hook.invoke<void>(map, game_type, client_count, agent_count, hardcore, map_is_preloaded, migrate);
|
||||
}
|
||||
@ -448,7 +571,7 @@ namespace party
|
||||
|
||||
void connect(const game::netadr_s& target)
|
||||
{
|
||||
command::execute("luiOpenPopup AcceptingInvite", false);
|
||||
command::execute("luiOpenPopup AcceptingInvite", true);
|
||||
|
||||
profile_infos::xuid::clear_xuids();
|
||||
profile_infos::clear_profile_infos();
|
||||
@ -462,9 +585,14 @@ namespace party
|
||||
|
||||
void info_response_error(const std::string& error)
|
||||
{
|
||||
console::error("%s\n", error.data());
|
||||
command::execute("luiLeaveMenu AcceptingInvite", false);
|
||||
game::Com_SetLocalizedErrorMessage(error.data(), "MENU_NOTICE");
|
||||
command::execute("luiLeaveMenu AcceptingInvite", true);
|
||||
|
||||
game::shared::menu_error(error);
|
||||
}
|
||||
|
||||
void clear_sv_motd()
|
||||
{
|
||||
server_connection_state.motd.clear();
|
||||
}
|
||||
|
||||
connection_state get_server_connection_state()
|
||||
@ -731,7 +859,7 @@ namespace party
|
||||
info.set("sv_discordImageUrl", get_dvar_string("sv_discordImageUrl"));
|
||||
info.set("sv_discordImageText", get_dvar_string("sv_discordImageText"));
|
||||
|
||||
/*const auto fs_game = get_dvar_string("fs_game");
|
||||
const auto fs_game = get_dvar_string("fs_game");
|
||||
info.set("fs_game", fs_game);
|
||||
|
||||
if (!fs_game.empty())
|
||||
@ -742,7 +870,7 @@ namespace party
|
||||
fs_game.data(), file.extension.data()));
|
||||
info.set(file.name, hash);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
network::send(target, "infoResponse", info.build(), '\n');
|
||||
});
|
||||
@ -819,12 +947,11 @@ namespace party
|
||||
}
|
||||
|
||||
server_connection_state.base_url = info.get("sv_wwwBaseUrl");
|
||||
/*
|
||||
if (download_files(target, info, false))
|
||||
|
||||
if (download_files(target, info, true))
|
||||
{
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
server_connection_state.motd = info.get("sv_motd");
|
||||
server_connection_state.max_clients = std::stoi(sv_maxclients_str);
|
||||
|
@ -10,7 +10,7 @@ namespace party
|
||||
bool hostDefined;
|
||||
std::string motd;
|
||||
int max_clients;
|
||||
std::string base_url; // yk, for when we need it ;)
|
||||
std::string base_url;
|
||||
};
|
||||
|
||||
struct discord_information
|
||||
|
@ -24,8 +24,6 @@ namespace scripting
|
||||
std::unordered_map<std::string, std::vector<std::pair<std::string, const char*>>> script_function_table_sort;
|
||||
std::unordered_map<const char*, std::pair<std::string, std::string>> script_function_table_rev;
|
||||
|
||||
utils::concurrency::container<shared_table_t> shared_table;
|
||||
|
||||
std::string current_file;
|
||||
|
||||
namespace
|
||||
|
@ -3,15 +3,11 @@
|
||||
|
||||
namespace scripting
|
||||
{
|
||||
using shared_table_t = std::unordered_map<std::string, std::string>;
|
||||
|
||||
extern std::unordered_map<int, std::unordered_map<std::string, int>> fields_table;
|
||||
extern std::unordered_map<std::string, std::unordered_map<std::string, const char*>> script_function_table;
|
||||
extern std::unordered_map<std::string, std::vector<std::pair<std::string, const char*>>> script_function_table_sort;
|
||||
extern std::unordered_map<const char*, std::pair<std::string, std::string>> script_function_table_rev;
|
||||
|
||||
extern utils::concurrency::container<shared_table_t> shared_table;
|
||||
|
||||
extern std::string current_file;
|
||||
|
||||
void on_shutdown(const std::function<void(bool, bool)>& callback);
|
||||
|
@ -4,7 +4,6 @@
|
||||
#include "game/game.hpp"
|
||||
#include "game/dvars.hpp"
|
||||
|
||||
|
||||
#include "command.hpp"
|
||||
#include "console/console.hpp"
|
||||
#include "fastfiles.hpp"
|
||||
@ -15,6 +14,7 @@
|
||||
#include "scheduler.hpp"
|
||||
#include "scripting.hpp"
|
||||
#include "server_list.hpp"
|
||||
#include "download.hpp"
|
||||
|
||||
#include "game/ui_scripting/execution.hpp"
|
||||
//#include "game/scripting/execution.hpp"
|
||||
@ -30,6 +30,19 @@
|
||||
|
||||
namespace ui_scripting
|
||||
{
|
||||
namespace lua_calls
|
||||
{
|
||||
int64_t is_development_build_stub([[maybe_unused]] game::hks::lua_State* luaVM)
|
||||
{
|
||||
#if defined(DEV_BUILD) || defined(DEBUG)
|
||||
ui_scripting::push_value(true);
|
||||
#else
|
||||
ui_scripting::push_value(false);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
std::unordered_map<game::hks::cclosure*, std::function<arguments(const function_arguments& args)>> converted_functions;
|
||||
@ -170,60 +183,6 @@ namespace ui_scripting
|
||||
};
|
||||
*/
|
||||
|
||||
game_type["sharedset"] = [](const game&, const std::string& key, const std::string& value)
|
||||
{
|
||||
scripting::shared_table.access([key, value](scripting::shared_table_t& table)
|
||||
{
|
||||
table[key] = value;
|
||||
});
|
||||
};
|
||||
|
||||
game_type["sharedget"] = [](const game&, const std::string& key)
|
||||
{
|
||||
std::string result;
|
||||
scripting::shared_table.access([key, &result](scripting::shared_table_t& table)
|
||||
{
|
||||
result = table[key];
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
game_type["sharedclear"] = [](const game&)
|
||||
{
|
||||
scripting::shared_table.access([](scripting::shared_table_t& table)
|
||||
{
|
||||
table.clear();
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
game_type["assetlist"] = [](const game&, const std::string& type_string)
|
||||
{
|
||||
auto table_ = table();
|
||||
auto index = 1;
|
||||
auto type_index = -1;
|
||||
for (auto i = 0; i < ::game::XAssetType::ASSET_TYPE_COUNT; i++)
|
||||
{
|
||||
if (type_string == ::game::g_assetNames[i])
|
||||
{
|
||||
type_index = i;
|
||||
}
|
||||
}
|
||||
if (type_index == -1)
|
||||
{
|
||||
throw std::runtime_error("Asset type does not exist");
|
||||
}
|
||||
const auto type = static_cast<::game::XAssetType>(type_index);
|
||||
fastfiles::enum_assets(type, [type, &table_, &index](const ::game::XAssetHeader header)
|
||||
{
|
||||
const auto asset = ::game::XAsset{type, header};
|
||||
const std::string asset_name = ::game::DB_GetXAssetName(&asset);
|
||||
table_[index++] = asset_name;
|
||||
}, true);
|
||||
return table_;
|
||||
};
|
||||
*/
|
||||
|
||||
game_type["getcurrentgamelanguage"] = [](const game&)
|
||||
{
|
||||
return steam::SteamApps()->GetCurrentGameLanguage();
|
||||
@ -235,11 +194,35 @@ namespace ui_scripting
|
||||
material.data()));
|
||||
};
|
||||
|
||||
auto scheduler = table();
|
||||
lua["scheduler"] = scheduler;
|
||||
|
||||
scheduler["once"] = [](const function_argument& args)
|
||||
{
|
||||
scheduler::once([args]()
|
||||
{
|
||||
auto func = args.as<function>();
|
||||
func();
|
||||
}, scheduler::lui);
|
||||
};
|
||||
|
||||
auto server_list_table = table();
|
||||
lua["serverlist"] = server_list_table;
|
||||
|
||||
server_list_table["getplayercount"] = server_list::get_player_count;
|
||||
server_list_table["getservercount"] = server_list::get_server_count;
|
||||
|
||||
auto download_table = table();
|
||||
lua["download"] = download_table;
|
||||
|
||||
download_table["abort"] = download::stop_download;
|
||||
|
||||
//download_table["userdownloadresponse"] = party::user_download_response;
|
||||
//download_table["getwwwurl"] = []
|
||||
//{
|
||||
// const auto state = party::get_server_connection_state();
|
||||
// return state.base_url;
|
||||
//};
|
||||
}
|
||||
|
||||
void enable_globals()
|
||||
@ -311,10 +294,14 @@ namespace ui_scripting
|
||||
}
|
||||
}
|
||||
|
||||
void* hks_start_stub(char a1, char a2)
|
||||
int hks_start_stub()
|
||||
{
|
||||
const auto _0 = gsl::finally(&try_start);
|
||||
return hks_start_hook.invoke<void*>(a1, a2);
|
||||
auto result = hks_start_hook.invoke<int>();
|
||||
if (result)
|
||||
{
|
||||
try_start();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void hks_shutdown_stub()
|
||||
@ -458,8 +445,11 @@ namespace ui_scripting
|
||||
hks_load_hook.create(0x1411E0B00, hks_load_stub);
|
||||
|
||||
hks_package_require_hook.create(0x1411C7F00, hks_package_require_stub);
|
||||
hks_start_hook.create(0x140615090, hks_start_stub);
|
||||
hks_start_hook.create(0x1406023A0, hks_start_stub);
|
||||
hks_shutdown_hook.create(0x1406124B0, hks_shutdown_stub);
|
||||
|
||||
// replace LUA engine calls
|
||||
utils::hook::set(0x1414B4D98, lua_calls::is_development_build_stub); // IsDevelopmentBuild
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -133,7 +133,14 @@ namespace demonware
|
||||
|
||||
std::string bdStorage::get_user_file_path(const std::string& name)
|
||||
{
|
||||
return "iw7-mod/players2/user/" + name;
|
||||
const auto regular_path = "iw7-mod/players2/user/"s;
|
||||
static const auto fs_game = game::Dvar_FindVar("fs_game");
|
||||
if (fs_game && fs_game->current.string && *fs_game->current.string)
|
||||
{
|
||||
return regular_path + fs_game->current.string + "/" + name;
|
||||
}
|
||||
|
||||
return regular_path + name;
|
||||
}
|
||||
|
||||
void bdStorage::uploadAndValidateFiles(service_server* server, byte_buffer* buffer) const
|
||||
|
@ -25,15 +25,8 @@ namespace game
|
||||
{
|
||||
void client_println(int client_num, const std::string& text)
|
||||
{
|
||||
if (game::Com_GameMode_GetActiveGameMode() == game::GAME_MODE_SP)
|
||||
{
|
||||
game::CG_Utils_GameMessage(client_num, text.data(), 0); // why is nothing printed?
|
||||
}
|
||||
else
|
||||
{
|
||||
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
|
||||
utils::string::va("f \"%s\"", text.data()));
|
||||
}
|
||||
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
|
||||
utils::string::va("f \"%s\"", text.data()));
|
||||
}
|
||||
|
||||
bool cheats_ok(int client_num, bool print)
|
||||
@ -53,6 +46,12 @@ namespace game
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void menu_error(const std::string& error)
|
||||
{
|
||||
console::error("%s\n", error.data());
|
||||
game::Com_SetLocalizedErrorMessage(error.data(), "MENU_NOTICE");
|
||||
}
|
||||
}
|
||||
|
||||
int Cmd_Argc()
|
||||
|
@ -45,6 +45,7 @@ namespace game
|
||||
{
|
||||
void client_println(int client_num, const std::string& text);
|
||||
bool cheats_ok(int client_num = 0, bool print = false);
|
||||
void menu_error(const std::string& error);
|
||||
}
|
||||
|
||||
int Cmd_Argc();
|
||||
|
157
src/client/utils/hash.cpp
Normal file
157
src/client/utils/hash.cpp
Normal file
@ -0,0 +1,157 @@
|
||||
#include <std_include.hpp>
|
||||
|
||||
#include "game/game.hpp"
|
||||
|
||||
#include "hash.hpp"
|
||||
#include "component/console/console.hpp"
|
||||
|
||||
#include <zlib.h>
|
||||
#include <utils/cryptography.hpp>
|
||||
#include <utils/string.hpp>
|
||||
|
||||
namespace utils::hash
|
||||
{
|
||||
namespace
|
||||
{
|
||||
constexpr auto read_buffer_size = 1ull * 1024ull * 1024ull; // 1MB
|
||||
|
||||
std::string get_file_hash_pakfile(std::ifstream& file_stream, const std::size_t file_size,
|
||||
const std::string& filename)
|
||||
{
|
||||
if (file_size < sizeof(game::XPakHeader))
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
game::XPakHeader header{};
|
||||
file_stream.read(reinterpret_cast<char*>(&header), sizeof(game::XPakHeader));
|
||||
|
||||
constexpr auto hash_size = sizeof(game::DB_AuthHash);
|
||||
|
||||
game::DB_AuthHash empty_hash{};
|
||||
if (!std::memcmp(header.hash.bytes, empty_hash.bytes, hash_size))
|
||||
{
|
||||
console::warn("Computing pakfile hash because its missing, this may take some time...\n");
|
||||
|
||||
hash_state state;
|
||||
sha256_init(&state);
|
||||
|
||||
std::string buffer;
|
||||
buffer.resize(read_buffer_size);
|
||||
|
||||
auto bytes_to_read = file_size - sizeof(game::XPakHeader);
|
||||
while (bytes_to_read > 0)
|
||||
{
|
||||
const auto read_size = std::min(read_buffer_size, bytes_to_read);
|
||||
file_stream.read(buffer.data(), read_size);
|
||||
sha256_process(&state, reinterpret_cast<std::uint8_t*>(buffer.data()), static_cast<std::uint32_t>(read_size));
|
||||
bytes_to_read -= read_size;
|
||||
}
|
||||
|
||||
file_stream.close();
|
||||
|
||||
if (sha256_done(&state, header.hash.bytes) != CRYPT_OK)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
std::fstream out_stream;
|
||||
out_stream.open(filename, std::ios_base::binary | std::ios_base::out | std::ios_base::in);
|
||||
out_stream.write(reinterpret_cast<char*>(&header), sizeof(game::XPakHeader));
|
||||
}
|
||||
|
||||
const auto hash_str = std::string{header.hash.bytes, header.hash.bytes + hash_size};
|
||||
|
||||
return utils::string::dump_hex(hash_str, "");
|
||||
}
|
||||
|
||||
std::string get_file_hash_generic(std::ifstream& file_stream, const std::size_t file_size)
|
||||
{
|
||||
auto crc_value = crc32(0L, Z_NULL, 0);
|
||||
auto bytes_to_read = file_size;
|
||||
|
||||
std::string buffer;
|
||||
buffer.resize(read_buffer_size);
|
||||
|
||||
while (bytes_to_read > 0)
|
||||
{
|
||||
const auto read_size = std::min(bytes_to_read, read_buffer_size);
|
||||
file_stream.read(buffer.data(), read_size);
|
||||
crc_value = crc32(crc_value, reinterpret_cast<std::uint8_t*>(buffer.data()), static_cast<std::uint32_t>(read_size));
|
||||
bytes_to_read -= read_size;
|
||||
}
|
||||
|
||||
std::string hash;
|
||||
hash.append(reinterpret_cast<char*>(&crc_value), sizeof(crc_value));
|
||||
return utils::string::dump_hex(hash, "");
|
||||
}
|
||||
|
||||
std::string get_pakfile_buffer_hash(std::string& buffer)
|
||||
{
|
||||
if (buffer.size() < sizeof(game::XPakHeader))
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
constexpr auto hash_size = sizeof(game::DB_AuthHash);
|
||||
const auto header = reinterpret_cast<game::XPakHeader*>(buffer.data());
|
||||
|
||||
game::DB_AuthHash empty_hash{};
|
||||
if (!std::memcmp(header->hash.bytes, empty_hash.bytes, hash_size))
|
||||
{
|
||||
console::warn("Computing pakfile hash because its missing, this may take some time...\n");
|
||||
const auto hash_start = reinterpret_cast<std::uint8_t*>(buffer.data() + sizeof(game::XPakHeader));
|
||||
const auto len = buffer.size() - sizeof(game::XPakHeader);
|
||||
const auto hash = utils::cryptography::sha256::compute(hash_start, len, false);
|
||||
std::memcpy(header->hash.bytes, hash.data(), sizeof(header->hash));
|
||||
}
|
||||
|
||||
std::string hash = {header->hash.bytes, header->hash.bytes + hash_size};
|
||||
return utils::string::dump_hex(hash, "");
|
||||
}
|
||||
|
||||
std::string get_generic_buffer_hash(const std::string& buffer)
|
||||
{
|
||||
auto crc_value = crc32(0L, Z_NULL, 0);
|
||||
crc_value = crc32(crc_value, reinterpret_cast<const std::uint8_t*>(buffer.data()),
|
||||
static_cast<std::uint32_t>(buffer.size()));
|
||||
std::string hash;
|
||||
hash.append(reinterpret_cast<char*>(&crc_value), sizeof(crc_value));
|
||||
return utils::string::dump_hex(hash, "");
|
||||
}
|
||||
}
|
||||
|
||||
std::string get_file_hash(const std::string& file)
|
||||
{
|
||||
std::ifstream file_stream(file, std::ios::binary);
|
||||
if (!file_stream.is_open())
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
file_stream.seekg(0, std::ios::end);
|
||||
const auto file_size = static_cast<std::size_t>(file_stream.tellg());
|
||||
file_stream.seekg(0, std::ios::beg);
|
||||
|
||||
if (file.ends_with(".pak"))
|
||||
{
|
||||
return get_file_hash_pakfile(file_stream, file_size, file);
|
||||
}
|
||||
else
|
||||
{
|
||||
return get_file_hash_generic(file_stream, file_size);
|
||||
}
|
||||
}
|
||||
|
||||
std::string get_buffer_hash(std::string& buffer, const std::string& filename)
|
||||
{
|
||||
if (filename.ends_with(".pak"))
|
||||
{
|
||||
return get_pakfile_buffer_hash(buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
return get_generic_buffer_hash(buffer);
|
||||
}
|
||||
}
|
||||
}
|
7
src/client/utils/hash.hpp
Normal file
7
src/client/utils/hash.hpp
Normal file
@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
namespace utils::hash
|
||||
{
|
||||
std::string get_file_hash(const std::string& file);
|
||||
std::string get_buffer_hash(std::string& buffer, const std::string& filename);
|
||||
}
|
Loading…
Reference in New Issue
Block a user