diff --git a/OpenRA.Mods.RA/Widgets/Logic/MainMenuLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/MainMenuLogic.cs index 2aee8c1f08..43d78833cf 100644 --- a/OpenRA.Mods.RA/Widgets/Logic/MainMenuLogic.cs +++ b/OpenRA.Mods.RA/Widgets/Logic/MainMenuLogic.cs @@ -85,7 +85,12 @@ namespace OpenRA.Mods.RA.Widgets.Logic { "onStart", RemoveShellmapUI } }); }; - missionsButton.Disabled = !Game.modData.Manifest.Missions.Any(); + + var hasCampaign = Game.modData.Manifest.Missions.Any(); + var hasMissions = Game.modData.MapCache + .Any(p => p.Status == MapStatus.Available && p.Map.Type == "Mission" && !p.Map.Selectable); + + missionsButton.Disabled = !hasCampaign && !hasMissions; singleplayerMenu.Get("SKIRMISH_BUTTON").OnClick = StartSkirmishGame; diff --git a/OpenRA.Mods.RA/Widgets/Logic/MissionBrowserLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/MissionBrowserLogic.cs index 96eff6bdb1..50ddbdee52 100644 --- a/OpenRA.Mods.RA/Widgets/Logic/MissionBrowserLogic.cs +++ b/OpenRA.Mods.RA/Widgets/Logic/MissionBrowserLogic.cs @@ -9,6 +9,7 @@ #endregion using System; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; @@ -29,6 +30,10 @@ namespace OpenRA.Mods.RA.Widgets.Logic readonly ButtonWidget stopVideoButton; readonly VqaPlayerWidget videoPlayer; + readonly ScrollPanelWidget missionList; + readonly ScrollItemWidget headerTemplate; + readonly ScrollItemWidget template; + MapPreview selectedMapPreview; bool showVideoPlayer; @@ -38,10 +43,10 @@ namespace OpenRA.Mods.RA.Widgets.Logic { this.onStart = onStart; - var missionList = widget.Get("MISSION_LIST"); + missionList = widget.Get("MISSION_LIST"); - var headerTemplate = widget.Get("HEADER"); - var template = widget.Get("TEMPLATE"); + headerTemplate = widget.Get("HEADER"); + template = widget.Get("TEMPLATE"); var title = widget.GetOrNull("MISSIONBROWSER_TITLE"); if (title != null) @@ -66,43 +71,42 @@ namespace OpenRA.Mods.RA.Widgets.Logic stopVideoButton.IsVisible = () => showVideoPlayer; stopVideoButton.OnClick = StopVideo; - var yaml = new MiniYaml(null, Game.modData.Manifest.Missions.Select(MiniYaml.FromFile).Aggregate(MiniYaml.MergeLiberal)).ToDictionary(); - + var allMaps = new List(); missionList.RemoveChildren(); - var selectedFirst = false; - foreach (var kv in yaml) + // Add a group for each campaign + if (Game.modData.Manifest.Missions.Any()) { - var header = ScrollItemWidget.Setup(headerTemplate, () => true, () => {}); - header.Get("LABEL").GetText = () => kv.Key; - missionList.AddChild(header); + var yaml = Game.modData.Manifest.Missions.Select(MiniYaml.FromFile).Aggregate(MiniYaml.MergeLiberal); - var missionMapPaths = kv.Value.Nodes.Select(n => Platform.ResolvePath(n.Key)); - - var maps = Game.modData.MapCache - .Where(p => p.Status == MapStatus.Available && missionMapPaths.Contains(Path.GetFullPath(p.Map.Path))) - .Select(p => p.Map); - - foreach (var m in maps) + foreach (var kv in yaml) { - var map = m; + var missionMapPaths = kv.Value.Nodes.Select(n => Path.GetFullPath(n.Key)); - var item = ScrollItemWidget.Setup(template, - () => selectedMapPreview != null && selectedMapPreview.Uid == map.Uid, - () => SelectMap(map), - StartMission); + var maps = Game.modData.MapCache + .Where(p => p.Status == MapStatus.Available && missionMapPaths.Contains(Path.GetFullPath(p.Map.Path))) + .Select(p => p.Map); - item.Get("TITLE").GetText = () => map.Title; - missionList.AddChild(item); - - if (!selectedFirst) - { - SelectMap(map); - selectedFirst = true; - } + CreateMissionGroup(kv.Key, maps); + allMaps.AddRange(maps); } } + // Add an additional group for loose missions + // Loose missions must define Type: Mission and Selectable: false. + var looseMissions = Game.modData.MapCache + .Where(p => p.Status == MapStatus.Available && p.Map.Type == "Mission" && !p.Map.Selectable && !allMaps.Contains(p.Map)) + .Select(p => p.Map); + + if (looseMissions.Any()) + { + CreateMissionGroup("Missions", looseMissions); + allMaps.AddRange(looseMissions); + } + + if (allMaps.Any()) + SelectMap(allMaps.First()); + widget.Get("STARTGAME_BUTTON").OnClick = StartMission; widget.Get("BACK_BUTTON").OnClick = () => @@ -114,6 +118,26 @@ namespace OpenRA.Mods.RA.Widgets.Logic }; } + void CreateMissionGroup(string title, IEnumerable maps) + { + var header = ScrollItemWidget.Setup(headerTemplate, () => true, () => {}); + header.Get("LABEL").GetText = () => title; + missionList.AddChild(header); + + foreach (var m in maps) + { + var map = m; + + var item = ScrollItemWidget.Setup(template, + () => selectedMapPreview != null && selectedMapPreview.Uid == map.Uid, + () => SelectMap(map), + StartMission); + + item.Get("TITLE").GetText = () => map.Title; + missionList.AddChild(item); + } + } + float cachedSoundVolume; float cachedMusicVolume; void SelectMap(Map map) diff --git a/mods/ra/missions.yaml b/mods/ra/missions.yaml index d557bdd945..9777f0d2cc 100644 --- a/mods/ra/missions.yaml +++ b/mods/ra/missions.yaml @@ -1,6 +1,3 @@ Allied Campaign: ./mods/ra/maps/allies-01-classic ./mods/ra/maps/allies-02-classic - -Missions: - ./mods/ra/maps/intervention