diff --git a/OpenRA.FileFormats/Map/Map.cs b/OpenRA.FileFormats/Map/Map.cs index 799fb613e8..7e0b31af8a 100644 --- a/OpenRA.FileFormats/Map/Map.cs +++ b/OpenRA.FileFormats/Map/Map.cs @@ -53,7 +53,7 @@ namespace OpenRA.FileFormats public TileReference[,] MapTiles; public TileReference[,] MapResources; - + public string [,] CustomTerrain; // Temporary compat hacks public int XOffset { get { return TopLeft.X; } } @@ -148,6 +148,7 @@ namespace OpenRA.FileFormats // Rules Rules = yaml["Rules"].Nodes; + CustomTerrain = new string[MapSize.X, MapSize.Y]; LoadUid(); LoadBinaryData(); } diff --git a/OpenRA.Game/Graphics/Minimap.cs b/OpenRA.Game/Graphics/Minimap.cs index 03d5901cc5..069f7ba2a5 100644 --- a/OpenRA.Game/Graphics/Minimap.cs +++ b/OpenRA.Game/Graphics/Minimap.cs @@ -88,24 +88,19 @@ namespace OpenRA.Graphics var bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); - var customTerrain = world.WorldActor.traits.WithInterface(); unsafe { int* c = (int*)bitmapData.Scan0; - + for (var x = 0; x < map.Width; x++) for (var y = 0; y < map.Height; y++) { - var xy = new int2(x + map.TopLeft.X, y + map.TopLeft.Y); - foreach (var t in customTerrain) - { - var tt = t.GetTerrainType(xy); - if (tt != null) - { - *(c + (y * bitmapData.Stride >> 2) + x) = world.TileSet.Terrain[tt].Color.ToArgb(); - break; - } - } + var mapX = x + map.TopLeft.X; + var mapY = y + map.TopLeft.Y; + var custom = map.CustomTerrain[mapX,mapY]; + if (custom == null) + continue; + *(c + (y * bitmapData.Stride >> 2) + x) = world.TileSet.Terrain[custom].Color.ToArgb(); } } bitmap.UnlockBits(bitmapData); diff --git a/OpenRA.Game/Traits/Mobile.cs b/OpenRA.Game/Traits/Mobile.cs index e3894e4e3a..58dfafaaa7 100644 --- a/OpenRA.Game/Traits/Mobile.cs +++ b/OpenRA.Game/Traits/Mobile.cs @@ -192,13 +192,8 @@ namespace OpenRA.Traits { if (!self.World.Map.IsInMap(cell.X,cell.Y)) return float.PositiveInfinity; - - // Custom terrain types don't stack: pick one - var customTerrain = self.World.WorldActor.traits.WithInterface() - .Select( t => t.GetTerrainType(cell) ) - .FirstOrDefault( t => t != null ); - - var type = (customTerrain != null) ? customTerrain : self.World.GetTerrainType(cell); + + var type = self.World.GetTerrainType(cell); var additionalCost = self.World.WorldActor.traits.WithInterface() .Select( t => t.GetTerrainCost(cell, self) ).Sum(); @@ -210,13 +205,8 @@ namespace OpenRA.Traits var unitInfo = self.Info.Traits.GetOrDefault(); if( unitInfo == null ) return 0f; - - // Custom terrain types don't stack: pick one - var customTerrain = self.World.WorldActor.traits.WithInterface() - .Select( t => t.GetTerrainType(cell) ) - .FirstOrDefault( t => t != null ); - - var type = (customTerrain != null) ? customTerrain : self.World.GetTerrainType(cell); + + var type = self.World.GetTerrainType(cell); var modifier = self.traits .WithInterface() diff --git a/OpenRA.Game/Traits/TraitsInterfaces.cs b/OpenRA.Game/Traits/TraitsInterfaces.cs index e2769c2497..b314185508 100644 --- a/OpenRA.Game/Traits/TraitsInterfaces.cs +++ b/OpenRA.Game/Traits/TraitsInterfaces.cs @@ -48,7 +48,6 @@ namespace OpenRA.Traits public interface IAvoidHazard { string Type { get; } } public interface IStoreOre { int Capacity { get; }} - public interface ITerrainTypeModifier { string GetTerrainType(int2 cell); } public interface ITerrainCost { float GetTerrainCost(int2 cell, Actor forActor); } public interface IDisable { bool Disabled { get; } } diff --git a/OpenRA.Game/Traits/World/ResourceLayer.cs b/OpenRA.Game/Traits/World/ResourceLayer.cs index 5a8fcd37a9..abf3efd17d 100644 --- a/OpenRA.Game/Traits/World/ResourceLayer.cs +++ b/OpenRA.Game/Traits/World/ResourceLayer.cs @@ -17,7 +17,7 @@ namespace OpenRA.Traits { public class ResourceLayerInfo : TraitInfo { } - public class ResourceLayer: IRenderOverlay, ILoadWorldHook, ITerrainTypeModifier + public class ResourceLayer: IRenderOverlay, ILoadWorldHook { World world; @@ -75,15 +75,7 @@ namespace OpenRA.Traits if (content[x, y].type != null) content[x, y].density = GetIdealDensity(x, y); } - - public string GetTerrainType(int2 cell) - { - if (content[cell.X,cell.Y].type == null) - return null; - - return content[cell.X,cell.Y].type.info.TerrainType; - } - + Sprite[] ChooseContent(ResourceType t) { return t.info.Sprites[world.SharedRandom.Next(t.info.Sprites.Length)]; @@ -120,6 +112,8 @@ namespace OpenRA.Traits content[i, j].density = Math.Min( content[i, j].image.Length - 1, content[i, j].density + n); + + world.Map.CustomTerrain[i,j] = t.info.TerrainType; } public bool IsFull(int i, int j) { return content[i, j].density == content[i, j].image.Length - 1; } @@ -133,6 +127,7 @@ namespace OpenRA.Traits { content[p.X, p.Y].type = null; content[p.X, p.Y].image = null; + world.Map.CustomTerrain[p.X, p.Y] = null; } return type; } diff --git a/OpenRA.Game/WorldUtils.cs b/OpenRA.Game/WorldUtils.cs index c67bd3504a..c7c5521993 100755 --- a/OpenRA.Game/WorldUtils.cs +++ b/OpenRA.Game/WorldUtils.cs @@ -95,7 +95,8 @@ namespace OpenRA public static string GetTerrainType(this World world, int2 cell) { - return world.TileSet.GetTerrainType(world.Map.MapTiles[cell.X, cell.Y]); + var custom = world.Map.CustomTerrain[cell.X, cell.Y]; + return custom != null ? custom : world.TileSet.GetTerrainType(world.Map.MapTiles[cell.X, cell.Y]); } public static TerrainTypeInfo GetTerrainInfo(this World world, int2 cell) diff --git a/OpenRA.Mods.RA/Bridge.cs b/OpenRA.Mods.RA/Bridge.cs index 29e0bc5ebc..15bafdb25b 100644 --- a/OpenRA.Mods.RA/Bridge.cs +++ b/OpenRA.Mods.RA/Bridge.cs @@ -171,6 +171,10 @@ namespace OpenRA.Mods.RA currentTemplate = (ds == DamageState.Half && Info.DamagedTemplate > 0) ? Info.DamagedTemplate : (ds == DamageState.Dead && Info.DestroyedTemplate > 0) ? Info.DestroyedTemplate : Info.Template; + // Update map + foreach (var c in TileSprites[currentTemplate].Keys) + self.World.Map.CustomTerrain[c.X, c.Y] = GetTerrainType(c); + if (Info.Long && ds == DamageState.Dead) { // Long bridges have custom art for multiple segments being destroyed diff --git a/OpenRA.Mods.RA/BridgeLayer.cs b/OpenRA.Mods.RA/BridgeLayer.cs index 837b46cef6..980ebe5267 100644 --- a/OpenRA.Mods.RA/BridgeLayer.cs +++ b/OpenRA.Mods.RA/BridgeLayer.cs @@ -22,7 +22,7 @@ namespace OpenRA.Mods.RA public object Create(ActorInitializer init) { return new BridgeLayer(init.self, this); } } - class BridgeLayer : ILoadWorldHook, ITerrainTypeModifier + class BridgeLayer : ILoadWorldHook { readonly BridgeLayerInfo Info; readonly World world; @@ -106,13 +106,6 @@ namespace OpenRA.Mods.RA bridge.Create(tile, subTiles); } - public string GetTerrainType(int2 cell) - { - if (Bridges[ cell.X, cell.Y ] != null) - return Bridges[ cell.X, cell.Y ].GetTerrainType(cell); - return null; - } - // Used to check for neighbouring bridges public Bridge GetBridge(int2 cell) { diff --git a/OpenRA.Mods.RA/CrateDrop.cs b/OpenRA.Mods.RA/CrateDrop.cs index 774e7c9f8b..00ac4c13af 100644 --- a/OpenRA.Mods.RA/CrateDrop.cs +++ b/OpenRA.Mods.RA/CrateDrop.cs @@ -58,7 +58,7 @@ namespace OpenRA.Mods.RA var p = self.World.ChooseRandomCell(self.World.SharedRandom); // Is this valid terrain? - var terrainType = self.World.TileSet.GetTerrainType(self.World.Map.MapTiles[p.X, p.Y]); + var terrainType = self.World.GetTerrainType(p); if (!(inWater ? info.ValidWater : info.ValidGround).Contains(terrainType)) continue; // Don't drop on any actors diff --git a/OpenRA.Mods.RA/CrateSpawner.cs b/OpenRA.Mods.RA/CrateSpawner.cs index 02208493e4..c5dd0ab6f1 100644 --- a/OpenRA.Mods.RA/CrateSpawner.cs +++ b/OpenRA.Mods.RA/CrateSpawner.cs @@ -57,7 +57,7 @@ namespace OpenRA.Mods.RA var p = self.World.ChooseRandomCell(self.World.SharedRandom); // Is this valid terrain? - var terrainType = self.World.TileSet.GetTerrainType(self.World.Map.MapTiles[p.X, p.Y]); + var terrainType = self.World.GetTerrainType(p); if (!(inWater ? info.ValidWater : info.ValidGround).Contains(terrainType)) continue; // Don't spawn on any actors