Merge pull request #6901 from pchote/heightmaps-part-two

Implement terrain heightmaps
This commit is contained in:
Matthias Mailänder
2014-11-08 18:22:57 +01:00
18 changed files with 540 additions and 79 deletions

View File

@@ -188,6 +188,27 @@ namespace OpenRA
return InvalidValueAction(value, fieldType, fieldName);
}
else if (fieldType == typeof(Color[]))
{
var parts = value.Split(',');
if (parts.Length % 4 != 0)
return InvalidValueAction(value, fieldType, fieldName);
var colors = new Color[parts.Length / 4];
for (var i = 0; i < colors.Length; i++)
{
colors[i] = Color.FromArgb(
Exts.ParseIntegerInvariant(parts[4 * i]).Clamp(0, 255),
Exts.ParseIntegerInvariant(parts[4 * i + 1]).Clamp(0, 255),
Exts.ParseIntegerInvariant(parts[4 * i + 2]).Clamp(0, 255),
Exts.ParseIntegerInvariant(parts[4 * i + 3]).Clamp(0, 255));
}
return colors;
}
else if (fieldType == typeof(HSLColor))
{
var parts = value.Split(',');

View File

@@ -39,6 +39,8 @@ namespace OpenRA.Graphics
// Map bounds (world-px)
readonly Rectangle mapBounds;
readonly int maxGroundHeight;
// Viewport geometry (world-px)
public int2 CenterLocation { get; private set; }
@@ -96,6 +98,7 @@ namespace OpenRA.Graphics
var br = wr.ScreenPxPosition(map.CenterOfCell(Map.MapToCell(map.TileShape, new CPos(b.Right, b.Bottom))) + new WVec(511, 511, 0));
mapBounds = Rectangle.FromLTRB(tl.X, tl.Y, br.X, br.Y);
maxGroundHeight = wr.world.TileSet.MaxGroundHeight;
CenterLocation = (tl + br) / 2;
Zoom = Game.Settings.Graphics.PixelDouble ? 2 : 1;
}
@@ -144,8 +147,8 @@ namespace OpenRA.Graphics
var cbr = map.CenterOfCell(VisibleCells.BottomRight) + new WVec(512, 512, 0);
// Convert to screen coordinates
var tl = WorldToViewPx(worldRenderer.ScreenPxPosition(ctl)).Clamp(ScreenClip);
var br = WorldToViewPx(worldRenderer.ScreenPxPosition(cbr)).Clamp(ScreenClip);
var tl = WorldToViewPx(worldRenderer.ScreenPxPosition(ctl - new WVec(0, 0, ctl.Z))).Clamp(ScreenClip);
var br = WorldToViewPx(worldRenderer.ScreenPxPosition(cbr - new WVec(0, 0, cbr.Z))).Clamp(ScreenClip);
return Rectangle.FromLTRB(tl.X, tl.Y, br.X, br.Y);
}
}
@@ -156,14 +159,20 @@ namespace OpenRA.Graphics
{
if (cellsDirty)
{
// Visible rectangle in map coordinates
var map = worldRenderer.world.Map;
var ctl = Map.CellToMap(map.TileShape, map.CellContaining(worldRenderer.Position(TopLeft)));
var cbr = Map.CellToMap(map.TileShape, map.CellContaining(worldRenderer.Position(BottomRight)));
var wtl = worldRenderer.Position(TopLeft);
var wbr = worldRenderer.Position(BottomRight);
// Add a 2 cell cordon to prevent holes, then convert back to cell coordinates
var tl = map.Clamp(Map.MapToCell(map.TileShape, ctl - new CVec(2, 2)));
var br = map.Clamp(Map.MapToCell(map.TileShape, cbr + new CVec(2, 2)));
// Visible rectangle in map coordinates
var ctl = new CPos(wtl.X / 1024, wtl.Y / 1024);
var dy = map.TileShape == TileShape.Diamond ? 512 : 1024;
var cbr = new CPos((wbr.X + 1023) / 1024, (wbr.Y + dy - 1) / dy);
// Add a 1 cell cordon to prevent holes, then convert back to cell coordinates
var tl = map.Clamp(Map.MapToCell(map.TileShape, ctl - new CVec(1, 1)));
// Also need to account for height of cells in rows below the bottom
var br = map.Clamp(Map.MapToCell(map.TileShape, cbr + new CVec(1, 2 + maxGroundHeight / 2)));
cells = new CellRegion(map.TileShape, tl, br);
cellsDirty = false;

View File

@@ -24,6 +24,38 @@ using OpenRA.Traits;
namespace OpenRA
{
struct BinaryDataHeader
{
public readonly byte Format;
public readonly uint TilesOffset;
public readonly uint HeightsOffset;
public readonly uint ResourcesOffset;
public BinaryDataHeader(Stream s, int2 expectedSize)
{
Format = s.ReadUInt8();
var width = s.ReadUInt16();
var height = s.ReadUInt16();
if (width != expectedSize.X || height != expectedSize.Y)
throw new InvalidDataException("Invalid tile data");
if (Format == 1)
{
TilesOffset = 5;
HeightsOffset = 0;
ResourcesOffset = (uint)(3 * width * height + 5);
}
else if (Format == 2)
{
TilesOffset = s.ReadUInt32();
HeightsOffset = s.ReadUInt32();
ResourcesOffset = s.ReadUInt32();
}
else
throw new InvalidDataException("Unknown binary map format '{0}'".F(Format));
}
}
public class MapOptions
{
public bool? Cheats;
@@ -118,11 +150,14 @@ namespace OpenRA
[FieldLoader.Ignore] public List<MiniYamlNode> TranslationDefinitions = new List<MiniYamlNode>();
// Binary map data
[FieldLoader.Ignore] public byte TileFormat = 1;
[FieldLoader.Ignore] public byte TileFormat = 2;
public int2 MapSize;
[FieldLoader.Ignore] public Lazy<CellLayer<TerrainTile>> MapTiles;
[FieldLoader.Ignore] public Lazy<CellLayer<ResourceTile>> MapResources;
[FieldLoader.Ignore] public Lazy<CellLayer<byte>> MapHeight;
[FieldLoader.Ignore] public CellLayer<byte> CustomTerrain;
[FieldLoader.Ignore] Lazy<TileSet> cachedTileSet;
@@ -145,6 +180,13 @@ namespace OpenRA
return ret;
});
var makeMapHeight = Exts.Lazy(() =>
{
var ret = new CellLayer<byte>(tileShape, size);
ret.Clear(0);
return ret;
});
var map = new Map()
{
Title = "Name your map here",
@@ -155,6 +197,7 @@ namespace OpenRA
Options = new MapOptions(),
MapResources = Exts.Lazy(() => new CellLayer<ResourceTile>(tileShape, size)),
MapTiles = makeMapTiles,
MapHeight = makeMapHeight,
Actors = Exts.Lazy(() => new Dictionary<string, ActorReference>()),
Smudges = Exts.Lazy(() => new List<SmudgeReference>())
};
@@ -253,6 +296,8 @@ namespace OpenRA
MapTiles = Exts.Lazy(() => LoadMapTiles());
MapResources = Exts.Lazy(() => LoadResourceTiles());
MapHeight = Exts.Lazy(() => LoadMapHeight());
TileShape = Game.modData.Manifest.TileShape;
SubCellOffsets = Game.modData.Manifest.SubCellOffsets;
LastSubCell = (SubCell)(SubCellOffsets.Length - 1);
@@ -395,33 +440,25 @@ namespace OpenRA
public CellLayer<TerrainTile> LoadMapTiles()
{
var tiles = new CellLayer<TerrainTile>(this);
using (var dataStream = Container.GetContent("map.bin"))
using (var s = Container.GetContent("map.bin"))
{
if (dataStream.ReadUInt8() != 1)
throw new InvalidDataException("Unknown binary map format");
// Load header info
var width = dataStream.ReadUInt16();
var height = dataStream.ReadUInt16();
if (width != MapSize.X || height != MapSize.Y)
throw new InvalidDataException("Invalid tile data");
// Load tile data
var data = dataStream.ReadBytes(MapSize.X * MapSize.Y * 3);
var d = 0;
for (var i = 0; i < MapSize.X; i++)
var header = new BinaryDataHeader(s, MapSize);
if (header.TilesOffset > 0)
{
for (var j = 0; j < MapSize.Y; j++)
s.Position = header.TilesOffset;
for (var i = 0; i < MapSize.X; i++)
{
var tile = BitConverter.ToUInt16(data, d);
d += 2;
for (var j = 0; j < MapSize.Y; j++)
{
var tile = s.ReadUInt16();
var index = s.ReadUInt8();
var index = data[d++];
if (index == byte.MaxValue)
index = (byte)(i % 4 + (j % 4) * 4);
// TODO: Remember to remove this when rewriting tile variants / PickAny
if (index == byte.MaxValue)
index = (byte)(i % 4 + (j % 4) * 4);
tiles[i, j] = new TerrainTile(tile, index);
tiles[i, j] = new TerrainTile(tile, index);
}
}
}
}
@@ -429,32 +466,45 @@ namespace OpenRA
return tiles;
}
public CellLayer<byte> LoadMapHeight()
{
var maxHeight = cachedTileSet.Value.MaxGroundHeight;
var tiles = new CellLayer<byte>(this);
using (var s = Container.GetContent("map.bin"))
{
var header = new BinaryDataHeader(s, MapSize);
if (header.HeightsOffset > 0)
{
s.Position = header.HeightsOffset;
for (var i = 0; i < MapSize.X; i++)
for (var j = 0; j < MapSize.Y; j++)
tiles[i, j] = s.ReadUInt8().Clamp((byte)0, maxHeight);
}
}
return tiles;
}
public CellLayer<ResourceTile> LoadResourceTiles()
{
var resources = new CellLayer<ResourceTile>(this);
using (var dataStream = Container.GetContent("map.bin"))
using (var s = Container.GetContent("map.bin"))
{
if (dataStream.ReadUInt8() != 1)
throw new InvalidDataException("Unknown binary map format");
// Load header info
var width = dataStream.ReadUInt16();
var height = dataStream.ReadUInt16();
if (width != MapSize.X || height != MapSize.Y)
throw new InvalidDataException("Invalid tile data");
// Skip past tile data
dataStream.Seek(3 * MapSize.X * MapSize.Y, SeekOrigin.Current);
var data = dataStream.ReadBytes(MapSize.X * MapSize.Y * 2);
var d = 0;
// Load resource data
for (var i = 0; i < MapSize.X; i++)
for (var j = 0; j < MapSize.Y; j++)
resources[i, j] = new ResourceTile(data[d++], data[d++]);
var header = new BinaryDataHeader(s, MapSize);
if (header.ResourcesOffset > 0)
{
s.Position = header.ResourcesOffset;
for (var i = 0; i < MapSize.X; i++)
{
for (var j = 0; j < MapSize.Y; j++)
{
var type = s.ReadUInt8();
var density = s.ReadUInt8();
resources[i, j] = new ResourceTile(type, density);
}
}
}
}
return resources;
@@ -465,28 +515,53 @@ namespace OpenRA
var dataStream = new MemoryStream();
using (var writer = new BinaryWriter(dataStream))
{
// File header consists of a version byte, followed by 2 ushorts for width and height
// Binary data version
writer.Write(TileFormat);
// Size
writer.Write((ushort)MapSize.X);
writer.Write((ushort)MapSize.Y);
// Data offsets
var tilesOffset = 17;
var heightsOffset = cachedTileSet.Value.MaxGroundHeight > 0 ? 3 * MapSize.X * MapSize.Y + 17 : 0;
var resourcesOffset = (cachedTileSet.Value.MaxGroundHeight > 0 ? 4 : 3) * MapSize.X * MapSize.Y + 17;
writer.Write((uint)tilesOffset);
writer.Write((uint)heightsOffset);
writer.Write((uint)resourcesOffset);
// Tile data
for (var i = 0; i < MapSize.X; i++)
for (var j = 0; j < MapSize.Y; j++)
if (tilesOffset != 0)
{
for (var i = 0; i < MapSize.X; i++)
{
var tile = MapTiles.Value[i, j];
writer.Write(tile.Type);
writer.Write(tile.Index);
for (var j = 0; j < MapSize.Y; j++)
{
var tile = MapTiles.Value[i, j];
writer.Write(tile.Type);
writer.Write(tile.Index);
}
}
}
// Height data
if (heightsOffset != 0)
for (var i = 0; i < MapSize.X; i++)
for (var j = 0; j < MapSize.Y; j++)
writer.Write(MapHeight.Value[i, j]);
// Resource data
for (var i = 0; i < MapSize.X; i++)
if (resourcesOffset != 0)
{
for (var j = 0; j < MapSize.Y; j++)
for (var i = 0; i < MapSize.X; i++)
{
var tile = MapResources.Value[i, j];
writer.Write(tile.Type);
writer.Write(tile.Index);
for (var j = 0; j < MapSize.Y; j++)
{
var tile = MapResources.Value[i, j];
writer.Write(tile.Type);
writer.Write(tile.Index);
}
}
}
}
@@ -513,7 +588,9 @@ namespace OpenRA
// (b) Therefore:
// - ax + by adds (a - b) * 512 + 512 to u
// - ax + by adds (a + b) * 512 + 512 to v
return new WPos(512 * (cell.X - cell.Y + 1), 512 * (cell.X + cell.Y + 1), 0);
var z = Contains(cell) ? 512 * MapHeight.Value[cell] : 0;
return new WPos(512 * (cell.X - cell.Y + 1), 512 * (cell.X + cell.Y + 1), z);
}
public WPos CenterOfSubCell(CPos cell, SubCell subCell)
@@ -588,10 +665,12 @@ namespace OpenRA
{
var oldMapTiles = MapTiles.Value;
var oldMapResources = MapResources.Value;
var oldMapHeight = MapHeight.Value;
var newSize = new Size(width, height);
MapTiles = Exts.Lazy(() => CellLayer.Resize(oldMapTiles, newSize, oldMapTiles[0, 0]));
MapResources = Exts.Lazy(() => CellLayer.Resize(oldMapResources, newSize, oldMapResources[0, 0]));
MapHeight = Exts.Lazy(() => CellLayer.Resize(oldMapHeight, newSize, oldMapHeight[0, 0]));
MapSize = new int2(newSize);
}

View File

@@ -148,7 +148,7 @@ namespace OpenRA
public class TileSet
{
static readonly string[] Fields = { "Name", "Id", "SheetSize", "Palette", "PlayerPalette", "Extensions", "WaterPaletteRotationBase", "EditorTemplateOrder", "IgnoreTileSpriteOffsets" };
static readonly string[] Fields = { "Name", "Id", "SheetSize", "Palette", "PlayerPalette", "Extensions", "WaterPaletteRotationBase", "EditorTemplateOrder", "IgnoreTileSpriteOffsets", "MaximumHeight" };
public readonly string Name;
public readonly string Id;
@@ -156,11 +156,14 @@ namespace OpenRA
public readonly string Palette;
public readonly string PlayerPalette;
public readonly string[] Extensions;
public readonly int WaterPaletteRotationBase = 0x60;
public readonly Dictionary<ushort, TerrainTemplateInfo> Templates = new Dictionary<ushort, TerrainTemplateInfo>();
public readonly int WaterPaletteRotationBase = 0x60;
public readonly byte MaxGroundHeight = 0;
public readonly Color[] HeightDebugColors = new[] { Color.Red };
public readonly string[] EditorTemplateOrder;
public readonly bool IgnoreTileSpriteOffsets;
public readonly Dictionary<ushort, TerrainTemplateInfo> Templates = new Dictionary<ushort, TerrainTemplateInfo>();
public readonly TerrainTypeInfo[] TerrainInfo;
readonly Dictionary<string, byte> terrainIndexByType = new Dictionary<string, byte>();
readonly byte defaultWalkableTerrainIndex;

View File

@@ -23,6 +23,7 @@ namespace OpenRA.Traits
public bool BuildAnywhere;
public bool ShowCombatGeometry;
public bool ShowDebugGeometry;
public bool ShowTerrainGeometry;
public object Create(ActorInitializer init) { return new DeveloperMode(this); }
}
@@ -41,6 +42,7 @@ namespace OpenRA.Traits
// Client side only
public bool ShowCombatGeometry;
public bool ShowDebugGeometry;
public bool ShowTerrainGeometry;
public DeveloperMode(DeveloperModeInfo info)
{
@@ -53,6 +55,7 @@ namespace OpenRA.Traits
BuildAnywhere = info.BuildAnywhere;
ShowCombatGeometry = info.ShowCombatGeometry;
ShowDebugGeometry = info.ShowDebugGeometry;
ShowTerrainGeometry = info.ShowTerrainGeometry;
}
public void ResolveOrder(Actor self, Order order)

View File

@@ -100,8 +100,13 @@ namespace OpenRA.Mods.Common.Graphics
public void Render(WorldRenderer wr)
{
// TODO: This is a temporary workaround until we have a proper ramp-aware height calculation
var groundPos = wr.world.Map.CenterOfCell(wr.world.Map.CellContaining(pos));
var ts = Game.modData.Manifest.TileSize;
var groundZ = ts.Height * (groundPos.Z - pos.Z) / 1024f;
var pxOrigin = wr.ScreenPosition(pos);
var groundZ = 0.5f*(pxOrigin.Y - wr.ScreenZPosition(pos, 0));
var shadowOrigin = pxOrigin - groundZ*(new float2(renderProxy.ShadowDirection, 1));
var psb = renderProxy.ProjectedShadowBounds;

View File

@@ -152,6 +152,7 @@
<Compile Include="SpriteLoaders\ShpD2Loader.cs" />
<Compile Include="Widgets\Logic\SettingsLogic.cs" />
<Compile Include="Widgets\TerrainTemplatePreviewWidget.cs" />
<Compile Include="World\TerrainGeometryOverlay.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>

View File

@@ -0,0 +1,127 @@
#region Copyright & License Information
/*
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Drawing;
using System.Collections.Generic;
using System.Linq;
using OpenRA.Traits;
using OpenRA.Graphics;
namespace OpenRA.Mods.Common
{
[Desc("Renders a debug overlay showing the terrain cells. Attach this to the world actor.")]
public class TerrainGeometryOverlayInfo : ITraitInfo
{
public object Create(ActorInitializer init) { return new TerrainGeometryOverlay(init.self); }
}
public class TerrainGeometryOverlay : IRenderOverlay
{
readonly int[][] vertices = new int[][]
{
// Flat
new[] { 0, 0, 0, 0 },
// Slopes (two corners high)
new[] { 0, 0, 1, 1 },
new[] { 1, 0, 0, 1 },
new[] { 1, 1, 0, 0 },
new[] { 0, 1, 1, 0 },
// Slopes (one corner high)
new[] { 0, 0, 0, 1 },
new[] { 1, 0, 0, 0 },
new[] { 0, 1, 0, 0 },
new[] { 0, 0, 1, 0 },
// Slopes (three corners high)
new[] { 1, 0, 1, 1 },
new[] { 1, 1, 0, 1 },
new[] { 1, 1, 1, 0 },
new[] { 0, 1, 1, 1 },
// Slopes (two corners high, one corner double high)
new[] { 1, 0, 1, 2 },
new[] { 2, 1, 0, 1 },
new[] { 1, 2, 1, 0 },
new[] { 0, 1, 2, 1 },
// Slopes (two corners high, alternating)
new[] { 1, 0, 1, 0 },
new[] { 0, 1, 0, 1 },
new[] { 1, 0, 1, 0 },
new[] { 0, 1, 0, 1 }
};
readonly Lazy<DeveloperMode> devMode;
public TerrainGeometryOverlay(Actor self)
{
devMode = Exts.Lazy(() => self.World.LocalPlayer != null ? self.World.LocalPlayer.PlayerActor.Trait<DeveloperMode>() : null);
}
public void Render(WorldRenderer wr)
{
if (devMode.Value == null || !devMode.Value.ShowTerrainGeometry)
return;
var ts = wr.world.Map.TileShape;
var colors = wr.world.TileSet.HeightDebugColors;
var leftDelta = ts == TileShape.Diamond ? new WVec(-512, 0, 0) : new WVec(-512, -512, 0);
var topDelta = ts == TileShape.Diamond ? new WVec(0, -512, 0) : new WVec(512, -512, 0);
var rightDelta = ts == TileShape.Diamond ? new WVec(512, 0, 0) : new WVec(512, 512, 0);
var bottomDelta = ts == TileShape.Diamond ? new WVec(0, 512, 0) : new WVec(-512, 512, 0);
foreach (var cell in wr.Viewport.VisibleCells)
{
var lr = Game.Renderer.WorldLineRenderer;
var pos = wr.world.Map.CenterOfCell(cell);
var height = (int)wr.world.Map.MapHeight.Value[cell];
var tile = wr.world.Map.MapTiles.Value[cell];
TerrainTileInfo tileInfo = null;
// TODO: This is a temporary workaround for our sloppy tileset definitions
// (ra/td templates omit Clear tiles from templates)
try
{
tileInfo = wr.world.TileSet.Templates[tile.Type][tile.Index];
}
catch (Exception) { }
if (tileInfo == null)
continue;
var leftHeight = vertices[tileInfo.RampType][0];
var topHeight = vertices[tileInfo.RampType][1];
var rightHeight = vertices[tileInfo.RampType][2];
var bottomHeight = vertices[tileInfo.RampType][3];
var leftColor = colors[height + leftHeight];
var topColor = colors[height + topHeight];
var rightColor = colors[height + rightHeight];
var bottomColor = colors[height + bottomHeight];
var left = wr.ScreenPxPosition(pos + leftDelta + new WVec(0, 0, 512 * leftHeight)).ToFloat2();
var top = wr.ScreenPxPosition(pos + topDelta + new WVec(0, 0, 512 * topHeight)).ToFloat2();
var right = wr.ScreenPxPosition(pos + rightDelta + new WVec(0, 0, 512 * rightHeight)).ToFloat2();
var bottom = wr.ScreenPxPosition(pos + bottomDelta + new WVec(0, 0, 512 * bottomHeight)).ToFloat2();
lr.DrawLine(left, top, leftColor, topColor);
lr.DrawLine(top, right, topColor, rightColor);
lr.DrawLine(right, bottom, rightColor, bottomColor);
lr.DrawLine(bottom, left, bottomColor, leftColor);
}
}
}
}

View File

@@ -74,6 +74,13 @@ namespace OpenRA.Mods.RA.Widgets.Logic
showGeometryCheckbox.OnClick = () => devTrait.ShowDebugGeometry ^= true;
}
var showTerrainGeometryCheckbox = widget.GetOrNull<CheckboxWidget>("SHOW_TERRAIN_OVERLAY");
if (showTerrainGeometryCheckbox != null)
{
showTerrainGeometryCheckbox.IsChecked = () => devTrait.ShowTerrainGeometry;
showTerrainGeometryCheckbox.OnClick = () => devTrait.ShowTerrainGeometry ^= true;
}
var allTechCheckbox = widget.GetOrNull<CheckboxWidget>("ENABLE_TECH");
if (allTechCheckbox != null)
{

View File

@@ -83,30 +83,36 @@ Container@DEBUG_PANEL:
Width: PARENT_RIGHT
Checkbox@SHOW_UNIT_PATHS:
X: 45
Y: 285
Y: 275
Width: 200
Height: 20
Font: Regular
Text: Show Unit Paths
Checkbox@SHOW_ASTAR:
X: 45
Y: 315
Y: 305
Height: 20
Width: 200
Font: Regular
Text: Show A* Cost
Checkbox@SHOW_COMBATOVERLAY:
X: 290
Y: 285
Y: 275
Height: 20
Width: 200
Font: Regular
Text: Show Combat Geometry
Checkbox@SHOW_GEOMETRY:
X: 290
Y: 315
Y: 305
Height: 20
Width: 200
Font: Regular
Text: Show Render Geometry
Checkbox@SHOW_TERRAIN_OVERLAY:
X: 290
Y: 335
Height: 20
Width: 200
Font: Regular
Text: Show Terrain Geometry

View File

@@ -125,6 +125,7 @@ World:
AllowedTerrainTypes: Clear,Road
AllowUnderActors: false
PathfinderDebugOverlay:
TerrainGeometryOverlay:
SpawnMapActors:
MPStartLocations:
CreateMPPlayers:

View File

@@ -104,6 +104,7 @@ World:
Race: ordos
DomainIndex:
PathfinderDebugOverlay:
TerrainGeometryOverlay:
BuildableTerrainLayer:
D2kResourceLayer:
ResourceClaimLayer:

View File

@@ -1,6 +1,6 @@
Container@DEBUG_PANEL:
Logic: DebugMenuLogic
Y: 20
Y: 10
Width: PARENT_RIGHT
Height: PARENT_BOTTOM
Children:
@@ -88,30 +88,36 @@ Container@DEBUG_PANEL:
Width: PARENT_RIGHT
Checkbox@SHOW_UNIT_PATHS:
X: 45
Y: 285
Y: 275
Width: 200
Height: 20
Font: Regular
Text: Show Unit Paths
Checkbox@SHOW_ASTAR:
X: 45
Y: 315
Y: 305
Height: 20
Width: 200
Font: Regular
Text: Show A* Cost
Checkbox@SHOW_COMBATOVERLAY:
X: 290
Y: 285
Y: 275
Height: 20
Width: 200
Font: Regular
Text: Show Combat Geometry
Checkbox@SHOW_GEOMETRY:
X: 290
Y: 315
Y: 305
Height: 20
Width: 200
Font: Regular
Text: Show Render Geometry
Checkbox@SHOW_TERRAIN_OVERLAY:
X: 290
Y: 335
Height: 20
Width: 200
Font: Regular
Text: Show Terrain Geometry

View File

@@ -133,6 +133,7 @@ World:
AllowUnderActors: false
TerrainType: Gems
PathfinderDebugOverlay:
TerrainGeometryOverlay:
SpawnMapActors:
CreateMPPlayers:
MPStartUnits@mcvonly:

Binary file not shown.

View File

@@ -0,0 +1,188 @@
Selectable: True
MapFormat: 6
RequiresMod: ts
Title: A River Runs Near It
Description: Describe your map here
Author: Westwood Studios
Tileset: TEMPERAT
MapSize: 134,256
Bounds: 2,4,130,234
UseAsShellmap: False
Type: Conquest
Options:
Players:
PlayerReference@Neutral:
Name: Neutral
OwnsWorld: True
NonCombatant: True
Race: gdi
PlayerReference@Multi0:
Name: Multi0
Playable: True
Race: Random
Enemies: Creeps
PlayerReference@Multi1:
Name: Multi1
Playable: True
Race: Random
Enemies: Creeps
PlayerReference@Multi2:
Name: Multi2
Playable: True
Race: Random
Enemies: Creeps
PlayerReference@Multi3:
Name: Multi3
Playable: True
Race: Random
Enemies: Creeps
PlayerReference@Multi4:
Name: Multi4
Playable: True
Race: Random
Enemies: Creeps
PlayerReference@Multi5:
Name: Multi5
Playable: True
Race: Random
Enemies: Creeps
PlayerReference@Creeps:
Name: Creeps
NonCombatant: True
Race: gdi
Enemies: Multi0, Multi1, Multi2, Multi3, Multi4, Multi5
Actors:
Actor0: tibtre01
Location: 133,-102
Owner: Neutral
Actor1: tibtre02
Location: 74,-39
Owner: Neutral
Actor2: tibtre03
Location: 52,21
Owner: Neutral
Actor3: tibtre02
Location: 110,88
Owner: Neutral
Actor4: tibtre03
Location: 177,39
Owner: Neutral
Actor5: tibtre01
Location: 208,-37
Owner: Neutral
Actor6: tibtre02
Location: 91,62
Owner: Neutral
Actor7: tibtre03
Location: 84,76
Owner: Neutral
Actor8: tibtre03
Location: 62,-7
Owner: Neutral
Actor9: tibtre03
Location: 179,-73
Owner: Neutral
Actor10: tibtre02
Location: 169,-63
Owner: Neutral
Actor11: tibtre01
Location: 111,-77
Owner: Neutral
Actor12: tibtre02
Location: 87,-66
Owner: Neutral
Actor13: tibtre03
Location: 99,-6
Owner: Neutral
Actor14: tibtre01
Location: 81,40
Owner: Neutral
Actor15: tibtre01
Location: 125,114
Owner: Neutral
Actor16: tibtre01
Location: 150,71
Owner: Neutral
Actor17: tibtre03
Location: 164,56
Owner: Neutral
Actor18: tibtre03
Location: 190,5
Owner: Neutral
Actor19: tibtre02
Location: 138,-66
Owner: Neutral
Actor20: tibtre01
Location: 181,-41
Owner: Neutral
Actor21: tibtre01
Location: 115,23
Owner: Neutral
Actor22: tibtre02
Location: 144,23
Owner: Neutral
Actor23: tibtre01
Location: 115,-24
Owner: Neutral
Actor24: tibtre01
Location: 150,-25
Owner: Neutral
Actor25: tibtre01
Location: 23,10
Owner: Neutral
Actor26: tibtre01
Location: 223,-1
Owner: Neutral
Actor27: mpspawn
Location: 59,26
Owner: Neutral
Actor28: mpspawn
Location: 207,-31
Owner: Neutral
Actor29: mpspawn
Location: 82,-35
Owner: Neutral
Actor30: mpspawn
Location: 178,34
Owner: Neutral
Actor31: mpspawn
Location: 137,-94
Owner: Neutral
Actor32: mpspawn
Location: 115,85
Owner: Neutral
Actor33: waypoint
Location: 132,-4
Owner: Neutral
Actor34: waypoint
Location: 132,-4
Owner: Neutral
Smudges:
Rules:
Sequences:
VoxelSequences:
Weapons:
Voices:
Notifications:
Translations:

View File

@@ -148,6 +148,7 @@ World:
AllowUnderActors: false
TerrainType: BlueTiberium
PathfinderDebugOverlay:
TerrainGeometryOverlay:
SpawnMapActors:
CreateMPPlayers:
MPStartUnits@MCV:

View File

@@ -3,6 +3,8 @@ General:
Id: TEMPERAT
Extensions: .tem, .shp
Palette: isotem.pal
MaxGroundHeight: 16
HeightDebugColors: 128,0,0,0, 128,0,0,68, 128,0,0,136, 128,0,0,204, 128,0,0,255, 128,68,0,204, 128,136,0,136, 128,204,0,68, 128,255,17,0, 128,255,85,0, 128,255,153,0, 128,255,221,0, 128,221,255,0, 128,153,255,0, 128,85,255,0, 128,17,255,0
EditorTemplateOrder: Misc Buildings, Clear, Cliff Pieces, Ice Flow, House, Blank, Ice Ramps, Cliff Set, Civilian Buildings, Shore Pieces, Rough LAT tile, Clear/Rough LAT, Cliff/Water pieces, Bendy Dirt Roads, Dirt Road Junctions, Straight Dirt Roads, Bridges, Paved Roads, Water, Dirt Road Slopes, Slope Set Pieces, Dead Oil Tanker, Ruins, Waterfalls, Ground 01, Ground 02, Sand, Sand/Clear LAT, Rough ground, Paved Road Ends, TrainBridges, Pavement, Pavement/Clear LAT, Paved road bits, Green, Green/Clear LAT, Ramp edge fixup, Water slopes, Pavement (Use for LAT), Paved Road Slopes, Monorail Slopes, Waterfalls-B, Waterfalls-C, Waterfalls-D, Tunnel Floor, Tunnel Side, TrackTunnel Floor, Destroyable Cliffs, Water Caves, Scrin Wreckage, DirtTrackTunnel Floor, DirtTunnel Floor
SheetSize: 2048