Expose mod.yaml content to localisation.

Mod metadata, load screens and mod content is all now sourced from ftl files, allowing these items to be translated.

Translations are now initialized as part of ModData creation, as currently they are made available too late for the usage we need here.

The "modcontent" mod learns a new parameter for "Content.TranslationFile" - this allows a mod to provide the path of a translation file to the mod which it can load. This allows mods such as ra, cnc, d2k, ts to own the translations for their ModContent, yet still make them accessible to the modcontent mod.

CheckFluentReference learns to validate all these new fields to ensure translations have been set.
This commit is contained in:
RoosterDragon
2024-09-23 19:58:33 +01:00
committed by Gustas
parent d1583e8587
commit bb17cfa179
36 changed files with 292 additions and 144 deletions

View File

@@ -27,7 +27,6 @@ namespace OpenRA
{ {
public readonly string Id; public readonly string Id;
public readonly string Version; public readonly string Version;
public readonly string Title;
public readonly string LaunchPath; public readonly string LaunchPath;
public readonly string[] LaunchArgs; public readonly string[] LaunchArgs;
public Sprite Icon { get; internal set; } public Sprite Icon { get; internal set; }
@@ -127,7 +126,6 @@ namespace OpenRA
{ {
new MiniYamlNode("Id", mod.Id), new MiniYamlNode("Id", mod.Id),
new MiniYamlNode("Version", mod.Metadata.Version), new MiniYamlNode("Version", mod.Metadata.Version),
new MiniYamlNode("Title", mod.Metadata.Title),
new MiniYamlNode("LaunchPath", launchPath), new MiniYamlNode("LaunchPath", launchPath),
new MiniYamlNode("LaunchArgs", new[] { "Game.Mod=" + mod.Id }.Concat(launchArgs).JoinWith(", ")) new MiniYamlNode("LaunchArgs", new[] { "Game.Mod=" + mod.Id }.Concat(launchArgs).JoinWith(", "))
})); }));

View File

@@ -395,7 +395,7 @@ namespace OpenRA
Mods = new InstalledMods(modSearchPaths, explicitModPaths); Mods = new InstalledMods(modSearchPaths, explicitModPaths);
Console.WriteLine("Internal mods:"); Console.WriteLine("Internal mods:");
foreach (var mod in Mods) foreach (var mod in Mods)
Console.WriteLine($"\t{mod.Key}: {mod.Value.Metadata.Title} ({mod.Value.Metadata.Version})"); Console.WriteLine($"\t{mod.Key} ({mod.Value.Metadata.Version})");
modLaunchWrapper = args.GetValue("Engine.LaunchWrapper", null); modLaunchWrapper = args.GetValue("Engine.LaunchWrapper", null);
@@ -420,7 +420,7 @@ namespace OpenRA
Console.WriteLine("External mods:"); Console.WriteLine("External mods:");
foreach (var mod in ExternalMods) foreach (var mod in ExternalMods)
Console.WriteLine($"\t{mod.Key}: {mod.Value.Title} ({mod.Value.Version})"); Console.WriteLine($"\t{mod.Key} ({mod.Value.Version})");
InitializeMod(modID, args); InitializeMod(modID, args);
} }
@@ -499,8 +499,8 @@ namespace OpenRA
Cursor = new CursorManager(ModData.CursorProvider, ModData.Manifest.CursorSheetSize); Cursor = new CursorManager(ModData.CursorProvider, ModData.Manifest.CursorSheetSize);
var metadata = ModData.Manifest.Metadata; var metadata = ModData.Manifest.Metadata;
if (!string.IsNullOrEmpty(metadata.WindowTitle)) if (!string.IsNullOrEmpty(metadata.WindowTitleTranslated))
Renderer.Window.SetWindowTitle(metadata.WindowTitle); Renderer.Window.SetWindowTitle(metadata.WindowTitleTranslated);
PerfHistory.Items["render"].HasNormalTick = false; PerfHistory.Items["render"].HasNormalTick = false;
PerfHistory.Items["batches"].HasNormalTick = false; PerfHistory.Items["batches"].HasNormalTick = false;

View File

@@ -45,12 +45,20 @@ namespace OpenRA
public class ModMetadata public class ModMetadata
{ {
public string Title; // FieldLoader used here, must matching naming in YAML.
public string Version; #pragma warning disable IDE1006 // Naming Styles
public string Website; [FluentReference]
public string WebIcon32; readonly string Title;
public string WindowTitle; public readonly string Version;
public bool Hidden; public readonly string Website;
public readonly string WebIcon32;
[FluentReference]
readonly string WindowTitle;
public readonly bool Hidden;
#pragma warning restore IDE1006 // Naming Styles
public string TitleTranslated => FluentProvider.GetString(Title);
public string WindowTitleTranslated => WindowTitle != null ? FluentProvider.GetString(WindowTitle) : null;
} }
/// <summary>Describes what is to be loaded in order to run a mod.</summary> /// <summary>Describes what is to be loaded in order to run a mod.</summary>

View File

