diff --git a/Makefile b/Makefile index 55cdbfb537..c51c067e40 100644 --- a/Makefile +++ b/Makefile @@ -219,10 +219,11 @@ crashdialog: $(crashdialog_TARGET) utility_SRCS := $(shell find OpenRA.Utility/ -iname '*.cs') utility_TARGET = OpenRA.Utility.exe utility_KIND = exe -utility_DEPS = $(game_TARGET) +utility_DEPS = $(game_TARGET) $(mod_ra_TARGET) utility_LIBS = $(COMMON_LIBS) $(utility_DEPS) thirdparty/ICSharpCode.SharpZipLib.dll PROGRAMS += utility utility: $(utility_TARGET) + @$(CP) $(mod_ra_TARGET) . # Patches binary headers to work around a mono bug diff --git a/OpenRA.Utility/Command.cs b/OpenRA.Utility/Command.cs index 96fb4e16ee..e2ac801fcf 100644 --- a/OpenRA.Utility/Command.cs +++ b/OpenRA.Utility/Command.cs @@ -20,6 +20,7 @@ using System.Text; using OpenRA.FileFormats; using OpenRA.FileSystem; using OpenRA.Graphics; +using OpenRA.Mods.RA; using OpenRA.Scripting; using OpenRA.Traits; @@ -544,5 +545,53 @@ namespace OpenRA.Utility map.Save(dest); Console.WriteLine(dest + " saved."); } + + [Desc("MOD", "Export the game rules into a CSV file to inspect in a spreadheet.")] + public static void ExportCharacterSeparatedRules(string[] args) + { + var mod = args[1]; + Game.modData = new ModData(mod); + var rules = Game.modData.RulesetCache.LoadDefaultRules(); + var dump = new StringBuilder(); + dump.AppendLine("Name;Faction;Health;Cost;Damage per Second"); + foreach (var actorInfo in rules.Actors.Values) + { + if (actorInfo.Name.StartsWith("^")) + continue; + + var buildable = actorInfo.Traits.GetOrDefault(); + if (buildable == null) + continue; + var faction = FieldSaver.FormatValue(buildable.Owner, buildable.Owner.GetType()); + + var damagePerSecond = 0f; + var armaments = actorInfo.Traits.WithInterface(); + if (armaments.Any()) + { + var weapons = armaments.Select(a => a.Weapon).Select(w => rules.Weapons[w.ToLowerInvariant()]); + if (weapons.Any()) + { + var damage = weapons.Select(w => new { ROF = w.ROF > 0 ? w.ROF : 1, Damage = w.Burst * w.Warheads.Sum(z => z.Damage) }); + damagePerSecond = damage.Sum(d => (float)d.Damage / d.ROF * 25); + } + } + + var tooltip = actorInfo.Traits.GetOrDefault(); + var name = tooltip != null ? tooltip.Name : actorInfo.Name; + + var health = actorInfo.Traits.GetOrDefault(); + var hp = health != null ? health.HP : 0; + + var value = actorInfo.Traits.GetOrDefault(); + var cost = value != null ? value.Cost : 0; + + dump.AppendLine("{0};{1};{2};{3};{4}".F(name, faction, hp, cost, damagePerSecond)); + } + + var filename = "{0}-mod-rules.csv".F(mod); + using (StreamWriter outfile = new StreamWriter(filename)) + outfile.Write(dump.ToString()); + Console.WriteLine("{0} has been saved.\nOpen in a spreadsheet application as values separated by semicolon.".F(filename)); + } } } diff --git a/OpenRA.Utility/OpenRA.Utility.csproj b/OpenRA.Utility/OpenRA.Utility.csproj index 61464771f7..b2c1e38dd6 100644 --- a/OpenRA.Utility/OpenRA.Utility.csproj +++ b/OpenRA.Utility/OpenRA.Utility.csproj @@ -87,6 +87,10 @@ {0DFB103F-2962-400F-8C6D-E2C28CCBA633} OpenRA.Game + + {4A8A43B5-A9EF-4ED0-99DD-4BAB10A0DB6E} + OpenRA.Mods.RA + diff --git a/OpenRA.Utility/Program.cs b/OpenRA.Utility/Program.cs index 5f8a7ec73f..9c8aff6307 100644 --- a/OpenRA.Utility/Program.cs +++ b/OpenRA.Utility/Program.cs @@ -34,7 +34,8 @@ namespace OpenRA.Utility { "--upgrade-map", UpgradeRules.UpgradeMap }, { "--upgrade-mod", UpgradeRules.UpgradeMod }, { "--map-import", Command.ImportLegacyMap }, - { "--extract-language-strings", ExtractLanguageStrings.FromMod } + { "--extract-language-strings", ExtractLanguageStrings.FromMod }, + { "--csv", Command.ExportCharacterSeparatedRules } }; static void Main(string[] args)