Merge pull request #5234 from pavlos256/startup

Improve startup speed
This commit is contained in:
Paul Chote
2014-05-17 23:50:45 +12:00
163 changed files with 1135 additions and 720 deletions

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS) * Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
@@ -29,7 +29,7 @@ namespace OpenRA.Editor
currentMod = args.FirstOrDefault() ?? "ra"; currentMod = args.FirstOrDefault() ?? "ra";
toolStripComboBox1.Items.AddRange(Mod.AllMods.Keys.ToArray()); toolStripComboBox1.Items.AddRange(ModMetadata.AllMods.Keys.ToArray());
toolStripComboBox1.SelectedIndexChanged += (_, e) => toolStripComboBox1.SelectedIndexChanged += (_, e) =>
{ {
@@ -48,7 +48,7 @@ namespace OpenRA.Editor
Game.modData = new ModData(currentMod); Game.modData = new ModData(currentMod);
GlobalFileSystem.LoadFromManifest(Game.modData.Manifest); GlobalFileSystem.LoadFromManifest(Game.modData.Manifest);
Rules.LoadRules(Game.modData.Manifest, new Map()); Program.Rules = Game.modData.RulesetCache.LoadDefaultRules();
var mod = Game.modData.Manifest.Mod; var mod = Game.modData.Manifest.Mod;
Text = "{0} Mod Version: {1} - OpenRA Editor".F(mod.Title, mod.Version); Text = "{0} Mod Version: {1} - OpenRA Editor".F(mod.Title, mod.Version);
@@ -69,7 +69,8 @@ namespace OpenRA.Editor
void OnMapChanged() void OnMapChanged()
{ {
MakeDirty(); MakeDirty();
miniMapBox.Image = Minimap.AddStaticResources(surface1.Map, Minimap.TerrainBitmap(surface1.Map, true)); var tileSet = Program.Rules.TileSets[surface1.Map.Tileset];
miniMapBox.Image = Minimap.RenderMapPreview(tileSet, surface1.Map, true);
cashToolStripStatusLabel.Text = CalculateTotalResource().ToString(); cashToolStripStatusLabel.Text = CalculateTotalResource().ToString();
} }
@@ -84,7 +85,7 @@ namespace OpenRA.Editor
var objSaved = kv.Value.Save(); var objSaved = kv.Value.Save();
// TODO: make this work properly // TODO: make this work properly
foreach (var init in Rules.Info[kv.Value.Type].GetInitKeys()) foreach (var init in Program.Rules.Actors[kv.Value.Type].GetInitKeys())
apd.AddRow(init.First, apd.AddRow(init.First,
apd.MakeEditorControl(init.Second, apd.MakeEditorControl(init.Second,
() => objSaved.NodesDict.ContainsKey(init.First) ? objSaved.NodesDict[init.First].Value : null, () => objSaved.NodesDict.ContainsKey(init.First) ? objSaved.NodesDict[init.First].Value : null,
@@ -120,7 +121,7 @@ namespace OpenRA.Editor
if (map.Players.Count == 0) if (map.Players.Count == 0)
map.MakeDefaultPlayers(); map.MakeDefaultPlayers();
PrepareMapResources(Game.modData.Manifest, map); PrepareMapResources(Game.modData, map);
// Calculate total net worth of resources in cash // Calculate total net worth of resources in cash
cashToolStripStatusLabel.Text = CalculateTotalResource().ToString(); cashToolStripStatusLabel.Text = CalculateTotalResource().ToString();
@@ -135,17 +136,18 @@ namespace OpenRA.Editor
resourcePalette.Controls.Clear(); resourcePalette.Controls.Clear();
loadedMapName = null; loadedMapName = null;
PrepareMapResources(Game.modData.Manifest, map); PrepareMapResources(Game.modData, map);
MakeDirty(); MakeDirty();
} }
// this code is insanely stupid, and mostly my fault -- chrisf // this code is insanely stupid, and mostly my fault -- chrisf
void PrepareMapResources(Manifest manifest, Map map) void PrepareMapResources(ModData modData, Map map)
{ {
Rules.LoadRules(manifest, map); Program.Rules = map.Rules;
tileset = Rules.TileSets[map.Tileset];
tilesetRenderer = new TileSetRenderer(tileset, manifest.TileSize); tileset = Program.Rules.TileSets[map.Tileset];
tilesetRenderer = new TileSetRenderer(tileset, modData.Manifest.TileSize);
var shadowIndex = new int[] { 3, 4 }; var shadowIndex = new int[] { 3, 4 };
var palette = new Palette(GlobalFileSystem.Open(tileset.Palette), shadowIndex); var palette = new Palette(GlobalFileSystem.Open(tileset.Palette), shadowIndex);
@@ -208,11 +210,11 @@ namespace OpenRA.Editor
var actorTemplates = new List<ActorTemplate>(); var actorTemplates = new List<ActorTemplate>();
foreach (var a in Rules.Info.Keys) foreach (var a in Program.Rules.Actors.Keys)
{ {
try try
{ {
var info = Rules.Info[a]; var info = Program.Rules.Actors[a];
if (!info.Traits.Contains<RenderSimpleInfo>()) continue; if (!info.Traits.Contains<RenderSimpleInfo>()) continue;
var etf = info.Traits.GetOrDefault<EditorTilesetFilterInfo>(); var etf = info.Traits.GetOrDefault<EditorTilesetFilterInfo>();
@@ -253,7 +255,7 @@ namespace OpenRA.Editor
var resourceTemplates = new List<ResourceTemplate>(); var resourceTemplates = new List<ResourceTemplate>();
foreach (var a in Rules.Info["world"].Traits.WithInterface<ResourceTypeInfo>()) foreach (var a in Program.Rules.Actors["world"].Traits.WithInterface<ResourceTypeInfo>())
{ {
try try
{ {
@@ -286,7 +288,7 @@ namespace OpenRA.Editor
p.ResumeLayout(); p.ResumeLayout();
} }
miniMapBox.Image = Minimap.AddStaticResources(surface1.Map, Minimap.TerrainBitmap(surface1.Map, true)); miniMapBox.Image = Minimap.RenderMapPreview(tileset, surface1.Map, true);
propertiesToolStripMenuItem.Enabled = true; propertiesToolStripMenuItem.Enabled = true;
toolStripMenuItemProperties.Enabled = true; toolStripMenuItemProperties.Enabled = true;
@@ -388,12 +390,12 @@ namespace OpenRA.Editor
using (var nmd = new NewMapDialog()) using (var nmd = new NewMapDialog())
{ {
nmd.TheaterBox.Items.Clear(); nmd.TheaterBox.Items.Clear();
nmd.TheaterBox.Items.AddRange(Rules.TileSets.Select(a => a.Value.Id).ToArray()); nmd.TheaterBox.Items.AddRange(Program.Rules.TileSets.Select(a => a.Value.Id).ToArray());
nmd.TheaterBox.SelectedIndex = 0; nmd.TheaterBox.SelectedIndex = 0;
if (DialogResult.OK == nmd.ShowDialog()) if (DialogResult.OK == nmd.ShowDialog())
{ {
var tileset = OpenRA.Rules.TileSets[nmd.TheaterBox.SelectedItem as string]; var tileset = Program.Rules.TileSets[nmd.TheaterBox.SelectedItem as string];
var map = Map.FromTileset(tileset); var map = Map.FromTileset(tileset);
map.Resize((int)nmd.MapWidth.Value, (int)nmd.MapHeight.Value); map.Resize((int)nmd.MapWidth.Value, (int)nmd.MapHeight.Value);
@@ -402,7 +404,7 @@ namespace OpenRA.Editor
map.Players.Clear(); map.Players.Clear();
map.MakeDefaultPlayers(); map.MakeDefaultPlayers();
map.FixOpenAreas(); map.FixOpenAreas(Program.Rules);
NewMap(map); NewMap(map);
} }
@@ -485,7 +487,7 @@ namespace OpenRA.Editor
void FixOpenAreas(object sender, EventArgs e) void FixOpenAreas(object sender, EventArgs e)
{ {
dirty = true; dirty = true;
surface1.Map.FixOpenAreas(); surface1.Map.FixOpenAreas(Program.Rules);
surface1.Chunks.Clear(); surface1.Chunks.Clear();
surface1.Invalidate(); surface1.Invalidate();
} }

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
@@ -75,7 +75,8 @@ namespace OpenRA.Editor
try try
{ {
MiniMapBox.Image = Minimap.AddStaticResources(map, Minimap.TerrainBitmap(map, true)); var tileset = Program.Rules.TileSets[map.Tileset];
MiniMapBox.Image = Minimap.RenderMapPreview(tileset, map, true);
} }
catch (Exception ed) catch (Exception ed)
{ {

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
@@ -19,9 +19,13 @@ namespace OpenRA.Editor
{ {
static class Program static class Program
{ {
public static Ruleset Rules;
[STAThread] [STAThread]
static void Main(string[] args) static void Main(string[] args)
{ {
Log.AddChannel("perf", null);
Application.CurrentCulture = CultureInfo.InvariantCulture; Application.CurrentCulture = CultureInfo.InvariantCulture;
Application.EnableVisualStyles(); Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false); Application.SetCompatibleTextRenderingDefault(false);

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
@@ -379,7 +379,7 @@ namespace OpenRA.Editor
ColorPalette GetPaletteForPlayerInner(string name) ColorPalette GetPaletteForPlayerInner(string name)
{ {
var pr = Map.Players[name]; var pr = Map.Players[name];
var pcpi = Rules.Info["player"].Traits.Get<PlayerColorPaletteInfo>(); var pcpi = Program.Rules.Actors["player"].Traits.Get<PlayerColorPaletteInfo>();
var remap = new PlayerColorRemap(pcpi.RemapIndex, pr.Color, pcpi.Ramp); var remap = new PlayerColorRemap(pcpi.RemapIndex, pr.Color, pcpi.Ramp);
return new Palette(PlayerPalette, remap).AsSystemPalette(); return new Palette(PlayerPalette, remap).AsSystemPalette();
} }

View File

@@ -69,10 +69,10 @@ namespace OpenRA
if (name != null) if (name != null)
{ {
if (!Rules.Info.ContainsKey(name.ToLowerInvariant())) if (!world.Map.Rules.Actors.ContainsKey(name.ToLowerInvariant()))
throw new NotImplementedException("No rules definition for unit {0}".F(name.ToLowerInvariant())); throw new NotImplementedException("No rules definition for unit {0}".F(name.ToLowerInvariant()));
Info = Rules.Info[name.ToLowerInvariant()]; Info = world.Map.Rules.Actors[name.ToLowerInvariant()];
foreach (var trait in Info.TraitsInConstructOrder()) foreach (var trait in Info.TraitsInConstructOrder())
AddTrait(trait.Create(init)); AddTrait(trait.Create(init));
} }

View File

@@ -21,7 +21,7 @@ namespace OpenRA.Effects
public MoveFlash(WPos pos, World world) public MoveFlash(WPos pos, World world)
{ {
this.pos = pos; this.pos = pos;
anim = new Animation("moveflsh"); anim = new Animation(world, "moveflsh");
anim.PlayThen("idle", () => world.AddFrameEndTask(w => w.Remove(this))); anim.PlayThen("idle", () => world.AddFrameEndTask(w => w.Remove(this)));
} }

View File

@@ -117,6 +117,8 @@ namespace OpenRA
}, parent, id); }, parent, id);
} }
// Note: These delayed actions should only be used by widgets or disposing objects
// - things that depend on a particular world should be queuing them on the worldactor.
static ActionQueue delayedActions = new ActionQueue(); static ActionQueue delayedActions = new ActionQueue();
public static void RunAfterTick(Action a) { delayedActions.Add(a); } public static void RunAfterTick(Action a) { delayedActions.Add(a); }
public static void RunAfterDelay(int delay, Action a) { delayedActions.Add(a, delay); } public static void RunAfterDelay(int delay, Action a) { delayedActions.Add(a, delay); }
@@ -151,8 +153,11 @@ namespace OpenRA
using (new PerfSample("render_widgets")) using (new PerfSample("render_widgets"))
{ {
Ui.Draw(); Ui.Draw();
if (modData != null && modData.CursorProvider != null)
{
var cursorName = Ui.Root.GetCursorOuter(Viewport.LastMousePos) ?? "default"; var cursorName = Ui.Root.GetCursorOuter(Viewport.LastMousePos) ?? "default";
CursorProvider.DrawCursor(Renderer, cursorName, Viewport.LastMousePos, (int)cursorFrame); modData.CursorProvider.DrawCursor(Renderer, cursorName, Viewport.LastMousePos, (int)cursorFrame);
}
} }
using (new PerfSample("render_flip")) using (new PerfSample("render_flip"))
@@ -248,11 +253,12 @@ namespace OpenRA
BeforeGameStart(); BeforeGameStart();
Map map; Map map;
using (new PerfTimer("PrepareMap")) using (new PerfTimer("PrepareMap"))
map = modData.PrepareMap(mapUID); map = modData.PrepareMap(mapUID);
using (new PerfTimer("NewWorld")) using (new PerfTimer("NewWorld"))
{ {
orderManager.world = new World(modData.Manifest, map, orderManager, isShellmap); orderManager.world = new World(map, orderManager, isShellmap);
orderManager.world.Timestep = Timestep; orderManager.world.Timestep = Timestep;
} }
worldRenderer = new WorldRenderer(orderManager.world); worldRenderer = new WorldRenderer(orderManager.world);
@@ -354,7 +360,7 @@ namespace OpenRA
} }
Console.WriteLine("Available mods:"); Console.WriteLine("Available mods:");
foreach (var mod in Mod.AllMods) foreach (var mod in ModMetadata.AllMods)
Console.WriteLine("\t{0}: {1} ({2})", mod.Key, mod.Value.Title, mod.Value.Version); Console.WriteLine("\t{0}: {1} ({2})", mod.Key, mod.Value.Title, mod.Value.Version);
InitializeWithMod(Settings.Game.Mod, args.GetValue("Launch.Replay", null)); InitializeWithMod(Settings.Game.Mod, args.GetValue("Launch.Replay", null));
@@ -379,7 +385,7 @@ namespace OpenRA
orderManager.Dispose(); orderManager.Dispose();
// Fall back to default if the mod doesn't exist // Fall back to default if the mod doesn't exist
if (!Mod.AllMods.ContainsKey(mod)) if (!ModMetadata.AllMods.ContainsKey(mod))
mod = new GameSettings().Mod; mod = new GameSettings().Mod;
Console.WriteLine("Loading mod: {0}", mod); Console.WriteLine("Loading mod: {0}", mod);

View File

@@ -1,56 +0,0 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.GameRules;
namespace OpenRA
{
public static class Rules
{
public static Dictionary<string, ActorInfo> Info;
public static Dictionary<string, WeaponInfo> Weapons;
public static Dictionary<string, SoundInfo> Voices;
public static Dictionary<string, SoundInfo> Notifications;
public static Dictionary<string, MusicInfo> Music;
public static Dictionary<string, string> Movies;
public static Dictionary<string, TileSet> TileSets;
public static void LoadRules(Manifest m, Map map)
{
// Added support to extend the list of rules (add it to m.LocalRules)
Info = LoadYamlRules(m.Rules, map.Rules, (k, y) => new ActorInfo(k.Key.ToLowerInvariant(), k.Value, y));
Weapons = LoadYamlRules(m.Weapons, map.Weapons, (k, _) => new WeaponInfo(k.Key.ToLowerInvariant(), k.Value));
Voices = LoadYamlRules(m.Voices, map.Voices, (k, _) => new SoundInfo(k.Value));
Notifications = LoadYamlRules(m.Notifications, map.Notifications, (k, _) => new SoundInfo(k.Value));
Music = LoadYamlRules(m.Music, new List<MiniYamlNode>(), (k, _) => new MusicInfo(k.Key, k.Value));
Movies = LoadYamlRules(m.Movies, new List<MiniYamlNode>(), (k, v) => k.Value.Value);
TileSets = new Dictionary<string, TileSet>();
foreach (var file in m.TileSets)
{
var t = new TileSet(file);
TileSets.Add(t.Id,t);
}
}
static Dictionary<string, T> LoadYamlRules<T>(string[] files, List<MiniYamlNode> dict, Func<MiniYamlNode, Dictionary<string, MiniYaml>, T> f)
{
var y = files.Select(MiniYaml.FromFile).Aggregate(dict, MiniYaml.MergeLiberal);
var yy = y.ToDictionary(x => x.Key, x => x.Value);
return y.ToDictionaryWithConflictLog(kv => kv.Key.ToLowerInvariant(), kv => f(kv, yy), "LoadYamlRules", null, null);
}
public static IEnumerable<KeyValuePair<string, MusicInfo>> InstalledMusic { get { return Music.Where(m => m.Value.Exists); } }
}
}

View File

@@ -0,0 +1,52 @@
#region Copyright & License Information
/*
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.GameRules;
using OpenRA.Graphics;
namespace OpenRA
{
public class Ruleset
{
public readonly IReadOnlyDictionary<string, ActorInfo> Actors;
public readonly IReadOnlyDictionary<string, WeaponInfo> Weapons;
public readonly IReadOnlyDictionary<string, SoundInfo> Voices;
public readonly IReadOnlyDictionary<string, SoundInfo> Notifications;
public readonly IReadOnlyDictionary<string, MusicInfo> Music;
public readonly IReadOnlyDictionary<string, string> Movies;
public readonly IReadOnlyDictionary<string, TileSet> TileSets;
public readonly IReadOnlyDictionary<string, SequenceProvider> Sequences;
public Ruleset(
IDictionary<string, ActorInfo> actors,
IDictionary<string, WeaponInfo> weapons,
IDictionary<string, SoundInfo> voices,
IDictionary<string, SoundInfo> notifications,
IDictionary<string, MusicInfo> music,
IDictionary<string, string> movies,
IDictionary<string, TileSet> tileSets,
IDictionary<string, SequenceProvider> sequences)
{
Actors = new ReadOnlyDictionary<string, ActorInfo>(actors);
Weapons = new ReadOnlyDictionary<string, WeaponInfo>(weapons);
Voices = new ReadOnlyDictionary<string, SoundInfo>(voices);
Notifications = new ReadOnlyDictionary<string, SoundInfo>(notifications);
Music = new ReadOnlyDictionary<string, MusicInfo>(music);
Movies = new ReadOnlyDictionary<string, string>(movies);
TileSets = new ReadOnlyDictionary<string, TileSet>(tileSets);
Sequences = new ReadOnlyDictionary<string, SequenceProvider>(sequences);
}
public IEnumerable<KeyValuePair<string, MusicInfo>> InstalledMusic { get { return Music.Where(m => m.Value.Exists); } }
}
}

View File

@@ -0,0 +1,142 @@
#region Copyright & License Information
/*
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.GameRules;
using OpenRA.Graphics;
using OpenRA.Support;
namespace OpenRA
{
public class RulesetCache
{
readonly ModData modData;
readonly Dictionary<string, ActorInfo> actorCache = new Dictionary<string, ActorInfo>();
readonly Dictionary<string, WeaponInfo> weaponCache = new Dictionary<string, WeaponInfo>();
readonly Dictionary<string, SoundInfo> voiceCache = new Dictionary<string, SoundInfo>();
readonly Dictionary<string, SoundInfo> notificationCache = new Dictionary<string, SoundInfo>();
readonly Dictionary<string, MusicInfo> musicCache = new Dictionary<string, MusicInfo>();
readonly Dictionary<string, string> movieCache = new Dictionary<string, string>();
readonly Dictionary<string, TileSet> tileSetCache = new Dictionary<string, TileSet>();
readonly Dictionary<string, SequenceCache> sequenceCaches = new Dictionary<string, SequenceCache>();
public event EventHandler LoadingProgress;
void RaiseProgress()
{
if (LoadingProgress != null)
LoadingProgress(this, new EventArgs());
}
public RulesetCache(ModData modData)
{
this.modData = modData;
}
public Ruleset LoadDefaultRules()
{
return LoadMapRules(new Map());
}
public Ruleset LoadMapRules(Map map)
{
var m = modData.Manifest;
Dictionary<string, ActorInfo> actors;
Dictionary<string, WeaponInfo> weapons;
Dictionary<string, SoundInfo> voices;
Dictionary<string, SoundInfo> notifications;
Dictionary<string, MusicInfo> music;
Dictionary<string, string> movies;
Dictionary<string, TileSet> tileSets;
using (new PerfTimer("Actors"))
actors = LoadYamlRules(actorCache, m.Rules, map.RuleDefinitions, (k, y) => new ActorInfo(k.Key.ToLowerInvariant(), k.Value, y));
using (new PerfTimer("Weapons"))
weapons = LoadYamlRules(weaponCache, m.Weapons, map.WeaponDefinitions, (k, _) => new WeaponInfo(k.Key.ToLowerInvariant(), k.Value));
using (new PerfTimer("Voices"))
voices = LoadYamlRules(voiceCache, m.Voices, map.VoiceDefinitions, (k, _) => new SoundInfo(k.Value));
using (new PerfTimer("Notifications"))
notifications = LoadYamlRules(notificationCache, m.Notifications, map.NotificationDefinitions, (k, _) => new SoundInfo(k.Value));
using (new PerfTimer("Music"))
music = LoadYamlRules(musicCache, m.Music, new List<MiniYamlNode>(), (k, _) => new MusicInfo(k.Key, k.Value));
using (new PerfTimer("Movies"))
movies = LoadYamlRules(movieCache, m.Movies, new List<MiniYamlNode>(), (k, v) => k.Value.Value);
using (new PerfTimer("TileSets"))
tileSets = LoadTileSets(tileSetCache, sequenceCaches, m.TileSets);
var sequences = sequenceCaches.ToDictionary(kvp => kvp.Key, kvp => new SequenceProvider(kvp.Value, map));
return new Ruleset(actors, weapons, voices, notifications, music, movies, tileSets, sequences);
}
Dictionary<string, T> LoadYamlRules<T>(
Dictionary<string, T> itemCache,
string[] files, List<MiniYamlNode> nodes,
Func<MiniYamlNode, Dictionary<string, MiniYaml>, T> f)
{
RaiseProgress();
var inputKey = string.Concat(string.Join("|", files), "|", nodes.WriteToString());
var mergedNodes = files
.Select(s => MiniYaml.FromFile(s))
.Aggregate(nodes, MiniYaml.MergeLiberal);
Func<MiniYamlNode, Dictionary<string, MiniYaml>, T> wrap = (wkv, wyy) =>
{
var key = inputKey + wkv.Value.ToLines(wkv.Key).JoinWith("|");
T t;
if (itemCache.TryGetValue(key, out t))
return t;
t = f(wkv, wyy);
itemCache.Add(key, t);
RaiseProgress();
return t;
};
var yy = mergedNodes.ToDictionary(x => x.Key, x => x.Value);
var itemSet = mergedNodes.ToDictionaryWithConflictLog(kv => kv.Key.ToLowerInvariant(), kv => wrap(kv, yy), "LoadYamlRules", null, null);
RaiseProgress();
return itemSet;
}
Dictionary<string, TileSet> LoadTileSets(Dictionary<string, TileSet> itemCache, Dictionary<string, SequenceCache> sequenceCaches, string[] files)
{
var items = new Dictionary<string, TileSet>();
foreach (var file in files)
{
TileSet t;
if (itemCache.TryGetValue(file, out t))
items.Add(t.Id, t);
else
{
t = new TileSet(modData, file);
itemCache.Add(file, t);
// every time we load a tile set, we create a sequence cache for it
var sc = new SequenceCache(modData, t);
sequenceCaches.Add(t.Id, sc);
items.Add(t.Id, t);
}
}
return items;
}
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
@@ -19,7 +19,7 @@ namespace OpenRA.Graphics
public bool IsDecoration = false; public bool IsDecoration = false;
public Func<bool> Paused; public Func<bool> Paused;
Func<int> facingFunc; readonly Func<int> facingFunc;
int frame = 0; int frame = 0;
bool backwards = false; bool backwards = false;
@@ -28,11 +28,17 @@ namespace OpenRA.Graphics
public string Name { get { return name; } } public string Name { get { return name; } }
public Animation(string name) readonly SequenceProvider sequenceProvider;
: this(name, () => 0) {}
public Animation(string name, Func<int> facingFunc) public Animation(World world, string name)
: this(world, name, () => 0) { }
public Animation(World world, string name, Func<int> facingFunc)
: this(world.Map.SequenceProvider, name, facingFunc) { }
public Animation(SequenceProvider sequenceProvider, string name, Func<int> facingFunc)
{ {
this.sequenceProvider = sequenceProvider;
this.name = name.ToLowerInvariant(); this.name = name.ToLowerInvariant();
this.tickFunc = () => {}; this.tickFunc = () => {};
this.facingFunc = facingFunc; this.facingFunc = facingFunc;
@@ -66,7 +72,7 @@ namespace OpenRA.Graphics
{ {
backwards = false; backwards = false;
tickAlways = false; tickAlways = false;
CurrentSequence = SequenceProvider.GetSequence(name, sequenceName); CurrentSequence = sequenceProvider.GetSequence(name, sequenceName);
frame = 0; frame = 0;
tickFunc = () => tickFunc = () =>
{ {
@@ -81,7 +87,7 @@ namespace OpenRA.Graphics
if (!HasSequence(sequenceName)) if (!HasSequence(sequenceName))
return false; return false;
CurrentSequence = SequenceProvider.GetSequence(name, sequenceName); CurrentSequence = sequenceProvider.GetSequence(name, sequenceName);
frame %= CurrentSequence.Length; frame %= CurrentSequence.Length;
return true; return true;
} }
@@ -90,7 +96,7 @@ namespace OpenRA.Graphics
{ {
backwards = false; backwards = false;
tickAlways = false; tickAlways = false;
CurrentSequence = SequenceProvider.GetSequence(name, sequenceName); CurrentSequence = sequenceProvider.GetSequence(name, sequenceName);
frame = 0; frame = 0;
tickFunc = () => tickFunc = () =>
{ {
@@ -114,7 +120,7 @@ namespace OpenRA.Graphics
{ {
backwards = false; backwards = false;
tickAlways = true; tickAlways = true;
CurrentSequence = SequenceProvider.GetSequence(name, sequenceName); CurrentSequence = sequenceProvider.GetSequence(name, sequenceName);
frame = func(); frame = func();
tickFunc = () => frame = func(); tickFunc = () => frame = func();
} }
@@ -128,7 +134,7 @@ namespace OpenRA.Graphics
Tick(40); // tick one frame Tick(40); // tick one frame
} }
public bool HasSequence(string seq) { return SequenceProvider.HasSequence(name, seq); } public bool HasSequence(string seq) { return sequenceProvider.HasSequence(name, seq); }
public void Tick(int t) public void Tick(int t)
{ {
@@ -159,7 +165,7 @@ namespace OpenRA.Graphics
public Sequence GetSequence(string sequenceName) public Sequence GetSequence(string sequenceName)
{ {
return SequenceProvider.GetSequence(name, sequenceName); return sequenceProvider.GetSequence(name, sequenceName);
} }
} }
} }

View File

@@ -16,23 +16,16 @@ using OpenRA.Primitives;
namespace OpenRA.Graphics namespace OpenRA.Graphics
{ {
public static class CursorProvider public class CursorProvider
{ {
static HardwarePalette palette; HardwarePalette palette;
static Dictionary<string, CursorSequence> cursors; Dictionary<string, CursorSequence> cursors;
static Cache<string, PaletteReference> palettes; Cache<string, PaletteReference> palettes;
static PaletteReference CreatePaletteReference(string name) public CursorProvider(ModData modData)
{ {
var pal = palette.GetPalette(name); var sequenceFiles = modData.Manifest.Cursors;
if (pal == null)
throw new InvalidOperationException("Palette `{0}` does not exist".F(name));
return new PaletteReference(name, palette.GetPaletteIndex(name), pal);
}
public static void Initialize(string[] sequenceFiles)
{
cursors = new Dictionary<string, CursorSequence>(); cursors = new Dictionary<string, CursorSequence>();
palettes = new Cache<string, PaletteReference>(CreatePaletteReference); palettes = new Cache<string, PaletteReference>(CreatePaletteReference);
var sequences = new MiniYaml(null, sequenceFiles.Select(s => MiniYaml.FromFile(s)).Aggregate(MiniYaml.MergeLiberal)); var sequences = new MiniYaml(null, sequenceFiles.Select(s => MiniYaml.FromFile(s)).Aggregate(MiniYaml.MergeLiberal));
@@ -49,26 +42,35 @@ namespace OpenRA.Graphics
foreach (var p in sequences.NodesDict["Palettes"].Nodes) foreach (var p in sequences.NodesDict["Palettes"].Nodes)
palette.AddPalette(p.Key, new Palette(GlobalFileSystem.Open(p.Value.Value), shadowIndex), false); palette.AddPalette(p.Key, new Palette(GlobalFileSystem.Open(p.Value.Value), shadowIndex), false);
var spriteLoader = new SpriteLoader(new string[0], new SheetBuilder(SheetType.Indexed));
foreach (var s in sequences.NodesDict["Cursors"].Nodes) foreach (var s in sequences.NodesDict["Cursors"].Nodes)
LoadSequencesForCursor(s.Key, s.Value); LoadSequencesForCursor(spriteLoader, s.Key, s.Value);
palette.Initialize(); palette.Initialize();
} }
static void LoadSequencesForCursor(string cursorSrc, MiniYaml cursor) PaletteReference CreatePaletteReference(string name)
{ {
Game.modData.LoadScreen.Display(); var pal = palette.GetPalette(name);
if (pal == null)
throw new InvalidOperationException("Palette `{0}` does not exist".F(name));
foreach (var sequence in cursor.Nodes) return new PaletteReference(name, palette.GetPaletteIndex(name), pal);
cursors.Add(sequence.Key, new CursorSequence(cursorSrc, cursor.Value, sequence.Value));
} }
public static bool HasCursorSequence(string cursor) void LoadSequencesForCursor(SpriteLoader loader, string cursorSrc, MiniYaml cursor)
{
foreach (var sequence in cursor.Nodes)
cursors.Add(sequence.Key, new CursorSequence(loader, cursorSrc, cursor.Value, sequence.Value));
}
public bool HasCursorSequence(string cursor)
{ {
return cursors.ContainsKey(cursor); return cursors.ContainsKey(cursor);
} }
public static void DrawCursor(Renderer renderer, string cursorName, int2 lastMousePos, int cursorFrame) public void DrawCursor(Renderer renderer, string cursorName, int2 lastMousePos, int cursorFrame)
{ {
var cursorSequence = GetCursorSequence(cursorName); var cursorSequence = GetCursorSequence(cursorName);
var cursorSprite = cursorSequence.GetSprite(cursorFrame); var cursorSprite = cursorSequence.GetSprite(cursorFrame);
@@ -80,13 +82,12 @@ namespace OpenRA.Graphics
cursorSprite.size); cursorSprite.size);
} }
public static CursorSequence GetCursorSequence(string cursor) public CursorSequence GetCursorSequence(string cursor)
{ {
try { return cursors[cursor]; } try { return cursors[cursor]; }
catch (KeyNotFoundException) catch (KeyNotFoundException)
{ {
throw new InvalidOperationException( throw new InvalidOperationException("Cursor does not have a sequence `{0}`".F(cursor));
"Cursor does not have a sequence `{0}`".F(cursor));
} }
} }
} }

View File

@@ -25,9 +25,9 @@ namespace OpenRA.Graphics
Sprite[] sprites; Sprite[] sprites;
public CursorSequence(string cursorSrc, string palette, MiniYaml info) public CursorSequence(SpriteLoader loader, string cursorSrc, string palette, MiniYaml info)
{ {
sprites = Game.modData.SpriteLoader.LoadAllSprites(cursorSrc); sprites = loader.LoadAllSprites(cursorSrc);
var d = info.NodesDict; var d = info.NodesDict;
start = Exts.ParseIntegerInvariant(d["start"].Value); start = Exts.ParseIntegerInvariant(d["start"].Value);

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
@@ -19,14 +19,8 @@ namespace OpenRA.Graphics
{ {
public class Minimap public class Minimap
{ {
public static Bitmap TerrainBitmap(Map map) public static Bitmap TerrainBitmap(TileSet tileset, Map map, bool actualSize = false)
{ {
return TerrainBitmap(map, false);
}
public static Bitmap TerrainBitmap(Map map, bool actualSize)
{
var tileset = Rules.TileSets[map.Tileset];
var width = map.Bounds.Width; var width = map.Bounds.Width;
var height = map.Bounds.Height; var height = map.Bounds.Height;
@@ -61,10 +55,9 @@ namespace OpenRA.Graphics
// Add the static resources defined in the map; if the map lives // Add the static resources defined in the map; if the map lives
// in a world use AddCustomTerrain instead // in a world use AddCustomTerrain instead
public static Bitmap AddStaticResources(Map map, Bitmap terrainBitmap) static Bitmap AddStaticResources(TileSet tileset, Map map, Ruleset resourceRules, Bitmap terrainBitmap)
{ {
Bitmap terrain = new Bitmap(terrainBitmap); Bitmap terrain = new Bitmap(terrainBitmap);
var tileset = Rules.TileSets[map.Tileset];
var bitmapData = terrain.LockBits(terrain.Bounds(), var bitmapData = terrain.LockBits(terrain.Bounds(),
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
@@ -81,7 +74,7 @@ namespace OpenRA.Graphics
if (map.MapResources.Value[mapX, mapY].Type == 0) if (map.MapResources.Value[mapX, mapY].Type == 0)
continue; continue;
var res = Rules.Info["world"].Traits.WithInterface<ResourceTypeInfo>() var res = resourceRules.Actors["world"].Traits.WithInterface<ResourceTypeInfo>()
.Where(t => t.ResourceType == map.MapResources.Value[mapX, mapY].Type) .Where(t => t.ResourceType == map.MapResources.Value[mapX, mapY].Type)
.Select(t => t.TerrainType).FirstOrDefault(); .Select(t => t.TerrainType).FirstOrDefault();
if (res == null) if (res == null)
@@ -185,10 +178,15 @@ namespace OpenRA.Graphics
return bitmap; return bitmap;
} }
public static Bitmap RenderMapPreview(Map map, bool actualSize) public static Bitmap RenderMapPreview(TileSet tileset, Map map, bool actualSize)
{ {
Bitmap terrain = TerrainBitmap(map, actualSize); return RenderMapPreview(tileset, map, map.Rules, actualSize);
return AddStaticResources(map, terrain); }
public static Bitmap RenderMapPreview(TileSet tileset, Map map, Ruleset resourceRules, bool actualSize)
{
Bitmap terrain = TerrainBitmap(tileset, map, actualSize);
return AddStaticResources(tileset, map, resourceRules, terrain);
} }
} }
} }

View File

@@ -29,7 +29,7 @@ namespace OpenRA.Graphics
public readonly int ShadowZOffset; public readonly int ShadowZOffset;
public readonly int[] Frames; public readonly int[] Frames;
public Sequence(string unit, string name, MiniYaml info) public Sequence(SpriteLoader loader, string unit, string name, MiniYaml info)
{ {
var srcOverride = info.Value; var srcOverride = info.Value;
Name = name; Name = name;
@@ -50,7 +50,7 @@ namespace OpenRA.Graphics
// Apply offset to each sprite in the sequence // Apply offset to each sprite in the sequence
// Different sequences may apply different offsets to the same frame // Different sequences may apply different offsets to the same frame
sprites = Game.modData.SpriteLoader.LoadAllSprites(srcOverride ?? unit).Select( sprites = loader.LoadAllSprites(srcOverride ?? unit).Select(
s => new Sprite(s.sheet, s.bounds, s.offset + offset, s.channel, blendMode)).ToArray(); s => new Sprite(s.sheet, s.bounds, s.offset + offset, s.channel, blendMode)).ToArray();
if (!d.ContainsKey("Length")) if (!d.ContainsKey("Length"))

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
@@ -13,69 +13,101 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using OpenRA.FileFormats; using OpenRA.FileFormats;
using OpenRA.Primitives;
namespace OpenRA.Graphics namespace OpenRA.Graphics
{ {
public static class SequenceProvider public class SequenceProvider
{ {
static Dictionary<string, Dictionary<string, Sequence>> units; readonly Lazy<IReadOnlyDictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>>> sequences;
public readonly SpriteLoader SpriteLoader;
public static void Initialize(string[] sequenceFiles, List<MiniYamlNode> sequenceNodes) public SequenceProvider(SequenceCache cache, Map map)
{ {
units = new Dictionary<string, Dictionary<string, Sequence>>(); this.sequences = Exts.Lazy(() => cache.LoadSequences(map));
this.SpriteLoader = cache.SpriteLoader;
}
var sequences = sequenceFiles public Sequence GetSequence(string unitName, string sequenceName)
{
Lazy<IReadOnlyDictionary<string, Sequence>> unitSeq;
if (!sequences.Value.TryGetValue(unitName, out unitSeq))
throw new InvalidOperationException("Unit `{0}` does not have any sequences defined.".F(unitName));
Sequence seq;
if (!unitSeq.Value.TryGetValue(sequenceName, out seq))
throw new InvalidOperationException("Unit `{0}` does not have a sequence named `{1}`".F(unitName, sequenceName));
return seq;
}
public bool HasSequence(string unitName, string sequenceName)
{
Lazy<IReadOnlyDictionary<string, Sequence>> unitSeq;
if (!sequences.Value.TryGetValue(unitName, out unitSeq))
throw new InvalidOperationException("Unit `{0}` does not have any sequences defined.".F(unitName));
return unitSeq.Value.ContainsKey(sequenceName);
}
public IEnumerable<string> Sequences(string unitName)
{
Lazy<IReadOnlyDictionary<string, Sequence>> unitSeq;
if (!sequences.Value.TryGetValue(unitName, out unitSeq))
throw new InvalidOperationException("Unit `{0}` does not have any sequences defined.".F(unitName));
return unitSeq.Value.Keys;
}
}
public class SequenceCache
{
readonly ModData modData;
readonly Lazy<SpriteLoader> spriteLoader;
public SpriteLoader SpriteLoader { get { return spriteLoader.Value; } }
readonly Dictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>> sequenceCache = new Dictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>>();
public SequenceCache(ModData modData, TileSet tileSet)
{
this.modData = modData;
spriteLoader = Exts.Lazy(() => new SpriteLoader(tileSet.Extensions, new SheetBuilder(SheetType.Indexed)));
}
public IReadOnlyDictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>> LoadSequences(Map map)
{
using (new Support.PerfTimer("LoadSequences"))
return Load(map.SequenceDefinitions);
}
IReadOnlyDictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>> Load(List<MiniYamlNode> sequenceNodes)
{
var sequenceFiles = modData.Manifest.Sequences;
var nodes = sequenceFiles
.Select(s => MiniYaml.FromFile(s)) .Select(s => MiniYaml.FromFile(s))
.Aggregate(sequenceNodes, MiniYaml.MergeLiberal); .Aggregate(sequenceNodes, MiniYaml.MergeLiberal);
foreach (var s in sequences) var items = new Dictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>>();
LoadSequencesForUnit(s.Key, s.Value); foreach (var node in nodes)
} {
var key = node.Value.ToLines(node.Key).JoinWith("|");
static void LoadSequencesForUnit(string unit, MiniYaml sequences) Lazy<IReadOnlyDictionary<string, Sequence>> t;
{ if (sequenceCache.TryGetValue(key, out t))
Game.modData.LoadScreen.Display(); items.Add(node.Key, t);
try
{
var seq = sequences.NodesDict.ToDictionary(x => x.Key, x => new Sequence(unit,x.Key,x.Value));
units.Add(unit, seq);
}
catch (FileNotFoundException)
{
// Do nothing; we can crash later if we actually wanted art
}
}
public static Sequence GetSequence(string unitName, string sequenceName)
{
try { return units[unitName][sequenceName]; }
catch (KeyNotFoundException)
{
if (units.ContainsKey(unitName))
throw new InvalidOperationException(
"Unit `{0}` does not have a sequence `{1}`".F(unitName, sequenceName));
else else
throw new InvalidOperationException(
"Unit `{0}` does not have all sequences defined.".F(unitName));
}
}
public static bool HasSequence(string unit, string seq)
{ {
if (!units.ContainsKey(unit)) t = Exts.Lazy(() => (IReadOnlyDictionary<string, Sequence>)new ReadOnlyDictionary<string, Sequence>(
throw new InvalidOperationException( node.Value.NodesDict.ToDictionary(x => x.Key, x =>
"Unit `{0}` does not have sequence `{1}` defined.".F(unit, seq)); new Sequence(spriteLoader.Value, node.Key, x.Key, x.Value))));
sequenceCache.Add(key, t);
return units[unit].ContainsKey(seq); items.Add(node.Key, t);
}
} }
public static IEnumerable<string> Sequences(string unit) return new ReadOnlyDictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>>(items);
{
if (!units.ContainsKey(unit))
throw new InvalidOperationException(
"Unit `{0}` does not have all sequences defined.".F(unit));
return units[unit].Keys;
} }
} }
} }

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
@@ -18,7 +18,7 @@ namespace OpenRA.Graphics
{ {
public class SpriteLoader public class SpriteLoader
{ {
readonly SheetBuilder SheetBuilder; public readonly SheetBuilder SheetBuilder;
readonly Cache<string, Sprite[]> sprites; readonly Cache<string, Sprite[]> sprites;
readonly string[] exts; readonly string[] exts;

View File

@@ -19,7 +19,7 @@ namespace OpenRA
// Describes what is to be loaded in order to run a mod // Describes what is to be loaded in order to run a mod
public class Manifest public class Manifest
{ {
public readonly Mod Mod; public readonly ModMetadata Mod;
public readonly string[] public readonly string[]
Folders, MapFolders, Rules, ServerTraits, Folders, MapFolders, Rules, ServerTraits,
Sequences, VoxelSequences, Cursors, Chrome, Assemblies, ChromeLayout, Sequences, VoxelSequences, Cursors, Chrome, Assemblies, ChromeLayout,
@@ -38,7 +38,7 @@ namespace OpenRA
var path = new[] { "mods", mod, "mod.yaml" }.Aggregate(Path.Combine); var path = new[] { "mods", mod, "mod.yaml" }.Aggregate(Path.Combine);
var yaml = new MiniYaml(null, MiniYaml.FromFile(path)).NodesDict; var yaml = new MiniYaml(null, MiniYaml.FromFile(path)).NodesDict;
Mod = FieldLoader.Load<Mod>(yaml["Metadata"]); Mod = FieldLoader.Load<ModMetadata>(yaml["Metadata"]);
Mod.Id = mod; Mod.Id = mod;
// TODO: Use fieldloader // TODO: Use fieldloader

View File

@@ -8,6 +8,7 @@
*/ */
#endregion #endregion
using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using OpenRA.Primitives; using OpenRA.Primitives;
@@ -17,16 +18,24 @@ namespace OpenRA
public class ActorReference : IEnumerable public class ActorReference : IEnumerable
{ {
public string Type; public string Type;
public TypeDictionary InitDict; public TypeDictionary InitDict
{
get { return initDict.Value; }
}
Lazy<TypeDictionary> initDict;
public ActorReference( string type ) : this( type, new Dictionary<string, MiniYaml>() ) { } public ActorReference( string type ) : this( type, new Dictionary<string, MiniYaml>() ) { }
public ActorReference( string type, Dictionary<string, MiniYaml> inits ) public ActorReference( string type, Dictionary<string, MiniYaml> inits )
{ {
Type = type; Type = type;
InitDict = new TypeDictionary(); initDict = Exts.Lazy(() =>
foreach( var i in inits ) {
InitDict.Add( LoadInit( i.Key, i.Value ) ); var dict = new TypeDictionary();
foreach (var i in inits)
dict.Add(LoadInit(i.Key, i.Value));
return dict;
});
} }
static IActorInit LoadInit(string traitName, MiniYaml my) static IActorInit LoadInit(string traitName, MiniYaml my)

View File

@@ -18,6 +18,7 @@ using System.Text;
using OpenRA.FileSystem; using OpenRA.FileSystem;
using OpenRA.Network; using OpenRA.Network;
using OpenRA.Traits; using OpenRA.Traits;
using OpenRA.Graphics;
namespace OpenRA namespace OpenRA
{ {
@@ -94,13 +95,13 @@ namespace OpenRA
[FieldLoader.Ignore] public Dictionary<string, PlayerReference> Players = new Dictionary<string, PlayerReference>(); [FieldLoader.Ignore] public Dictionary<string, PlayerReference> Players = new Dictionary<string, PlayerReference>();
[FieldLoader.Ignore] public Lazy<List<SmudgeReference>> Smudges; [FieldLoader.Ignore] public Lazy<List<SmudgeReference>> Smudges;
[FieldLoader.Ignore] public List<MiniYamlNode> Rules = new List<MiniYamlNode>(); [FieldLoader.Ignore] public List<MiniYamlNode> RuleDefinitions = new List<MiniYamlNode>();
[FieldLoader.Ignore] public List<MiniYamlNode> Sequences = new List<MiniYamlNode>(); [FieldLoader.Ignore] public List<MiniYamlNode> SequenceDefinitions = new List<MiniYamlNode>();
[FieldLoader.Ignore] public List<MiniYamlNode> VoxelSequences = new List<MiniYamlNode>(); [FieldLoader.Ignore] public List<MiniYamlNode> VoxelSequenceDefinitions = new List<MiniYamlNode>();
[FieldLoader.Ignore] public List<MiniYamlNode> Weapons = new List<MiniYamlNode>(); [FieldLoader.Ignore] public List<MiniYamlNode> WeaponDefinitions = new List<MiniYamlNode>();
[FieldLoader.Ignore] public List<MiniYamlNode> Voices = new List<MiniYamlNode>(); [FieldLoader.Ignore] public List<MiniYamlNode> VoiceDefinitions = new List<MiniYamlNode>();
[FieldLoader.Ignore] public List<MiniYamlNode> Notifications = new List<MiniYamlNode>(); [FieldLoader.Ignore] public List<MiniYamlNode> NotificationDefinitions = new List<MiniYamlNode>();
[FieldLoader.Ignore] public List<MiniYamlNode> Translations = new List<MiniYamlNode>(); [FieldLoader.Ignore] public List<MiniYamlNode> TranslationDefinitions = new List<MiniYamlNode>();
// Binary map data // Binary map data
[FieldLoader.Ignore] public byte TileFormat = 1; [FieldLoader.Ignore] public byte TileFormat = 1;
@@ -110,6 +111,10 @@ namespace OpenRA
[FieldLoader.Ignore] public Lazy<TileReference<byte, byte>[,]> MapResources; [FieldLoader.Ignore] public Lazy<TileReference<byte, byte>[,]> MapResources;
[FieldLoader.Ignore] public string[,] CustomTerrain; [FieldLoader.Ignore] public string[,] CustomTerrain;
[FieldLoader.Ignore] Lazy<Ruleset> rules;
public Ruleset Rules { get { return rules != null ? rules.Value : null; } }
public SequenceProvider SequenceProvider { get { return Rules.Sequences[Tileset]; } }
public static Map FromTileset(TileSet tileset) public static Map FromTileset(TileSet tileset)
{ {
var tile = tileset.Templates.First(); var tile = tileset.Templates.First();
@@ -128,6 +133,7 @@ namespace OpenRA
Actors = Exts.Lazy(() => new Dictionary<string, ActorReference>()), Actors = Exts.Lazy(() => new Dictionary<string, ActorReference>()),
Smudges = Exts.Lazy(() => new List<SmudgeReference>()) Smudges = Exts.Lazy(() => new List<SmudgeReference>())
}; };
map.PostInit();
return map; return map;
} }
@@ -210,13 +216,13 @@ namespace OpenRA
return ret; return ret;
}); });
Rules = MiniYaml.NodesOrEmpty(yaml, "Rules"); RuleDefinitions = MiniYaml.NodesOrEmpty(yaml, "Rules");
Sequences = MiniYaml.NodesOrEmpty(yaml, "Sequences"); SequenceDefinitions = MiniYaml.NodesOrEmpty(yaml, "Sequences");
VoxelSequences = MiniYaml.NodesOrEmpty(yaml, "VoxelSequences"); VoxelSequenceDefinitions = MiniYaml.NodesOrEmpty(yaml, "VoxelSequences");
Weapons = MiniYaml.NodesOrEmpty(yaml, "Weapons"); WeaponDefinitions = MiniYaml.NodesOrEmpty(yaml, "Weapons");
Voices = MiniYaml.NodesOrEmpty(yaml, "Voices"); VoiceDefinitions = MiniYaml.NodesOrEmpty(yaml, "Voices");
Notifications = MiniYaml.NodesOrEmpty(yaml, "Notifications"); NotificationDefinitions = MiniYaml.NodesOrEmpty(yaml, "Notifications");
Translations = MiniYaml.NodesOrEmpty(yaml, "Translations"); TranslationDefinitions = MiniYaml.NodesOrEmpty(yaml, "Translations");
CustomTerrain = new string[MapSize.X, MapSize.Y]; CustomTerrain = new string[MapSize.X, MapSize.Y];
@@ -233,6 +239,18 @@ namespace OpenRA
if (Container.Exists("map.png")) if (Container.Exists("map.png"))
CustomPreview = new Bitmap(Container.GetContent("map.png")); CustomPreview = new Bitmap(Container.GetContent("map.png"));
PostInit();
}
void PostInit()
{
rules = Exts.Lazy(() => Game.modData.RulesetCache.LoadMapRules(this));
}
public Ruleset PreloadRules()
{
return rules.Value;
} }
public CPos[] GetSpawnPoints() public CPos[] GetSpawnPoints()
@@ -282,13 +300,13 @@ namespace OpenRA
); );
root.Add(new MiniYamlNode("Smudges", MiniYaml.FromList<SmudgeReference>(Smudges.Value))); root.Add(new MiniYamlNode("Smudges", MiniYaml.FromList<SmudgeReference>(Smudges.Value)));
root.Add(new MiniYamlNode("Rules", null, Rules)); root.Add(new MiniYamlNode("Rules", null, RuleDefinitions));
root.Add(new MiniYamlNode("Sequences", null, Sequences)); root.Add(new MiniYamlNode("Sequences", null, SequenceDefinitions));
root.Add(new MiniYamlNode("VoxelSequences", null, VoxelSequences)); root.Add(new MiniYamlNode("VoxelSequences", null, VoxelSequenceDefinitions));
root.Add(new MiniYamlNode("Weapons", null, Weapons)); root.Add(new MiniYamlNode("Weapons", null, WeaponDefinitions));
root.Add(new MiniYamlNode("Voices", null, Voices)); root.Add(new MiniYamlNode("Voices", null, VoiceDefinitions));
root.Add(new MiniYamlNode("Notifications", null, Notifications)); root.Add(new MiniYamlNode("Notifications", null, NotificationDefinitions));
root.Add(new MiniYamlNode("Translations", null, Translations)); root.Add(new MiniYamlNode("Translations", null, TranslationDefinitions));
var entries = new Dictionary<string, byte[]>(); var entries = new Dictionary<string, byte[]>();
entries.Add("map.bin", SaveBinaryData()); entries.Add("map.bin", SaveBinaryData());
@@ -452,7 +470,7 @@ namespace OpenRA
public void MakeDefaultPlayers() public void MakeDefaultPlayers()
{ {
var firstRace = OpenRA.Rules.Info["world"].Traits var firstRace = Rules.Actors["world"].Traits
.WithInterface<CountryInfo>().First(c => c.Selectable).Race; .WithInterface<CountryInfo>().First(c => c.Selectable).Race;
if (!Players.ContainsKey("Neutral")) if (!Players.ContainsKey("Neutral"))
@@ -489,10 +507,10 @@ namespace OpenRA
}); });
} }
public void FixOpenAreas() public void FixOpenAreas(Ruleset rules)
{ {
var r = new Random(); var r = new Random();
var tileset = OpenRA.Rules.TileSets[Tileset]; var tileset = rules.TileSets[Tileset];
for (var j = Bounds.Top; j < Bounds.Bottom; j++) for (var j = Bounds.Top; j < Bounds.Bottom; j++)
{ {

14
OpenRA.Game/Map/MapCache.cs Executable file → Normal file
View File

@@ -27,30 +27,30 @@ namespace OpenRA
{ {
public static readonly MapPreview UnknownMap = new MapPreview(null, null); public static readonly MapPreview UnknownMap = new MapPreview(null, null);
readonly Cache<string, MapPreview> previews; readonly Cache<string, MapPreview> previews;
readonly Manifest manifest; readonly ModData modData;
readonly SheetBuilder sheetBuilder; readonly SheetBuilder sheetBuilder;
Thread previewLoaderThread; Thread previewLoaderThread;
object syncRoot = new object(); object syncRoot = new object();
Queue<MapPreview> generateMinimap = new Queue<MapPreview>(); Queue<MapPreview> generateMinimap = new Queue<MapPreview>();
public MapCache(Manifest m) public MapCache(ModData modData)
{ {
manifest = m; this.modData = modData;
previews = new Cache<string, MapPreview>(uid => new MapPreview(uid, this)); previews = new Cache<string, MapPreview>(uid => new MapPreview(uid, this));
sheetBuilder = new SheetBuilder(SheetType.BGRA); sheetBuilder = new SheetBuilder(SheetType.BGRA);
} }
public void LoadMaps() public void LoadMaps()
{ {
var paths = manifest.MapFolders.SelectMany(f => FindMapsIn(f)); var paths = modData.Manifest.MapFolders.SelectMany(f => FindMapsIn(f));
foreach (var path in paths) foreach (var path in paths)
{ {
try try
{ {
using (new Support.PerfTimer(path)) using (new Support.PerfTimer(path))
{ {
var map = new Map(path, manifest.Mod.Id); var map = new Map(path, modData.Manifest.Mod.Id);
if (manifest.MapCompatibility.Contains(map.RequiresMod)) if (modData.Manifest.MapCompatibility.Contains(map.RequiresMod))
previews[map.Uid].UpdateFromMap(map); previews[map.Uid].UpdateFromMap(map);
} }
} }
@@ -149,7 +149,7 @@ namespace OpenRA
// the next render cycle. // the next render cycle.
// (d) Any partially written bytes from the next minimap is in an // (d) Any partially written bytes from the next minimap is in an
// unallocated area, and will be committed in the next cycle. // unallocated area, and will be committed in the next cycle.
var bitmap = p.CustomPreview ?? Minimap.RenderMapPreview(p.Map, true); var bitmap = p.CustomPreview ?? Minimap.RenderMapPreview(modData.DefaultRules.TileSets[p.Map.Tileset], p.Map, modData.DefaultRules, true);
p.Minimap = sheetBuilder.Add(bitmap); p.Minimap = sheetBuilder.Add(bitmap);
lock (syncRoot) lock (syncRoot)

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
@@ -8,21 +8,23 @@
*/ */
#endregion #endregion
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using OpenRA.Graphics;
namespace OpenRA namespace OpenRA
{ {
public class TerrainTypeInfo public class TerrainTypeInfo
{ {
public string Type; public readonly string Type;
public string[] TargetTypes = { }; public readonly string[] TargetTypes = { };
public string[] AcceptsSmudgeType = { }; public readonly string[] AcceptsSmudgeType = { };
public bool IsWater = false; // TODO: Remove this public readonly bool IsWater = false; // TODO: Remove this
public Color Color; public readonly Color Color;
public string CustomCursor; public readonly string CustomCursor;
public TerrainTypeInfo() { } public TerrainTypeInfo() { }
public TerrainTypeInfo(MiniYaml my) { FieldLoader.Load(this, my); } public TerrainTypeInfo(MiniYaml my) { FieldLoader.Load(this, my); }
@@ -32,19 +34,26 @@ namespace OpenRA
public class TileTemplate public class TileTemplate
{ {
public ushort Id; public readonly ushort Id;
public string Image; public readonly string Image;
public int[] Frames; public readonly int[] Frames;
public int2 Size; public readonly int2 Size;
public bool PickAny; public readonly bool PickAny;
public string Category; public readonly string Category;
[FieldLoader.LoadUsing("LoadTiles")] [FieldLoader.LoadUsing("LoadTiles")]
public Dictionary<byte, string> Tiles = new Dictionary<byte, string>(); public readonly Dictionary<byte, string> Tiles = new Dictionary<byte, string>();
public TileTemplate() { } public TileTemplate() { }
public TileTemplate(MiniYaml my) { FieldLoader.Load(this, my); } public TileTemplate(MiniYaml my) { FieldLoader.Load(this, my); }
public TileTemplate(ushort id, string image, int2 size)
{
this.Id = id;
this.Image = image;
this.Size = size;
}
static object LoadTiles(MiniYaml y) static object LoadTiles(MiniYaml y)
{ {
return y.NodesDict["Tiles"].NodesDict.ToDictionary( return y.NodesDict["Tiles"].NodesDict.ToDictionary(
@@ -75,22 +84,20 @@ namespace OpenRA
public class TileSet public class TileSet
{ {
public string Name; public readonly string Name;
public string Id; public readonly string Id;
public int SheetSize = 512; public readonly int SheetSize = 512;
public string Palette; public readonly string Palette;
public string PlayerPalette; public readonly string PlayerPalette;
public string[] Extensions; public readonly string[] Extensions;
public int WaterPaletteRotationBase = 0x60; public readonly int WaterPaletteRotationBase = 0x60;
public Dictionary<string, TerrainTypeInfo> Terrain = new Dictionary<string, TerrainTypeInfo>(); public readonly Dictionary<string, TerrainTypeInfo> Terrain = new Dictionary<string, TerrainTypeInfo>();
public Dictionary<ushort, TileTemplate> Templates = new Dictionary<ushort, TileTemplate>(); public readonly Dictionary<ushort, TileTemplate> Templates = new Dictionary<ushort, TileTemplate>();
public string[] EditorTemplateOrder; public readonly string[] EditorTemplateOrder;
static readonly string[] Fields = { "Name", "Id", "SheetSize", "Palette", "Extensions" }; static readonly string[] Fields = { "Name", "Id", "SheetSize", "Palette", "Extensions" };
public TileSet() { } public TileSet(ModData modData, string filepath)
public TileSet(string filepath)
{ {
var yaml = MiniYaml.DictFromFile(filepath); var yaml = MiniYaml.DictFromFile(filepath);
@@ -106,6 +113,14 @@ namespace OpenRA
.Select(y => new TileTemplate(y)).ToDictionary(t => t.Id); .Select(y => new TileTemplate(y)).ToDictionary(t => t.Id);
} }
public TileSet(string name, string id, string palette, string[] extensions)
{
this.Name = name;
this.Id = id;
this.Palette = palette;
this.Extensions = extensions;
}
public void Save(string filepath) public void Save(string filepath)
{ {
var root = new List<MiniYamlNode>(); var root = new List<MiniYamlNode>();

45
OpenRA.Game/ModData.cs Executable file → Normal file
View File

@@ -1,6 +1,6 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
@@ -25,9 +25,12 @@ namespace OpenRA
public readonly WidgetLoader WidgetLoader; public readonly WidgetLoader WidgetLoader;
public readonly MapCache MapCache; public readonly MapCache MapCache;
public ILoadScreen LoadScreen = null; public ILoadScreen LoadScreen = null;
public SheetBuilder SheetBuilder;
public SpriteLoader SpriteLoader;
public VoxelLoader VoxelLoader; public VoxelLoader VoxelLoader;
public readonly RulesetCache RulesetCache;
public CursorProvider CursorProvider { get; private set; }
Lazy<Ruleset> defaultRules;
public Ruleset DefaultRules { get { return defaultRules.Value; } }
public ModData(string mod) public ModData(string mod)
{ {
@@ -38,12 +41,26 @@ namespace OpenRA
LoadScreen.Init(Manifest, Manifest.LoadScreen.NodesDict.ToDictionary(x => x.Key, x => x.Value.Value)); LoadScreen.Init(Manifest, Manifest.LoadScreen.NodesDict.ToDictionary(x => x.Key, x => x.Value.Value));
LoadScreen.Display(); LoadScreen.Display();
WidgetLoader = new WidgetLoader(this); WidgetLoader = new WidgetLoader(this);
MapCache = new MapCache(Manifest); RulesetCache = new RulesetCache(this);
RulesetCache.LoadingProgress += HandleLoadingProgress;
MapCache = new MapCache(this);
// HACK: Mount only local folders so we have a half-working environment for the asset installer // HACK: Mount only local folders so we have a half-working environment for the asset installer
GlobalFileSystem.UnmountAll(); GlobalFileSystem.UnmountAll();
foreach (var dir in Manifest.Folders) foreach (var dir in Manifest.Folders)
GlobalFileSystem.Mount(dir); GlobalFileSystem.Mount(dir);
defaultRules = Exts.Lazy(() => RulesetCache.LoadDefaultRules());
initialThreadId = System.Threading.Thread.CurrentThread.ManagedThreadId;
}
// HACK: Only update the loading screen if we're in the main thread.
int initialThreadId;
void HandleLoadingProgress(object sender, EventArgs e)
{
if (LoadScreen != null && System.Threading.Thread.CurrentThread.ManagedThreadId == initialThreadId)
LoadScreen.Display();
} }
public void InitializeLoaders() public void InitializeLoaders()
@@ -52,10 +69,9 @@ namespace OpenRA
// horribly when you use ModData in unexpected ways. // horribly when you use ModData in unexpected ways.
ChromeMetrics.Initialize(Manifest.ChromeMetrics); ChromeMetrics.Initialize(Manifest.ChromeMetrics);
ChromeProvider.Initialize(Manifest.Chrome); ChromeProvider.Initialize(Manifest.Chrome);
SheetBuilder = new SheetBuilder(SheetType.Indexed);
SpriteLoader = new SpriteLoader(new string[0], SheetBuilder);
VoxelLoader = new VoxelLoader(); VoxelLoader = new VoxelLoader();
CursorProvider.Initialize(Manifest.Cursors);
CursorProvider = new CursorProvider(this);
} }
public IEnumerable<string> Languages { get; private set; } public IEnumerable<string> Languages { get; private set; }
@@ -75,7 +91,7 @@ namespace OpenRA
var yaml = Manifest.Translations.Select(MiniYaml.FromFile).Aggregate(MiniYaml.MergeLiberal); var yaml = Manifest.Translations.Select(MiniYaml.FromFile).Aggregate(MiniYaml.MergeLiberal);
Languages = yaml.Select(t => t.Key).ToArray(); Languages = yaml.Select(t => t.Key).ToArray();
yaml = MiniYaml.MergeLiberal(map.Translations, yaml); yaml = MiniYaml.MergeLiberal(map.TranslationDefinitions, yaml);
foreach (var y in yaml) foreach (var y in yaml)
{ {
@@ -118,16 +134,11 @@ namespace OpenRA
// Mount map package so custom assets can be used. TODO: check priority. // Mount map package so custom assets can be used. TODO: check priority.
GlobalFileSystem.Mount(GlobalFileSystem.OpenPackage(map.Path, null, int.MaxValue)); GlobalFileSystem.Mount(GlobalFileSystem.OpenPackage(map.Path, null, int.MaxValue));
using (new Support.PerfTimer("LoadRules")) using (new Support.PerfTimer("Map.LoadRules"))
Rules.LoadRules(Manifest, map); map.PreloadRules();
SpriteLoader = new SpriteLoader(Rules.TileSets[map.Tileset].Extensions, SheetBuilder);
VoxelProvider.Initialize(Manifest.VoxelSequences, map.VoxelSequenceDefinitions);
using (new Support.PerfTimer("SequenceProvider.Initialize"))
{
// TODO: Don't load the sequences for assets that are not used in this tileset. Maybe use the existing EditorTilesetFilters.
SequenceProvider.Initialize(Manifest.Sequences, map.Sequences);
}
VoxelProvider.Initialize(Manifest.VoxelSequences, map.VoxelSequences);
return map; return map;
} }
} }

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
@@ -14,9 +14,9 @@ using System.Linq;
namespace OpenRA namespace OpenRA
{ {
public class Mod public class ModMetadata
{ {
public static readonly Dictionary<string, Mod> AllMods = ValidateMods(Directory.GetDirectories("mods").Select(x => x.Substring(5)).ToArray()); public static readonly Dictionary<string, ModMetadata> AllMods = ValidateMods(Directory.GetDirectories("mods").Select(x => x.Substring(5)).ToArray());
public string Id; public string Id;
public string Title; public string Title;
@@ -24,9 +24,9 @@ namespace OpenRA
public string Version; public string Version;
public string Author; public string Author;
public static Dictionary<string, Mod> ValidateMods(string[] mods) public static Dictionary<string, ModMetadata> ValidateMods(string[] mods)
{ {
var ret = new Dictionary<string, Mod>(); var ret = new Dictionary<string, ModMetadata>();
foreach (var m in mods) foreach (var m in mods)
{ {
var yamlPath = new[] { "mods", m, "mod.yaml" }.Aggregate(Path.Combine); var yamlPath = new[] { "mods", m, "mod.yaml" }.Aggregate(Path.Combine);
@@ -37,7 +37,7 @@ namespace OpenRA
if (!yaml.NodesDict.ContainsKey("Metadata")) if (!yaml.NodesDict.ContainsKey("Metadata"))
continue; continue;
var mod = FieldLoader.Load<Mod>(yaml.NodesDict["Metadata"]); var mod = FieldLoader.Load<ModMetadata>(yaml.NodesDict["Metadata"]);
mod.Id = m; mod.Id = m;
ret.Add(m, mod); ret.Add(m, mod);

View File

@@ -99,7 +99,6 @@
<Compile Include="Game.cs" /> <Compile Include="Game.cs" />
<Compile Include="GameRules\ActorInfo.cs" /> <Compile Include="GameRules\ActorInfo.cs" />
<Compile Include="GameRules\MusicInfo.cs" /> <Compile Include="GameRules\MusicInfo.cs" />
<Compile Include="GameRules\Rules.cs" />
<Compile Include="GameRules\SoundInfo.cs" /> <Compile Include="GameRules\SoundInfo.cs" />
<Compile Include="GameRules\WeaponInfo.cs" /> <Compile Include="GameRules\WeaponInfo.cs" />
<Compile Include="Graphics\Animation.cs" /> <Compile Include="Graphics\Animation.cs" />
@@ -244,6 +243,10 @@
<Compile Include="Scripting\ScriptMemberExts.cs" /> <Compile Include="Scripting\ScriptMemberExts.cs" />
<Compile Include="Scripting\ScriptPlayerInterface.cs" /> <Compile Include="Scripting\ScriptPlayerInterface.cs" />
<Compile Include="Traits\Player\FixedColorPalette.cs" /> <Compile Include="Traits\Player\FixedColorPalette.cs" />
<Compile Include="Primitives\ReadOnlyDictionary.cs" />
<Compile Include="ModMetadata.cs" />
<Compile Include="GameRules\Ruleset.cs" />
<Compile Include="GameRules\RulesetCache.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="FileSystem\D2kSoundResources.cs" /> <Compile Include="FileSystem\D2kSoundResources.cs" />
@@ -303,7 +306,6 @@
<Compile Include="Hotkey.cs" /> <Compile Include="Hotkey.cs" />
<Compile Include="Keycode.cs" /> <Compile Include="Keycode.cs" />
<Compile Include="MiniYaml.cs" /> <Compile Include="MiniYaml.cs" />
<Compile Include="Mod.cs" />
<Compile Include="Platform.cs" /> <Compile Include="Platform.cs" />
<Compile Include="StreamExts.cs" /> <Compile Include="StreamExts.cs" />
<Compile Include="Map\Map.cs" /> <Compile Include="Map\Map.cs" />

View File

@@ -47,7 +47,7 @@ namespace OpenRA
static CountryInfo ChooseCountry(World world, string name) static CountryInfo ChooseCountry(World world, string name)
{ {
var selectableCountries = Rules.Info["world"].Traits var selectableCountries = world.Map.Rules.Actors["world"].Traits
.WithInterface<CountryInfo>().Where( c => c.Selectable ) .WithInterface<CountryInfo>().Where( c => c.Selectable )
.ToArray(); .ToArray();

View File

@@ -0,0 +1,90 @@
#region Copyright & License Information
/*
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
namespace OpenRA
{
/// <summary>
/// A minimal read only dictionary interface for .NET 4
/// </summary>
/// <remarks>
/// .NET 4.5 has an implementation built-in, this code is not meant to
/// duplicate it but provide a compatible interface that can be replaced
/// when we switch to .NET 4.5 or higher.
/// </remarks>
public interface IReadOnlyDictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>
{
int Count { get; }
TValue this[TKey key] { get; }
IEnumerable<TKey> Keys { get; }
IEnumerable<TValue> Values { get; }
bool ContainsKey(TKey key);
bool TryGetValue(TKey key, out TValue value);
}
/// <summary>
/// A minimal read only dictionary for .NET 4 implemented as a wrapper
/// around an IDictionary.
/// </summary>
public class ReadOnlyDictionary<TKey, TValue> : IReadOnlyDictionary<TKey, TValue>
{
private readonly IDictionary<TKey, TValue> dict;
public ReadOnlyDictionary()
: this(new Dictionary<TKey, TValue>())
{
}
public ReadOnlyDictionary(IDictionary<TKey, TValue> dict)
{
if (dict == null)
throw new ArgumentNullException("dict");
this.dict = dict;
}
#region IReadOnlyDictionary implementation
public bool ContainsKey(TKey key)
{
return dict.ContainsKey(key);
}
public bool TryGetValue(TKey key, out TValue value)
{
return dict.TryGetValue(key, out value);
}
public int Count { get { return dict.Count; } }
public TValue this[TKey key] { get { return dict[key]; } }
public IEnumerable<TKey> Keys { get { return dict.Keys; } }
public IEnumerable<TValue> Values { get { return dict.Values; } }
#endregion
#region IEnumerable implementation
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
return dict.GetEnumerator();
}
#endregion
#region IEnumerable implementation
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return dict.GetEnumerator();
}
#endregion
}
}

View File

@@ -296,15 +296,18 @@ namespace OpenRA
} }
// Returns true if played successfully // Returns true if played successfully
public static bool PlayPredefined(Player p, Actor voicedUnit, string type, string definition, string variant, bool relative, WPos pos, float volumeModifier, bool attenuateVolume) public static bool PlayPredefined(Ruleset ruleset, Player p, Actor voicedUnit, string type, string definition, string variant, bool relative, WPos pos, float volumeModifier, bool attenuateVolume)
{ {
if (ruleset == null)
throw new ArgumentNullException("ruleset");
if (definition == null) if (definition == null)
return false; return false;
if (Rules.Voices == null || Rules.Notifications == null) if (ruleset.Voices == null || ruleset.Notifications == null)
return false; return false;
var rules = (voicedUnit != null) ? Rules.Voices[type] : Rules.Notifications[type]; var rules = (voicedUnit != null) ? ruleset.Voices[type] : ruleset.Notifications[type];
if (rules == null) if (rules == null)
return false; return false;
@@ -366,7 +369,7 @@ namespace OpenRA
return false; return false;
var type = mi.Voice.ToLowerInvariant(); var type = mi.Voice.ToLowerInvariant();
return PlayPredefined(null, voicedUnit, type, phrase, variant, true, WPos.Zero, 1f, true); return PlayPredefined(voicedUnit.World.Map.Rules, null, voicedUnit, type, phrase, variant, true, WPos.Zero, 1f, true);
} }
public static bool PlayVoiceLocal(string phrase, Actor voicedUnit, string variant, WPos pos, float volume) public static bool PlayVoiceLocal(string phrase, Actor voicedUnit, string variant, WPos pos, float volume)
@@ -379,15 +382,18 @@ namespace OpenRA
return false; return false;
var type = mi.Voice.ToLowerInvariant(); var type = mi.Voice.ToLowerInvariant();
return PlayPredefined(null, voicedUnit, type, phrase, variant, false, pos, volume, true); return PlayPredefined(voicedUnit.World.Map.Rules, null, voicedUnit, type, phrase, variant, false, pos, volume, true);
} }
public static bool PlayNotification(Player player, string type, string notification, string variant) public static bool PlayNotification(Ruleset rules, Player player, string type, string notification, string variant)
{ {
if (rules == null)
throw new ArgumentNullException("rules");
if (type == null || notification == null) if (type == null || notification == null)
return false; return false;
return PlayPredefined(player, null, type.ToLowerInvariant(), notification, variant, true, WPos.Zero, 1f, false); return PlayPredefined(rules, player, null, type.ToLowerInvariant(), notification, variant, true, WPos.Zero, 1f, false);
} }
} }

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2012 The OpenRA Developers (see AUTHORS) * Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
@@ -118,7 +118,7 @@ namespace OpenRA.Traits
{ {
if (Ore > 0.8 * OreCapacity) if (Ore > 0.8 * OreCapacity)
{ {
Sound.PlayNotification(Owner, "Speech", "SilosNeeded", Owner.Country.Race); Sound.PlayNotification(self.World.Map.Rules, Owner, "Speech", "SilosNeeded", Owner.Country.Race);
AlertSilo = true; AlertSilo = true;
} }
else else
@@ -163,14 +163,14 @@ namespace OpenRA.Traits
public void playCashTickUp(Actor self) public void playCashTickUp(Actor self)
{ {
if (Game.Settings.Sound.CashTicks) if (Game.Settings.Sound.CashTicks)
Sound.PlayNotification(self.Owner, "Sounds", "CashTickUp", self.Owner.Country.Race); Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Sounds", "CashTickUp", self.Owner.Country.Race);
} }
public void playCashTickDown(Actor self) public void playCashTickDown(Actor self)
{ {
if (Game.Settings.Sound.CashTicks && nextCashTickTime == 0) if (Game.Settings.Sound.CashTicks && nextCashTickTime == 0)
{ {
Sound.PlayNotification(self.Owner, "Sounds", "CashTickDown", self.Owner.Country.Race); Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Sounds", "CashTickDown", self.Owner.Country.Race);
nextCashTickTime = 2; nextCashTickTime = 2;
} }
} }

View File

@@ -19,9 +19,9 @@ namespace OpenRA.Traits
{ {
public override object Create(ActorInitializer init) { return new RenderSimple(init.self); } public override object Create(ActorInitializer init) { return new RenderSimple(init.self); }
public virtual IEnumerable<IRenderable> RenderPreview(ActorInfo ai, PaletteReference pr) public virtual IEnumerable<IRenderable> RenderPreview(World world, ActorInfo ai, PaletteReference pr)
{ {
var anim = new Animation(RenderSimple.GetImage(ai), () => 0); var anim = new Animation(world, RenderSimple.GetImage(ai), () => 0);
anim.PlayRepeating("idle"); anim.PlayRepeating("idle");
return anim.Render(WPos.Zero, WVec.Zero, 0, pr, Scale); return anim.Render(WPos.Zero, WVec.Zero, 0, pr, Scale);
@@ -35,7 +35,7 @@ namespace OpenRA.Traits
public RenderSimple(Actor self, Func<int> baseFacing) public RenderSimple(Actor self, Func<int> baseFacing)
: base(self) : base(self)
{ {
anims.Add("", new Animation(GetImage(self), baseFacing)); anims.Add("", new Animation(self.World, GetImage(self), baseFacing));
Info = self.Info.Traits.Get<RenderSimpleInfo>(); Info = self.Info.Traits.Get<RenderSimpleInfo>();
} }

View File

@@ -57,7 +57,7 @@ namespace OpenRA.Traits
var group = self.World.Selection.GetControlGroupForActor(self); var group = self.World.Selection.GetControlGroupForActor(self);
if (group == null) return; if (group == null) return;
var pipImages = new Animation("pips"); var pipImages = new Animation(self.World, "pips");
var pal = wr.Palette(Info.Palette); var pal = wr.Palette(Info.Palette);
pipImages.PlayFetchIndex("groups", () => (int)group); pipImages.PlayFetchIndex("groups", () => (int)group);
pipImages.Tick(); pipImages.Tick();
@@ -75,7 +75,7 @@ namespace OpenRA.Traits
if (!pipSources.Any()) if (!pipSources.Any())
return; return;
var pipImages = new Animation("pips"); var pipImages = new Animation(self.World, "pips");
pipImages.PlayRepeating(pipStrings[0]); pipImages.PlayRepeating(pipStrings[0]);
var pipSize = pipImages.Image.size.ToInt2(); var pipSize = pipImages.Image.size.ToInt2();
@@ -115,7 +115,7 @@ namespace OpenRA.Traits
if (!self.Owner.IsAlliedWith(self.World.RenderPlayer)) if (!self.Owner.IsAlliedWith(self.World.RenderPlayer))
return; return;
var tagImages = new Animation("pips"); var tagImages = new Animation(self.World, "pips");
var pal = wr.Palette(Info.Palette); var pal = wr.Palette(Info.Palette);
var tagxyOffset = new int2(0, 6); var tagxyOffset = new int2(0, 6);
var tagBase = wr.Viewport.WorldToViewPx(basePosition); var tagBase = wr.Viewport.WorldToViewPx(basePosition);

View File

@@ -32,7 +32,7 @@ namespace OpenRA.Traits
public PipType PipColor = PipType.Yellow; public PipType PipColor = PipType.Yellow;
public object Create(ActorInitializer init) { return new ResourceType(this); } public object Create(ActorInitializer init) { return new ResourceType(this, init.world); }
} }
public class ResourceType : IWorldLoaded public class ResourceType : IWorldLoaded
@@ -41,13 +41,13 @@ namespace OpenRA.Traits
public PaletteReference Palette { get; private set; } public PaletteReference Palette { get; private set; }
public readonly Dictionary<string, Sprite[]> Variants; public readonly Dictionary<string, Sprite[]> Variants;
public ResourceType(ResourceTypeInfo info) public ResourceType(ResourceTypeInfo info, World world)
{ {
this.Info = info; this.Info = info;
Variants = new Dictionary<string, Sprite[]>(); Variants = new Dictionary<string, Sprite[]>();
foreach (var v in info.Variants) foreach (var v in info.Variants)
{ {
var seq = SequenceProvider.GetSequence("resources", v); var seq = world.Map.SequenceProvider.GetSequence("resources", v);
var sprites = Exts.MakeArray(seq.Length, x => seq.GetSprite(x)); var sprites = Exts.MakeArray(seq.Length, x => seq.GetSprite(x));
Variants.Add(v, sprites); Variants.Add(v, sprites);
} }

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS) * Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
@@ -53,8 +53,13 @@ namespace OpenRA.Widgets
public Action OnDoubleClick = () => {}; public Action OnDoubleClick = () => {};
public Action<KeyInput> OnKeyPress = _ => {}; public Action<KeyInput> OnKeyPress = _ => {};
public ButtonWidget() readonly Ruleset modRules;
[ObjectCreator.UseCtor]
public ButtonWidget(Ruleset modRules)
{ {
this.modRules = modRules;
GetText = () => { return Text; }; GetText = () => { return Text; };
GetColor = () => TextColor; GetColor = () => TextColor;
GetColorDisabled = () => TextColorDisabled; GetColorDisabled = () => TextColorDisabled;
@@ -70,6 +75,8 @@ namespace OpenRA.Widgets
protected ButtonWidget(ButtonWidget other) protected ButtonWidget(ButtonWidget other)
: base(other) : base(other)
{ {
this.modRules = other.modRules;
Text = other.Text; Text = other.Text;
Font = other.Font; Font = other.Font;
TextColor = other.TextColor; TextColor = other.TextColor;
@@ -113,10 +120,10 @@ namespace OpenRA.Widgets
if (!IsDisabled()) if (!IsDisabled())
{ {
OnKeyPress(e); OnKeyPress(e);
Sound.PlayNotification(null, "Sounds", "ClickSound", null); Sound.PlayNotification(modRules, null, "Sounds", "ClickSound", null);
} }
else else
Sound.PlayNotification(null, "Sounds", "ClickDisabledSound", null); Sound.PlayNotification(modRules, null, "Sounds", "ClickDisabledSound", null);
return true; return true;
} }
@@ -153,12 +160,12 @@ namespace OpenRA.Widgets
{ {
OnMouseDown(mi); OnMouseDown(mi);
Depressed = true; Depressed = true;
Sound.PlayNotification(null, "Sounds", "ClickSound", null); Sound.PlayNotification(modRules, null, "Sounds", "ClickSound", null);
} }
else else
{ {
YieldMouseFocus(mi); YieldMouseFocus(mi);
Sound.PlayNotification(null, "Sounds", "ClickDisabledSound", null); Sound.PlayNotification(modRules, null, "Sounds", "ClickDisabledSound", null);
} }
} }
else if (mi.Event == MouseInputEvent.Move && HasMouseFocus) else if (mi.Event == MouseInputEvent.Move && HasMouseFocus)

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
@@ -11,6 +11,7 @@
using System; using System;
using System.Drawing; using System.Drawing;
using OpenRA.Graphics; using OpenRA.Graphics;
using OpenRA.Network;
namespace OpenRA.Widgets namespace OpenRA.Widgets
{ {
@@ -23,7 +24,9 @@ namespace OpenRA.Widgets
public int CheckOffset = 2; public int CheckOffset = 2;
public bool HasPressedState = ChromeMetrics.Get<bool>("CheckboxPressedState"); public bool HasPressedState = ChromeMetrics.Get<bool>("CheckboxPressedState");
public CheckboxWidget() [ObjectCreator.UseCtor]
public CheckboxWidget(Ruleset modRules)
: base(modRules)
{ {
GetCheckType = () => CheckType; GetCheckType = () => CheckType;
} }

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
@@ -12,6 +12,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using OpenRA.Graphics; using OpenRA.Graphics;
using OpenRA.Network;
namespace OpenRA.Widgets namespace OpenRA.Widgets
{ {
@@ -20,7 +21,9 @@ namespace OpenRA.Widgets
Widget panel; Widget panel;
MaskWidget fullscreenMask; MaskWidget fullscreenMask;
public DropDownButtonWidget() { } [ObjectCreator.UseCtor]
public DropDownButtonWidget(Ruleset modRules)
: base(modRules) { }
protected DropDownButtonWidget(DropDownButtonWidget widget) : base(widget) { } protected DropDownButtonWidget(DropDownButtonWidget widget) : base(widget) { }

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
@@ -9,6 +9,8 @@
#endregion #endregion
using System; using System;
using OpenRA.Graphics;
using OpenRA.Network;
namespace OpenRA.Widgets namespace OpenRA.Widgets
{ {
@@ -17,7 +19,9 @@ namespace OpenRA.Widgets
public string ItemKey; public string ItemKey;
public string BaseName = "scrollitem"; public string BaseName = "scrollitem";
public ScrollItemWidget() [ObjectCreator.UseCtor]
public ScrollItemWidget(Ruleset modRules)
: base(modRules)
{ {
IsVisible = () => false; IsVisible = () => false;
VisualHeight = 0; VisualHeight = 0;

View File

@@ -36,7 +36,7 @@ namespace OpenRA.Widgets
if (Unit != null && Sequence != null) if (Unit != null && Sequence != null)
{ {
var anim = new Animation(Unit, () => Facing); var anim = new Animation(worldRenderer.world, Unit, () => Facing);
anim.PlayFetchIndex(Sequence, () => Frame); anim.PlayFetchIndex(Sequence, () => Frame);
GetAnimation = () => anim; GetAnimation = () => anim;
} }

View File

@@ -19,7 +19,7 @@ namespace OpenRA.Widgets
public Func<string> GetPalette; public Func<string> GetPalette;
public Func<Sprite> GetSprite; public Func<Sprite> GetSprite;
readonly WorldRenderer worldRenderer; protected readonly WorldRenderer worldRenderer;
[ObjectCreator.UseCtor] [ObjectCreator.UseCtor]
public SpriteWidget(WorldRenderer worldRenderer) public SpriteWidget(WorldRenderer worldRenderer)

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
@@ -18,10 +18,13 @@ namespace OpenRA
{ {
public class WidgetLoader public class WidgetLoader
{ {
Dictionary<string, MiniYamlNode> widgets = new Dictionary<string, MiniYamlNode>(); readonly Dictionary<string, MiniYamlNode> widgets = new Dictionary<string, MiniYamlNode>();
readonly ModData modData;
public WidgetLoader(ModData modData) public WidgetLoader(ModData modData)
{ {
this.modData = modData;
foreach (var file in modData.Manifest.ChromeLayout.Select(a => MiniYaml.FromFile(a))) foreach (var file in modData.Manifest.ChromeLayout.Select(a => MiniYaml.FromFile(a)))
foreach( var w in file ) foreach( var w in file )
{ {
@@ -55,6 +58,8 @@ namespace OpenRA
if (child.Key != "Children") if (child.Key != "Children")
FieldLoader.LoadField(widget, child.Key, child.Value.Value); FieldLoader.LoadField(widget, child.Key, child.Value.Value);
if (!args.ContainsKey("modRules"))
args = new WidgetArgs(args) { { "modRules", modData.DefaultRules } };
widget.Initialize(args); widget.Initialize(args);
foreach (var child in node.Value.Nodes) foreach (var child in node.Value.Nodes)

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
@@ -118,14 +118,14 @@ namespace OpenRA
} }
} }
internal World(Manifest manifest, Map map, OrderManager orderManager, bool isShellmap) internal World(Map map, OrderManager orderManager, bool isShellmap)
{ {
IsShellmap = isShellmap; IsShellmap = isShellmap;
this.orderManager = orderManager; this.orderManager = orderManager;
orderGenerator_ = new UnitOrderGenerator(); orderGenerator_ = new UnitOrderGenerator();
Map = map; Map = map;
TileSet = Rules.TileSets[Map.Tileset]; TileSet = map.Rules.TileSets[Map.Tileset];
SharedRandom = new XRandom(orderManager.LobbyInfo.GlobalSettings.RandomSeed); SharedRandom = new XRandom(orderManager.LobbyInfo.GlobalSettings.RandomSeed);
WorldActor = CreateActor("World", new TypeDictionary()); WorldActor = CreateActor("World", new TypeDictionary());

View File

@@ -151,7 +151,7 @@ namespace OpenRA
var selectable = a.Info.Traits.GetOrDefault<SelectableInfo>(); var selectable = a.Info.Traits.GetOrDefault<SelectableInfo>();
if (selectable == null) return null; if (selectable == null) return null;
var v = selectable.Voice; var v = selectable.Voice;
return (v == null) ? null : Rules.Voices[v.ToLowerInvariant()]; return (v == null) ? null : a.World.Map.Rules.Voices[v.ToLowerInvariant()];
} }
public static void PlayVoiceForOrders(this World w, Order[] orders) public static void PlayVoiceForOrders(this World w, Order[] orders)

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
@@ -69,7 +69,7 @@ namespace OpenRA.Lint
foreach (var testMap in maps) foreach (var testMap in maps)
{ {
if (testMap.Rules.Count < 1) if (testMap.RuleDefinitions.Count < 1)
{ {
if (verbose) if (verbose)
Console.WriteLine("No custom rules detected. Omitting Map: {0}".F(testMap.Title)); Console.WriteLine("No custom rules detected. Omitting Map: {0}".F(testMap.Title));
@@ -79,7 +79,7 @@ namespace OpenRA.Lint
if (verbose) if (verbose)
Console.WriteLine("Map: {0}".F(testMap.Title)); Console.WriteLine("Map: {0}".F(testMap.Title));
Rules.LoadRules(Game.modData.Manifest, testMap); testMap.PreloadRules();
foreach (var customPassType in Game.modData.ObjectCreator foreach (var customPassType in Game.modData.ObjectCreator
.GetTypesImplementing<ILintPass>()) .GetTypesImplementing<ILintPass>())

View File

@@ -18,11 +18,11 @@ namespace OpenRA.Mods.Cnc.Effects
{ {
public class IonCannon : IEffect public class IonCannon : IEffect
{ {
Target target; readonly Target target;
Animation anim; readonly Animation anim;
Player firedBy; readonly Player firedBy;
string palette; readonly string palette;
string weapon; readonly string weapon;
public IonCannon(Player firedBy, string weapon, World world, CPos location, string effect, string palette) public IonCannon(Player firedBy, string weapon, World world, CPos location, string effect, string palette)
{ {
@@ -30,7 +30,7 @@ namespace OpenRA.Mods.Cnc.Effects
this.weapon = weapon; this.weapon = weapon;
this.palette = palette; this.palette = palette;
target = Target.FromCell(location); target = Target.FromCell(location);
anim = new Animation(effect); anim = new Animation(world, effect);
anim.PlayThen("idle", () => Finish(world)); anim.PlayThen("idle", () => Finish(world));
} }

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
@@ -40,7 +40,7 @@ namespace OpenRA.Mods.Cnc
if (r == null) return; if (r == null) return;
if (!info.Resources.Contains(r.Info.Name)) return; if (!info.Resources.Contains(r.Info.Name)) return;
var weapon = Rules.Weapons[info.Weapon.ToLowerInvariant()]; var weapon = self.World.Map.Rules.Weapons[info.Weapon.ToLowerInvariant()];
self.InflictDamage(self.World.WorldActor, weapon.Warheads[0].Damage, weapon.Warheads[0]); self.InflictDamage(self.World.WorldActor, weapon.Warheads[0].Damage, weapon.Warheads[0]);
poisonTicks = weapon.ROF; poisonTicks = weapon.ROF;

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
@@ -52,7 +52,7 @@ namespace OpenRA.Mods.Cnc
owner.World.AddFrameEndTask(w => owner.World.AddFrameEndTask(w =>
{ {
var altitude = Rules.Info[actorType].Traits.Get<PlaneInfo>().CruiseAltitude; var altitude = self.World.Map.Rules.Actors[actorType].Traits.Get<PlaneInfo>().CruiseAltitude;
var a = w.CreateActor(actorType, new TypeDictionary var a = w.CreateActor(actorType, new TypeDictionary
{ {
new CenterPositionInit(startPos.CenterPosition + new WVec(WRange.Zero, WRange.Zero, altitude)), new CenterPositionInit(startPos.CenterPosition + new WVec(WRange.Zero, WRange.Zero, altitude)),
@@ -69,7 +69,7 @@ namespace OpenRA.Mods.Cnc
rb.PlayCustomAnimRepeating(self, "idle"); rb.PlayCustomAnimRepeating(self, "idle");
self.World.AddFrameEndTask(ww => DoProduction(self, producee, exit)); self.World.AddFrameEndTask(ww => DoProduction(self, producee, exit));
Sound.PlayNotification(self.Owner, "Speech", (Info as ProductionAirdropInfo).ReadyAudio, self.Owner.Country.Race); Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", (Info as ProductionAirdropInfo).ReadyAudio, self.Owner.Country.Race);
})); }));
a.QueueActivity(new Fly(a, Target.FromCell(endPos))); a.QueueActivity(new Fly(a, Target.FromCell(endPos)));

View File

@@ -35,19 +35,19 @@ namespace OpenRA.Mods.RA.Render
var turret = self.TraitsImplementing<Turreted>() var turret = self.TraitsImplementing<Turreted>()
.First(t => t.Name == info.Turret); .First(t => t.Name == info.Turret);
left = new Animation(name, () => turret.turretFacing); left = new Animation(self.World, name, () => turret.turretFacing);
left.Play("left"); left.Play("left");
anims.Add("left", new AnimationWithOffset(left, null, () => facing.Facing > 128, 0)); anims.Add("left", new AnimationWithOffset(left, null, () => facing.Facing > 128, 0));
right = new Animation(name, () => turret.turretFacing); right = new Animation(self.World, name, () => turret.turretFacing);
right.Play("right"); right.Play("right");
anims.Add("right", new AnimationWithOffset(right, null, () => facing.Facing <= 128, 0)); anims.Add("right", new AnimationWithOffset(right, null, () => facing.Facing <= 128, 0));
var leftWake = new Animation(name); var leftWake = new Animation(self.World, name);
leftWake.Play("wake-left"); leftWake.Play("wake-left");
anims.Add("wake-left", new AnimationWithOffset(leftWake, null, () => facing.Facing > 128, -87)); anims.Add("wake-left", new AnimationWithOffset(leftWake, null, () => facing.Facing > 128, -87));
var rightWake = new Animation(name); var rightWake = new Animation(self.World, name);
rightWake.Play("wake-right"); rightWake.Play("wake-right");
anims.Add("wake-right", new AnimationWithOffset(rightWake, null, () => facing.Facing <= 128, -87)); anims.Add("wake-right", new AnimationWithOffset(rightWake, null, () => facing.Facing <= 128, -87));

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
@@ -22,7 +22,7 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic
public class CncIngameChromeLogic public class CncIngameChromeLogic
{ {
Widget ingameRoot; Widget ingameRoot;
World world; readonly World world;
[ObjectCreator.UseCtor] [ObjectCreator.UseCtor]
public CncIngameChromeLogic(Widget widget, World world) public CncIngameChromeLogic(Widget widget, World world)
@@ -95,7 +95,7 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic
.Any(a => a.Actor.Owner == world.LocalPlayer && a.Trait.IsActive); .Any(a => a.Actor.Owner == world.LocalPlayer && a.Trait.IsActive);
if (radarEnabled != cachedRadarEnabled) if (radarEnabled != cachedRadarEnabled)
Sound.PlayNotification(null, "Sounds", radarEnabled ? "RadarUp" : "RadarDown", null); Sound.PlayNotification(world.Map.Rules, null, "Sounds", radarEnabled ? "RadarUp" : "RadarDown", null);
cachedRadarEnabled = radarEnabled; cachedRadarEnabled = radarEnabled;
// Switch to observer mode after win/loss // Switch to observer mode after win/loss

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
@@ -39,7 +39,7 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic
// TODO: Create a mechanism to do things like this cleaner. Also needed for scripted missions // TODO: Create a mechanism to do things like this cleaner. Also needed for scripted missions
Action onQuit = () => Action onQuit = () =>
{ {
Sound.PlayNotification(null, "Speech", "Leave", null); Sound.PlayNotification(world.Map.Rules, null, "Speech", "Leave", null);
resumeDisabled = true; resumeDisabled = true;
Game.RunAfterDelay(1200, () => mpe.Fade(MenuPaletteEffect.EffectType.Black)); Game.RunAfterDelay(1200, () => mpe.Fade(MenuPaletteEffect.EffectType.Black));
Game.RunAfterDelay(1200 + 40 * mpe.Info.FadeLength, () => Game.RunAfterDelay(1200 + 40 * mpe.Info.FadeLength, () =>

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
@@ -20,7 +20,7 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic
public class CncInstallMusicLogic public class CncInstallMusicLogic
{ {
[ObjectCreator.UseCtor] [ObjectCreator.UseCtor]
public CncInstallMusicLogic(Widget widget, Action onExit) public CncInstallMusicLogic(Widget widget, Ruleset modRules, Action onExit)
{ {
var installButton = widget.GetOrNull<ButtonWidget>("INSTALL_BUTTON"); var installButton = widget.GetOrNull<ButtonWidget>("INSTALL_BUTTON");
if (installButton != null) if (installButton != null)
@@ -33,7 +33,7 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic
GlobalFileSystem.Mount(Path.Combine(path, "scores.mix")); GlobalFileSystem.Mount(Path.Combine(path, "scores.mix"));
GlobalFileSystem.Mount(Path.Combine(path, "transit.mix")); GlobalFileSystem.Mount(Path.Combine(path, "transit.mix"));
Rules.Music.Do(m => m.Value.Reload()); modRules.Music.Do(m => m.Value.Reload());
var musicPlayerLogic = (MusicPlayerLogic)installButton.Parent.LogicObject; var musicPlayerLogic = (MusicPlayerLogic)installButton.Parent.LogicObject;
musicPlayerLogic.BuildMusicTable(); musicPlayerLogic.BuildMusicTable();
@@ -50,7 +50,7 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic
{ "filesToCopy", new[] { "SCORES.MIX" } }, { "filesToCopy", new[] { "SCORES.MIX" } },
{ "filesToExtract", new[] { "transit.mix" } }, { "filesToExtract", new[] { "transit.mix" } },
}); });
installButton.IsVisible = () => Rules.InstalledMusic.ToArray().Length < 3; // HACK around music being split between transit.mix and scores.mix installButton.IsVisible = () => modRules.InstalledMusic.ToArray().Length < 3; // HACK around music being split between transit.mix and scores.mix
} }
} }
} }

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
@@ -16,7 +16,7 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic
public class ProductionTabsLogic public class ProductionTabsLogic
{ {
ProductionTabsWidget tabs; ProductionTabsWidget tabs;
World world; readonly World world;
void SetupProductionGroupButton(ProductionTypeButtonWidget button) void SetupProductionGroupButton(ProductionTypeButtonWidget button)
{ {

View File

@@ -23,6 +23,7 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic
[ObjectCreator.UseCtor] [ObjectCreator.UseCtor]
public ProductionTooltipLogic(Widget widget, TooltipContainerWidget tooltipContainer, ProductionPaletteWidget palette) public ProductionTooltipLogic(Widget widget, TooltipContainerWidget tooltipContainer, ProductionPaletteWidget palette)
{ {
var mapRules = palette.World.Map.Rules;
var pm = palette.World.LocalPlayer.PlayerActor.Trait<PowerManager>(); var pm = palette.World.LocalPlayer.PlayerActor.Trait<PowerManager>();
var pr = palette.World.LocalPlayer.PlayerActor.Trait<PlayerResources>(); var pr = palette.World.LocalPlayer.PlayerActor.Trait<PlayerResources>();
@@ -45,7 +46,7 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic
if (actor == null || actor == lastActor) if (actor == null || actor == lastActor)
return; return;
var info = Rules.Info[actor]; var info = mapRules.Actors[actor];
var tooltip = info.Traits.Get<TooltipInfo>(); var tooltip = info.Traits.Get<TooltipInfo>();
var buildable = info.Traits.Get<BuildableInfo>(); var buildable = info.Traits.Get<BuildableInfo>();
var cost = info.Traits.Get<ValuedInfo>().Cost; var cost = info.Traits.Get<ValuedInfo>().Cost;
@@ -53,7 +54,7 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic
nameLabel.GetText = () => tooltip.Name; nameLabel.GetText = () => tooltip.Name;
var prereqs = buildable.Prerequisites.Select(a => ActorName(a)); var prereqs = buildable.Prerequisites.Select(a => ActorName(mapRules, a));
var requiresString = prereqs.Any() ? requiresLabel.Text.F(prereqs.JoinWith(", ")) : ""; var requiresString = prereqs.Any() ? requiresLabel.Text.F(prereqs.JoinWith(", ")) : "";
requiresLabel.GetText = () => requiresString; requiresLabel.GetText = () => requiresString;
@@ -92,11 +93,10 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic
}; };
} }
static string ActorName(string a) static string ActorName(Ruleset rules, string a)
{ {
ActorInfo ai; ActorInfo ai;
Rules.Info.TryGetValue(a.ToLowerInvariant(), out ai); if (rules.Actors.TryGetValue(a.ToLowerInvariant(), out ai) && ai.Traits.Contains<TooltipInfo>())
if (ai != null && ai.Traits.Contains<TooltipInfo>())
return ai.Traits.Get<TooltipInfo>().Name; return ai.Traits.Get<TooltipInfo>().Name;
return a; return a;

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
@@ -72,9 +72,9 @@ namespace OpenRA.Mods.Cnc.Widgets
tooltipContainer = Exts.Lazy(() => tooltipContainer = Exts.Lazy(() =>
Ui.Root.Get<TooltipContainerWidget>(TooltipContainer)); Ui.Root.Get<TooltipContainerWidget>(TooltipContainer));
cantBuild = new Animation("clock"); cantBuild = new Animation(world, "clock");
cantBuild.PlayFetchIndex("idle", () => 0); cantBuild.PlayFetchIndex("idle", () => 0);
clock = new Animation("clock"); clock = new Animation(world, "clock");
} }
public override void Tick() public override void Tick()
@@ -114,7 +114,7 @@ namespace OpenRA.Mods.Cnc.Widgets
if (mi.Event != MouseInputEvent.Down) if (mi.Event != MouseInputEvent.Down)
return true; return true;
var actor = Rules.Info[icon.Name]; var actor = World.Map.Rules.Actors[icon.Name];
var first = icon.Queued.FirstOrDefault(); var first = icon.Queued.FirstOrDefault();
if (mi.Button == MouseButton.Left) if (mi.Button == MouseButton.Left)
@@ -135,7 +135,7 @@ namespace OpenRA.Mods.Cnc.Widgets
{ {
// Queue a new item // Queue a new item
Sound.Play(TabClick); Sound.Play(TabClick);
Sound.PlayNotification(World.LocalPlayer, "Speech", CurrentQueue.Info.QueuedAudio, World.LocalPlayer.Country.Race); Sound.PlayNotification(World.Map.Rules, World.LocalPlayer, "Speech", CurrentQueue.Info.QueuedAudio, World.LocalPlayer.Country.Race);
World.IssueOrder(Order.StartProduction(CurrentQueue.self, icon.Name, World.IssueOrder(Order.StartProduction(CurrentQueue.self, icon.Name,
Game.GetModifierKeys().HasModifier(Modifiers.Shift) ? 5 : 1)); Game.GetModifierKeys().HasModifier(Modifiers.Shift) ? 5 : 1));
} }
@@ -152,13 +152,13 @@ namespace OpenRA.Mods.Cnc.Widgets
// instant cancel of things we havent started yet and things that are finished // instant cancel of things we havent started yet and things that are finished
if (first.Paused || first.Done || first.TotalCost == first.RemainingCost) if (first.Paused || first.Done || first.TotalCost == first.RemainingCost)
{ {
Sound.PlayNotification(World.LocalPlayer, "Speech", CurrentQueue.Info.CancelledAudio, World.LocalPlayer.Country.Race); Sound.PlayNotification(World.Map.Rules, World.LocalPlayer, "Speech", CurrentQueue.Info.CancelledAudio, World.LocalPlayer.Country.Race);
World.IssueOrder(Order.CancelProduction(CurrentQueue.self, icon.Name, World.IssueOrder(Order.CancelProduction(CurrentQueue.self, icon.Name,
Game.GetModifierKeys().HasModifier(Modifiers.Shift) ? 5 : 1)); Game.GetModifierKeys().HasModifier(Modifiers.Shift) ? 5 : 1));
} }
else else
{ {
Sound.PlayNotification(World.LocalPlayer, "Speech", CurrentQueue.Info.OnHoldAudio, World.LocalPlayer.Country.Race); Sound.PlayNotification(World.Map.Rules, World.LocalPlayer, "Speech", CurrentQueue.Info.OnHoldAudio, World.LocalPlayer.Country.Race);
World.IssueOrder(Order.PauseProduction(CurrentQueue.self, icon.Name, true)); World.IssueOrder(Order.PauseProduction(CurrentQueue.self, icon.Name, true));
} }
} }
@@ -183,7 +183,7 @@ namespace OpenRA.Mods.Cnc.Widgets
var x = i % Columns; var x = i % Columns;
var y = i / Columns; var y = i / Columns;
var rect = new Rectangle(rb.X + x * 64 + 1, rb.Y + y * 48 + 1, 64, 48); var rect = new Rectangle(rb.X + x * 64 + 1, rb.Y + y * 48 + 1, 64, 48);
var icon = new Animation(RenderSimple.GetImage(item)); var icon = new Animation(World, RenderSimple.GetImage(item));
icon.Play(item.Traits.Get<TooltipInfo>().Icon); icon.Play(item.Traits.Get<TooltipInfo>().Icon);
var pi = new ProductionIcon() var pi = new ProductionIcon()
{ {

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
@@ -60,6 +60,8 @@ namespace OpenRA.Mods.Cnc.Widgets
class ProductionTabsWidget : Widget class ProductionTabsWidget : Widget
{ {
readonly World world;
public readonly string PaletteWidget = null; public readonly string PaletteWidget = null;
public readonly string TypesContainer = null; public readonly string TypesContainer = null;
@@ -79,7 +81,9 @@ namespace OpenRA.Mods.Cnc.Widgets
[ObjectCreator.UseCtor] [ObjectCreator.UseCtor]
public ProductionTabsWidget(World world) public ProductionTabsWidget(World world)
{ {
Groups = Rules.Info.Values.SelectMany(a => a.Traits.WithInterface<ProductionQueueInfo>()) this.world = world;
Groups = world.Map.Rules.Actors.Values.SelectMany(a => a.Traits.WithInterface<ProductionQueueInfo>())
.Select(q => q.Group).Distinct().ToDictionary(g => g, g => new ProductionTabGroup() { Group = g }); .Select(q => q.Group).Distinct().ToDictionary(g => g, g => new ProductionTabGroup() { Group = g });
// Only visible if the production palette has icons to display // Only visible if the production palette has icons to display
@@ -93,7 +97,7 @@ namespace OpenRA.Mods.Cnc.Widgets
if (queueGroup == null) if (queueGroup == null)
return true; return true;
Sound.PlayNotification(null, "Sounds", "ClickSound", null); Sound.PlayNotification(world.Map.Rules, null, "Sounds", "ClickSound", null);
// Prioritize alerted queues // Prioritize alerted queues
var queues = Groups[queueGroup].Tabs.Select(t => t.Queue) var queues = Groups[queueGroup].Tabs.Select(t => t.Queue)
@@ -253,9 +257,9 @@ namespace OpenRA.Mods.Cnc.Widgets
if (leftPressed || rightPressed) if (leftPressed || rightPressed)
{ {
if ((leftPressed && !leftDisabled) || (rightPressed && !rightDisabled)) if ((leftPressed && !leftDisabled) || (rightPressed && !rightDisabled))
Sound.PlayNotification(null, "Sounds", "ClickSound", null); Sound.PlayNotification(world.Map.Rules, null, "Sounds", "ClickSound", null);
else else
Sound.PlayNotification(null, "Sounds", "ClickDisabledSound", null); Sound.PlayNotification(world.Map.Rules, null, "Sounds", "ClickDisabledSound", null);
} }
// Check production tabs // Check production tabs
@@ -263,7 +267,7 @@ namespace OpenRA.Mods.Cnc.Widgets
if (offsetloc.X > 0 && offsetloc.X < contentWidth) if (offsetloc.X > 0 && offsetloc.X < contentWidth)
{ {
CurrentQueue = Groups[queueGroup].Tabs[offsetloc.X / (TabWidth - 1)].Queue; CurrentQueue = Groups[queueGroup].Tabs[offsetloc.X / (TabWidth - 1)].Queue;
Sound.PlayNotification(null, "Sounds", "ClickSound", null); Sound.PlayNotification(world.Map.Rules, null, "Sounds", "ClickSound", null);
} }
return true; return true;

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
@@ -16,7 +16,10 @@ namespace OpenRA.Mods.Cnc.Widgets
{ {
public readonly string ProductionGroup; public readonly string ProductionGroup;
public ProductionTypeButtonWidget() { } [ObjectCreator.UseCtor]
public ProductionTypeButtonWidget(Ruleset modRules)
: base(modRules) { }
protected ProductionTypeButtonWidget(ProductionTypeButtonWidget other) protected ProductionTypeButtonWidget(ProductionTypeButtonWidget other)
: base(other) : base(other)
{ {

View File

@@ -52,8 +52,8 @@ namespace OpenRA.Mods.Cnc.Widgets
tooltipContainer = Exts.Lazy(() => tooltipContainer = Exts.Lazy(() =>
Ui.Root.Get<TooltipContainerWidget>(TooltipContainer)); Ui.Root.Get<TooltipContainerWidget>(TooltipContainer));
icon = new Animation("icon"); icon = new Animation(world, "icon");
clock = new Animation("clock"); clock = new Animation(world, "clock");
} }
public class SupportPowerIcon public class SupportPowerIcon

View File

@@ -23,7 +23,7 @@ namespace OpenRA.Mods.Cnc
public WithFire(Actor self, WithFireInfo info) public WithFire(Actor self, WithFireInfo info)
{ {
var rs = self.Trait<RenderSprites>(); var rs = self.Trait<RenderSprites>();
var roof = new Animation(rs.GetImage(self)); var roof = new Animation(self.World, rs.GetImage(self));
roof.PlayThen("fire-start", () => roof.PlayRepeating("fire-loop")); roof.PlayThen("fire-start", () => roof.PlayRepeating("fire-loop"));
rs.anims.Add("fire", new AnimationWithOffset(roof, null, null, 1024)); rs.anims.Add("fire", new AnimationWithOffset(roof, null, null, 1024));
} }

View File

@@ -23,7 +23,7 @@ namespace OpenRA.Mods.Cnc
public WithRoof(Actor self) public WithRoof(Actor self)
{ {
var rs = self.Trait<RenderSprites>(); var rs = self.Trait<RenderSprites>();
var roof = new Animation(rs.GetImage(self), () => self.Trait<IFacing>().Facing); var roof = new Animation(self.World, rs.GetImage(self), () => self.Trait<IFacing>().Facing);
roof.Play("roof"); roof.Play("roof");
rs.anims.Add("roof", new AnimationWithOffset(roof, null, null, 1024)); rs.anims.Add("roof", new AnimationWithOffset(roof, null, null, 1024));
} }

View File

@@ -39,7 +39,7 @@ namespace OpenRA.Mods.Cnc
{ {
this.info = info; this.info = info;
health = self.Trait<Health>(); health = self.Trait<Health>();
weapon = Rules.Weapons[info.Weapon.ToLowerInvariant()]; weapon = self.World.Map.Rules.Weapons[info.Weapon.ToLowerInvariant()];
} }
public void AddedToWorld(Actor self) public void AddedToWorld(Actor self)

View File

@@ -38,7 +38,7 @@ namespace OpenRA.Mods.RA.Render
buildComplete = !self.HasTrait<Building>(); // always render instantly for units buildComplete = !self.HasTrait<Building>(); // always render instantly for units
overlay = new Animation(rs.GetImage(self)); overlay = new Animation(self.World, rs.GetImage(self));
overlay.Play(info.Sequence); overlay.Play(info.Sequence);
rs.anims.Add("crane_overlay_{0}".F(info.Sequence), rs.anims.Add("crane_overlay_{0}".F(info.Sequence),
new AnimationWithOffset(overlay, new AnimationWithOffset(overlay,

View File

@@ -32,7 +32,7 @@ namespace OpenRA.Mods.RA.Render
if (!init.Contains<SkipMakeAnimsInit>()) if (!init.Contains<SkipMakeAnimsInit>())
{ {
var overlay = new Animation(rs.GetImage(init.self)); var overlay = new Animation(init.world, rs.GetImage(init.self));
overlay.PlayThen(info.Sequence, () => buildComplete = false); overlay.PlayThen(info.Sequence, () => buildComplete = false);
rs.anims.Add("make_overlay_{0}".F(info.Sequence), rs.anims.Add("make_overlay_{0}".F(info.Sequence),
new AnimationWithOffset(overlay, null, () => !buildComplete)); new AnimationWithOffset(overlay, null, () => !buildComplete));

View File

@@ -42,7 +42,7 @@ namespace OpenRA.Mods.RA.Render
buildComplete = !self.HasTrait<Building>(); // always render instantly for units buildComplete = !self.HasTrait<Building>(); // always render instantly for units
overlay = new Animation(rs.GetImage(self)); overlay = new Animation(self.World, rs.GetImage(self));
overlay.Play(info.Sequence); overlay.Play(info.Sequence);
rs.anims.Add("docking_overlay_{0}".F(info.Sequence), rs.anims.Add("docking_overlay_{0}".F(info.Sequence),
new AnimationWithOffset(overlay, new AnimationWithOffset(overlay,

View File

@@ -47,7 +47,7 @@ namespace OpenRA.Mods.RA.Render
buildComplete = !self.HasTrait<Building>(); // always render instantly for units buildComplete = !self.HasTrait<Building>(); // always render instantly for units
overlay = new Animation(rs.GetImage(self)); overlay = new Animation(self.World, rs.GetImage(self));
overlay.PlayRepeating(info.Sequence); overlay.PlayRepeating(info.Sequence);
rs.anims.Add("production_overlay_{0}".F(info.Sequence), rs.anims.Add("production_overlay_{0}".F(info.Sequence),
new AnimationWithOffset(overlay, new AnimationWithOffset(overlay,

View File

@@ -40,7 +40,7 @@ namespace OpenRA.Mods.D2k
{ {
foreach (var name in info.Weapons) foreach (var name in info.Weapons)
{ {
var wep = Rules.Weapons[name]; var wep = self.World.Map.Rules.Weapons[name];
var pieces = self.World.SharedRandom.Next(info.Pieces[0], info.Pieces[1]); var pieces = self.World.SharedRandom.Next(info.Pieces[0], info.Pieces[1]);
var range = self.World.SharedRandom.Next(info.Range[0].Range, info.Range[1].Range); var range = self.World.SharedRandom.Next(info.Range[0].Range, info.Range[1].Range);

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS) * Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
@@ -68,9 +68,9 @@ namespace OpenRA.Mods.RA.AI
// Place the building // Place the building
var type = BuildingType.Building; var type = BuildingType.Building;
if (Rules.Info[currentBuilding.Item].Traits.Contains<AttackBaseInfo>()) if (ai.Map.Rules.Actors[currentBuilding.Item].Traits.Contains<AttackBaseInfo>())
type = BuildingType.Defense; type = BuildingType.Defense;
else if (Rules.Info[currentBuilding.Item].Traits.Contains<OreRefineryInfo>()) else if (ai.Map.Rules.Actors[currentBuilding.Item].Traits.Contains<OreRefineryInfo>())
type = BuildingType.Refinery; type = BuildingType.Refinery;
var location = ai.ChooseBuildLocation(currentBuilding.Item, type); var location = ai.ChooseBuildLocation(currentBuilding.Item, type);

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS) * Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
@@ -83,7 +83,7 @@ namespace OpenRA.Mods.RA.AI
static object LoadBuildingLimits(MiniYaml y) { return LoadList<int>(y, "BuildingLimits"); } static object LoadBuildingLimits(MiniYaml y) { return LoadList<int>(y, "BuildingLimits"); }
public object Create(ActorInitializer init) { return new HackyAI(this); } public object Create(ActorInitializer init) { return new HackyAI(this, init); }
} }
public class Enemy { public int Aggro; } public class Enemy { public int Aggro; }
@@ -119,15 +119,17 @@ namespace OpenRA.Mods.RA.AI
const int MaxBaseDistance = 40; const int MaxBaseDistance = 40;
public const int feedbackTime = 30; // ticks; = a bit over 1s. must be >= netlag. public const int feedbackTime = 30; // ticks; = a bit over 1s. must be >= netlag.
public World world { get { return p.PlayerActor.World; } } public readonly World world;
public Map Map { get { return world.Map; } }
IBotInfo IBot.Info { get { return this.Info; } } IBotInfo IBot.Info { get { return this.Info; } }
public HackyAI(HackyAIInfo info) public HackyAI(HackyAIInfo info, ActorInitializer init)
{ {
Info = info; Info = info;
world = init.world;
// Temporary hack. // Temporary hack.
rallypointTestBuilding = Rules.Info[Info.RallypointTestBuilding].Traits.Get<BuildingInfo>(); rallypointTestBuilding = Map.Rules.Actors[Info.RallypointTestBuilding].Traits.Get<BuildingInfo>();
} }
public static void BotDebug(string s, params object[] args) public static void BotDebug(string s, params object[] args)
@@ -151,7 +153,7 @@ namespace OpenRA.Mods.RA.AI
random = new XRandom((int)p.PlayerActor.ActorID); random = new XRandom((int)p.PlayerActor.ActorID);
resourceTypes = Rules.Info["world"].Traits.WithInterface<ResourceTypeInfo>() resourceTypes = Map.Rules.Actors["world"].Traits.WithInterface<ResourceTypeInfo>()
.Select(t => t.TerrainType).ToArray(); .Select(t => t.TerrainType).ToArray();
} }
@@ -185,8 +187,8 @@ namespace OpenRA.Mods.RA.AI
foreach (var unit in Info.UnitsToBuild) foreach (var unit in Info.UnitsToBuild)
if (buildableThings.Any(b => b.Name == unit.Key)) if (buildableThings.Any(b => b.Name == unit.Key))
if (myUnits.Count(a => a == unit.Key) < unit.Value * myUnits.Length) if (myUnits.Count(a => a == unit.Key) < unit.Value * myUnits.Length)
if (HasAdequateAirUnits(Rules.Info[unit.Key])) if (HasAdequateAirUnits(Map.Rules.Actors[unit.Key]))
return Rules.Info[unit.Key]; return Map.Rules.Actors[unit.Key];
return null; return null;
} }
@@ -215,7 +217,7 @@ namespace OpenRA.Mods.RA.AI
ActorInfo GetBuildingInfoByCommonName(string commonName, Player owner) ActorInfo GetBuildingInfoByCommonName(string commonName, Player owner)
{ {
if (commonName == "ConstructionYard") if (commonName == "ConstructionYard")
return Rules.Info.Where(k => Info.BuildingCommonNames[commonName].Contains(k.Key)).Random(random).Value; return Map.Rules.Actors.Where(k => Info.BuildingCommonNames[commonName].Contains(k.Key)).Random(random).Value;
return GetInfoByCommonName(Info.BuildingCommonNames, commonName, owner); return GetInfoByCommonName(Info.BuildingCommonNames, commonName, owner);
} }
@@ -230,7 +232,7 @@ namespace OpenRA.Mods.RA.AI
if (!names.Any() || !names.ContainsKey(commonName)) if (!names.Any() || !names.ContainsKey(commonName))
return null; return null;
return Rules.Info.Where(k => names[commonName].Contains(k.Key) && return Map.Rules.Actors.Where(k => names[commonName].Contains(k.Key) &&
k.Value.Traits.Get<BuildableInfo>().Owner.Contains(owner.Country.Race)).Random(random).Value; k.Value.Traits.Get<BuildableInfo>().Owner.Contains(owner.Country.Race)).Random(random).Value;
} }
@@ -314,8 +316,8 @@ namespace OpenRA.Mods.RA.AI
foreach (var frac in Info.BuildingFractions) foreach (var frac in Info.BuildingFractions)
if (buildableThings.Any(b => b.Name == frac.Key)) if (buildableThings.Any(b => b.Name == frac.Key))
if (myBuildings.Count(a => a == frac.Key) < frac.Value * myBuildings.Length && HasAdequateNumber(frac.Key, p) && if (myBuildings.Count(a => a == frac.Key) < frac.Value * myBuildings.Length && HasAdequateNumber(frac.Key, p) &&
playerPower.ExcessPower >= Rules.Info[frac.Key].Traits.Get<BuildingInfo>().Power) playerPower.ExcessPower >= Map.Rules.Actors[frac.Key].Traits.Get<BuildingInfo>().Power)
return Rules.Info[frac.Key]; return Map.Rules.Actors[frac.Key];
return null; return null;
} }
@@ -334,7 +336,7 @@ namespace OpenRA.Mods.RA.AI
public CPos? ChooseBuildLocation(string actorType, bool distanceToBaseIsImportant, int maxBaseDistance, BuildingType type) public CPos? ChooseBuildLocation(string actorType, bool distanceToBaseIsImportant, int maxBaseDistance, BuildingType type)
{ {
var bi = Rules.Info[actorType].Traits.GetOrDefault<BuildingInfo>(); var bi = Map.Rules.Actors[actorType].Traits.GetOrDefault<BuildingInfo>();
if (bi == null) if (bi == null)
return null; return null;
@@ -348,7 +350,7 @@ namespace OpenRA.Mods.RA.AI
foreach (var t in tlist) foreach (var t in tlist)
if (world.CanPlaceBuilding(actorType, bi, t, null)) if (world.CanPlaceBuilding(actorType, bi, t, null))
if (bi.IsCloseEnoughToBase(world, p, actorType, t)) if (bi.IsCloseEnoughToBase(world, p, actorType, t))
if (NoBuildingsUnder(Util.ExpandFootprint(FootprintUtils.Tiles(actorType, bi, t), false))) if (NoBuildingsUnder(Util.ExpandFootprint(FootprintUtils.Tiles(Map.Rules, actorType, bi, t), false)))
return t; return t;
} }
@@ -377,7 +379,7 @@ namespace OpenRA.Mods.RA.AI
if (distanceToBaseIsImportant && !bi.IsCloseEnoughToBase(world, p, actorType, t)) if (distanceToBaseIsImportant && !bi.IsCloseEnoughToBase(world, p, actorType, t))
continue; continue;
if (NoBuildingsUnder(Util.ExpandFootprint(FootprintUtils.Tiles(actorType, bi, t), false))) if (NoBuildingsUnder(Util.ExpandFootprint(FootprintUtils.Tiles(Map.Rules, actorType, bi, t), false)))
return t; return t;
} }
} }
@@ -850,7 +852,7 @@ namespace OpenRA.Mods.RA.AI
if (queue == null) if (queue == null)
return; return;
if (Rules.Info[name] != null) if (Map.Rules.Actors[name] != null)
world.IssueOrder(Order.StartProduction(queue.self, name, 1)); world.IssueOrder(Order.StartProduction(queue.self, name, 1));
} }

View File

@@ -31,7 +31,7 @@ namespace OpenRA.Mods.RA
public void Killed(Actor self, AttackInfo e) public void Killed(Actor self, AttackInfo e)
{ {
var player = (info.NotifyAll) ? self.World.LocalPlayer : self.Owner; var player = (info.NotifyAll) ? self.World.LocalPlayer : self.Owner;
Sound.PlayNotification(player, "Speech", info.Notification, self.Owner.Country.Race); Sound.PlayNotification(self.World.Map.Rules, player, "Speech", info.Notification, self.Owner.Country.Race);
} }
} }
} }

View File

@@ -82,7 +82,7 @@ namespace OpenRA.Mods.RA
Coords = Exts.Lazy(() => self.Trait<IBodyOrientation>()); Coords = Exts.Lazy(() => self.Trait<IBodyOrientation>());
limitedAmmo = Exts.Lazy(() => self.TraitOrDefault<LimitedAmmo>()); limitedAmmo = Exts.Lazy(() => self.TraitOrDefault<LimitedAmmo>());
Weapon = Rules.Weapons[info.Weapon.ToLowerInvariant()]; Weapon = self.World.Map.Rules.Weapons[info.Weapon.ToLowerInvariant()];
Burst = Weapon.Burst; Burst = Weapon.Burst;
if (info.LocalOffset.Length % 3 != 0) if (info.LocalOffset.Length % 3 != 0)

View File

@@ -157,7 +157,7 @@ namespace OpenRA.Mods.RA
if (barrel != null && a.Info.MuzzleSequence != null) if (barrel != null && a.Info.MuzzleSequence != null)
{ {
// Muzzle facing is fixed once the firing starts // Muzzle facing is fixed once the firing starts
var muzzleAnim = new Animation(paxRender[a.Actor].GetImage(a.Actor), () => muzzleFacing); var muzzleAnim = new Animation(self.World, paxRender[a.Actor].GetImage(a.Actor), () => muzzleFacing);
var sequence = a.Info.MuzzleSequence; var sequence = a.Info.MuzzleSequence;
if (a.Info.MuzzleSplitFacings > 0) if (a.Info.MuzzleSplitFacings > 0)

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
@@ -44,7 +44,7 @@ namespace OpenRA.Mods.RA
// Build a list of templates that should be overlayed with bridges // Build a list of templates that should be overlayed with bridges
foreach(var bridge in Info.Bridges) foreach(var bridge in Info.Bridges)
{ {
var bi = Rules.Info[bridge].Traits.Get<BridgeInfo>(); var bi = w.Map.Rules.Actors[bridge].Traits.Get<BridgeInfo>();
foreach (var template in bi.Templates) foreach (var template in bi.Templates)
BridgeTypes.Add(template.First, Pair.New(bridge, template.Second)); BridgeTypes.Add(template.First, Pair.New(bridge, template.Second));
} }

View File

@@ -51,7 +51,7 @@ namespace OpenRA.Mods.RA.Buildings
for (var i = 0; i < rows * width; i++) for (var i = 0; i < rows * width; i++)
{ {
var index = i; var index = i;
var anim = new Animation(rs.GetImage(self)); var anim = new Animation(self.World, rs.GetImage(self));
var cellOffset = new CVec(i % width, i / width + bibOffset); var cellOffset = new CVec(i % width, i / width + bibOffset);
// Some mods may define terrain-specific bibs // Some mods may define terrain-specific bibs

6
OpenRA.Mods.RA/Buildings/Building.cs Executable file → Normal file
View File

@@ -1,6 +1,6 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
@@ -65,7 +65,7 @@ namespace OpenRA.Mods.RA.Buildings
return false; return false;
var buildingMaxBounds = (CVec)Dimensions; var buildingMaxBounds = (CVec)Dimensions;
var buildingTraits = Rules.Info[buildingName].Traits; var buildingTraits = world.Map.Rules.Actors[buildingName].Traits;
if (buildingTraits.Contains<BibInfo>() && !(buildingTraits.Get<BibInfo>().HasMinibib)) if (buildingTraits.Contains<BibInfo>() && !(buildingTraits.Get<BibInfo>().HasMinibib))
buildingMaxBounds += new CVec(0, 1); buildingMaxBounds += new CVec(0, 1);
@@ -91,7 +91,7 @@ namespace OpenRA.Mods.RA.Buildings
} }
} }
var buildingTiles = FootprintUtils.Tiles(buildingName, this, topLeft).ToList(); var buildingTiles = FootprintUtils.Tiles(world.Map.Rules, buildingName, this, topLeft).ToList();
return nearnessCandidates return nearnessCandidates
.Any(a => buildingTiles .Any(a => buildingTiles
.Any(b => Math.Abs(a.X - b.X) <= Adjacent .Any(b => Math.Abs(a.X - b.X) <= Adjacent

View File

@@ -34,7 +34,7 @@ namespace OpenRA.Mods.RA.Buildings
if (b == null) if (b == null)
return; return;
foreach (var u in FootprintUtils.Tiles(a.Info.Name, b.Info, a.Location)) foreach (var u in FootprintUtils.Tiles(map.Rules, a.Info.Name, b.Info, a.Location))
if (map.IsInMap(u) && influence[u.X, u.Y] == null) if (map.IsInMap(u) && influence[u.X, u.Y] == null)
influence[u.X, u.Y] = a; influence[u.X, u.Y] = a;
}; };
@@ -45,7 +45,7 @@ namespace OpenRA.Mods.RA.Buildings
if (b == null) if (b == null)
return; return;
foreach (var u in FootprintUtils.Tiles(a.Info.Name, b.Info, a.Location)) foreach (var u in FootprintUtils.Tiles(map.Rules, a.Info.Name, b.Info, a.Location))
if (map.IsInMap(u) && influence[u.X, u.Y] == a) if (map.IsInMap(u) && influence[u.X, u.Y] == a)
influence[u.X, u.Y] = null; influence[u.X, u.Y] = null;
}; };

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
@@ -37,7 +37,7 @@ namespace OpenRA.Mods.RA.Buildings
if (order.OrderString == "PowerDown") if (order.OrderString == "PowerDown")
{ {
disabled = !disabled; disabled = !disabled;
Sound.PlayNotification(self.Owner, "Sounds", (disabled ? "EnablePower" : "DisablePower"), self.Owner.Country.Race); Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Sounds", (disabled ? "EnablePower" : "DisablePower"), self.Owner.Country.Race);
PowerManager.UpdateActor(self, disabled ? 0 : normalPower); PowerManager.UpdateActor(self, disabled ? 0 : normalPower);
if (disabled) if (disabled)

8
OpenRA.Mods.RA/Buildings/FootprintUtils.cs Executable file → Normal file
View File

@@ -1,6 +1,6 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
@@ -16,13 +16,13 @@ namespace OpenRA.Mods.RA.Buildings
{ {
public static class FootprintUtils public static class FootprintUtils
{ {
public static IEnumerable<CPos> Tiles(string name, BuildingInfo buildingInfo, CPos topLeft) public static IEnumerable<CPos> Tiles(Ruleset rules, string name, BuildingInfo buildingInfo, CPos topLeft)
{ {
var dim = (CVec)buildingInfo.Dimensions; var dim = (CVec)buildingInfo.Dimensions;
var footprint = buildingInfo.Footprint.Where(x => !char.IsWhiteSpace(x)); var footprint = buildingInfo.Footprint.Where(x => !char.IsWhiteSpace(x));
var buildingTraits = Rules.Info[name].Traits; var buildingTraits = rules.Actors[name].Traits;
if (buildingTraits.Contains<BibInfo>() && !(buildingTraits.Get<BibInfo>().HasMinibib)) if (buildingTraits.Contains<BibInfo>() && !(buildingTraits.Get<BibInfo>().HasMinibib))
{ {
dim += new CVec(0, 1); dim += new CVec(0, 1);
@@ -34,7 +34,7 @@ namespace OpenRA.Mods.RA.Buildings
public static IEnumerable<CPos> Tiles(Actor a) public static IEnumerable<CPos> Tiles(Actor a)
{ {
return Tiles( a.Info.Name, a.Info.Traits.Get<BuildingInfo>(), a.Location ); return Tiles(a.World.Map.Rules, a.Info.Name, a.Info.Traits.Get<BuildingInfo>(), a.Location);
} }
public static IEnumerable<CPos> UnpathableTiles(string name, BuildingInfo buildingInfo, CPos position) public static IEnumerable<CPos> UnpathableTiles(string name, BuildingInfo buildingInfo, CPos position)

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2012 The OpenRA Developers (see AUTHORS) * Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
@@ -108,7 +108,7 @@ namespace OpenRA.Mods.RA.Buildings
if (--nextPowerAdviceTime <= 0) if (--nextPowerAdviceTime <= 0)
{ {
if (lowPower) if (lowPower)
Sound.PlayNotification(self.Owner, "Speech", "LowPower", self.Owner.Country.Race); Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", "LowPower", self.Owner.Country.Race);
nextPowerAdviceTime = Info.AdviceInterval; nextPowerAdviceTime = Info.AdviceInterval;
} }
} }

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
@@ -51,7 +51,7 @@ namespace OpenRA.Mods.RA.Buildings
else else
{ {
Repairer = p; Repairer = p;
Sound.PlayNotification(Repairer, "Speech", "Repairing", self.Owner.Country.Race); Sound.PlayNotification(self.World.Map.Rules, Repairer, "Speech", "Repairing", self.Owner.Country.Race);
self.World.AddFrameEndTask( self.World.AddFrameEndTask(
w => w.Add(new RepairIndicator(self, Info.IndicatorPalettePrefix, p))); w => w.Add(new RepairIndicator(self, Info.IndicatorPalettePrefix, p)));

6
OpenRA.Mods.RA/Buildings/Util.cs Executable file → Normal file
View File

@@ -1,6 +1,6 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
@@ -35,14 +35,14 @@ namespace OpenRA.Mods.RA.Buildings
return true; return true;
var res = world.WorldActor.Trait<ResourceLayer>(); var res = world.WorldActor.Trait<ResourceLayer>();
return FootprintUtils.Tiles(name, building, topLeft).All( return FootprintUtils.Tiles(world.Map.Rules, name, building, topLeft).All(
t => world.Map.IsInMap(t.X, t.Y) && res.GetResource(t) == null && t => world.Map.IsInMap(t.X, t.Y) && res.GetResource(t) == null &&
world.IsCellBuildable(t, building, toIgnore)); world.IsCellBuildable(t, building, toIgnore));
} }
public static IEnumerable<CPos> GetLineBuildCells(World world, CPos location, string name, BuildingInfo bi) public static IEnumerable<CPos> GetLineBuildCells(World world, CPos location, string name, BuildingInfo bi)
{ {
var lbi = Rules.Info[name].Traits.Get<LineBuildInfo>(); var lbi = world.Map.Rules.Actors[name].Traits.Get<LineBuildInfo>();
var topLeft = location; // 1x1 assumption! var topLeft = location; // 1x1 assumption!
if (world.IsCellBuildable(topLeft, bi)) if (world.IsCellBuildable(topLeft, bi))

View File

@@ -31,7 +31,7 @@ namespace OpenRA.Mods.RA
{ {
Info = info; Info = info;
var anim = new Animation("fire", () => 0); var anim = new Animation(self.World, "fire", () => 0);
anim.IsDecoration = true; anim.IsDecoration = true;
anim.PlayRepeating(Info.Anim); anim.PlayRepeating(Info.Anim);
self.Trait<RenderSprites>().anims.Add("fire", anim); self.Trait<RenderSprites>().anims.Add("fire", anim);

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS) * Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
@@ -34,7 +34,7 @@ namespace OpenRA.Mods.RA
return; return;
var race = info.NewOwnerVoice ? newOwner.Country.Race : oldOwner.Country.Race; var race = info.NewOwnerVoice ? newOwner.Country.Race : oldOwner.Country.Race;
Sound.PlayNotification(captor.World.LocalPlayer, "Speech", info.Notification, race); Sound.PlayNotification(self.World.Map.Rules, captor.World.LocalPlayer, "Speech", info.Notification, race);
} }
} }
} }

View File

@@ -158,7 +158,7 @@ namespace OpenRA.Mods.RA
public static void DoExplosion(Actor attacker, string weapontype, WPos pos) public static void DoExplosion(Actor attacker, string weapontype, WPos pos)
{ {
var weapon = Rules.Weapons[weapontype.ToLowerInvariant()]; var weapon = attacker.World.Map.Rules.Weapons[weapontype.ToLowerInvariant()];
if (weapon.Report != null && weapon.Report.Any()) if (weapon.Report != null && weapon.Report.Any())
Sound.Play(weapon.Report.Random(attacker.World.SharedRandom), pos); Sound.Play(weapon.Report.Random(attacker.World.SharedRandom), pos);

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
@@ -70,7 +70,7 @@ namespace OpenRA.Mods.RA
Game.RunAfterDelay(Info.NotificationDelay, () => Game.RunAfterDelay(Info.NotificationDelay, () =>
{ {
if (Game.IsCurrentWorld(self.World)) if (Game.IsCurrentWorld(self.World))
Sound.PlayNotification(self.Owner, "Speech", "Lose", self.Owner.Country.Race); Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", "Lose", self.Owner.Country.Race);
}); });
} }
@@ -81,7 +81,7 @@ namespace OpenRA.Mods.RA
Game.Debug("{0} is victorious.".F(self.Owner.PlayerName)); Game.Debug("{0} is victorious.".F(self.Owner.PlayerName));
if (self.Owner == self.World.LocalPlayer) if (self.Owner == self.World.LocalPlayer)
Game.RunAfterDelay(Info.NotificationDelay, () => Sound.PlayNotification(self.Owner, "Speech", "Win", self.Owner.Country.Race)); Game.RunAfterDelay(Info.NotificationDelay, () => Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", "Win", self.Owner.Country.Race));
} }
} }

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
@@ -90,7 +90,7 @@ namespace OpenRA.Mods.RA
{ {
var crate = w.CreateActor(false, crateActor, new TypeDictionary { new OwnerInit(w.WorldActor.Owner) }); var crate = w.CreateActor(false, crateActor, new TypeDictionary { new OwnerInit(w.WorldActor.Owner) });
var startPos = w.ChooseRandomEdgeCell(); var startPos = w.ChooseRandomEdgeCell();
var altitude = Rules.Info[info.DeliveryAircraft].Traits.Get<PlaneInfo>().CruiseAltitude; var altitude = self.World.Map.Rules.Actors[info.DeliveryAircraft].Traits.Get<PlaneInfo>().CruiseAltitude;
var plane = w.CreateActor(info.DeliveryAircraft, new TypeDictionary var plane = w.CreateActor(info.DeliveryAircraft, new TypeDictionary
{ {
new CenterPositionInit(startPos.CenterPosition + new WVec(WRange.Zero, WRange.Zero, altitude)), new CenterPositionInit(startPos.CenterPosition + new WVec(WRange.Zero, WRange.Zero, altitude)),

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
@@ -34,7 +34,7 @@ namespace OpenRA.Mods.RA.Crates
public bool CanGiveTo(Actor collector) public bool CanGiveTo(Actor collector)
{ {
var bi = Rules.Info[Info.Unit].Traits.GetOrDefault<BuildableInfo>(); var bi = self.World.Map.Rules.Actors[Info.Unit].Traits.GetOrDefault<BuildableInfo>();
// this unit is not buildable by the collector's country, so // this unit is not buildable by the collector's country, so
// don't give them free ones either. // don't give them free ones either.
@@ -68,7 +68,7 @@ namespace OpenRA.Mods.RA.Crates
IEnumerable<CPos> GetSuitableCells(CPos near) IEnumerable<CPos> GetSuitableCells(CPos near)
{ {
var mi = Rules.Info[Info.Unit].Traits.Get<MobileInfo>(); var mi = self.World.Map.Rules.Actors[Info.Unit].Traits.Get<MobileInfo>();
for (var i = -1; i < 2; i++) for (var i = -1; i < 2; i++)
for (var j = -1; j < 2; j++) for (var j = -1; j < 2; j++)

View File

@@ -21,8 +21,8 @@ namespace OpenRA.Mods.RA.Effects
readonly WPos position; readonly WPos position;
readonly string palettePrefix; readonly string palettePrefix;
readonly string posterPalette; readonly string posterPalette;
readonly Animation arrow = new Animation("beacon"); readonly Animation arrow;
readonly Animation circles = new Animation("beacon"); readonly Animation circles;
readonly Animation poster; readonly Animation poster;
static readonly int maxArrowHeight = 512; static readonly int maxArrowHeight = 512;
int arrowHeight = maxArrowHeight; int arrowHeight = maxArrowHeight;
@@ -35,12 +35,15 @@ namespace OpenRA.Mods.RA.Effects
this.palettePrefix = palettePrefix; this.palettePrefix = palettePrefix;
this.posterPalette = posterPalette; this.posterPalette = posterPalette;
arrow = new Animation(owner.World, "beacon");
circles = new Animation(owner.World, "beacon");
arrow.Play("arrow"); arrow.Play("arrow");
circles.Play("circles"); circles.Play("circles");
if (posterType != null) if (posterType != null)
{ {
poster = new Animation("beacon"); poster = new Animation(owner.World, "beacon");
poster.Play(posterType); poster.Play(posterType);
} }

View File

@@ -66,6 +66,8 @@ namespace OpenRA.Mods.RA.Effects
this.args = args; this.args = args;
this.pos = args.Source; this.pos = args.Source;
var world = args.SourceActor.World;
if (info.Angle.Length > 1 && info.Speed.Length > 1) if (info.Angle.Length > 1 && info.Speed.Length > 1)
{ {
angle = new WAngle(args.SourceActor.World.SharedRandom.Next(info.Angle[0].Angle, info.Angle[1].Angle)); angle = new WAngle(args.SourceActor.World.SharedRandom.Next(info.Angle[0].Angle, info.Angle[1].Angle));
@@ -89,7 +91,7 @@ namespace OpenRA.Mods.RA.Effects
if (info.Image != null) if (info.Image != null)
{ {
anim = new Animation(info.Image, GetEffectiveFacing); anim = new Animation(world, info.Image, GetEffectiveFacing);
anim.PlayRepeating("idle"); anim.PlayRepeating("idle");
} }

View File

@@ -28,7 +28,7 @@ namespace OpenRA.Mods.RA.Effects
this.pos = pos; this.pos = pos;
this.cell = pos.ToCPos(); this.cell = pos.ToCPos();
this.paletteName = paletteName; this.paletteName = paletteName;
anim = new Animation(image); anim = new Animation(world, image);
anim.PlayThen(sequence, () => world.AddFrameEndTask(w => w.Remove(this))); anim.PlayThen(sequence, () => world.AddFrameEndTask(w => w.Remove(this)));
} }

View File

@@ -17,13 +17,15 @@ namespace OpenRA.Mods.RA.Effects
class CrateEffect : IEffect class CrateEffect : IEffect
{ {
readonly string palette; readonly string palette;
Actor a; readonly Actor a;
Animation anim = new Animation("crate-effects"); readonly Animation anim;
public CrateEffect(Actor a, string seq, string palette) public CrateEffect(Actor a, string seq, string palette)
{ {
this.a = a; this.a = a;
this.palette = palette; this.palette = palette;
anim = new Animation(a.World, "crate-effects");
anim.PlayThen(seq, () => a.World.AddFrameEndTask(w => w.Remove(this))); anim.PlayThen(seq, () => a.World.AddFrameEndTask(w => w.Remove(this)));
} }

View File

@@ -28,7 +28,7 @@ namespace OpenRA.Mods.RA.Effects
this.pos = pos; this.pos = pos;
this.cell = pos.ToCPos(); this.cell = pos.ToCPos();
this.palette = palette; this.palette = palette;
anim = new Animation("explosion"); anim = new Animation(world, "explosion");
anim.PlayThen(sequence, () => world.AddFrameEndTask(w => w.Remove(this))); anim.PlayThen(sequence, () => world.AddFrameEndTask(w => w.Remove(this)));
} }

View File

@@ -47,7 +47,7 @@ namespace OpenRA.Mods.RA.Effects
{ {
this.self = self; this.self = self;
this.info = info; this.info = info;
anim = new Animation("gpsdot"); anim = new Animation(self.World, "gpsdot");
anim.PlayRepeating(info.String); anim.PlayRepeating(info.String);
self.World.AddFrameEndTask(w => w.Add(this)); self.World.AddFrameEndTask(w => w.Add(this));

View File

@@ -16,27 +16,29 @@ namespace OpenRA.Mods.RA.Effects
{ {
class GpsSatellite : IEffect class GpsSatellite : IEffect
{ {
WPos Pos; WPos pos;
Animation Anim = new Animation("sputnik"); readonly Animation anim;
public GpsSatellite(WPos pos) public GpsSatellite(World world, WPos pos)
{ {
Pos = pos; this.pos = pos;
Anim.PlayRepeating("idle");
anim = new Animation(world, "sputnik");
anim.PlayRepeating("idle");
} }
public void Tick( World world ) public void Tick( World world )
{ {
Anim.Tick(); anim.Tick();
Pos += new WVec(0, 0, 427); pos += new WVec(0, 0, 427);
if (Pos.Z > Pos.Y) if (pos.Z > pos.Y)
world.AddFrameEndTask(w => w.Remove(this)); world.AddFrameEndTask(w => w.Remove(this));
} }
public IEnumerable<IRenderable> Render(WorldRenderer wr) public IEnumerable<IRenderable> Render(WorldRenderer wr)
{ {
return Anim.Render(Pos, wr.Palette("effect")); return anim.Render(pos, wr.Palette("effect"));
} }
} }
} }

View File

@@ -40,7 +40,7 @@ namespace OpenRA.Mods.RA.Effects
pos = args.Source; pos = args.Source;
velocity = new WVec(WRange.Zero, WRange.Zero, -info.Velocity); velocity = new WVec(WRange.Zero, WRange.Zero, -info.Velocity);
anim = new Animation(info.Image); anim = new Animation(args.SourceActor.World, info.Image);
if (anim.HasSequence("open")) if (anim.HasSequence("open"))
anim.PlayThen("open", () => anim.PlayRepeating("idle")); anim.PlayThen("open", () => anim.PlayRepeating("idle"));
else else

View File

@@ -55,7 +55,7 @@ namespace OpenRA.Mods.RA.Effects
this.target = args.PassiveTarget; this.target = args.PassiveTarget;
if (info.HitAnim != null) if (info.HitAnim != null)
this.hitanim = new Animation(info.HitAnim); this.hitanim = new Animation(args.SourceActor.World, info.HitAnim);
} }
public void Tick(World world) public void Tick(World world)

View File

@@ -88,7 +88,7 @@ namespace OpenRA.Mods.RA.Effects
if (info.Image != null) if (info.Image != null)
{ {
anim = new Animation(info.Image, () => facing); anim = new Animation(args.SourceActor.World, info.Image, () => facing);
anim.PlayRepeating("idle"); anim.PlayRepeating("idle");
} }

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
@@ -45,11 +45,11 @@ namespace OpenRA.Mods.RA.Effects
descendSource = targetPos + offset; descendSource = targetPos + offset;
descendTarget = targetPos; descendTarget = targetPos;
anim = new Animation(weapon); anim = new Animation(firedBy.World, weapon);
anim.PlayRepeating("up"); anim.PlayRepeating("up");
pos = launchPos; pos = launchPos;
var weaponRules = Rules.Weapons[weapon.ToLowerInvariant()]; var weaponRules = firedBy.World.Map.Rules.Weapons[weapon.ToLowerInvariant()];
if (weaponRules.Report != null && weaponRules.Report.Any()) if (weaponRules.Report != null && weaponRules.Report.Any())
Sound.Play(weaponRules.Report.Random(firedBy.World.SharedRandom), pos); Sound.Play(weaponRules.Report.Random(firedBy.World.SharedRandom), pos);

View File

@@ -29,7 +29,7 @@ namespace OpenRA.Mods.RA.Effects
this.cargo = cargo; this.cargo = cargo;
var pai = cargo.Info.Traits.GetOrDefault<ParachuteAttachmentInfo>(); var pai = cargo.Info.Traits.GetOrDefault<ParachuteAttachmentInfo>();
paraAnim = new Animation(pai != null ? pai.ParachuteSprite : "parach"); paraAnim = new Animation(cargo.World, pai != null ? pai.ParachuteSprite : "parach");
paraAnim.PlayThen("open", () => paraAnim.PlayRepeating("idle")); paraAnim.PlayThen("open", () => paraAnim.PlayRepeating("idle"));
if (pai != null) if (pai != null)

View File

@@ -18,12 +18,15 @@ namespace OpenRA.Mods.RA.Effects
{ {
class PowerdownIndicator : IEffect class PowerdownIndicator : IEffect
{ {
Actor a; readonly Actor a;
Animation anim = new Animation("poweroff"); readonly Animation anim;
public PowerdownIndicator(Actor a) public PowerdownIndicator(Actor a)
{ {
this.a = a; anim.PlayRepeating("offline"); this.a = a;
anim = new Animation(a.World, "poweroff");
anim.PlayRepeating("offline");
} }
public void Tick(World world) public void Tick(World world)

View File

@@ -21,14 +21,19 @@ namespace OpenRA.Mods.RA.Effects
readonly Actor building; readonly Actor building;
readonly RA.RallyPoint rp; readonly RA.RallyPoint rp;
readonly string palettePrefix; readonly string palettePrefix;
public Animation flag = new Animation("rallypoint"); readonly Animation flag;
public Animation circles = new Animation("rallypoint"); readonly Animation circles;
public RallyPoint(Actor building, string palettePrefix) public RallyPoint(Actor building, string palettePrefix)
{ {
this.building = building; this.building = building;
rp = building.Trait<RA.RallyPoint>();
this.palettePrefix = palettePrefix; this.palettePrefix = palettePrefix;
rp = building.Trait<RA.RallyPoint>();
flag = new Animation(building.World, "rallypoint");
circles = new Animation(building.World, "rallypoint");
flag.PlayRepeating("flag"); flag.PlayRepeating("flag");
circles.Play("circles"); circles.Play("circles");
} }

View File

@@ -17,16 +17,17 @@ namespace OpenRA.Mods.RA.Effects
{ {
class Rank : IEffect class Rank : IEffect
{ {
Actor self; readonly Actor self;
Animation anim = new Animation("rank"); readonly Animation anim;
readonly string paletteName; readonly string paletteName;
public Rank(Actor self, string paletteName) public Rank(Actor self, string paletteName)
{ {
this.self = self; this.self = self;
this.paletteName = paletteName; this.paletteName = paletteName;
var xp = self.Trait<GainsExperience>();
var xp = self.Trait<GainsExperience>();
anim = new Animation(self.World, "rank");
anim.PlayRepeating("rank"); anim.PlayRepeating("rank");
anim.PlayFetchIndex("rank", () => xp.Level == 0 ? 0 : xp.Level - 1); anim.PlayFetchIndex("rank", () => xp.Level == 0 ? 0 : xp.Level - 1);
} }

View File

@@ -18,18 +18,20 @@ namespace OpenRA.Mods.RA.Effects
{ {
class RepairIndicator : IEffect class RepairIndicator : IEffect
{ {
Actor building; readonly Actor building;
Player player; readonly Player player;
string palettePrefix; readonly string palettePrefix;
Animation anim = new Animation("allyrepair"); readonly Animation anim;
RepairableBuilding rb; readonly RepairableBuilding rb;
public RepairIndicator(Actor building, string palettePrefix, Player player) public RepairIndicator(Actor building, string palettePrefix, Player player)
{ {
this.building = building; this.building = building;
this.player = player; this.player = player;
this.palettePrefix = palettePrefix; this.palettePrefix = palettePrefix;
rb = building.Trait<RepairableBuilding>(); rb = building.Trait<RepairableBuilding>();
anim = new Animation(building.World, "allyrepair");
anim.PlayRepeating("repair"); anim.PlayRepeating("repair");
} }

View File

@@ -17,11 +17,13 @@ namespace OpenRA.Mods.RA.Effects
class SatelliteLaunch : IEffect class SatelliteLaunch : IEffect
{ {
int frame = 0; int frame = 0;
Animation doors = new Animation("atek"); readonly Animation doors;
WPos pos; readonly WPos pos;
public SatelliteLaunch(Actor a) public SatelliteLaunch(Actor a)
{ {
doors = new Animation(a.World, "atek");
doors.PlayThen("active", doors.PlayThen("active",
() => a.World.AddFrameEndTask(w => w.Remove(this))); () => a.World.AddFrameEndTask(w => w.Remove(this)));
@@ -33,7 +35,7 @@ namespace OpenRA.Mods.RA.Effects
doors.Tick(); doors.Tick();
if (++frame == 19) if (++frame == 19)
world.AddFrameEndTask(w => w.Add(new GpsSatellite(pos))); world.AddFrameEndTask(w => w.Add(new GpsSatellite(world, pos)));
} }
public IEnumerable<IRenderable> Render(WorldRenderer wr) public IEnumerable<IRenderable> Render(WorldRenderer wr)

Some files were not shown because too many files have changed in this diff Show More