Add the world components of the new editor.
This commit is contained in:
@@ -48,7 +48,7 @@ namespace OpenRA
|
||||
return info;
|
||||
}
|
||||
|
||||
public MiniYaml Save()
|
||||
public MiniYaml Save(Func<object, bool> initFilter = null)
|
||||
{
|
||||
var ret = new MiniYaml(Type);
|
||||
foreach (var init in InitDict)
|
||||
@@ -56,6 +56,9 @@ namespace OpenRA
|
||||
if (init is ISuppressInitExport)
|
||||
continue;
|
||||
|
||||
if (initFilter != null && !initFilter(init))
|
||||
continue;
|
||||
|
||||
var initName = init.GetType().Name;
|
||||
ret.Nodes.Add(new MiniYamlNode(initName.Substring(0, initName.Length - 4), FieldSaver.Save(init)));
|
||||
}
|
||||
|
||||
@@ -170,7 +170,8 @@ namespace OpenRA
|
||||
TileSet = map.Rules.TileSets[Map.Tileset];
|
||||
SharedRandom = new MersenneTwister(orderManager.LobbyInfo.GlobalSettings.RandomSeed);
|
||||
|
||||
WorldActor = CreateActor("World", new TypeDictionary());
|
||||
var worldActorType = type == WorldType.Editor ? "EditorWorld" : "World";
|
||||
WorldActor = CreateActor(worldActorType, new TypeDictionary());
|
||||
ActorMap = WorldActor.Trait<ActorMap>();
|
||||
ScreenMap = WorldActor.Trait<ScreenMap>();
|
||||
|
||||
|
||||
@@ -627,6 +627,9 @@
|
||||
<Compile Include="Traits\Plug.cs" />
|
||||
<Compile Include="Widgets\Logic\Ingame\MenuButtonsChromeLogic.cs" />
|
||||
<Compile Include="Widgets\Logic\Ingame\LoadIngamePerfLogic.cs" />
|
||||
<Compile Include="Traits\World\EditorActorLayer.cs" />
|
||||
<Compile Include="Traits\World\EditorActorPreview.cs" />
|
||||
<Compile Include="Traits\World\EditorResourceLayer.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
|
||||
268
OpenRA.Mods.Common/Traits/World/EditorActorLayer.cs
Normal file
268
OpenRA.Mods.Common/Traits/World/EditorActorLayer.cs
Normal file
@@ -0,0 +1,268 @@
|
||||
#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;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Mods.Common.Graphics;
|
||||
using OpenRA.Primitives;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Traits
|
||||
{
|
||||
[Desc("Required for the map editor to work. Attach this to the world actor.")]
|
||||
public class EditorActorLayerInfo : ITraitInfo
|
||||
{
|
||||
[Desc("Size of partition bins (world pixels)")]
|
||||
public readonly int BinSize = 250;
|
||||
|
||||
public object Create(ActorInitializer init) { return new EditorActorLayer(init.Self, this); }
|
||||
}
|
||||
|
||||
public class EditorActorLayer : IWorldLoaded, ITickRender, IRender, IRadarSignature, ICreatePlayers
|
||||
{
|
||||
readonly EditorActorLayerInfo info;
|
||||
readonly Dictionary<string, EditorActorPreview> previews = new Dictionary<string, EditorActorPreview>();
|
||||
readonly Dictionary<CPos, List<EditorActorPreview>> cellMap = new Dictionary<CPos, List<EditorActorPreview>>();
|
||||
|
||||
SpatiallyPartitioned<EditorActorPreview> screenMap;
|
||||
WorldRenderer worldRenderer;
|
||||
|
||||
public MapPlayers Players { get; private set; }
|
||||
|
||||
public EditorActorLayer(Actor self, EditorActorLayerInfo info)
|
||||
{
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
public void CreatePlayers(World w)
|
||||
{
|
||||
if (w.Type != WorldType.Editor)
|
||||
return;
|
||||
|
||||
Players = new MapPlayers(w.Map.PlayerDefinitions);
|
||||
}
|
||||
|
||||
public void WorldLoaded(World world, WorldRenderer wr)
|
||||
{
|
||||
if (world.Type != WorldType.Editor)
|
||||
return;
|
||||
|
||||
worldRenderer = wr;
|
||||
|
||||
foreach (var pr in Players.Players.Values)
|
||||
wr.UpdatePalettesForPlayer(pr.Name, pr.Color, false);
|
||||
|
||||
var ts = Game.ModData.Manifest.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);
|
||||
|
||||
foreach (var kv in world.Map.ActorDefinitions)
|
||||
Add(kv.Key, new ActorReference(kv.Value.Value, kv.Value.ToDictionary()), true);
|
||||
|
||||
// Update neighbours in one pass
|
||||
foreach (var p in previews.Values)
|
||||
UpdateNeighbours(p.Footprint);
|
||||
}
|
||||
|
||||
public void TickRender(WorldRenderer wr, Actor self)
|
||||
{
|
||||
if (wr.World.Type != WorldType.Editor)
|
||||
return;
|
||||
|
||||
foreach (var kv in previews.Values)
|
||||
kv.Tick();
|
||||
}
|
||||
|
||||
static readonly IEnumerable<IRenderable> NoRenderables = Enumerable.Empty<IRenderable>();
|
||||
public virtual IEnumerable<IRenderable> Render(Actor self, WorldRenderer wr)
|
||||
{
|
||||
if (wr.World.Type != WorldType.Editor)
|
||||
return NoRenderables;
|
||||
|
||||
return PreviewsInBox(wr.Viewport.TopLeft, wr.Viewport.BottomRight)
|
||||
.SelectMany(p => p.Render());
|
||||
}
|
||||
|
||||
public EditorActorPreview Add(ActorReference reference) { return Add(NextActorName(), reference); }
|
||||
|
||||
EditorActorPreview Add(string id, ActorReference reference, bool initialSetup = false)
|
||||
{
|
||||
var owner = Players.Players[reference.InitDict.Get<OwnerInit>().PlayerName];
|
||||
|
||||
var preview = new EditorActorPreview(worldRenderer, id, reference, owner);
|
||||
previews.Add(id, preview);
|
||||
screenMap.Add(preview, preview.Bounds);
|
||||
|
||||
foreach (var kv in preview.Footprint)
|
||||
{
|
||||
List<EditorActorPreview> list;
|
||||
if (!cellMap.TryGetValue(kv.Key, out list))
|
||||
{
|
||||
list = new List<EditorActorPreview>();
|
||||
cellMap.Add(kv.Key, list);
|
||||
}
|
||||
|
||||
list.Add(preview);
|
||||
}
|
||||
|
||||
if (!initialSetup)
|
||||
{
|
||||
UpdateNeighbours(preview.Footprint);
|
||||
|
||||
if (reference.Type == "mpspawn")
|
||||
SyncMultiplayerCount();
|
||||
}
|
||||
|
||||
return preview;
|
||||
}
|
||||
|
||||
public void Remove(EditorActorPreview preview)
|
||||
{
|
||||
previews.Remove(preview.ID);
|
||||
screenMap.Remove(preview);
|
||||
|
||||
foreach (var kv in preview.Footprint)
|
||||
{
|
||||
List<EditorActorPreview> list;
|
||||
if (!cellMap.TryGetValue(kv.Key, out list))
|
||||
continue;
|
||||
|
||||
list.Remove(preview);
|
||||
|
||||
if (!list.Any())
|
||||
cellMap.Remove(kv.Key);
|
||||
}
|
||||
|
||||
UpdateNeighbours(preview.Footprint);
|
||||
|
||||
if (preview.Info.Name == "mpspawn")
|
||||
SyncMultiplayerCount();
|
||||
}
|
||||
|
||||
void SyncMultiplayerCount()
|
||||
{
|
||||
var newCount = previews.Count(p => p.Value.Info.Name == "mpspawn");
|
||||
var mp = Players.Players.Where(p => p.Key.StartsWith("Multi")).ToList();
|
||||
foreach (var kv in mp)
|
||||
{
|
||||
var name = kv.Key;
|
||||
var index = int.Parse(name.Substring(5));
|
||||
|
||||
if (index >= newCount)
|
||||
{
|
||||
Players.Players.Remove(name);
|
||||
worldRenderer.World.Players.RemoveAll(pp => pp.InternalName == name);
|
||||
}
|
||||
}
|
||||
|
||||
for (var index = 0; index < newCount; index++)
|
||||
{
|
||||
if (Players.Players.ContainsKey("Multi{0}".F(index)))
|
||||
continue;
|
||||
|
||||
var pr = new PlayerReference
|
||||
{
|
||||
Name = "Multi{0}".F(index),
|
||||
Race = "Random",
|
||||
Playable = true,
|
||||
Enemies = new[] { "Creeps" }
|
||||
};
|
||||
|
||||
Players.Players.Add(pr.Name, pr);
|
||||
worldRenderer.UpdatePalettesForPlayer(pr.Name, pr.Color, true);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateNeighbours(IReadOnlyDictionary<CPos, SubCell> footprint)
|
||||
{
|
||||
// Include actors inside the footprint too
|
||||
var cells = OpenRA.Traits.Util.ExpandFootprint(footprint.Keys, true);
|
||||
foreach (var p in cells.SelectMany(c => PreviewsAt(c)))
|
||||
p.ReplaceInit(new RuntimeNeighbourInit(NeighbouringPreviews(p.Footprint)));
|
||||
}
|
||||
|
||||
Dictionary<CPos, string[]> NeighbouringPreviews(IReadOnlyDictionary<CPos, SubCell> footprint)
|
||||
{
|
||||
var cells = OpenRA.Traits.Util.ExpandFootprint(footprint.Keys, true).Except(footprint.Keys);
|
||||
return cells.ToDictionary(c => c, c => PreviewsAt(c).Select(p => p.Info.Name).ToArray());
|
||||
}
|
||||
|
||||
public IEnumerable<EditorActorPreview> PreviewsInBox(int2 a, int2 b)
|
||||
{
|
||||
return screenMap.InBox(Rectangle.FromLTRB(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y), Math.Max(a.X, b.X), Math.Max(a.Y, b.Y)));
|
||||
}
|
||||
|
||||
public IEnumerable<EditorActorPreview> PreviewsInBox(Rectangle r)
|
||||
{
|
||||
return screenMap.InBox(r);
|
||||
}
|
||||
|
||||
public IEnumerable<EditorActorPreview> PreviewsAt(CPos cell)
|
||||
{
|
||||
List<EditorActorPreview> list;
|
||||
if (cellMap.TryGetValue(cell, out list))
|
||||
return list;
|
||||
|
||||
return Enumerable.Empty<EditorActorPreview>();
|
||||
}
|
||||
|
||||
public SubCell FreeSubCellAt(CPos cell)
|
||||
{
|
||||
var map = worldRenderer.World.Map;
|
||||
var previews = PreviewsAt(cell).ToList();
|
||||
if (!previews.Any())
|
||||
return map.DefaultSubCell;
|
||||
|
||||
for (var i = (int)SubCell.First; i < map.SubCellOffsets.Length; i++)
|
||||
if (!previews.Any(p => p.Footprint[cell] == (SubCell)i))
|
||||
return (SubCell)i;
|
||||
|
||||
return SubCell.Invalid;
|
||||
}
|
||||
|
||||
public IEnumerable<EditorActorPreview> PreviewsAt(int2 worldPx)
|
||||
{
|
||||
return screenMap.At(worldPx);
|
||||
}
|
||||
|
||||
string NextActorName()
|
||||
{
|
||||
var id = previews.Count();
|
||||
var possibleName = "Actor" + id.ToString();
|
||||
|
||||
while (previews.ContainsKey(possibleName))
|
||||
{
|
||||
id++;
|
||||
possibleName = "Actor" + id.ToString();
|
||||
}
|
||||
|
||||
return possibleName;
|
||||
}
|
||||
|
||||
public List<MiniYamlNode> Save()
|
||||
{
|
||||
var nodes = new List<MiniYamlNode>();
|
||||
foreach (var a in previews)
|
||||
nodes.Add(new MiniYamlNode(a.Key, a.Value.Save()));
|
||||
|
||||
return nodes;
|
||||
}
|
||||
|
||||
public IEnumerable<Pair<CPos, Color>> RadarSignatureCells(Actor self)
|
||||
{
|
||||
return cellMap.SelectMany(c => c.Value.Select(p => Pair.New(c.Key, p.Owner.Color.RGB)));
|
||||
}
|
||||
}
|
||||
}
|
||||
164
OpenRA.Mods.Common/Traits/World/EditorActorPreview.cs
Normal file
164
OpenRA.Mods.Common/Traits/World/EditorActorPreview.cs
Normal file
@@ -0,0 +1,164 @@
|
||||
#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;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Mods.Common.Graphics;
|
||||
using OpenRA.Primitives;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Traits
|
||||
{
|
||||
public class EditorActorPreview
|
||||
{
|
||||
public readonly string Tooltip;
|
||||
public readonly string ID;
|
||||
public readonly ActorInfo Info;
|
||||
public readonly PlayerReference Owner;
|
||||
public readonly WPos CenterPosition;
|
||||
public readonly IReadOnlyDictionary<CPos, SubCell> Footprint;
|
||||
public readonly Rectangle Bounds;
|
||||
|
||||
public SubCell SubCell { get; private set; }
|
||||
|
||||
readonly ActorReference actor;
|
||||
readonly WorldRenderer worldRenderer;
|
||||
IActorPreview[] previews;
|
||||
|
||||
public EditorActorPreview(WorldRenderer worldRenderer, string id, ActorReference actor, PlayerReference owner)
|
||||
{
|
||||
ID = id;
|
||||
this.actor = actor;
|
||||
this.Owner = owner;
|
||||
this.worldRenderer = worldRenderer;
|
||||
|
||||
if (!actor.InitDict.Contains<RaceInit>())
|
||||
actor.InitDict.Add(new RaceInit(owner.Race));
|
||||
|
||||
if (!actor.InitDict.Contains<OwnerInit>())
|
||||
actor.InitDict.Add(new OwnerInit(owner.Name));
|
||||
|
||||
var world = worldRenderer.World;
|
||||
if (!world.Map.Rules.Actors.TryGetValue(actor.Type.ToLowerInvariant(), out Info))
|
||||
throw new InvalidDataException("Actor {0} of unknown type {1}".F(id, actor.Type.ToLowerInvariant()));
|
||||
|
||||
CenterPosition = PreviewPosition(world, actor.InitDict);
|
||||
|
||||
var location = actor.InitDict.Get<LocationInit>().Value(worldRenderer.World);
|
||||
var ios = Info.Traits.GetOrDefault<IOccupySpaceInfo>();
|
||||
|
||||
var subCellInit = actor.InitDict.GetOrDefault<SubCellInit>();
|
||||
var subCell = subCellInit != null ? subCellInit.Value(worldRenderer.World) : SubCell.Any;
|
||||
|
||||
if (ios != null)
|
||||
Footprint = ios.OccupiedCells(Info, location, subCell);
|
||||
else
|
||||
{
|
||||
var footprint = new Dictionary<CPos, SubCell>() { { location, SubCell.FullCell } };
|
||||
Footprint = new ReadOnlyDictionary<CPos, SubCell>(footprint);
|
||||
}
|
||||
|
||||
var tooltipInfo = Info.Traits.GetOrDefault<ITooltipInfo>();
|
||||
Tooltip = "{0} ({1})".F(tooltipInfo != null ? tooltipInfo.TooltipForPlayerStance(Stance.None) : Info.Name, ID);
|
||||
|
||||
GeneratePreviews();
|
||||
|
||||
// Bounds are fixed from the initial render.
|
||||
// If this is a problem, then we may need to fetch the area from somewhere else
|
||||
var r = previews
|
||||
.SelectMany(p => p.Render(worldRenderer, CenterPosition))
|
||||
.Select(rr => rr.PrepareRender(worldRenderer));
|
||||
|
||||
if (r.Any())
|
||||
{
|
||||
Bounds = r.First().ScreenBounds(worldRenderer);
|
||||
foreach (var rr in r.Skip(1))
|
||||
Bounds = Rectangle.Union(Bounds, rr.ScreenBounds(worldRenderer));
|
||||
}
|
||||
}
|
||||
|
||||
public void Tick()
|
||||
{
|
||||
foreach (var p in previews)
|
||||
p.Tick();
|
||||
}
|
||||
|
||||
public IEnumerable<IRenderable> Render()
|
||||
{
|
||||
return previews.SelectMany(p => p.Render(worldRenderer, CenterPosition));
|
||||
}
|
||||
|
||||
public void ReplaceInit<T>(T init)
|
||||
{
|
||||
var original = actor.InitDict.GetOrDefault<T>();
|
||||
if (original != null)
|
||||
actor.InitDict.Remove(original);
|
||||
|
||||
actor.InitDict.Add(init);
|
||||
GeneratePreviews();
|
||||
}
|
||||
|
||||
public T Init<T>()
|
||||
{
|
||||
return actor.InitDict.GetOrDefault<T>();
|
||||
}
|
||||
|
||||
public MiniYaml Save()
|
||||
{
|
||||
Func<object, bool> saveInit = init =>
|
||||
{
|
||||
var race = init as RaceInit;
|
||||
if (race != null && race.Race == Owner.Race)
|
||||
return false;
|
||||
|
||||
// TODO: Other default values will need to be filtered
|
||||
// here after we have built a properties panel
|
||||
return true;
|
||||
};
|
||||
|
||||
return actor.Save(saveInit);
|
||||
}
|
||||
|
||||
WPos PreviewPosition(World world, TypeDictionary init)
|
||||
{
|
||||
if (init.Contains<CenterPositionInit>())
|
||||
return init.Get<CenterPositionInit>().Value(world);
|
||||
|
||||
if (init.Contains<LocationInit>())
|
||||
{
|
||||
var cell = init.Get<LocationInit>().Value(world);
|
||||
var offset = WVec.Zero;
|
||||
|
||||
var subCellInit = actor.InitDict.GetOrDefault<SubCellInit>();
|
||||
var subCell = subCellInit != null ? subCellInit.Value(worldRenderer.World) : SubCell.Any;
|
||||
|
||||
var buildingInfo = Info.Traits.GetOrDefault<BuildingInfo>();
|
||||
if (buildingInfo != null)
|
||||
offset = FootprintUtils.CenterOffset(world, buildingInfo);
|
||||
|
||||
return world.Map.CenterOfSubCell(cell, subCell) + offset;
|
||||
}
|
||||
else
|
||||
throw new InvalidDataException("Actor {0} must define Location or CenterPosition".F(ID));
|
||||
}
|
||||
|
||||
void GeneratePreviews()
|
||||
{
|
||||
var init = new ActorPreviewInitializer(Info, worldRenderer, actor.InitDict);
|
||||
previews = Info.Traits.WithInterface<IRenderActorPreviewInfo>()
|
||||
.SelectMany(rpi => rpi.RenderPreview(init))
|
||||
.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
148
OpenRA.Mods.Common/Traits/World/EditorResourceLayer.cs
Normal file
148
OpenRA.Mods.Common/Traits/World/EditorResourceLayer.cs
Normal file
@@ -0,0 +1,148 @@
|
||||
#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;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Mods.Common.Graphics;
|
||||
using OpenRA.Primitives;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Traits
|
||||
{
|
||||
using CellContents = ResourceLayer.CellContents;
|
||||
|
||||
[Desc("Required for the map editor to work. Attach this to the world actor.")]
|
||||
public class EditorResourceLayerInfo : ITraitInfo, Requires<ResourceTypeInfo>
|
||||
{
|
||||
public virtual object Create(ActorInitializer init) { return new EditorResourceLayer(init.Self); }
|
||||
}
|
||||
|
||||
public class EditorResourceLayer : IWorldLoaded, IRenderOverlay
|
||||
{
|
||||
protected readonly Map Map;
|
||||
protected readonly TileSet Tileset;
|
||||
protected readonly Dictionary<int, ResourceType> Resources;
|
||||
protected readonly CellLayer<CellContents> Tiles;
|
||||
protected readonly HashSet<CPos> Dirty = new HashSet<CPos>();
|
||||
|
||||
public EditorResourceLayer(Actor self)
|
||||
{
|
||||
if (self.World.Type != WorldType.Editor)
|
||||
return;
|
||||
|
||||
Map = self.World.Map;
|
||||
Tileset = self.World.TileSet;
|
||||
|
||||
Tiles = new CellLayer<CellContents>(Map);
|
||||
Resources = self.TraitsImplementing<ResourceType>()
|
||||
.ToDictionary(r => r.Info.ResourceType, r => r);
|
||||
|
||||
Map.MapResources.Value.CellEntryChanged += UpdateCell;
|
||||
}
|
||||
|
||||
public void WorldLoaded(World w, WorldRenderer wr)
|
||||
{
|
||||
if (w.Type != WorldType.Editor)
|
||||
return;
|
||||
|
||||
foreach (var cell in Map.Cells)
|
||||
UpdateCell(cell);
|
||||
}
|
||||
|
||||
public void UpdateCell(CPos cell)
|
||||
{
|
||||
var uv = cell.ToMPos(Map);
|
||||
var tile = Map.MapResources.Value[uv];
|
||||
|
||||
ResourceType type;
|
||||
if (Resources.TryGetValue(tile.Type, out type))
|
||||
{
|
||||
Tiles[uv] = new CellContents
|
||||
{
|
||||
Type = type,
|
||||
Variant = ChooseRandomVariant(type),
|
||||
};
|
||||
|
||||
Map.CustomTerrain[uv] = Tileset.GetTerrainIndex(type.Info.TerrainType);
|
||||
}
|
||||
else
|
||||
{
|
||||
Tiles[uv] = CellContents.Empty;
|
||||
Map.CustomTerrain[uv] = byte.MaxValue;
|
||||
}
|
||||
|
||||
// Ingame resource rendering is a giant hack (#6395),
|
||||
// so we must also touch all the neighbouring tiles
|
||||
Dirty.Add(cell);
|
||||
foreach (var d in CVec.Directions)
|
||||
{
|
||||
var c = cell + d;
|
||||
if (Map.Contains(c))
|
||||
Dirty.Add(c);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual string ChooseRandomVariant(ResourceType t)
|
||||
{
|
||||
return t.Variants.Keys.Random(Game.CosmeticRandom);
|
||||
}
|
||||
|
||||
public virtual CellContents UpdateDirtyTile(CPos c)
|
||||
{
|
||||
var t = Tiles[c];
|
||||
|
||||
// Empty tile
|
||||
if (t.Type == null)
|
||||
{
|
||||
t.Sprite = null;
|
||||
return t;
|
||||
}
|
||||
|
||||
// Set density based on the number of neighboring resources
|
||||
var adjacent = 0;
|
||||
var type = t.Type;
|
||||
for (var u = -1; u < 2; u++)
|
||||
for (var v = -1; v < 2; v++)
|
||||
if (Map.MapResources.Value[c + new CVec(u, v)].Type == type.Info.ResourceType)
|
||||
adjacent++;
|
||||
|
||||
t.Density = Math.Max(int2.Lerp(0, type.Info.MaxDensity, adjacent, 9), 1);
|
||||
|
||||
var sprites = type.Variants[t.Variant];
|
||||
var frame = int2.Lerp(0, sprites.Length - 1, t.Density - 1, type.Info.MaxDensity);
|
||||
t.Sprite = sprites[frame];
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
public void Render(WorldRenderer wr)
|
||||
{
|
||||
if (wr.World.Type != WorldType.Editor)
|
||||
return;
|
||||
|
||||
foreach (var c in Dirty)
|
||||
Tiles[c] = UpdateDirtyTile(c);
|
||||
|
||||
Dirty.Clear();
|
||||
|
||||
foreach (var uv in wr.Viewport.VisibleCells.MapCoords)
|
||||
{
|
||||
var t = Tiles[uv];
|
||||
if (t.Sprite != null)
|
||||
new SpriteRenderable(t.Sprite, wr.World.Map.CenterOfCell(uv.ToCPos(Map)),
|
||||
WVec.Zero, -511, t.Type.Palette, 1f, true).Render(wr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -248,6 +248,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
public struct CellContents
|
||||
{
|
||||
public static readonly CellContents Empty = new CellContents();
|
||||
public ResourceType Type;
|
||||
public int Density;
|
||||
public string Variant;
|
||||
|
||||
@@ -102,6 +102,7 @@ namespace OpenRA.Mods.Common.Widgets
|
||||
{
|
||||
leaveButton.Disabled = true;
|
||||
|
||||
if (world.Type == WorldType.Regular)
|
||||
Sound.PlayNotification(world.Map.Rules, null, "Speech", "Leave",
|
||||
world.LocalPlayer == null ? null : world.LocalPlayer.Country.Race);
|
||||
|
||||
|
||||
@@ -90,6 +90,7 @@
|
||||
<Compile Include="UtilityCommands\ImportD2kMapCommand.cs" />
|
||||
<Compile Include="Traits\Render\WithAttackOverlay.cs" />
|
||||
<Compile Include="Traits\Render\WithDecorationCarryable.cs" />
|
||||
<Compile Include="Traits\World\D2kEditorResourceLayer.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
|
||||
96
OpenRA.Mods.D2k/Traits/World/D2kEditorResourceLayer.cs
Normal file
96
OpenRA.Mods.D2k/Traits/World/D2kEditorResourceLayer.cs
Normal file
@@ -0,0 +1,96 @@
|
||||
#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;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Mods.Common.Traits;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.D2k.Traits
|
||||
{
|
||||
using CellContents = D2kResourceLayer.CellContents;
|
||||
using ClearSides = D2kResourceLayer.ClearSides;
|
||||
|
||||
[Desc("Used to render spice with round borders.")]
|
||||
public class D2kEditorResourceLayerInfo : EditorResourceLayerInfo
|
||||
{
|
||||
public override object Create(ActorInitializer init) { return new D2kEditorResourceLayer(init.Self); }
|
||||
}
|
||||
|
||||
public class D2kEditorResourceLayer : EditorResourceLayer
|
||||
{
|
||||
public D2kEditorResourceLayer(Actor self)
|
||||
: base(self) { }
|
||||
|
||||
public override CellContents UpdateDirtyTile(CPos c)
|
||||
{
|
||||
var t = Tiles[c];
|
||||
|
||||
// Empty tile
|
||||
if (t.Type == null)
|
||||
{
|
||||
t.Sprite = null;
|
||||
return t;
|
||||
}
|
||||
|
||||
int index;
|
||||
var clear = FindClearSides(t.Type, c);
|
||||
if (clear == ClearSides.None)
|
||||
{
|
||||
var sprites = D2kResourceLayer.Variants[t.Variant];
|
||||
var frame = t.Density > t.Type.Info.MaxDensity / 2 ? 1 : 0;
|
||||
t.Sprite = t.Type.Variants.First().Value[sprites[frame]];
|
||||
}
|
||||
else if (D2kResourceLayer.SpriteMap.TryGetValue(clear, out index))
|
||||
t.Sprite = t.Type.Variants.First().Value[index];
|
||||
else
|
||||
t.Sprite = null;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
protected override string ChooseRandomVariant(ResourceType t)
|
||||
{
|
||||
return D2kResourceLayer.Variants.Keys.Random(Game.CosmeticRandom);
|
||||
}
|
||||
|
||||
ClearSides FindClearSides(ResourceType t, CPos p)
|
||||
{
|
||||
var ret = ClearSides.None;
|
||||
if (Tiles[p + new CVec(0, -1)].Type != t)
|
||||
ret |= ClearSides.Top | ClearSides.TopLeft | ClearSides.TopRight;
|
||||
|
||||
if (Tiles[p + new CVec(-1, 0)].Type != t)
|
||||
ret |= ClearSides.Left | ClearSides.TopLeft | ClearSides.BottomLeft;
|
||||
|
||||
if (Tiles[p + new CVec(1, 0)].Type != t)
|
||||
ret |= ClearSides.Right | ClearSides.TopRight | ClearSides.BottomRight;
|
||||
|
||||
if (Tiles[p + new CVec(0, 1)].Type != t)
|
||||
ret |= ClearSides.Bottom | ClearSides.BottomLeft | ClearSides.BottomRight;
|
||||
|
||||
if (Tiles[p + new CVec(-1, -1)].Type != t)
|
||||
ret |= ClearSides.TopLeft;
|
||||
|
||||
if (Tiles[p + new CVec(1, -1)].Type != t)
|
||||
ret |= ClearSides.TopRight;
|
||||
|
||||
if (Tiles[p + new CVec(-1, 1)].Type != t)
|
||||
ret |= ClearSides.BottomLeft;
|
||||
|
||||
if (Tiles[p + new CVec(1, 1)].Type != t)
|
||||
ret |= ClearSides.BottomRight;
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,7 @@ namespace OpenRA.Mods.D2k.Traits
|
||||
|
||||
public class D2kResourceLayer : ResourceLayer
|
||||
{
|
||||
[Flags] enum ClearSides : byte
|
||||
[Flags] public enum ClearSides : byte
|
||||
{
|
||||
None = 0x0,
|
||||
Left = 0x1,
|
||||
@@ -37,7 +37,7 @@ namespace OpenRA.Mods.D2k.Traits
|
||||
All = 0xFF
|
||||
}
|
||||
|
||||
static readonly Dictionary<string, int[]> Variants = new Dictionary<string, int[]>()
|
||||
public static readonly Dictionary<string, int[]> Variants = new Dictionary<string, int[]>()
|
||||
{
|
||||
{ "cleara", new[] { 0, 50 } },
|
||||
{ "clearb", new[] { 1, 51 } },
|
||||
@@ -45,7 +45,7 @@ namespace OpenRA.Mods.D2k.Traits
|
||||
{ "cleard", new[] { 0, 53 } },
|
||||
};
|
||||
|
||||
static readonly Dictionary<ClearSides, int> SpriteMap = new Dictionary<ClearSides, int>()
|
||||
public static readonly Dictionary<ClearSides, int> SpriteMap = new Dictionary<ClearSides, int>()
|
||||
{
|
||||
{ ClearSides.None, 0 },
|
||||
{ ClearSides.Left | ClearSides.Top | ClearSides.TopLeft | ClearSides.TopRight | ClearSides.BottomLeft | ClearSides.BottomRight, 2 },
|
||||
|
||||
@@ -1,17 +1,8 @@
|
||||
World:
|
||||
^BaseWorld:
|
||||
Inherits: ^Palettes
|
||||
ChatCommands:
|
||||
DevCommands:
|
||||
PlayerCommands:
|
||||
HelpCommand:
|
||||
ScreenMap:
|
||||
ActorMap:
|
||||
LoadWidgetAtGameStart:
|
||||
ShellmapRoot: MENU_BACKGROUND
|
||||
ScreenShaker:
|
||||
BuildingInfluence:
|
||||
BridgeLayer:
|
||||
Bridges: bridge1, bridge2, bridge3, bridge4
|
||||
TerrainGeometryOverlay:
|
||||
ShroudRenderer:
|
||||
ShroudVariants: typea, typeb, typec, typed
|
||||
FogVariants: typea, typeb, typec, typed
|
||||
@@ -30,18 +21,6 @@ World:
|
||||
Name: Nod
|
||||
Race: nod
|
||||
Description: Brotherhood of Nod\nThe Brotherhood is a religious cult centered around their leader Kane\nand the alien substance Tiberium. They utilize stealth technology\nand guerilla tactics to defeat those who oppose them.
|
||||
ProductionQueueFromSelection:
|
||||
ProductionTabsWidget: PRODUCTION_TABS
|
||||
DomainIndex:
|
||||
SmudgeLayer@SCORCH:
|
||||
Type: Scorch
|
||||
Sequence: scorches
|
||||
SmokePercentage: 50
|
||||
SmudgeLayer@CRATER:
|
||||
Type: Crater
|
||||
Sequence: craters
|
||||
ResourceLayer:
|
||||
ResourceClaimLayer:
|
||||
ResourceType@green-tib:
|
||||
ResourceType: 1
|
||||
Palette: staticterrain
|
||||
@@ -66,8 +45,33 @@ World:
|
||||
PipColor: Blue
|
||||
AllowedTerrainTypes: Clear,Road
|
||||
AllowUnderActors: true
|
||||
LoadWidgetAtGameStart:
|
||||
ShellmapRoot: MENU_BACKGROUND
|
||||
|
||||
World:
|
||||
Inherits: ^BaseWorld
|
||||
ChatCommands:
|
||||
DevCommands:
|
||||
PlayerCommands:
|
||||
HelpCommand:
|
||||
ScreenShaker:
|
||||
NukePaletteEffect:
|
||||
BuildingInfluence:
|
||||
BridgeLayer:
|
||||
Bridges: bridge1, bridge2, bridge3, bridge4
|
||||
ProductionQueueFromSelection:
|
||||
ProductionTabsWidget: PRODUCTION_TABS
|
||||
DomainIndex:
|
||||
SmudgeLayer@SCORCH:
|
||||
Type: Scorch
|
||||
Sequence: scorches
|
||||
SmokePercentage: 50
|
||||
SmudgeLayer@CRATER:
|
||||
Type: Crater
|
||||
Sequence: craters
|
||||
ResourceLayer:
|
||||
ResourceClaimLayer:
|
||||
PathfinderDebugOverlay:
|
||||
TerrainGeometryOverlay:
|
||||
SpawnMapActors:
|
||||
MPStartLocations:
|
||||
CreateMPPlayers:
|
||||
@@ -143,3 +147,7 @@ World:
|
||||
PanelName: SKIRMISH_STATS
|
||||
RadarPings:
|
||||
|
||||
EditorWorld:
|
||||
Inherits: ^BaseWorld
|
||||
EditorActorLayer:
|
||||
EditorResourceLayer:
|
||||
|
||||
@@ -1,23 +1,8 @@
|
||||
World:
|
||||
^BaseWorld:
|
||||
Inherits: ^Palettes
|
||||
ChatCommands:
|
||||
DevCommands:
|
||||
PlayerCommands:
|
||||
HelpCommand:
|
||||
ScreenMap:
|
||||
ActorMap:
|
||||
LoadWidgetAtGameStart:
|
||||
ScreenShaker:
|
||||
BuildingInfluence:
|
||||
ProductionQueueFromSelection:
|
||||
ProductionPaletteWidget: PRODUCTION_PALETTE
|
||||
WormManager:
|
||||
CrateSpawner:
|
||||
Minimum: 0
|
||||
Maximum: 2
|
||||
SpawnInterval: 60
|
||||
WaterChance: 0
|
||||
ValidGround: Sand, Dune, Rock
|
||||
TerrainGeometryOverlay:
|
||||
ShroudRenderer:
|
||||
ShroudVariants: typea, typeb, typec, typed
|
||||
FogVariants: typea, typeb, typec, typed
|
||||
@@ -46,12 +31,6 @@ World:
|
||||
Name: Corrino
|
||||
Race: corrino
|
||||
Selectable: false
|
||||
DomainIndex:
|
||||
PathfinderDebugOverlay:
|
||||
BuildableTerrainLayer:
|
||||
D2kResourceLayer:
|
||||
TerrainGeometryOverlay:
|
||||
ResourceClaimLayer:
|
||||
ResourceType@Spice:
|
||||
ResourceType: 1
|
||||
Palette: d2k
|
||||
@@ -64,6 +43,30 @@ World:
|
||||
PipColor: green
|
||||
AllowedTerrainTypes: Sand
|
||||
AllowUnderActors: true
|
||||
LoadWidgetAtGameStart:
|
||||
|
||||
World:
|
||||
Inherits: ^BaseWorld
|
||||
ChatCommands:
|
||||
DevCommands:
|
||||
PlayerCommands:
|
||||
HelpCommand:
|
||||
ScreenShaker:
|
||||
BuildingInfluence:
|
||||
ProductionQueueFromSelection:
|
||||
ProductionPaletteWidget: PRODUCTION_PALETTE
|
||||
WormManager:
|
||||
CrateSpawner:
|
||||
Minimum: 0
|
||||
Maximum: 2
|
||||
SpawnInterval: 60
|
||||
WaterChance: 0
|
||||
ValidGround: Sand, Dune, Rock
|
||||
DomainIndex:
|
||||
PathfinderDebugOverlay:
|
||||
BuildableTerrainLayer:
|
||||
D2kResourceLayer:
|
||||
ResourceClaimLayer:
|
||||
SmudgeLayer@Rock:
|
||||
Type: RockCrater
|
||||
Sequence: rockcraters
|
||||
@@ -135,3 +138,8 @@ World:
|
||||
RadarPings:
|
||||
ObjectivesPanel:
|
||||
PanelName: SKIRMISH_STATS
|
||||
|
||||
EditorWorld:
|
||||
Inherits: ^BaseWorld
|
||||
EditorActorLayer:
|
||||
D2kEditorResourceLayer:
|
||||
|
||||
@@ -1,25 +1,9 @@
|
||||
World:
|
||||
^BaseWorld:
|
||||
Inherits: ^Palettes
|
||||
ChatCommands:
|
||||
DevCommands:
|
||||
PlayerCommands:
|
||||
HelpCommand:
|
||||
ScreenMap:
|
||||
ActorMap:
|
||||
ScreenMap:
|
||||
TerrainGeometryOverlay:
|
||||
LoadWidgetAtGameStart:
|
||||
ScreenShaker:
|
||||
BuildingInfluence:
|
||||
ProductionQueueFromSelection:
|
||||
ProductionPaletteWidget: PRODUCTION_PALETTE
|
||||
BridgeLayer:
|
||||
Bridges: bridge1, bridge2, br1, br2, br3, sbridge1, sbridge2, sbridge3, sbridge4
|
||||
CrateSpawner:
|
||||
DeliveryAircraft: badr
|
||||
QuantizedFacings: 16
|
||||
Minimum: 1
|
||||
Maximum: 3
|
||||
SpawnInterval: 120
|
||||
WaterChance: .2
|
||||
ShroudRenderer:
|
||||
FogVariants: shroud
|
||||
Index: 255, 16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240, 20, 40, 56, 65, 97, 130, 148, 194, 24, 33, 66, 132, 28, 41, 67, 134, 1, 2, 4, 8, 3, 6, 12, 9, 7, 14, 13, 11, 5, 10, 15, 255
|
||||
@@ -77,16 +61,6 @@ World:
|
||||
RandomRaceMembers: russia, ukraine
|
||||
Side: Random
|
||||
Description: A random Soviet country.
|
||||
DomainIndex:
|
||||
SmudgeLayer@SCORCH:
|
||||
Type: Scorch
|
||||
Sequence: scorches
|
||||
SmokePercentage: 50
|
||||
SmudgeLayer@CRATER:
|
||||
Type: Crater
|
||||
Sequence: craters
|
||||
ResourceLayer:
|
||||
ResourceClaimLayer:
|
||||
ResourceType@ore:
|
||||
ResourceType: 1
|
||||
Palette: player
|
||||
@@ -111,8 +85,37 @@ World:
|
||||
AllowedTerrainTypes: Clear,Road
|
||||
AllowUnderActors: true
|
||||
TerrainType: Gems
|
||||
|
||||
World:
|
||||
Inherits: ^BaseWorld
|
||||
ChatCommands:
|
||||
DevCommands:
|
||||
PlayerCommands:
|
||||
HelpCommand:
|
||||
ScreenShaker:
|
||||
BuildingInfluence:
|
||||
ProductionQueueFromSelection:
|
||||
ProductionPaletteWidget: PRODUCTION_PALETTE
|
||||
BridgeLayer:
|
||||
Bridges: bridge1, bridge2, br1, br2, br3, sbridge1, sbridge2, sbridge3, sbridge4
|
||||
CrateSpawner:
|
||||
DeliveryAircraft: badr
|
||||
QuantizedFacings: 16
|
||||
Minimum: 1
|
||||
Maximum: 3
|
||||
SpawnInterval: 120
|
||||
WaterChance: .2
|
||||
DomainIndex:
|
||||
SmudgeLayer@SCORCH:
|
||||
Type: Scorch
|
||||
Sequence: scorches
|
||||
SmokePercentage: 50
|
||||
SmudgeLayer@CRATER:
|
||||
Type: Crater
|
||||
Sequence: craters
|
||||
ResourceLayer:
|
||||
ResourceClaimLayer:
|
||||
PathfinderDebugOverlay:
|
||||
TerrainGeometryOverlay:
|
||||
SpawnMapActors:
|
||||
CreateMPPlayers:
|
||||
MPStartUnits@mcvonly:
|
||||
@@ -162,3 +165,7 @@ World:
|
||||
ObjectivesPanel:
|
||||
PanelName: SKIRMISH_STATS
|
||||
|
||||
EditorWorld:
|
||||
Inherits: ^BaseWorld
|
||||
EditorActorLayer:
|
||||
EditorResourceLayer:
|
||||
|
||||
@@ -1,15 +1,8 @@
|
||||
World:
|
||||
^BaseWorld:
|
||||
Inherits: ^Palettes
|
||||
ChatCommands:
|
||||
DevCommands:
|
||||
PlayerCommands:
|
||||
HelpCommand:
|
||||
ScreenMap:
|
||||
ActorMap:
|
||||
LoadWidgetAtGameStart:
|
||||
BuildingInfluence:
|
||||
ProductionQueueFromSelection:
|
||||
ProductionPaletteWidget: PRODUCTION_PALETTE
|
||||
ShroudRenderer:
|
||||
Index: 255, 16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240, 20, 40, 56, 65, 97, 130, 148, 194, 24, 33, 66, 132, 28, 41, 67, 134, 1, 2, 4, 8, 3, 6, 12, 9, 7, 14, 13, 11, 5, 10, 15, 255
|
||||
UseExtendedIndex: true
|
||||
@@ -25,6 +18,41 @@ World:
|
||||
Country@1:
|
||||
Name: Nod
|
||||
Race: nod
|
||||
ResourceType@Tiberium:
|
||||
ResourceType: 1
|
||||
Palette: greentiberium
|
||||
EditorSprite: waypoint # TODO: editor can't handle the real ones
|
||||
Variants: tib01, tib02, tib03, tib04, tib05, tib06, tib07, tib08, tib09, tib10, tib11, tib12, tib13, tib14, tib15, tib16, tib17, tib18, tib19, tib20
|
||||
MaxDensity: 12
|
||||
ValuePerUnit: 50
|
||||
Name: Tiberium
|
||||
PipColor: Green
|
||||
AllowedTerrainTypes: Clear, Rough, DirtRoad
|
||||
AllowUnderActors: true
|
||||
TerrainType: Tiberium
|
||||
ResourceType@BlueTiberium:
|
||||
ResourceType: 2
|
||||
Palette: bluetiberium
|
||||
EditorSprite: waypoint # TODO: editor can't handle the real ones
|
||||
Variants: tib01, tib02, tib03, tib04, tib05, tib06, tib07, tib08, tib09, tib10, tib11, tib12, tib13, tib14, tib15, tib16, tib17, tib18, tib19, tib20
|
||||
MaxDensity: 12
|
||||
ValuePerUnit: 100
|
||||
Name: BlueTiberium
|
||||
PipColor: Blue
|
||||
AllowedTerrainTypes: Clear, Rough, DirtRoad
|
||||
AllowUnderActors: true
|
||||
TerrainType: BlueTiberium
|
||||
TerrainGeometryOverlay:
|
||||
|
||||
World:
|
||||
Inherits: ^BaseWorld
|
||||
ChatCommands:
|
||||
DevCommands:
|
||||
PlayerCommands:
|
||||
HelpCommand:
|
||||
BuildingInfluence:
|
||||
ProductionQueueFromSelection:
|
||||
ProductionPaletteWidget: PRODUCTION_PALETTE
|
||||
DomainIndex:
|
||||
SmudgeLayer@SMALLSCORCH:
|
||||
Type: SmallScorch
|
||||
@@ -55,32 +83,7 @@ World:
|
||||
Sequence: largecraters
|
||||
ResourceLayer:
|
||||
ResourceClaimLayer:
|
||||
ResourceType@Tiberium:
|
||||
ResourceType: 1
|
||||
Palette: greentiberium
|
||||
EditorSprite: waypoint # TODO: editor can't handle the real ones
|
||||
Variants: tib01, tib02, tib03, tib04, tib05, tib06, tib07, tib08, tib09, tib10, tib11, tib12, tib13, tib14, tib15, tib16, tib17, tib18, tib19, tib20
|
||||
MaxDensity: 12
|
||||
ValuePerUnit: 50
|
||||
Name: Tiberium
|
||||
PipColor: Green
|
||||
AllowedTerrainTypes: Clear, Rough, DirtRoad
|
||||
AllowUnderActors: true
|
||||
TerrainType: Tiberium
|
||||
ResourceType@BlueTiberium:
|
||||
ResourceType: 2
|
||||
Palette: bluetiberium
|
||||
EditorSprite: waypoint # TODO: editor can't handle the real ones
|
||||
Variants: tib01, tib02, tib03, tib04, tib05, tib06, tib07, tib08, tib09, tib10, tib11, tib12, tib13, tib14, tib15, tib16, tib17, tib18, tib19, tib20
|
||||
MaxDensity: 12
|
||||
ValuePerUnit: 100
|
||||
Name: BlueTiberium
|
||||
PipColor: Blue
|
||||
AllowedTerrainTypes: Clear, Rough, DirtRoad
|
||||
AllowUnderActors: true
|
||||
TerrainType: BlueTiberium
|
||||
PathfinderDebugOverlay:
|
||||
TerrainGeometryOverlay:
|
||||
SpawnMapActors:
|
||||
CreateMPPlayers:
|
||||
MPStartUnits@MCV:
|
||||
@@ -151,3 +154,7 @@ World:
|
||||
RadarPings:
|
||||
StartGameNotification:
|
||||
|
||||
EditorWorld:
|
||||
Inherits: ^BaseWorld
|
||||
EditorActorLayer:
|
||||
EditorResourceLayer:
|
||||
|
||||
Reference in New Issue
Block a user