@@ -65,6 +65,8 @@ namespace OpenRA
Manifest.LoadCustomData(ObjectCreator); Manifest.LoadCustomData(ObjectCreator);
FluentProvider.Initialize(this, DefaultFileSystem);
if (useLoadScreen) if (useLoadScreen)
{ {
LoadScreen = ObjectCreator.CreateObject<ILoadScreen>(Manifest.LoadScreen.Value); LoadScreen = ObjectCreator.CreateObject<ILoadScreen>(Manifest.LoadScreen.Value);

View File

@@ -182,13 +182,13 @@ namespace OpenRA.Network
if (external != null && external.Version == Version) if (external != null && external.Version == Version)
{ {
// Use external mod registration to populate the section header // Use external mod registration to populate the section header
ModTitle = external.Title; ModTitle = external.Id;
} }
else if (Game.Mods.TryGetValue(Mod, out var mod)) else if (Game.Mods.TryGetValue(Mod, out var mod))
{ {
// Use internal mod data to populate the section header, but // Use internal mod data to populate the section header, but
// on-connect switching must use the external mod plumbing. // on-connect switching must use the external mod plumbing.
ModTitle = mod.Metadata.Title; ModTitle = mod.Metadata.TitleTranslated;
} }
else else
{ {
@@ -199,7 +199,7 @@ namespace OpenRA.Network
.FirstOrDefault(m => m.Id == Mod); .FirstOrDefault(m => m.Id == Mod);
if (guessMod != null) if (guessMod != null)
ModTitle = guessMod.Title; ModTitle = guessMod.Id;
else else
ModTitle = $"Unknown mod: {Mod}"; ModTitle = $"Unknown mod: {Mod}";
} }
@@ -222,7 +222,7 @@ namespace OpenRA.Network
Map = server.Map.Uid; Map = server.Map.Uid;
Mod = manifest.Id; Mod = manifest.Id;
Version = manifest.Metadata.Version; Version = manifest.Metadata.Version;
ModTitle = manifest.Metadata.Title; ModTitle = manifest.Metadata.TitleTranslated;
ModWebsite = manifest.Metadata.Website; ModWebsite = manifest.Metadata.Website;
ModIcon32 = manifest.Metadata.WebIcon32; ModIcon32 = manifest.Metadata.WebIcon32;
Protected = !string.IsNullOrEmpty(server.Settings.Password); Protected = !string.IsNullOrEmpty(server.Settings.Password);

View File

@@ -122,7 +122,7 @@ namespace OpenRA.Network
Log.Write("sync", $"Player: {Game.Settings.Player.Name} ({Platform.CurrentPlatform} {Environment.OSVersion} {Platform.RuntimeVersion})"); Log.Write("sync", $"Player: {Game.Settings.Player.Name} ({Platform.CurrentPlatform} {Environment.OSVersion} {Platform.RuntimeVersion})");
if (Game.IsHost) if (Game.IsHost)
Log.Write("sync", "Player is host."); Log.Write("sync", "Player is host.");
Log.Write("sync", $"Game ID: {orderManager.LobbyInfo.GlobalSettings.GameUid} (Mod: {mod.Title} at Version {mod.Version})"); Log.Write("sync", $"Game ID: {orderManager.LobbyInfo.GlobalSettings.GameUid} (Mod: {mod.TitleTranslated} at Version {mod.Version})");
Log.Write("sync", $"Sync for net frame {r.Frame} -------------"); Log.Write("sync", $"Sync for net frame {r.Frame} -------------");
Log.Write("sync", $"SharedRandom: {r.SyncedRandom} (#{r.TotalCount})"); Log.Write("sync", $"SharedRandom: {r.SyncedRandom} (#{r.TotalCount})");
Log.Write("sync", "Synced Traits:"); Log.Write("sync", "Synced Traits:");

View File

@@ -31,8 +31,8 @@ namespace OpenRA
if (Game.ModData != null) if (Game.ModData != null)
{ {
var mod = Game.ModData.Manifest.Metadata; var manifest = Game.ModData.Manifest;
Log.Write("exception", $"{mod.Title} mod version {mod.Version}"); Log.Write("exception", $"{manifest.Id} mod version {manifest.Metadata.Version}");
} }
if (Game.OrderManager != null && Game.OrderManager.World != null && Game.OrderManager.World.Map != null) if (Game.OrderManager != null && Game.OrderManager.World != null && Game.OrderManager.World.Map != null)

View File

@@ -19,6 +19,9 @@ namespace OpenRA.Mods.Cnc
{ {
public sealed class CncLoadScreen : SheetLoadScreen public sealed class CncLoadScreen : SheetLoadScreen
{ {
[FluentReference]
const string Loading = "loadscreen-loading";
int loadTick; int loadTick;
Sprite nodLogo, gdiLogo, evaLogo, brightBlock, dimBlock; Sprite nodLogo, gdiLogo, evaLogo, brightBlock, dimBlock;
@@ -31,11 +34,15 @@ namespace OpenRA.Mods.Cnc
int lastDensity; int lastDensity;
Size lastResolution; Size lastResolution;
string message = "";
public override void Init(ModData modData, Dictionary<string, string> info) public override void Init(ModData modData, Dictionary<string, string> info)
{ {
base.Init(modData, info); base.Init(modData, info);
versionText = modData.Manifest.Metadata.Version; versionText = modData.Manifest.Metadata.Version;
message = FluentProvider.GetString(Loading);
} }
public override void DisplayInner(Renderer r, Sheet s, int density) public override void DisplayInner(Renderer r, Sheet s, int density)
@@ -89,7 +96,7 @@ namespace OpenRA.Mods.Cnc
if (r.Fonts != null) if (r.Fonts != null)
{ {
var loadingFont = r.Fonts["BigBold"]; var loadingFont = r.Fonts["BigBold"];
var loadingText = Info["Text"]; var loadingText = message;
var loadingPos = new float2((bounds.Width - loadingFont.Measure(loadingText).X) / 2, barY); var loadingPos = new float2((bounds.Width - loadingFont.Measure(loadingText).X) / 2, barY);
loadingFont.DrawText(loadingText, loadingPos, Color.Gray); loadingFont.DrawText(loadingText, loadingPos, Color.Gray);

View File

@@ -48,7 +48,12 @@ namespace OpenRA.Mods.Common.FileSystem
if (contentInstalled) if (contentInstalled)
return false; return false;
Game.InitializeMod(content.ContentInstallerMod, new Arguments("Content.Mod=" + modData.Manifest.Id)); string translationPath;
using (var fs = (FileStream)modData.DefaultFileSystem.Open(content.Translation))
translationPath = fs.Name;
Game.InitializeMod(
content.ContentInstallerMod,
new Arguments(new[] { "Content.Mod=" + modData.Manifest.Id, "Content.TranslationFile=" + translationPath }));
return true; return true;
} }
} }

View File

@@ -43,16 +43,17 @@ namespace OpenRA.Mods.Common.Lint
var mapTranslations = FieldLoader.GetValue<string[]>("value", map.TranslationDefinitions.Value); var mapTranslations = FieldLoader.GetValue<string[]>("value", map.TranslationDefinitions.Value);
foreach (var language in GetModLanguages(modData)) var allModTranslations = modData.Manifest.Translations.Append(modData.Manifest.Get<ModContent>().Translation).ToArray();
foreach (var language in GetModLanguages(allModTranslations))
{ {
// Check keys and variables are not missing across all language files. // Check keys and variables are not missing across all language files.
// But for maps we don't warn on unused keys. They might be unused on *this* map, // But for maps we don't warn on unused keys. They might be unused on *this* map,
// but the mod or another map may use them and we don't have sight of that. // but the mod or another map may use them and we don't have sight of that.
CheckKeys( CheckKeys(
modData.Manifest.Translations.Concat(mapTranslations), map.Open, usedKeys, allModTranslations.Concat(mapTranslations), map.Open, usedKeys,
language, _ => false, emitError, emitWarning); language, _ => false, emitError, emitWarning);
var modFluentBundle = new FluentBundle(language, modData.Manifest.Translations, modData.DefaultFileSystem, _ => { }); var modFluentBundle = new FluentBundle(language, allModTranslations, modData.DefaultFileSystem, _ => { });
var mapFluentBundle = new FluentBundle(language, mapTranslations, map, error => emitError(error.Message)); var mapFluentBundle = new FluentBundle(language, mapTranslations, map, error => emitError(error.Message));
foreach (var group in usedKeys.KeysWithContext) foreach (var group in usedKeys.KeysWithContext)
@@ -78,14 +79,15 @@ namespace OpenRA.Mods.Common.Lint
foreach (var context in usedKeys.EmptyKeyContexts) foreach (var context in usedKeys.EmptyKeyContexts)
emitWarning($"Empty key in mod translation files required by {context}"); emitWarning($"Empty key in mod translation files required by {context}");
foreach (var language in GetModLanguages(modData)) var allModTranslations = modData.Manifest.Translations.Append(modData.Manifest.Get<ModContent>().Translation).ToArray();
foreach (var language in GetModLanguages(allModTranslations))
{ {
Console.WriteLine($"Testing language: {language}"); Console.WriteLine($"Testing language: {language}");
CheckModWidgets(modData, usedKeys, testedFields); CheckModWidgets(modData, usedKeys, testedFields);
// With the fully populated keys, check keys and variables are not missing and not unused across all language files. // With the fully populated keys, check keys and variables are not missing and not unused across all language files.
var keyWithAttrs = CheckKeys( var keyWithAttrs = CheckKeys(
modData.Manifest.Translations, modData.DefaultFileSystem.Open, usedKeys, allModTranslations, modData.DefaultFileSystem.Open, usedKeys,
language, language,
file => file =>
!modData.Manifest.AllowUnusedTranslationsInExternalPackages || !modData.Manifest.AllowUnusedTranslationsInExternalPackages ||
@@ -113,9 +115,9 @@ namespace OpenRA.Mods.Common.Lint
$"`{field.ReflectedType.Name}.{field.Name}` - previous warnings may be incorrect"); $"`{field.ReflectedType.Name}.{field.Name}` - previous warnings may be incorrect");
} }
static IEnumerable<string> GetModLanguages(ModData modData) static IEnumerable<string> GetModLanguages(IEnumerable<string> translations)
{ {
return modData.Manifest.Translations return translations
.Select(filename => FilenameRegex.Match(filename).Groups["language"].Value) .Select(filename => FilenameRegex.Match(filename).Groups["language"].Value)
.Distinct() .Distinct()
.OrderBy(l => l); .OrderBy(l => l);
@@ -249,51 +251,55 @@ namespace OpenRA.Mods.Common.Lint
.Where(t => t.IsSubclassOf(typeof(TraitInfo)) || t.IsSubclassOf(typeof(Warhead))) .Where(t => t.IsSubclassOf(typeof(TraitInfo)) || t.IsSubclassOf(typeof(Warhead)))
.SelectMany(t => t.GetFields().Where(f => f.HasAttribute<FluentReferenceAttribute>()))); .SelectMany(t => t.GetFields().Where(f => f.HasAttribute<FluentReferenceAttribute>())));
// HACK: Need to hardcode the custom loader for GameSpeeds. // TODO: linter does not work with LoadUsing
var gameSpeeds = modData.Manifest.Get<GameSpeeds>(); GetUsedTranslationKeysFromFieldsWithTranslationReferenceAttribute(
var gameSpeedNameField = typeof(GameSpeed).GetField(nameof(GameSpeed.Name)); usedKeys, testedFields, Utility.GetFields(typeof(GameSpeed)), modData.Manifest.Get<GameSpeeds>().Speeds.Values);
var gameSpeedFluentReference = Utility.GetCustomAttributes<FluentReferenceAttribute>(gameSpeedNameField, true)[0];
testedFields.Add(gameSpeedNameField);
foreach (var speed in gameSpeeds.Speeds.Values)
usedKeys.Add(speed.Name, gameSpeedFluentReference, $"`{nameof(GameSpeed)}.{nameof(GameSpeed.Name)}`");
// TODO: linter does not work with LoadUsing // TODO: linter does not work with LoadUsing
foreach (var actorInfo in modData.DefaultRules.Actors) GetUsedTranslationKeysFromFieldsWithTranslationReferenceAttribute(
usedKeys, testedFields,
Utility.GetFields(typeof(ResourceRendererInfo.ResourceTypeInfo)),
modData.DefaultRules.Actors
.SelectMany(actorInfo => actorInfo.Value.TraitInfos<ResourceRendererInfo>())
.SelectMany(info => info.ResourceTypes.Values));
const BindingFlags Binding = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;
var constFields = modData.ObjectCreator.GetTypes().SelectMany(modType => modType.GetFields(Binding)).Where(f => f.IsLiteral);
GetUsedTranslationKeysFromFieldsWithTranslationReferenceAttribute(
usedKeys, testedFields, constFields, new[] { (object)null });
var modMetadataFields = typeof(ModMetadata).GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
GetUsedTranslationKeysFromFieldsWithTranslationReferenceAttribute(
usedKeys, testedFields, modMetadataFields, new[] { modData.Manifest.Metadata });
var modContent = modData.Manifest.Get<ModContent>();
GetUsedTranslationKeysFromFieldsWithTranslationReferenceAttribute(
usedKeys, testedFields, Utility.GetFields(typeof(ModContent)), new[] { modContent });
GetUsedTranslationKeysFromFieldsWithTranslationReferenceAttribute(
usedKeys, testedFields, Utility.GetFields(typeof(ModContent.ModPackage)), modContent.Packages.Values);
return (usedKeys, testedFields);
}
static void GetUsedTranslationKeysFromFieldsWithTranslationReferenceAttribute(
Keys usedKeys, List<FieldInfo> testedFields,
IEnumerable<FieldInfo> newFields, IEnumerable<object> objects)
{
var fieldsWithAttribute =
newFields
.Select(f => (Field: f, FluentReference: Utility.GetCustomAttributes<FluentReferenceAttribute>(f, true).SingleOrDefault()))
.Where(x => x.FluentReference != null)
.ToArray();
testedFields.AddRange(fieldsWithAttribute.Select(x => x.Field));
foreach (var obj in objects)
{ {
foreach (var info in actorInfo.Value.TraitInfos<ResourceRendererInfo>()) foreach (var (field, fluentReference) in fieldsWithAttribute)
{ {
var resourceTypeNameField = typeof(ResourceRendererInfo.ResourceTypeInfo).GetField(nameof(ResourceRendererInfo.ResourceTypeInfo.Name)); var keys = LintExts.GetFieldValues(obj, field, fluentReference.DictionaryReference);
var resourceTypeFluentReference = Utility.GetCustomAttributes<FluentReferenceAttribute>(resourceTypeNameField, true)[0];
testedFields.Add(resourceTypeNameField);
foreach (var resourceTypes in info.ResourceTypes)
usedKeys.Add(
resourceTypes.Value.Name,
resourceTypeFluentReference,
$"`{nameof(ResourceRendererInfo.ResourceTypeInfo)}.{nameof(ResourceRendererInfo.ResourceTypeInfo.Name)}`");
}
}
foreach (var modType in modData.ObjectCreator.GetTypes())
{
const BindingFlags Binding = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;
foreach (var field in modType.GetFields(Binding))
{
// Checking for constant string fields.
if (!field.IsLiteral)
continue;
var fluentReference = Utility.GetCustomAttributes<FluentReferenceAttribute>(field, true).SingleOrDefault();
if (fluentReference == null)
continue;
testedFields.Add(field);
var keys = LintExts.GetFieldValues(null, field, fluentReference.DictionaryReference);
foreach (var key in keys) foreach (var key in keys)
usedKeys.Add(key, fluentReference, $"`{field.ReflectedType.Name}.{field.Name}`"); usedKeys.Add(key, fluentReference, $"`{field.ReflectedType.Name}.{field.Name}`");
} }
} }
return (usedKeys, testedFields);
} }
static void CheckModWidgets(ModData modData, Keys usedKeys, List<FieldInfo> testedFields) static void CheckModWidgets(ModData modData, Keys usedKeys, List<FieldInfo> testedFields)

View File

@@ -30,10 +30,11 @@ namespace OpenRA.Mods.Common.Lint
void ILintPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData) void ILintPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData)
{ {
Run(emitError, emitWarning, modData.DefaultFileSystem, modData.Manifest.Translations); var allModTranslations = modData.Manifest.Translations.Append(modData.Manifest.Get<ModContent>().Translation);
Run(emitError, emitWarning, modData.DefaultFileSystem, allModTranslations);
} }
static void Run(Action<string> emitError, Action<string> emitWarning, IReadOnlyFileSystem fileSystem, string[] paths) static void Run(Action<string> emitError, Action<string> emitWarning, IReadOnlyFileSystem fileSystem, IEnumerable<string> paths)
{ {
foreach (var path in paths) foreach (var path in paths)
{ {

View File

@@ -9,7 +9,9 @@
*/ */
#endregion #endregion
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using OpenRA.Graphics; using OpenRA.Graphics;
using OpenRA.Mods.Common.Widgets; using OpenRA.Mods.Common.Widgets;
using OpenRA.Primitives; using OpenRA.Primitives;
@@ -18,6 +20,9 @@ namespace OpenRA.Mods.Common.LoadScreens
{ {
public sealed class LogoStripeLoadScreen : SheetLoadScreen public sealed class LogoStripeLoadScreen : SheetLoadScreen
{ {
[FluentReference]
const string Loading = "loadscreen-loading";
Rectangle stripeRect; Rectangle stripeRect;
float2 logoPos; float2 logoPos;
Sprite stripe, logo; Sprite stripe, logo;
@@ -26,14 +31,13 @@ namespace OpenRA.Mods.Common.LoadScreens
int lastDensity; int lastDensity;
Size lastResolution; Size lastResolution;
string[] messages = { "Loading..." }; string[] messages = Array.Empty<string>();
public override void Init(ModData modData, Dictionary<string, string> info) public override void Init(ModData modData, Dictionary<string, string> info)
{ {
base.Init(modData, info); base.Init(modData, info);
if (info.TryGetValue("Text", out var text)) messages = FluentProvider.GetString(Loading).Split(',').Select(x => x.Trim()).ToArray();
messages = text.Split(',');
} }
public override void DisplayInner(Renderer r, Sheet s, int density) public override void DisplayInner(Renderer r, Sheet s, int density)
@@ -59,7 +63,7 @@ namespace OpenRA.Mods.Common.LoadScreens
if (logo != null) if (logo != null)
r.RgbaSpriteRenderer.DrawSprite(logo, logoPos); r.RgbaSpriteRenderer.DrawSprite(logo, logoPos);
if (r.Fonts != null) if (r.Fonts != null && messages.Length > 0)
{ {
var text = messages.Random(Game.CosmeticRandom); var text = messages.Random(Game.CosmeticRandom);
var textSize = r.Fonts["Bold"].Measure(text); var textSize = r.Fonts["Bold"].Measure(text);

View File

@@ -52,6 +52,10 @@ namespace OpenRA.Mods.Common.LoadScreens
if (modId == null || !Game.Mods.TryGetValue(modId, out var selectedMod)) if (modId == null || !Game.Mods.TryGetValue(modId, out var selectedMod))
throw new InvalidOperationException("Invalid or missing Content.Mod argument."); throw new InvalidOperationException("Invalid or missing Content.Mod argument.");
var translationFilePath = args.GetValue("Content.TranslationFile", null);
if (translationFilePath == null || !File.Exists(translationFilePath))
throw new InvalidOperationException("Invalid or missing Content.TranslationFile argument.");
var content = selectedMod.Get<ModContent>(Game.ModData.ObjectCreator); var content = selectedMod.Get<ModContent>(Game.ModData.ObjectCreator);
Ui.LoadWidget("MODCONTENT_BACKGROUND", Ui.Root, new WidgetArgs()); Ui.LoadWidget("MODCONTENT_BACKGROUND", Ui.Root, new WidgetArgs());
@@ -63,6 +67,7 @@ namespace OpenRA.Mods.Common.LoadScreens
{ "continueLoading", () => Game.RunAfterTick(() => Game.InitializeMod(modId, new Arguments())) }, { "continueLoading", () => Game.RunAfterTick(() => Game.InitializeMod(modId, new Arguments())) },
{ "mod", selectedMod }, { "mod", selectedMod },
{ "content", content }, { "content", content },
{ "translationFilePath", translationFilePath },
}; };
Ui.OpenWindow("CONTENT_PROMPT_PANEL", widgetArgs); Ui.OpenWindow("CONTENT_PROMPT_PANEL", widgetArgs);
@@ -71,9 +76,10 @@ namespace OpenRA.Mods.Common.LoadScreens
{ {
var widgetArgs = new WidgetArgs var widgetArgs = new WidgetArgs
{ {
{ "onCancel", () => Game.RunAfterTick(() => Game.InitializeMod(modId, new Arguments())) },
{ "mod", selectedMod }, { "mod", selectedMod },
{ "content", content }, { "content", content },
{ "onCancel", () => Game.RunAfterTick(() => Game.InitializeMod(modId, new Arguments())) } { "translationFilePath", translationFilePath },
}; };
Ui.OpenWindow("CONTENT_PANEL", widgetArgs); Ui.OpenWindow("CONTENT_PANEL", widgetArgs);

View File

@@ -21,6 +21,7 @@ namespace OpenRA
{ {
public class ModPackage public class ModPackage
{ {
[FluentReference]
public readonly string Title; public readonly string Title;
public readonly string Identifier; public readonly string Identifier;
public readonly string[] TestFiles = Array.Empty<string>(); public readonly string[] TestFiles = Array.Empty<string>();
@@ -100,10 +101,13 @@ namespace OpenRA
} }
} }
[FluentReference]
public readonly string InstallPromptMessage; public readonly string InstallPromptMessage;
public readonly string QuickDownload; public readonly string QuickDownload;
[FluentReference]
public readonly string HeaderMessage; public readonly string HeaderMessage;
public readonly string ContentInstallerMod = "modcontent"; public readonly string ContentInstallerMod = "modcontent";
public readonly string Translation;
[FieldLoader.LoadUsing(nameof(LoadPackages))] [FieldLoader.LoadUsing(nameof(LoadPackages))]
public readonly Dictionary<string, ModPackage> Packages = new(); public readonly Dictionary<string, ModPackage> Packages = new();

View File

@@ -62,7 +62,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
var maps = new List<(IReadWritePackage Package, string Map)>(); var maps = new List<(IReadWritePackage Package, string Map)>();
if (args.Length < 2) if (args.Length < 2)
{ {
Console.WriteLine($"Testing mod: {modData.Manifest.Metadata.Title}"); Console.WriteLine($"Testing mod: {modData.Manifest.Metadata.TitleTranslated}");
// Run all rule checks on the default mod rules. // Run all rule checks on the default mod rules.
CheckRules(modData, modData.DefaultRules); CheckRules(modData, modData.DefaultRules);

View File

@@ -193,7 +193,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
var switchButton = panel.Get<ButtonWidget>("SWITCH_BUTTON"); var switchButton = panel.Get<ButtonWidget>("SWITCH_BUTTON");
var mod = CurrentServerSettings.ServerExternalMod; var mod = CurrentServerSettings.ServerExternalMod;
var modTitle = mod.Title; var modTitle = mod.Id;
var modVersion = mod.Version; var modVersion = mod.Version;
switchButton.OnClick = () => switchButton.OnClick = () =>

View File

@@ -87,6 +87,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
readonly ModData modData; readonly ModData modData;
readonly ModContent content; readonly ModContent content;
readonly Dictionary<string, ModContent.ModSource> sources; readonly Dictionary<string, ModContent.ModSource> sources;
readonly FluentBundle externalFluentBundle;
readonly Widget panel; readonly Widget panel;
readonly LabelWidget titleLabel; readonly LabelWidget titleLabel;
@@ -116,11 +117,13 @@ namespace OpenRA.Mods.Common.Widgets.Logic
Mode visible = Mode.Progress; Mode visible = Mode.Progress;
[ObjectCreator.UseCtor] [ObjectCreator.UseCtor]
public InstallFromSourceLogic(Widget widget, ModData modData, ModContent content, Dictionary<string, ModContent.ModSource> sources) public InstallFromSourceLogic(
Widget widget, ModData modData, ModContent content, Dictionary<string, ModContent.ModSource> sources, FluentBundle externalFluentBundle)
{ {
this.modData = modData; this.modData = modData;
this.content = content; this.content = content;
this.sources = sources; this.sources = sources;
this.externalFluentBundle = externalFluentBundle;
Log.AddChannel("install", "install.log"); Log.AddChannel("install", "install.log");
@@ -339,7 +342,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic
{ {
var containerWidget = (ContainerWidget)checkboxListTemplate.Clone(); var containerWidget = (ContainerWidget)checkboxListTemplate.Clone();
var checkboxWidget = containerWidget.Get<CheckboxWidget>("PACKAGE_CHECKBOX"); var checkboxWidget = containerWidget.Get<CheckboxWidget>("PACKAGE_CHECKBOX");
checkboxWidget.GetText = () => package.Title; var title = externalFluentBundle.GetString(package.Title);
checkboxWidget.GetText = () => title;
checkboxWidget.IsDisabled = () => package.Required; checkboxWidget.IsDisabled = () => package.Required;
checkboxWidget.IsChecked = () => selectedPackages[package.Identifier]; checkboxWidget.IsChecked = () => selectedPackages[package.Identifier];
checkboxWidget.OnClick = () => selectedPackages[package.Identifier] = !selectedPackages[package.Identifier]; checkboxWidget.OnClick = () => selectedPackages[package.Identifier] = !selectedPackages[package.Identifier];

View File

@@ -11,6 +11,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using OpenRA.FileSystem; using OpenRA.FileSystem;
using OpenRA.Widgets; using OpenRA.Widgets;
@@ -30,10 +31,12 @@ namespace OpenRA.Mods.Common.Widgets.Logic
readonly Dictionary<string, ModContent.ModSource> sources = new(); readonly Dictionary<string, ModContent.ModSource> sources = new();
readonly Dictionary<string, ModContent.ModDownload> downloads = new(); readonly Dictionary<string, ModContent.ModDownload> downloads = new();
readonly FluentBundle externalFluentBundle;
bool sourceAvailable; bool sourceAvailable;
[ObjectCreator.UseCtor] [ObjectCreator.UseCtor]
public ModContentLogic(Widget widget, Manifest mod, ModContent content, Action onCancel) public ModContentLogic(Widget widget, Manifest mod, ModContent content, Action onCancel, string translationFilePath)
{ {
this.content = content; this.content = content;
@@ -58,20 +61,25 @@ namespace OpenRA.Mods.Common.Widgets.Logic
modFileSystem.UnmountAll(); modFileSystem.UnmountAll();
externalFluentBundle = new FluentBundle(Game.Settings.Player.Language, File.ReadAllText(translationFilePath), _ => { });
scrollPanel = panel.Get<ScrollPanelWidget>("PACKAGES"); scrollPanel = panel.Get<ScrollPanelWidget>("PACKAGES");
template = scrollPanel.Get<ContainerWidget>("PACKAGE_TEMPLATE"); template = scrollPanel.Get<ContainerWidget>("PACKAGE_TEMPLATE");
var headerTemplate = panel.Get<LabelWidget>("HEADER_TEMPLATE"); var headerTemplate = panel.Get<LabelWidget>("HEADER_TEMPLATE");
var headerLines = !string.IsNullOrEmpty(content.HeaderMessage) ? content.HeaderMessage.Replace("\\n", "\n").Split('\n') : Array.Empty<string>(); var headerLines =
!string.IsNullOrEmpty(content.HeaderMessage)
? externalFluentBundle.GetString(content.HeaderMessage)
: null;
var headerHeight = 0; var headerHeight = 0;
foreach (var l in headerLines) if (headerLines != null)
{ {
var line = (LabelWidget)headerTemplate.Clone(); var label = (LabelWidget)headerTemplate.Clone();
line.GetText = () => l; label.GetText = () => headerLines;
line.Bounds.Y += headerHeight; label.IncreaseHeightToFitCurrentText();
panel.AddChild(line); panel.AddChild(label);
headerHeight += headerTemplate.Bounds.Height; headerHeight += label.Bounds.Height;
} }
panel.Bounds.Height += headerHeight; panel.Bounds.Height += headerHeight;
@@ -85,7 +93,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic
sourceButton.OnClick = () => Ui.OpenWindow("SOURCE_INSTALL_PANEL", new WidgetArgs sourceButton.OnClick = () => Ui.OpenWindow("SOURCE_INSTALL_PANEL", new WidgetArgs
{ {
{ "sources", sources }, { "sources", sources },
{ "content", content } { "content", content },
{ "externalFluentBundle", externalFluentBundle },
}); });
var backButton = panel.Get<ButtonWidget>("BACK_BUTTON"); var backButton = panel.Get<ButtonWidget>("BACK_BUTTON");
@@ -109,7 +118,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
{ {
var container = template.Clone(); var container = template.Clone();
var titleWidget = container.Get<LabelWidget>("TITLE"); var titleWidget = container.Get<LabelWidget>("TITLE");
var title = p.Value.Title; var title = externalFluentBundle.GetString(p.Value.Title);
titleWidget.GetText = () => title; titleWidget.GetText = () => title;
var requiredWidget = container.Get<LabelWidget>("REQUIRED"); var requiredWidget = container.Get<LabelWidget>("REQUIRED");

View File

@@ -27,14 +27,17 @@ namespace OpenRA.Mods.Common.Widgets.Logic
const string Quit = "button-quit"; const string Quit = "button-quit";
readonly ModContent content; readonly ModContent content;
readonly FluentBundle externalFluentBundle;
bool requiredContentInstalled; bool requiredContentInstalled;
[ObjectCreator.UseCtor] [ObjectCreator.UseCtor]
public ModContentPromptLogic(ModData modData, Widget widget, Manifest mod, ModContent content, Action continueLoading) public ModContentPromptLogic(ModData modData, Widget widget, Manifest mod, ModContent content, Action continueLoading, string translationFilePath)
{ {
this.content = content; this.content = content;
CheckRequiredContentInstalled(); CheckRequiredContentInstalled();
externalFluentBundle = new FluentBundle(Game.Settings.Player.Language, File.ReadAllText(translationFilePath), _ => { });
var continueMessage = FluentProvider.GetString(Continue); var continueMessage = FluentProvider.GetString(Continue);
var quitMessage = FluentProvider.GetString(Quit); var quitMessage = FluentProvider.GetString(Quit);
@@ -42,17 +45,17 @@ namespace OpenRA.Mods.Common.Widgets.Logic
var headerTemplate = panel.Get<LabelWidget>("HEADER_TEMPLATE"); var headerTemplate = panel.Get<LabelWidget>("HEADER_TEMPLATE");
var headerLines = var headerLines =
!string.IsNullOrEmpty(content.InstallPromptMessage) !string.IsNullOrEmpty(content.InstallPromptMessage)
? content.InstallPromptMessage.Replace("\\n", "\n").Split('\n') ? externalFluentBundle.GetString(content.InstallPromptMessage)
: Array.Empty<string>(); : null;
var headerHeight = 0; var headerHeight = 0;
foreach (var l in headerLines) if (headerLines != null)
{ {
var line = (LabelWidget)headerTemplate.Clone(); var label = (LabelWidget)headerTemplate.Clone();
line.GetText = () => l; label.GetText = () => headerLines;
line.Bounds.Y += headerHeight; label.IncreaseHeightToFitCurrentText();
panel.AddChild(line); panel.AddChild(label);
headerHeight += headerTemplate.Bounds.Height; headerHeight += label.Bounds.Height;
} }
panel.Bounds.Height += headerHeight; panel.Bounds.Height += headerHeight;
@@ -64,9 +67,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic
{ {
Ui.OpenWindow("CONTENT_PANEL", new WidgetArgs Ui.OpenWindow("CONTENT_PANEL", new WidgetArgs
{ {
{ "onCancel", CheckRequiredContentInstalled },
{ "mod", mod }, { "mod", mod },
{ "content", content }, { "content", content },
{ "onCancel", CheckRequiredContentInstalled } { "translationFilePath", translationFilePath },
}); });
}; };

View File

@@ -93,7 +93,12 @@ namespace OpenRA.Mods.Common.Widgets.Logic
return; return;
var content = modData.Manifest.Get<ModContent>(); var content = modData.Manifest.Get<ModContent>();
Game.InitializeMod(content.ContentInstallerMod, new Arguments(new[] { "Content.Mod=" + modData.Manifest.Id })); string translationPath;
using (var fs = (FileStream)modData.DefaultFileSystem.Open(content.Translation))
translationPath = fs.Name;
Game.InitializeMod(
content.ContentInstallerMod,
new Arguments(new[] { "Content.Mod=" + modData.Manifest.Id, "Content.TranslationFile=" + translationPath }));
}); });
}; };
} }

View File

@@ -93,9 +93,6 @@ namespace OpenRA.Server
modData.MapCache.LoadPreviewImages = false; // PERF: Server doesn't need previews, save memory by not loading them. modData.MapCache.LoadPreviewImages = false; // PERF: Server doesn't need previews, save memory by not loading them.
modData.MapCache.LoadMaps(); modData.MapCache.LoadMaps();
// HACK: Related to the above one, initialize fluent so we can resolve lobby option ids to strings.
FluentProvider.Initialize(modData, modData.DefaultFileSystem);
var endpoints = new List<IPEndPoint> { new(IPAddress.IPv6Any, settings.ListenPort), new(IPAddress.Any, settings.ListenPort) }; var endpoints = new List<IPEndPoint> { new(IPAddress.IPv6Any, settings.ListenPort), new(IPAddress.Any, settings.ListenPort) };
var server = new Server(endpoints, settings, modData, ServerType.Dedicated); var server = new Server(endpoints, settings, modData, ServerType.Dedicated);

View File

@@ -0,0 +1,6 @@
## Metadata
mod-title = Tiberian Dawn
mod-windowtitle = OpenRA - Tiberian Dawn
## CncLoadScreen
loadscreen-loading = Loading

View File

@@ -0,0 +1,13 @@
modcontent-installprompt =
Tiberian Dawn requires artwork and audio from the original game.
Quick Install will automatically download this content (without music or videos) from a mirror of the 2007 C&C Gold freeware release.
Advanced Install includes options for copying the music, videos, and other content from an original game disc or digital installation.
modcontent-header =
Game content may be extracted from the original game discs or an existing digital install. OpenRA can also download the base game files from an online mirror of the 2007 freeware release of C&C.
modcontent-package-basefiles = Base Game Files
modcontent-package-basemusic = Base Game Music
modcontent-package-gdi = GDI Campaign Briefings
modcontent-package-nod = Nod Campaign Briefings
modcontent-package-covertopsmusic = Covert Operations Music

View File

@@ -1,9 +1,9 @@
Metadata: Metadata:
Title: Tiberian Dawn Title: mod-title
Version: {DEV_VERSION} Version: {DEV_VERSION}
Website: https://www.openra.net Website: https://www.openra.net
WebIcon32: https://www.openra.net/images/icons/cnc_32x32.png WebIcon32: https://www.openra.net/images/icons/cnc_32x32.png
WindowTitle: OpenRA - Tiberian Dawn WindowTitle: mod-windowtitle
PackageFormats: Mix PackageFormats: Mix
@@ -146,6 +146,7 @@ ChromeLayout:
Translations: Translations:
common|languages/en.ftl common|languages/en.ftl
common|languages/rules/en.ftl common|languages/rules/en.ftl
cnc|languages/en.ftl
cnc|languages/chrome/en.ftl cnc|languages/chrome/en.ftl
cnc|languages/rules/en.ftl cnc|languages/rules/en.ftl
@@ -176,7 +177,6 @@ LoadScreen: CncLoadScreen
Image: cnc|uibits/chrome.png Image: cnc|uibits/chrome.png
Image2x: cnc|uibits/chrome-2x.png Image2x: cnc|uibits/chrome-2x.png
Image3x: cnc|uibits/chrome-3x.png Image3x: cnc|uibits/chrome-3x.png
Text: Loading
ServerTraits: ServerTraits:
LobbyCommands LobbyCommands
@@ -278,34 +278,34 @@ GameSpeeds:
OrderLatency: 6 OrderLatency: 6
ModContent: ModContent:
InstallPromptMessage: Tiberian Dawn requires artwork and audio from the original game.\n\nQuick Install will automatically download this content (without music\nor videos) from a mirror of the 2007 C&C Gold freeware release.\n\nAdvanced Install includes options for copying the music, videos, and\nother content from an original game disc or digital installation. InstallPromptMessage: modcontent-installprompt
QuickDownload: basefiles QuickDownload: basefiles
HeaderMessage: Game content may be extracted from the original game discs or an\nexisting digital install. OpenRA can also download the base game\nfiles from an online mirror of the 2007 freeware release of C&C. HeaderMessage: modcontent-header
Packages: Packages:
ContentPackage@base: ContentPackage@base:
Title: Base Game Files Title: modcontent-package-basefiles
Identifier: base Identifier: base
TestFiles: ^SupportDir|Content/cnc/conquer.mix, ^SupportDir|Content/cnc/desert.mix, ^SupportDir|Content/cnc/sounds.mix, ^SupportDir|Content/cnc/speech.mix, ^SupportDir|Content/cnc/temperat.mix, ^SupportDir|Content/cnc/tempicnh.mix, ^SupportDir|Content/cnc/winter.mix TestFiles: ^SupportDir|Content/cnc/conquer.mix, ^SupportDir|Content/cnc/desert.mix, ^SupportDir|Content/cnc/sounds.mix, ^SupportDir|Content/cnc/speech.mix, ^SupportDir|Content/cnc/temperat.mix, ^SupportDir|Content/cnc/tempicnh.mix, ^SupportDir|Content/cnc/winter.mix
Sources: gdi95, nod95, tfd, tuc-steam, tuc-origin, cncr-steam, cncr-origin Sources: gdi95, nod95, tfd, tuc-steam, tuc-origin, cncr-steam, cncr-origin
Required: true Required: true
Download: basefiles Download: basefiles
ContentPackage@music: ContentPackage@music:
Title: Base Game Music Title: modcontent-package-basemusic
Identifier: music Identifier: music
TestFiles: ^SupportDir|Content/cnc/scores.mix TestFiles: ^SupportDir|Content/cnc/scores.mix
Sources: gdi95, nod95, tfd, tuc-steam, tuc-origin, cncr-steam, cncr-origin Sources: gdi95, nod95, tfd, tuc-steam, tuc-origin, cncr-steam, cncr-origin
ContentPackage@movies-gdi: ContentPackage@movies-gdi:
Title: GDI Campaign Briefings Title: modcontent-package-gdi
Identifier: movies-gdi Identifier: movies-gdi
TestFiles: ^SupportDir|Content/cnc/movies/visor.vqa, ^SupportDir|Content/cnc/movies/turtkill.vqa, ^SupportDir|Content/cnc/movies/tbrinfo3.vqa, ^SupportDir|Content/cnc/movies/tbrinfo2.vqa, ^SupportDir|Content/cnc/movies/tbrinfo1.vqa, ^SupportDir|Content/cnc/movies/seige.vqa, ^SupportDir|Content/cnc/movies/samsite.vqa, ^SupportDir|Content/cnc/movies/samdie.vqa, ^SupportDir|Content/cnc/movies/sabotage.vqa, ^SupportDir|Content/cnc/movies/retro.vqa, ^SupportDir|Content/cnc/movies/podium.vqa, ^SupportDir|Content/cnc/movies/planecra.vqa, ^SupportDir|Content/cnc/movies/pintle.vqa, ^SupportDir|Content/cnc/movies/paratrop.vqa, ^SupportDir|Content/cnc/movies/nodsweep.vqa, ^SupportDir|Content/cnc/movies/nodlose.vqa, ^SupportDir|Content/cnc/movies/nodflees.vqa, ^SupportDir|Content/cnc/movies/nod1.vqa, ^SupportDir|Content/cnc/movies/nitejump.vqa, ^SupportDir|Content/cnc/movies/napalm.vqa, ^SupportDir|Content/cnc/movies/logo.vqa, ^SupportDir|Content/cnc/movies/landing.vqa, ^SupportDir|Content/cnc/movies/intro2.vqa, ^SupportDir|Content/cnc/movies/hellvaly.vqa, ^SupportDir|Content/cnc/movies/gunboat.vqa, ^SupportDir|Content/cnc/movies/generic.vqa, ^SupportDir|Content/cnc/movies/gdilose.vqa, ^SupportDir|Content/cnc/movies/gdifinb.vqa, ^SupportDir|Content/cnc/movies/gdifina.vqa, ^SupportDir|Content/cnc/movies/gdiend2.vqa, ^SupportDir|Content/cnc/movies/gdiend1.vqa, ^SupportDir|Content/cnc/movies/gdi9.vqa, ^SupportDir|Content/cnc/movies/gdi8b.vqa, ^SupportDir|Content/cnc/movies/gdi8a.vqa, ^SupportDir|Content/cnc/movies/gdi7.vqa, ^SupportDir|Content/cnc/movies/gdi6.vqa, ^SupportDir|Content/cnc/movies/gdi5.vqa, ^SupportDir|Content/cnc/movies/gdi4b.vqa, ^SupportDir|Content/cnc/movies/gdi4a.vqa, ^SupportDir|Content/cnc/movies/gdi3lose.vqa, ^SupportDir|Content/cnc/movies/gdi3.vqa, ^SupportDir|Content/cnc/movies/gdi2.vqa, ^SupportDir|Content/cnc/movies/gdi15.vqa, ^SupportDir|Content/cnc/movies/gdi14.vqa, ^SupportDir|Content/cnc/movies/gdi13.vqa, ^SupportDir|Content/cnc/movies/gdi12.vqa, ^SupportDir|Content/cnc/movies/gdi11.vqa, ^SupportDir|Content/cnc/movies/gdi10.vqa, ^SupportDir|Content/cnc/movies/gdi1.vqa, ^SupportDir|Content/cnc/movies/gameover.vqa, ^SupportDir|Content/cnc/movies/forestkl.vqa, ^SupportDir|Content/cnc/movies/flyy.vqa, ^SupportDir|Content/cnc/movies/flag.vqa, ^SupportDir|Content/cnc/movies/dino.vqa, ^SupportDir|Content/cnc/movies/desolat.vqa, ^SupportDir|Content/cnc/movies/consyard.vqa, ^SupportDir|Content/cnc/movies/cc2tease.vqa, ^SupportDir|Content/cnc/movies/burdet2.vqa, ^SupportDir|Content/cnc/movies/burdet1.vqa, ^SupportDir|Content/cnc/movies/bombflee.vqa, ^SupportDir|Content/cnc/movies/bombaway.vqa, ^SupportDir|Content/cnc/movies/bkground.vqa, ^SupportDir|Content/cnc/movies/bcanyon.vqa, ^SupportDir|Content/cnc/movies/banner.vqa TestFiles: ^SupportDir|Content/cnc/movies/visor.vqa, ^SupportDir|Content/cnc/movies/turtkill.vqa, ^SupportDir|Content/cnc/movies/tbrinfo3.vqa, ^SupportDir|Content/cnc/movies/tbrinfo2.vqa, ^SupportDir|Content/cnc/movies/tbrinfo1.vqa, ^SupportDir|Content/cnc/movies/seige.vqa, ^SupportDir|Content/cnc/movies/samsite.vqa, ^SupportDir|Content/cnc/movies/samdie.vqa, ^SupportDir|Content/cnc/movies/sabotage.vqa, ^SupportDir|Content/cnc/movies/retro.vqa, ^SupportDir|Content/cnc/movies/podium.vqa, ^SupportDir|Content/cnc/movies/planecra.vqa, ^SupportDir|Content/cnc/movies/pintle.vqa, ^SupportDir|Content/cnc/movies/paratrop.vqa, ^SupportDir|Content/cnc/movies/nodsweep.vqa, ^SupportDir|Content/cnc/movies/nodlose.vqa, ^SupportDir|Content/cnc/movies/nodflees.vqa, ^SupportDir|Content/cnc/movies/nod1.vqa, ^SupportDir|Content/cnc/movies/nitejump.vqa, ^SupportDir|Content/cnc/movies/napalm.vqa, ^SupportDir|Content/cnc/movies/logo.vqa, ^SupportDir|Content/cnc/movies/landing.vqa, ^SupportDir|Content/cnc/movies/intro2.vqa, ^SupportDir|Content/cnc/movies/hellvaly.vqa, ^SupportDir|Content/cnc/movies/gunboat.vqa, ^SupportDir|Content/cnc/movies/generic.vqa, ^SupportDir|Content/cnc/movies/gdilose.vqa, ^SupportDir|Content/cnc/movies/gdifinb.vqa, ^SupportDir|Content/cnc/movies/gdifina.vqa, ^SupportDir|Content/cnc/movies/gdiend2.vqa, ^SupportDir|Content/cnc/movies/gdiend1.vqa, ^SupportDir|Content/cnc/movies/gdi9.vqa, ^SupportDir|Content/cnc/movies/gdi8b.vqa, ^SupportDir|Content/cnc/movies/gdi8a.vqa, ^SupportDir|Content/cnc/movies/gdi7.vqa, ^SupportDir|Content/cnc/movies/gdi6.vqa, ^SupportDir|Content/cnc/movies/gdi5.vqa, ^SupportDir|Content/cnc/movies/gdi4b.vqa, ^SupportDir|Content/cnc/movies/gdi4a.vqa, ^SupportDir|Content/cnc/movies/gdi3lose.vqa, ^SupportDir|Content/cnc/movies/gdi3.vqa, ^SupportDir|Content/cnc/movies/gdi2.vqa, ^SupportDir|Content/cnc/movies/gdi15.vqa, ^SupportDir|Content/cnc/movies/gdi14.vqa, ^SupportDir|Content/cnc/movies/gdi13.vqa, ^SupportDir|Content/cnc/movies/gdi12.vqa, ^SupportDir|Content/cnc/movies/gdi11.vqa, ^SupportDir|Content/cnc/movies/gdi10.vqa, ^SupportDir|Content/cnc/movies/gdi1.vqa, ^SupportDir|Content/cnc/movies/gameover.vqa, ^SupportDir|Content/cnc/movies/forestkl.vqa, ^SupportDir|Content/cnc/movies/flyy.vqa, ^SupportDir|Content/cnc/movies/flag.vqa, ^SupportDir|Content/cnc/movies/dino.vqa, ^SupportDir|Content/cnc/movies/desolat.vqa, ^SupportDir|Content/cnc/movies/consyard.vqa, ^SupportDir|Content/cnc/movies/cc2tease.vqa, ^SupportDir|Content/cnc/movies/burdet2.vqa, ^SupportDir|Content/cnc/movies/burdet1.vqa, ^SupportDir|Content/cnc/movies/bombflee.vqa, ^SupportDir|Content/cnc/movies/bombaway.vqa, ^SupportDir|Content/cnc/movies/bkground.vqa, ^SupportDir|Content/cnc/movies/bcanyon.vqa, ^SupportDir|Content/cnc/movies/banner.vqa
Sources: gdi95, tfd, tuc-steam, tuc-origin, cncr-steam, cncr-origin Sources: gdi95, tfd, tuc-steam, tuc-origin, cncr-steam, cncr-origin
ContentPackage@movies-nod: ContentPackage@movies-nod:
Title: Nod Campaign Briefings Title: modcontent-package-nod
Identifier: movies-nod Identifier: movies-nod
TestFiles: ^SupportDir|Content/cnc/movies/visor.vqa, ^SupportDir|Content/cnc/movies/trtkil_d.vqa, ^SupportDir|Content/cnc/movies/tiberfx.vqa, ^SupportDir|Content/cnc/movies/tankkill.vqa, ^SupportDir|Content/cnc/movies/tankgo.vqa, ^SupportDir|Content/cnc/movies/sundial.vqa, ^SupportDir|Content/cnc/movies/stealth.vqa, ^SupportDir|Content/cnc/movies/spycrash.vqa, ^SupportDir|Content/cnc/movies/sethpre.vqa, ^SupportDir|Content/cnc/movies/seige.vqa, ^SupportDir|Content/cnc/movies/samsite.vqa, ^SupportDir|Content/cnc/movies/retro.vqa, ^SupportDir|Content/cnc/movies/refint.vqa, ^SupportDir|Content/cnc/movies/obel.vqa, ^SupportDir|Content/cnc/movies/nuke.vqa, ^SupportDir|Content/cnc/movies/nodlose.vqa, ^SupportDir|Content/cnc/movies/nodfinal.vqa, ^SupportDir|Content/cnc/movies/nodend4.vqa, ^SupportDir|Content/cnc/movies/nodend3.vqa, ^SupportDir|Content/cnc/movies/nodend2.vqa, ^SupportDir|Content/cnc/movies/nodend1.vqa, ^SupportDir|Content/cnc/movies/nod9.vqa, ^SupportDir|Content/cnc/movies/nod8.vqa, ^SupportDir|Content/cnc/movies/nod7b.vqa, ^SupportDir|Content/cnc/movies/nod7a.vqa, ^SupportDir|Content/cnc/movies/nod6.vqa, ^SupportDir|Content/cnc/movies/nod5.vqa, ^SupportDir|Content/cnc/movies/nod4b.vqa, ^SupportDir|Content/cnc/movies/nod4a.vqa, ^SupportDir|Content/cnc/movies/nod3.vqa, ^SupportDir|Content/cnc/movies/nod2.vqa, ^SupportDir|Content/cnc/movies/nod1pre.vqa, ^SupportDir|Content/cnc/movies/nod13.vqa, ^SupportDir|Content/cnc/movies/nod12.vqa, ^SupportDir|Content/cnc/movies/nod11.vqa, ^SupportDir|Content/cnc/movies/nod10b.vqa, ^SupportDir|Content/cnc/movies/nod10a.vqa, ^SupportDir|Content/cnc/movies/nod1.vqa, ^SupportDir|Content/cnc/movies/logo.vqa, ^SupportDir|Content/cnc/movies/landing.vqa, ^SupportDir|Content/cnc/movies/kanepre.vqa, ^SupportDir|Content/cnc/movies/intro2.vqa, ^SupportDir|Content/cnc/movies/insites.vqa, ^SupportDir|Content/cnc/movies/generic.vqa, ^SupportDir|Content/cnc/movies/gdi1.vqa, ^SupportDir|Content/cnc/movies/gameover.vqa, ^SupportDir|Content/cnc/movies/forestkl.vqa, ^SupportDir|Content/cnc/movies/flag.vqa, ^SupportDir|Content/cnc/movies/dino.vqa, ^SupportDir|Content/cnc/movies/dessweep.vqa, ^SupportDir|Content/cnc/movies/deskill.vqa, ^SupportDir|Content/cnc/movies/desflees.vqa, ^SupportDir|Content/cnc/movies/consyard.vqa, ^SupportDir|Content/cnc/movies/cc2tease.vqa, ^SupportDir|Content/cnc/movies/bombflee.vqa, ^SupportDir|Content/cnc/movies/bombaway.vqa, ^SupportDir|Content/cnc/movies/bcanyon.vqa, ^SupportDir|Content/cnc/movies/banner.vqa, ^SupportDir|Content/cnc/movies/akira.vqa, ^SupportDir|Content/cnc/movies/airstrk.vqa TestFiles: ^SupportDir|Content/cnc/movies/visor.vqa, ^SupportDir|Content/cnc/movies/trtkil_d.vqa, ^SupportDir|Content/cnc/movies/tiberfx.vqa, ^SupportDir|Content/cnc/movies/tankkill.vqa, ^SupportDir|Content/cnc/movies/tankgo.vqa, ^SupportDir|Content/cnc/movies/sundial.vqa, ^SupportDir|Content/cnc/movies/stealth.vqa, ^SupportDir|Content/cnc/movies/spycrash.vqa, ^SupportDir|Content/cnc/movies/sethpre.vqa, ^SupportDir|Content/cnc/movies/seige.vqa, ^SupportDir|Content/cnc/movies/samsite.vqa, ^SupportDir|Content/cnc/movies/retro.vqa, ^SupportDir|Content/cnc/movies/refint.vqa, ^SupportDir|Content/cnc/movies/obel.vqa, ^SupportDir|Content/cnc/movies/nuke.vqa, ^SupportDir|Content/cnc/movies/nodlose.vqa, ^SupportDir|Content/cnc/movies/nodfinal.vqa, ^SupportDir|Content/cnc/movies/nodend4.vqa, ^SupportDir|Content/cnc/movies/nodend3.vqa, ^SupportDir|Content/cnc/movies/nodend2.vqa, ^SupportDir|Content/cnc/movies/nodend1.vqa, ^SupportDir|Content/cnc/movies/nod9.vqa, ^SupportDir|Content/cnc/movies/nod8.vqa, ^SupportDir|Content/cnc/movies/nod7b.vqa, ^SupportDir|Content/cnc/movies/nod7a.vqa, ^SupportDir|Content/cnc/movies/nod6.vqa, ^SupportDir|Content/cnc/movies/nod5.vqa, ^SupportDir|Content/cnc/movies/nod4b.vqa, ^SupportDir|Content/cnc/movies/nod4a.vqa, ^SupportDir|Content/cnc/movies/nod3.vqa, ^SupportDir|Content/cnc/movies/nod2.vqa, ^SupportDir|Content/cnc/movies/nod1pre.vqa, ^SupportDir|Content/cnc/movies/nod13.vqa, ^SupportDir|Content/cnc/movies/nod12.vqa, ^SupportDir|Content/cnc/movies/nod11.vqa, ^SupportDir|Content/cnc/movies/nod10b.vqa, ^SupportDir|Content/cnc/movies/nod10a.vqa, ^SupportDir|Content/cnc/movies/nod1.vqa, ^SupportDir|Content/cnc/movies/logo.vqa, ^SupportDir|Content/cnc/movies/landing.vqa, ^SupportDir|Content/cnc/movies/kanepre.vqa, ^SupportDir|Content/cnc/movies/intro2.vqa, ^SupportDir|Content/cnc/movies/insites.vqa, ^SupportDir|Content/cnc/movies/generic.vqa, ^SupportDir|Content/cnc/movies/gdi1.vqa, ^SupportDir|Content/cnc/movies/gameover.vqa, ^SupportDir|Content/cnc/movies/forestkl.vqa, ^SupportDir|Content/cnc/movies/flag.vqa, ^SupportDir|Content/cnc/movies/dino.vqa, ^SupportDir|Content/cnc/movies/dessweep.vqa, ^SupportDir|Content/cnc/movies/deskill.vqa, ^SupportDir|Content/cnc/movies/desflees.vqa, ^SupportDir|Content/cnc/movies/consyard.vqa, ^SupportDir|Content/cnc/movies/cc2tease.vqa, ^SupportDir|Content/cnc/movies/bombflee.vqa, ^SupportDir|Content/cnc/movies/bombaway.vqa, ^SupportDir|Content/cnc/movies/bcanyon.vqa, ^SupportDir|Content/cnc/movies/banner.vqa, ^SupportDir|Content/cnc/movies/akira.vqa, ^SupportDir|Content/cnc/movies/airstrk.vqa
Sources: nod95, tfd, tuc-steam, tuc-origin, cncr-steam, cncr-origin Sources: nod95, tfd, tuc-steam, tuc-origin, cncr-steam, cncr-origin
ContentPackage@music-covertops: ContentPackage@music-covertops:
Title: Covert Operations Music Title: modcontent-package-covertopsmusic
Identifier: music-covertops Identifier: music-covertops
TestFiles: ^SupportDir|Content/cnc/scores-covertops.mix TestFiles: ^SupportDir|Content/cnc/scores-covertops.mix
Sources: covertops, tfd, tuc-steam, tuc-origin, cncr-steam, cncr-origin Sources: covertops, tfd, tuc-steam, tuc-origin, cncr-steam, cncr-origin
@@ -318,6 +318,7 @@ ModContent:
cnc|installer/nod95.yaml cnc|installer/nod95.yaml
cnc|installer/origin.yaml cnc|installer/origin.yaml
cnc|installer/steam.yaml cnc|installer/steam.yaml
Translation: cnc|languages/modcontent/en.ftl
DiscordService: DiscordService:
ApplicationId: 699223250181292033 ApplicationId: 699223250181292033

View File

@@ -0,0 +1,6 @@
## Metadata
mod-title = Dune 2000
mod-windowtitle = OpenRA - Dune 2000
## LogoStripLoadScreen
loadscreen-loading = Filling Crates..., Breeding Sandworms..., Fuelling carryalls..., Deploying harvesters..., Preparing thopters..., Summoning mentats...

View File

@@ -0,0 +1,12 @@
modcontent-installprompt =
Dune 2000 requires artwork and audio from the original game.
Quick Install will automatically download this content (without music or videos) from an online mirror of the game files.
Advanced Install includes options for copying the music, videos, and other content from an original game disc.
modcontent-header =
The original game content may be copied from an original game disc, or downloaded from an online mirror of the game files.
modcontent-package-basefiles = Base Game Files
modcontent-package-106patch = 1.06 Patch Content
modcontent-package-music = Game Music
modcontent-package-briefings = Campaign Briefings

View File

@@ -1,9 +1,9 @@
Metadata: Metadata:
Title: Dune 2000 Title: mod-title
Version: {DEV_VERSION} Version: {DEV_VERSION}
Website: https://www.openra.net Website: https://www.openra.net
WebIcon32: https://www.openra.net/images/icons/d2k_32x32.png WebIcon32: https://www.openra.net/images/icons/d2k_32x32.png
WindowTitle: OpenRA - Dune 2000 WindowTitle: mod-windowtitle
PackageFormats: D2kSoundResources PackageFormats: D2kSoundResources
@@ -124,6 +124,7 @@ Translations:
common|languages/en.ftl common|languages/en.ftl
common|languages/chrome/en.ftl common|languages/chrome/en.ftl
common|languages/rules/en.ftl common|languages/rules/en.ftl
d2k|languages/en.ftl
d2k|languages/chrome/en.ftl d2k|languages/chrome/en.ftl
d2k|languages/rules/en.ftl d2k|languages/rules/en.ftl
@@ -160,7 +161,6 @@ LoadScreen: LogoStripeLoadScreen
Image: d2k|uibits/loadscreen.png Image: d2k|uibits/loadscreen.png
Image2x: d2k|uibits/loadscreen-2x.png Image2x: d2k|uibits/loadscreen-2x.png
Image3x: d2k|uibits/loadscreen-3x.png Image3x: d2k|uibits/loadscreen-3x.png
Text: Filling Crates..., Breeding Sandworms..., Fuelling carryalls..., Deploying harvesters..., Preparing thopters..., Summoning mentats...
ServerTraits: ServerTraits:
LobbyCommands LobbyCommands
@@ -259,31 +259,31 @@ GameSpeeds:
OrderLatency: 6 OrderLatency: 6
ModContent: ModContent:
InstallPromptMessage: Dune 2000 requires artwork and audio from the original game.\n\nQuick Install will automatically download this content (without\nmusic or videos) from an online mirror of the game files.\n\nAdvanced Install includes options for copying the music, videos,\nand other content from an original game disc. InstallPromptMessage: modcontent-installprompt
HeaderMessage: The original game content may be copied from an original game disc,\nor downloaded from an online mirror of the game files. HeaderMessage: modcontent-header
QuickDownload: quickinstall QuickDownload: quickinstall
Packages: Packages:
ContentPackage@base: ContentPackage@base:
Title: Base Game Files Title: modcontent-package-basefiles
Identifier: base Identifier: base
TestFiles: ^SupportDir|Content/d2k/v3/BLOXBASE.R16, ^SupportDir|Content/d2k/v3/BLOXBAT.R16, ^SupportDir|Content/d2k/v3/BLOXBGBS.R16, ^SupportDir|Content/d2k/v3/BLOXICE.R16, ^SupportDir|Content/d2k/v3/BLOXTREE.R16, ^SupportDir|Content/d2k/v3/BLOXWAST.R16, ^SupportDir|Content/d2k/v3/SOUND.RS, ^SupportDir|Content/d2k/v3/PALETTE.BIN TestFiles: ^SupportDir|Content/d2k/v3/BLOXBASE.R16, ^SupportDir|Content/d2k/v3/BLOXBAT.R16, ^SupportDir|Content/d2k/v3/BLOXBGBS.R16, ^SupportDir|Content/d2k/v3/BLOXICE.R16, ^SupportDir|Content/d2k/v3/BLOXTREE.R16, ^SupportDir|Content/d2k/v3/BLOXWAST.R16, ^SupportDir|Content/d2k/v3/SOUND.RS, ^SupportDir|Content/d2k/v3/PALETTE.BIN
Sources: d2k, gruntmods Sources: d2k, gruntmods
Required: true Required: true
Download: basefiles Download: basefiles
ContentPackage@patch: ContentPackage@patch:
Title: 1.06 Patch Content Title: modcontent-package-106patch
Identifier: patch Identifier: patch
TestFiles: ^SupportDir|Content/d2k/v3/DATA.R16 TestFiles: ^SupportDir|Content/d2k/v3/DATA.R16
Sources: gruntmods Sources: gruntmods
Required: true Required: true
Download: patch106 Download: patch106
ContentPackage@music: ContentPackage@music:
Title: Game Music Title: modcontent-package-music
Identifier: music Identifier: music
TestFiles: ^SupportDir|Content/d2k/v3/Music/AMBUSH.AUD, ^SupportDir|Content/d2k/v3/Music/WAITGAME.AUD TestFiles: ^SupportDir|Content/d2k/v3/Music/AMBUSH.AUD, ^SupportDir|Content/d2k/v3/Music/WAITGAME.AUD
Sources: d2k, gruntmods Sources: d2k, gruntmods
ContentPackage@movies: ContentPackage@movies:
Title: Campaign Briefings Title: modcontent-package-briefings
Identifier: movies Identifier: movies
TestFiles: ^SupportDir|Content/d2k/v3/Movies/A_BR01_E.VQA TestFiles: ^SupportDir|Content/d2k/v3/Movies/A_BR01_E.VQA
Sources: d2k Sources: d2k
@@ -292,6 +292,7 @@ ModContent:
Sources: Sources:
d2k|installer/d2k.yaml d2k|installer/d2k.yaml
d2k|installer/gruntmods.yaml d2k|installer/gruntmods.yaml
Translation: d2k|languages/modcontent/en.ftl
DiscordService: DiscordService:
ApplicationId: 712711732770111550 ApplicationId: 712711732770111550

View File

@@ -21,10 +21,12 @@ Background@CONTENT_PANEL:
Align: Center Align: Center
Font: MediumBold Font: MediumBold
Label@HEADER_TEMPLATE: Label@HEADER_TEMPLATE:
X: 30
Y: 66 Y: 66
Width: PARENT_RIGHT Width: PARENT_RIGHT - 60
Height: 16 Height: 16
Align: Center Align: Center
WordWrap: true
ScrollPanel@PACKAGES: ScrollPanel@PACKAGES:
X: 30 X: 30
Y: 84 Y: 84
@@ -342,10 +344,12 @@ Background@CONTENT_PROMPT_PANEL:
Align: Center Align: Center
Font: MediumBold Font: MediumBold
Label@HEADER_TEMPLATE: Label@HEADER_TEMPLATE:
X: 30
Y: 65 Y: 65
Width: PARENT_RIGHT Width: PARENT_RIGHT - 60
Height: 16 Height: 16
Align: Center Align: Center
WordWrap: true
Button@ADVANCED_BUTTON: Button@ADVANCED_BUTTON:
X: 30 X: 30
Y: PARENT_BOTTOM - 52 Y: PARENT_BOTTOM - 52

View File

@@ -0,0 +1,2 @@
## Metadata
mod-title = Mod Content Manager

View File

@@ -1,5 +1,5 @@
Metadata: Metadata:
Title: Mod Content Manager Title: mod-title
Version: {DEV_VERSION} Version: {DEV_VERSION}
Hidden: true Hidden: true
@@ -37,6 +37,7 @@ ChromeMetrics:
Translations: Translations:
common|languages/en.ftl common|languages/en.ftl
modcontent|languages/en.ftl
Fonts: Fonts:
Tiny: Tiny:

6
mods/ra/languages/en.ftl Normal file
View File

@@ -0,0 +1,6 @@
## Metadata
mod-title = Red Alert
mod-windowtitle = OpenRA - Red Alert
## LogoStripeLoadScreen
loadscreen-loading = Filling Crates..., Charging Capacitors..., Reticulating Splines..., Planting Trees..., Building Bridges..., Aging Empires..., Compiling EVA..., Constructing Pylons..., Activating Skynet..., Splitting Atoms...

View File

@@ -0,0 +1,16 @@
modcontent-installprompt =
Red Alert requires artwork and audio from the original game.
Quick Install will automatically download this content (without music or videos) from a mirror of the 2008 Red Alert freeware release.
Advanced Install includes options for copying the music, videos, and other content from an original game disc or digital installation.
modcontent-header =
Game content may be extracted from the original game discs or an existing digital install. OpenRA can also download the base game files from an online mirror of the 2008 freeware release of RA.
modcontent-package-basefiles = Base Game Files
modcontent-package-aftermathfiles = Aftermath Expansion Files
modcontent-package-deserttileset = C&C Desert Tileset
modcontent-package-basemusic = Base Game Music
modcontent-package-allied = Allied Campaign Briefings
modcontent-package-soviet = Soviet Campaign Briefings
modcontent-package-counterstrikemusic = Counterstrike Music
modcontent-package-aftermathmusic = Aftermath Music

View File

@@ -1,9 +1,9 @@
Metadata: Metadata:
Title: Red Alert Title: mod-title
Version: {DEV_VERSION} Version: {DEV_VERSION}
Website: https://www.openra.net Website: https://www.openra.net
WebIcon32: https://www.openra.net/images/icons/ra_32x32.png WebIcon32: https://www.openra.net/images/icons/ra_32x32.png
WindowTitle: OpenRA - Red Alert WindowTitle: mod-windowtitle
PackageFormats: Mix PackageFormats: Mix
@@ -142,6 +142,7 @@ Translations:
common|languages/en.ftl common|languages/en.ftl
common|languages/chrome/en.ftl common|languages/chrome/en.ftl
common|languages/rules/en.ftl common|languages/rules/en.ftl
ra|languages/en.ftl
ra|languages/chrome/en.ftl ra|languages/chrome/en.ftl
ra|languages/rules/en.ftl ra|languages/rules/en.ftl
@@ -179,7 +180,6 @@ LoadScreen: LogoStripeLoadScreen
Image: ra|uibits/loadscreen.png Image: ra|uibits/loadscreen.png
Image2x: ra|uibits/loadscreen-2x.png Image2x: ra|uibits/loadscreen-2x.png
Image3x: ra|uibits/loadscreen-3x.png Image3x: ra|uibits/loadscreen-3x.png
Text: Filling Crates..., Charging Capacitors..., Reticulating Splines..., Planting Trees..., Building Bridges..., Aging Empires..., Compiling EVA..., Constructing Pylons..., Activating Skynet..., Splitting Atoms...
ServerTraits: ServerTraits:
LobbyCommands LobbyCommands
@@ -281,53 +281,53 @@ GameSpeeds:
OrderLatency: 6 OrderLatency: 6
ModContent: ModContent:
InstallPromptMessage: Red Alert requires artwork and audio from the original game.\n\nQuick Install will automatically download this content (without music\nor videos) from a mirror of the 2008 Red Alert freeware release.\n\nAdvanced Install includes options for copying the music, videos, and\nother content from an original game disc or digital installation. InstallPromptMessage: modcontent-installprompt
QuickDownload: quickinstall QuickDownload: quickinstall
HeaderMessage: Game content may be extracted from the original game discs or an\nexisting digital install. OpenRA can also download the base game\nfiles from an online mirror of the 2008 freeware release of RA. HeaderMessage: modcontent-header
Packages: Packages:
ContentPackage@base: ContentPackage@base:
Title: Base Game Files Title: modcontent-package-basefiles
Identifier: base Identifier: base
TestFiles: ^SupportDir|Content/ra/v2/allies.mix, ^SupportDir|Content/ra/v2/conquer.mix, ^SupportDir|Content/ra/v2/interior.mix, ^SupportDir|Content/ra/v2/hires.mix, ^SupportDir|Content/ra/v2/lores.mix, ^SupportDir|Content/ra/v2/local.mix, ^SupportDir|Content/ra/v2/speech.mix, ^SupportDir|Content/ra/v2/russian.mix, ^SupportDir|Content/ra/v2/snow.mix, ^SupportDir|Content/ra/v2/sounds.mix, ^SupportDir|Content/ra/v2/temperat.mix TestFiles: ^SupportDir|Content/ra/v2/allies.mix, ^SupportDir|Content/ra/v2/conquer.mix, ^SupportDir|Content/ra/v2/interior.mix, ^SupportDir|Content/ra/v2/hires.mix, ^SupportDir|Content/ra/v2/lores.mix, ^SupportDir|Content/ra/v2/local.mix, ^SupportDir|Content/ra/v2/speech.mix, ^SupportDir|Content/ra/v2/russian.mix, ^SupportDir|Content/ra/v2/snow.mix, ^SupportDir|Content/ra/v2/sounds.mix, ^SupportDir|Content/ra/v2/temperat.mix
Sources: allied, soviet, tfd, ra-steam, ra-origin, cncr-steam, cncr-origin Sources: allied, soviet, tfd, ra-steam, ra-origin, cncr-steam, cncr-origin
Required: true Required: true
Download: basefiles Download: basefiles
ContentPackage@aftermathbase: ContentPackage@aftermathbase:
Title: Aftermath Expansion Files Title: modcontent-package-aftermathfiles
Identifier: aftermathbase Identifier: aftermathbase
TestFiles: ^SupportDir|Content/ra/v2/expand/expand2.mix, ^SupportDir|Content/ra/v2/expand/hires1.mix, ^SupportDir|Content/ra/v2/expand/lores1.mix, ^SupportDir|Content/ra/v2/expand/chrotnk1.aud, ^SupportDir|Content/ra/v2/expand/fixit1.aud, ^SupportDir|Content/ra/v2/expand/jburn1.aud, ^SupportDir|Content/ra/v2/expand/jchrge1.aud, ^SupportDir|Content/ra/v2/expand/jcrisp1.aud, ^SupportDir|Content/ra/v2/expand/jdance1.aud, ^SupportDir|Content/ra/v2/expand/jjuice1.aud, ^SupportDir|Content/ra/v2/expand/jjump1.aud, ^SupportDir|Content/ra/v2/expand/jlight1.aud, ^SupportDir|Content/ra/v2/expand/jpower1.aud, ^SupportDir|Content/ra/v2/expand/jshock1.aud, ^SupportDir|Content/ra/v2/expand/jyes1.aud, ^SupportDir|Content/ra/v2/expand/madchrg2.aud, ^SupportDir|Content/ra/v2/expand/madexplo.aud, ^SupportDir|Content/ra/v2/expand/mboss1.aud, ^SupportDir|Content/ra/v2/expand/mhear1.aud, ^SupportDir|Content/ra/v2/expand/mhotdig1.aud, ^SupportDir|Content/ra/v2/expand/mhowdy1.aud, ^SupportDir|Content/ra/v2/expand/mhuh1.aud, ^SupportDir|Content/ra/v2/expand/mlaff1.aud, ^SupportDir|Content/ra/v2/expand/mrise1.aud, ^SupportDir|Content/ra/v2/expand/mwrench1.aud, ^SupportDir|Content/ra/v2/expand/myeehaw1.aud, ^SupportDir|Content/ra/v2/expand/myes1.aud TestFiles: ^SupportDir|Content/ra/v2/expand/expand2.mix, ^SupportDir|Content/ra/v2/expand/hires1.mix, ^SupportDir|Content/ra/v2/expand/lores1.mix, ^SupportDir|Content/ra/v2/expand/chrotnk1.aud, ^SupportDir|Content/ra/v2/expand/fixit1.aud, ^SupportDir|Content/ra/v2/expand/jburn1.aud, ^SupportDir|Content/ra/v2/expand/jchrge1.aud, ^SupportDir|Content/ra/v2/expand/jcrisp1.aud, ^SupportDir|Content/ra/v2/expand/jdance1.aud, ^SupportDir|Content/ra/v2/expand/jjuice1.aud, ^SupportDir|Content/ra/v2/expand/jjump1.aud, ^SupportDir|Content/ra/v2/expand/jlight1.aud, ^SupportDir|Content/ra/v2/expand/jpower1.aud, ^SupportDir|Content/ra/v2/expand/jshock1.aud, ^SupportDir|Content/ra/v2/expand/jyes1.aud, ^SupportDir|Content/ra/v2/expand/madchrg2.aud, ^SupportDir|Content/ra/v2/expand/madexplo.aud, ^SupportDir|Content/ra/v2/expand/mboss1.aud, ^SupportDir|Content/ra/v2/expand/mhear1.aud, ^SupportDir|Content/ra/v2/expand/mhotdig1.aud, ^SupportDir|Content/ra/v2/expand/mhowdy1.aud, ^SupportDir|Content/ra/v2/expand/mhuh1.aud, ^SupportDir|Content/ra/v2/expand/mlaff1.aud, ^SupportDir|Content/ra/v2/expand/mrise1.aud, ^SupportDir|Content/ra/v2/expand/mwrench1.aud, ^SupportDir|Content/ra/v2/expand/myeehaw1.aud, ^SupportDir|Content/ra/v2/expand/myes1.aud
Sources: aftermath, tfd, ra-steam, ra-origin, cncr-steam, cncr-origin Sources: aftermath, tfd, ra-steam, ra-origin, cncr-steam, cncr-origin
Required: true Required: true
Download: aftermath Download: aftermath
ContentPackage@cncdesert: ContentPackage@cncdesert:
Title: C&C Desert Tileset Title: modcontent-package-deserttileset
Identifier: cncdesert Identifier: cncdesert
TestFiles: ^SupportDir|Content/ra/v2/cnc/desert.mix TestFiles: ^SupportDir|Content/ra/v2/cnc/desert.mix
Sources: tfd, cnc-steam, cnc-origin, cnc95, cncr-steam, cncr-origin Sources: tfd, cnc-steam, cnc-origin, cnc95, cncr-steam, cncr-origin
Required: true Required: true
Download: cncdesert Download: cncdesert
ContentPackage@music: ContentPackage@music:
Title: Base Game Music Title: modcontent-package-basemusic
Identifier: music Identifier: music
TestFiles: ^SupportDir|Content/ra/v2/scores.mix TestFiles: ^SupportDir|Content/ra/v2/scores.mix
Sources: allied, soviet, tfd, ra-steam, ra-origin, cncr-steam, cncr-origin Sources: allied, soviet, tfd, ra-steam, ra-origin, cncr-steam, cncr-origin
ContentPackage@movies-allied: ContentPackage@movies-allied:
Title: Allied Campaign Briefings Title: modcontent-package-allied
Identifier: movies-allied Identifier: movies-allied
TestFiles: ^SupportDir|Content/ra/v2/movies/aagun.vqa, ^SupportDir|Content/ra/v2/movies/aftrmath.vqa, ^SupportDir|Content/ra/v2/movies/ally1.vqa, ^SupportDir|Content/ra/v2/movies/ally10.vqa, ^SupportDir|Content/ra/v2/movies/ally10b.vqa, ^SupportDir|Content/ra/v2/movies/ally11.vqa, ^SupportDir|Content/ra/v2/movies/ally12.vqa, ^SupportDir|Content/ra/v2/movies/ally14.vqa, ^SupportDir|Content/ra/v2/movies/ally2.vqa, ^SupportDir|Content/ra/v2/movies/ally4.vqa, ^SupportDir|Content/ra/v2/movies/ally5.vqa, ^SupportDir|Content/ra/v2/movies/ally6.vqa, ^SupportDir|Content/ra/v2/movies/ally8.vqa, ^SupportDir|Content/ra/v2/movies/ally9.vqa, ^SupportDir|Content/ra/v2/movies/allyend.vqa, ^SupportDir|Content/ra/v2/movies/allymorf.vqa, ^SupportDir|Content/ra/v2/movies/apcescpe.vqa, ^SupportDir|Content/ra/v2/movies/assess.vqa, ^SupportDir|Content/ra/v2/movies/battle.vqa, ^SupportDir|Content/ra/v2/movies/binoc.vqa, ^SupportDir|Content/ra/v2/movies/bmap.vqa, ^SupportDir|Content/ra/v2/movies/brdgtilt.vqa, ^SupportDir|Content/ra/v2/movies/crontest.vqa, ^SupportDir|Content/ra/v2/movies/cronfail.vqa, ^SupportDir|Content/ra/v2/movies/destroyr.vqa, ^SupportDir|Content/ra/v2/movies/dud.vqa, ^SupportDir|Content/ra/v2/movies/elevator.vqa, ^SupportDir|Content/ra/v2/movies/flare.vqa, ^SupportDir|Content/ra/v2/movies/frozen.vqa, ^SupportDir|Content/ra/v2/movies/grvestne.vqa, ^SupportDir|Content/ra/v2/movies/landing.vqa, ^SupportDir|Content/ra/v2/movies/masasslt.vqa, ^SupportDir|Content/ra/v2/movies/mcv.vqa, ^SupportDir|Content/ra/v2/movies/mcv_land.vqa, ^SupportDir|Content/ra/v2/movies/montpass.vqa, ^SupportDir|Content/ra/v2/movies/oildrum.vqa, ^SupportDir|Content/ra/v2/movies/overrun.vqa, ^SupportDir|Content/ra/v2/movies/prolog.vqa, ^SupportDir|Content/ra/v2/movies/redintro.vqa, ^SupportDir|Content/ra/v2/movies/shipsink.vqa, ^SupportDir|Content/ra/v2/movies/shorbom1.vqa, ^SupportDir|Content/ra/v2/movies/shorbom2.vqa, ^SupportDir|Content/ra/v2/movies/shorbomb.vqa, ^SupportDir|Content/ra/v2/movies/snowbomb.vqa, ^SupportDir|Content/ra/v2/movies/soviet1.vqa, ^SupportDir|Content/ra/v2/movies/sovtstar.vqa, ^SupportDir|Content/ra/v2/movies/spy.vqa, ^SupportDir|Content/ra/v2/movies/tanya1.vqa, ^SupportDir|Content/ra/v2/movies/tanya2.vqa, ^SupportDir|Content/ra/v2/movies/toofar.vqa, ^SupportDir|Content/ra/v2/movies/trinity.vqa TestFiles: ^SupportDir|Content/ra/v2/movies/aagun.vqa, ^SupportDir|Content/ra/v2/movies/aftrmath.vqa, ^SupportDir|Content/ra/v2/movies/ally1.vqa, ^SupportDir|Content/ra/v2/movies/ally10.vqa, ^SupportDir|Content/ra/v2/movies/ally10b.vqa, ^SupportDir|Content/ra/v2/movies/ally11.vqa, ^SupportDir|Content/ra/v2/movies/ally12.vqa, ^SupportDir|Content/ra/v2/movies/ally14.vqa, ^SupportDir|Content/ra/v2/movies/ally2.vqa, ^SupportDir|Content/ra/v2/movies/ally4.vqa, ^SupportDir|Content/ra/v2/movies/ally5.vqa, ^SupportDir|Content/ra/v2/movies/ally6.vqa, ^SupportDir|Content/ra/v2/movies/ally8.vqa, ^SupportDir|Content/ra/v2/movies/ally9.vqa, ^SupportDir|Content/ra/v2/movies/allyend.vqa, ^SupportDir|Content/ra/v2/movies/allymorf.vqa, ^SupportDir|Content/ra/v2/movies/apcescpe.vqa, ^SupportDir|Content/ra/v2/movies/assess.vqa, ^SupportDir|Content/ra/v2/movies/battle.vqa, ^SupportDir|Content/ra/v2/movies/binoc.vqa, ^SupportDir|Content/ra/v2/movies/bmap.vqa, ^SupportDir|Content/ra/v2/movies/brdgtilt.vqa, ^SupportDir|Content/ra/v2/movies/crontest.vqa, ^SupportDir|Content/ra/v2/movies/cronfail.vqa, ^SupportDir|Content/ra/v2/movies/destroyr.vqa, ^SupportDir|Content/ra/v2/movies/dud.vqa, ^SupportDir|Content/ra/v2/movies/elevator.vqa, ^SupportDir|Content/ra/v2/movies/flare.vqa, ^SupportDir|Content/ra/v2/movies/frozen.vqa, ^SupportDir|Content/ra/v2/movies/grvestne.vqa, ^SupportDir|Content/ra/v2/movies/landing.vqa, ^SupportDir|Content/ra/v2/movies/masasslt.vqa, ^SupportDir|Content/ra/v2/movies/mcv.vqa, ^SupportDir|Content/ra/v2/movies/mcv_land.vqa, ^SupportDir|Content/ra/v2/movies/montpass.vqa, ^SupportDir|Content/ra/v2/movies/oildrum.vqa, ^SupportDir|Content/ra/v2/movies/overrun.vqa, ^SupportDir|Content/ra/v2/movies/prolog.vqa, ^SupportDir|Content/ra/v2/movies/redintro.vqa, ^SupportDir|Content/ra/v2/movies/shipsink.vqa, ^SupportDir|Content/ra/v2/movies/shorbom1.vqa, ^SupportDir|Content/ra/v2/movies/shorbom2.vqa, ^SupportDir|Content/ra/v2/movies/shorbomb.vqa, ^SupportDir|Content/ra/v2/movies/snowbomb.vqa, ^SupportDir|Content/ra/v2/movies/soviet1.vqa, ^SupportDir|Content/ra/v2/movies/sovtstar.vqa, ^SupportDir|Content/ra/v2/movies/spy.vqa, ^SupportDir|Content/ra/v2/movies/tanya1.vqa, ^SupportDir|Content/ra/v2/movies/tanya2.vqa, ^SupportDir|Content/ra/v2/movies/toofar.vqa, ^SupportDir|Content/ra/v2/movies/trinity.vqa
Sources: allied, tfd, ra-steam, ra-origin, cncr-steam, cncr-origin Sources: allied, tfd, ra-steam, ra-origin, cncr-steam, cncr-origin
ContentPackage@movies-soviet: ContentPackage@movies-soviet:
Title: Soviet Campaign Briefings Title: modcontent-package-soviet
Identifier: movies-soviet Identifier: movies-soviet
TestFiles: ^SupportDir|Content/ra/v2/movies/aagun.vqa, ^SupportDir|Content/ra/v2/movies/cronfail.vqa, ^SupportDir|Content/ra/v2/movies/airfield.vqa, ^SupportDir|Content/ra/v2/movies/ally1.vqa, ^SupportDir|Content/ra/v2/movies/allymorf.vqa, ^SupportDir|Content/ra/v2/movies/averted.vqa, ^SupportDir|Content/ra/v2/movies/beachead.vqa, ^SupportDir|Content/ra/v2/movies/bmap.vqa, ^SupportDir|Content/ra/v2/movies/bombrun.vqa, ^SupportDir|Content/ra/v2/movies/countdwn.vqa, ^SupportDir|Content/ra/v2/movies/double.vqa, ^SupportDir|Content/ra/v2/movies/dpthchrg.vqa, ^SupportDir|Content/ra/v2/movies/execute.vqa, ^SupportDir|Content/ra/v2/movies/flare.vqa, ^SupportDir|Content/ra/v2/movies/landing.vqa, ^SupportDir|Content/ra/v2/movies/mcvbrdge.vqa, ^SupportDir|Content/ra/v2/movies/mig.vqa, ^SupportDir|Content/ra/v2/movies/movingin.vqa, ^SupportDir|Content/ra/v2/movies/mtnkfact.vqa, ^SupportDir|Content/ra/v2/movies/nukestok.vqa, ^SupportDir|Content/ra/v2/movies/onthprwl.vqa, ^SupportDir|Content/ra/v2/movies/periscop.vqa, ^SupportDir|Content/ra/v2/movies/prolog.vqa, ^SupportDir|Content/ra/v2/movies/radrraid.vqa, ^SupportDir|Content/ra/v2/movies/redintro.vqa, ^SupportDir|Content/ra/v2/movies/search.vqa, ^SupportDir|Content/ra/v2/movies/sfrozen.vqa, ^SupportDir|Content/ra/v2/movies/sitduck.vqa, ^SupportDir|Content/ra/v2/movies/slntsrvc.vqa, ^SupportDir|Content/ra/v2/movies/snowbomb.vqa, ^SupportDir|Content/ra/v2/movies/snstrafe.vqa, ^SupportDir|Content/ra/v2/movies/sovbatl.vqa, ^SupportDir|Content/ra/v2/movies/sovcemet.vqa, ^SupportDir|Content/ra/v2/movies/sovfinal.vqa, ^SupportDir|Content/ra/v2/movies/soviet1.vqa, ^SupportDir|Content/ra/v2/movies/soviet10.vqa, ^SupportDir|Content/ra/v2/movies/soviet11.vqa, ^SupportDir|Content/ra/v2/movies/soviet12.vqa, ^SupportDir|Content/ra/v2/movies/soviet13.vqa, ^SupportDir|Content/ra/v2/movies/soviet14.vqa, ^SupportDir|Content/ra/v2/movies/soviet2.vqa, ^SupportDir|Content/ra/v2/movies/soviet3.vqa, ^SupportDir|Content/ra/v2/movies/soviet4.vqa, ^SupportDir|Content/ra/v2/movies/soviet5.vqa, ^SupportDir|Content/ra/v2/movies/soviet6.vqa, ^SupportDir|Content/ra/v2/movies/soviet7.vqa, ^SupportDir|Content/ra/v2/movies/soviet8.vqa, ^SupportDir|Content/ra/v2/movies/soviet9.vqa, ^SupportDir|Content/ra/v2/movies/sovmcv.vqa, ^SupportDir|Content/ra/v2/movies/sovtstar.vqa, ^SupportDir|Content/ra/v2/movies/spotter.vqa, ^SupportDir|Content/ra/v2/movies/strafe.vqa, ^SupportDir|Content/ra/v2/movies/take_off.vqa, ^SupportDir|Content/ra/v2/movies/tesla.vqa, ^SupportDir|Content/ra/v2/movies/v2rocket.vqa TestFiles: ^SupportDir|Content/ra/v2/movies/aagun.vqa, ^SupportDir|Content/ra/v2/movies/cronfail.vqa, ^SupportDir|Content/ra/v2/movies/airfield.vqa, ^SupportDir|Content/ra/v2/movies/ally1.vqa, ^SupportDir|Content/ra/v2/movies/allymorf.vqa, ^SupportDir|Content/ra/v2/movies/averted.vqa, ^SupportDir|Content/ra/v2/movies/beachead.vqa, ^SupportDir|Content/ra/v2/movies/bmap.vqa, ^SupportDir|Content/ra/v2/movies/bombrun.vqa, ^SupportDir|Content/ra/v2/movies/countdwn.vqa, ^SupportDir|Content/ra/v2/movies/double.vqa, ^SupportDir|Content/ra/v2/movies/dpthchrg.vqa, ^SupportDir|Content/ra/v2/movies/execute.vqa, ^SupportDir|Content/ra/v2/movies/flare.vqa, ^SupportDir|Content/ra/v2/movies/landing.vqa, ^SupportDir|Content/ra/v2/movies/mcvbrdge.vqa, ^SupportDir|Content/ra/v2/movies/mig.vqa, ^SupportDir|Content/ra/v2/movies/movingin.vqa, ^SupportDir|Content/ra/v2/movies/mtnkfact.vqa, ^SupportDir|Content/ra/v2/movies/nukestok.vqa, ^SupportDir|Content/ra/v2/movies/onthprwl.vqa, ^SupportDir|Content/ra/v2/movies/periscop.vqa, ^SupportDir|Content/ra/v2/movies/prolog.vqa, ^SupportDir|Content/ra/v2/movies/radrraid.vqa, ^SupportDir|Content/ra/v2/movies/redintro.vqa, ^SupportDir|Content/ra/v2/movies/search.vqa, ^SupportDir|Content/ra/v2/movies/sfrozen.vqa, ^SupportDir|Content/ra/v2/movies/sitduck.vqa, ^SupportDir|Content/ra/v2/movies/slntsrvc.vqa, ^SupportDir|Content/ra/v2/movies/snowbomb.vqa, ^SupportDir|Content/ra/v2/movies/snstrafe.vqa, ^SupportDir|Content/ra/v2/movies/sovbatl.vqa, ^SupportDir|Content/ra/v2/movies/sovcemet.vqa, ^SupportDir|Content/ra/v2/movies/sovfinal.vqa, ^SupportDir|Content/ra/v2/movies/soviet1.vqa, ^SupportDir|Content/ra/v2/movies/soviet10.vqa, ^SupportDir|Content/ra/v2/movies/soviet11.vqa, ^SupportDir|Content/ra/v2/movies/soviet12.vqa, ^SupportDir|Content/ra/v2/movies/soviet13.vqa, ^SupportDir|Content/ra/v2/movies/soviet14.vqa, ^SupportDir|Content/ra/v2/movies/soviet2.vqa, ^SupportDir|Content/ra/v2/movies/soviet3.vqa, ^SupportDir|Content/ra/v2/movies/soviet4.vqa, ^SupportDir|Content/ra/v2/movies/soviet5.vqa, ^SupportDir|Content/ra/v2/movies/soviet6.vqa, ^SupportDir|Content/ra/v2/movies/soviet7.vqa, ^SupportDir|Content/ra/v2/movies/soviet8.vqa, ^SupportDir|Content/ra/v2/movies/soviet9.vqa, ^SupportDir|Content/ra/v2/movies/sovmcv.vqa, ^SupportDir|Content/ra/v2/movies/sovtstar.vqa, ^SupportDir|Content/ra/v2/movies/spotter.vqa, ^SupportDir|Content/ra/v2/movies/strafe.vqa, ^SupportDir|Content/ra/v2/movies/take_off.vqa, ^SupportDir|Content/ra/v2/movies/tesla.vqa, ^SupportDir|Content/ra/v2/movies/v2rocket.vqa
Sources: soviet, tfd, ra-steam, ra-origin Sources: soviet, tfd, ra-steam, ra-origin
ContentPackage@music-counterstrike: ContentPackage@music-counterstrike:
Title: Counterstrike Music Title: modcontent-package-counterstrikemusic
Identifier: music-counterstrike Identifier: music-counterstrike
TestFiles: ^SupportDir|Content/ra/v2/expand/araziod.aud, ^SupportDir|Content/ra/v2/expand/backstab.aud, ^SupportDir|Content/ra/v2/expand/chaos2.aud, ^SupportDir|Content/ra/v2/expand/shut_it.aud, ^SupportDir|Content/ra/v2/expand/2nd_hand.aud, ^SupportDir|Content/ra/v2/expand/twinmix1.aud, ^SupportDir|Content/ra/v2/expand/under3.aud, ^SupportDir|Content/ra/v2/expand/vr2.aud, TestFiles: ^SupportDir|Content/ra/v2/expand/araziod.aud, ^SupportDir|Content/ra/v2/expand/backstab.aud, ^SupportDir|Content/ra/v2/expand/chaos2.aud, ^SupportDir|Content/ra/v2/expand/shut_it.aud, ^SupportDir|Content/ra/v2/expand/2nd_hand.aud, ^SupportDir|Content/ra/v2/expand/twinmix1.aud, ^SupportDir|Content/ra/v2/expand/under3.aud, ^SupportDir|Content/ra/v2/expand/vr2.aud,
Sources: counterstrike, ra-steam, ra-origin, cncr-steam, cncr-origin Sources: counterstrike, ra-steam, ra-origin, cncr-steam, cncr-origin
ContentPackage@music-aftermath: ContentPackage@music-aftermath:
Title: Aftermath Music Title: modcontent-package-aftermathmusic
Identifier: music-aftermath Identifier: music-aftermath
TestFiles: ^SupportDir|Content/ra/v2/expand/await.aud, ^SupportDir|Content/ra/v2/expand/bog.aud, ^SupportDir|Content/ra/v2/expand/float_v2.aud, ^SupportDir|Content/ra/v2/expand/gloom.aud, ^SupportDir|Content/ra/v2/expand/grndwire.aud, ^SupportDir|Content/ra/v2/expand/rpt.aud, ^SupportDir|Content/ra/v2/expand/search.aud, ^SupportDir|Content/ra/v2/expand/traction.aud, ^SupportDir|Content/ra/v2/expand/wastelnd.aud TestFiles: ^SupportDir|Content/ra/v2/expand/await.aud, ^SupportDir|Content/ra/v2/expand/bog.aud, ^SupportDir|Content/ra/v2/expand/float_v2.aud, ^SupportDir|Content/ra/v2/expand/gloom.aud, ^SupportDir|Content/ra/v2/expand/grndwire.aud, ^SupportDir|Content/ra/v2/expand/rpt.aud, ^SupportDir|Content/ra/v2/expand/search.aud, ^SupportDir|Content/ra/v2/expand/traction.aud, ^SupportDir|Content/ra/v2/expand/wastelnd.aud
Sources: aftermath, ra-steam, ra-origin, cncr-steam, cncr-origin Sources: aftermath, ra-steam, ra-origin, cncr-steam, cncr-origin
@@ -342,6 +342,7 @@ ModContent:
ra|installer/origin.yaml ra|installer/origin.yaml
ra|installer/soviet95.yaml ra|installer/soviet95.yaml
ra|installer/steam.yaml ra|installer/steam.yaml
Translation: ra|languages/modcontent/en.ftl
DiscordService: DiscordService:
ApplicationId: 699222659766026240 ApplicationId: 699222659766026240

6
mods/ts/languages/en.ftl Normal file
View File

@@ -0,0 +1,6 @@
## Metadata
mod-title = Tiberian Sun
mod-windowtitle = OpenRA - Tiberian Sun
## LogoStripeLoadScreen
loadscreen-loading = Updating EVA installation..., Changing perspective...

View File

@@ -0,0 +1,12 @@
modcontent-installprompt =
Tiberian Sun requires artwork and audio from the original game.
Quick Install will automatically download this content (without music or videos) from a mirror of the 2012 Tiberian Sun freeware release.
Advanced Install includes options for copying the music, videos, and other content from an original game disc or digital installation.
modcontent-header =
Game content may be extracted from the original game discs or an existing digital install. OpenRA can also download the base game files from an online mirror of the 2012 freeware release of TS.
modcontent-package-basefiles = Base Game Files
modcontent-package-basemusic = Base Game Music
modcontent-package-firestormfiles = Firestorm Expansion Files
modcontent-package-firestormmusic = Firestorm Expansion Music

View File

@@ -1,9 +1,9 @@
Metadata: Metadata:
Title: Tiberian Sun Title: mod-title
Version: {DEV_VERSION} Version: {DEV_VERSION}
Website: https://www.openra.net Website: https://www.openra.net
WebIcon32: https://www.openra.net/images/icons/ts_32x32.png WebIcon32: https://www.openra.net/images/icons/ts_32x32.png
WindowTitle: OpenRA - Tiberian Sun WindowTitle: mod-windowtitle
PackageFormats: Mix PackageFormats: Mix
@@ -187,6 +187,7 @@ Translations:
common|languages/en.ftl common|languages/en.ftl
common|languages/chrome/en.ftl common|languages/chrome/en.ftl
common|languages/rules/en.ftl common|languages/rules/en.ftl
ts|languages/en.ftl
ts|languages/chrome/en.ftl ts|languages/chrome/en.ftl
ts|languages/rules/en.ftl ts|languages/rules/en.ftl
@@ -216,7 +217,6 @@ Hotkeys:
LoadScreen: LogoStripeLoadScreen LoadScreen: LogoStripeLoadScreen
Image: ts|uibits/loadscreen.png Image: ts|uibits/loadscreen.png
Text: Updating EVA installation..., Changing perspective...
ServerTraits: ServerTraits:
LobbyCommands LobbyCommands
@@ -312,31 +312,31 @@ GameSpeeds:
OrderLatency: 6 OrderLatency: 6
ModContent: ModContent:
InstallPromptMessage: Tiberian Sun requires artwork and audio from the original game.\n\nQuick Install will automatically download this content (without music\nor videos) from a mirror of the 2012 Tiberian Sun freeware release.\n\nAdvanced Install includes options for copying the music, videos, and\nother content from an original game disc or digital installation. InstallPromptMessage: modcontent-installprompt
QuickDownload: quickinstall QuickDownload: quickinstall
HeaderMessage: Game content may be extracted from the original game discs or an\nexisting digital install. OpenRA can also download the base game\nfiles from an online mirror of the 2012 freeware release of TS. HeaderMessage: modcontent-header
Packages: Packages:
ContentPackage@tibsun: ContentPackage@tibsun:
Title: Base Game Files Title: modcontent-package-basefiles
Identifier: tibsun Identifier: tibsun
TestFiles: ^SupportDir|Content/ts/cache.mix, ^SupportDir|Content/ts/conquer.mix, ^SupportDir|Content/ts/isosnow.mix, ^SupportDir|Content/ts/isotemp.mix, ^SupportDir|Content/ts/local.mix, ^SupportDir|Content/ts/sidec01.mix, ^SupportDir|Content/ts/sidec02.mix, ^SupportDir|Content/ts/sno.mix, ^SupportDir|Content/ts/snow.mix, ^SupportDir|Content/ts/sounds.mix, ^SupportDir|Content/ts/speech01.mix, ^SupportDir|Content/ts/tem.mix, ^SupportDir|Content/ts/temperat.mix TestFiles: ^SupportDir|Content/ts/cache.mix, ^SupportDir|Content/ts/conquer.mix, ^SupportDir|Content/ts/isosnow.mix, ^SupportDir|Content/ts/isotemp.mix, ^SupportDir|Content/ts/local.mix, ^SupportDir|Content/ts/sidec01.mix, ^SupportDir|Content/ts/sidec02.mix, ^SupportDir|Content/ts/sno.mix, ^SupportDir|Content/ts/snow.mix, ^SupportDir|Content/ts/sounds.mix, ^SupportDir|Content/ts/speech01.mix, ^SupportDir|Content/ts/tem.mix, ^SupportDir|Content/ts/temperat.mix
Sources: tibsun, tfd, steam, origin Sources: tibsun, tfd, steam, origin
Required: true Required: true
Download: basefiles Download: basefiles
ContentPackage@tibsun-music: ContentPackage@tibsun-music:
Title: Base Game Music Title: modcontent-package-basemusic
Identifier: tibsun-music Identifier: tibsun-music
TestFiles: ^SupportDir|Content/ts/scores.mix TestFiles: ^SupportDir|Content/ts/scores.mix
Sources: tibsun, tfd, steam, origin Sources: tibsun, tfd, steam, origin
ContentPackage@fstorm: ContentPackage@fstorm:
Title: Firestorm Expansion Files Title: modcontent-package-firestormfiles
Identifier: fstorm Identifier: fstorm
TestFiles: ^SupportDir|Content/ts/firestorm/e01sc01.mix, ^SupportDir|Content/ts/firestorm/e01sc02.mix, ^SupportDir|Content/ts/firestorm/e01vox01.mix, ^SupportDir|Content/ts/firestorm/e01vox02.mix TestFiles: ^SupportDir|Content/ts/firestorm/e01sc01.mix, ^SupportDir|Content/ts/firestorm/e01sc02.mix, ^SupportDir|Content/ts/firestorm/e01vox01.mix, ^SupportDir|Content/ts/firestorm/e01vox02.mix
Sources: tfd, steam, origin, fstorm Sources: tfd, steam, origin, fstorm
Required: true Required: true
Download: fstorm Download: fstorm
ContentPackage@fstorm-music: ContentPackage@fstorm-music:
Title: Firestorm Expansion Music Title: modcontent-package-firestormmusic
Identifier: fstorm-music Identifier: fstorm-music
Sources: tfd, steam, origin, fstorm Sources: tfd, steam, origin, fstorm
TestFiles: ^SupportDir|Content/ts/firestorm/scores01.mix TestFiles: ^SupportDir|Content/ts/firestorm/scores01.mix
@@ -348,6 +348,7 @@ ModContent:
ts|installer/steam.yaml ts|installer/steam.yaml
ts|installer/origin.yaml ts|installer/origin.yaml
ts|installer/tibsun.yaml ts|installer/tibsun.yaml
Translation: ts|languages/modcontent/en.ftl
DiscordService: DiscordService:
ApplicationId: 712713986558394399 ApplicationId: 712713986558394399