Merge pull request #10232 from penev92/modSupport
Implement mod loading from the support directory
This commit is contained in:
@@ -191,7 +191,7 @@ namespace OpenRA
|
||||
|
||||
public static void InitializeSettings(Arguments args)
|
||||
{
|
||||
Settings = new Settings(Platform.ResolvePath("^", "settings.yaml"), args);
|
||||
Settings = new Settings(Platform.ResolvePath(Path.Combine("^", "settings.yaml")), args);
|
||||
}
|
||||
|
||||
internal static void Initialize(Arguments args)
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace OpenRA
|
||||
}
|
||||
}
|
||||
|
||||
// Describes what is to be loaded in order to run a mod
|
||||
/// <summary> Describes what is to be loaded in order to run a mod. </summary>
|
||||
public class Manifest
|
||||
{
|
||||
public static readonly Dictionary<string, Manifest> AllMods = LoadMods();
|
||||
@@ -61,13 +61,16 @@ namespace OpenRA
|
||||
readonly TypeDictionary modules = new TypeDictionary();
|
||||
readonly Dictionary<string, MiniYaml> yaml;
|
||||
|
||||
public Manifest(string mod)
|
||||
public Manifest(string modId, string modPath = null)
|
||||
{
|
||||
var path = Platform.ResolvePath(".", "mods", mod, "mod.yaml");
|
||||
if (modPath == null)
|
||||
modPath = ModMetadata.CandidateModPaths[modId];
|
||||
|
||||
var path = Path.Combine(modPath, "mod.yaml");
|
||||
yaml = new MiniYaml(null, MiniYaml.FromFile(path)).ToDictionary();
|
||||
|
||||
Mod = FieldLoader.Load<ModMetadata>(yaml["Metadata"]);
|
||||
Mod.Id = mod;
|
||||
Mod.Id = modId;
|
||||
|
||||
// TODO: Use fieldloader
|
||||
Folders = YamlList(yaml, "Folders", true);
|
||||
@@ -106,12 +109,10 @@ namespace OpenRA
|
||||
RequiresMods = yaml["RequiresMods"].ToDictionary(my => my.Value);
|
||||
|
||||
// Allow inherited mods to import parent maps.
|
||||
var compat = new List<string>();
|
||||
compat.Add(mod);
|
||||
var compat = new List<string> { Mod.Id };
|
||||
|
||||
if (yaml.ContainsKey("SupportsMapsFrom"))
|
||||
foreach (var c in yaml["SupportsMapsFrom"].Value.Split(','))
|
||||
compat.Add(c.Trim());
|
||||
compat.AddRange(yaml["SupportsMapsFrom"].Value.Split(',').Select(c => c.Trim()));
|
||||
|
||||
MapCompatibility = compat.ToArray();
|
||||
|
||||
@@ -156,8 +157,10 @@ namespace OpenRA
|
||||
if (!yaml.ContainsKey(key))
|
||||
return new string[] { };
|
||||
|
||||
var list = yaml[key].ToDictionary().Keys.ToArray();
|
||||
return parsePaths ? list.Select(Platform.ResolvePath).ToArray() : list;
|
||||
if (parsePaths)
|
||||
return yaml[key].Nodes.Select(node => Platform.ResolvePath(node.Key, node.Value.Value ?? string.Empty)).ToArray();
|
||||
|
||||
return yaml[key].ToDictionary().Keys.ToArray();
|
||||
}
|
||||
|
||||
static IReadOnlyDictionary<string, string> YamlDictionary(Dictionary<string, MiniYaml> yaml, string key, bool parsePaths = false)
|
||||
@@ -168,15 +171,19 @@ namespace OpenRA
|
||||
var inner = new Dictionary<string, string>();
|
||||
foreach (var node in yaml[key].Nodes)
|
||||
{
|
||||
var line = node.Key;
|
||||
if (node.Value.Value != null)
|
||||
line += ":" + node.Value.Value;
|
||||
|
||||
// '@' may be used in mod.yaml to indicate extra information (similar to trait @ tags).
|
||||
// Applies to MapFolders (to indicate System and User directories) and Packages (to indicate package annotation).
|
||||
if (node.Key.Contains('@'))
|
||||
if (line.Contains('@'))
|
||||
{
|
||||
var split = node.Key.Split('@');
|
||||
inner.Add(split[0], split[1]);
|
||||
var split = line.Split('@');
|
||||
inner.Add(parsePaths ? Platform.ResolvePath(split[0]) : split[0], split[1]);
|
||||
}
|
||||
else
|
||||
inner.Add(node.Key, null);
|
||||
inner.Add(line, null);
|
||||
}
|
||||
|
||||
return new ReadOnlyDictionary<string, string>(inner);
|
||||
@@ -198,20 +205,16 @@ namespace OpenRA
|
||||
|
||||
static Dictionary<string, Manifest> LoadMods()
|
||||
{
|
||||
var basePath = Platform.ResolvePath(".", "mods");
|
||||
var mods = Directory.GetDirectories(basePath)
|
||||
.Select(x => x.Substring(basePath.Length + 1));
|
||||
|
||||
var ret = new Dictionary<string, Manifest>();
|
||||
foreach (var mod in mods)
|
||||
foreach (var mod in ModMetadata.CandidateModPaths)
|
||||
{
|
||||
if (!File.Exists(Platform.ResolvePath(".", "mods", mod, "mod.yaml")))
|
||||
if (!File.Exists(Path.Combine(mod.Value, "mod.yaml")))
|
||||
continue;
|
||||
|
||||
try
|
||||
{
|
||||
var manifest = new Manifest(mod);
|
||||
ret.Add(mod, manifest);
|
||||
var manifest = new Manifest(mod.Key, mod.Value);
|
||||
ret.Add(mod.Key, manifest);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -17,6 +17,7 @@ namespace OpenRA
|
||||
{
|
||||
public class ModMetadata
|
||||
{
|
||||
public static readonly Dictionary<string, string> CandidateModPaths = GetCandidateMods();
|
||||
public static readonly Dictionary<string, ModMetadata> AllMods = ValidateMods();
|
||||
|
||||
public string Id;
|
||||
@@ -24,21 +25,19 @@ namespace OpenRA
|
||||
public string Description;
|
||||
public string Version;
|
||||
public string Author;
|
||||
public string LogoImagePath;
|
||||
public string PreviewImagePath;
|
||||
public bool Hidden;
|
||||
public ContentInstaller Content;
|
||||
|
||||
static Dictionary<string, ModMetadata> ValidateMods()
|
||||
{
|
||||
var basePath = Platform.ResolvePath(".", "mods");
|
||||
var mods = Directory.GetDirectories(basePath)
|
||||
.Select(x => x.Substring(basePath.Length + 1));
|
||||
|
||||
var ret = new Dictionary<string, ModMetadata>();
|
||||
foreach (var m in mods)
|
||||
foreach (var pair in CandidateModPaths)
|
||||
{
|
||||
try
|
||||
{
|
||||
var yamlPath = Platform.ResolvePath(".", "mods", m, "mod.yaml");
|
||||
var yamlPath = Path.Combine(pair.Value, "mod.yaml");
|
||||
if (!File.Exists(yamlPath))
|
||||
continue;
|
||||
|
||||
@@ -47,22 +46,40 @@ namespace OpenRA
|
||||
if (!nd.ContainsKey("Metadata"))
|
||||
continue;
|
||||
|
||||
var mod = FieldLoader.Load<ModMetadata>(nd["Metadata"]);
|
||||
mod.Id = m;
|
||||
var metadata = FieldLoader.Load<ModMetadata>(nd["Metadata"]);
|
||||
metadata.Id = pair.Key;
|
||||
|
||||
if (nd.ContainsKey("ContentInstaller"))
|
||||
mod.Content = FieldLoader.Load<ContentInstaller>(nd["ContentInstaller"]);
|
||||
metadata.Content = FieldLoader.Load<ContentInstaller>(nd["ContentInstaller"]);
|
||||
|
||||
ret.Add(m, mod);
|
||||
ret.Add(pair.Key, metadata);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("An exception occurred when trying to load ModMetadata for `{0}`:".F(m));
|
||||
Console.WriteLine("An exception occurred when trying to load ModMetadata for `{0}`:".F(pair.Key));
|
||||
Console.WriteLine(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static Dictionary<string, string> GetCandidateMods()
|
||||
{
|
||||
// Get mods that are in the game folder.
|
||||
var basePath = Platform.ResolvePath(Path.Combine(".", "mods"));
|
||||
var mods = Directory.GetDirectories(basePath)
|
||||
.ToDictionary(x => x.Substring(basePath.Length + 1));
|
||||
|
||||
// Get mods that are in the support folder.
|
||||
var supportPath = Platform.ResolvePath(Path.Combine("^", "mods"));
|
||||
if (!Directory.Exists(supportPath))
|
||||
return mods;
|
||||
|
||||
foreach (var pair in Directory.GetDirectories(supportPath).ToDictionary(x => x.Substring(supportPath.Length + 1)))
|
||||
mods.Add(pair.Key, pair.Value);
|
||||
|
||||
return mods;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,11 +95,19 @@ namespace OpenRA
|
||||
|
||||
public static string GameDir { get { return AppDomain.CurrentDomain.BaseDirectory; } }
|
||||
|
||||
/// <summary>Replace special character prefixes with full paths</summary>
|
||||
/// <summary>Replaces special character prefixes with full paths.</summary>
|
||||
public static string ResolvePath(string path)
|
||||
{
|
||||
path = path.TrimEnd(new char[] { ' ', '\t' });
|
||||
|
||||
// If the path contains ':', chances are it is a package path.
|
||||
// If it isn't, someone passed an already resolved path, which is wrong.
|
||||
if (path.IndexOf(":", StringComparison.Ordinal) > 1)
|
||||
{
|
||||
var split = path.Split(':');
|
||||
return ResolvePath(split[0], split[1]);
|
||||
}
|
||||
|
||||
// paths starting with ^ are relative to the support dir
|
||||
if (path.StartsWith("^"))
|
||||
path = SupportDir + path.Substring(1);
|
||||
@@ -111,7 +119,17 @@ namespace OpenRA
|
||||
return path;
|
||||
}
|
||||
|
||||
/// <summary>Replace special character prefixes with full paths</summary>
|
||||
/// <summary>Replaces package names with full paths. Avoid using this for non-package paths.</summary>
|
||||
public static string ResolvePath(string package, string target)
|
||||
{
|
||||
// Resolve mod package paths.
|
||||
if (ModMetadata.AllMods.ContainsKey(package))
|
||||
package = ModMetadata.CandidateModPaths[package];
|
||||
|
||||
return ResolvePath(Path.Combine(package, target));
|
||||
}
|
||||
|
||||
/// <summary>Replace special character prefixes with full paths.</summary>
|
||||
public static string ResolvePath(params string[] path)
|
||||
{
|
||||
return ResolvePath(path.Aggregate(Path.Combine));
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using OpenRA.Graphics;
|
||||
@@ -49,7 +50,7 @@ namespace OpenRA
|
||||
var resolution = GetResolution(graphicSettings);
|
||||
|
||||
var rendererName = serverSettings.Dedicated ? "Null" : graphicSettings.Renderer;
|
||||
var rendererPath = Platform.ResolvePath(".", "OpenRA.Platforms." + rendererName + ".dll");
|
||||
var rendererPath = Platform.ResolvePath(Path.Combine(".", "OpenRA.Platforms." + rendererName + ".dll"));
|
||||
|
||||
Device = CreateDevice(Assembly.LoadFile(rendererPath), resolution.Width, resolution.Height, graphicSettings.Mode);
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace OpenRA
|
||||
|
||||
public Sound(string engineName)
|
||||
{
|
||||
var enginePath = Platform.ResolvePath(".", "OpenRA.Platforms." + engineName + ".dll");
|
||||
var enginePath = Platform.ResolvePath(Path.Combine(".", "OpenRA.Platforms." + engineName + ".dll"));
|
||||
soundEngine = CreateDevice(Assembly.LoadFile(enginePath));
|
||||
}
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var preview = new Bitmap(Platform.ResolvePath(".", "mods", mod.Id, "preview.png")))
|
||||
using (var preview = new Bitmap(Platform.ResolvePath(mod.PreviewImagePath)))
|
||||
if (preview.Width == 296 && preview.Height == 196)
|
||||
previews.Add(mod.Id, sheetBuilder.Add(preview));
|
||||
}
|
||||
@@ -90,7 +90,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
|
||||
try
|
||||
{
|
||||
using (var logo = new Bitmap(Platform.ResolvePath(".", "mods", mod.Id, "logo.png")))
|
||||
using (var logo = new Bitmap(Platform.ResolvePath(mod.LogoImagePath)))
|
||||
if (logo.Width == 96 && logo.Height == 96)
|
||||
logos.Add(mod.Id, sheetBuilder.Add(logo));
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ Chrome:
|
||||
Assemblies:
|
||||
./mods/common/OpenRA.Mods.Common.dll
|
||||
./mods/ra/OpenRA.Mods.RA.dll
|
||||
./mods/d2k/OpenRA.Mods.D2k.dll
|
||||
d2k:OpenRA.Mods.D2k.dll
|
||||
./mods/cnc/OpenRA.Mods.Cnc.dll
|
||||
./mods/ts/OpenRA.Mods.TS.dll
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@ Metadata:
|
||||
Description: Join the Global Defense Initiative or the Brotherhood of Nod in our\nrecreation of the classic game that started it all.\n\nTiberian Dawn modernizes the original Command & Conquer gameplay\nby introducing features from later games, including per-factory\nproduction queues, unit veterancy, and capturable tech structures.
|
||||
Version: {DEV_VERSION}
|
||||
Author: the OpenRA Developers
|
||||
LogoImagePath: ./mods/cnc/logo.png
|
||||
PreviewImagePath: ./mods/cnc/preview.png
|
||||
|
||||
RequiresMods:
|
||||
modchooser: {DEV_VERSION}
|
||||
|
||||
@@ -3,96 +3,98 @@ Metadata:
|
||||
Description: Three great houses fight for the precious spice, melange.\nHe who controls the spice controls the universe!\n\nTry to establish a foothold on the desert planet Arrakis\nwith its harsh environmental conditions and protect your\nharvesting operations from giant sandworms as well as\nruthless enemy factions.
|
||||
Version: {DEV_VERSION}
|
||||
Author: the OpenRA Developers
|
||||
LogoImagePath: d2k:logo.png
|
||||
PreviewImagePath: d2k:preview.png
|
||||
|
||||
RequiresMods:
|
||||
modchooser: {DEV_VERSION}
|
||||
|
||||
Folders:
|
||||
.
|
||||
./mods/d2k
|
||||
./mods/d2k/bits
|
||||
./mods/d2k/bits/tex
|
||||
./mods/d2k/bits/xmas
|
||||
./mods/d2k/uibits
|
||||
d2k:
|
||||
d2k:bits
|
||||
d2k:bits/tex
|
||||
d2k:bits/xmas
|
||||
d2k:uibits
|
||||
~^Content/d2k
|
||||
~^Content/d2k/GAMESFX
|
||||
~^Content/d2k/Movies
|
||||
~^Content/d2k/Music
|
||||
|
||||
MapFolders:
|
||||
./mods/d2k/maps@System
|
||||
d2k:maps@System
|
||||
~^maps/d2k@User
|
||||
|
||||
Packages:
|
||||
SOUND.RS
|
||||
|
||||
Rules:
|
||||
./mods/d2k/rules/misc.yaml
|
||||
./mods/d2k/rules/ai.yaml
|
||||
./mods/d2k/rules/player.yaml
|
||||
./mods/d2k/rules/world.yaml
|
||||
./mods/d2k/rules/palettes.yaml
|
||||
./mods/d2k/rules/defaults.yaml
|
||||
./mods/d2k/rules/vehicles.yaml
|
||||
./mods/d2k/rules/starport.yaml
|
||||
./mods/d2k/rules/husks.yaml
|
||||
./mods/d2k/rules/structures.yaml
|
||||
./mods/d2k/rules/aircraft.yaml
|
||||
./mods/d2k/rules/infantry.yaml
|
||||
./mods/d2k/rules/arrakis.yaml
|
||||
d2k:rules/misc.yaml
|
||||
d2k:rules/ai.yaml
|
||||
d2k:rules/player.yaml
|
||||
d2k:rules/world.yaml
|
||||
d2k:rules/palettes.yaml
|
||||
d2k:rules/defaults.yaml
|
||||
d2k:rules/vehicles.yaml
|
||||
d2k:rules/starport.yaml
|
||||
d2k:rules/husks.yaml
|
||||
d2k:rules/structures.yaml
|
||||
d2k:rules/aircraft.yaml
|
||||
d2k:rules/infantry.yaml
|
||||
d2k:rules/arrakis.yaml
|
||||
|
||||
Sequences:
|
||||
./mods/d2k/sequences/aircraft.yaml
|
||||
./mods/d2k/sequences/vehicles.yaml
|
||||
./mods/d2k/sequences/infantry.yaml
|
||||
./mods/d2k/sequences/structures.yaml
|
||||
./mods/d2k/sequences/misc.yaml
|
||||
d2k:sequences/aircraft.yaml
|
||||
d2k:sequences/vehicles.yaml
|
||||
d2k:sequences/infantry.yaml
|
||||
d2k:sequences/structures.yaml
|
||||
d2k:sequences/misc.yaml
|
||||
|
||||
TileSets:
|
||||
./mods/d2k/tilesets/arrakis.yaml
|
||||
d2k:tilesets/arrakis.yaml
|
||||
|
||||
MapGrid:
|
||||
TileSize: 32,32
|
||||
Type: Rectangular
|
||||
|
||||
Cursors:
|
||||
./mods/d2k/cursors.yaml
|
||||
d2k:cursors.yaml
|
||||
|
||||
Chrome:
|
||||
./mods/d2k/chrome.yaml
|
||||
d2k:chrome.yaml
|
||||
|
||||
Assemblies:
|
||||
./mods/common/OpenRA.Mods.Common.dll
|
||||
./mods/cnc/OpenRA.Mods.Cnc.dll
|
||||
./mods/d2k/OpenRA.Mods.D2k.dll
|
||||
d2k:OpenRA.Mods.D2k.dll
|
||||
|
||||
ChromeLayout:
|
||||
./mods/d2k/chrome/ingame.yaml
|
||||
d2k:chrome/ingame.yaml
|
||||
./mods/ra/chrome/ingame-chat.yaml
|
||||
./mods/ra/chrome/ingame-diplomacy.yaml
|
||||
./mods/ra/chrome/ingame-fmvplayer.yaml
|
||||
./mods/d2k/chrome/ingame-menu.yaml
|
||||
d2k:chrome/ingame-menu.yaml
|
||||
./mods/ra/chrome/ingame-info.yaml
|
||||
./mods/ra/chrome/ingame-infoscripterror.yaml
|
||||
./mods/ra/chrome/ingame-infobriefing.yaml
|
||||
./mods/ra/chrome/ingame-infoobjectives.yaml
|
||||
./mods/d2k/chrome/ingame-infostats.yaml
|
||||
./mods/d2k/chrome/ingame-observer.yaml
|
||||
d2k:chrome/ingame-infostats.yaml
|
||||
d2k:chrome/ingame-observer.yaml
|
||||
./mods/ra/chrome/ingame-observerstats.yaml
|
||||
./mods/d2k/chrome/ingame-player.yaml
|
||||
d2k:chrome/ingame-player.yaml
|
||||
./mods/ra/chrome/ingame-perf.yaml
|
||||
./mods/ra/chrome/ingame-debug.yaml
|
||||
./mods/d2k/chrome/mainmenu.yaml
|
||||
d2k:chrome/mainmenu.yaml
|
||||
./mods/ra/chrome/settings.yaml
|
||||
./mods/ra/chrome/credits.yaml
|
||||
./mods/ra/chrome/lobby.yaml
|
||||
./mods/ra/chrome/lobby-mappreview.yaml
|
||||
./mods/d2k/chrome/lobby-players.yaml
|
||||
./mods/d2k/chrome/lobby-options.yaml
|
||||
d2k:chrome/lobby-players.yaml
|
||||
d2k:chrome/lobby-options.yaml
|
||||
./mods/ra/chrome/lobby-music.yaml
|
||||
./mods/ra/chrome/lobby-kickdialogs.yaml
|
||||
./mods/ra/chrome/lobby-globalchat.yaml
|
||||
./mods/d2k/chrome/color-picker.yaml
|
||||
d2k:chrome/color-picker.yaml
|
||||
./mods/ra/chrome/map-chooser.yaml
|
||||
./mods/ra/chrome/multiplayer.yaml
|
||||
./mods/ra/chrome/multiplayer-browser.yaml
|
||||
@@ -100,33 +102,33 @@ ChromeLayout:
|
||||
./mods/ra/chrome/multiplayer-directconnect.yaml
|
||||
./mods/ra/chrome/multiplayer-globalchat.yaml
|
||||
./mods/ra/chrome/connection.yaml
|
||||
./mods/d2k/chrome/dropdowns.yaml
|
||||
d2k:chrome/dropdowns.yaml
|
||||
./mods/ra/chrome/musicplayer.yaml
|
||||
./mods/d2k/chrome/tooltips.yaml
|
||||
d2k:chrome/tooltips.yaml
|
||||
./mods/ra/chrome/assetbrowser.yaml
|
||||
./mods/d2k/chrome/missionbrowser.yaml
|
||||
d2k:chrome/missionbrowser.yaml
|
||||
./mods/ra/chrome/confirmation-dialogs.yaml
|
||||
./mods/ra/chrome/editor.yaml
|
||||
./mods/ra/chrome/replaybrowser.yaml
|
||||
|
||||
Weapons:
|
||||
./mods/d2k/weapons.yaml
|
||||
./mods/d2k/weapons/debris.yaml
|
||||
d2k:weapons.yaml
|
||||
d2k:weapons/debris.yaml
|
||||
|
||||
Voices:
|
||||
./mods/d2k/audio/voices.yaml
|
||||
d2k:audio/voices.yaml
|
||||
|
||||
Notifications:
|
||||
./mods/d2k/audio/notifications.yaml
|
||||
d2k:audio/notifications.yaml
|
||||
|
||||
Music:
|
||||
./mods/d2k/audio/music.yaml
|
||||
d2k:audio/music.yaml
|
||||
|
||||
Translations:
|
||||
./mods/d2k/languages/english.yaml
|
||||
d2k:languages/english.yaml
|
||||
|
||||
LoadScreen: LogoStripeLoadScreen
|
||||
Image: ./mods/d2k/uibits/loadscreen.png
|
||||
Image: d2k:uibits/loadscreen.png
|
||||
Text: Filling Crates..., Breeding Sandworms..., Fuelling carryalls..., Deploying harvesters..., Preparing 'thopters..., Summoning mentats...
|
||||
|
||||
ContentInstaller:
|
||||
@@ -161,7 +163,7 @@ LobbyDefaults:
|
||||
TechLevel: Unrestricted
|
||||
|
||||
ChromeMetrics:
|
||||
./mods/d2k/metrics.yaml
|
||||
d2k:metrics.yaml
|
||||
|
||||
Fonts:
|
||||
Regular:
|
||||
@@ -171,7 +173,7 @@ Fonts:
|
||||
Font:./mods/common/FreeSansBold.ttf
|
||||
Size:14
|
||||
Title:
|
||||
Font:./mods/d2k/Dune2k.ttf
|
||||
Font:d2k:Dune2k.ttf
|
||||
Size:32
|
||||
MediumBold:
|
||||
Font:./mods/common/FreeSansBold.ttf
|
||||
@@ -190,7 +192,7 @@ Fonts:
|
||||
Size:10
|
||||
|
||||
Missions:
|
||||
./mods/d2k/missions.yaml
|
||||
d2k:missions.yaml
|
||||
|
||||
SupportsMapsFrom: d2k
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@ Metadata:
|
||||
Description: In a world where Hitler was assassinated and the Third Reich never\nexisted, the Soviet Union seeks power over all of Europe. Allied\nagainst this Evil Empire, the free world faces a Cold War turned hot.\n\nRed Alert fuses the quick and fun gameplay of the original\nC&C: Red Alert, with balance improvements and new gameplay\nfeatures inspired by modern RTS games.
|
||||
Version: {DEV_VERSION}
|
||||
Author: the OpenRA Developers
|
||||
LogoImagePath: ./mods/ra/logo.png
|
||||
PreviewImagePath: ./mods/ra/preview.png
|
||||
|
||||
RequiresMods:
|
||||
modchooser: {DEV_VERSION}
|
||||
|
||||
@@ -3,6 +3,8 @@ Metadata:
|
||||
Description: Developer stub, not yet ready for release!
|
||||
Version: {DEV_VERSION}
|
||||
Author: the OpenRA Developers
|
||||
LogoImagePath: ./mods/ts/logo.png
|
||||
PreviewImagePath: ./mods/ts/preview.png
|
||||
|
||||
RequiresMods:
|
||||
modchooser: {DEV_VERSION}
|
||||
@@ -142,7 +144,7 @@ ChromeLayout:
|
||||
./mods/ra/chrome/ingame-infobriefing.yaml
|
||||
./mods/ra/chrome/ingame-infoobjectives.yaml
|
||||
./mods/ra/chrome/ingame-infostats.yaml
|
||||
./mods/d2k/chrome/ingame-observer.yaml
|
||||
d2k:chrome/ingame-observer.yaml
|
||||
./mods/ts/chrome/ingame-observerstats.yaml
|
||||
./mods/ts/chrome/ingame-player.yaml
|
||||
./mods/ra/chrome/ingame-perf.yaml
|
||||
|
||||
Reference in New Issue
Block a user