#region Copyright & License Information /* * Copyright 2007-2018 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, either version 3 of * the License, or (at your option) any later version. For more * information, see COPYING. */ #endregion using System.Collections.Generic; using OpenRA.Graphics; using OpenRA.Traits; namespace OpenRA.Mods.D2k.Traits { [Desc("Attach this to the world actor. Required for LaysTerrain to work.")] public class BuildableTerrainLayerInfo : ITraitInfo { [Desc("Palette to render the layer sprites in.")] public readonly string Palette = TileSet.TerrainPaletteInternalName; [Desc("The hitpoints, which can be reduced by the DamagesConcreteWarhead.")] public readonly int MaxStrength = 9000; public object Create(ActorInitializer init) { return new BuildableTerrainLayer(init.Self, this); } } public class BuildableTerrainLayer : IRenderOverlay, IWorldLoaded, ITickRender, INotifyActorDisposing { readonly BuildableTerrainLayerInfo info; readonly Dictionary dirty = new Dictionary(); readonly Map map; readonly CellLayer strength; TerrainSpriteLayer render; Theater theater; bool disposed; public BuildableTerrainLayer(Actor self, BuildableTerrainLayerInfo info) { this.info = info; map = self.World.Map; strength = new CellLayer(self.World.Map); } public void WorldLoaded(World w, WorldRenderer wr) { theater = wr.Theater; render = new TerrainSpriteLayer(w, wr, theater.Sheet, BlendMode.Alpha, wr.Palette(info.Palette), wr.World.Type != WorldType.Editor); } public void AddTile(CPos cell, TerrainTile tile) { map.CustomTerrain[cell] = map.Rules.TileSet.GetTerrainIndex(tile); strength[cell] = info.MaxStrength; // Terrain tiles define their origin at the topleft var s = theater.TileSprite(tile); dirty[cell] = new Sprite(s.Sheet, s.Bounds, s.ZRamp, float2.Zero, s.Channel, s.BlendMode); } public void HitTile(CPos cell, int damage) { if (strength[cell] == 0) return; strength[cell] = strength[cell] - damage; if (strength[cell] < 1) RemoveTile(cell); } public void RemoveTile(CPos cell) { map.CustomTerrain[cell] = byte.MaxValue; strength[cell] = 0; dirty[cell] = null; } void ITickRender.TickRender(WorldRenderer wr, Actor self) { var remove = new List(); foreach (var kv in dirty) { if (!self.World.FogObscures(kv.Key)) { render.Update(kv.Key, kv.Value); remove.Add(kv.Key); } } foreach (var r in remove) dirty.Remove(r); } void IRenderOverlay.Render(WorldRenderer wr) { render.Draw(wr.Viewport); } void INotifyActorDisposing.Disposing(Actor self) { if (disposed) return; render.Dispose(); disposed = true; } } }