Add MapGrid class
MapGrid is a mod Manifest field which includes (and thus makes redundant) TileSize, TileShape, SubCells info and MaximumTerrainHeight.
This commit is contained in:
@@ -44,7 +44,7 @@ namespace OpenRA
|
||||
|
||||
public MPos ToMPos(Map map)
|
||||
{
|
||||
return ToMPos(map.TileShape);
|
||||
return ToMPos(map.Grid.Type);
|
||||
}
|
||||
|
||||
public MPos ToMPos(TileShape shape)
|
||||
|
||||
@@ -20,12 +20,12 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
public static Bitmap TerrainBitmap(TileSet tileset, Map map, bool actualSize = false)
|
||||
{
|
||||
var isDiamond = map.TileShape == TileShape.Diamond;
|
||||
var isDiamond = map.Grid.Type == TileShape.Diamond;
|
||||
var b = map.Bounds;
|
||||
|
||||
// Fudge the heightmap offset by adding as much extra as we need / can.
|
||||
// This tries to correct for our incorrect assumption that MPos == PPos
|
||||
var heightOffset = Math.Min(map.MaximumTerrainHeight, map.MapSize.Y - b.Bottom);
|
||||
var heightOffset = Math.Min(map.Grid.MaximumTerrainHeight, map.MapSize.Y - b.Bottom);
|
||||
var width = b.Width;
|
||||
var height = b.Height + heightOffset;
|
||||
|
||||
@@ -81,12 +81,12 @@ namespace OpenRA.Graphics
|
||||
static Bitmap AddStaticResources(TileSet tileset, Map map, Ruleset resourceRules, Bitmap terrainBitmap)
|
||||
{
|
||||
var terrain = new Bitmap(terrainBitmap);
|
||||
var isDiamond = map.TileShape == TileShape.Diamond;
|
||||
var isDiamond = map.Grid.Type == TileShape.Diamond;
|
||||
var b = map.Bounds;
|
||||
|
||||
// Fudge the heightmap offset by adding as much extra as we need / can
|
||||
// This tries to correct for our incorrect assumption that MPos == PPos
|
||||
var heightOffset = Math.Min(map.MaximumTerrainHeight, map.MapSize.Y - b.Bottom);
|
||||
var heightOffset = Math.Min(map.Grid.MaximumTerrainHeight, map.MapSize.Y - b.Bottom);
|
||||
var width = b.Width;
|
||||
var height = b.Height + heightOffset;
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
var pos = sprite == null ? float2.Zero :
|
||||
worldRenderer.ScreenPosition(map.CenterOfCell(cell)) + sprite.Offset - 0.5f * sprite.Size;
|
||||
Update(cell.ToMPos(map.TileShape), sprite, pos);
|
||||
Update(cell.ToMPos(map.Grid.Type), sprite, pos);
|
||||
}
|
||||
|
||||
public void Update(MPos uv, Sprite sprite, float2 pos)
|
||||
|
||||
@@ -92,15 +92,15 @@ namespace OpenRA.Graphics
|
||||
public Viewport(WorldRenderer wr, Map map)
|
||||
{
|
||||
worldRenderer = wr;
|
||||
var grid = Game.ModData.Manifest.Get<MapGrid>();
|
||||
|
||||
// Calculate map bounds in world-px
|
||||
if (wr.World.Type == WorldType.Editor)
|
||||
{
|
||||
// The full map is visible in the editor
|
||||
var ts = Game.ModData.Manifest.TileSize;
|
||||
var width = map.MapSize.X * ts.Width;
|
||||
var height = map.MapSize.Y * ts.Height;
|
||||
if (wr.World.Map.TileShape == TileShape.Diamond)
|
||||
var width = map.MapSize.X * grid.TileSize.Width;
|
||||
var height = map.MapSize.Y * grid.TileSize.Height;
|
||||
if (wr.World.Map.Grid.Type == TileShape.Diamond)
|
||||
height /= 2;
|
||||
|
||||
mapBounds = new Rectangle(0, 0, width, height);
|
||||
@@ -115,23 +115,22 @@ namespace OpenRA.Graphics
|
||||
}
|
||||
|
||||
Zoom = Game.Settings.Graphics.PixelDouble ? 2 : 1;
|
||||
tileSize = Game.ModData.Manifest.TileSize;
|
||||
tileSize = grid.TileSize;
|
||||
}
|
||||
|
||||
public CPos ViewToWorld(int2 view)
|
||||
{
|
||||
var world = worldRenderer.Viewport.ViewToWorldPx(view);
|
||||
var map = worldRenderer.World.Map;
|
||||
var ts = Game.ModData.Manifest.TileSize;
|
||||
var candidates = CandidateMouseoverCells(world);
|
||||
var candidates = CandidateMouseoverCells(world).ToList();
|
||||
var tileSet = worldRenderer.World.TileSet;
|
||||
|
||||
foreach (var uv in candidates)
|
||||
{
|
||||
// Coarse filter to nearby cells
|
||||
var p = map.CenterOfCell(uv.ToCPos(map.TileShape));
|
||||
var p = map.CenterOfCell(uv.ToCPos(map.Grid.Type));
|
||||
var s = worldRenderer.ScreenPxPosition(p);
|
||||
if (Math.Abs(s.X - world.X) <= ts.Width && Math.Abs(s.Y - world.Y) <= ts.Height)
|
||||
if (Math.Abs(s.X - world.X) <= tileSize.Width && Math.Abs(s.Y - world.Y) <= tileSize.Height)
|
||||
{
|
||||
var ramp = 0;
|
||||
if (map.Contains(uv))
|
||||
@@ -153,11 +152,11 @@ namespace OpenRA.Graphics
|
||||
|
||||
// Mouse is not directly over a cell (perhaps on a cliff)
|
||||
// Try and find the closest cell
|
||||
if (candidates.Any())
|
||||
if (candidates.Count > 0)
|
||||
{
|
||||
return candidates.OrderBy(uv =>
|
||||
{
|
||||
var p = map.CenterOfCell(uv.ToCPos(map.TileShape));
|
||||
var p = map.CenterOfCell(uv.ToCPos(map.Grid.Type));
|
||||
var s = worldRenderer.ScreenPxPosition(p);
|
||||
var dx = Math.Abs(s.X - world.X);
|
||||
var dy = Math.Abs(s.Y - world.Y);
|
||||
@@ -177,8 +176,8 @@ namespace OpenRA.Graphics
|
||||
var minPos = worldRenderer.ProjectedPosition(world);
|
||||
|
||||
// Find all the cells that could potentially have been clicked
|
||||
var a = map.CellContaining(minPos - new WVec(1024, 0, 0)).ToMPos(map.TileShape);
|
||||
var b = map.CellContaining(minPos + new WVec(512, 512 * map.MaximumTerrainHeight, 0)).ToMPos(map.TileShape);
|
||||
var a = map.CellContaining(minPos - new WVec(1024, 0, 0)).ToMPos(map.Grid.Type);
|
||||
var b = map.CellContaining(minPos + new WVec(512, 512 * map.Grid.MaximumTerrainHeight, 0)).ToMPos(map.Grid.Type);
|
||||
|
||||
for (var v = b.V; v >= a.V; v--)
|
||||
for (var u = b.U; u >= a.U; u--)
|
||||
@@ -244,7 +243,7 @@ namespace OpenRA.Graphics
|
||||
// Diamond tile shapes don't have straight edges, and so we need
|
||||
// an additional cell margin to include the cells that are half
|
||||
// visible on each edge.
|
||||
if (map.TileShape == TileShape.Diamond)
|
||||
if (map.Grid.Type == TileShape.Diamond)
|
||||
{
|
||||
tl = new PPos(tl.U - 1, tl.V - 1);
|
||||
br = new PPos(br.U + 1, br.V + 1);
|
||||
|
||||
@@ -25,6 +25,7 @@ namespace OpenRA.Graphics
|
||||
static readonly int[][] RangeCircleStartRotations = Exts.MakeArray(RangeCircleSegments, i => WRot.FromFacing(8 * i).AsMatrix());
|
||||
static readonly int[][] RangeCircleEndRotations = Exts.MakeArray(RangeCircleSegments, i => WRot.FromFacing(8 * i + 6).AsMatrix());
|
||||
|
||||
public readonly Size TileSize;
|
||||
public readonly World World;
|
||||
public readonly Theater Theater;
|
||||
public Viewport Viewport { get; private set; }
|
||||
@@ -40,6 +41,7 @@ namespace OpenRA.Graphics
|
||||
internal WorldRenderer(World world)
|
||||
{
|
||||
World = world;
|
||||
TileSize = World.Map.Grid.TileSize;
|
||||
Viewport = new Viewport(this, world.Map);
|
||||
|
||||
createPaletteReference = CreatePaletteReference;
|
||||
@@ -231,8 +233,7 @@ namespace OpenRA.Graphics
|
||||
// Conversion between world and screen coordinates
|
||||
public float2 ScreenPosition(WPos pos)
|
||||
{
|
||||
var ts = Game.ModData.Manifest.TileSize;
|
||||
return new float2(ts.Width * pos.X / 1024f, ts.Height * (pos.Y - pos.Z) / 1024f);
|
||||
return new float2(TileSize.Width * pos.X / 1024f, TileSize.Height * (pos.Y - pos.Z) / 1024f);
|
||||
}
|
||||
|
||||
public int2 ScreenPxPosition(WPos pos)
|
||||
@@ -245,10 +246,9 @@ namespace OpenRA.Graphics
|
||||
// For scaling vectors to pixel sizes in the voxel renderer
|
||||
public void ScreenVectorComponents(WVec vec, out float x, out float y, out float z)
|
||||
{
|
||||
var ts = Game.ModData.Manifest.TileSize;
|
||||
x = ts.Width * vec.X / 1024f;
|
||||
y = ts.Height * vec.Y / 1024f;
|
||||
z = ts.Height * vec.Z / 1024f;
|
||||
x = TileSize.Width * vec.X / 1024f;
|
||||
y = TileSize.Height * vec.Y / 1024f;
|
||||
z = TileSize.Height * vec.Z / 1024f;
|
||||
}
|
||||
|
||||
// For scaling vectors to pixel sizes in the voxel renderer
|
||||
@@ -269,8 +269,7 @@ namespace OpenRA.Graphics
|
||||
|
||||
public float ScreenZPosition(WPos pos, int offset)
|
||||
{
|
||||
var ts = Game.ModData.Manifest.TileSize;
|
||||
return ZPosition(pos, offset) * ts.Height / 1024f;
|
||||
return ZPosition(pos, offset) * TileSize.Height / 1024f;
|
||||
}
|
||||
|
||||
static int ZPosition(WPos pos, int offset)
|
||||
@@ -284,8 +283,7 @@ namespace OpenRA.Graphics
|
||||
/// </summary>
|
||||
public WPos ProjectedPosition(int2 screenPx)
|
||||
{
|
||||
var ts = Game.ModData.Manifest.TileSize;
|
||||
return new WPos(1024 * screenPx.X / ts.Width, 1024 * screenPx.Y / ts.Height, 0);
|
||||
return new WPos(1024 * screenPx.X / TileSize.Width, 1024 * screenPx.Y / TileSize.Height, 0);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace OpenRA
|
||||
|
||||
public CPos ToCPos(Map map)
|
||||
{
|
||||
return ToCPos(map.TileShape);
|
||||
return ToCPos(map.Grid.Type);
|
||||
}
|
||||
|
||||
public CPos ToCPos(TileShape shape)
|
||||
|
||||
@@ -10,14 +10,12 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using OpenRA.Primitives;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public enum TileShape { Rectangle, Diamond }
|
||||
public interface IGlobalModData { }
|
||||
|
||||
public sealed class SpriteSequenceFormat : IGlobalModData
|
||||
@@ -47,31 +45,13 @@ namespace OpenRA
|
||||
public readonly MiniYaml LobbyDefaults;
|
||||
|
||||
public readonly Dictionary<string, Pair<string, int>> Fonts;
|
||||
public readonly Size TileSize = new Size(24, 24);
|
||||
public readonly TileShape TileShape = TileShape.Rectangle;
|
||||
public readonly byte MaximumTerrainHeight = 0;
|
||||
|
||||
public readonly string[] SpriteFormats = { };
|
||||
|
||||
[Desc("(x,y,z) offset of the full cell and each sub-cell", "X & Y should be between -512 ... 512 and Z >= 0")]
|
||||
public readonly WVec[] SubCellOffsets =
|
||||
{
|
||||
new WVec(0, 0, 0), // full cell - index 0
|
||||
new WVec(-299, -256, 0), // top left - index 1
|
||||
new WVec(256, -256, 0), // top right - index 2
|
||||
new WVec(0, 0, 0), // center - index 3
|
||||
new WVec(-299, 256, 0), // bottom left - index 4
|
||||
new WVec(256, 256, 0), // bottom right - index 5
|
||||
};
|
||||
|
||||
[Desc("Default subcell index used if SubCellInit is absent", "0 - full cell, 1 - first sub-cell")]
|
||||
public readonly int SubCellDefaultIndex = 3;
|
||||
|
||||
readonly string[] reservedModuleNames = { "Metadata", "Folders", "MapFolders", "Packages", "Rules",
|
||||
"Sequences", "VoxelSequences", "Cursors", "Chrome", "Assemblies", "ChromeLayout", "Weapons",
|
||||
"Voices", "Notifications", "Music", "Translations", "TileSets", "ChromeMetrics", "Missions",
|
||||
"ServerTraits", "LoadScreen", "LobbyDefaults", "Fonts", "TileSize", "MaximumTerrainHeight",
|
||||
"TileShape", "SubCells", "SupportsMapsFrom", "SpriteFormats" };
|
||||
"ServerTraits", "LoadScreen", "LobbyDefaults", "Fonts", "SupportsMapsFrom", "SpriteFormats" };
|
||||
|
||||
readonly TypeDictionary modules = new TypeDictionary();
|
||||
readonly Dictionary<string, MiniYaml> yaml;
|
||||
@@ -118,33 +98,6 @@ namespace OpenRA
|
||||
return Pair.New(nd["Font"].Value, Exts.ParseIntegerInvariant(nd["Size"].Value));
|
||||
});
|
||||
|
||||
if (yaml.ContainsKey("TileSize"))
|
||||
TileSize = FieldLoader.GetValue<Size>("TileSize", yaml["TileSize"].Value);
|
||||
|
||||
if (yaml.ContainsKey("TileShape"))
|
||||
TileShape = FieldLoader.GetValue<TileShape>("TileShape", yaml["TileShape"].Value);
|
||||
|
||||
if (yaml.ContainsKey("MaximumTerrainHeight"))
|
||||
MaximumTerrainHeight = FieldLoader.GetValue<byte>("MaximumTerrainHeight", yaml["MaximumTerrainHeight"].Value);
|
||||
|
||||
if (yaml.ContainsKey("SubCells"))
|
||||
{
|
||||
var subcells = yaml["SubCells"].ToDictionary();
|
||||
|
||||
// Read (x,y,z) offset (relative to cell center) pairs for positioning subcells
|
||||
if (subcells.ContainsKey("Offsets"))
|
||||
SubCellOffsets = FieldLoader.GetValue<WVec[]>("Offsets", subcells["Offsets"].Value);
|
||||
|
||||
if (subcells.ContainsKey("DefaultIndex"))
|
||||
SubCellDefaultIndex = FieldLoader.GetValue<int>("DefaultIndex", subcells["DefaultIndex"].Value);
|
||||
else // Otherwise set the default subcell index to the middle subcell entry
|
||||
SubCellDefaultIndex = SubCellOffsets.Length / 2;
|
||||
}
|
||||
|
||||
// Validate default index - 0 for no subcells, otherwise > 1 & <= subcell count (offset triples count - 1)
|
||||
if (SubCellDefaultIndex < (SubCellOffsets.Length > 1 ? 1 : 0) || SubCellDefaultIndex >= SubCellOffsets.Length)
|
||||
throw new InvalidDataException("Subcell default index must be a valid index into the offset triples and must be greater than 0 for mods with subcells");
|
||||
|
||||
// Allow inherited mods to import parent maps.
|
||||
var compat = new List<string>();
|
||||
compat.Add(mod);
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace OpenRA
|
||||
readonly T[] entries;
|
||||
|
||||
public CellLayer(Map map)
|
||||
: this(map.TileShape, new Size(map.MapSize.X, map.MapSize.Y)) { }
|
||||
: this(map.Grid.Type, new Size(map.MapSize.X, map.MapSize.Y)) { }
|
||||
|
||||
public CellLayer(TileShape shape, Size size)
|
||||
{
|
||||
|
||||
@@ -151,8 +151,7 @@ namespace OpenRA
|
||||
};
|
||||
|
||||
public const int MaxTilesInCircleRange = 50;
|
||||
public readonly TileShape TileShape;
|
||||
public readonly byte MaximumTerrainHeight;
|
||||
public readonly MapGrid Grid;
|
||||
|
||||
[FieldLoader.Ignore] public readonly WVec[] SubCellOffsets;
|
||||
public readonly SubCell DefaultSubCell;
|
||||
@@ -275,7 +274,7 @@ namespace OpenRA
|
||||
public Map(TileSet tileset, int width, int height)
|
||||
{
|
||||
var size = new Size(width, height);
|
||||
var tileShape = Game.ModData.Manifest.TileShape;
|
||||
Grid = Game.ModData.Manifest.Get<MapGrid>();
|
||||
var tileRef = new TerrainTile(tileset.Templates.First().Key, (byte)0);
|
||||
|
||||
Title = "Name your map here";
|
||||
@@ -287,29 +286,27 @@ namespace OpenRA
|
||||
Videos = new MapVideos();
|
||||
Options = new MapOptions();
|
||||
|
||||
MapResources = Exts.Lazy(() => new CellLayer<ResourceTile>(tileShape, size));
|
||||
MapResources = Exts.Lazy(() => new CellLayer<ResourceTile>(Grid.Type, size));
|
||||
|
||||
MapTiles = Exts.Lazy(() =>
|
||||
{
|
||||
var ret = new CellLayer<TerrainTile>(tileShape, size);
|
||||
var ret = new CellLayer<TerrainTile>(Grid.Type, size);
|
||||
ret.Clear(tileRef);
|
||||
if (MaximumTerrainHeight > 0)
|
||||
if (Grid.MaximumTerrainHeight > 0)
|
||||
ret.CellEntryChanged += UpdateProjection;
|
||||
return ret;
|
||||
});
|
||||
|
||||
MapHeight = Exts.Lazy(() =>
|
||||
{
|
||||
var ret = new CellLayer<byte>(tileShape, size);
|
||||
var ret = new CellLayer<byte>(Grid.Type, size);
|
||||
ret.Clear(0);
|
||||
if (MaximumTerrainHeight > 0)
|
||||
if (Grid.MaximumTerrainHeight > 0)
|
||||
ret.CellEntryChanged += UpdateProjection;
|
||||
return ret;
|
||||
});
|
||||
|
||||
SpawnPoints = Exts.Lazy(() => new CPos[0]);
|
||||
TileShape = tileShape;
|
||||
MaximumTerrainHeight = Game.ModData.Manifest.MaximumTerrainHeight;
|
||||
|
||||
PostInit();
|
||||
}
|
||||
@@ -374,12 +371,11 @@ namespace OpenRA
|
||||
MapResources = Exts.Lazy(LoadResourceTiles);
|
||||
MapHeight = Exts.Lazy(LoadMapHeight);
|
||||
|
||||
TileShape = Game.ModData.Manifest.TileShape;
|
||||
MaximumTerrainHeight = Game.ModData.Manifest.MaximumTerrainHeight;
|
||||
Grid = Game.ModData.Manifest.Get<MapGrid>();
|
||||
|
||||
SubCellOffsets = Game.ModData.Manifest.SubCellOffsets;
|
||||
SubCellOffsets = Grid.SubCellOffsets;
|
||||
LastSubCell = (SubCell)(SubCellOffsets.Length - 1);
|
||||
DefaultSubCell = (SubCell)Game.ModData.Manifest.SubCellDefaultIndex;
|
||||
DefaultSubCell = (SubCell)Grid.SubCellDefaultIndex;
|
||||
|
||||
if (Container.Exists("map.png"))
|
||||
using (var dataStream = Container.GetContent("map.png"))
|
||||
@@ -417,7 +413,7 @@ namespace OpenRA
|
||||
|
||||
var tl = new MPos(0, 0).ToCPos(this);
|
||||
var br = new MPos(MapSize.X - 1, MapSize.Y - 1).ToCPos(this);
|
||||
AllCells = new CellRegion(TileShape, tl, br);
|
||||
AllCells = new CellRegion(Grid.Type, tl, br);
|
||||
|
||||
var btl = new PPos(Bounds.Left, Bounds.Top);
|
||||
var bbr = new PPos(Bounds.Right - 1, Bounds.Bottom - 1);
|
||||
@@ -427,10 +423,10 @@ namespace OpenRA
|
||||
foreach (var uv in AllCells.MapCoords)
|
||||
CustomTerrain[uv] = byte.MaxValue;
|
||||
|
||||
var leftDelta = TileShape == TileShape.Diamond ? new WVec(-512, 0, 0) : new WVec(-512, -512, 0);
|
||||
var topDelta = TileShape == TileShape.Diamond ? new WVec(0, -512, 0) : new WVec(512, -512, 0);
|
||||
var rightDelta = TileShape == TileShape.Diamond ? new WVec(512, 0, 0) : new WVec(512, 512, 0);
|
||||
var bottomDelta = TileShape == TileShape.Diamond ? new WVec(0, 512, 0) : new WVec(-512, 512, 0);
|
||||
var leftDelta = Grid.Type == TileShape.Diamond ? new WVec(-512, 0, 0) : new WVec(-512, -512, 0);
|
||||
var topDelta = Grid.Type == TileShape.Diamond ? new WVec(0, -512, 0) : new WVec(512, -512, 0);
|
||||
var rightDelta = Grid.Type == TileShape.Diamond ? new WVec(512, 0, 0) : new WVec(512, 512, 0);
|
||||
var bottomDelta = Grid.Type == TileShape.Diamond ? new WVec(0, 512, 0) : new WVec(-512, 512, 0);
|
||||
CellCorners = CellCornerHalfHeights.Select(ramp => new WVec[]
|
||||
{
|
||||
leftDelta + new WVec(0, 0, 512 * ramp[0]),
|
||||
@@ -453,7 +449,7 @@ namespace OpenRA
|
||||
// Initialize collections
|
||||
foreach (var cell in AllCells)
|
||||
{
|
||||
var uv = cell.ToMPos(TileShape);
|
||||
var uv = cell.ToMPos(Grid.Type);
|
||||
cellProjection[uv] = new PPos[0];
|
||||
inverseCellProjection[uv] = new List<MPos>();
|
||||
}
|
||||
@@ -467,9 +463,9 @@ namespace OpenRA
|
||||
{
|
||||
MPos uv;
|
||||
|
||||
if (MaximumTerrainHeight == 0)
|
||||
if (Grid.MaximumTerrainHeight == 0)
|
||||
{
|
||||
uv = cell.ToMPos(TileShape);
|
||||
uv = cell.ToMPos(Grid.Type);
|
||||
cellProjection[cell] = new[] { (PPos)uv };
|
||||
var inverse = inverseCellProjection[uv];
|
||||
inverse.Clear();
|
||||
@@ -480,7 +476,7 @@ namespace OpenRA
|
||||
if (!initializedCellProjection)
|
||||
InitializeCellProjection();
|
||||
|
||||
uv = cell.ToMPos(TileShape);
|
||||
uv = cell.ToMPos(Grid.Type);
|
||||
|
||||
// Remove old reverse projection
|
||||
foreach (var puv in cellProjection[uv])
|
||||
@@ -635,7 +631,7 @@ namespace OpenRA
|
||||
}
|
||||
}
|
||||
|
||||
if (MaximumTerrainHeight > 0)
|
||||
if (Grid.MaximumTerrainHeight > 0)
|
||||
tiles.CellEntryChanged += UpdateProjection;
|
||||
|
||||
return tiles;
|
||||
@@ -652,11 +648,11 @@ namespace OpenRA
|
||||
s.Position = header.HeightsOffset;
|
||||
for (var i = 0; i < MapSize.X; i++)
|
||||
for (var j = 0; j < MapSize.Y; j++)
|
||||
tiles[new MPos(i, j)] = s.ReadUInt8().Clamp((byte)0, MaximumTerrainHeight);
|
||||
tiles[new MPos(i, j)] = s.ReadUInt8().Clamp((byte)0, Grid.MaximumTerrainHeight);
|
||||
}
|
||||
}
|
||||
|
||||
if (MaximumTerrainHeight > 0)
|
||||
if (Grid.MaximumTerrainHeight > 0)
|
||||
tiles.CellEntryChanged += UpdateProjection;
|
||||
|
||||
return tiles;
|
||||
@@ -701,8 +697,8 @@ namespace OpenRA
|
||||
|
||||
// Data offsets
|
||||
var tilesOffset = 17;
|
||||
var heightsOffset = MaximumTerrainHeight > 0 ? 3 * MapSize.X * MapSize.Y + 17 : 0;
|
||||
var resourcesOffset = (MaximumTerrainHeight > 0 ? 4 : 3) * MapSize.X * MapSize.Y + 17;
|
||||
var heightsOffset = Grid.MaximumTerrainHeight > 0 ? 3 * MapSize.X * MapSize.Y + 17 : 0;
|
||||
var resourcesOffset = (Grid.MaximumTerrainHeight > 0 ? 4 : 3) * MapSize.X * MapSize.Y + 17;
|
||||
|
||||
writer.Write((uint)tilesOffset);
|
||||
writer.Write((uint)heightsOffset);
|
||||
@@ -751,7 +747,7 @@ namespace OpenRA
|
||||
// .ToMPos() returns the same result if the X and Y coordinates
|
||||
// are switched. X < Y is invalid in the Diamond coordinate system,
|
||||
// so we pre-filter these to avoid returning the wrong result
|
||||
if (TileShape == TileShape.Diamond && cell.X < cell.Y)
|
||||
if (Grid.Type == TileShape.Diamond && cell.X < cell.Y)
|
||||
return false;
|
||||
|
||||
return Contains(cell.ToMPos(this));
|
||||
@@ -767,7 +763,7 @@ namespace OpenRA
|
||||
|
||||
bool ContainsAllProjectedCellsCovering(MPos uv)
|
||||
{
|
||||
if (MaximumTerrainHeight == 0)
|
||||
if (Grid.MaximumTerrainHeight == 0)
|
||||
return Contains((PPos)uv);
|
||||
|
||||
foreach (var puv in ProjectedCellsCovering(uv))
|
||||
@@ -783,7 +779,7 @@ namespace OpenRA
|
||||
|
||||
public WPos CenterOfCell(CPos cell)
|
||||
{
|
||||
if (TileShape == TileShape.Rectangle)
|
||||
if (Grid.Type == TileShape.Rectangle)
|
||||
return new WPos(1024 * cell.X + 512, 1024 * cell.Y + 512, 0);
|
||||
|
||||
// Convert from diamond cell position (x, y) to world position (u, v):
|
||||
@@ -815,7 +811,7 @@ namespace OpenRA
|
||||
|
||||
public CPos CellContaining(WPos pos)
|
||||
{
|
||||
if (TileShape == TileShape.Rectangle)
|
||||
if (Grid.Type == TileShape.Rectangle)
|
||||
return new CPos(pos.X / 1024, pos.Y / 1024);
|
||||
|
||||
// Convert from world position to diamond cell position:
|
||||
@@ -834,7 +830,7 @@ namespace OpenRA
|
||||
public PPos ProjectedCellCovering(WPos pos)
|
||||
{
|
||||
var projectedPos = pos - new WVec(0, pos.Z, pos.Z);
|
||||
return (PPos)CellContaining(projectedPos).ToMPos(TileShape);
|
||||
return (PPos)CellContaining(projectedPos).ToMPos(Grid.Type);
|
||||
}
|
||||
|
||||
static readonly PPos[] NoProjectedCells = { };
|
||||
@@ -881,7 +877,7 @@ namespace OpenRA
|
||||
|
||||
var tl = new MPos(0, 0).ToCPos(this);
|
||||
var br = new MPos(MapSize.X - 1, MapSize.Y - 1).ToCPos(this);
|
||||
AllCells = new CellRegion(TileShape, tl, br);
|
||||
AllCells = new CellRegion(Grid.Type, tl, br);
|
||||
}
|
||||
|
||||
public void SetBounds(PPos tl, PPos br)
|
||||
@@ -896,7 +892,7 @@ namespace OpenRA
|
||||
// for diamond cells.
|
||||
var wtop = tl.V * 1024;
|
||||
var wbottom = (br.V + 1) * 1024;
|
||||
if (TileShape == TileShape.Diamond)
|
||||
if (Grid.Type == TileShape.Diamond)
|
||||
{
|
||||
wtop /= 2;
|
||||
wbottom /= 2;
|
||||
@@ -995,7 +991,7 @@ namespace OpenRA
|
||||
|
||||
public MPos Clamp(MPos uv)
|
||||
{
|
||||
if (MaximumTerrainHeight == 0)
|
||||
if (Grid.MaximumTerrainHeight == 0)
|
||||
return (MPos)Clamp((PPos)uv);
|
||||
|
||||
// Already in bounds, so don't need to do anything.
|
||||
@@ -1030,7 +1026,7 @@ namespace OpenRA
|
||||
if (!unProjected.Any())
|
||||
{
|
||||
// Adjust V until we find a cell that works
|
||||
for (var x = 2; x <= 2 * MaximumTerrainHeight; x++)
|
||||
for (var x = 2; x <= 2 * Grid.MaximumTerrainHeight; x++)
|
||||
{
|
||||
var dv = ((x & 1) == 1 ? 1 : -1) * x / 2;
|
||||
var test = new PPos(projected.U, projected.V + dv);
|
||||
@@ -1070,12 +1066,12 @@ namespace OpenRA
|
||||
cells = Unproject(new PPos(u, v));
|
||||
} while (!cells.Any());
|
||||
|
||||
return cells.Random(rand).ToCPos(TileShape);
|
||||
return cells.Random(rand).ToCPos(Grid.Type);
|
||||
}
|
||||
|
||||
public CPos ChooseClosestEdgeCell(CPos cell)
|
||||
{
|
||||
return ChooseClosestEdgeCell(cell.ToMPos(TileShape)).ToCPos(TileShape);
|
||||
return ChooseClosestEdgeCell(cell.ToMPos(Grid.Type)).ToCPos(Grid.Type);
|
||||
}
|
||||
|
||||
public MPos ChooseClosestEdgeCell(MPos uv)
|
||||
@@ -1101,7 +1097,7 @@ namespace OpenRA
|
||||
if (!unProjected.Any())
|
||||
{
|
||||
// Adjust V until we find a cell that works
|
||||
for (var x = 2; x <= 2 * MaximumTerrainHeight; x++)
|
||||
for (var x = 2; x <= 2 * Grid.MaximumTerrainHeight; x++)
|
||||
{
|
||||
var dv = ((x & 1) == 1 ? 1 : -1) * x / 2;
|
||||
var test = new PPos(edge.U, edge.V + dv);
|
||||
@@ -1137,7 +1133,7 @@ namespace OpenRA
|
||||
cells = Unproject(new PPos(u, v));
|
||||
} while (!cells.Any());
|
||||
|
||||
return cells.Random(rand).ToCPos(TileShape);
|
||||
return cells.Random(rand).ToCPos(Grid.Type);
|
||||
}
|
||||
|
||||
public WDist DistanceToEdge(WPos pos, WVec dir)
|
||||
|
||||
45
OpenRA.Game/Map/MapGrid.cs
Normal file
45
OpenRA.Game/Map/MapGrid.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2015 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.Drawing;
|
||||
using System.IO;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public enum TileShape { Rectangle, Diamond }
|
||||
|
||||
public class MapGrid : IGlobalModData
|
||||
{
|
||||
public readonly TileShape Type = TileShape.Rectangle;
|
||||
public readonly Size TileSize = new Size(24, 24);
|
||||
public readonly byte MaximumTerrainHeight = 0;
|
||||
public readonly byte SubCellDefaultIndex = byte.MaxValue;
|
||||
public readonly WVec[] SubCellOffsets =
|
||||
{
|
||||
new WVec(0, 0, 0), // full cell - index 0
|
||||
new WVec(-299, -256, 0), // top left - index 1
|
||||
new WVec(256, -256, 0), // top right - index 2
|
||||
new WVec(0, 0, 0), // center - index 3
|
||||
new WVec(-299, 256, 0), // bottom left - index 4
|
||||
new WVec(256, 256, 0), // bottom right - index 5
|
||||
};
|
||||
|
||||
public MapGrid(MiniYaml yaml)
|
||||
{
|
||||
FieldLoader.Load(this, yaml);
|
||||
|
||||
// The default subcell index defaults to the middle entry
|
||||
if (SubCellDefaultIndex == byte.MaxValue)
|
||||
SubCellDefaultIndex = (byte)(SubCellOffsets.Length / 2);
|
||||
else if (SubCellDefaultIndex < (SubCellOffsets.Length > 1 ? 1 : 0) || SubCellDefaultIndex >= SubCellOffsets.Length)
|
||||
throw new InvalidDataException("Subcell default index must be a valid index into the offset triples and must be greater than 0 for mods with subcells");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,7 +42,8 @@ namespace OpenRA
|
||||
// been projected into this region if they have height > 0.
|
||||
// Each height step is equivalent to 512 WRange units, which is one MPos
|
||||
// step for diamond cells, but only half a MPos step for classic cells. Doh!
|
||||
var heightOffset = map.TileShape == TileShape.Diamond ? map.MaximumTerrainHeight : map.MaximumTerrainHeight / 2;
|
||||
var maxHeight = map.Grid.MaximumTerrainHeight;
|
||||
var heightOffset = map.Grid.Type == TileShape.Diamond ? maxHeight : maxHeight / 2;
|
||||
|
||||
// Use the MapHeight data array to clamp the bottom coordinate so it doesn't overflow the map
|
||||
mapBottomRight = map.MapHeight.Value.Clamp(new MPos(bottomRight.U, bottomRight.V + heightOffset));
|
||||
|
||||
@@ -94,6 +94,7 @@
|
||||
<Compile Include="LogProxy.cs" />
|
||||
<Compile Include="FileFormats\IdxReader.cs" />
|
||||
<Compile Include="FileSystem\BagFile.cs" />
|
||||
<Compile Include="Map\MapGrid.cs" />
|
||||
<Compile Include="Map\MapPlayers.cs" />
|
||||
<Compile Include="ContentInstaller.cs" />
|
||||
<Compile Include="MPos.cs" />
|
||||
|
||||
@@ -36,9 +36,9 @@ namespace OpenRA.Traits
|
||||
|
||||
public ScreenMap(World world, ScreenMapInfo info)
|
||||
{
|
||||
var ts = Game.ModData.Manifest.TileSize;
|
||||
var width = world.Map.MapSize.X * ts.Width;
|
||||
var height = world.Map.MapSize.Y * ts.Height;
|
||||
var size = world.Map.Grid.TileSize;
|
||||
var width = world.Map.MapSize.X * size.Width;
|
||||
var height = world.Map.MapSize.Y * size.Height;
|
||||
partitionedFrozenActors = new Cache<Player, SpatiallyPartitioned<FrozenActor>>(
|
||||
_ => new SpatiallyPartitioned<FrozenActor>(width, height, info.BinSize));
|
||||
partitionedActors = new SpatiallyPartitioned<Actor>(width, height, info.BinSize);
|
||||
|
||||
@@ -48,7 +48,8 @@ namespace OpenRA.Mods.Common.Widgets
|
||||
preview.IsVisible = () => editorWidget.CurrentBrush == this;
|
||||
|
||||
preview.Template = world.TileSet.Templates.First(t => t.Value.Id == template).Value;
|
||||
bounds = worldRenderer.Theater.TemplateBounds(preview.Template, Game.ModData.Manifest.TileSize, world.Map.TileShape);
|
||||
var grid = world.Map.Grid;
|
||||
bounds = worldRenderer.Theater.TemplateBounds(preview.Template, grid.TileSize, grid.Type);
|
||||
|
||||
// The preview widget may be rendered by the higher-level code before it is ticked.
|
||||
// Force a manual tick to ensure the bounds are set correctly for this first draw.
|
||||
@@ -106,7 +107,7 @@ namespace OpenRA.Mods.Common.Widgets
|
||||
continue;
|
||||
|
||||
mapTiles[c] = new TerrainTile(Template, index);
|
||||
mapHeight[c] = (byte)(baseHeight + template[index].Height).Clamp(0, map.MaximumTerrainHeight);
|
||||
mapHeight[c] = (byte)(baseHeight + template[index].Height).Clamp(0, map.Grid.MaximumTerrainHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,8 +106,7 @@ namespace OpenRA.Mods.Common.Graphics
|
||||
{
|
||||
var groundPos = voxel.pos - new WVec(0, 0, wr.World.Map.DistanceAboveTerrain(voxel.pos).Length);
|
||||
|
||||
var ts = Game.ModData.Manifest.TileSize;
|
||||
var groundZ = ts.Height * (groundPos.Z - voxel.pos.Z) / 1024f;
|
||||
var groundZ = wr.World.Map.Grid.TileSize.Height * (groundPos.Z - voxel.pos.Z) / 1024f;
|
||||
|
||||
var pxOrigin = wr.ScreenPosition(voxel.pos);
|
||||
var shadowOrigin = pxOrigin - groundZ * (new float2(renderProxy.ShadowDirection, 1));
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace OpenRA.Mods.Common.Pathfinder
|
||||
CellLayer<CellInfo>.CreateInstance(
|
||||
mpos => new CellInfo(int.MaxValue, int.MaxValue, mpos.ToCPos(map), CellStatus.Unvisited),
|
||||
new Size(map.MapSize.X, map.MapSize.Y),
|
||||
map.TileShape);
|
||||
map.Grid.Type);
|
||||
}
|
||||
|
||||
public PooledCellInfoLayer Get()
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
foreach (var pr in Players.Players.Values)
|
||||
wr.UpdatePalettesForPlayer(pr.Name, pr.Color, false);
|
||||
|
||||
var ts = Game.ModData.Manifest.TileSize;
|
||||
var ts = world.Map.Grid.TileSize;
|
||||
var width = world.Map.MapSize.X * ts.Width;
|
||||
var height = world.Map.MapSize.Y * ts.Height;
|
||||
screenMap = new SpatiallyPartitioned<EditorActorPreview>(width, height, info.BinSize);
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
|
||||
internal static void ConvertPxToRange(ref string input, int scaleMult, int scaleDiv)
|
||||
{
|
||||
var value = Exts.ParseIntegerInvariant(input);
|
||||
var ts = Game.ModData.Manifest.TileSize;
|
||||
var ts = Game.ModData.Manifest.Get<MapGrid>().TileSize;
|
||||
var world = value * 1024 * scaleMult / (scaleDiv * ts.Height);
|
||||
var cells = world / 1024;
|
||||
var subcells = world - 1024 * cells;
|
||||
@@ -69,7 +69,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
|
||||
internal static void ConvertInt2ToWVec(ref string input)
|
||||
{
|
||||
var offset = FieldLoader.GetValue<int2>("(value)", input);
|
||||
var ts = Game.ModData.Manifest.TileSize;
|
||||
var ts = Game.ModData.Manifest.Get<MapGrid>().TileSize;
|
||||
var world = new WVec(offset.X * 1024 / ts.Width, offset.Y * 1024 / ts.Height, 0);
|
||||
input = world.ToString();
|
||||
}
|
||||
|
||||
@@ -67,12 +67,11 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
var frame = sequence.Frames != null ? sequence.Frames.Last() : resource.MaxDensity - 1;
|
||||
layerPreview.GetSprite = () => sequence.GetSprite(frame);
|
||||
|
||||
var tileWidth = Game.ModData.Manifest.TileSize.Width;
|
||||
var tileHeight = Game.ModData.Manifest.TileSize.Height;
|
||||
layerPreview.Bounds.Width = tileWidth;
|
||||
layerPreview.Bounds.Height = tileHeight;
|
||||
newResourcePreviewTemplate.Bounds.Width = tileWidth + (layerPreview.Bounds.X * 2);
|
||||
newResourcePreviewTemplate.Bounds.Height = tileHeight + (layerPreview.Bounds.Y * 2);
|
||||
var tileSize = Game.ModData.Manifest.Get<MapGrid>().TileSize;
|
||||
layerPreview.Bounds.Width = tileSize.Width;
|
||||
layerPreview.Bounds.Height = tileSize.Height;
|
||||
newResourcePreviewTemplate.Bounds.Width = tileSize.Width + (layerPreview.Bounds.X * 2);
|
||||
newResourcePreviewTemplate.Bounds.Height = tileSize.Height + (layerPreview.Bounds.Y * 2);
|
||||
|
||||
newResourcePreviewTemplate.IsVisible = () => true;
|
||||
newResourcePreviewTemplate.GetTooltipText = () => resource.Name;
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
width = Math.Max(2, width);
|
||||
height = Math.Max(2, height);
|
||||
|
||||
var maxTerrainHeight = Game.ModData.Manifest.MaximumTerrainHeight;
|
||||
var maxTerrainHeight = world.Map.Grid.MaximumTerrainHeight;
|
||||
var tileset = modRules.TileSets[tilesetDropDown.Text];
|
||||
var map = new Map(tileset, width + 2, height + maxTerrainHeight + 2);
|
||||
|
||||
|
||||
@@ -68,7 +68,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
|
||||
var preview = item.Get<TerrainTemplatePreviewWidget>("TILE_PREVIEW");
|
||||
var template = tileset.Templates[tileId];
|
||||
var bounds = worldRenderer.Theater.TemplateBounds(template, Game.ModData.Manifest.TileSize, worldRenderer.World.Map.TileShape);
|
||||
var grid = worldRenderer.World.Map.Grid;
|
||||
var bounds = worldRenderer.Theater.TemplateBounds(template, grid.TileSize, grid.Type);
|
||||
|
||||
// Scale templates to fit within the panel
|
||||
var scale = 1f;
|
||||
|
||||
@@ -62,6 +62,7 @@ namespace OpenRA.Mods.Common.Widgets
|
||||
readonly Color spawnColor, spawnContrastColor;
|
||||
readonly int2 spawnLabelOffset;
|
||||
readonly int cellWidth;
|
||||
readonly TileShape shape;
|
||||
|
||||
public Func<MapPreview> Preview = () => null;
|
||||
public Func<Dictionary<CPos, SpawnOccupant>> SpawnOccupants = () => new Dictionary<CPos, SpawnOccupant>();
|
||||
@@ -83,7 +84,8 @@ namespace OpenRA.Mods.Common.Widgets
|
||||
spawnContrastColor = ChromeMetrics.Get<Color>("SpawnContrastColor");
|
||||
spawnLabelOffset = ChromeMetrics.Get<int2>("SpawnLabelOffset");
|
||||
|
||||
cellWidth = Game.ModData.Manifest.TileShape == TileShape.Diamond ? 2 : 1;
|
||||
shape = Game.ModData.Manifest.Get<MapGrid>().Type;
|
||||
cellWidth = shape == TileShape.Diamond ? 2 : 1;
|
||||
}
|
||||
|
||||
protected MapPreviewWidget(MapPreviewWidget other)
|
||||
@@ -106,6 +108,7 @@ namespace OpenRA.Mods.Common.Widgets
|
||||
spawnContrastColor = ChromeMetrics.Get<Color>("SpawnContrastColor");
|
||||
spawnLabelOffset = ChromeMetrics.Get<int2>("SpawnLabelOffset");
|
||||
|
||||
shape = other.shape;
|
||||
cellWidth = other.cellWidth;
|
||||
}
|
||||
|
||||
@@ -138,8 +141,7 @@ namespace OpenRA.Mods.Common.Widgets
|
||||
public int2 ConvertToPreview(CPos cell)
|
||||
{
|
||||
var preview = Preview();
|
||||
var tileShape = Game.ModData.Manifest.TileShape;
|
||||
var point = cell.ToMPos(tileShape);
|
||||
var point = cell.ToMPos(shape);
|
||||
var dx = (int)(previewScale * cellWidth * (point.U - preview.Bounds.Left));
|
||||
var dy = (int)(previewScale * (point.V - preview.Bounds.Top));
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ namespace OpenRA.Mods.Common.Widgets
|
||||
this.worldRenderer = worldRenderer;
|
||||
radarPings = world.WorldActor.TraitOrDefault<RadarPings>();
|
||||
|
||||
isDiamond = world.Map.TileShape == TileShape.Diamond;
|
||||
isDiamond = world.Map.Grid.Type == TileShape.Diamond;
|
||||
cellWidth = isDiamond ? 2 : 1;
|
||||
previewWidth = world.Map.MapSize.X;
|
||||
previewHeight = world.Map.MapSize.Y;
|
||||
@@ -379,7 +379,7 @@ namespace OpenRA.Mods.Common.Widgets
|
||||
if (!world.Map.Contains(cell.First))
|
||||
continue;
|
||||
|
||||
var uv = cell.First.ToMPos(world.Map.TileShape);
|
||||
var uv = cell.First.ToMPos(world.Map.Grid.Type);
|
||||
var color = cell.Second.ToArgb();
|
||||
if (isDiamond)
|
||||
{
|
||||
|
||||
@@ -41,8 +41,9 @@ namespace OpenRA.Mods.Common.Widgets
|
||||
if (template == null)
|
||||
return;
|
||||
|
||||
var ts = Game.ModData.Manifest.TileSize;
|
||||
var shape = Game.ModData.Manifest.TileShape;
|
||||
var grid = Game.ModData.Manifest.Get<MapGrid>();
|
||||
var ts = grid.TileSize;
|
||||
var shape = grid.Type;
|
||||
bounds = worldRenderer.Theater.TemplateBounds(template, ts, shape);
|
||||
}
|
||||
}
|
||||
@@ -70,8 +71,9 @@ namespace OpenRA.Mods.Common.Widgets
|
||||
if (template == null)
|
||||
return;
|
||||
|
||||
var ts = Game.ModData.Manifest.TileSize;
|
||||
var shape = Game.ModData.Manifest.TileShape;
|
||||
var grid = Game.ModData.Manifest.Get<MapGrid>();
|
||||
var ts = grid.TileSize;
|
||||
var shape = grid.Type;
|
||||
var scale = GetScale();
|
||||
|
||||
var sb = new Rectangle((int)(scale * bounds.X), (int)(scale * bounds.Y), (int)(scale * bounds.Width), (int)(scale * bounds.Height));
|
||||
|
||||
@@ -201,6 +201,10 @@ Fonts:
|
||||
Missions:
|
||||
./mods/cnc/missions.yaml
|
||||
|
||||
MapGrid:
|
||||
TileSize: 24,24
|
||||
Type: Rectangle
|
||||
|
||||
SupportsMapsFrom: cnc
|
||||
|
||||
SpriteFormats: ShpTD, TmpTD, ShpTS, TmpRA
|
||||
|
||||
@@ -49,7 +49,9 @@ Sequences:
|
||||
TileSets:
|
||||
./mods/d2k/tilesets/arrakis.yaml
|
||||
|
||||
MapGrid:
|
||||
TileSize: 32,32
|
||||
Type: Rectangle
|
||||
|
||||
Cursors:
|
||||
./mods/d2k/cursors.yaml
|
||||
|
||||
@@ -201,6 +201,10 @@ Fonts:
|
||||
Missions:
|
||||
./mods/ra/missions.yaml
|
||||
|
||||
MapGrid:
|
||||
TileSize: 24,24
|
||||
Type: Rectangle
|
||||
|
||||
SupportsMapsFrom: ra
|
||||
|
||||
SpriteFormats: ShpTD, TmpRA, TmpTD, ShpTS
|
||||
|
||||
@@ -111,12 +111,12 @@ TileSets:
|
||||
./mods/ts/tilesets/temperate.yaml
|
||||
./mods/ts/tilesets/snow.yaml
|
||||
|
||||
MapGrid:
|
||||
TileSize: 48,24
|
||||
TileShape: Diamond
|
||||
SubCells:
|
||||
Offsets: 0,0,0, -256,128,0, 0,-128,0, 256,128,0
|
||||
DefaultIndex: 2
|
||||
Type: Diamond
|
||||
MaximumTerrainHeight: 16
|
||||
SubCellOffsets: 0,0,0, -256,128,0, 0,-128,0, 256,128,0
|
||||
SubCellDefaultIndex: 2
|
||||
|
||||
Cursors:
|
||||
./mods/ts/cursors.yaml
|
||||
|
||||
Reference in New Issue
Block a user