diff --git a/CHANGELOG b/CHANGELOG
index 018f756dea..7d92929a72 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -16,8 +16,9 @@ NEW:
Added a setting for team health bar colors.
Asset Browser:
Fixed crashes when trying to load invalid filenames or sprites with just 1 frame.
- Added support for browsing the folders for R8 files.
+ Added support for all sprite types.
Added palette chooser and colorpicker dropdown boxes.
+ Overhauled layout.
Red Alert:
Added MAD Tank.
Fixed a crash in Monster Tank Madness.
@@ -86,6 +87,10 @@ NEW:
Fixed corrupted replays (which would immediately desync).
Removed runtime mod merging.
Added support for map scripting with Lua.
+ Overhauled sprite loading code.
+ Improved error message when loading corrupted sprites.
+ Rewritten shp(ts) parser makes more efficient use of texture space.
+ Added support for the dune 2 shp format.
Build system and packages:
Added GeoIP to Makefile so it is installed properly.
Added desktop shortcut creation support to the Makefile and Windows installer.
@@ -113,7 +118,13 @@ NEW:
Added InvalidTargets property to weapons.
Added modifier support for build palette hotkeys.
The Requires: option for inheriting from a parent mod has been removed. Mods can directly reference the parent mod files instead.
- Icons are now defined in Sequences not Rules.
+ Icons definitions have moved from the unit's rules to its sequence.
+ Mouse cursors (cursors.yaml) must now specify their file extension.
+ OpenRA.Utility --png will now generate a set of frames for any sprite type [shp(td)/shp(ts)/shp(d2)/r8/tmp(td)/tmp(ra)].
+ OpenRA.Utility --shp now requires a list of frames to be combined into a shp.
+ Removed Utility --tmp-png, --r8, --fromd2 commands (use --png instead).
+ Removed Asset Browser file extraction / conversion (use the Utility instead).
+ Unified sprite loading allows any sprite type to be used anywhere: shp can now be used for terrain, and tmp for units.
20130915:
All mods:
diff --git a/Makefile b/Makefile
index eb5c4a81fa..aec7f8ba0c 100644
--- a/Makefile
+++ b/Makefile
@@ -159,8 +159,8 @@ STD_MOD_DEPS = $(STD_MOD_LIBS) $(ralint_TARGET)
mod_ra_SRCS := $(shell find OpenRA.Mods.RA/ -iname '*.cs')
mod_ra_TARGET = mods/ra/OpenRA.Mods.RA.dll
mod_ra_KIND = library
-mod_ra_DEPS = $(STD_MOD_DEPS) $(utility_TARGET) $(geoip_TARGET) $(irc_TARGET) $(lua_TARGET)
-mod_ra_LIBS = $(COMMON_LIBS) $(STD_MOD_LIBS) $(utility_TARGET) $(geoip_TARGET) $(irc_TARGET) $(lua_TARGET)
+mod_ra_DEPS = $(STD_MOD_DEPS) $(geoip_TARGET) $(irc_TARGET) $(lua_TARGET)
+mod_ra_LIBS = $(COMMON_LIBS) $(STD_MOD_LIBS) $(geoip_TARGET) $(irc_TARGET) $(lua_TARGET)
PROGRAMS += mod_ra
mod_ra: $(mod_ra_TARGET)
diff --git a/OpenRA.Editor/OpenRA.Editor.csproj b/OpenRA.Editor/OpenRA.Editor.csproj
index 166adf6e68..be2dd5e5fa 100644
--- a/OpenRA.Editor/OpenRA.Editor.csproj
+++ b/OpenRA.Editor/OpenRA.Editor.csproj
@@ -165,6 +165,7 @@
Component
+
diff --git a/OpenRA.Editor/RenderUtils.cs b/OpenRA.Editor/RenderUtils.cs
index f7b6871521..2d29595e8b 100644
--- a/OpenRA.Editor/RenderUtils.cs
+++ b/OpenRA.Editor/RenderUtils.cs
@@ -8,8 +8,10 @@
*/
#endregion
+using System.Collections;
using System.Drawing;
using System.Drawing.Imaging;
+using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Traits;
@@ -17,11 +19,11 @@ namespace OpenRA.Editor
{
static class RenderUtils
{
- static Bitmap RenderShp(ShpReader shp, Palette p)
+ static Bitmap RenderShp(ISpriteSource shp, Palette p)
{
- var frame = shp[0];
+ var frame = shp.Frames.First();
- var bitmap = new Bitmap(shp.Width, shp.Height, PixelFormat.Format8bppIndexed);
+ var bitmap = new Bitmap(frame.Size.Width, frame.Size.Height, PixelFormat.Format8bppIndexed);
bitmap.Palette = p.AsSystemPalette();
@@ -33,9 +35,9 @@ namespace OpenRA.Editor
byte* q = (byte*)data.Scan0.ToPointer();
var stride2 = data.Stride;
- for (var i = 0; i < shp.Width; i++)
- for (var j = 0; j < shp.Height; j++)
- q[j * stride2 + i] = frame.Image[i + shp.Width * j];
+ for (var i = 0; i < frame.Size.Width; i++)
+ for (var j = 0; j < frame.Size.Height; j++)
+ q[j * stride2 + i] = frame.Data[i + frame.Size.Width * j];
}
bitmap.UnlockBits(data);
@@ -78,10 +80,11 @@ namespace OpenRA.Editor
var image = info.SpriteNames[0];
using (var s = FileSystem.OpenWithExts(image, exts))
{
- var shp = new ShpReader(s);
- var frame = shp[shp.ImageCount - 1];
+ // TODO: Do this properly
+ var shp = new ShpReader(s) as ISpriteSource;
+ var frame = shp.Frames.Last();
- var bitmap = new Bitmap(shp.Width, shp.Height, PixelFormat.Format8bppIndexed);
+ var bitmap = new Bitmap(frame.Size.Width, frame.Size.Height, PixelFormat.Format8bppIndexed);
bitmap.Palette = p.AsSystemPalette();
var data = bitmap.LockBits(bitmap.Bounds(),
ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
@@ -91,13 +94,13 @@ namespace OpenRA.Editor
byte* q = (byte*)data.Scan0.ToPointer();
var stride = data.Stride;
- for (var i = 0; i < shp.Width; i++)
- for (var j = 0; j < shp.Height; j++)
- q[j * stride + i] = frame.Image[i + shp.Width * j];
+ for (var i = 0; i < frame.Size.Width; i++)
+ for (var j = 0; j < frame.Size.Height; j++)
+ q[j * stride + i] = frame.Data[i + frame.Size.Width * j];
}
bitmap.UnlockBits(data);
- return new ResourceTemplate { Bitmap = bitmap, Info = info, Value = shp.ImageCount - 1 };
+ return new ResourceTemplate { Bitmap = bitmap, Info = info, Value = shp.Frames.Count() - 1 };
}
}
}
diff --git a/OpenRA.FileFormats/Graphics/TileSetRenderer.cs b/OpenRA.Editor/TileSetRenderer.cs
similarity index 71%
rename from OpenRA.FileFormats/Graphics/TileSetRenderer.cs
rename to OpenRA.Editor/TileSetRenderer.cs
index 98c7459438..c1b1482b1f 100644
--- a/OpenRA.FileFormats/Graphics/TileSetRenderer.cs
+++ b/OpenRA.Editor/TileSetRenderer.cs
@@ -11,9 +11,11 @@
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
+using System.IO;
using System.Linq;
+using OpenRA.FileFormats;
-namespace OpenRA.FileFormats
+namespace OpenRA.Editor
{
public class TileSetRenderer
{
@@ -21,20 +23,31 @@ namespace OpenRA.FileFormats
Dictionary> templates;
public Size TileSize;
- List LoadTemplate(string filename, string[] exts, Cache r8cache, int[] frames)
+ List LoadTemplate(string filename, string[] exts, Dictionary sourceCache, int[] frames)
{
- if (exts.Contains(".R8") && FileSystem.Exists(filename + ".R8"))
+ ISpriteSource source;
+ if (!sourceCache.ContainsKey(filename))
{
- var data = new List();
+ using (var s = FileSystem.OpenWithExts(filename, exts))
+ source = SpriteSource.LoadSpriteSource(s, filename);
- foreach (var f in frames)
- data.Add(f >= 0 ? r8cache[filename][f].Image : null);
+ if (source.CacheWhenLoadingTileset)
+ sourceCache.Add(filename, source);
+ }
+ else
+ source = sourceCache[filename];
- return data;
+ if (frames != null)
+ {
+ var ret = new List();
+ var srcFrames = source.Frames.ToArray();
+ foreach (var i in frames)
+ ret.Add(srcFrames[i].Data);
+
+ return ret;
}
- using (var s = FileSystem.OpenWithExts(filename, exts))
- return new Terrain(s).TileBitmapBytes;
+ return source.Frames.Select(f => f.Data).ToList();
}
public TileSetRenderer(TileSet tileset, Size tileSize)
@@ -43,9 +56,9 @@ namespace OpenRA.FileFormats
this.TileSize = tileSize;
templates = new Dictionary>();
- var r8cache = new Cache(s => new R8Reader(FileSystem.OpenWithExts(s, ".R8")));
+ var sourceCache = new Dictionary();
foreach (var t in TileSet.Templates)
- templates.Add(t.Key, LoadTemplate(t.Value.Image, tileset.Extensions, r8cache, t.Value.Frames));
+ templates.Add(t.Key, LoadTemplate(t.Value.Image, tileset.Extensions, sourceCache, t.Value.Frames));
}
public Bitmap RenderTemplate(ushort id, Palette p)
diff --git a/OpenRA.FileFormats/Graphics/Dune2ShpReader.cs b/OpenRA.FileFormats/Graphics/Dune2ShpReader.cs
deleted file mode 100644
index 3951a50458..0000000000
--- a/OpenRA.FileFormats/Graphics/Dune2ShpReader.cs
+++ /dev/null
@@ -1,144 +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.Collections;
-using System.Collections.Generic;
-using System.Drawing;
-using System.IO;
-
-namespace OpenRA.FileFormats
-{
- public enum Dune2ImageFlags : int
- {
- F80_F2 = 0,
- F2 = 2,
- L16_F80_F2_1 = 1,
- L16_F80_F2_2 = 3,
- Ln_F80_F2 = 5
- }
-
- public class Dune2ImageHeader
- {
- public readonly Dune2ImageFlags Flags;
- public readonly int Width;
- public readonly int Height;
- public readonly int Slices;
- public readonly int FileSize;
- public readonly int DataSize;
-
- public readonly byte[] LookupTable;
- public byte[] Image;
-
- public Dune2ImageHeader(Stream s)
- {
- Flags = (Dune2ImageFlags)s.ReadUInt16();
- Slices = s.ReadUInt8();
- Width = s.ReadUInt16();
- Height = s.ReadUInt8();
- FileSize = s.ReadUInt16();
- DataSize = s.ReadUInt16();
-
- if (Flags == Dune2ImageFlags.L16_F80_F2_1 ||
- Flags == Dune2ImageFlags.L16_F80_F2_2 ||
- Flags == Dune2ImageFlags.Ln_F80_F2)
- {
- int n = Flags == Dune2ImageFlags.Ln_F80_F2 ? s.ReadUInt8() : (byte)16;
- LookupTable = new byte[n];
- for (int i = 0; i < n; i++)
- LookupTable[i] = s.ReadUInt8();
- }
- else
- {
- LookupTable = new byte[256];
- for (int i = 0; i < 256; i++)
- LookupTable[i] = (byte)i;
- LookupTable[1] = 0x7f;
- LookupTable[2] = 0x7e;
- LookupTable[3] = 0x7d;
- LookupTable[4] = 0x7c;
- }
- }
-
- public Size Size
- {
- get { return new Size(Width, Height); }
- }
- }
-
- public class Dune2ShpReader : IEnumerable
- {
- public readonly int ImageCount;
-
- List headers = new List();
-
- public Dune2ShpReader(Stream s)
- {
- ImageCount = s.ReadUInt16();
-
- //Last offset is pointer to end of file.
- uint[] offsets = new uint[ImageCount + 1];
-
- uint temp = s.ReadUInt32();
-
- //If fourth byte in file is non-zero, the offsets are two bytes each.
- bool twoByteOffsets = (temp & 0xFF0000) > 0;
- if (twoByteOffsets)
- {
- offsets[0] = ((temp & 0xFFFF0000) >> 16) + 2; //Offset does not account for image count bytes
- offsets[1] = (temp & 0xFFFF) + 2;
- }
- else
- offsets[0] = temp + 2;
-
- for (int i = twoByteOffsets ? 2 : 1; i < ImageCount + 1; i++)
- offsets[i] = (twoByteOffsets ? s.ReadUInt16() : s.ReadUInt32()) + 2;
-
- for (int i = 0; i < ImageCount; i++)
- {
- s.Seek(offsets[i], SeekOrigin.Begin);
- Dune2ImageHeader header = new Dune2ImageHeader(s);
- byte[] imgData = s.ReadBytes(header.FileSize);
- header.Image = new byte[header.Height * header.Width];
-
- //Decode image data
- if (header.Flags != Dune2ImageFlags.F2)
- {
- byte[] tempData = new byte[header.DataSize];
- Format80.DecodeInto(imgData, tempData);
- Format2.DecodeInto(tempData, header.Image);
- }
- else
- Format2.DecodeInto(imgData, header.Image);
-
- //Lookup values in lookup table
- if (header.LookupTable != null)
- for (int j = 0; j < header.Image.Length; j++)
- header.Image[j] = header.LookupTable[header.Image[j]];
-
- headers.Add(header);
- }
- }
-
- public Dune2ImageHeader this[int index]
- {
- get { return headers[index]; }
- }
-
- public IEnumerator GetEnumerator()
- {
- return headers.GetEnumerator();
- }
-
- IEnumerator IEnumerable.GetEnumerator()
- {
- return GetEnumerator();
- }
- }
-}
diff --git a/OpenRA.FileFormats/Graphics/R8Reader.cs b/OpenRA.FileFormats/Graphics/R8Reader.cs
index 132c48a436..edc95b2cf2 100644
--- a/OpenRA.FileFormats/Graphics/R8Reader.cs
+++ b/OpenRA.FileFormats/Graphics/R8Reader.cs
@@ -12,17 +12,16 @@ using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
+using System.Linq;
namespace OpenRA.FileFormats
{
- public class R8Image
+ class R8Image : ISpriteFrame
{
- public readonly Size Size;
- public readonly int2 Offset;
- public readonly byte[] Image;
-
- // Legacy variable. Can be removed when the utility command is made sensible.
- public readonly Size FrameSize;
+ public Size Size { get; private set; }
+ public Size FrameSize { get; private set; }
+ public float2 Offset { get; private set; }
+ public byte[] Data { get; set; }
public R8Image(Stream s)
{
@@ -52,7 +51,7 @@ namespace OpenRA.FileFormats
// Skip alignment byte
s.ReadUInt8();
- Image = s.ReadBytes(width*height);
+ Data = s.ReadBytes(width*height);
// Ignore palette
if (type == 1 && paletteOffset != 0)
@@ -60,33 +59,20 @@ namespace OpenRA.FileFormats
}
}
- public class R8Reader : IEnumerable
+ public class R8Reader : ISpriteSource
{
- readonly List headers = new List();
+ readonly List frames = new List();
+ public IEnumerable Frames { get { return frames.Cast(); } }
+ public bool CacheWhenLoadingTileset { get { return true; } }
- public readonly int Frames;
+ public readonly int ImageCount;
public R8Reader(Stream stream)
{
while (stream.Position < stream.Length)
{
- headers.Add(new R8Image(stream));
- Frames++;
+ frames.Add(new R8Image(stream));
+ ImageCount++;
}
}
-
- public R8Image this[int index]
- {
- get { return headers[index]; }
- }
-
- public IEnumerator GetEnumerator()
- {
- return headers.GetEnumerator();
- }
-
- IEnumerator IEnumerable.GetEnumerator()
- {
- return GetEnumerator();
- }
}
}
diff --git a/OpenRA.FileFormats/Graphics/ShpD2Reader.cs b/OpenRA.FileFormats/Graphics/ShpD2Reader.cs
new file mode 100644
index 0000000000..aa21efc521
--- /dev/null
+++ b/OpenRA.FileFormats/Graphics/ShpD2Reader.cs
@@ -0,0 +1,115 @@
+#region Copyright & License Information
+/*
+ * Copyright 2007-2013 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.Collections;
+using System.Collections.Generic;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+
+namespace OpenRA.FileFormats
+{
+ enum Dune2ImageFlags : int
+ {
+ F80_F2 = 0,
+ F2 = 2,
+ L16_F80_F2_1 = 1,
+ L16_F80_F2_2 = 3,
+ Ln_F80_F2 = 5
+ }
+
+ class Frame : ISpriteFrame
+ {
+ public Size Size { get; private set; }
+ public Size FrameSize { get { return Size; } }
+ public float2 Offset { get { return float2.Zero; } }
+ public byte[] Data { get; set; }
+
+ public Frame(Stream s)
+ {
+ var flags = (Dune2ImageFlags)s.ReadUInt16();
+ s.Position += 1;
+ var width = s.ReadUInt16();
+ var height = s.ReadUInt8();
+ Size = new Size(width, height);
+
+ var frameSize = s.ReadUInt16();
+ var dataSize = s.ReadUInt16();
+
+ byte[] table;
+ if (flags == Dune2ImageFlags.L16_F80_F2_1 ||
+ flags == Dune2ImageFlags.L16_F80_F2_2 ||
+ flags == Dune2ImageFlags.Ln_F80_F2)
+ {
+ var n = flags == Dune2ImageFlags.Ln_F80_F2 ? s.ReadUInt8() : (byte)16;
+ table = new byte[n];
+ for (var i = 0; i < n; i++)
+ table[i] = s.ReadUInt8();
+ }
+ else
+ {
+ table = new byte[256];
+ for (var i = 0; i < 256; i++)
+ table[i] = (byte)i;
+ table[1] = 0x7f;
+ table[2] = 0x7e;
+ table[3] = 0x7d;
+ table[4] = 0x7c;
+ }
+
+ // Subtract header size
+ var imgData = s.ReadBytes(frameSize - 10);
+ Data = new byte[width * height];
+
+ // Decode image data
+ if (flags != Dune2ImageFlags.F2)
+ {
+ var tempData = new byte[dataSize];
+ Format80.DecodeInto(imgData, tempData);
+ Format2.DecodeInto(tempData, Data);
+ }
+ else
+ Format2.DecodeInto(imgData, Data);
+
+ // Lookup values in lookup table
+ for (var j = 0; j < Data.Length; j++)
+ Data[j] = table[Data[j]];
+ }
+ }
+
+ public class ShpD2Reader : ISpriteSource
+ {
+ List headers = new List();
+ public IEnumerable Frames { get { return headers.Cast(); } }
+ public bool CacheWhenLoadingTileset { get { return false; } }
+
+ public ShpD2Reader(Stream s)
+ {
+ var imageCount = s.ReadUInt16();
+
+ // Last offset is pointer to end of file.
+ var offsets = new uint[imageCount + 1];
+ var temp = s.ReadUInt32();
+
+ // If fourth byte in file is non-zero, the offsets are two bytes each.
+ var twoByteOffset = (temp & 0xFF0000) > 0;
+ s.Position = 2;
+
+ for (var i = 0; i < imageCount + 1; i++)
+ offsets[i] = (twoByteOffset ? s.ReadUInt16() : s.ReadUInt32()) + 2;
+
+ for (var i = 0; i < imageCount; i++)
+ {
+ s.Position = offsets[i];
+ headers.Add(new Frame(s));
+ }
+ }
+ }
+}
diff --git a/OpenRA.FileFormats/Graphics/ShpReader.cs b/OpenRA.FileFormats/Graphics/ShpReader.cs
index 0795b2696a..b211b94751 100644
--- a/OpenRA.FileFormats/Graphics/ShpReader.cs
+++ b/OpenRA.FileFormats/Graphics/ShpReader.cs
@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
- * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
+ * Copyright 2007-2013 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,
@@ -15,153 +15,180 @@ using System.Linq;
namespace OpenRA.FileFormats
{
- public class ImageHeader
+ enum Format { Format20 = 0x20, Format40 = 0x40, Format80 = 0x80 }
+
+ class ImageHeader : ISpriteFrame
{
- public uint Offset;
+ public Size Size { get { return reader.Size; } }
+ public Size FrameSize { get { return reader.Size; } }
+ public float2 Offset { get { return float2.Zero; } }
+ public byte[] Data { get; set; }
+
+ public uint FileOffset;
public Format Format;
public uint RefOffset;
public Format RefFormat;
public ImageHeader RefImage;
- public byte[] Image;
-
+ ShpReader reader;
+ // Used by ShpWriter
public ImageHeader() { }
- public ImageHeader( BinaryReader reader )
+ public ImageHeader(Stream stream, ShpReader reader)
{
- var data = reader.ReadUInt32();
- Offset = data & 0xffffff;
+ this.reader = reader;
+ var data = stream.ReadUInt32();
+ FileOffset = data & 0xffffff;
Format = (Format)(data >> 24);
- RefOffset = reader.ReadUInt16();
- RefFormat = (Format)reader.ReadUInt16();
+ RefOffset = stream.ReadUInt16();
+ RefFormat = (Format)stream.ReadUInt16();
}
- public static readonly int SizeOnDisk = 8;
-
public void WriteTo(BinaryWriter writer)
{
- writer.Write(Offset | ((uint)Format << 24));
+ writer.Write(FileOffset | ((uint)Format << 24));
writer.Write((ushort)RefOffset);
writer.Write((ushort)RefFormat);
}
}
- public enum Format { Format20 = 0x20, Format40 = 0x40, Format80 = 0x80 }
-
- public class ShpReader
+ public class ShpReader : ISpriteSource
{
- public readonly int ImageCount;
- public readonly ushort Width;
- public readonly ushort Height;
-
- public Size Size { get { return new Size(Width, Height); } }
-
readonly List headers = new List();
+ public IEnumerable Frames { get { return headers.Cast(); } }
+ public bool CacheWhenLoadingTileset { get { return false; } }
+ public readonly Size Size;
int recurseDepth = 0;
+ readonly int imageCount;
public ShpReader(Stream stream)
{
- using (var reader = new BinaryReader(stream))
+ imageCount = stream.ReadUInt16();
+ stream.Position += 4;
+ var width = stream.ReadUInt16();
+ var height = stream.ReadUInt16();
+ Size = new Size(width, height);
+
+ stream.Position += 4;
+ for (var i = 0; i < imageCount; i++)
+ headers.Add(new ImageHeader(stream, this));
+
+ // Skip eof and zero headers
+ stream.Position += 16;
+
+ var offsets = headers.ToDictionary(h => h.FileOffset, h => h);
+ for (var i = 0; i < imageCount; i++)
{
- ImageCount = reader.ReadUInt16();
- reader.ReadUInt16();
- reader.ReadUInt16();
- Width = reader.ReadUInt16();
- Height = reader.ReadUInt16();
- reader.ReadUInt32();
+ var h = headers[i];
+ if (h.Format == Format.Format20)
+ h.RefImage = headers[i - 1];
- for (int i = 0 ; i < ImageCount ; i++)
- headers.Add(new ImageHeader(reader));
-
- new ImageHeader(reader); // end-of-file header
- new ImageHeader(reader); // all-zeroes header
-
- var offsets = headers.ToDictionary(h => h.Offset, h =>h);
-
- for (int i = 0 ; i < ImageCount ; i++)
- {
- var h = headers[ i ];
- if (h.Format == Format.Format20)
- h.RefImage = headers[i - 1];
-
- else if (h.Format == Format.Format40)
- if (!offsets.TryGetValue(h.RefOffset, out h.RefImage))
- throw new InvalidDataException("Reference doesnt point to image data {0}->{1}".F(h.Offset, h.RefOffset));
- }
-
- foreach (ImageHeader h in headers)
- Decompress(stream, h);
+ else if (h.Format == Format.Format40 && !offsets.TryGetValue(h.RefOffset, out h.RefImage))
+ throw new InvalidDataException("Reference doesnt point to image data {0}->{1}".F(h.FileOffset, h.RefOffset));
}
+
+ foreach (var h in headers)
+ Decompress(stream, h);
}
- public ImageHeader this[int index]
+ static byte[] ReadCompressedData(Stream stream, ImageHeader h)
{
- get { return headers[index]; }
+ stream.Position = h.FileOffset;
+
+ // Actually, far too big. There's no length field with the correct length though :(
+ var compressedLength = (int)(stream.Length - stream.Position);
+ var compressedBytes = new byte[compressedLength];
+ stream.Read(compressedBytes, 0, compressedLength);
+
+ return compressedBytes;
}
void Decompress(Stream stream, ImageHeader h)
{
- if (recurseDepth > ImageCount)
+ if (recurseDepth > imageCount)
throw new InvalidDataException("Format20/40 headers contain infinite loop");
- switch(h.Format)
+ switch (h.Format)
{
case Format.Format20:
case Format.Format40:
+ {
+ if (h.RefImage.Data == null)
{
- if (h.RefImage.Image == null)
- {
- ++recurseDepth;
- Decompress(stream, h.RefImage);
- --recurseDepth;
- }
+ ++recurseDepth;
+ Decompress(stream, h.RefImage);
+ --recurseDepth;
+ }
+
+ h.Data = CopyImageData(h.RefImage.Data);
+ Format40.DecodeInto(ReadCompressedData(stream, h), h.Data);
+ break;
+ }
- h.Image = CopyImageData(h.RefImage.Image);
- Format40.DecodeInto(ReadCompressedData(stream, h), h.Image);
- break;
- }
case Format.Format80:
- {
- var imageBytes = new byte[Width * Height];
- Format80.DecodeInto(ReadCompressedData(stream, h), imageBytes);
- h.Image = imageBytes;
- break;
- }
+ {
+ var imageBytes = new byte[Size.Width * Size.Height];
+ Format80.DecodeInto(ReadCompressedData(stream, h), imageBytes);
+ h.Data = imageBytes;
+ break;
+ }
+
default:
throw new InvalidDataException();
}
}
- static byte[] ReadCompressedData(Stream stream, ImageHeader h)
- {
- stream.Position = h.Offset;
- // TODO: Actually, far too big. There's no length field with the correct length though :(
- var compressedLength = (int)(stream.Length - stream.Position);
-
- var compressedBytes = new byte[ compressedLength ];
- stream.Read( compressedBytes, 0, compressedLength );
-
- return compressedBytes;
- }
-
byte[] CopyImageData(byte[] baseImage)
{
- var imageData = new byte[Width * Height];
- for (int i = 0 ; i < Width * Height ; i++)
+ var imageData = new byte[Size.Width * Size.Height];
+ for (var i = 0; i < Size.Width * Size.Height; i++)
imageData[i] = baseImage[i];
return imageData;
}
- public IEnumerable Frames { get { return headers; } }
-
public static ShpReader Load(string filename)
{
using (var s = File.OpenRead(filename))
return new ShpReader(s);
}
+
+ public static void Write(Stream s, Size size, IEnumerable frames)
+ {
+ var compressedFrames = frames.Select(f => Format80.Encode(f)).ToArray();
+
+ // note: end-of-file and all-zeroes headers
+ var dataOffset = 14 + (compressedFrames.Length + 2) * 8;
+
+ using (var bw = new BinaryWriter(s))
+ {
+ bw.Write((ushort)compressedFrames.Length);
+ bw.Write((ushort)0);
+ bw.Write((ushort)0);
+ bw.Write((ushort)size.Width);
+ bw.Write((ushort)size.Height);
+ bw.Write((uint)0);
+
+ foreach (var f in compressedFrames)
+ {
+ var ih = new ImageHeader { Format = Format.Format80, FileOffset = (uint)dataOffset };
+ dataOffset += f.Length;
+
+ ih.WriteTo(bw);
+ }
+
+ var eof = new ImageHeader { FileOffset = (uint)dataOffset };
+ eof.WriteTo(bw);
+
+ var allZeroes = new ImageHeader { };
+ allZeroes.WriteTo(bw);
+
+ foreach (var f in compressedFrames)
+ bw.Write(f);
+ }
+ }
}
}
diff --git a/OpenRA.FileFormats/Graphics/ShpTSReader.cs b/OpenRA.FileFormats/Graphics/ShpTSReader.cs
index 68cfbb918b..90c45aa85a 100644
--- a/OpenRA.FileFormats/Graphics/ShpTSReader.cs
+++ b/OpenRA.FileFormats/Graphics/ShpTSReader.cs
@@ -1,615 +1,112 @@
#region Copyright & License Information
/*
* Copyright 2007-2013 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
* as published by the Free Software Foundation. For more information,
- * see LICENSE.
+ * see COPYING.
*/
#endregion
-using System;
-using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
+using System.Linq;
namespace OpenRA.FileFormats
{
-
- public struct Header
+ class FrameHeader : ISpriteFrame
{
- public ushort A;
- // Unknown
- // Width and Height of the images
- public ushort Width;
- public ushort Height;
- public ushort NumImages;
- }
+ public Size Size { get; private set; }
+ public Size FrameSize { get; private set; }
+ public float2 Offset { get; private set; }
+ public byte[] Data { get; set; }
- public class HeaderImage
- {
- public ushort x;
- public ushort y;
- public ushort cx;
- public ushort cy;
- // cx and cy are width n height of stored image
- public byte compression;
- public byte[] align;
- public byte[] transparent;
- public int zero;
- public int offset;
- public byte[] Image;
- }
+ public readonly uint FileOffset;
+ public readonly byte Format;
- public struct SHPData
- {
- public HeaderImage HeaderImage;
- public byte[] Databuffer;
- public byte[] FrameImage;
- }
-
- public struct SHP
- {
- public Header Header;
- public SHPData[] Data;
- }
-
-
- public class ShpTSReader : IEnumerable
- {
- public readonly int ImageCount;
- public readonly ushort Width;
- public readonly ushort Height;
- public readonly ushort Width2;
- public readonly ushort Height2;
- public int arroff = 0;
- public int erri = 0;
- public int errj = 0;
- public int errk = 0;
- public int errl = 0;
-
- public static int FindNextOffsetFrom(SHP SHP, int Init, int Last)
+ public FrameHeader(Stream stream, Size frameSize)
{
- int result;
- result = 0;
- Last++;
- while ((result == 0) && (Init < Last))
- {
- result = SHP.Data[Init].HeaderImage.offset;
- Init++;
- }
- return result;
+ var x = stream.ReadUInt16();
+ var y = stream.ReadUInt16();
+ var width = stream.ReadUInt16();
+ var height = stream.ReadUInt16();
+
+ Offset = new float2(x + 0.5f * (width - frameSize.Width), y + 0.5f * (height - frameSize.Height));
+ Size = new Size(width, height);
+ FrameSize = frameSize;
+
+ Format = stream.ReadUInt8();
+ stream.Position += 11;
+ FileOffset = stream.ReadUInt32();
}
+ }
- private readonly List headers = new List();
+ public class ShpTSReader : ISpriteSource
+ {
+ readonly List frames = new List();
+ public IEnumerable Frames { get { return frames.Cast(); } }
+ public bool CacheWhenLoadingTileset { get { return false; } }
- public ShpTSReader(Stream s)
+ public ShpTSReader(Stream stream)
{
+ stream.ReadUInt16();
+ var width = stream.ReadUInt16();
+ var height = stream.ReadUInt16();
+ var size = new Size(width, height);
+ var frameCount = stream.ReadUInt16();
- SHP SHP = new SHP();
- int FileSize;
- int x;
- int k = 0;
- int l = 0;
+ for (var i = 0; i < frameCount; i++)
+ frames.Add(new FrameHeader(stream, size));
- int ImageSize;
- int NextOffset;
+ for (var i = 0; i < frameCount; i++)
+ {
+ var f = frames[i];
+ if (f.FileOffset == 0)
+ continue;
- byte[] FData;
- byte cp;
- byte[] Databuffer;
+ stream.Position = f.FileOffset;
- FileSize = (int)s.Length;
- // Get Header
- SHP.Header.A = s.ReadUInt16();
- SHP.Header.Width = s.ReadUInt16();
- SHP.Header.Height = s.ReadUInt16();
- SHP.Header.NumImages = s.ReadUInt16();
+ // Uncompressed
+ if (f.Format == 1 || f.Format == 0)
+ f.Data = stream.ReadBytes(f.Size.Width * f.Size.Height);
- SHP.Data = new SHPData[SHP.Header.NumImages + 1];
-
- ImageCount = SHP.Header.NumImages;
-
- for (x = 1; x <= SHP.Header.NumImages; x++)
+ // Uncompressed scanlines
+ else if (f.Format == 2)
{
- SHP.Data[x].HeaderImage = new HeaderImage();
-
- SHP.Data[x].HeaderImage.x = s.ReadUInt16();
- SHP.Data[x].HeaderImage.y = s.ReadUInt16();
- SHP.Data[x].HeaderImage.cx = s.ReadUInt16();
- SHP.Data[x].HeaderImage.cy = s.ReadUInt16();
-
- SHP.Data[x].HeaderImage.compression = s.ReadUInt8();
- SHP.Data[x].HeaderImage.align = s.ReadBytes(3);
- s.ReadInt32();
- SHP.Data[x].HeaderImage.zero = s.ReadUInt8();
- SHP.Data[x].HeaderImage.transparent = s.ReadBytes(3);
-
- SHP.Data[x].HeaderImage.offset = s.ReadInt32();
-
- }
-
- Width = SHP.Header.Width;
- Height = SHP.Header.Height;
-
- for (int i = 0; i < ImageCount; i++)
- {
- headers.Add(SHP.Data[i+1].HeaderImage);
- }
-
- // Read and decode each image from the file
- for (x = 1; x <= SHP.Header.NumImages; x++)
- {
- headers[x - 1].Image = new byte[(Width * Height)];
- for (int i = 0; i < headers[x - 1].Image.Length; i++)
- headers[x - 1].Image[i] = 0;
-
- FData = new byte[(Width * Height)];
-
- // Does it really reads the frame?
- if (SHP.Data[x].HeaderImage.offset != 0)
+ f.Data = new byte[f.Size.Width * f.Size.Height];
+ for (var j = 0; j < f.Size.Height; j++)
{
- try
+ var length = stream.ReadUInt16() - 2;
+ stream.Read(f.Data, f.Size.Width * j, length);
+ }
+ }
+
+ // RLE-zero compressed scanlines
+ else if (f.Format == 3)
+ {
+ f.Data = new byte[f.Size.Width * f.Size.Height];
+
+ for (var j = 0; j < f.Size.Height; j++)
+ {
+ var k = j * f.Size.Width;
+ var length = stream.ReadUInt16() - 2;
+ while (length > 0)
{
- // Now it checks the compression:
- if ((SHP.Data[x].HeaderImage.compression == 3))
- {
- // decode it
- // Compression 3
- NextOffset = FindNextOffsetFrom(SHP, x + 1, SHP.Header.NumImages);
- if (NextOffset != 0)
+ var b = stream.ReadUInt8();
+ length--;
+
+ if (b == 0)
{
-
- ImageSize = NextOffset - SHP.Data[x].HeaderImage.offset;
- Databuffer = new byte[ImageSize];
- for (int i = 0; i < ImageSize; i++)
- {
- s.Seek(SHP.Data[x].HeaderImage.offset + i, SeekOrigin.Begin);
- Databuffer[i] = s.ReadUInt8();
- }
- SHP.Data[x].Databuffer = new byte[(SHP.Data[x].HeaderImage.cx * SHP.Data[x].HeaderImage.cy)];
- Decode3(Databuffer, ref SHP.Data[x].Databuffer, SHP.Data[x].HeaderImage.cx, SHP.Data[x].HeaderImage.cy, ref FileSize);
-
- k = 0;
- l = 0;
- for (int i = 0; i < Height; i++)
- {
- erri = i;
- for (int j = SHP.Data[x].HeaderImage.x; j < Width; j++)
- {
- errj = j;
- errl = l;
- errk = k;
- arroff = i + j + l;
-
- if (((j + 1) > (SHP.Data[x].HeaderImage.cx + SHP.Data[x].HeaderImage.x)) || ((i + 1) > (SHP.Data[x].HeaderImage.cy)))
- cp = 0;
- else
- cp = SHP.Data[x].Databuffer[i + (j - SHP.Data[x].HeaderImage.x) + l];
-
- FData[i + j + k] = cp;
-
- if (j == (SHP.Data[x].HeaderImage.cx + SHP.Data[x].HeaderImage.x - 1))
- l = l + (SHP.Data[x].HeaderImage.cx - 1);
-
- if (j == (Width - 1))
- k = k + (Width - 1);
- }
- }
- //FData = headers[x - 1].Image;
- k = 0;
- for (int i = 0; i < (Height - SHP.Data[x].HeaderImage.y); i++)
- {
- for (int j = 0; j < Width; j++)
- {
- headers[x - 1].Image[i + j + k + (Width * SHP.Data[x].HeaderImage.y)] = FData[i + j + k];
- if (j == (Width - 1))
- {
- k = k + (Width - 1);
- }
- }
- }
-
+ k += stream.ReadUInt8();
+ length--;
}
else
- {
-
- ImageSize = 0;
- ImageSize = FileSize - SHP.Data[x].HeaderImage.offset;
- Databuffer = new byte[ImageSize];
- for (int i = 0; i < ImageSize; i++)
- {
- s.Seek(SHP.Data[x].HeaderImage.offset + i, SeekOrigin.Begin);
- Databuffer[i] = s.ReadUInt8();
- }
- SHP.Data[x].Databuffer = new byte[((SHP.Data[x].HeaderImage.cx * SHP.Data[x].HeaderImage.cy))];
-
- Decode3(Databuffer, ref SHP.Data[x].Databuffer, SHP.Data[x].HeaderImage.cx, SHP.Data[x].HeaderImage.cy, ref ImageSize);
-
- k = 0;
- l = 0;
- for (int i = 0; i < Height; i++)
- {
- erri = i;
- for (int j = SHP.Data[x].HeaderImage.x; j < Width; j++)
- {
- errj = j;
- errl = l;
- errk = k;
- arroff = i + j + l;
-
- if (((j + 1) > (SHP.Data[x].HeaderImage.cx + SHP.Data[x].HeaderImage.x)) || ((i + 1) > (SHP.Data[x].HeaderImage.cy)))
- cp = 0;
- else
- cp = SHP.Data[x].Databuffer[i + (j - SHP.Data[x].HeaderImage.x) + l];
-
- FData[i + j + k] = cp;
-
- if (j == (SHP.Data[x].HeaderImage.cx + SHP.Data[x].HeaderImage.x - 1))
- l = l + (SHP.Data[x].HeaderImage.cx - 1);
-
- if (j == (Width - 1))
- k = k + (Width - 1);
- }
- }
- //FData = headers[x - 1].Image;
- k = 0;
- for (int i = 0; i < (Height - SHP.Data[x].HeaderImage.y); i++)
- {
- for (int j = 0; j < Width; j++)
- {
- headers[x - 1].Image[i + j + k + (Width * SHP.Data[x].HeaderImage.y)] = FData[i + j + k];
- if (j == (Width - 1))
- {
- k = k + (Width - 1);
- }
- }
- }
- }
+ f.Data[k++] = b;
}
- else if ((SHP.Data[x].HeaderImage.compression == 2))
- {
- NextOffset = FindNextOffsetFrom(SHP, x + 1, SHP.Header.NumImages);
- if (NextOffset != 0)
- {
- ImageSize = NextOffset - SHP.Data[x].HeaderImage.offset;
- SHP.Data[x].Databuffer = new byte[(SHP.Data[x].HeaderImage.cx * SHP.Data[x].HeaderImage.cy)];
- Databuffer = new byte[ImageSize];
- for (int i = 0; i < ImageSize; i++)
- {
- s.Seek(SHP.Data[x].HeaderImage.offset + i, SeekOrigin.Begin);
- Databuffer[i] = s.ReadUInt8();
- }
-
- Decode2(Databuffer, ref SHP.Data[x].Databuffer, SHP.Data[x].HeaderImage.cx, SHP.Data[x].HeaderImage.cy, ref ImageSize);
-
- k = 0;
- l = 0;
- for (int i = 0; i < Height; i++)
- {
- erri = i;
- for (int j = SHP.Data[x].HeaderImage.x; j < Width; j++)
- {
- errj = j;
- errl = l;
- errk = k;
- arroff = i + j + l;
-
- if (((j + 1) > (SHP.Data[x].HeaderImage.cx + SHP.Data[x].HeaderImage.x)) || ((i + 1) > (SHP.Data[x].HeaderImage.cy)))
- cp = 0;
- else
- cp = SHP.Data[x].Databuffer[i + (j - SHP.Data[x].HeaderImage.x) + l];
-
- FData[i + j + k] = cp;
-
- if (j == (SHP.Data[x].HeaderImage.cx + SHP.Data[x].HeaderImage.x - 1))
- l = l + (SHP.Data[x].HeaderImage.cx - 1);
-
- if (j == (Width - 1))
- k = k + (Width - 1);
- }
- }
- //FData = headers[x - 1].Image;
- k = 0;
- for (int i = 0; i < (Height - SHP.Data[x].HeaderImage.y); i++)
- {
- for (int j = 0; j < Width; j++)
- {
- headers[x - 1].Image[i + j + k + (Width * SHP.Data[x].HeaderImage.y)] = FData[i + j + k];
- if (j == (Width - 1))
- {
- k = k + (Width - 1);
- }
- }
- }
-
- // Compression 2
- }
- else
- {
- ImageSize = 0;
- ImageSize = FileSize - SHP.Data[x].HeaderImage.offset;
- Databuffer = new byte[ImageSize];
- for (int i = 0; i < ImageSize; i++)
- {
- s.Seek(SHP.Data[x].HeaderImage.offset + i, SeekOrigin.Begin);
- Databuffer[i] = s.ReadUInt8();
- }
- SHP.Data[x].Databuffer = new byte[((SHP.Data[x].HeaderImage.cx * SHP.Data[x].HeaderImage.cy))];
- Decode2(Databuffer, ref SHP.Data[x].Databuffer, SHP.Data[x].HeaderImage.cx, SHP.Data[x].HeaderImage.cy, ref ImageSize);
-
- k = 0;
- l = 0;
- for (int i = 0; i < Height; i++)
- {
- erri = i;
- for (int j = SHP.Data[x].HeaderImage.x; j < Width; j++)
- {
- errj = j;
- errl = l;
- errk = k;
- arroff = i + j + l;
-
- if (((j + 1) > (SHP.Data[x].HeaderImage.cx + SHP.Data[x].HeaderImage.x)) || ((i + 1) > (SHP.Data[x].HeaderImage.cy)))
- cp = 0;
- else
- cp = SHP.Data[x].Databuffer[i + (j - SHP.Data[x].HeaderImage.x) + l];
-
- FData[i + j + k] = cp;
-
- if (j == (SHP.Data[x].HeaderImage.cx + SHP.Data[x].HeaderImage.x - 1))
- l = l + (SHP.Data[x].HeaderImage.cx - 1);
-
- if (j == (Width - 1))
- k = k + (Width - 1);
- }
- }
- //FData = headers[x - 1].Image;
- k = 0;
- for (int i = 0; i < (Height - SHP.Data[x].HeaderImage.y); i++)
- {
- for (int j = 0; j < Width; j++)
- {
- headers[x - 1].Image[i + j + k + (Width * SHP.Data[x].HeaderImage.y)] = FData[i + j + k];
- if (j == (Width - 1))
- {
- k = k + (Width - 1);
- }
- }
- }
- // Compression 2
- }
- }
- else
- {
- // Compression 1
- ImageSize = (int)(SHP.Data[x].HeaderImage.cx * SHP.Data[x].HeaderImage.cy);
- Databuffer = new byte[ImageSize];
- for (int i = 0; i < ImageSize; i++)
- {
- s.Seek(SHP.Data[x].HeaderImage.offset + i, SeekOrigin.Begin);
- Databuffer[i] = s.ReadUInt8();
- }
- SHP.Data[x].Databuffer = new byte[(SHP.Data[x].HeaderImage.cx * SHP.Data[x].HeaderImage.cy)];
- SHP.Data[x].Databuffer = Databuffer;
-
- k = 0;
- l = 0;
- for (int i = 0; i < Height; i++)
- {
- erri = i;
- for (int j = SHP.Data[x].HeaderImage.x; j < Width; j++)
- {
- errj = j;
- errl = l;
- errk = k;
- arroff = i + j + l;
-
- if (((j + 1) > (SHP.Data[x].HeaderImage.cx + SHP.Data[x].HeaderImage.x)) || ((i + 1) > (SHP.Data[x].HeaderImage.cy)))
- cp = 0;
- else
- cp = SHP.Data[x].Databuffer[i + (j - SHP.Data[x].HeaderImage.x) + l];
-
- FData[i + j + k] = cp;
-
- if (j == (SHP.Data[x].HeaderImage.cx + SHP.Data[x].HeaderImage.x - 1))
- l = l + (SHP.Data[x].HeaderImage.cx - 1);
-
- if (j == (Width - 1))
- k = k + (Width - 1);
- }
- }
- //FData = headers[x - 1].Image;
- k = 0;
- for (int i = 0; i < (Height - SHP.Data[x].HeaderImage.y); i++)
- {
- for (int j = 0; j < Width; j++)
- {
- headers[x - 1].Image[i + j + k + (Width * SHP.Data[x].HeaderImage.y)] = FData[i + j + k];
- if (j == (Width - 1))
- {
- k = k + (Width - 1);
- }
- }
- }
- }
- }
- catch (Exception e)
- {
- Console.WriteLine(e.Message);
}
}
- // Set the shp's databuffer to the result after decompression
- }
- //Width = Width2;
- //Height = Height2;
- }
-
- public HeaderImage this[int index]
- {
- get { return headers[index]; }
- }
-
- public static void ReInterpretWordFromBytes(byte Byte1, byte Byte2, ref ushort FullValue)
- {
- FullValue = (ushort)((Byte2 * 256) + Byte1);
- }
-
- public static void ReInterpretWordFromBytes(byte Byte1, byte Byte2, ref uint FullValue)
- {
- FullValue = (uint)((Byte2 * 256) + Byte1);
- }
-
- // Compression 3:
- public static void Decode3(byte[] Source, ref byte[] Dest, int cx, int cy, ref int max)
- {
- int SP;
- int DP;
- int x;
- int y;
- int Count;
- int v;
- int maxdp;
- ushort Pos;
- maxdp = cx * cy;
- SP = 0;
- DP = 0;
- Pos = 0;
- try
- {
- for (y = 1; y <= cy; y++)
- {
- ReInterpretWordFromBytes(Source[SP], Source[SP + 1], ref Pos);
-
- Count = Pos - 2;
-
- SP = SP + 2;
-
- x = 0;
- while (Count > 0)
- {
- Count = Count - 1;
- if ((SP > max) || (DP > maxdp))
- {
- break;
- }
- else
- {
- // SP has reached max value, exit
- v = Source[SP];
- SP++;
- if (v != 0)
- {
- if ((SP > max) || (DP > maxdp))
- {
- break;
- }
- else
- {
- x++;
- Dest[DP] += (byte)v;
- }
- DP++;
- }
- else
- {
- Count -= 1;
- v = Source[SP];
-
- SP++;
- if ((x + v) > cx)
- {
- v = cx - x;
- }
- x = x + v;
- while (v > 0)
- {
- if ((SP > max) || (DP > maxdp))
- {
- break;
- }
- else
- {
- v -= 1;
- Dest[DP] = 0;
-
- }
- DP++;
- // SP has reached max value, exit
- }
- }
- }
- }
- if ((SP >= max) || (DP >= maxdp))
- {
- return;
- }
- // SP has reached max value, exit
- }
- }
-
- catch (Exception e)
- {
- Console.WriteLine(e.Message);
- }
-
- }
-
- public static void Decode2(byte[] Source, ref byte[] Dest, int cx, int cy, ref int max)
- {
- int SP;
- int DP;
- int y;
- int Count;
- int maxdp;
- ushort Pos;
- maxdp = cx * cy;
- SP = 0;
- DP = 0;
- Pos = 0;
- try
- {
- for (y = 1; y <= cy; y++)
- {
- ReInterpretWordFromBytes(Source[SP], Source[SP + 1], ref Pos);
- Count = Pos - 2;
- SP += 2;
- while (Count > 0)
- {
- Count -= 1;
- if ((SP > max) || (DP > maxdp))
- {
- return;
- }
- // SP has reached max value, exit
- Dest[DP] = Source[SP];
- SP++;
- DP++;
- }
- if ((SP >= max) || (DP >= maxdp))
- {
- return;
- }
- // SP has reached max value, exit
- }
- }
- catch (Exception e)
- {
- Console.WriteLine(e.Message);
}
}
-
- public IEnumerator GetEnumerator()
- {
- return headers.GetEnumerator();
- }
-
- IEnumerator IEnumerable.GetEnumerator()
- {
- return GetEnumerator();
- }
-
- public Size Size { get { return new Size(Width, Height); } }
}
-}
+}
\ No newline at end of file
diff --git a/OpenRA.FileFormats/Graphics/ShpWriter.cs b/OpenRA.FileFormats/Graphics/ShpWriter.cs
deleted file mode 100644
index 9475f02c68..0000000000
--- a/OpenRA.FileFormats/Graphics/ShpWriter.cs
+++ /dev/null
@@ -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.Collections.Generic;
-using System.IO;
-using System.Linq;
-
-namespace OpenRA.FileFormats.Graphics
-{
- // format80-only SHP writer
-
- public static class ShpWriter
- {
- public static void Write(Stream s, int width, int height, IEnumerable frames)
- {
- var compressedFrames = frames.Select(f => Format80.Encode(f)).ToArray();
-
- // note: end-of-file and all-zeroes headers
- var dataOffset = 14 + (compressedFrames.Length + 2) * ImageHeader.SizeOnDisk;
-
- using (var bw = new BinaryWriter(s))
- {
- bw.Write((ushort)compressedFrames.Length);
- bw.Write((ushort)0); // unused
- bw.Write((ushort)0); // unused
- bw.Write((ushort)width);
- bw.Write((ushort)height);
- bw.Write((uint)0); // unused
-
- foreach (var f in compressedFrames)
- {
- var ih = new ImageHeader { Format = Format.Format80, Offset = (uint)dataOffset };
- dataOffset += f.Length;
-
- ih.WriteTo(bw);
- }
-
- var eof = new ImageHeader { Offset = (uint)dataOffset };
- eof.WriteTo(bw);
-
- var allZeroes = new ImageHeader { };
- allZeroes.WriteTo(bw);
-
- foreach (var f in compressedFrames)
- bw.Write(f);
- }
- }
- }
-}
diff --git a/OpenRA.FileFormats/Graphics/SpriteSource.cs b/OpenRA.FileFormats/Graphics/SpriteSource.cs
new file mode 100644
index 0000000000..9c7f25a672
--- /dev/null
+++ b/OpenRA.FileFormats/Graphics/SpriteSource.cs
@@ -0,0 +1,236 @@
+#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.Collections.Generic;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+
+namespace OpenRA.FileFormats
+{
+ public interface ISpriteFrame
+ {
+ Size Size { get; }
+ Size FrameSize { get; }
+ float2 Offset { get; }
+ byte[] Data { get; }
+ }
+
+ public interface ISpriteSource
+ {
+ IEnumerable Frames { get; }
+ bool CacheWhenLoadingTileset { get; }
+ }
+
+ public enum SpriteType { Unknown, ShpTD, ShpTS, ShpD2, TmpTD, TmpRA, R8 }
+ public static class SpriteSource
+ {
+ static bool IsTmpRA(Stream s)
+ {
+ var start = s.Position;
+
+ s.Position += 20;
+ var a = s.ReadUInt32();
+ s.Position += 2;
+ var b = s.ReadUInt16();
+
+ s.Position = start;
+ return a == 0 && b == 0x2c73;
+ }
+
+ static bool IsTmpTD(Stream s)
+ {
+ var start = s.Position;
+
+ s.Position += 16;
+ var a = s.ReadUInt32();
+ var b = s.ReadUInt32();
+
+ s.Position = start;
+ return a == 0 && b == 0x0D1AFFFF;
+ }
+
+ static bool IsShpTS(Stream s)
+ {
+ var start = s.Position;
+
+ // First word is zero
+ if (s.ReadUInt16() != 0)
+ {
+ s.Position = start;
+ return false;
+ }
+
+ // Sanity Check the image count
+ s.Position += 4;
+ var imageCount = s.ReadUInt16();
+ if (s.Position + 24 * imageCount > s.Length)
+ {
+ s.Position = start;
+ return false;
+ }
+
+ // Check the size and format flag
+ // Some files define bogus frames, so loop until we find a valid one
+ s.Position += 4;
+ ushort w, h, f = 0;
+ byte type;
+ do
+ {
+ w = s.ReadUInt16();
+ h = s.ReadUInt16();
+ type = s.ReadUInt8();
+ }
+ while (w == 0 && h == 0 && f++ < imageCount);
+
+ s.Position = start;
+ return type < 4;
+ }
+
+ static bool IsShpTD(Stream s)
+ {
+ var start = s.Position;
+
+ // First word is the image count
+ var imageCount = s.ReadUInt16();
+ if (imageCount == 0)
+ {
+ s.Position = start;
+ return false;
+ }
+
+ // Last offset should point to the end of file
+ var finalOffset = start + 14 + 8 * imageCount;
+ if (finalOffset > s.Length)
+ {
+ s.Position = start;
+ return false;
+ }
+
+ s.Position = finalOffset;
+ var eof = s.ReadUInt32();
+ if (eof != s.Length)
+ {
+ s.Position = start;
+ return false;
+ }
+
+ // Check the format flag on the first frame
+ s.Position = start + 17;
+ var b = s.ReadUInt8();
+
+ s.Position = start;
+ return b == 0x20 || b == 0x40 || b == 0x80;
+ }
+
+ static bool IsShpD2(Stream s)
+ {
+ var start = s.Position;
+
+ // First word is the image count
+ var imageCount = s.ReadUInt16();
+ if (imageCount == 0)
+ {
+ s.Position = start;
+ return false;
+ }
+
+ // Test for two vs four byte offset
+ var testOffset = s.ReadUInt32();
+ var offsetSize = (testOffset & 0xFF0000) > 0 ? 2 : 4;
+
+ // Last offset should point to the end of file
+ var finalOffset = start + 2 + offsetSize * imageCount;
+ if (finalOffset > s.Length)
+ {
+ s.Position = start;
+ return false;
+ }
+
+ s.Position = finalOffset;
+ var eof = offsetSize == 2 ? s.ReadUInt16() : s.ReadUInt32();
+ if (eof + 2 != s.Length)
+ {
+ s.Position = start;
+ return false;
+ }
+
+ // Check the format flag on the first frame
+ var b = s.ReadUInt16();
+ s.Position = start;
+ return b == 5 || b <= 3;
+ }
+
+ static bool IsR8(Stream s)
+ {
+ var start = s.Position;
+
+ // First byte is nonzero
+ if (s.ReadUInt8() == 0)
+ {
+ s.Position = start;
+ return false;
+ }
+
+ // Check the format of the first frame
+ s.Position = start + 25;
+ var d = s.ReadUInt8();
+
+ s.Position = start;
+ return d == 8;
+ }
+
+ public static SpriteType DetectSpriteType(Stream s)
+ {
+ if (IsShpTD(s))
+ return SpriteType.ShpTD;
+
+ if (IsShpTS(s))
+ return SpriteType.ShpTS;
+
+ if (IsR8(s))
+ return SpriteType.R8;
+
+ if (IsTmpRA(s))
+ return SpriteType.TmpRA;
+
+ if (IsTmpTD(s))
+ return SpriteType.TmpTD;
+
+ if (IsShpD2(s))
+ return SpriteType.ShpD2;
+
+ return SpriteType.Unknown;
+ }
+
+ public static ISpriteSource LoadSpriteSource(Stream s, string filename)
+ {
+ var type = DetectSpriteType(s);
+ switch (type)
+ {
+ case SpriteType.ShpTD:
+ return new ShpReader(s);
+ case SpriteType.ShpTS:
+ return new ShpTSReader(s);
+ case SpriteType.R8:
+ return new R8Reader(s);
+ case SpriteType.TmpRA:
+ return new TmpRAReader(s);
+ case SpriteType.TmpTD:
+ return new TmpTDReader(s);
+ case SpriteType.ShpD2:
+ return new ShpD2Reader(s);
+ case SpriteType.Unknown:
+ default:
+ throw new InvalidDataException(filename + " is not a valid sprite file");
+ }
+ }
+ }
+}
diff --git a/OpenRA.FileFormats/Graphics/TmpRAReader.cs b/OpenRA.FileFormats/Graphics/TmpRAReader.cs
new file mode 100644
index 0000000000..ce627eacac
--- /dev/null
+++ b/OpenRA.FileFormats/Graphics/TmpRAReader.cs
@@ -0,0 +1,50 @@
+#region Copyright & License Information
+/*
+ * Copyright 2007-2013 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.Collections.Generic;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+
+namespace OpenRA.FileFormats
+{
+ public class TmpRAReader : ISpriteSource
+ {
+ readonly List tiles = new List();
+ public IEnumerable Frames { get { return tiles.Cast(); } }
+ public bool CacheWhenLoadingTileset { get { return false; } }
+
+ public TmpRAReader(Stream s)
+ {
+ var width = s.ReadUInt16();
+ var height = s.ReadUInt16();
+ var size = new Size(width, height);
+
+ s.Position += 12;
+ var imgStart = s.ReadUInt32();
+ s.Position += 8;
+ var indexEnd = s.ReadInt32();
+ s.Position += 4;
+ var indexStart = s.ReadInt32();
+
+ s.Position = indexStart;
+ foreach (byte b in s.ReadBytes(indexEnd - indexStart))
+ {
+ if (b != 255)
+ {
+ s.Position = imgStart + b * width * height;
+ tiles.Add(new TmpTile(s.ReadBytes(width * height), size));
+ }
+ else
+ tiles.Add(new TmpTile(null, size));
+ }
+ }
+ }
+}
diff --git a/OpenRA.FileFormats/Graphics/TmpTDReader.cs b/OpenRA.FileFormats/Graphics/TmpTDReader.cs
new file mode 100644
index 0000000000..fe73203966
--- /dev/null
+++ b/OpenRA.FileFormats/Graphics/TmpTDReader.cs
@@ -0,0 +1,68 @@
+#region Copyright & License Information
+/*
+ * Copyright 2007-2013 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.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.IO;
+
+namespace OpenRA.FileFormats
+{
+ public class TmpTile : ISpriteFrame
+ {
+ public Size Size { get; private set; }
+ public Size FrameSize { get; private set; }
+ public float2 Offset { get { return float2.Zero; } }
+ public byte[] Data { get; set; }
+
+ public TmpTile(byte[] data, Size size)
+ {
+ FrameSize = size;
+ Data = data;
+
+ if (data == null)
+ Data = new byte[0];
+ else
+ Size = size;
+ }
+ }
+
+ public class TmpTDReader : ISpriteSource
+ {
+ readonly List tiles = new List();
+ public IEnumerable Frames { get { return tiles.Cast(); } }
+ public bool CacheWhenLoadingTileset { get { return false; } }
+
+ public TmpTDReader(Stream s)
+ {
+ var width = s.ReadUInt16();
+ var height = s.ReadUInt16();
+ var size = new Size(width, height);
+
+ s.Position += 8;
+ var imgStart = s.ReadUInt32();
+ s.Position += 8;
+ var indexEnd = s.ReadInt32();
+ var indexStart = s.ReadInt32();
+
+ s.Position = indexStart;
+ foreach (byte b in s.ReadBytes(indexEnd - indexStart))
+ {
+ if (b != 255)
+ {
+ s.Position = imgStart + b * width * height;
+ tiles.Add(new TmpTile(s.ReadBytes(width * height), size));
+ }
+ else
+ tiles.Add(new TmpTile(null, size));
+ }
+ }
+ }
+}
diff --git a/OpenRA.FileFormats/Map/Terrain.cs b/OpenRA.FileFormats/Map/Terrain.cs
deleted file mode 100644
index 92fbacb2df..0000000000
--- a/OpenRA.FileFormats/Map/Terrain.cs
+++ /dev/null
@@ -1,77 +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.Collections.Generic;
-using System.IO;
-
-namespace OpenRA.FileFormats
-{
- public class Terrain
- {
- public readonly List TileBitmapBytes = new List();
- public readonly int Width;
- public readonly int Height;
-
- public Terrain(Stream s)
- {
- // Try loading as a cnc .tem
- Width = s.ReadUInt16();
- Height = s.ReadUInt16();
-
- /*NumTiles = */s.ReadUInt16();
- /*Zero1 = */s.ReadUInt16();
- /*uint Size = */s.ReadUInt32();
- var imgStart = s.ReadUInt32();
- /*Zero2 = */s.ReadUInt32();
-
- int indexEnd, indexStart;
-
- // ID1 = FFFFh for cnc
- if (s.ReadUInt16() == 65535)
- {
- /*ID2 = */s.ReadUInt16();
- indexEnd = s.ReadInt32();
- indexStart = s.ReadInt32();
- }
- else
- {
- // Load as a ra .tem
- s.Position = 0;
- Width = s.ReadUInt16();
- Height = s.ReadUInt16();
-
- /*NumTiles = */s.ReadUInt16();
- s.ReadUInt16();
- /*XDim = */s.ReadUInt16();
- /*YDim = */s.ReadUInt16();
- /*uint FileSize = */s.ReadUInt32();
- imgStart = s.ReadUInt32();
- s.ReadUInt32();
- s.ReadUInt32();
- indexEnd = s.ReadInt32();
- s.ReadUInt32();
- indexStart = s.ReadInt32();
- }
-
- s.Position = indexStart;
-
- foreach (byte b in s.ReadBytes(indexEnd - indexStart))
- {
- if (b != 255)
- {
- s.Position = imgStart + b * Width * Height;
- TileBitmapBytes.Add(s.ReadBytes(Width * Height));
- }
- else
- TileBitmapBytes.Add(null);
- }
- }
- }
-}
diff --git a/OpenRA.FileFormats/OpenRA.FileFormats.csproj b/OpenRA.FileFormats/OpenRA.FileFormats.csproj
index f8f42f2b1c..e867a1dc03 100644
--- a/OpenRA.FileFormats/OpenRA.FileFormats.csproj
+++ b/OpenRA.FileFormats/OpenRA.FileFormats.csproj
@@ -90,19 +90,16 @@
-
-
-
@@ -144,7 +141,6 @@
-
@@ -153,6 +149,10 @@
+
+
+
+
diff --git a/OpenRA.Game/Graphics/SheetBuilder.cs b/OpenRA.Game/Graphics/SheetBuilder.cs
index a2ba52d535..0cee8661ef 100644
--- a/OpenRA.Game/Graphics/SheetBuilder.cs
+++ b/OpenRA.Game/Graphics/SheetBuilder.cs
@@ -10,6 +10,7 @@
using System;
using System.Drawing;
+using OpenRA.FileFormats;
using OpenRA.FileFormats.Graphics;
namespace OpenRA.Graphics
@@ -52,9 +53,14 @@ namespace OpenRA.Graphics
this.allocateSheet = allocateSheet;
}
+ public Sprite Add(ISpriteFrame frame) { return Add(frame.Data, frame.Size, frame.Offset); }
public Sprite Add(byte[] src, Size size) { return Add(src, size, float2.Zero); }
public Sprite Add(byte[] src, Size size, float2 spriteOffset)
{
+ // Don't bother allocating empty sprites
+ if (size.Width == 0 || size.Height == 0)
+ return new Sprite(current, Rectangle.Empty, spriteOffset, channel, BlendMode.Alpha);
+
var rect = Allocate(size, spriteOffset);
Util.FastCopyIntoChannel(rect, src);
current.CommitData();
diff --git a/OpenRA.Game/Graphics/SpriteLoader.cs b/OpenRA.Game/Graphics/SpriteLoader.cs
index ff14eca590..ad34831633 100644
--- a/OpenRA.Game/Graphics/SpriteLoader.cs
+++ b/OpenRA.Game/Graphics/SpriteLoader.cs
@@ -16,39 +16,25 @@ namespace OpenRA.Graphics
{
public class SpriteLoader
{
- public SpriteLoader(string[] exts, SheetBuilder sheetBuilder)
- {
- SheetBuilder = sheetBuilder;
- this.exts = exts;
- sprites = new Cache(LoadSprites);
- }
-
readonly SheetBuilder SheetBuilder;
readonly Cache sprites;
readonly string[] exts;
- Sprite[] LoadSprites(string filename)
+ public SpriteLoader(string[] exts, SheetBuilder sheetBuilder)
{
- // TODO: Cleanly abstract file type detection
- if (filename.ToLower().EndsWith("r8"))
- {
- var r8 = new R8Reader(FileSystem.Open(filename));
- return r8.Select(a => SheetBuilder.Add(a.Image, a.Size, a.Offset)).ToArray();
- }
+ SheetBuilder = sheetBuilder;
- BinaryReader reader = new BinaryReader(FileSystem.OpenWithExts(filename, exts));
+ // Include extension-less version
+ this.exts = exts.Append("").ToArray();
+ sprites = new Cache(CacheSpriteFrames);
+ }
- var ImageCount = reader.ReadUInt16();
- if (ImageCount == 0)
- {
- var shp = new ShpTSReader(FileSystem.OpenWithExts(filename, exts));
- return shp.Select(a => SheetBuilder.Add(a.Image, shp.Size)).ToArray();
- }
- else
- {
- var shp = new ShpReader(FileSystem.OpenWithExts(filename, exts));
- return shp.Frames.Select(a => SheetBuilder.Add(a.Image, shp.Size)).ToArray();
- }
+ Sprite[] CacheSpriteFrames(string filename)
+ {
+ var stream = FileSystem.OpenWithExts(filename, exts);
+ return SpriteSource.LoadSpriteSource(stream, filename).Frames
+ .Select(a => SheetBuilder.Add(a))
+ .ToArray();
}
public Sprite[] LoadAllSprites(string filename) { return sprites[filename]; }
diff --git a/OpenRA.Game/Graphics/Theater.cs b/OpenRA.Game/Graphics/Theater.cs
index 48bfc1451f..fdbb5908b8 100644
--- a/OpenRA.Game/Graphics/Theater.cs
+++ b/OpenRA.Game/Graphics/Theater.cs
@@ -11,6 +11,7 @@
using System;
using System.Collections.Generic;
using System.Drawing;
+using System.IO;
using System.Linq;
using OpenRA.FileFormats;
@@ -22,27 +23,31 @@ namespace OpenRA.Graphics
Dictionary templates;
Sprite missingTile;
- Sprite[] LoadTemplate(string filename, string[] exts, Cache r8Cache, int[] frames)
+ Sprite[] LoadTemplate(string filename, string[] exts, Dictionary sourceCache, int[] frames)
{
- if (exts.Contains(".R8") && FileSystem.Exists(filename+".R8"))
+ ISpriteSource source;
+ if (!sourceCache.ContainsKey(filename))
{
- return frames.Select(f =>
- {
- if (f < 0)
- return null;
+ using (var s = FileSystem.OpenWithExts(filename, exts))
+ source = SpriteSource.LoadSpriteSource(s, filename);
- var image = r8Cache[filename][f];
- return sheetBuilder.Add(image.Image, new Size(image.Size.Width, image.Size.Height));
- }).ToArray();
+ if (source.CacheWhenLoadingTileset)
+ sourceCache.Add(filename, source);
+ }
+ else
+ source = sourceCache[filename];
+
+ if (frames != null)
+ {
+ var ret = new List();
+ var srcFrames = source.Frames.ToArray();
+ foreach (var i in frames)
+ ret.Add(sheetBuilder.Add(srcFrames[i]));
+
+ return ret.ToArray();
}
- using (var s = FileSystem.OpenWithExts(filename, exts))
- {
- var t = new Terrain(s);
- return t.TileBitmapBytes
- .Select(b => b != null ? sheetBuilder.Add(b, new Size(t.Width, t.Height)) : null)
- .ToArray();
- }
+ return source.Frames.Select(f => sheetBuilder.Add(f)).ToArray();
}
public Theater(TileSet tileset)
@@ -57,11 +62,11 @@ namespace OpenRA.Graphics
return new Sheet(new Size(tileset.SheetSize, tileset.SheetSize));
};
- var r8Cache = new Cache(s => new R8Reader(FileSystem.OpenWithExts(s, ".R8")));
+ var sourceCache = new Dictionary();
templates = new Dictionary();
sheetBuilder = new SheetBuilder(SheetType.Indexed, allocate);
foreach (var t in tileset.Templates)
- templates.Add(t.Value.Id, LoadTemplate(t.Value.Image, tileset.Extensions, r8Cache, t.Value.Frames));
+ templates.Add(t.Value.Id, LoadTemplate(t.Value.Image, tileset.Extensions, sourceCache, t.Value.Frames));
// 1x1px transparent tile
missingTile = sheetBuilder.Add(new byte[1], new Size(1, 1));
@@ -70,11 +75,13 @@ namespace OpenRA.Graphics
public Sprite TileSprite(TileReference r)
{
Sprite[] template;
- if (templates.TryGetValue(r.Type, out template))
- if (template.Length > r.Index && template[r.Index] != null)
- return template[r.Index];
+ if (!templates.TryGetValue(r.Type, out template))
+ return missingTile;
- return missingTile;
+ if (r.Index >= template.Length)
+ return missingTile;
+
+ return template[r.Index];
}
public Sheet Sheet { get { return sheetBuilder.Current; } }
diff --git a/OpenRA.Game/ModData.cs b/OpenRA.Game/ModData.cs
index 1414d405de..48ae466e28 100755
--- a/OpenRA.Game/ModData.cs
+++ b/OpenRA.Game/ModData.cs
@@ -75,7 +75,7 @@ namespace OpenRA
ChromeMetrics.Initialize(Manifest.ChromeMetrics);
ChromeProvider.Initialize(Manifest.Chrome);
SheetBuilder = new SheetBuilder(SheetType.Indexed);
- SpriteLoader = new SpriteLoader(new string[] { ".shp" }, SheetBuilder);
+ SpriteLoader = new SpriteLoader(new string[0], SheetBuilder);
VoxelLoader = new VoxelLoader();
CursorProvider.Initialize(Manifest.Cursors);
}
diff --git a/OpenRA.Game/Widgets/ShpImageWidget.cs b/OpenRA.Game/Widgets/ShpImageWidget.cs
index 4c8cb912a7..5c1dabaa0b 100644
--- a/OpenRA.Game/Widgets/ShpImageWidget.cs
+++ b/OpenRA.Game/Widgets/ShpImageWidget.cs
@@ -56,6 +56,7 @@ namespace OpenRA.Widgets
Sprite sprite = null;
string cachedImage = null;
int cachedFrame = -1;
+ float2 cachedOffset = float2.Zero;
public override void Draw()
{
@@ -68,9 +69,10 @@ namespace OpenRA.Widgets
sprite = Game.modData.SpriteLoader.LoadAllSprites(image)[frame];
cachedImage = image;
cachedFrame = frame;
+ cachedOffset = 0.5f * (new float2(RenderBounds.Size) - sprite.size);
}
- Game.Renderer.SpriteRenderer.DrawSprite(sprite, RenderOrigin, worldRenderer.Palette(palette));
+ Game.Renderer.SpriteRenderer.DrawSprite(sprite, RenderOrigin + cachedOffset, worldRenderer.Palette(palette));
}
public int FrameCount
diff --git a/OpenRA.Game/Widgets/WidgetUtils.cs b/OpenRA.Game/Widgets/WidgetUtils.cs
index 0ab460b639..1cfbefb13f 100644
--- a/OpenRA.Game/Widgets/WidgetUtils.cs
+++ b/OpenRA.Game/Widgets/WidgetUtils.cs
@@ -29,14 +29,14 @@ namespace OpenRA.Widgets
Game.Renderer.RgbaSpriteRenderer.DrawSprite(s,pos);
}
- public static void DrawSHP(Sprite s, float2 pos, WorldRenderer wr)
+ public static void DrawSHPCentered(Sprite s, float2 pos, WorldRenderer wr)
{
- Game.Renderer.SpriteRenderer.DrawSprite(s, pos, wr.Palette("chrome"));
+ Game.Renderer.SpriteRenderer.DrawSprite(s, pos - 0.5f * s.size, wr.Palette("chrome"));
}
- public static void DrawSHP(Sprite s, float2 pos, WorldRenderer wr, float2 size)
+ public static void DrawSHPCentered(Sprite s, float2 pos, WorldRenderer wr, float scale)
{
- Game.Renderer.SpriteRenderer.DrawSprite(s, pos, wr.Palette("chrome"), size);
+ Game.Renderer.SpriteRenderer.DrawSprite(s, pos - 0.5f * scale * s.size, wr.Palette("chrome"), scale * s.size);
}
public static void DrawPanel(string collection, Rectangle Bounds)
diff --git a/OpenRA.Mods.Cnc/Widgets/ProductionPaletteWidget.cs b/OpenRA.Mods.Cnc/Widgets/ProductionPaletteWidget.cs
index 8dea9c77eb..3e299090c8 100755
--- a/OpenRA.Mods.Cnc/Widgets/ProductionPaletteWidget.cs
+++ b/OpenRA.Mods.Cnc/Widgets/ProductionPaletteWidget.cs
@@ -197,11 +197,14 @@ namespace OpenRA.Mods.Cnc.Widgets
public override void Draw()
{
+ var iconSize = new float2(64, 48);
+ var iconOffset = 0.5f * iconSize;
+
overlayFont = Game.Renderer.Fonts["TinyBold"];
- timeOffset = new float2(32, 24) - overlayFont.Measure(WidgetUtils.FormatTime(0)) / 2;
+ timeOffset = iconOffset - overlayFont.Measure(WidgetUtils.FormatTime(0)) / 2;
queuedOffset = new float2(4, 2);
- holdOffset = new float2(32, 24) - overlayFont.Measure(HoldText) / 2;
- readyOffset = new float2(32, 24) - overlayFont.Measure(ReadyText) / 2;
+ holdOffset = iconOffset - overlayFont.Measure(HoldText) / 2;
+ readyOffset = iconOffset - overlayFont.Measure(ReadyText) / 2;
if (CurrentQueue == null)
return;
@@ -215,7 +218,7 @@ namespace OpenRA.Mods.Cnc.Widgets
// Icons
foreach (var icon in icons.Values)
{
- WidgetUtils.DrawSHP(icon.Sprite, icon.Pos, worldRenderer);
+ WidgetUtils.DrawSHPCentered(icon.Sprite, icon.Pos + iconOffset, worldRenderer);
// Build progress
if (icon.Queued.Count > 0)
@@ -225,10 +228,10 @@ namespace OpenRA.Mods.Cnc.Widgets
() => (first.TotalTime - first.RemainingTime)
* (clock.CurrentSequence.Length - 1) / first.TotalTime);
clock.Tick();
- WidgetUtils.DrawSHP(clock.Image, icon.Pos, worldRenderer);
+ WidgetUtils.DrawSHPCentered(clock.Image, icon.Pos + iconOffset, worldRenderer);
}
else if (!buildableItems.Any(a => a.Name == icon.Name))
- WidgetUtils.DrawSHP(cantBuild.Image, icon.Pos, worldRenderer);
+ WidgetUtils.DrawSHPCentered(cantBuild.Image, icon.Pos + iconOffset, worldRenderer);
}
// Overlays
diff --git a/OpenRA.Mods.Cnc/Widgets/SupportPowersWidget.cs b/OpenRA.Mods.Cnc/Widgets/SupportPowersWidget.cs
index dec4cd1389..3a970da1b9 100755
--- a/OpenRA.Mods.Cnc/Widgets/SupportPowersWidget.cs
+++ b/OpenRA.Mods.Cnc/Widgets/SupportPowersWidget.cs
@@ -89,10 +89,13 @@ namespace OpenRA.Mods.Cnc.Widgets
public override void Draw()
{
+ var iconSize = new float2(64, 48);
+ var iconOffset = 0.5f * iconSize;
+
overlayFont = Game.Renderer.Fonts["TinyBold"];
- holdOffset = new float2(32, 24) - overlayFont.Measure(HoldText) / 2;
- readyOffset = new float2(32, 24) - overlayFont.Measure(ReadyText) / 2;
- timeOffset = new float2(32, 24) - overlayFont.Measure(WidgetUtils.FormatTime(0)) / 2;
+ holdOffset = iconOffset - overlayFont.Measure(HoldText) / 2;
+ readyOffset = iconOffset - overlayFont.Measure(ReadyText) / 2;
+ timeOffset = iconOffset - overlayFont.Measure(WidgetUtils.FormatTime(0)) / 2;
// Background
foreach (var rect in icons.Keys)
@@ -101,14 +104,14 @@ namespace OpenRA.Mods.Cnc.Widgets
// Icons
foreach (var p in icons.Values)
{
- WidgetUtils.DrawSHP(p.Sprite, p.Pos, worldRenderer);
+ WidgetUtils.DrawSHPCentered(p.Sprite, p.Pos + iconOffset, worldRenderer);
// Charge progress
clock.PlayFetchIndex("idle",
() => (p.Power.TotalTime - p.Power.RemainingTime)
* (clock.CurrentSequence.Length - 1) / p.Power.TotalTime);
clock.Tick();
- WidgetUtils.DrawSHP(clock.Image, p.Pos, worldRenderer);
+ WidgetUtils.DrawSHPCentered(clock.Image, p.Pos + iconOffset, worldRenderer);
}
// Overlay
diff --git a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj
index eba63a2dde..8bfeee8316 100644
--- a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj
+++ b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj
@@ -33,9 +33,9 @@
true
- true
+ True
full
- false
+ False
bin\Debug\
DEBUG;TRACE
prompt
@@ -47,17 +47,17 @@
AllRules.ruleset
- true
+ True
pdbonly
- true
+ True
TRACE
prompt
4
bin\Release\
AllRules.ruleset
- true
+ True
@@ -70,14 +70,13 @@
-
- False
- ..\thirdparty\ICSharpCode.SharpZipLib.dll
-
..\thirdparty\Mono.Nat.dll
False
+
+ ..\thirdparty\ICSharpCode.SharpZipLib.dll
+
@@ -444,7 +443,6 @@
-
@@ -481,7 +479,7 @@
- {e915a0a4-2641-4f7e-8a88-8f123fa88bf1}
+ {E915A0A4-2641-4F7E-8A88-8F123FA88BF1}
LuaInterface
@@ -495,13 +493,9 @@
False
- {85b48234-8b31-4be6-af9c-665cc6866841}
+ {85B48234-8B31-4BE6-AF9C-665CC6866841}
OpenRA.Irc
-
- {F33337BE-CB69-4B24-850F-07D23E408DDF}
- OpenRA.Utility
-
{021DDD6A-A608-424C-9A9A-252D8A9989E0}
GeoIP
diff --git a/OpenRA.Mods.RA/Widgets/BuildPaletteWidget.cs b/OpenRA.Mods.RA/Widgets/BuildPaletteWidget.cs
index db0fe250f4..e6fd815b5c 100755
--- a/OpenRA.Mods.RA/Widgets/BuildPaletteWidget.cs
+++ b/OpenRA.Mods.RA/Widgets/BuildPaletteWidget.cs
@@ -203,6 +203,7 @@ namespace OpenRA.Mods.RA.Widgets
string paletteCollection = "palette-" + world.LocalPlayer.Country.Race;
float2 origin = new float2(paletteOrigin.X + 9, paletteOrigin.Y + 9);
+ var iconOffset = 0.5f * new float2(IconWidth, IconHeight);
var x = 0;
var y = 0;
@@ -233,7 +234,7 @@ namespace OpenRA.Mods.RA.Widgets
var drawPos = new float2(rect.Location);
var icon = new Animation(RenderSimple.GetImage(item));
icon.Play(item.Traits.Get().Icon);
- WidgetUtils.DrawSHP(icon.Image, drawPos, worldRenderer);
+ WidgetUtils.DrawSHPCentered(icon.Image, drawPos + iconOffset, worldRenderer);
var firstOfThis = queue.AllQueued().FirstOrDefault(a => a.Item == item.Name);
@@ -248,7 +249,7 @@ namespace OpenRA.Mods.RA.Widgets
() => (firstOfThis.TotalTime - firstOfThis.RemainingTime)
* (clock.CurrentSequence.Length - 1) / firstOfThis.TotalTime);
clock.Tick();
- WidgetUtils.DrawSHP(clock.Image, drawPos, worldRenderer);
+ WidgetUtils.DrawSHPCentered(clock.Image, drawPos + iconOffset, worldRenderer);
if (queue.CurrentItem() == firstOfThis)
textBits.Add(Pair.New(overlayPos, GetOverlayForItem(firstOfThis)));
@@ -269,7 +270,7 @@ namespace OpenRA.Mods.RA.Widgets
if (x != 0) y++;
foreach (var ob in overlayBits)
- WidgetUtils.DrawSHP(ob.First, ob.Second, worldRenderer);
+ WidgetUtils.DrawSHPCentered(ob.First, ob.Second + iconOffset, worldRenderer);
var font = Game.Renderer.Fonts["TinyBold"];
foreach (var tb in textBits)
diff --git a/OpenRA.Mods.RA/Widgets/Logic/AssetBrowserLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/AssetBrowserLogic.cs
index 2c7adaaad3..44f88cbe9e 100644
--- a/OpenRA.Mods.RA/Widgets/Logic/AssetBrowserLogic.cs
+++ b/OpenRA.Mods.RA/Widgets/Logic/AssetBrowserLogic.cs
@@ -35,6 +35,8 @@ namespace OpenRA.Mods.RA.Widgets.Logic
PaletteFromFile currentPalette;
+ static readonly string[] AllowedExtensions = { ".shp", ".r8", ".tem", ".des", ".sno", ".int" };
+
[ObjectCreator.UseCtor]
public AssetBrowserLogic(Widget widget, Action onExit, World world)
{
@@ -60,6 +62,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
var paletteDropDown = panel.Get("PALETTE_SELECTOR");
paletteDropDown.OnMouseDown = _ => ShowPaletteDropdown(paletteDropDown, world);
+ paletteDropDown.GetText = () => currentPalette.Name;
var colorPreview = panel.Get("COLOR_MANAGER");
colorPreview.Color = Game.Settings.Player.Color;
@@ -80,7 +83,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
frameSlider.OnChange += x => { spriteWidget.Frame = (int)Math.Round(x); };
frameSlider.GetValue = () => spriteWidget.Frame;
- panel.Get("FRAME_COUNT").GetText = () => "{0}/{1}".F(spriteWidget.Frame, spriteWidget.FrameCount);
+ panel.Get("FRAME_COUNT").GetText = () => "{0} / {1}".F(spriteWidget.Frame + 1, spriteWidget.FrameCount + 1);
playButton = panel.Get("BUTTON_PLAY");
playButton.OnClick = () =>
@@ -118,96 +121,15 @@ namespace OpenRA.Mods.RA.Widgets.Logic
template = panel.Get("ASSET_TEMPLATE");
PopulateAssetList();
- var modID = Game.modData.Manifest.Mod.Id;
-
- // TODO: This should not invoke the OpenRA.Utility.exe, but use it's functions directly.
- // TODO: Does not work with SHP(TS) yet?!
- panel.Get("EXPORT_BUTTON").OnClick = () =>
- {
- var ExtractGameFiles = new string[][]
- {
- new string[] { "--extract", modID, currentPalette.Filename, "--userdir" },
- new string[] { "--extract", modID, "{0}.shp".F(spriteWidget.Image), "--userdir" },
- };
-
- var ExportToPng = new string[][]
- {
- new string[] { "--png", Platform.SupportDir + "{0}.shp".F(spriteWidget.Image), Platform.SupportDir + currentPalette.Filename },
- };
-
- var ImportFromPng = new string[][] { };
-
- var args = new WidgetArgs()
- {
- { "ExtractGameFiles", ExtractGameFiles },
- { "ExportToPng", ExportToPng },
- { "ImportFromPng", ImportFromPng }
- };
-
- Ui.OpenWindow("CONVERT_ASSETS_PANEL", args);
- };
-
- panel.Get("EXTRACT_BUTTON").OnClick = () =>
- {
- var ExtractGameFilesList = new List();
- var ExportToPngList = new List();
-
- ExtractGameFilesList.Add(new string[] { "--extract", modID, currentPalette.Filename, "--userdir" });
-
- foreach (var shp in availableShps)
- {
- ExtractGameFilesList.Add(new string[] { "--extract", modID, shp, "--userdir" });
- ExportToPngList.Add(new string[] { "--png", Platform.SupportDir + shp, Platform.SupportDir + currentPalette.Filename });
- Console.WriteLine(Platform.SupportDir + shp);
- }
-
- var ExtractGameFiles = ExtractGameFilesList.ToArray();
- var ExportToPng = ExportToPngList.ToArray();
- var ImportFromPng = new string[][] { };
-
- var args = new WidgetArgs()
- {
- { "ExtractGameFiles", ExtractGameFiles },
- { "ExportToPng", ExportToPng },
- { "ImportFromPng", ImportFromPng }
- };
-
- Ui.OpenWindow("CONVERT_ASSETS_PANEL", args);
- };
-
- panel.Get("IMPORT_BUTTON").OnClick = () =>
- {
- var imageSizeInput = panel.Get("IMAGE_SIZE_INPUT");
- var imageFilename = panel.Get("IMAGE_FILENAME_INPUT");
-
- var ExtractGameFiles = new string[][] { };
- var ExportToPng = new string[][] { };
- var ImportFromPng = new string[][]
- {
- new string[] { "--shp", Platform.SupportDir + imageFilename.Text, imageSizeInput.Text },
- };
-
- var args = new WidgetArgs()
- {
- { "ExtractGameFiles", ExtractGameFiles },
- { "ExportToPng", ExportToPng },
- { "ImportFromPng", ImportFromPng }
- };
-
- Ui.OpenWindow("CONVERT_ASSETS_PANEL", args);
- };
-
panel.Get("CLOSE_BUTTON").OnClick = () => { Ui.CloseWindow(); onExit(); };
}
void AddAsset(ScrollPanelWidget list, string filepath, ScrollItemWidget template)
{
- var r8 = filepath.EndsWith(".r8", true, CultureInfo.InvariantCulture);
- var filename = Path.GetFileName(filepath);
- var sprite = r8 ? filename : Path.GetFileNameWithoutExtension(filepath);
+ var filename = Path.GetFileName(filepath);
var item = ScrollItemWidget.Setup(template,
- () => spriteWidget.Image == sprite,
- () => {filenameInput.Text = filename; LoadAsset(filename); });
+ () => spriteWidget.Image == filename,
+ () => { filenameInput.Text = filename; LoadAsset(filename); });
item.Get("TITLE").GetText = () => filepath;
list.AddChild(item);
@@ -221,11 +143,8 @@ namespace OpenRA.Mods.RA.Widgets.Logic
if (!FileSystem.Exists(filename))
return false;
- var r8 = filename.EndsWith(".r8", true, CultureInfo.InvariantCulture);
- var sprite = r8 ? filename : Path.GetFileNameWithoutExtension(filename);
-
spriteWidget.Frame = 0;
- spriteWidget.Image = sprite;
+ spriteWidget.Image = filename;
frameSlider.MaximumValue = (float)spriteWidget.FrameCount;
frameSlider.Ticks = spriteWidget.FrameCount + 1;
return true;
@@ -265,7 +184,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
var files = assetSource.AllFileNames();
foreach (var file in files)
{
- if (file.EndsWith(".shp", true, CultureInfo.InvariantCulture) || file.EndsWith(".r8", true, CultureInfo.InvariantCulture))
+ if (AllowedExtensions.Any(ext => file.EndsWith(ext, true, CultureInfo.InvariantCulture)))
{
AddAsset(assetList, file, template);
availableShps.Add(file);
@@ -278,8 +197,8 @@ namespace OpenRA.Mods.RA.Widgets.Logic
Func setupItem = (palette, itemTemplate) =>
{
var item = ScrollItemWidget.Setup(itemTemplate,
- () => currentPalette.Name == palette.Name,
- () => { currentPalette = palette; spriteWidget.Palette = currentPalette.Name; });
+ () => currentPalette.Name == palette.Name,
+ () => { currentPalette = palette; spriteWidget.Palette = currentPalette.Name; });
item.Get("LABEL").GetText = () => palette.Name;
return item;
};
diff --git a/OpenRA.Mods.RA/Widgets/Logic/ConvertGameFilesLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/ConvertGameFilesLogic.cs
deleted file mode 100644
index 8cd8bfcc60..0000000000
--- a/OpenRA.Mods.RA/Widgets/Logic/ConvertGameFilesLogic.cs
+++ /dev/null
@@ -1,110 +0,0 @@
-#region Copyright & License Information
-/*
- * Copyright 2007-2013 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.IO;
-using System.Linq;
-using System.Threading;
-using OpenRA.Utility;
-using OpenRA.Widgets;
-
-namespace OpenRA.Mods.RA.Widgets.Logic
-{
- public class ConvertGameFilesLogic
- {
- Widget panel;
- ProgressBarWidget progressBar;
- LabelWidget statusLabel;
- ButtonWidget retryButton, backButton;
- Widget extractingContainer;
-
- string[][] ExtractGameFiles, ExportToPng, ImportFromPng;
-
- [ObjectCreator.UseCtor]
- public ConvertGameFilesLogic(Widget widget, string[][] ExtractGameFiles, string[][] ExportToPng, string[][] ImportFromPng)
- {
- panel = widget.Get("CONVERT_ASSETS_PANEL");
- progressBar = panel.Get("PROGRESS_BAR");
- statusLabel = panel.Get("STATUS_LABEL");
-
- backButton = panel.Get("BACK_BUTTON");
- backButton.OnClick = Ui.CloseWindow;
-
- retryButton = panel.Get("RETRY_BUTTON");
- retryButton.OnClick = Extract;
-
- extractingContainer = panel.Get("EXTRACTING");
-
- this.ExtractGameFiles = ExtractGameFiles;
- this.ExportToPng = ExportToPng;
- this.ImportFromPng = ImportFromPng;
-
- Extract();
- }
-
- void Extract()
- {
- backButton.IsDisabled = () => true;
- retryButton.IsDisabled = () => true;
- extractingContainer.IsVisible = () => true;
-
- var onError = (Action)(s => Game.RunAfterTick(() =>
- {
- statusLabel.GetText = () => "Error: "+s;
- backButton.IsDisabled = () => false;
- retryButton.IsDisabled = () => false;
- }));
-
- var t = new Thread( _ =>
- {
- try
- {
- for (int i = 0; i < ExtractGameFiles.Length; i++)
- {
- progressBar.Percentage = i*100/ExtractGameFiles.Count();
- statusLabel.GetText = () => "Extracting...";
- Command.ExtractFiles(ExtractGameFiles[i]);
- }
-
- for (int i = 0; i < ExportToPng.Length; i++)
- {
- progressBar.Percentage = i*100/ExportToPng.Count();
- statusLabel.GetText = () => "Exporting SHP to PNG...";
- Command.ConvertShpToPng(ExportToPng[i]);
- }
-
- for (int i = 0; i < ImportFromPng.Length; i++)
- {
- progressBar.Percentage = i*100/ImportFromPng.Count();
- statusLabel.GetText = () => "Converting PNG to SHP...";
- Command.ConvertPngToShp(ImportFromPng[i]);
- }
-
- Game.RunAfterTick(() =>
- {
- progressBar.Percentage = 100;
- statusLabel.GetText = () => "Done. Check {0}".F(Platform.SupportDir);
- backButton.IsDisabled = () => false;
- });
- }
- catch (FileNotFoundException f)
- {
- onError(f.FileName+" not found.");
- }
- catch (Exception e)
- {
- onError(e.Message);
- }
-
- }) { IsBackground = true };
- t.Start();
- }
- }
-}
diff --git a/OpenRA.Mods.RA/Widgets/ObserverProductionIconsWidget.cs b/OpenRA.Mods.RA/Widgets/ObserverProductionIconsWidget.cs
index af7ff43802..8bc0abc7d3 100644
--- a/OpenRA.Mods.RA/Widgets/ObserverProductionIconsWidget.cs
+++ b/OpenRA.Mods.RA/Widgets/ObserverProductionIconsWidget.cs
@@ -25,6 +25,10 @@ namespace OpenRA.Mods.RA.Widgets
WorldRenderer worldRenderer;
Dictionary clocks;
+ public int IconWidth = 32;
+ public int IconHeight = 24;
+ public int IconSpacing = 8;
+
[ObjectCreator.UseCtor]
public ObserverProductionIconsWidget(World world, WorldRenderer worldRenderer)
{
@@ -59,6 +63,8 @@ namespace OpenRA.Mods.RA.Widgets
clocks.Add(queue.Trait, new Animation("clock"));
}
}
+
+ var iconSize = new float2(IconWidth, IconHeight);
foreach (var queue in queues)
{
var current = queue.Trait.CurrentItem();
@@ -71,16 +77,15 @@ namespace OpenRA.Mods.RA.Widgets
var icon = new Animation(RenderSimple.GetImage(actor));
icon.Play(actor.Traits.Get().Icon);
- var size = icon.Image.size / new float2(2, 2);
- var location = new float2(RenderBounds.Location) + new float2(queue.i * (int)size.Length, 0);
- WidgetUtils.DrawSHP(icon.Image, location, worldRenderer, size);
+ var location = new float2(RenderBounds.Location) + new float2(queue.i * (IconWidth + IconSpacing), 0);
+ WidgetUtils.DrawSHPCentered(icon.Image, location + 0.5f * iconSize, worldRenderer, 0.5f);
var clock = clocks[queue.Trait];
clock.PlayFetchIndex("idle",
() => current.TotalTime == 0 ? 0 : ((current.TotalTime - current.RemainingTime)
* (clock.CurrentSequence.Length - 1) / current.TotalTime));
clock.Tick();
- WidgetUtils.DrawSHP(clock.Image, location, worldRenderer, size);
+ WidgetUtils.DrawSHPCentered(clock.Image, location + 0.5f * iconSize, worldRenderer, 0.5f);
var tiny = Game.Renderer.Fonts["Tiny"];
var text = GetOverlayForItem(current);
diff --git a/OpenRA.Mods.RA/Widgets/ObserverSupportPowerIconsWidget.cs b/OpenRA.Mods.RA/Widgets/ObserverSupportPowerIconsWidget.cs
index e192e162c1..408510763f 100644
--- a/OpenRA.Mods.RA/Widgets/ObserverSupportPowerIconsWidget.cs
+++ b/OpenRA.Mods.RA/Widgets/ObserverSupportPowerIconsWidget.cs
@@ -25,6 +25,10 @@ namespace OpenRA.Mods.RA.Widgets
WorldRenderer worldRenderer;
Dictionary clocks;
+ public int IconWidth = 32;
+ public int IconHeight = 24;
+ public int IconSpacing = 8;
+
[ObjectCreator.UseCtor]
public ObserverSupportPowerIconsWidget(World world, WorldRenderer worldRenderer)
{
@@ -61,22 +65,24 @@ namespace OpenRA.Mods.RA.Widgets
clocks.Add(power.a.Key, new Animation("clock"));
}
}
+
+ var iconSize = new float2(IconWidth, IconHeight);
foreach (var power in powers)
{
var item = power.a.Value;
if (item == null || item.Info == null || item.Info.Icon == null)
continue;
+
icon.Play(item.Info.Icon);
- var size = icon.Image.size / new float2(2, 2);
- var location = new float2(RenderBounds.Location) + new float2(power.i * (int)size.Length, 0);
- WidgetUtils.DrawSHP(icon.Image, location, worldRenderer, size);
+ var location = new float2(RenderBounds.Location) + new float2(power.i * (IconWidth + IconSpacing), 0);
+ WidgetUtils.DrawSHPCentered(icon.Image, location + 0.5f * iconSize, worldRenderer, 0.5f);
var clock = clocks[power.a.Key];
clock.PlayFetchIndex("idle",
() => item.TotalTime == 0 ? 0 : ((item.TotalTime - item.RemainingTime)
* (clock.CurrentSequence.Length - 1) / item.TotalTime));
clock.Tick();
- WidgetUtils.DrawSHP(clock.Image, location, worldRenderer, size);
+ WidgetUtils.DrawSHPCentered(clock.Image, location + 0.5f * iconSize, worldRenderer, 0.5f);
var tiny = Game.Renderer.Fonts["Tiny"];
var text = GetOverlayForItem(item);
diff --git a/OpenRA.Mods.RA/Widgets/SupportPowerBinWidget.cs b/OpenRA.Mods.RA/Widgets/SupportPowerBinWidget.cs
index 27a4f32dbb..13436ab4f6 100755
--- a/OpenRA.Mods.RA/Widgets/SupportPowerBinWidget.cs
+++ b/OpenRA.Mods.RA/Widgets/SupportPowerBinWidget.cs
@@ -23,6 +23,9 @@ namespace OpenRA.Mods.RA.Widgets
[Translate] public string ReadyText = "";
[Translate] public string HoldText = "";
+ public int IconWidth = 64;
+ public int IconHeight = 48;
+
Animation icon;
Animation clock;
readonly List>> buttons = new List>>();
@@ -84,10 +87,11 @@ namespace OpenRA.Mods.RA.Widgets
WidgetUtils.DrawRGBA(WidgetUtils.GetChromeImage(world, "specialbin-bottom"), new float2(rectBounds.X, rectBounds.Y + numPowers * 51));
// HACK: Hack Hack Hack
- rectBounds.Width = 69;
- rectBounds.Height = 10 + numPowers * 51 + 21;
+ rectBounds.Width = IconWidth + 5;
+ rectBounds.Height = 31 + numPowers * (IconHeight + 3);
var y = rectBounds.Y + 10;
+ var iconSize = new float2(IconWidth, IconHeight);
foreach (var kv in powers)
{
var sp = kv.Value;
@@ -137,14 +141,14 @@ namespace OpenRA.Mods.RA.Widgets
}
}
- WidgetUtils.DrawSHP(icon.Image, drawPos, worldRenderer);
+ WidgetUtils.DrawSHPCentered(icon.Image, drawPos + 0.5f * iconSize, worldRenderer);
clock.PlayFetchIndex("idle",
() => sp.TotalTime == 0 ? clock.CurrentSequence.Length - 1 : (sp.TotalTime - sp.RemainingTime)
* (clock.CurrentSequence.Length - 1) / sp.TotalTime);
clock.Tick();
- WidgetUtils.DrawSHP(clock.Image, drawPos, worldRenderer);
+ WidgetUtils.DrawSHPCentered(clock.Image, drawPos + 0.5f * iconSize, worldRenderer);
var overlay = sp.Ready ? ReadyText : sp.Active ? null : HoldText;
var font = Game.Renderer.Fonts["TinyBold"];
diff --git a/OpenRA.Utility/Command.cs b/OpenRA.Utility/Command.cs
index 9d738ef85d..cc9bcea144 100644
--- a/OpenRA.Utility/Command.cs
+++ b/OpenRA.Utility/Command.cs
@@ -19,6 +19,7 @@ using System.Runtime.InteropServices;
using OpenRA.FileFormats;
using OpenRA.FileFormats.Graphics;
using OpenRA.GameRules;
+using OpenRA.Graphics;
using OpenRA.Traits;
namespace OpenRA.Utility
@@ -42,46 +43,37 @@ namespace OpenRA.Utility
public static void ConvertPngToShp(string[] args)
{
- var src = args[1];
- var dest = Path.ChangeExtension(src, ".shp");
- var width = int.Parse(args[2]);
+ var dest = args[1].Split('-').First() + ".shp";
+ var frames = args.Skip(1).Select(a => PngLoader.Load(a));
- var srcImage = PngLoader.Load(src);
-
- if (srcImage.Width % width != 0)
- throw new InvalidOperationException("Bogus width; not a whole number of frames");
+ var size = frames.First().Size;
+ if (frames.Any(f => f.Size != size))
+ throw new InvalidOperationException("All frames must be the same size");
using (var destStream = File.Create(dest))
- ShpWriter.Write(destStream, width, srcImage.Height,
- srcImage.ToFrames(width));
+ ShpReader.Write(destStream, size, frames.Select(f => f.ToBytes()));
Console.WriteLine(dest + " saved.");
}
- static IEnumerable ToFrames(this Bitmap bitmap, int width)
+ static byte[] ToBytes(this Bitmap bitmap)
{
- for (var x = 0; x < bitmap.Width; x += width)
- {
- var data = bitmap.LockBits(new Rectangle(x, 0, width, bitmap.Height), ImageLockMode.ReadOnly,
- PixelFormat.Format8bppIndexed);
+ var data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly,
+ PixelFormat.Format8bppIndexed);
- var bytes = new byte[width * bitmap.Height];
- for (var i = 0; i < bitmap.Height; i++)
- Marshal.Copy(new IntPtr(data.Scan0.ToInt64() + i * data.Stride),
- bytes, i * width, width);
+ var bytes = new byte[bitmap.Width * bitmap.Height];
+ for (var i = 0; i < bitmap.Height; i++)
+ Marshal.Copy(new IntPtr(data.Scan0.ToInt64() + i * data.Stride),
+ bytes, i * bitmap.Width, bitmap.Width);
- bitmap.UnlockBits(data);
+ bitmap.UnlockBits(data);
- yield return bytes;
- }
+ return bytes;
}
public static void ConvertShpToPng(string[] args)
{
var src = args[1];
- var dest = Path.ChangeExtension(src, ".png");
-
- var srcImage = ShpReader.Load(src);
var shadowIndex = new int[] { };
if (args.Contains("--noshadow"))
{
@@ -93,134 +85,55 @@ namespace OpenRA.Utility
var palette = Palette.Load(args[2], shadowIndex);
- using (var bitmap = new Bitmap(srcImage.ImageCount * srcImage.Width, srcImage.Height, PixelFormat.Format8bppIndexed))
+ ISpriteSource source;
+ using (var stream = File.OpenRead(src))
+ source = SpriteSource.LoadSpriteSource(stream, src);
+
+ // The r8 padding requires external information that we can't access here.
+ var usePadding = !(args.Contains("--nopadding") || source is R8Reader);
+ var count = 0;
+ var prefix = Path.GetFileNameWithoutExtension(src);
+
+ foreach (var frame in source.Frames)
{
- var x = 0;
- bitmap.Palette = palette.AsSystemPalette();
+ var frameSize = usePadding ? frame.FrameSize : frame.Size;
+ var offset = usePadding ? (frame.Offset - 0.5f * new float2(frame.Size - frame.FrameSize)).ToInt2() : int2.Zero;
- foreach (var frame in srcImage.Frames)
+ // shp(ts) may define empty frames
+ if (frameSize.Width == 0 && frameSize.Height == 0)
{
- var data = bitmap.LockBits(new Rectangle(x, 0, srcImage.Width, srcImage.Height), ImageLockMode.WriteOnly,
- PixelFormat.Format8bppIndexed);
+ count++;
+ continue;
+ }
- for (var i = 0; i < bitmap.Height; i++)
- Marshal.Copy(frame.Image, i * srcImage.Width,
- new IntPtr(data.Scan0.ToInt64() + i * data.Stride), srcImage.Width);
+ using (var bitmap = new Bitmap(frameSize.Width, frameSize.Height, PixelFormat.Format8bppIndexed))
+ {
+ bitmap.Palette = palette.AsSystemPalette();
+ var data = bitmap.LockBits(new Rectangle(0, 0, frameSize.Width, frameSize.Height),
+ ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
- x += srcImage.Width;
+ // Clear the frame
+ if (usePadding)
+ {
+ var clearRow = new byte[data.Stride];
+ for (var i = 0; i < frameSize.Height; i++)
+ Marshal.Copy(clearRow, 0, new IntPtr(data.Scan0.ToInt64() + i * data.Stride), data.Stride);
+ }
+
+ for (var i = 0; i < frame.Size.Height; i++)
+ {
+ var destIndex = new IntPtr(data.Scan0.ToInt64() + (i + offset.Y) * data.Stride + offset.X);
+ Marshal.Copy(frame.Data, i * frame.Size.Width, destIndex, frame.Size.Width);
+ }
bitmap.UnlockBits(data);
+
+ var filename = "{0}-{1:D4}.png".F(prefix, count++);
+ bitmap.Save(filename);
}
-
- bitmap.Save(dest);
- Console.WriteLine(dest + " saved");
- }
- }
-
- public static void ConvertR8ToPng(string[] args)
- {
- var srcImage = new R8Reader(File.OpenRead(args[1]));
- var shadowIndex = new int[] { };
- if (args.Contains("--noshadow"))
- {
- Array.Resize(ref shadowIndex, shadowIndex.Length + 1);
- shadowIndex[shadowIndex.Length - 1] = 3;
}
- var palette = Palette.Load(args[2], shadowIndex);
- var startFrame = int.Parse(args[3]);
- var endFrame = int.Parse(args[4]) + 1;
- var filename = args[5];
- var frameCount = endFrame - startFrame;
-
- var frame = srcImage[startFrame];
- var bitmap = new Bitmap(frame.FrameSize.Width * frameCount, frame.FrameSize.Height, PixelFormat.Format8bppIndexed);
- bitmap.Palette = palette.AsSystemPalette();
-
- frame = srcImage[startFrame];
-
- if (args.Contains("--tileset"))
- {
- int f = 0;
- var tileset = new Bitmap(frame.FrameSize.Width * 20, frame.FrameSize.Height * 40, PixelFormat.Format8bppIndexed);
- tileset.Palette = palette.AsSystemPalette();
-
- for (int h = 0; h < 40; h++)
- {
- for (int w = 0; w < 20; w++)
- {
- if (h * 20 + w < frameCount)
- {
- Console.WriteLine(f);
- frame = srcImage[f];
-
- var data = tileset.LockBits(new Rectangle(w * frame.Size.Width, h * frame.Size.Height, frame.Size.Width, frame.Size.Height),
- ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
-
- for (var i = 0; i < frame.Size.Height; i++)
- Marshal.Copy(frame.Image, i * frame.Size.Width,
- new IntPtr(data.Scan0.ToInt64() + i * data.Stride), frame.Size.Width);
-
- tileset.UnlockBits(data);
- f++;
- }
- }
- }
-
- bitmap = tileset;
- }
-
- bitmap.Save(filename + ".png");
- Console.WriteLine(filename + ".png saved");
- }
-
- public static void ConvertTmpToPng(string[] args)
- {
- var mod = args[1];
- var theater = args[2];
- var templateNames = args.Skip(3);
- var shadowIndex = new int[] { 3, 4 };
-
- var manifest = new Manifest(mod);
- FileSystem.LoadFromManifest(manifest);
-
- var tileset = manifest.TileSets.Select(a => new TileSet(a))
- .FirstOrDefault(ts => ts.Name == theater);
-
- if (tileset == null)
- throw new InvalidOperationException("No theater named '{0}'".F(theater));
-
- var renderer = new TileSetRenderer(tileset, new Size(manifest.TileSize, manifest.TileSize));
- var palette = new Palette(FileSystem.Open(tileset.Palette), shadowIndex);
-
- foreach (var templateName in templateNames)
- {
- var template = tileset.Templates.FirstOrDefault(tt => tt.Value.Image == templateName);
- if (template.Value == null)
- throw new InvalidOperationException("No such template '{0}'".F(templateName));
-
- using (var image = renderer.RenderTemplate(template.Value.Id, palette))
- image.Save(Path.ChangeExtension(templateName, ".png"));
- }
- }
-
- public static void ConvertFormat2ToFormat80(string[] args)
- {
- var src = args[1];
- var dest = args[2];
-
- Dune2ShpReader srcImage = null;
- using (var s = File.OpenRead(src))
- srcImage = new Dune2ShpReader(s);
-
- var size = srcImage.First().Size;
-
- if (!srcImage.All(im => im.Size == size))
- throw new InvalidOperationException("All the frames must be the same size to convert from Dune2 to RA");
-
- using (var destStream = File.Create(dest))
- ShpWriter.Write(destStream, size.Width, size.Height,
- srcImage.Select(im => im.Image));
+ Console.WriteLine("Saved {0}-[0..{1}].png", prefix, count - 1);
}
public static void ExtractFiles(string[] args)
@@ -233,16 +146,12 @@ namespace OpenRA.Utility
foreach (var f in files)
{
- if (f == "--userdir")
- break;
-
var src = FileSystem.Open(f);
if (src == null)
throw new InvalidOperationException("File not found: {0}".F(f));
var data = src.ReadAllBytes();
- var output = args.Contains("--userdir") ? Platform.SupportDir + f : f;
- File.WriteAllBytes(output, data);
- Console.WriteLine(output + " saved.");
+ File.WriteAllBytes(f, data);
+ Console.WriteLine(f + " saved.");
}
}
@@ -300,8 +209,8 @@ namespace OpenRA.Utility
var srcImage = ShpReader.Load(args[3]);
using (var destStream = File.Create(args[4]))
- ShpWriter.Write(destStream, srcImage.Width, srcImage.Height,
- srcImage.Frames.Select(im => im.Image.Select(px => (byte)remap[px]).ToArray()));
+ ShpReader.Write(destStream, srcImage.Size,
+ srcImage.Frames.Select(im => im.Data.Select(px => (byte)remap[px]).ToArray()));
}
public static void TransposeShp(string[] args)
@@ -323,8 +232,7 @@ namespace OpenRA.Utility
}
using (var destStream = File.Create(args[2]))
- ShpWriter.Write(destStream, srcImage.Width, srcImage.Height,
- destFrames.Select(f => f.Image));
+ ShpReader.Write(destStream, srcImage.Size, destFrames.Select(f => f.Data));
}
static string FriendlyTypeName(Type t)
diff --git a/OpenRA.Utility/Program.cs b/OpenRA.Utility/Program.cs
index f3c9edea08..89c4f453de 100644
--- a/OpenRA.Utility/Program.cs
+++ b/OpenRA.Utility/Program.cs
@@ -23,11 +23,8 @@ namespace OpenRA.Utility
{ "--settings-value", Command.Settings },
{ "--shp", Command.ConvertPngToShp },
{ "--png", Command.ConvertShpToPng },
- { "--fromd2", Command.ConvertFormat2ToFormat80 },
{ "--extract", Command.ExtractFiles },
- { "--tmp-png", Command.ConvertTmpToPng },
{ "--remap", Command.RemapShp },
- { "--r8", Command.ConvertR8ToPng },
{ "--transpose", Command.TransposeShp },
{ "--docs", Command.ExtractTraitDocs },
{ "--map-hash", Command.GetMapHash },
@@ -58,13 +55,10 @@ namespace OpenRA.Utility
Console.WriteLine("Usage: OpenRA.Utility.exe [OPTION] [ARGS]");
Console.WriteLine();
Console.WriteLine(" --settings-value KEY Get value of KEY from settings.yaml");
- Console.WriteLine(" --shp PNGFILE FRAMEWIDTH Convert a single PNG with multiple frames appended after another to a SHP");
- Console.WriteLine(" --png SHPFILE PALETTE [--noshadow] Convert a SHP to a PNG containing all of its frames, optionally removing the shadow");
- Console.WriteLine(" --fromd2 DUNE2SHP C&CSHP Convert a Dune II SHP (C&C mouse cursor) to C&C SHP format.");
- Console.WriteLine(" --extract MOD[,MOD]* FILES [--userdir] Extract files from mod packages to the current (or user) directory");
- Console.WriteLine(" --tmp-png MOD[,MOD]* THEATER FILES Extract terrain tiles to PNG");
+ Console.WriteLine(" --shp PNGFILE [PNGFILE ...] Combine a list of PNG images into a SHP");
+ Console.WriteLine(" --png SPRITEFILE PALETTE [--noshadow] [--nopadding] Convert a shp/tmp/R8 to a series of PNGs, optionally removing shadow");
+ Console.WriteLine(" --extract MOD[,MOD]* FILES Extract files from mod packages to the current directory");
Console.WriteLine(" --remap SRCMOD:PAL DESTMOD:PAL SRCSHP DESTSHP Remap SHPs to another palette");
- Console.WriteLine(" --r8 R8FILE PALETTE START END FILENAME [--noshadow] [--tileset] Convert Dune 2000 DATA.R8 to PNGs choosing start- and endframe as well as type to append multiple frames to one PNG named by filename optionally removing the shadow.");
Console.WriteLine(" --transpose SRCSHP DESTSHP START N M [START N M ...] Transpose the N*M block of frames starting at START.");
Console.WriteLine(" --docs MOD Generate trait documentation in MarkDown format.");
Console.WriteLine(" --map-hash MAPFILE Generate hash of specified oramap file.");
diff --git a/mods/cnc/chrome/dialogs.yaml b/mods/cnc/chrome/dialogs.yaml
index 0dd2997576..ea64b03ece 100644
--- a/mods/cnc/chrome/dialogs.yaml
+++ b/mods/cnc/chrome/dialogs.yaml
@@ -30,8 +30,10 @@ Background@COLOR_CHOOSER:
Width:144
Height:72
ShpImage@FACT:
- X:160
- Y:13
+ X:153
+ Y:1
+ Width:80
+ Height:73
Image:fact
Palette:colorpicker
Button@RANDOM_BUTTON:
diff --git a/mods/cnc/cursors.yaml b/mods/cnc/cursors.yaml
index cad78974c9..b5e237e8ba 100644
--- a/mods/cnc/cursors.yaml
+++ b/mods/cnc/cursors.yaml
@@ -4,7 +4,7 @@
Cursors:
- mouse2: cursor
+ mouse2.shp: cursor
scroll-t:
start:1
scroll-tr:
@@ -114,7 +114,7 @@ Cursors:
start:154
length:24
- mouse4:cursor
+ mouse4.shp:cursor
move:
start:0
length:8
@@ -125,7 +125,7 @@ Cursors:
start:0
length: 8
- attackmove:cursor
+ attackmove.shp:cursor
attackmove:
start:0
length:8
@@ -138,7 +138,7 @@ Cursors:
start:13
length:1
- mouse3: cursor2
+ mouse3.shp: cursor2
enter-blocked:
start:212
length:1
@@ -170,7 +170,7 @@ Cursors:
start:213
length:1
- nopower: cursor
+ nopower.shp: cursor
powerdown-blocked:
start:0
length: 1
diff --git a/mods/d2k/chrome/assetbrowser.yaml b/mods/d2k/chrome/assetbrowser.yaml
deleted file mode 100644
index 270cdec6cd..0000000000
--- a/mods/d2k/chrome/assetbrowser.yaml
+++ /dev/null
@@ -1,215 +0,0 @@
-Background@ASSETBROWSER_BG:
- Logic:AssetBrowserLogic
- X:(WINDOW_RIGHT - WIDTH)/2
- Y:(WINDOW_BOTTOM - HEIGHT)/2
- Width:700
- Height:410
- Children:
- ColorPreviewManager@COLOR_MANAGER:
- Label@ASSETBROWSER_TITLE:
- X:0
- Y:10
- Width:PARENT_RIGHT
- Height:25
- Text:Game Asset Viewer & Converter
- Align:Center
- Font:Bold
- DropDownButton@SOURCE_SELECTOR:
- X:40
- Y:45
- Width:160
- Height:25
- Font:Bold
- Text:Folders
- ScrollPanel@ASSET_LIST:
- X:40
- Y:80
- Width:160
- Height:190
- Children:
- ScrollItem@ASSET_TEMPLATE:
- Width:PARENT_RIGHT-27
- Height:25
- X:2
- Y:0
- Visible:false
- Children:
- Label@TITLE:
- X:10
- Width:PARENT_RIGHT-20
- Height:25
- TextField@FILENAME_INPUT:
- X:40
- Y:280
- Width:140
- Height:25
- Text:mouse.r8
- Button@LOAD_BUTTON:
- X:40
- Y:310
- Width:140
- Height:25
- Text:Load
- Font:Bold
- Key:return
- DropDownButton@PALETTE_SELECTOR:
- X:230
- Y:45
- Width:150
- Height:25
- Font:Bold
- Text:Palette
- DropDownButton@COLOR:
- X:380
- Y:45
- Width:80
- Height:25
- Children:
- ColorBlock@COLORBLOCK:
- X:5
- Y:6
- Width:PARENT_RIGHT-35
- Height:PARENT_BOTTOM-12
- Background@SPRITE_BG:
- X:220
- Y:80
- Width:250
- Height:250
- Background:dialog4
- Children:
- ShpImage@SPRITE:
- X:4
- Y:4
- Width:246
- Height:246
- Image:mouse.r8
- Label@ACTIONS_TITLE:
- X:PARENT_RIGHT - 150
- Y:45
- Width:PARENT_RIGHT
- Height:25
- Text:Actions
- Font:Bold
- Button@EXPORT_BUTTON:
- X:PARENT_RIGHT - 200
- Y:80
- Width:160
- Height:25
- Text:Selected to PNG
- Font:Bold
- Button@EXTRACT_BUTTON:
- X:PARENT_RIGHT - 200
- Y:115
- Width:160
- Height:25
- Text:Extract all to PNG
- Font:Bold
- TextField@IMAGE_FILENAME_INPUT:
- X:PARENT_RIGHT - 200
- Y:PARENT_BOTTOM - 235
- Width:100
- Height:25
- Text:pixelart.png
- TextField@IMAGE_SIZE_INPUT:
- X:PARENT_RIGHT - 90
- Y:PARENT_BOTTOM - 235
- Width:50
- Height:25
- Text:width
- Button@IMPORT_BUTTON:
- X:PARENT_RIGHT - 200
- Y:PARENT_BOTTOM - 200
- Width:160
- Height:25
- Text:Import from PNG
- Font:Bold
- Button@CLOSE_BUTTON:
- X:PARENT_RIGHT - 200
- Y:PARENT_BOTTOM - 115
- Width:160
- Height:25
- Text:Close
- Font:Bold
- Key:escape
- Container@FRAME_SELECTOR:
- X:45
- Y:360
- Children:
- Button@BUTTON_PREV:
- X:0
- Y:0
- Width:25
- Height:25
- Children:
- Image@IMAGE_PREV:
- X:0
- Y:0
- Width:25
- Height:25
- ImageCollection:music
- ImageName:prev
- Button@BUTTON_PLAY:
- X:35
- Y:0
- Width:25
- Height:25
- Children:
- Image@IMAGE_PLAY:
- X:0
- Y:0
- Width:25
- Height:25
- ImageCollection:music
- ImageName:play
- Button@BUTTON_PAUSE:
- Visible: no
- X:35
- Y:0
- Width:25
- Height:25
- Children:
- Image@IMAGE_PAUSE:
- X:0
- Y:0
- Width:25
- Height:25
- ImageCollection:music
- ImageName:pause
- Button@BUTTON_STOP:
- X:70
- Y:0
- Width:25
- Height:25
- Children:
- Image@IMAGE_STOP:
- X:0
- Y:0
- Width:25
- Height:25
- ImageCollection:music
- ImageName:stop
- Button@BUTTON_NEXT:
- X:105
- Y:0
- Width:25
- Height:25
- Children:
- Image@IMAGE_NEXT:
- X:0
- Y:0
- Width:25
- Height:25
- ImageCollection:music
- ImageName:next
- Slider@FRAME_SLIDER:
- X:160
- Y:0
- Width:410
- Height:20
- MinimumValue: 0
- Label@FRAME_COUNT:
- X:585
- Y:0
- Width:25
- Height:25
- Font:Bold
\ No newline at end of file
diff --git a/mods/d2k/chrome/color-picker.yaml b/mods/d2k/chrome/color-picker.yaml
index 5a099fff48..0d4991736e 100644
--- a/mods/d2k/chrome/color-picker.yaml
+++ b/mods/d2k/chrome/color-picker.yaml
@@ -30,8 +30,10 @@ Background@COLOR_CHOOSER:
Width:144
Height:72
ShpImage@FACT:
- X:160
- Y:8
+ X:153
+ Y:1
+ Width:80
+ Height:73
Image:DATA.R8
Frame:1936
Palette:colorpicker
diff --git a/mods/d2k/chrome/ingame.yaml b/mods/d2k/chrome/ingame.yaml
index 92876a52a9..d7a96bad48 100644
--- a/mods/d2k/chrome/ingame.yaml
+++ b/mods/d2k/chrome/ingame.yaml
@@ -150,6 +150,8 @@ Container@PLAYER_WIDGETS:
SupportPowerBin@INGAME_POWERS_BIN:
X:0
Y:25
+ IconWidth: 60
+ IconHeight: 48
ReadyText: READY
HoldText: ON HOLD
BuildPalette@INGAME_BUILD_PALETTE:
diff --git a/mods/d2k/cursors.yaml b/mods/d2k/cursors.yaml
index f3d920dcb8..758cd367ec 100644
--- a/mods/d2k/cursors.yaml
+++ b/mods/d2k/cursors.yaml
@@ -2,10 +2,10 @@ ShadowIndex: 1
Palettes:
cursor: cursor.pal
- mouse.r8: d2k.pal
+ mouse: d2k.pal
Cursors:
- mouse.r8: mouse.r8
+ mouse.r8: mouse
scroll-t:
start:112
x: 24
@@ -252,7 +252,7 @@ Cursors:
x: 24
y: 24
- nopower: cursor
+ nopower.shp: cursor
powerdown-blocked:
start:0
length: 1
diff --git a/mods/d2k/mod.yaml b/mods/d2k/mod.yaml
index 7fff8c53f6..bdccad9daa 100644
--- a/mods/d2k/mod.yaml
+++ b/mods/d2k/mod.yaml
@@ -76,8 +76,7 @@ ChromeLayout:
mods/ra/chrome/cheats.yaml
mods/ra/chrome/musicplayer.yaml
mods/d2k/chrome/tooltips.yaml
- mods/d2k/chrome/assetbrowser.yaml
- mods/ra/chrome/convertassets.yaml
+ mods/ra/chrome/assetbrowser.yaml
mods/ra/chrome/irc.yaml
Weapons:
diff --git a/mods/d2k/sequences/aircraft.yaml b/mods/d2k/sequences/aircraft.yaml
index bdbf974858..4a4bffa6b3 100644
--- a/mods/d2k/sequences/aircraft.yaml
+++ b/mods/d2k/sequences/aircraft.yaml
@@ -1,27 +1,27 @@
carryall:
- idle: DATA.R8
+ idle: DATA
Start: 1923
Facings: -32
- unload: DATA.R8
+ unload: DATA
Start: 1923
Facings: -32
- icon: DATA.R8
+ icon: DATA
Start: 4029
Offset: -30,-24
orni:
- idle: DATA.R8
+ idle: DATA
Start: 1955
Facings: -32
Length: 3
Tick: 120
Transpose: true
- icon: DATA.R8
+ icon: DATA
Start: 4031
Offset: -30,-24
frigate:
- idle: DATA.R8
+ idle: DATA
Start: 2517
Facings: 1
\ No newline at end of file
diff --git a/mods/d2k/sequences/infantry.yaml b/mods/d2k/sequences/infantry.yaml
index 7747737bbe..c86c982526 100644
--- a/mods/d2k/sequences/infantry.yaml
+++ b/mods/d2k/sequences/infantry.yaml
@@ -1,441 +1,441 @@
rifle:
- stand: DATA.R8
+ stand: DATA
Start: 206
Facings: -8
Transpose: true
- stand2: DATA.R8
+ stand2: DATA
Start: 206
Facings: -8
Transpose: true
- stand3: DATA.R8
+ stand3: DATA
Start: 206
Facings: -8
Transpose: true
- run: DATA.R8
+ run: DATA
Start: 214
Length: 6
Facings: -8
Tick: 110
Transpose: true
- shoot: DATA.R8
+ shoot: DATA
Start: 254
Length: 6
Facings: -8
Transpose: true
- prone-stand: DATA.R8
+ prone-stand: DATA
Start: 302
Facings: -8
Transpose: true
- prone-run: DATA.R8
+ prone-run: DATA
Start: 310
Length: 3
Facings: -8
Transpose: true
Tick: 110
- standup-0: DATA.R8
+ standup-0: DATA
Start: 302
Facings: -8
Transpose: true
Tick: 120
- prone-shoot: DATA.R8
+ prone-shoot: DATA
Start: 334
Length: 6
Facings: -8
Transpose: true
- die1: DATA.R8
+ die1: DATA
Start: 382
Length: 5
- die2: DATA.R8
+ die2: DATA
Start: 387
Length: 7
Tick: 80
- die3: DATA.R8
+ die3: DATA
Start: 394
Length: 7
- die4: DATA.R8
+ die4: DATA
Start: 401
Length: 7
- die5: DATA.R8
+ die5: DATA
Start: 408
Length: 7
- die6: DATA.R8
+ die6: DATA
Start: 415
Length: 12
- die-crushed: DATA.R8
+ die-crushed: DATA
Start: 430
Length: 12
Tick: 1600
- icon: DATA.R8
+ icon: DATA
Start: 4011
Offset: -30,-24
bazooka:
- stand: DATA.R8
+ stand: DATA
Start: 458
Facings: -8
Transpose: true
- stand2: DATA.R8
+ stand2: DATA
Start: 458
Facings: -8
Transpose: true
- stand3: DATA.R8
+ stand3: DATA
Start: 458
Facings: -8
Transpose: true
- run: DATA.R8
+ run: DATA
Start: 466
Length: 6
Facings: -8
Tick: 120
Transpose: true
- shoot: DATA.R8
+ shoot: DATA
Start: 506
Length: 6
Facings: -8
Transpose: true
- prone-stand: DATA.R8
+ prone-stand: DATA
Start: 562
Length: 1
Facings: -8
Transpose: true
- prone-run: DATA.R8
+ prone-run: DATA
Start: 570
Length: 3
Facings: -8
Transpose: true
Tick: 120
- standup-0: DATA.R8
+ standup-0: DATA
Start: 554
Length: 1
Facings: -8
Transpose: true
- prone-shoot: DATA.R8
+ prone-shoot: DATA
Start: 586
Length: 6
Facings: -8
Transpose: true
- die1: DATA.R8
+ die1: DATA
Start: 634
Length: 5
- die2: DATA.R8
+ die2: DATA
Start: 639
Length: 7
- die3: DATA.R8
+ die3: DATA
Start: 646
Length: 7
- die4: DATA.R8
+ die4: DATA
Start: 653
Length: 7
- die5: DATA.R8
+ die5: DATA
Start: 660
Length: 7
- die6: DATA.R8
+ die6: DATA
Start: 660
Length: 7
- die-crushed: DATA.R8
+ die-crushed: DATA
Start: 668
Length: 26
Tick: 1600
- icon: DATA.R8
+ icon: DATA
Start: 4012
Offset: -30,-24
engineer:
- stand: DATA.R8
+ stand: DATA
Start: 1166
Facings: -8
Transpose: true
- stand2: DATA.R8
+ stand2: DATA
Start: 1166
Facings: -8
Transpose: true
- run: DATA.R8
+ run: DATA
Start: 1174
Length: 6
Facings: -8
Transpose: true
Tick: 120
- die1: DATA.R8
+ die1: DATA
Start: 1342
Length: 5
- die2: DATA.R8
+ die2: DATA
Start: 1347
Length: 7
- die3: DATA.R8
+ die3: DATA
Start: 1354
Length: 7
- die4: DATA.R8
+ die4: DATA
Start: 1361
Length: 7
- die5: DATA.R8
+ die5: DATA
Start: 1368
Length: 7
- die6: DATA.R8
+ die6: DATA
Start: 1368
Length: 7
- die-crushed: DATA.R8
+ die-crushed: DATA
Start: 1376
Length: 26
Tick: 1600
- icon: DATA.R8
+ icon: DATA
Start: 4013
Offset: -30,-24
medic: # actually thumper
- stand: DATA.R8
+ stand: DATA
Start: 1402
Facings: -8
Transpose: true
- stand2: DATA.R8
+ stand2: DATA
Start: 1402
Facings: -8
Transpose: true
- run: DATA.R8
+ run: DATA
Start: 1410
Length: 6
Facings: -8
Transpose: true
Tick: 120
- heal: DATA.R8
+ heal: DATA
Start: 1458
Length: 5
Tick: 480
- die1: DATA.R8
+ die1: DATA
Start: 1543
Length: 5
- die2: DATA.R8
+ die2: DATA
Start: 1548
Length: 7
- die3: DATA.R8
+ die3: DATA
Start: 1555
Length: 7
- die4: DATA.R8
+ die4: DATA
Start: 1562
Length: 7
- die5: DATA.R8
+ die5: DATA
Start: 1569
Length: 7
- die6: DATA.R8
+ die6: DATA
Start: 1569
Length: 7
- die-crushed: DATA.R8
+ die-crushed: DATA
Start: 1577
Length: 26
Tick: 1600
- icon: DATA.R8
+ icon: DATA
Start: 4014
Offset: -30,-24
thumping:
- idle: DATA.R8
+ idle: DATA
Start: 1458
Length: 5
Tick: 150
- make: DATA.R8
+ make: DATA
Start: 1458
Length: 5
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 1458
Length: 5
Tick: 150
- icon: DATA.R8
+ icon: DATA
Frames: 4014
Offset: -30,-24
fremen:
- stand: DATA.R8
+ stand: DATA
Start: 694
Facings: -8
Transpose: true
- stand2: DATA.R8
+ stand2: DATA
Start: 694
Facings: -8
Transpose: true
- run: DATA.R8
+ run: DATA
Start: 702
Length: 6
Facings: -8
Transpose: true
Tick: 120
- shoot: DATA.R8
+ shoot: DATA
Start: 742
Length: 6
Facings: -8
Transpose: true
- prone-stand: DATA.R8
+ prone-stand: DATA
Start: 798
Length: 1
Facings: -8
Transpose: true
- prone-run: DATA.R8
+ prone-run: DATA
Start: 806
Length: 3
Facings: -8
Transpose: true
Tick: 120
- standup-0: DATA.R8
+ standup-0: DATA
Start: 790
Length: 1
Facings: -8
Transpose: true
Tick: 120
- prone-shoot: DATA.R8
+ prone-shoot: DATA
Start: 822
Length: 6
Facings: -8
Transpose: true
- die1: DATA.R8
+ die1: DATA
Start: 870
Length: 5
- die2: DATA.R8
+ die2: DATA
Start: 875
Length: 7
- die3: DATA.R8
+ die3: DATA
Start: 882
Length: 7
- die4: DATA.R8
+ die4: DATA
Start: 889
Length: 7
- die5: DATA.R8
+ die5: DATA
Start: 896
Length: 7
- die6: DATA.R8
+ die6: DATA
Start: 896
Length: 7
- die-crushed: DATA.R8
+ die-crushed: DATA
Start: 904
Length: 26
Tick: 1600
- icon: DATA.R8
+ icon: DATA
Start: 4032
Offset: -30,-24
saboteur:
- stand: DATA.R8
+ stand: DATA
Start: 2149
Facings: -8
Transpose: true
- stand2: DATA.R8
+ stand2: DATA
Start: 2149
Facings: -8
Transpose: true
- stand3: DATA.R8
+ stand3: DATA
Start: 2149
Facings: -8
Transpose: true
- run: DATA.R8
+ run: DATA
Start: 2157
Length: 6
Facings: -8
Transpose: true
Tick: 120
- prone-stand: DATA.R8
+ prone-stand: DATA
Start: 2253
Length: 1
Facings: -8
Transpose: true
- prone-run: DATA.R8
+ prone-run: DATA
Start: 2261
Length: 3
Facings: -8
Transpose: true
Tick: 120
- standup-0: DATA.R8
+ standup-0: DATA
Start: 2245
Length: 1
Facings: -8
Transpose: true
Tick: 120
- die1: DATA.R8
+ die1: DATA
Start: 2325
Length: 5
- die2: DATA.R8
+ die2: DATA
Start: 2330
Length: 7
- die3: DATA.R8
+ die3: DATA
Start: 2337
Length: 7
- die4: DATA.R8
+ die4: DATA
Start: 2344
Length: 7
- die5: DATA.R8
+ die5: DATA
Start: 2351
Length: 7
- die6: DATA.R8
+ die6: DATA
Start: 2351
Length: 7
- die-crushed: DATA.R8
+ die-crushed: DATA
Start: 2359
Length: 26
Tick: 1600
- icon: DATA.R8
+ icon: DATA
Start: 4034
Offset: -30,-24
sardaukar:
- stand: DATA.R8
+ stand: DATA
Start: 930
Facings: -8
Transpose: true
- stand2: DATA.R8
+ stand2: DATA
Start: 930
Facings: -8
Transpose: true
- run: DATA.R8
+ run: DATA
Start: 938
Length: 6
Facings: -8
Transpose: true
Tick: 120
- shoot: DATA.R8
+ shoot: DATA
Start: 978
Length: 6
Facings: -8
Transpose: true
- prone-stand: DATA.R8
+ prone-stand: DATA
Start: 1034
Length: 1
Facings: -8
Transpose: true
- prone-run: DATA.R8
+ prone-run: DATA
Start: 1042
Length: 3
Facings: -8
Transpose: true
Tick: 120
- standup-0: DATA.R8
+ standup-0: DATA
Start: 1026
Length: 1
Facings: -8
Transpose: true
Tick: 120
- prone-shoot: DATA.R8
+ prone-shoot: DATA
Start: 1058
Length: 6
Facings: 8
Transpose: true
- die1: DATA.R8
+ die1: DATA
Start: 1106
Length: 5
- die2: DATA.R8
+ die2: DATA
Start: 1111
Length: 7
- die3: DATA.R8
+ die3: DATA
Start: 1118
Length: 7
- die4: DATA.R8
+ die4: DATA
Start: 1125
Length: 7
- die5: DATA.R8
+ die5: DATA
Start: 1132
Length: 7
- die6: DATA.R8
+ die6: DATA
Start: 1132
Length: 7
- die-crushed: DATA.R8
+ die-crushed: DATA
Start: 1140
Length: 26
Tick: 1600
- icon: DATA.R8
+ icon: DATA
Start: 4015
Offset: -30,-24
diff --git a/mods/d2k/sequences/misc.yaml b/mods/d2k/sequences/misc.yaml
index 50e14f4796..ceedd4c11b 100644
--- a/mods/d2k/sequences/misc.yaml
+++ b/mods/d2k/sequences/misc.yaml
@@ -1,87 +1,87 @@
explosion:
- piff: DATA.R8
+ piff: DATA
Start: 3626
Length: 5
- piffs: DATA.R8
+ piffs: DATA
Start: 3429
Length: 4
Tick: 80
BlendMode: Additive
- small_explosion: DATA.R8
+ small_explosion: DATA
Start: 3403
Length: 15
BlendMode: Additive
- med_explosion: DATA.R8
+ med_explosion: DATA
Start: 3390
Length: 12
BlendMode: Additive
- tiny_explosion: DATA.R8
+ tiny_explosion: DATA
Start: 3386
Length: 4
Tick: 80
BlendMode: Additive
- nuke: DATA.R8
+ nuke: DATA
Start: 3965
Length: 14
Tick: 60
BlendMode: Additive
- mini_explosion: DATA.R8
+ mini_explosion: DATA
Start: 3403
Length: 15
Tick: 60
BlendMode: Additive
- self_destruct: DATA.R8
+ self_destruct: DATA
Start: 3433
Length: 15
BlendMode: Additive
- building: DATA.R8
+ building: DATA
Start: 3448
Length: 22
BlendMode: Additive
- large_explosion: DATA.R8
+ large_explosion: DATA
Start: 3988
Length: 22
BlendMode: Additive
- artillery: DATA.R8
+ artillery: DATA
Start: 3988
Length: 22
BlendMode: Additive
- small_artillery: DATA.R8
+ small_artillery: DATA
Start: 3390
Length: 12
Tick: 60
BlendMode: Additive
- small_napalm: DATA.R8
+ small_napalm: DATA
Start: 3421
Length: 8
BlendMode: Additive
- shockwave: DATA.R8
+ shockwave: DATA
Start: 3687
Length: 6
BlendMode: Additive
Tick: 120
- deviator: DATA.R8
+ deviator: DATA
Start: 3512
Length: 23
BlendMode: Additive
Tick: 60
laserfire:
- idle: DATA.R8
+ idle: DATA
Start: 3386
Length: 4
Tick: 80
BlendMode: Additive
pips:
- groups: DATA.R8
+ groups: DATA
Start: 17
Length: 10
- tag-primary: DATA.R8
+ tag-primary: DATA
Start: 110
- pip-empty: DATA.R8
+ pip-empty: DATA
Start: 15
- pip-green: DATA.R8
+ pip-green: DATA
Start: 16
clock:
@@ -105,19 +105,19 @@ rank:
Length: *
overlay:
- build-valid-arrakis: DATA.R8
+ build-valid-arrakis: DATA
Start: 0
Offset: -16,-16
- build-invalid: DATA.R8
+ build-invalid: DATA
Start: 1
Offset: -16,-16
- target-select: DATA.R8
+ target-select: DATA
Start: 2
Offset: -16,-16
- target-valid-arrakis: DATA.R8
+ target-valid-arrakis: DATA
Start: 0
Offset: -16,-16
- target-invalid: DATA.R8
+ target-invalid: DATA
Start: 1
Offset: -16,-16
@@ -131,29 +131,29 @@ rallypoint:
Length: *
rpg:
- idle: DATA.R8
+ idle: DATA
Start: 3015
Facings: -32
120mm:
- idle: DATA.R8
+ idle: DATA
Start: 3014
Length: 1
BlendMode: Additive
155mm:
- idle: DATA.R8
+ idle: DATA
Start: 3081
Length: 1
crate-effects:
- dollar: DATA.R8
+ dollar: DATA
Start: 3679
Length: 8
- reveal-map: DATA.R8
+ reveal-map: DATA
Start: 3947
Length: 18
- hide-map: DATA.R8
+ hide-map: DATA
Start: 3911
Length: 36
levelup: levelup
@@ -162,70 +162,70 @@ crate-effects:
Tick: 200
allyrepair:
- repair: DATA.R8
+ repair: DATA
Frames: 3, 39
Length: 2
Tick: 300
missile:
- idle: DATA.R8
+ idle: DATA
Start: 3088
Facings: -32
missile2:
- idle: DATA.R8
+ idle: DATA
Start: 3306
Facings: -32
atomic:
- up: DATA.R8
+ up: DATA
Start: 2147
Length: 1
- down: DATA.R8
+ down: DATA
Start: 2148
Length: 1
fire:
- 1: DATA.R8
+ 1: DATA
Start: 3712
Length: 10
Offset: 0,-3
BlendMode: Additive
- 2: DATA.R8
+ 2: DATA
Start: 3723
Length: 11
Offset: 0,-3
BlendMode: Additive
- 3: DATA.R8
+ 3: DATA
Start: 3885
Length: 13
Offset: 0,-3
BlendMode: Additive
- 4: DATA.R8
+ 4: DATA
Start: 3712
Length: 10
Offset: 0,-3
BlendMode: Additive
smoke_m:
- idle: DATA.R8
+ idle: DATA
Start: 3418
Length: 2
BlendMode: Additive
- loop: DATA.R8
+ loop: DATA
Start: 3418
Length: 2
BlendMode: Additive
- end: DATA.R8
+ end: DATA
Start: 3418
Length: 3
BlendMode: Additive
bombs:
- open: DATA.R8
+ open: DATA
Start: 3280
Length: 4
- idle: DATA.R8
+ idle: DATA
Start: 3280
Length: 4
@@ -248,59 +248,59 @@ waypoint:
Length: *
sietch:
- idle: DATA.R8
+ idle: DATA
Start: 2998
doubleblast:
- idle: DATA.R8
+ idle: DATA
Start: 3279
Facings: -16
BlendMode: Additive
doubleblastbullet:
- idle: DATA.R8
+ idle: DATA
Start: 3248
Facings: -16
BlendMode: Additive
icon:
- paratroopers: DATA.R8
+ paratroopers: DATA
Start: 4029
Offset: -30,-24
- ornistrike: DATA.R8
+ ornistrike: DATA
Start: 4031
Offset: -30,-24
- deathhand: DATA.R8
+ deathhand: DATA
Start: 4035
Offset: -30,-24
crate:
- idle: DATA.R8
+ idle: DATA
Start: 102
ZOffset: -511
Offset: -16,-16
- land: DATA.R8
+ land: DATA
Start: 102
ZOffset: -511
Offset: -16,-16
spicebloom:
- make: DATA.R8
+ make: DATA
Start: 107
Length: 3
Offset: -16,-16
- active: DATA.R8
+ active: DATA
Start: 109
Length: 1
ZOffset: -511
Offset: -16,-16
- idle: DATA.R8
+ idle: DATA
Start: 109
ZOffset: -511
Offset: -16,-16
moveflsh:
- idle: DATA.R8
+ idle: DATA
Start: 3621
Length: 5
Tick: 80
diff --git a/mods/d2k/sequences/structures.yaml b/mods/d2k/sequences/structures.yaml
index 03825fad21..61995dceb0 100644
--- a/mods/d2k/sequences/structures.yaml
+++ b/mods/d2k/sequences/structures.yaml
@@ -1,1618 +1,1618 @@
walla:
- idle: DATA.R8
+ idle: DATA
Frames: 2527, 2530, 2528, 2538, 2531, 2532, 2542, 2535, 2529, 2539, 2533, 2534, 2540, 2536, 2537, 2541
Length: 16
Offset: -16,16
- scratched-idle: DATA.R8
+ scratched-idle: DATA
Frames: 2527, 2530, 2528, 2538, 2531, 2532, 2542, 2535, 2529, 2539, 2533, 2534, 2540, 2536, 2537, 2541
Length: 16
Offset: -16,16
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Frames: 2543, 2546, 2544, 2554, 2547, 2548, 2558, 2551, 2545, 2555, 2549, 2550, 2556, 2552, 2553, 2557
Length: 16
Offset: -16,16
- critical-idle: DATA.R8
+ critical-idle: DATA
Frames: 2543, 2546, 2544, 2554, 2547, 2548, 2558, 2551, 2545, 2555, 2549, 2550, 2556, 2552, 2553, 2557
Length: 16
Offset: -16,16
- icon: DATA.R8
+ icon: DATA
Start: 4063
Offset: -30,-24
wallh:
- idle: DATA.R8
+ idle: DATA
Frames: 2687, 2690, 2688, 2698, 2691, 2692, 2702, 2695, 2689, 2699, 2693, 2694, 2700, 2696, 2697, 2701
Length: 16
Offset: -16,16
- scratched-idle: DATA.R8
+ scratched-idle: DATA
Frames: 2687, 2690, 2688, 2698, 2691, 2692, 2702, 2695, 2689, 2699, 2693, 2694, 2700, 2696, 2697, 2701
Length: 16
Offset: -16,16
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Frames: 2703, 2706, 2704, 2714, 2707, 2708, 2718, 2711, 2705, 2715, 2709, 2710, 2716, 2712, 2713, 2717
Length: 16
Offset: -16,16
- critical-idle: DATA.R8
+ critical-idle: DATA
Frames: 2703, 2706, 2704, 2714, 2707, 2708, 2718, 2711, 2705, 2715, 2709, 2710, 2716, 2712, 2713, 2717
Length: 16
Offset: -16,16
- icon: DATA.R8
+ icon: DATA
Start: 4064
Offset: -30,-24
wallo:
- idle: DATA.R8
+ idle: DATA
Frames: 2847, 2850, 2848, 2858, 2851, 2852, 2862, 2855, 2849, 2859, 2853, 2854, 2860, 2856, 2857, 2861
Length: 16
Offset: -16,16
- scratched-idle: DATA.R8
+ scratched-idle: DATA
Frames: 2847, 2850, 2848, 2858, 2851, 2852, 2862, 2855, 2849, 2859, 2853, 2854, 2860, 2856, 2857, 2861
Length: 16
Offset: -16,16
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Frames: 2863, 2866, 2864, 2874, 2867, 2868, 2878, 2871, 2865, 2875, 2869, 2870, 2876, 2872, 2873, 2877
Length: 16
Offset: -16,16
- critical-idle: DATA.R8
+ critical-idle: DATA
Frames: 2863, 2866, 2864, 2874, 2867, 2868, 2878, 2871, 2865, 2875, 2869, 2870, 2876, 2872, 2873, 2877
Length: 16
Offset: -16,16
- icon: DATA.R8
+ icon: DATA
Start: 4065
Offset: -30,-24
guntowera:
- idle: DATA.R8
+ idle: DATA
Start: 2573
Facings: 1
Offset: -24,24
- recoil: DATA.R8
+ recoil: DATA
Start: 2573
Facings: 1
Offset: -24,24
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 2573
Facings: 1
Offset: -24,24
- damaged-recoil: DATA.R8
+ damaged-recoil: DATA
Start: 2573
Facings: 1
Offset: -24,24
- turret: DATA.R8
+ turret: DATA
Start: 2589
Facings: -32
Offset: -24,24
- muzzle: DATA.R8
+ muzzle: DATA
Frames: 3775, 3775, 3776, 3776, 3777, 3777, 3778, 3778, 3779, 3779, 3780, 3780, 3781, 3781, 3782, 3782, 3783, 3783, 3784, 3784, 3785, 3785, 3786, 3786, 3787, 3787, 3788, 3788, 3789, 3789, 3790, 3790, 3791, 3791, 3792, 3792, 3793, 3793, 3794, 3794, 3795, 3795, 3796, 3796, 3797, 3797, 3798, 3798, 3799, 3799, 3800, 3800, 3801, 3801, 3802, 3802, 3803, 3803, 3804, 3804, 3805, 3805, 3806, 3806
Facings: -32
Length: 2
BlendMode: Additive
- icon: DATA.R8
+ icon: DATA
Start: 4069
Offset: -30,-24
guntowerh:
- idle: DATA.R8
+ idle: DATA
Start: 2733
Facings: 1
Offset: -24,24
- recoil: DATA.R8
+ recoil: DATA
Start: 2733
Facings: 1
Offset: -24,24
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 2733
Facings: 1
Offset: -24,24
- damaged-recoil: DATA.R8
+ damaged-recoil: DATA
Start: 2733
Facings: 1
Offset: -24,24
- turret: DATA.R8
+ turret: DATA
Start: 2749
Facings: -32
Offset: -24,24
- muzzle: DATA.R8
+ muzzle: DATA
Frames: 3775, 3775, 3776, 3776, 3777, 3777, 3778, 3778, 3779, 3779, 3780, 3780, 3781, 3781, 3782, 3782, 3783, 3783, 3784, 3784, 3785, 3785, 3786, 3786, 3787, 3787, 3788, 3788, 3789, 3789, 3790, 3790, 3791, 3791, 3792, 3792, 3793, 3793, 3794, 3794, 3795, 3795, 3796, 3796, 3797, 3797, 3798, 3798, 3799, 3799, 3800, 3800, 3801, 3801, 3802, 3802, 3803, 3803, 3804, 3804, 3805, 3805, 3806, 3806
Facings: -32
Length: 2
BlendMode: Additive
- icon: DATA.R8
+ icon: DATA
Frames: 4070
Offset: -30,-24
guntowero:
- idle: DATA.R8
+ idle: DATA
Start: 2893
Facings: 1
Offset: -24,24
- recoil: DATA.R8
+ recoil: DATA
Start: 2893
Facings: 1
Offset: -24,24
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 2893
Facings: 1
Offset: -24,24
- damaged-recoil: DATA.R8
+ damaged-recoil: DATA
Start: 2893
Facings: 1
Offset: -24,24
- turret: DATA.R8
+ turret: DATA
Start: 2909
Facings: -32
Offset: -24,24
- muzzle: DATA.R8
+ muzzle: DATA
Frames: 3775, 3775, 3776, 3776, 3777, 3777, 3778, 3778, 3779, 3779, 3780, 3780, 3781, 3781, 3782, 3782, 3783, 3783, 3784, 3784, 3785, 3785, 3786, 3786, 3787, 3787, 3788, 3788, 3789, 3789, 3790, 3790, 3791, 3791, 3792, 3792, 3793, 3793, 3794, 3794, 3795, 3795, 3796, 3796, 3797, 3797, 3798, 3798, 3799, 3799, 3800, 3800, 3801, 3801, 3802, 3802, 3803, 3803, 3804, 3804, 3805, 3805, 3806, 3806
Facings: -32
Length: 2
BlendMode: Additive
- icon: DATA.R8
+ icon: DATA
Start: 4071
Offset: -30,-24
rockettowera:
- idle: DATA.R8
+ idle: DATA
Start: 2733
Facings: 1
Offset: -24,24
- recoil: DATA.R8
+ recoil: DATA
Start: 2733
Facings: 1
Offset: -24,24
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 2733
Facings: 1
Offset: -24,24
- damaged-recoil: DATA.R8
+ damaged-recoil: DATA
Start: 2733
Facings: 1
Offset: -24,24
- turret: DATA.R8
+ turret: DATA
Start: 2637
Facings: -32
Offset: -24,24
- icon: DATA.R8
+ icon: DATA
Start: 4075
Offset: -30,-24
rockettowerh:
- idle: DATA.R8
+ idle: DATA
Start: 2781
Facings: 1
Offset: -24,24
- recoil: DATA.R8
+ recoil: DATA
Start: 2781
Facings: 1
Offset: -24,24
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 2781
Facings: 1
Offset: -24,24
- damaged-recoil: DATA.R8
+ damaged-recoil: DATA
Start: 2781
Facings: 1
Offset: -24,24
- turret: DATA.R8
+ turret: DATA
Start: 2797
Facings: -32
Offset: -24,24
- icon: DATA.R8
+ icon: DATA
Start: 4076
Offset: -30,-24
rockettowero:
- idle: DATA.R8
+ idle: DATA
Start: 2941
Facings: 1
Offset: -24,24
- recoil: DATA.R8
+ recoil: DATA
Start: 2941
Facings: 1
Offset: -24,24
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 2941
Facings: 1
Offset: -24,24
- damaged-recoil: DATA.R8
+ damaged-recoil: DATA
Start: 2941
Facings: 1
Offset: -24,24
- turret: DATA.R8
+ turret: DATA
Start: 2957
Facings: -32
Offset: -24,24
- icon: DATA.R8
+ icon: DATA
Start: 4077
Offset: -30,-24
conyarda:
- idle: DATA.R8
+ idle: DATA
Start: 2559
Offset: -48,64
- make: DATA.R8
+ make: DATA
Start: 4109
Length: 30
Offset: -48,64
- crumble-overlay: DATA.R8
+ crumble-overlay: DATA
Start: 4139
Length: 12
Offset: -48,64
Tick: 170
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 2560
Offset: -48,64
-# build: DATA.R8 # TODO: overlay
+# build: DATA # TODO: overlay
# Start: 4436
# Length: 14
# Offset: -48,64
-# damaged-build: DATA.R8 # TODO: overlay
+# damaged-build: DATA # TODO: overlay
# Start: 4436
# Length: 14
# Offset: -48,64
- bib: BLOXBASE.R8
+ bib: BLOXBASE
Frames: 611, 612, 613, 631, 632, 633
Length: 6
Offset: -16,-16
- icon: DATA.R8
+ icon: DATA
Start: 4046
Offset: -30,-24
repaira:
- make: DATA.R8
+ make: DATA
Start: 4370
Length: 10
Offset: -48,48
- crumble-overlay: DATA.R8
+ crumble-overlay: DATA
Start: 4380
Length: 10
Offset: -48,48
Tick: 100
- idle: DATA.R8
+ idle: DATA
Start: 2571
Offset: -48,48
ZOffset: -1c511
-# active: DATA.R8 # TODO: overlay
+# active: DATA # TODO: overlay
# Start: 4746
# Length: 14
# Offset: -48,48
# ZOffset: -1c511
-# damaged-active: DATA.R8 # TODO: overlay
+# damaged-active: DATA # TODO: overlay
# Start: 4746
# Length: 14
# Tick: 60
# Offset: -48,48
# ZOffset: -1c511
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 2572
Offset: -48,48
ZOffset: -1c511
- icon: DATA.R8
+ icon: DATA
Start: 4096
Offset: -30,-24
repairh:
- make: DATA.R8
+ make: DATA
Start: 4370
Length: 10
Offset: -48,48
- crumble-overlay: DATA.R8
+ crumble-overlay: DATA
Start: 4380
Length: 10
Offset: -48,48
Tick: 100
- idle: DATA.R8
+ idle: DATA
Start: 2731
Offset: -48,48
ZOffset: -1c511
-# active: DATA.R8 # TODO: overlay
+# active: DATA # TODO: overlay
# Start: 4746
# Length: 14
# Offset: -48,48
# ZOffset: -1c511
-# damaged-active: DATA.R8 # TODO: overlay
+# damaged-active: DATA # TODO: overlay
# Start: 4746
# Length: 14
# Tick: 60
# Offset: -48,48
# ZOffset: -1c511
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 2732
Offset: -48,48
ZOffset: -1c511
- icon: DATA.R8
+ icon: DATA
Start: 4097
Offset: -30,-24
repairo:
- make: DATA.R8
+ make: DATA
Start: 4370
Length: 10
Offset: -48,48
- crumble-overlay: DATA.R8
+ crumble-overlay: DATA
Start: 4380
Length: 10
Offset: -48,48
Tick: 100
- idle: DATA.R8
+ idle: DATA
Start: 2891
Offset: -48,48
ZOffset: -1c511
-# active: DATA.R8 # TODO: overlay
+# active: DATA # TODO: overlay
# Start: 4746
# Length: 14
# Offset: -48,48
# ZOffset: -1c511
-# damaged-active: DATA.R8 # TODO: overlay
+# damaged-active: DATA # TODO: overlay
# Start: 4746
# Length: 14
# Tick: 60
# Offset: -48,48
# ZOffset: -1c511
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 2892
Offset: -48,48
ZOffset: -1c511
- icon: DATA.R8
+ icon: DATA
Start: 4098
Offset: -30,-24
starporta:
- idle: DATA.R8
+ idle: DATA
Start: 2671
ZOffset: -1c511
Offset: -48,64
- active: DATA.R8
+ active: DATA
Start: 2671
Length: 1
ZOffset: -1c511
Offset: -48,64
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 2672
ZOffset: -1c511
Offset: -48,64
- damaged-active: DATA.R8
+ damaged-active: DATA
Start: 2672
ZOffset: -1c511
Offset: -48,64
- make: DATA.R8
+ make: DATA
Start: 4347
Length: 11
Offset: -48,64
- crumble-overlay: DATA.R8
+ crumble-overlay: DATA
Start: 4358
Length: 11
Offset: -48,64
Tick: 100
- bib: BLOXBASE.R8
+ bib: BLOXBASE
Frames: 611, 612, 613, 631, 632, 633
Length: 6
Offset: -16,-16
- icon: DATA.R8
+ icon: DATA
Start: 4092
Offset: -30,-24
pwra:
- idle: DATA.R8
+ idle: DATA
Start: 2523
Offset: -32,64
- make: DATA.R8
+ make: DATA
Start: 4151
Length: 12
Offset: -32,64
- crumble-overlay: DATA.R8
+ crumble-overlay: DATA
Start: 4163
Length: 12
Offset: -32,64
Tick: 100
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 2524
Offset: -32,64
- idle-zaps: DATA.R8
+ idle-zaps: DATA
Start: 4492
Length: 10
Offset: -32,64
Tick: 200
- damaged-idle-zaps: DATA.R8
+ damaged-idle-zaps: DATA
Start: 4497
Length: 5
Offset: -32,64
Tick: 200
- bib: BLOXBASE.R8
+ bib: BLOXBASE
Frames: 617, 618, 637, 638
Length: 4
Offset: -16,-16
- icon: DATA.R8
+ icon: DATA
Start: 4056
Offset: -30,-24
barra:
- idle: DATA.R8
+ idle: DATA
Start: 2525
Offset: -32,64
- make: DATA.R8
+ make: DATA
Start: 4213
Length: 8
Offset: -32,64
- crumble-overlay: DATA.R8
+ crumble-overlay: DATA
Start: 4221
Length: 9
Offset: -32,64
Tick: 100
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 2526
Offset: -32,64
- bib: BLOXBASE.R8
+ bib: BLOXBASE
Frames: 617, 618, 637, 638
Length: 4
Offset: -16,-16
- icon: DATA.R8
+ icon: DATA
Start: 4059
Offset: -30,-24
radara:
- idle: DATA.R8
+ idle: DATA
Start: 2521
Offset: -48,80
- make: DATA.R8
+ make: DATA
Start: 4254
Length: 9
Offset: -48,80
- crumble-overlay: DATA.R8
+ crumble-overlay: DATA
Start: 4263
Length: 10
Offset: -48,80
Tick: 100
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 2522
Offset: -48,80
- idle-dish: DATA.R8
+ idle-dish: DATA
Start: 4522
Length: 30
Offset: -48,80
- bib: BLOXBASE.R8
+ bib: BLOXBASE
Frames: 611, 612, 613, 631, 632, 633
Length: 6
Offset: -16,-16
- icon: DATA.R8
+ icon: DATA
Start: 4072
Offset: -30,-24
refa:
- idle: DATA.R8
+ idle: DATA
Start: 2561
Length: 1
Offset: -48,64
- make: DATA.R8
+ make: DATA
Start: 4231
Length: 11
Offset: -48,64
- crumble-overlay: DATA.R8
+ crumble-overlay: DATA
Start: 4241
Length: 12
Offset: -48,64
Tick: 100
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 2561
Offset: -48,64
- idle-top: DATA.R8
+ idle-top: DATA
Start: 2562
Offset: -48,64
- damaged-idle-top: DATA.R8
+ damaged-idle-top: DATA
Start: 2563
Offset: -48,64
- bib: BLOXBASE.R8
+ bib: BLOXBASE
Frames: 611, 612, 613, 631, 632, 633
Length: 6
Offset: -16,-16
- icon: DATA.R8
+ icon: DATA
Start: 4066
Offset: -30,-24
siloa:
- idle: DATA.R8
+ idle: DATA
Start: 2566
Length: 4
Offset: -16,16
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 2569
Length: 1
Offset: -16,16
- make: DATA.R8
+ make: DATA
Start: 4313
Length: 7
Offset: -16,16
- crumble-overlay: DATA.R8
+ crumble-overlay: DATA
Start: 4320
Length: 7
Offset: -16,16
Tick: 200
- icon: DATA.R8
+ icon: DATA
Start: 4084
Offset: -30,-24
hightecha:
- idle: DATA.R8
+ idle: DATA
Start: 2564
Offset: -48,80
- make: DATA.R8
+ make: DATA
Start: 4274
Length: 10
Offset: -48,80
- crumble-overlay: DATA.R8
+ crumble-overlay: DATA
Start: 4284
Length: 10
Offset: -48,80
Tick: 100
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 2565
Offset: -48,80
- idle-welding: DATA.R8
+ idle-welding: DATA
Start: 4614
Length: 30
Offset: -48,80
Tick: 500
BlendMode: Additive
- bib: BLOXBASE.R8
+ bib: BLOXBASE
Frames: 611, 612, 613, 631, 632, 633
Length: 6
Offset: -16,-16
- icon: DATA.R8
+ icon: DATA
Start: 4078
Offset: -30,-24
researcha:
- idle: DATA.R8
+ idle: DATA
Start: 2669
Offset: -48,80
- make: DATA.R8
+ make: DATA
Start: 4391
Length: 10
Offset: -48,80
- crumble-overlay: DATA.R8
+ crumble-overlay: DATA
Start: 4401
Length: 11
Offset: -48,80
Tick: 100
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 2670
Offset: -48,80
- idle-lights: DATA.R8
+ idle-lights: DATA
Start: 4760
Length: 60
Tick: 80
Offset: -48,80
- bib: BLOXBASE.R8
+ bib: BLOXBASE
Frames: 611, 612, 613, 631, 632, 633
Length: 6
Offset: -16,-16
- icon: DATA.R8
+ icon: DATA
Start: 4099
Offset: -30,-24
researchh:
- idle: DATA.R8
+ idle: DATA
Start: 2829
Offset: -48,80
- make: DATA.R8
+ make: DATA
Start: 4391
Length: 10
Offset: -48,80
- crumble-overlay: DATA.R8
+ crumble-overlay: DATA
Start: 4401
Length: 11
Offset: -48,80
Tick: 100
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 2830
Offset: -48,80
- idle-lights: DATA.R8
+ idle-lights: DATA
Start: 4760
Length: 60
Tick: 80
Offset: -48,80
- bib: BLOXBASE.R8
+ bib: BLOXBASE
Frames: 611, 612, 613, 631, 632, 633
Length: 6
Offset: -16,-16
- icon: DATA.R8
+ icon: DATA
Start: 4100
Offset: -30,-24
researcho:
- idle: DATA.R8
+ idle: DATA
Start: 2989
Offset: -48,80
- make: DATA.R8
+ make: DATA
Start: 4391
Length: 10
Offset: -48,80
- crumble-overlay: DATA.R8
+ crumble-overlay: DATA
Start: 4401
Length: 11
Offset: -48,80
Tick: 100
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 2990
Offset: -48,80
- idle-lights: DATA.R8
+ idle-lights: DATA
Start: 4760
Length: 60
Tick: 80
Offset: -48,80
- bib: BLOXBASE.R8
+ bib: BLOXBASE
Frames: 611, 612, 613, 631, 632, 633
Length: 6
Offset: -16,-16
- icon: DATA.R8
+ icon: DATA
Start: 4101
Offset: -30,-24
palacea:
- idle: DATA.R8
+ idle: DATA
Start: 2676
Offset: -48,48
- make: DATA.R8
+ make: DATA
Start: 4413
Length: 11
Offset: -48,64
- crumble-overlay: DATA.R8
+ crumble-overlay: DATA
Start: 4424
Length: 11
Offset: -48,64
Tick: 100
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 2677
Offset: -48,48
- bib: BLOXBASE.R8
+ bib: BLOXBASE
Frames: 611, 612, 613, 631, 632, 633
Length: 6
Offset: -16,-16
- icon: DATA.R8
+ icon: DATA
Start: 4102
Offset: -30,-24
lighta:
- idle: DATA.R8
+ idle: DATA
Start: 2673
Length: 1
Offset: -48,64
- make: DATA.R8
+ make: DATA
Start: 4295
Length: 8
Offset: -48,64
- crumble-overlay: DATA.R8
+ crumble-overlay: DATA
Start: 4303
Length: 9
Offset: -48,64
Tick: 100
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 2673
Offset: -48,64
- build-top: DATA.R8
+ build-top: DATA
Start: 2674
Length: 1
Offset: -48,64
- damaged-build-top: DATA.R8
+ damaged-build-top: DATA
Start: 2675
Length: 1
Offset: -48,64
- idle-top: DATA.R8
+ idle-top: DATA
Start: 2674
Offset: -48,64
- damaged-idle-top: DATA.R8
+ damaged-idle-top: DATA
Start: 2675
Offset: -48,64
- idle-welding: DATA.R8
+ idle-welding: DATA
Start: 4644
Length: 30
Offset: -48,64
Tick: 200
BlendMode: Additive
- bib: BLOXBASE.R8
+ bib: BLOXBASE
Frames: 611, 612, 613, 631, 632, 633
Length: 6
Offset: -16,-16
- icon: DATA.R8
+ icon: DATA
Start: 4081
Offset: -30,-24
heavya:
- idle: DATA.R8
+ idle: DATA
Start: 2518
Length: 1
Offset: -48,80
- make: DATA.R8
+ make: DATA
Start: 4328
Length: 9
Offset: -48,80
- crumble-overlay: DATA.R8
+ crumble-overlay: DATA
Start: 4337
Length: 9
Offset: -48,80
Tick: 100
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 2518
Offset: -48,80
- build-top: DATA.R8
+ build-top: DATA
Start: 2519
Length: 1
Offset: -48,80
- damaged-build-top: DATA.R8
+ damaged-build-top: DATA
Start: 2520
Length: 1
Offset: -48,80
- idle-top: DATA.R8
+ idle-top: DATA
Start: 2519
Offset: -48,80
- damaged-idle-top: DATA.R8
+ damaged-idle-top: DATA
Start: 2520
Offset: -48,80
- idle-welding: DATA.R8
+ idle-welding: DATA
Start: 4674
Length: 47
Offset: -48,80
Tick: 200
BlendMode: Additive
- bib: BLOXBASE.R8
+ bib: BLOXBASE
Frames: 611, 612, 613, 631, 632, 633
Length: 6
Offset: -16,-16
- icon: DATA.R8
+ icon: DATA
Start: 4087
Offset: -30,-24
conyardh:
- idle: DATA.R8
+ idle: DATA
Start: 2719
Offset: -48,64
- make: DATA.R8
+ make: DATA
Start: 4109
Length: 30
Offset: -48,64
- crumble-overlay: DATA.R8
+ crumble-overlay: DATA
Start: 4139
Length: 12
Offset: -48,64
Tick: 170
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 2720
Offset: -48,64
-# build: DATA.R8 # TODO: overlay
+# build: DATA # TODO: overlay
# Start: 4450
# Length: 14
# Offset: -48,64
-# damaged-build: DATA.R8 # TODO: overlay
+# damaged-build: DATA # TODO: overlay
# Start: 4450
# Length: 14
# Offset: -48,64
- bib: BLOXBASE.R8
+ bib: BLOXBASE
Frames: 611, 612, 613, 631, 632, 633
Length: 6
Offset: -16,-16
- icon: DATA.R8
+ icon: DATA
Start: 4047
Offset: -30,-24
starporth:
- idle: DATA.R8
+ idle: DATA
Start: 2831
ZOffset: -1c511
Offset: -48,64
- active: DATA.R8
+ active: DATA
Start: 2831
Length: 1
Offset: -48,64
ZOffset: -1c511
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 2832
Offset: -48,64
ZOffset: -1c511
- damaged-active: DATA.R8
+ damaged-active: DATA
Start: 2832
Offset: -48,64
ZOffset: -1c511
- make: DATA.R8
+ make: DATA
Start: 4347
Length: 11
Offset: -48,64
- crumble-overlay: DATA.R8
+ crumble-overlay: DATA
Start: 4358
Length: 11
Offset: -48,64
Tick: 100
- bib: BLOXBASE.R8
+ bib: BLOXBASE
Frames: 611, 612, 613, 631, 632, 633
Length: 6
Offset: -16,-16
- icon: DATA.R8
+ icon: DATA
Start: 4093
Offset: -30,-24
pwrh:
- idle: DATA.R8
+ idle: DATA
Start: 2683
Offset: -32,64
- make: DATA.R8
+ make: DATA
Start: 4151
Length: 12
Offset: -32,64
- crumble-overlay: DATA.R8
+ crumble-overlay: DATA
Start: 4163
Length: 12
Offset: -32,64
Tick: 100
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 2684
Offset: -32,64
- idle-zaps: DATA.R8
+ idle-zaps: DATA
Start: 4502
Length: 10
Offset: -32,64
Tick: 200
- damaged-idle-zaps: DATA.R8
+ damaged-idle-zaps: DATA
Start: 4507
Length: 5
Offset: -32,64
Tick: 200
- bib: BLOXBASE.R8
+ bib: BLOXBASE
Frames: 617, 618, 637, 638
Length: 4
Offset: -16,-16
- icon: DATA.R8
+ icon: DATA
Start: 4057
Offset: -30,-24
barrh:
- idle: DATA.R8
+ idle: DATA
Start: 2685
Offset: -32,64
- make: DATA.R8
+ make: DATA
Start: 4213
Length: 8
Offset: -32,64
- crumble-overlay: DATA.R8
+ crumble-overlay: DATA
Start: 4221
Length: 9
Offset: -32,64
Tick: 100
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 2686
Offset: -32,64
- bib: BLOXBASE.R8
+ bib: BLOXBASE
Frames: 617, 618, 637, 638
Length: 4
Offset: -16,-16
- icon: DATA.R8
+ icon: DATA
Start: 4060
Offset: -30,-24
radarh:
- idle: DATA.R8
+ idle: DATA
Start: 2681
Offset: -48,80
- make: DATA.R8
+ make: DATA
Start: 4254
Length: 9
Offset: -48,80
- crumble-overlay: DATA.R8
+ crumble-overlay: DATA
Start: 4263
Length: 10
Offset: -48,80
Tick: 100
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 2682
Offset: -48,80
- idle-dish: DATA.R8
+ idle-dish: DATA
Start: 4553
Length: 30
Offset: -48,80
- bib: BLOXBASE.R8
+ bib: BLOXBASE
Frames: 611, 612, 613, 631, 632, 633
Length: 6
Offset: -16,-16
- icon: DATA.R8
+ icon: DATA
Start: 4073
Offset: -30,-24
refh:
- idle: DATA.R8
+ idle: DATA
Start: 2721
Length: 1
Offset: -48,64
- make: DATA.R8
+ make: DATA
Start: 4231
Length: 11
Offset: -48,64
- crumble-overlay: DATA.R8
+ crumble-overlay: DATA
Start: 4241
Length: 12
Offset: -48,64
Tick: 100
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 2721
Offset: -48,64
- idle-top: DATA.R8
+ idle-top: DATA
Start: 2722
Offset: -48,64
- damaged-idle-top: DATA.R8
+ damaged-idle-top: DATA
Start: 2723
Offset: -48,64
- bib: BLOXBASE.R8
+ bib: BLOXBASE
Frames: 611, 612, 613, 631, 632, 633
Length: 6
Offset: -16,-16
- icon: DATA.R8
+ icon: DATA
Start: 4067
Offset: -30,-24
siloh:
- idle: DATA.R8
+ idle: DATA
Start: 2726
Length: 4
Offset: -16,16
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 2730
Length: 1
Offset: -16,16
- make: DATA.R8
+ make: DATA
Start: 4313
Length: 7
Offset: -16,16
- crumble-overlay: DATA.R8
+ crumble-overlay: DATA
Start: 4320
Length: 7
Offset: -16,16
Tick: 200
- icon: DATA.R8
+ icon: DATA
Start: 4085
Offset: -30,-24
hightechh:
- idle: DATA.R8
+ idle: DATA
Start: 2724
Offset: -48,80
- make: DATA.R8
+ make: DATA
Start: 4274
Length: 10
Offset: -48,80
- crumble-overlay: DATA.R8
+ crumble-overlay: DATA
Start: 4284
Length: 10
Offset: -48,80
Tick: 100
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 2725
Offset: -48,80
- idle-welding: DATA.R8
+ idle-welding: DATA
Start: 4614
Length: 30
Offset: -48,80
Tick: 500
BlendMode: Additive
- bib: BLOXBASE.R8
+ bib: BLOXBASE
Frames: 611, 612, 613, 631, 632, 633
Length: 6
Offset: -16,-16
- icon: DATA.R8
+ icon: DATA
Start: 4079
Offset: -30,-24
palaceh:
- idle: DATA.R8
+ idle: DATA
Start: 2836
Offset: -48,64
- make: DATA.R8
+ make: DATA
Start: 4413
Length: 11
Offset: -48,64
- crumble-overlay: DATA.R8
+ crumble-overlay: DATA
Start: 4424
Length: 11
Offset: -48,64
Tick: 100
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 2837
Offset: -48,64
-# active: DATA.R8 # TODO: overlay
+# active: DATA # TODO: overlay
# Start: 4820
# Length: 20
# Offset: -48,64
- damaged-active: DATA.R8
+ damaged-active: DATA
Start: 4820
Length: 20
Offset: -48,64
- bib: BLOXBASE.R8
+ bib: BLOXBASE
Frames: 611, 612, 613, 631, 632, 633
Length: 6
Offset: -16,-16
- icon: DATA.R8
+ icon: DATA
Start: 4103
Offset: -30,-24
lighth:
- idle: DATA.R8
+ idle: DATA
Start: 2833
Length: 1
Offset: -48,64
- make: DATA.R8
+ make: DATA
Start: 4295
Length: 8
Offset: -48,64
- crumble-overlay: DATA.R8
+ crumble-overlay: DATA
Start: 4303
Length: 9
Offset: -48,64
Tick: 100
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 2833
Offset: -48,64
- build-top: DATA.R8
+ build-top: DATA
Start: 2834
Length: 1
Offset: -48,64
- damaged-build-top: DATA.R8
+ damaged-build-top: DATA
Start: 2835
Length: 1
Offset: -48,64
- idle-top: DATA.R8
+ idle-top: DATA
Start: 2834
Offset: -48,64
- damaged-idle-top: DATA.R8
+ damaged-idle-top: DATA
Start: 2835
Offset: -48,64
- idle-welding: DATA.R8
+ idle-welding: DATA
Start: 4644
Length: 30
Offset: -48,64
Tick: 200
BlendMode: Additive
- bib: BLOXBASE.R8
+ bib: BLOXBASE
Frames: 611, 612, 613, 631, 632, 633
Length: 6
Offset: -16,-16
- icon: DATA.R8
+ icon: DATA
Start: 4082
Offset: -30,-24
heavyh:
- idle: DATA.R8
+ idle: DATA
Start: 2678
Length: 1
Offset: -48,80
- make: DATA.R8
+ make: DATA
Start: 4328
Length: 9
Offset: -48,80
- crumble-overlay: DATA.R8
+ crumble-overlay: DATA
Start: 4337
Length: 9
Offset: -48,80
Tick: 100
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 2678
Offset: -48,80
- build-top: DATA.R8
+ build-top: DATA
Start: 2679
Length: 1
Offset: -48,80
- damaged-build-top: DATA.R8
+ damaged-build-top: DATA
Start: 2680
Length: 1
Offset: -48,80
- idle-top: DATA.R8
+ idle-top: DATA
Start: 2679
Offset: -48,80
- damaged-idle-top: DATA.R8
+ damaged-idle-top: DATA
Start: 2680
Offset: -48,80
- idle-welding: DATA.R8
+ idle-welding: DATA
Start: 4674
Length: 47
Offset: -48,80
Tick: 200
BlendMode: Additive
- bib: BLOXBASE.R8
+ bib: BLOXBASE
Frames: 611, 612, 613, 631, 632, 633
Length: 6
Offset: -16,-16
- icon: DATA.R8
+ icon: DATA
Start: 4088
Offset: -30,-24
conyardo:
- idle: DATA.R8
+ idle: DATA
Start: 2879
Offset: -48,64
- make: DATA.R8
+ make: DATA
Start: 4109
Length: 30
Offset: -48,64
- crumble-overlay: DATA.R8
+ crumble-overlay: DATA
Start: 4139
Length: 12
Offset: -48,64
Tick: 170
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 2880
Offset: -48,64
-# build: DATA.R8 # TODO: overlay
+# build: DATA # TODO: overlay
# Start: 4464
# Length: 14
# Offset: -48,64
-# damaged-build: DATA.R8 # TODO: overlay
+# damaged-build: DATA # TODO: overlay
# Start: 4464
# Length: 14
# Offset: -48,64
- bib: BLOXBASE.R8
+ bib: BLOXBASE
Frames: 611, 612, 613, 631, 632, 633
Length: 6
Offset: -16,-16
- icon: DATA.R8
+ icon: DATA
Start: 4048
Offset: -30,-24
starporto:
- idle: DATA.R8
+ idle: DATA
Start: 2991
Offset: -48,64
ZOffset: -1c511
- active: DATA.R8
+ active: DATA
Start: 2991
Length: 1
Offset: -48,64
ZOffset: -1c511
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 2992
Offset: -48,64
ZOffset: -1c511
- damaged-active: DATA.R8
+ damaged-active: DATA
Start: 2992
Offset: -48,64
ZOffset: -1c511
- make: DATA.R8
+ make: DATA
Start: 4347
Length: 11
Offset: -48,64
- crumble-overlay: DATA.R8
+ crumble-overlay: DATA
Start: 4358
Length: 11
Offset: -48,64
Tick: 100
- bib: BLOXBASE.R8
+ bib: BLOXBASE
Frames: 611, 612, 613, 631, 632, 633
Length: 6
Offset: -16,-16
- icon: DATA.R8
+ icon: DATA
Start: 4094
Offset: -30,-24
pwro:
- idle: DATA.R8
+ idle: DATA
Start: 2843
Length: 1
Offset: -32,64
- make: DATA.R8
+ make: DATA
Start: 4151
Length: 12
Offset: -32,64
- crumble-overlay: DATA.R8
+ crumble-overlay: DATA
Start: 4163
Length: 12
Offset: -32,64
Tick: 100
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 2844
Offset: -32,64
- idle-zaps: DATA.R8
+ idle-zaps: DATA
Start: 4512
Length: 10
Offset: -32,64
Tick: 200
- damaged-idle-zaps: DATA.R8
+ damaged-idle-zaps: DATA
Start: 4517
Length: 5
Offset: -32,64
Tick: 200
- bib: BLOXBASE.R8
+ bib: BLOXBASE
Frames: 617, 618, 637, 638
Length: 4
Offset: -16,-16
- icon: DATA.R8
+ icon: DATA
Start: 4058
Offset: -30,-24
barro:
- idle: DATA.R8
+ idle: DATA
Start: 2845
Offset: -32,64
- make: DATA.R8
+ make: DATA
Start: 4213
Length: 8
Offset: -32,64
- crumble-overlay: DATA.R8
+ crumble-overlay: DATA
Start: 4221
Length: 9
Offset: -32,64
Tick: 100
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 2846
Offset: -32,64
- bib: BLOXBASE.R8
+ bib: BLOXBASE
Frames: 617, 618, 637, 638
Length: 4
Offset: -16,-16
- icon: DATA.R8
+ icon: DATA
Start: 4061
Offset: -30,-24
radaro:
- idle: DATA.R8
+ idle: DATA
Start: 2841
Offset: -48,80
- make: DATA.R8
+ make: DATA
Start: 4254
Length: 9
Offset: -48,80
- crumble-overlay: DATA.R8
+ crumble-overlay: DATA
Start: 4263
Length: 10
Offset: -48,80
Tick: 100
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 2842
Offset: -48,80
- idle-dish: DATA.R8
+ idle-dish: DATA
Start: 4583
Length: 30
Offset: -48,80
- bib: BLOXBASE.R8
+ bib: BLOXBASE
Frames: 611, 612, 613, 631, 632, 633
Length: 6
Offset: -16,-16
- icon: DATA.R8
+ icon: DATA
Start: 4074
Offset: -30,-24
refo:
- idle: DATA.R8
+ idle: DATA
Start: 2881
Length: 1
Offset: -48,64
- make: DATA.R8
+ make: DATA
Start: 4231
Length: 11
Offset: -48,64
- crumble-overlay: DATA.R8
+ crumble-overlay: DATA
Start: 4241
Length: 12
Offset: -48,64
Tick: 100
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 2881
Offset: -48,64
- idle-top: DATA.R8
+ idle-top: DATA
Start: 2882
Offset: -48,64
- damaged-idle-top: DATA.R8
+ damaged-idle-top: DATA
Start: 2883
Offset: -48,64
- bib: BLOXBASE.R8
+ bib: BLOXBASE
Frames: 611, 612, 613, 631, 632, 633
Length: 6
Offset: -16,-16
- icon: DATA.R8
+ icon: DATA
Start: 4068
Offset: -30,-24
siloo:
- idle: DATA.R8
+ idle: DATA
Start: 2886
Length: 4
Offset: -16,16
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 2890
Length: 1
Offset: -16,16
- make: DATA.R8
+ make: DATA
Start: 4313
Length: 7
Offset: -16,16
- crumble-overlay: DATA.R8
+ crumble-overlay: DATA
Start: 4320
Length: 7
Offset: -16,16
Tick: 200
- icon: DATA.R8
+ icon: DATA
Start: 4086
Offset: -30,-24
hightecho:
- idle: DATA.R8
+ idle: DATA
Start: 2884
Offset: -48,80
- make: DATA.R8
+ make: DATA
Start: 4274
Length: 10
Offset: -48,80
- crumble-overlay: DATA.R8
+ crumble-overlay: DATA
Start: 4284
Length: 10
Offset: -48,80
Tick: 100
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 2885
Offset: -48,80
- idle-welding: DATA.R8
+ idle-welding: DATA
Start: 4614
Length: 30
Offset: -48,80
Tick: 500
BlendMode: Additive
- bib: BLOXBASE.R8
+ bib: BLOXBASE
Frames: 611, 612, 613, 631, 632, 633
Length: 6
Offset: -16,-16
- icon: DATA.R8
+ icon: DATA
Start: 4080
Offset: -30,-24
palaceo:
- idle: DATA.R8
+ idle: DATA
Start: 2996
Offset: -48,64
- make: DATA.R8
+ make: DATA
Start: 4413
Length: 11
Offset: -48,64
- crumble-overlay: DATA.R8
+ crumble-overlay: DATA
Start: 4424
Length: 11
Offset: -48,64
Tick: 100
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 2997
Offset: -48,64
- bib: BLOXBASE.R8
+ bib: BLOXBASE
Frames: 611, 612, 613, 631, 632, 633
Length: 6
Offset: -16,-16
- icon: DATA.R8
+ icon: DATA
Start: 4104
Offset: -30,-24
lighto:
- idle: DATA.R8
+ idle: DATA
Start: 2993
Length: 1
Offset: -48,64
- make: DATA.R8
+ make: DATA
Start: 4295
Length: 8
Offset: -48,64
- crumble-overlay: DATA.R8
+ crumble-overlay: DATA
Start: 4303
Length: 9
Offset: -48,64
Tick: 100
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 2993
Offset: -48,64
- build-top: DATA.R8
+ build-top: DATA
Start: 2994
Length: 1
Offset: -48,64
- damaged-build-top: DATA.R8
+ damaged-build-top: DATA
Start: 2995
Length: 1
Offset: -48,64
- idle-top: DATA.R8
+ idle-top: DATA
Start: 2994
Offset: -48,64
- damaged-idle-top: DATA.R8
+ damaged-idle-top: DATA
Start: 2995
Offset: -48,64
- idle-welding: DATA.R8
+ idle-welding: DATA
Start: 4644
Length: 30
Offset: -48,64
Tick: 200
BlendMode: Additive
- bib: BLOXBASE.R8
+ bib: BLOXBASE
Frames: 611, 612, 613, 631, 632, 633
Length: 6
Offset: -16,-16
- icon: DATA.R8
+ icon: DATA
Start: 4083
Offset: -30,-24
heavyo:
- idle: DATA.R8
+ idle: DATA
Start: 2838
Length: 1
Offset: -48,80
- make: DATA.R8
+ make: DATA
Start: 4328
Length: 9
Offset: -48,80
- crumble-overlay: DATA.R8
+ crumble-overlay: DATA
Start: 4337
Length: 9
Offset: -48,80
Tick: 100
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 2838
Offset: -48,80
- build-top: DATA.R8
+ build-top: DATA
Start: 2839
Length: 1
Offset: -48,80
- damaged-build-top: DATA.R8
+ damaged-build-top: DATA
Start: 2840
Length: 1
Offset: -48,80
- idle-top: DATA.R8
+ idle-top: DATA
Start: 2839
Offset: -48,80
- damaged-idle-top: DATA.R8
+ damaged-idle-top: DATA
Start: 2840
Offset: -48,80
- idle-welding: DATA.R8
+ idle-welding: DATA
Start: 4674
Length: 47
Offset: -48,80
Tick: 200
BlendMode: Additive
- bib: BLOXBASE.R8
+ bib: BLOXBASE
Frames: 611, 612, 613, 631, 632, 633
Length: 6
Offset: -16,-16
- icon: DATA.R8
+ icon: DATA
Start: 4089
Offset: -30,-24
palacec: # TODO: unused
- idle: DATA.R8
+ idle: DATA
Start: 3004
Offset: -48,64
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 3005
Offset: -48,64
- bib: BLOXBASE.R8
+ bib: BLOXBASE
Frames: 611, 612, 613, 631, 632, 633
Length: 6
Offset: -16,-16
icon: palacecicon
Start: 0
- make: DATA.R8
+ make: DATA
Start: 4413
Length: 11
Offset: -48,64
- crumble-overlay: DATA.R8
+ crumble-overlay: DATA
Start: 4424
Length: 11
Offset: -48,64
Tick: 100
starportc: # TODO: unused
- idle: DATA.R8
+ idle: DATA
Start: 2999
Offset: -48,64
ZOffset: -1c511
- active: DATA.R8
+ active: DATA
Start: 2999
Length: 1
Offset: -48,64
ZOffset: -1c511
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 3000
Offset: -48,64
ZOffset: -1c511
- damaged-active: DATA.R8
+ damaged-active: DATA
Start: 3000
Offset: -48,64
ZOffset: -1c511
- make: DATA.R8
+ make: DATA
Start: 4347
Length: 11
Offset: -48,64
- crumble-overlay: DATA.R8
+ crumble-overlay: DATA
Start: 4358
Length: 11
Offset: -48,64
Tick: 100
- bib: BLOXBASE.R8
+ bib: BLOXBASE
Frames: 611, 612, 613, 631, 632, 633
Length: 6
Offset: -16,-16
- icon: DATA.R8 # TODO: blank
+ icon: DATA # TODO: blank
Start: 4020
Offset: -30,-24
heavyc: # TODO: unused
- idle: DATA.R8
+ idle: DATA
Start: 3001
Length: 1
Offset: -48,64
- make: DATA.R8
+ make: DATA
Start: 4328
Length: 9
Offset: -48,80
- crumble-overlay: DATA.R8
+ crumble-overlay: DATA
Start: 4337
Length: 9
Offset: -48,80
Tick: 100
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 3001
Offset: -48,64
- build-top: DATA.R8
+ build-top: DATA
Start: 3002
Length: 1
Offset: -48,64
- damaged-build-top: DATA.R8
+ damaged-build-top: DATA
Start: 3003
Length: 1
Offset: -48,64
- idle-top: DATA.R8
+ idle-top: DATA
Start: 3002
Offset: -48,64
- damaged-idle-top: DATA.R8
+ damaged-idle-top: DATA
Start: 3003
Offset: -48,64
- idle-welding: DATA.R8
+ idle-welding: DATA
Start: 4674
Length: 47
Offset: -48,80
Tick: 200
BlendMode: Additive
- bib: BLOXBASE.R8
+ bib: BLOXBASE
Frames: 611, 612, 613, 631, 632, 633
Length: 6
Offset: -16,-16
- icon: DATA.R8 # TODO: blank
+ icon: DATA # TODO: blank
Start: 4020
Offset: -30,-24
conyardc: # TODO: unused
- idle: DATA.R8
+ idle: DATA
Start: 3006
Offset: -48,64
- make: DATA.R8
+ make: DATA
Start: 4109
Length: 30
Offset: -48,64
- crumble-overlay: DATA.R8
+ crumble-overlay: DATA
Start: 4139
Length: 12
Offset: -48,64
Tick: 200
- damaged-idle: DATA.R8
+ damaged-idle: DATA
Start: 3007
Offset: -48,64
-# build: DATA.R8 # TODO: overlay
+# build: DATA # TODO: overlay
# Start: 4478
# Length: 14
# Offset: -48,64
-# damaged-build: DATA.R8 # TODO: overlay
+# damaged-build: DATA # TODO: overlay
# Start: 4478
# Length: 14
# Offset: -48,64
- bib: BLOXBASE.R8
+ bib: BLOXBASE
Frames: 611, 612, 613, 631, 632, 633
Length: 6
Offset: -16,-16
- icon: DATA.R8
+ icon: DATA
Start: 4049
Offset: -30,-24
plates: # TODO: unused
- idle: DATA.R8
+ idle: DATA
Start: 3008
Length: 6
- 4-plates-icon: DATA.R8
+ 4-plates-icon: DATA
Start: 4050
Offset: -30,-24
- 6-plates-icon: DATA.R8
+ 6-plates-icon: DATA
Start: 4053
Offset: -30,-24
diff --git a/mods/d2k/sequences/vehicles.yaml b/mods/d2k/sequences/vehicles.yaml
index 3d8fe4debf..c562658597 100644
--- a/mods/d2k/sequences/vehicles.yaml
+++ b/mods/d2k/sequences/vehicles.yaml
@@ -1,174 +1,174 @@
dmcv:
- idle: DATA.R8
+ idle: DATA
Start: 1795
Facings: -32
- icon: DATA.R8
+ icon: DATA
Start: 4023
Offset: -30,-24
harvester:
- idle: DATA.R8
+ idle: DATA
Start: 1699
Facings: -32
- harvest: DATA.R8
+ harvest: DATA
Start: 3631
Length: 6
Facings: -8
Tick: 80
ZOffset: 1
- dock: DATA.R8
+ dock: DATA
Start: 3370
Length: 10
- dock-loop: DATA.R8
+ dock-loop: DATA
Start: 3380
Length: 1
- icon: DATA.R8
+ icon: DATA
Start: 4019
Offset: -30,-24
trike:
- idle: DATA.R8
+ idle: DATA
Start: 1635
Facings: -32
- unload: DATA.R8
+ unload: DATA
Start: 1635
Facings: -32
- muzzle: DATA.R8
+ muzzle: DATA
Frames: 3839, 3839, 3840, 3840, 3841, 3841, 3842, 3842, 3843, 3843, 3844, 3844, 3845, 3845, 3846, 3846, 3847, 3847, 3848, 3848, 3849, 3849, 3850, 3850, 3851, 3851, 3852, 3852, 3853, 3853, 3854, 3854, 3855, 3855, 3856, 3856, 3857, 3857, 3858, 3858, 3859, 3859, 3860, 3860, 3861, 3861, 3862, 3862, 3863, 3863, 3864, 3864, 3865, 3865, 3866, 3866, 3867, 3867, 3868, 3868, 3869, 3869, 3870, 3870
Facings: -32
Length: 2
BlendMode: Additive
- icon: DATA.R8
+ icon: DATA
Start: 4041
Offset: -30,-24
quad:
- idle: DATA.R8
+ idle: DATA
Start: 1667
Facings: -32
- unload: DATA.R8
+ unload: DATA
Start: 1667
Facings: -32
- icon: DATA.R8
+ icon: DATA
Start: 4018
Offset: -30,-24
siegetank:
- idle: DATA.R8
+ idle: DATA
Start: 1763
Facings: -32
- turret: DATA.R8
+ turret: DATA
Start: 1891
Facings: -32
- muzzle: DATA.R8
+ muzzle: DATA
Start: 3418
Length: 3
BlendMode: Additive
- icon: DATA.R8
+ icon: DATA
Start: 4026
Offset: -30,-24
missiletank:
- idle: DATA.R8
+ idle: DATA
Start: 1603
Facings: -32
- icon: DATA.R8
+ icon: DATA
Start: 4024
Offset: -30,-24
sonictank:
- idle: DATA.R8
+ idle: DATA
Start: 1827
Facings: -32
- icon: DATA.R8
+ icon: DATA
Start: 4027
Offset: -30,-24
combata:
- idle: DATA.R8
+ idle: DATA
Start: 1731
Facings: -32
- turret: DATA.R8
+ turret: DATA
Start: 1859
Facings: -32
- muzzle: DATA.R8
+ muzzle: DATA
Frames: 3775, 3775, 3776, 3776, 3777, 3777, 3778, 3778, 3779, 3779, 3780, 3780, 3781, 3781, 3782, 3782, 3783, 3783, 3784, 3784, 3785, 3785, 3786, 3786, 3787, 3787, 3788, 3788, 3789, 3789, 3790, 3790, 3791, 3791, 3792, 3792, 3793, 3793, 3794, 3794, 3795, 3795, 3796, 3796, 3797, 3797, 3798, 3798, 3799, 3799, 3800, 3800, 3801, 3801, 3802, 3802, 3803, 3803, 3804, 3804, 3805, 3805, 3806, 3806
Facings: -32
Length: 2
BlendMode: Additive
- icon: DATA.R8
+ icon: DATA
Start: 4020
Offset: -30,-24
combath:
- idle: DATA.R8
+ idle: DATA
Start: 2051
Facings: -32
- turret: DATA.R8
+ turret: DATA
Start: 2115
Facings: -32
- muzzle: DATA.R8
+ muzzle: DATA
Frames: 3775, 3775, 3776, 3776, 3777, 3777, 3778, 3778, 3779, 3779, 3780, 3780, 3781, 3781, 3782, 3782, 3783, 3783, 3784, 3784, 3785, 3785, 3786, 3786, 3787, 3787, 3788, 3788, 3789, 3789, 3790, 3790, 3791, 3791, 3792, 3792, 3793, 3793, 3794, 3794, 3795, 3795, 3796, 3796, 3797, 3797, 3798, 3798, 3799, 3799, 3800, 3800, 3801, 3801, 3802, 3802, 3803, 3803, 3804, 3804, 3805, 3805, 3806, 3806
Facings: -32
Length: 2
BlendMode: Additive
- icon: DATA.R8
+ icon: DATA
Start: 4021
Offset: -30,-24
devast:
- idle: DATA.R8
+ idle: DATA
Start: 2083
Facings: -32
- muzzle: DATA.R8
+ muzzle: DATA
Frames: 3807, 3807, 3808, 3808, 3809, 3809, 3810, 3810, 3810, 3811, 3811, 3812, 3812, 3813, 3813, 3814, 3814, 3815, 3816, 3816, 3817, 3817, 3818, 3819, 3819, 3820, 3820, 3821, 3821, 3822, 3822, 3823, 3823, 3824, 3824, 3825, 3825, 3826, 3826, 3827, 3827, 3828, 3828, 3829, 3829, 3830, 3830, 3831, 3831, 3832, 3832, 3832, 3833, 3833, 3834, 3834, 3835, 3835, 3836, 3836, 3837, 3837, 3838, 3838
Facings: -32
Length: 2
BlendMode: Additive
- icon: DATA.R8
+ icon: DATA
Start: 4028
Offset: -30,-24
combato:
- idle: DATA.R8
+ idle: DATA
Start: 2453
Facings: -32
- turret: DATA.R8
+ turret: DATA
Start: 2485
Facings: -32
- muzzle: DATA.R8
+ muzzle: DATA
Frames: 3775, 3775, 3776, 3776, 3777, 3777, 3778, 3778, 3779, 3779, 3780, 3780, 3781, 3781, 3782, 3782, 3783, 3783, 3784, 3784, 3785, 3785, 3786, 3786, 3787, 3787, 3788, 3788, 3789, 3789, 3790, 3790, 3791, 3791, 3792, 3792, 3793, 3793, 3794, 3794, 3795, 3795, 3796, 3796, 3797, 3797, 3798, 3798, 3799, 3799, 3800, 3800, 3801, 3801, 3802, 3802, 3803, 3803, 3804, 3804, 3805, 3805, 3806, 3806
Facings: -32
Length: 2
BlendMode: Additive
- icon: DATA.R8
+ icon: DATA
Start: 4022
Offset: -30,-24
raider:
- idle: DATA.R8
+ idle: DATA
Start: 2421
Facings: -32
- unload: DATA.R8
+ unload: DATA
Start: 2421
Facings: -32
- muzzle: DATA.R8
+ muzzle: DATA
Frames: 3743, 3743, 3744, 3744, 3745, 3745, 3746, 3746, 3747, 3747, 3748, 3748, 3749, 3749, 3750, 3750, 3751, 3751, 3752, 3752, 3753, 3753, 3754, 3754, 3755, 3755, 3756, 3756, 3757, 3757, 3758, 3758, 3759, 3759, 3760, 3760, 3761, 3761, 3762, 3762, 3763, 3763, 3764, 3764, 3765, 3765, 3766, 3766, 3767, 3767, 3768, 3768, 3769, 3769, 3770, 3770, 3771, 3771, 3772, 3772, 3773, 3773, 3774, 3774
Facings: -32
Length: 2
BlendMode: Additive
- icon: DATA.R8
+ icon: DATA
Start: 4017
Offset: -30,-24
stealthraider:
- idle: DATA.R8
+ idle: DATA
Start: 2421
Facings: -32
- unload: DATA.R8
+ unload: DATA
Start: 2421
Facings: -32
- muzzle: DATA.R8
+ muzzle: DATA
Frames: 3743, 3743, 3744, 3744, 3745, 3745, 3746, 3746, 3747, 3747, 3748, 3748, 3749, 3749, 3750, 3750, 3751, 3751, 3752, 3752, 3753, 3753, 3754, 3754, 3755, 3755, 3756, 3756, 3757, 3757, 3758, 3758, 3759, 3759, 3760, 3760, 3761, 3761, 3762, 3762, 3763, 3763, 3764, 3764, 3765, 3765, 3766, 3766, 3767, 3767, 3768, 3768, 3769, 3769, 3770, 3770, 3771, 3771, 3772, 3772, 3773, 3773, 3774, 3774
Facings: -32
Length: 2
@@ -177,9 +177,9 @@ stealthraider:
Start: 0
deviatortank:
- idle: DATA.R8
+ idle: DATA
Start: 2389
Facings: -32
- icon: DATA.R8
+ icon: DATA
Start: 4025
Offset: -30,-24
\ No newline at end of file
diff --git a/mods/d2k/tilesets/arrakis.yaml b/mods/d2k/tilesets/arrakis.yaml
index ddc8992a5a..54c531b82e 100644
--- a/mods/d2k/tilesets/arrakis.yaml
+++ b/mods/d2k/tilesets/arrakis.yaml
@@ -3,7 +3,7 @@ General:
Id: ARRAKIS
SheetSize: 1024
Palette: d2k.pal
- Extensions: .R8, .shp
+ Extensions: .R8, .r8, .shp
Terrain:
TerrainType@Sand:
diff --git a/mods/ra/chrome/assetbrowser.yaml b/mods/ra/chrome/assetbrowser.yaml
index bf313b1c9b..ef5fea2547 100644
--- a/mods/ra/chrome/assetbrowser.yaml
+++ b/mods/ra/chrome/assetbrowser.yaml
@@ -3,29 +3,36 @@ Background@ASSETBROWSER_BG:
X:(WINDOW_RIGHT - WIDTH)/2
Y:(WINDOW_BOTTOM - HEIGHT)/2
Width:700
- Height:410
+ Height:500
Children:
ColorPreviewManager@COLOR_MANAGER:
Label@ASSETBROWSER_TITLE:
- X:0
- Y:10
+ Y:20
Width:PARENT_RIGHT
Height:25
- Text:Game Asset Viewer & Converter
- Align:Center
Font:Bold
+ Align:Center
+ Text:Asset Browser
+ Label@SOURCE_SELECTOR_DESC:
+ X:20
+ Y:35
+ Width:160
+ Height:25
+ Font:TinyBold
+ Align:Center
+ Text:Select asset source
DropDownButton@SOURCE_SELECTOR:
- X:40
- Y:45
+ X:20
+ Y:60
Width:160
Height:25
Font:Bold
Text:Folders
ScrollPanel@ASSET_LIST:
- X:40
- Y:80
+ X:20
+ Y:90
Width:160
- Height:190
+ Height:275
Children:
ScrollItem@ASSET_TEMPLATE:
Width:PARENT_RIGHT-27
@@ -38,30 +45,45 @@ Background@ASSETBROWSER_BG:
X:10
Width:PARENT_RIGHT-20
Height:25
+ Label@FILENAME_DESC:
+ X:20
+ Y:370
+ Width:160
+ Height:25
+ Font:TinyBold
+ Align:Center
+ Text:Search for file
TextField@FILENAME_INPUT:
- X:40
- Y:280
- Width:140
+ X:20
+ Y:395
+ Width:160
Height:25
Text:mouse.shp
Button@LOAD_BUTTON:
- X:40
- Y:310
- Width:140
+ X:20
+ Y:425
+ Width:160
Height:25
Text:Load
Font:Bold
Key:return
- DropDownButton@PALETTE_SELECTOR:
- X:230
- Y:45
+ Label@PALETTE_DESC:
+ X:PARENT_RIGHT-WIDTH-270
+ Y:60
+ Width:150
+ Height:25
+ Font:Bold
+ Align:Right
+ Text:Palette:
+ DropDownButton@PALETTE_SELECTOR:
+ X:PARENT_RIGHT-WIDTH-110
+ Y:60
Width:150
Height:25
Font:Bold
- Text:Palette
DropDownButton@COLOR:
- X:380
- Y:45
+ X:PARENT_RIGHT-WIDTH-20
+ Y:60
Width:80
Height:25
Children:
@@ -71,69 +93,19 @@ Background@ASSETBROWSER_BG:
Width:PARENT_RIGHT-35
Height:PARENT_BOTTOM-12
Background@SPRITE_BG:
- X:220
- Y:80
- Width:250
- Height:250
- Background:dialog4
+ X:190
+ Y:90
+ Width:490
+ Height:330
+ Background:dialog3
Children:
ShpImage@SPRITE:
- X:4
- Y:4
- Width:246
- Height:246
+ Width:PARENT_RIGHT
+ Height:PARENT_BOTTOM
Image:mouse
- Label@ACTIONS_TITLE:
- X:PARENT_RIGHT - 150
- Y:45
- Width:PARENT_RIGHT
- Height:25
- Text:Actions
- Font:Bold
- Button@EXPORT_BUTTON:
- X:PARENT_RIGHT - 200
- Y:80
- Width:160
- Height:25
- Text:Selected to PNG
- Font:Bold
- Button@EXTRACT_BUTTON:
- X:PARENT_RIGHT - 200
- Y:115
- Width:160
- Height:25
- Text:Extract all to PNG
- Font:Bold
- TextField@IMAGE_FILENAME_INPUT:
- X:PARENT_RIGHT - 200
- Y:PARENT_BOTTOM - 235
- Width:100
- Height:25
- Text:pixelart.png
- TextField@IMAGE_SIZE_INPUT:
- X:PARENT_RIGHT - 90
- Y:PARENT_BOTTOM - 235
- Width:50
- Height:25
- Text:width
- Button@IMPORT_BUTTON:
- X:PARENT_RIGHT - 200
- Y:PARENT_BOTTOM - 200
- Width:160
- Height:25
- Text:Import from PNG
- Font:Bold
- Button@CLOSE_BUTTON:
- X:PARENT_RIGHT - 200
- Y:PARENT_BOTTOM - 115
- Width:160
- Height:25
- Text:Close
- Font:Bold
- Key:escape
Container@FRAME_SELECTOR:
- X:45
- Y:360
+ X:190
+ Y:425
Children:
Button@BUTTON_PREV:
X:0
@@ -202,14 +174,22 @@ Background@ASSETBROWSER_BG:
ImageCollection:music
ImageName:next
Slider@FRAME_SLIDER:
- X:160
- Y:0
- Width:410
+ X:140
+ Y:3
+ Width:300
Height:20
MinimumValue: 0
Label@FRAME_COUNT:
- X:585
- Y:0
- Width:25
+ X:445
+ Width:40
Height:25
- Font:Bold
\ No newline at end of file
+ Font:TinyBold
+ Align:Left
+ Button@CLOSE_BUTTON:
+ Key:escape
+ X:PARENT_RIGHT-180
+ Y:PARENT_BOTTOM-45
+ Width:160
+ Height:25
+ Font:Bold
+ Text:Close
\ No newline at end of file
diff --git a/mods/ra/chrome/color-picker.yaml b/mods/ra/chrome/color-picker.yaml
index 543e01b5c3..0daef841a9 100644
--- a/mods/ra/chrome/color-picker.yaml
+++ b/mods/ra/chrome/color-picker.yaml
@@ -30,8 +30,10 @@ Background@COLOR_CHOOSER:
Width:144
Height:72
ShpImage@FACT:
- X:156
+ X:153
Y:1
+ Width:80
+ Height:73
Image:fact
Palette:colorpicker
Button@RANDOM_BUTTON:
diff --git a/mods/ra/chrome/convertassets.yaml b/mods/ra/chrome/convertassets.yaml
deleted file mode 100644
index ecd4cc73af..0000000000
--- a/mods/ra/chrome/convertassets.yaml
+++ /dev/null
@@ -1,47 +0,0 @@
-Background@CONVERT_ASSETS_PANEL:
- Logic:ConvertGameFilesLogic
- X:(WINDOW_RIGHT - WIDTH)/2
- Y:(WINDOW_BOTTOM - HEIGHT)/2
- Width:500
- Height:160
- Children:
- Label@TITLE:
- X:0
- Y:20
- Width:PARENT_RIGHT
- Height:25
- Text:Extracting and Converting Gamefiles
- Align:Center
- Font:Bold
- Container@EXTRACTING:
- Width:PARENT_RIGHT
- Height:PARENT_BOTTOM
- Visible: false
- Children:
- ProgressBar@PROGRESS_BAR:
- X:50
- Y:55
- Width:PARENT_RIGHT - 100
- Height:25
- Label@STATUS_LABEL:
- X:50
- Y:80
- Width:PARENT_RIGHT - 100
- Height:25
- Align:Left
- Button@RETRY_BUTTON:
- X:PARENT_RIGHT - 280
- Y:PARENT_BOTTOM - 45
- Width:120
- Height:25
- Text:Retry
- Font:Bold
- Key:return
- Button@BACK_BUTTON:
- X:PARENT_RIGHT - 140
- Y:PARENT_BOTTOM - 45
- Width:120
- Height:25
- Text:Back
- Font:Bold
- Key:escape
\ No newline at end of file
diff --git a/mods/ra/chrome/modchooser.yaml b/mods/ra/chrome/modchooser.yaml
index e11d52b424..9a9bcc7f91 100644
--- a/mods/ra/chrome/modchooser.yaml
+++ b/mods/ra/chrome/modchooser.yaml
@@ -7,14 +7,15 @@ Background@MODS_PANEL:
Children:
Label@TITLE:
Text:Select Mod
- Width:PARENT_RIGHT
Y:20
+ Width:PARENT_RIGHT
+ Height:25
Font:Bold
Align:Center
ScrollPanel@MOD_LIST:
- X:15
+ X:20
Y:70
- Width:710
+ Width:700
Height:PARENT_BOTTOM - 125
Children:
ScrollItem@MOD_TEMPLATE:
diff --git a/mods/ra/cursors.yaml b/mods/ra/cursors.yaml
index 0e3e4c0347..929db975b1 100644
--- a/mods/ra/cursors.yaml
+++ b/mods/ra/cursors.yaml
@@ -2,7 +2,7 @@
cursor: cursor.pal
Cursors:
- mouse: cursor
+ mouse.shp: cursor
scroll-t:
start:1
scroll-tr:
@@ -163,7 +163,7 @@ Cursors:
start:148
length: 12
- nopower: cursor
+ nopower.shp: cursor
powerdown-blocked:
start:0
length: 1
diff --git a/mods/ra/mod.yaml b/mods/ra/mod.yaml
index e36a9a7edb..630f97383f 100644
--- a/mods/ra/mod.yaml
+++ b/mods/ra/mod.yaml
@@ -92,7 +92,6 @@ ChromeLayout:
mods/ra/chrome/musicplayer.yaml
mods/ra/chrome/tooltips.yaml
mods/ra/chrome/assetbrowser.yaml
- mods/ra/chrome/convertassets.yaml
mods/ra/chrome/irc.yaml
Weapons:
diff --git a/mods/ts/chrome/color-picker.yaml b/mods/ts/chrome/color-picker.yaml
index e7553cd415..6e33ea9771 100644
--- a/mods/ts/chrome/color-picker.yaml
+++ b/mods/ts/chrome/color-picker.yaml
@@ -30,8 +30,10 @@ Background@COLOR_CHOOSER:
Width:144
Height:72
ShpImage@GTCNST:
- X:121
- Y:0-68
+ X:153
+ Y:1-40
+ Width:80
+ Height:73
Image:gtcnstmk
Palette:colorpicker
Button@RANDOM_BUTTON:
diff --git a/mods/ts/cursors.yaml b/mods/ts/cursors.yaml
index 6ae5c78658..dcd50bde72 100644
--- a/mods/ts/cursors.yaml
+++ b/mods/ts/cursors.yaml
@@ -2,7 +2,7 @@
cursor: mousepal.pal
Cursors:
- mouse: cursor
+ mouse.shp: cursor
scroll-t: #TODO
start: 2
scroll-tr: #TODO
diff --git a/mods/ts/mod.yaml b/mods/ts/mod.yaml
index 0030ff7b92..ffb690c447 100644
--- a/mods/ts/mod.yaml
+++ b/mods/ts/mod.yaml
@@ -120,7 +120,6 @@ ChromeLayout:
mods/ra/chrome/musicplayer.yaml
mods/ra/chrome/tooltips.yaml
mods/ra/chrome/assetbrowser.yaml
- mods/ra/chrome/convertassets.yaml
mods/ra/chrome/irc.yaml
Weapons: