Merge pull request #3596 from pchote/fog-visibility-freezing
Fog visibility freezing fixes #3206 et al
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
#region Copyright & License Information
|
#region Copyright & License Information
|
||||||
/*
|
/*
|
||||||
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
|
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
|
||||||
* This file is part of OpenRA, which is free software. It is made
|
* 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
|
* available to you under the terms of the GNU General Public License
|
||||||
* as published by the Free Software Foundation. For more information,
|
* as published by the Free Software Foundation. For more information,
|
||||||
@@ -9,22 +9,23 @@
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using OpenRA.Graphics;
|
using OpenRA.Graphics;
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace OpenRA.Traits
|
namespace OpenRA.Traits
|
||||||
{
|
{
|
||||||
public class ResourceLayerInfo : TraitInfo<ResourceLayer> { }
|
public class ResourceLayerInfo : TraitInfo<ResourceLayer> { }
|
||||||
|
|
||||||
public class ResourceLayer : IRenderOverlay, IWorldLoaded
|
public class ResourceLayer : IRenderOverlay, IWorldLoaded, ITickRender
|
||||||
{
|
{
|
||||||
World world;
|
World world;
|
||||||
|
|
||||||
public ResourceType[] resourceTypes;
|
ResourceType[] resourceTypes;
|
||||||
CellContents[,] content;
|
CellContents[,] content;
|
||||||
|
CellContents[,] render;
|
||||||
|
List<CPos> dirty;
|
||||||
bool hasSetupPalettes;
|
bool hasSetupPalettes;
|
||||||
|
|
||||||
public void Render(WorldRenderer wr)
|
public void Render(WorldRenderer wr)
|
||||||
@@ -37,24 +38,31 @@ namespace OpenRA.Traits
|
|||||||
}
|
}
|
||||||
|
|
||||||
var clip = Game.viewport.WorldBounds(world);
|
var clip = Game.viewport.WorldBounds(world);
|
||||||
for (int x = clip.Left; x < clip.Right; x++)
|
for (var x = clip.Left; x < clip.Right; x++)
|
||||||
for (int y = clip.Top; y < clip.Bottom; y++)
|
{
|
||||||
|
for (var y = clip.Top; y < clip.Bottom; y++)
|
||||||
{
|
{
|
||||||
if (world.ShroudObscures(new CPos(x, y)))
|
var pos = new CPos(x, y);
|
||||||
|
if (world.ShroudObscures(pos))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var c = content[x, y];
|
var c = render[x, y];
|
||||||
if (c.image != null)
|
if (c.Image != null)
|
||||||
c.image[c.density].DrawAt(
|
{
|
||||||
new CPos(x, y).ToPPos().ToFloat2(),
|
var tile = c.Image[c.Density];
|
||||||
c.type.info.PaletteRef);
|
var px = wr.ScreenPxPosition(pos.CenterPosition) - 0.5f * tile.size;
|
||||||
|
tile.DrawAt(px, c.Type.info.PaletteRef);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WorldLoaded(World w)
|
public void WorldLoaded(World w)
|
||||||
{
|
{
|
||||||
this.world = w;
|
this.world = w;
|
||||||
content = new CellContents[w.Map.MapSize.X, w.Map.MapSize.Y];
|
content = new CellContents[w.Map.MapSize.X, w.Map.MapSize.Y];
|
||||||
|
render = new CellContents[w.Map.MapSize.X, w.Map.MapSize.Y];
|
||||||
|
dirty = new List<CPos>();
|
||||||
|
|
||||||
resourceTypes = w.WorldActor.TraitsImplementing<ResourceType>().ToArray();
|
resourceTypes = w.WorldActor.TraitsImplementing<ResourceType>().ToArray();
|
||||||
foreach (var rt in resourceTypes)
|
foreach (var rt in resourceTypes)
|
||||||
@@ -62,8 +70,8 @@ namespace OpenRA.Traits
|
|||||||
|
|
||||||
var map = w.Map;
|
var map = w.Map;
|
||||||
|
|
||||||
for (int x = map.Bounds.Left; x < map.Bounds.Right; x++)
|
for (var x = map.Bounds.Left; x < map.Bounds.Right; x++)
|
||||||
for (int y = map.Bounds.Top; y < map.Bounds.Bottom; y++)
|
for (var y = map.Bounds.Top; y < map.Bounds.Bottom; y++)
|
||||||
{
|
{
|
||||||
var type = resourceTypes.FirstOrDefault(
|
var type = resourceTypes.FirstOrDefault(
|
||||||
r => r.info.ResourceType == w.Map.MapResources.Value[x, y].type);
|
r => r.info.ResourceType == w.Map.MapResources.Value[x, y].type);
|
||||||
@@ -71,27 +79,53 @@ namespace OpenRA.Traits
|
|||||||
if (type == null)
|
if (type == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!AllowResourceAt(type, new CPos(x,y)))
|
if (!AllowResourceAt(type, new CPos(x, y)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
content[x, y].type = type;
|
render[x, y].Type = content[x, y].Type = type;
|
||||||
content[x, y].image = ChooseContent(type);
|
render[x, y].Image = content[x, y].Image = ChooseContent(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int x = map.Bounds.Left; x < map.Bounds.Right; x++)
|
for (var x = map.Bounds.Left; x < map.Bounds.Right; x++)
|
||||||
for (int y = map.Bounds.Top; y < map.Bounds.Bottom; y++)
|
{
|
||||||
if (content[x, y].type != null)
|
for (var y = map.Bounds.Top; y < map.Bounds.Bottom; y++)
|
||||||
|
{
|
||||||
|
if (content[x, y].Type != null)
|
||||||
{
|
{
|
||||||
content[x, y].density = GetIdealDensity(x, y);
|
render[x, y].Density = content[x, y].Density = GetIdealDensity(x, y);
|
||||||
w.Map.CustomTerrain[x, y] = content[x, y].type.info.TerrainType;
|
w.Map.CustomTerrain[x, y] = content[x, y].Type.info.TerrainType;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TickRender(WorldRenderer wr, Actor self)
|
||||||
|
{
|
||||||
|
var remove = new List<CPos>();
|
||||||
|
foreach (var c in dirty)
|
||||||
|
{
|
||||||
|
if (!self.World.FogObscures(c))
|
||||||
|
{
|
||||||
|
render[c.X, c.Y] = content[c.X, c.Y];
|
||||||
|
remove.Add(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var r in remove)
|
||||||
|
dirty.Remove(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool AllowResourceAt(ResourceType rt, CPos a)
|
public bool AllowResourceAt(ResourceType rt, CPos a)
|
||||||
{
|
{
|
||||||
if (!world.Map.IsInMap(a.X, a.Y)) return false;
|
if (!world.Map.IsInMap(a.X, a.Y))
|
||||||
if (!rt.info.AllowedTerrainTypes.Contains(world.GetTerrainInfo(a).Type)) return false;
|
return false;
|
||||||
if (!rt.info.AllowUnderActors && world.ActorMap.AnyUnitsAt(a)) return false;
|
|
||||||
|
if (!rt.info.AllowedTerrainTypes.Contains(world.GetTerrainInfo(a).Type))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!rt.info.AllowUnderActors && world.ActorMap.AnyUnitsAt(a))
|
||||||
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,77 +139,95 @@ namespace OpenRA.Traits
|
|||||||
int sum = 0;
|
int sum = 0;
|
||||||
for (var u = -1; u < 2; u++)
|
for (var u = -1; u < 2; u++)
|
||||||
for (var v = -1; v < 2; v++)
|
for (var v = -1; v < 2; v++)
|
||||||
if (content[i + u, j + v].type == t)
|
if (content[i + u, j + v].Type == t)
|
||||||
++sum;
|
++sum;
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetIdealDensity(int x, int y)
|
int GetIdealDensity(int x, int y)
|
||||||
{
|
{
|
||||||
return (GetAdjacentCellsWith(content[x, y].type, x, y) *
|
return (GetAdjacentCellsWith(content[x, y].Type, x, y) *
|
||||||
(content[x, y].image.Length - 1)) / 9;
|
(content[x, y].Image.Length - 1)) / 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddResource(ResourceType t, int i, int j, int n)
|
public void AddResource(ResourceType t, int i, int j, int n)
|
||||||
{
|
{
|
||||||
if (content[i, j].type == null)
|
if (content[i, j].Type == null)
|
||||||
{
|
{
|
||||||
content[i, j].type = t;
|
content[i, j].Type = t;
|
||||||
content[i, j].image = ChooseContent(t);
|
content[i, j].Image = ChooseContent(t);
|
||||||
content[i, j].density = -1;
|
content[i, j].Density = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (content[i, j].type != t)
|
if (content[i, j].Type != t)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
content[i, j].density = Math.Min(
|
content[i, j].Density = Math.Min(
|
||||||
content[i, j].image.Length - 1,
|
content[i, j].Image.Length - 1,
|
||||||
content[i, j].density + n);
|
content[i, j].Density + n);
|
||||||
|
|
||||||
world.Map.CustomTerrain[i, j] = t.info.TerrainType;
|
world.Map.CustomTerrain[i, j] = t.info.TerrainType;
|
||||||
|
|
||||||
|
var cell = new CPos(i, j);
|
||||||
|
if (!dirty.Contains(cell))
|
||||||
|
dirty.Add(cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsFull(int i, int j) { return content[i, j].density == content[i, j].image.Length - 1; }
|
public bool IsFull(int i, int j)
|
||||||
|
{
|
||||||
|
return content[i, j].Density == content[i, j].Image.Length - 1;
|
||||||
|
}
|
||||||
|
|
||||||
public ResourceType Harvest(CPos p)
|
public ResourceType Harvest(CPos p)
|
||||||
{
|
{
|
||||||
var type = content[p.X, p.Y].type;
|
var type = content[p.X, p.Y].Type;
|
||||||
if (type == null) return null;
|
if (type == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
if (--content[p.X, p.Y].density < 0)
|
if (--content[p.X, p.Y].Density < 0)
|
||||||
{
|
{
|
||||||
content[p.X, p.Y].type = null;
|
content[p.X, p.Y].Type = null;
|
||||||
content[p.X, p.Y].image = null;
|
content[p.X, p.Y].Image = null;
|
||||||
world.Map.CustomTerrain[p.X, p.Y] = null;
|
world.Map.CustomTerrain[p.X, p.Y] = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!dirty.Contains(p))
|
||||||
|
dirty.Add(p);
|
||||||
|
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Destroy(CPos p)
|
public void Destroy(CPos p)
|
||||||
{
|
{
|
||||||
// Don't break other users of CustomTerrain if there are no resources
|
// Don't break other users of CustomTerrain if there are no resources
|
||||||
if (content[p.X, p.Y].type == null)
|
if (content[p.X, p.Y].Type == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
content[p.X, p.Y].type = null;
|
content[p.X, p.Y].Type = null;
|
||||||
content[p.X, p.Y].image = null;
|
content[p.X, p.Y].Image = null;
|
||||||
content[p.X, p.Y].density = 0;
|
content[p.X, p.Y].Density = 0;
|
||||||
world.Map.CustomTerrain[p.X, p.Y] = null;
|
world.Map.CustomTerrain[p.X, p.Y] = null;
|
||||||
|
|
||||||
|
if (!dirty.Contains(p))
|
||||||
|
dirty.Add(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResourceType GetResource(CPos p) { return content[p.X, p.Y].type; }
|
public ResourceType GetResource(CPos p) { return content[p.X, p.Y].Type; }
|
||||||
public int GetResourceDensity(CPos p) { return content[p.X, p.Y].density; }
|
public ResourceType GetRenderedResource(CPos p) { return render[p.X, p.Y].Type; }
|
||||||
|
public int GetResourceDensity(CPos p) { return content[p.X, p.Y].Density; }
|
||||||
public int GetMaxResourceDensity(CPos p)
|
public int GetMaxResourceDensity(CPos p)
|
||||||
{
|
{
|
||||||
if (content[p.X, p.Y].image == null) return 0;
|
if (content[p.X, p.Y].Image == null)
|
||||||
return content[p.X, p.Y].image.Length - 1;
|
return 0;
|
||||||
|
|
||||||
|
return content[p.X, p.Y].Image.Length - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct CellContents
|
public struct CellContents
|
||||||
{
|
{
|
||||||
public ResourceType type;
|
public ResourceType Type;
|
||||||
public Sprite[] image;
|
public Sprite[] Image;
|
||||||
public int density;
|
public int Density;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#region Copyright & License Information
|
#region Copyright & License Information
|
||||||
/*
|
/*
|
||||||
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
|
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
|
||||||
* This file is part of OpenRA, which is free software. It is made
|
* 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
|
* available to you under the terms of the GNU General Public License
|
||||||
* as published by the Free Software Foundation. For more information,
|
* as published by the Free Software Foundation. For more information,
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using OpenRA.FileFormats;
|
using OpenRA.FileFormats;
|
||||||
using OpenRA.Graphics;
|
using OpenRA.Graphics;
|
||||||
@@ -19,16 +20,25 @@ namespace OpenRA.Mods.RA.Buildings
|
|||||||
{
|
{
|
||||||
class BibLayerInfo : ITraitInfo
|
class BibLayerInfo : ITraitInfo
|
||||||
{
|
{
|
||||||
public readonly string[] BibTypes = {"bib3", "bib2", "bib1"};
|
public readonly string[] BibTypes = { "bib3", "bib2", "bib1" };
|
||||||
public readonly int[] BibWidths = {2,3,4};
|
public readonly int[] BibWidths = { 2, 3, 4 };
|
||||||
|
public readonly bool FrozenUnderFog = false;
|
||||||
public object Create(ActorInitializer init) { return new BibLayer(init.self, this); }
|
public object Create(ActorInitializer init) { return new BibLayer(init.self, this); }
|
||||||
}
|
}
|
||||||
|
|
||||||
class BibLayer: IRenderOverlay, IWorldLoaded
|
struct CachedBib
|
||||||
|
{
|
||||||
|
public Dictionary<CPos, TileReference<byte, byte>> Tiles;
|
||||||
|
public IEnumerable<CPos> Footprint;
|
||||||
|
public bool Visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
class BibLayer : IRenderOverlay, IWorldLoaded, ITickRender
|
||||||
{
|
{
|
||||||
World world;
|
World world;
|
||||||
BibLayerInfo info;
|
BibLayerInfo info;
|
||||||
Dictionary<CPos, TileReference<byte, byte>> tiles;
|
Dictionary<Actor, CachedBib> visible;
|
||||||
|
Dictionary<Actor, CachedBib> dirty;
|
||||||
Sprite[][] bibSprites;
|
Sprite[][] bibSprites;
|
||||||
|
|
||||||
public BibLayer(Actor self, BibLayerInfo info)
|
public BibLayer(Actor self, BibLayerInfo info)
|
||||||
@@ -36,57 +46,89 @@ namespace OpenRA.Mods.RA.Buildings
|
|||||||
this.info = info;
|
this.info = info;
|
||||||
bibSprites = info.BibTypes.Select(x => Game.modData.SpriteLoader.LoadAllSprites(x)).ToArray();
|
bibSprites = info.BibTypes.Select(x => Game.modData.SpriteLoader.LoadAllSprites(x)).ToArray();
|
||||||
|
|
||||||
self.World.ActorAdded +=
|
self.World.ActorAdded += a => DoBib(a, true);
|
||||||
a => { if (a.HasTrait<Bib>()) DoBib(a,true); };
|
self.World.ActorRemoved += a => DoBib(a, false);
|
||||||
self.World.ActorRemoved +=
|
|
||||||
a => { if (a.HasTrait<Bib>()) DoBib(a,false); };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WorldLoaded(World w)
|
public void WorldLoaded(World w)
|
||||||
{
|
{
|
||||||
world = w;
|
world = w;
|
||||||
tiles = new Dictionary<CPos, TileReference<byte, byte>>();
|
visible = new Dictionary<Actor, CachedBib>();
|
||||||
|
dirty = new Dictionary<Actor, CachedBib>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DoBib(Actor b, bool isAdd)
|
public void DoBib(Actor b, bool isAdd)
|
||||||
{
|
{
|
||||||
|
if (!b.HasTrait<Bib>())
|
||||||
|
return;
|
||||||
|
|
||||||
var buildingInfo = b.Info.Traits.Get<BuildingInfo>();
|
var buildingInfo = b.Info.Traits.Get<BuildingInfo>();
|
||||||
var size = buildingInfo.Dimensions.X;
|
var size = buildingInfo.Dimensions.X;
|
||||||
var bibOffset = buildingInfo.Dimensions.Y - 1;
|
var bibOffset = buildingInfo.Dimensions.Y - 1;
|
||||||
|
|
||||||
int bib = Array.IndexOf(info.BibWidths,size);
|
var bib = Array.IndexOf(info.BibWidths, size);
|
||||||
if (bib < 0)
|
if (bib < 0)
|
||||||
{
|
{
|
||||||
Log.Write("debug", "Cannot bib {0}-wide building {1}", size, b.Info.Name);
|
Log.Write("debug", "Cannot bib {0}-wide building {1}", size, b.Info.Name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 2 * size; i++)
|
dirty[b] = new CachedBib()
|
||||||
{
|
{
|
||||||
var p = b.Location + new CVec(i % size, i / size + bibOffset);
|
Footprint = FootprintUtils.Tiles(b),
|
||||||
if (isAdd)
|
Tiles = new Dictionary<CPos, TileReference<byte, byte>>(),
|
||||||
tiles[p] = new TileReference<byte, byte>((byte)(bib + 1), (byte)i);
|
Visible = isAdd
|
||||||
else
|
};
|
||||||
tiles.Remove(p);
|
|
||||||
|
for (var i = 0; i < 2 * size; i++)
|
||||||
|
{
|
||||||
|
var cell = b.Location + new CVec(i % size, i / size + bibOffset);
|
||||||
|
var tile = new TileReference<byte, byte>((byte)(bib + 1), (byte) i);
|
||||||
|
dirty[b].Tiles.Add(cell, tile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Render( WorldRenderer wr )
|
public void TickRender(WorldRenderer wr, Actor self)
|
||||||
|
{
|
||||||
|
var remove = new List<Actor>();
|
||||||
|
foreach (var kv in dirty)
|
||||||
|
{
|
||||||
|
if (!info.FrozenUnderFog || kv.Value.Footprint.Any(c => !self.World.FogObscures(c)))
|
||||||
|
{
|
||||||
|
if (kv.Value.Visible)
|
||||||
|
visible[kv.Key] = kv.Value;
|
||||||
|
else
|
||||||
|
visible.Remove(kv.Key);
|
||||||
|
|
||||||
|
remove.Add(kv.Key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var r in remove)
|
||||||
|
dirty.Remove(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Render(WorldRenderer wr)
|
||||||
{
|
{
|
||||||
var pal = wr.Palette("terrain");
|
var pal = wr.Palette("terrain");
|
||||||
var cliprect = Game.viewport.WorldBounds(world);
|
var cliprect = Game.viewport.WorldBounds(world);
|
||||||
foreach (var kv in tiles)
|
|
||||||
{
|
|
||||||
if (!cliprect.Contains(kv.Key.X, kv.Key.Y))
|
|
||||||
continue;
|
|
||||||
if (world.ShroudObscures(kv.Key))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
bibSprites[kv.Value.type - 1][kv.Value.index].DrawAt(kv.Key.ToPPos().ToFloat2(), pal);
|
foreach (var bib in visible.Values)
|
||||||
|
{
|
||||||
|
foreach (var kv in bib.Tiles)
|
||||||
|
{
|
||||||
|
if (!cliprect.Contains(kv.Key.X, kv.Key.Y))
|
||||||
|
continue;
|
||||||
|
if (world.ShroudObscures(kv.Key))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var tile = bibSprites[kv.Value.type - 1][kv.Value.index];
|
||||||
|
tile.DrawAt(wr.ScreenPxPosition(kv.Key.CenterPosition) - 0.5f * tile.size, pal);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BibInfo : TraitInfo<Bib> { }
|
public class BibInfo : TraitInfo<Bib>, Requires<BuildingInfo> { }
|
||||||
public class Bib { }
|
public class Bib { }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,23 +17,30 @@ namespace OpenRA.Mods.RA.Effects
|
|||||||
{
|
{
|
||||||
public class Corpse : IEffect
|
public class Corpse : IEffect
|
||||||
{
|
{
|
||||||
readonly Animation Anim;
|
readonly World world;
|
||||||
readonly WPos Pos;
|
readonly WPos pos;
|
||||||
readonly string PaletteName;
|
readonly CPos cell;
|
||||||
|
readonly string paletteName;
|
||||||
|
readonly Animation anim;
|
||||||
|
|
||||||
public Corpse(World world, WPos pos, string image, string sequence, string paletteName)
|
public Corpse(World world, WPos pos, string image, string sequence, string paletteName)
|
||||||
{
|
{
|
||||||
Pos = pos;
|
this.world = world;
|
||||||
PaletteName = paletteName;
|
this.pos = pos;
|
||||||
Anim = new Animation(image);
|
this.cell = pos.ToCPos();
|
||||||
Anim.PlayThen(sequence, () => world.AddFrameEndTask(w => w.Remove(this)));
|
this.paletteName = paletteName;
|
||||||
|
anim = new Animation(image);
|
||||||
|
anim.PlayThen(sequence, () => world.AddFrameEndTask(w => w.Remove(this)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Tick(World world) { Anim.Tick(); }
|
public void Tick(World world) { anim.Tick(); }
|
||||||
|
|
||||||
public IEnumerable<IRenderable> Render(WorldRenderer wr)
|
public IEnumerable<IRenderable> Render(WorldRenderer wr)
|
||||||
{
|
{
|
||||||
return Anim.Render(Pos, wr.Palette(PaletteName));
|
if (world.FogObscures(cell))
|
||||||
|
return SpriteRenderable.None;
|
||||||
|
|
||||||
|
return anim.Render(pos, wr.Palette(paletteName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#region Copyright & License Information
|
#region Copyright & License Information
|
||||||
/*
|
/*
|
||||||
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
|
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
|
||||||
* This file is part of OpenRA, which is free software. It is made
|
* 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
|
* available to you under the terms of the GNU General Public License
|
||||||
* as published by the Free Software Foundation. For more information,
|
* as published by the Free Software Foundation. For more information,
|
||||||
@@ -23,18 +23,17 @@ namespace OpenRA.Mods.RA.Effects
|
|||||||
public CrateEffect(Actor a, string seq)
|
public CrateEffect(Actor a, string seq)
|
||||||
{
|
{
|
||||||
this.a = a;
|
this.a = a;
|
||||||
anim.PlayThen(seq,
|
anim.PlayThen(seq, () => a.World.AddFrameEndTask(w => w.Remove(this)));
|
||||||
() => a.World.AddFrameEndTask(w => w.Remove(this)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Tick( World world )
|
public void Tick(World world)
|
||||||
{
|
{
|
||||||
anim.Tick();
|
anim.Tick();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<IRenderable> Render(WorldRenderer wr)
|
public IEnumerable<IRenderable> Render(WorldRenderer wr)
|
||||||
{
|
{
|
||||||
if (!a.IsInWorld)
|
if (!a.IsInWorld || a.World.FogObscures(a.Location))
|
||||||
return SpriteRenderable.None;
|
return SpriteRenderable.None;
|
||||||
|
|
||||||
return anim.Render(a.CenterPosition, wr.Palette("effect"));
|
return anim.Render(a.CenterPosition, wr.Palette("effect"));
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#region Copyright & License Information
|
#region Copyright & License Information
|
||||||
/*
|
/*
|
||||||
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
|
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
|
||||||
* This file is part of OpenRA, which is free software. It is made
|
* 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
|
* available to you under the terms of the GNU General Public License
|
||||||
* as published by the Free Software Foundation. For more information,
|
* as published by the Free Software Foundation. For more information,
|
||||||
@@ -17,20 +17,27 @@ namespace OpenRA.Mods.RA.Effects
|
|||||||
{
|
{
|
||||||
public class Explosion : IEffect
|
public class Explosion : IEffect
|
||||||
{
|
{
|
||||||
Animation anim;
|
World world;
|
||||||
WPos pos;
|
WPos pos;
|
||||||
|
CPos cell;
|
||||||
|
Animation anim;
|
||||||
|
|
||||||
public Explosion(World world, WPos pos, string style)
|
public Explosion(World world, WPos pos, string style)
|
||||||
{
|
{
|
||||||
|
this.world = world;
|
||||||
this.pos = pos;
|
this.pos = pos;
|
||||||
|
this.cell = pos.ToCPos();
|
||||||
anim = new Animation("explosion");
|
anim = new Animation("explosion");
|
||||||
anim.PlayThen(style, () => world.AddFrameEndTask(w => w.Remove(this)));
|
anim.PlayThen(style, () => world.AddFrameEndTask(w => w.Remove(this)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Tick( World world ) { anim.Tick(); }
|
public void Tick(World world) { anim.Tick(); }
|
||||||
|
|
||||||
public IEnumerable<IRenderable> Render(WorldRenderer wr)
|
public IEnumerable<IRenderable> Render(WorldRenderer wr)
|
||||||
{
|
{
|
||||||
|
if (world.FogObscures(cell))
|
||||||
|
return SpriteRenderable.None;
|
||||||
|
|
||||||
return anim.Render(pos, wr.Palette("effect"));
|
return anim.Render(pos, wr.Palette("effect"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
53
OpenRA.Mods.RA/Effects/FrozenActorProxy.cs
Normal file
53
OpenRA.Mods.RA/Effects/FrozenActorProxy.cs
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007-2013 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.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRA.Effects;
|
||||||
|
using OpenRA.Graphics;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
|
||||||
|
namespace OpenRA.Mods.RA.Effects
|
||||||
|
{
|
||||||
|
public class FrozenActorProxy : IEffect
|
||||||
|
{
|
||||||
|
readonly Actor self;
|
||||||
|
readonly IEnumerable<CPos> footprint;
|
||||||
|
IRenderable[] renderables;
|
||||||
|
|
||||||
|
public FrozenActorProxy(Actor self, IEnumerable<CPos> footprint)
|
||||||
|
{
|
||||||
|
this.self = self;
|
||||||
|
this.footprint = footprint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Tick(World world) { }
|
||||||
|
public void SetRenderables(IEnumerable<IRenderable> r)
|
||||||
|
{
|
||||||
|
renderables = r.Select(rr => rr).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<IRenderable> Render(WorldRenderer wr)
|
||||||
|
{
|
||||||
|
if (renderables == null)
|
||||||
|
return SpriteRenderable.None;
|
||||||
|
|
||||||
|
if (footprint.Any(c => !wr.world.FogObscures(c)))
|
||||||
|
{
|
||||||
|
if (self.Destroyed)
|
||||||
|
self.World.AddFrameEndTask(w => w.Remove(this));
|
||||||
|
|
||||||
|
return SpriteRenderable.None;
|
||||||
|
}
|
||||||
|
|
||||||
|
return renderables;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -36,7 +36,7 @@ namespace OpenRA.Mods.RA.Effects
|
|||||||
|
|
||||||
public IEnumerable<IRenderable> Render(WorldRenderer wr)
|
public IEnumerable<IRenderable> Render(WorldRenderer wr)
|
||||||
{
|
{
|
||||||
if (a.Destroyed || a.Owner.IsAlliedWith(a.World.RenderPlayer))
|
if (a.Destroyed || wr.world.FogObscures(a))
|
||||||
return SpriteRenderable.None;
|
return SpriteRenderable.None;
|
||||||
|
|
||||||
return anim.Render(a.CenterPosition, wr.Palette("chrome"));
|
return anim.Render(a.CenterPosition, wr.Palette("chrome"));
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ namespace OpenRA.Mods.RA.Effects
|
|||||||
|
|
||||||
public IEnumerable<IRenderable> Render(WorldRenderer wr)
|
public IEnumerable<IRenderable> Render(WorldRenderer wr)
|
||||||
{
|
{
|
||||||
if (building.Destroyed)
|
if (building.Destroyed || wr.world.FogObscures(building))
|
||||||
return SpriteRenderable.None;
|
return SpriteRenderable.None;
|
||||||
|
|
||||||
return anim.Render(building.CenterPosition,
|
return anim.Render(building.CenterPosition,
|
||||||
|
|||||||
@@ -17,25 +17,29 @@ namespace OpenRA.Mods.RA.Effects
|
|||||||
{
|
{
|
||||||
public class Smoke : IEffect
|
public class Smoke : IEffect
|
||||||
{
|
{
|
||||||
readonly WPos Pos;
|
readonly World world;
|
||||||
readonly Animation Anim;
|
readonly WPos pos;
|
||||||
|
readonly CPos cell;
|
||||||
|
readonly Animation anim;
|
||||||
|
|
||||||
public Smoke(World world, WPos pos, string trail)
|
public Smoke(World world, WPos pos, string trail)
|
||||||
{
|
{
|
||||||
Pos = pos;
|
this.world = world;
|
||||||
Anim = new Animation(trail);
|
this.pos = pos;
|
||||||
Anim.PlayThen("idle",
|
this.cell = pos.ToCPos();
|
||||||
|
anim = new Animation(trail);
|
||||||
|
anim.PlayThen("idle",
|
||||||
() => world.AddFrameEndTask(w => w.Remove(this)));
|
() => world.AddFrameEndTask(w => w.Remove(this)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Tick(World world)
|
public void Tick(World world) { anim.Tick(); }
|
||||||
{
|
|
||||||
Anim.Tick();
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<IRenderable> Render(WorldRenderer wr)
|
public IEnumerable<IRenderable> Render(WorldRenderer wr)
|
||||||
{
|
{
|
||||||
return Anim.Render(Pos, wr.Palette("effect"));
|
if (world.FogObscures(cell))
|
||||||
|
return SpriteRenderable.None;
|
||||||
|
|
||||||
|
return anim.Render(pos, wr.Palette("effect"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -433,7 +433,7 @@ namespace OpenRA.Mods.RA
|
|||||||
if (!self.Owner.Shroud.IsExplored(location))
|
if (!self.Owner.Shroud.IsExplored(location))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var res = self.World.WorldActor.Trait<ResourceLayer>().GetResource(location);
|
var res = self.World.WorldActor.Trait<ResourceLayer>().GetRenderedResource(location);
|
||||||
var info = self.Info.Traits.Get<HarvesterInfo>();
|
var info = self.Info.Traits.Get<HarvesterInfo>();
|
||||||
|
|
||||||
if (res == null || !info.Resources.Contains(res.info.Name))
|
if (res == null || !info.Resources.Contains(res.info.Name))
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#region Copyright & License Information
|
#region Copyright & License Information
|
||||||
/*
|
/*
|
||||||
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
|
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
|
||||||
* This file is part of OpenRA, which is free software. It is made
|
* 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
|
* available to you under the terms of the GNU General Public License
|
||||||
* as published by the Free Software Foundation. For more information,
|
* as published by the Free Software Foundation. For more information,
|
||||||
@@ -11,25 +11,48 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using OpenRA.Graphics;
|
using OpenRA.Graphics;
|
||||||
|
using OpenRA.Mods.RA.Buildings;
|
||||||
|
using OpenRA.Mods.RA.Effects;
|
||||||
using OpenRA.Traits;
|
using OpenRA.Traits;
|
||||||
|
|
||||||
namespace OpenRA.Mods.RA
|
namespace OpenRA.Mods.RA
|
||||||
{
|
{
|
||||||
class FrozenUnderFogInfo : TraitInfo<FrozenUnderFog> {}
|
public class FrozenUnderFogInfo : ITraitInfo, Requires<BuildingInfo>, Requires<RenderSpritesInfo>
|
||||||
|
|
||||||
class FrozenUnderFog : IRenderModifier, IVisibilityModifier
|
|
||||||
{
|
{
|
||||||
public bool IsVisible(Actor self, Player byPlayer)
|
public object Create(ActorInitializer init) { return new FrozenUnderFog(init.self); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class FrozenUnderFog : IRenderModifier, IVisibilityModifier, ITickRender
|
||||||
|
{
|
||||||
|
FrozenActorProxy proxy;
|
||||||
|
IEnumerable<CPos> footprint;
|
||||||
|
bool visible;
|
||||||
|
|
||||||
|
public FrozenUnderFog(Actor self)
|
||||||
{
|
{
|
||||||
return byPlayer == null || Shroud.GetVisOrigins(self).Any(o => byPlayer.Shroud.IsVisible(o));
|
footprint = FootprintUtils.Tiles(self);
|
||||||
|
proxy = new FrozenActorProxy(self, footprint);
|
||||||
|
self.World.AddFrameEndTask(w => w.Add(proxy));
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsVisible(Actor self, Player byPlayer)
|
||||||
|
{
|
||||||
|
return byPlayer == null || footprint.Any(c => byPlayer.Shroud.IsVisible(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TickRender(WorldRenderer wr, Actor self)
|
||||||
|
{
|
||||||
|
if (self.Destroyed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
visible = IsVisible(self, self.World.RenderPlayer);
|
||||||
|
if (visible)
|
||||||
|
proxy.SetRenderables(self.Render(wr));
|
||||||
}
|
}
|
||||||
|
|
||||||
IRenderable[] cache = { };
|
|
||||||
public IEnumerable<IRenderable> ModifyRender(Actor self, WorldRenderer wr, IEnumerable<IRenderable> r)
|
public IEnumerable<IRenderable> ModifyRender(Actor self, WorldRenderer wr, IEnumerable<IRenderable> r)
|
||||||
{
|
{
|
||||||
if (IsVisible(self, self.World.RenderPlayer))
|
return visible ? r : SpriteRenderable.None;
|
||||||
cache = r.ToArray();
|
|
||||||
return cache;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#region Copyright & License Information
|
#region Copyright & License Information
|
||||||
/*
|
/*
|
||||||
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
|
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
|
||||||
* This file is part of OpenRA, which is free software. It is made
|
* 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
|
* available to you under the terms of the GNU General Public License
|
||||||
* as published by the Free Software Foundation. For more information,
|
* as published by the Free Software Foundation. For more information,
|
||||||
@@ -15,19 +15,18 @@ using OpenRA.Traits;
|
|||||||
|
|
||||||
namespace OpenRA.Mods.RA
|
namespace OpenRA.Mods.RA
|
||||||
{
|
{
|
||||||
class HiddenUnderFogInfo : TraitInfo<HiddenUnderFog> {}
|
public class HiddenUnderFogInfo : TraitInfo<HiddenUnderFog> { }
|
||||||
|
|
||||||
class HiddenUnderFog : IRenderModifier, IVisibilityModifier
|
public class HiddenUnderFog : IRenderModifier, IVisibilityModifier
|
||||||
{
|
{
|
||||||
public bool IsVisible(Actor self, Player byPlayer)
|
public bool IsVisible(Actor self, Player byPlayer)
|
||||||
{
|
{
|
||||||
return byPlayer == null || Shroud.GetVisOrigins(self).Any(o => byPlayer.Shroud.IsVisible(o));
|
return byPlayer == null || Shroud.GetVisOrigins(self).Any(o => byPlayer.Shroud.IsVisible(o));
|
||||||
}
|
}
|
||||||
|
|
||||||
static IRenderable[] Nothing = { };
|
|
||||||
public IEnumerable<IRenderable> ModifyRender(Actor self, WorldRenderer wr, IEnumerable<IRenderable> r)
|
public IEnumerable<IRenderable> ModifyRender(Actor self, WorldRenderer wr, IEnumerable<IRenderable> r)
|
||||||
{
|
{
|
||||||
return IsVisible(self, self.World.RenderPlayer) ? r : Nothing;
|
return IsVisible(self, self.World.RenderPlayer) ? r : SpriteRenderable.None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -461,6 +461,7 @@
|
|||||||
<Compile Include="World\DomainIndex.cs" />
|
<Compile Include="World\DomainIndex.cs" />
|
||||||
<Compile Include="MPStartUnits.cs" />
|
<Compile Include="MPStartUnits.cs" />
|
||||||
<Compile Include="Orders\SetChronoTankDestination.cs" />
|
<Compile Include="Orders\SetChronoTankDestination.cs" />
|
||||||
|
<Compile Include="Effects\FrozenActorProxy.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\OpenRA.FileFormats\OpenRA.FileFormats.csproj">
|
<ProjectReference Include="..\OpenRA.FileFormats\OpenRA.FileFormats.csproj">
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#region Copyright & License Information
|
#region Copyright & License Information
|
||||||
/*
|
/*
|
||||||
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
|
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
|
||||||
* This file is part of OpenRA, which is free software. It is made
|
* 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
|
* available to you under the terms of the GNU General Public License
|
||||||
* as published by the Free Software Foundation. For more information,
|
* as published by the Free Software Foundation. For more information,
|
||||||
@@ -14,25 +14,26 @@ using System.Drawing;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using OpenRA.FileFormats;
|
using OpenRA.FileFormats;
|
||||||
using OpenRA.Graphics;
|
using OpenRA.Graphics;
|
||||||
using OpenRA.Traits;
|
|
||||||
using OpenRA.Mods.RA.Effects;
|
using OpenRA.Mods.RA.Effects;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
|
||||||
namespace OpenRA.Mods.RA
|
namespace OpenRA.Mods.RA
|
||||||
{
|
{
|
||||||
public class SmudgeLayerInfo : ITraitInfo
|
public class SmudgeLayerInfo : ITraitInfo
|
||||||
{
|
{
|
||||||
public readonly string Type = "Scorch";
|
public readonly string Type = "Scorch";
|
||||||
public readonly string[] Types = {"sc1", "sc2", "sc3", "sc4", "sc5", "sc6"};
|
public readonly string[] Types = { "sc1", "sc2", "sc3", "sc4", "sc5", "sc6" };
|
||||||
public readonly int[] Depths = {1,1,1,1,1,1};
|
public readonly int[] Depths = { 1, 1, 1, 1, 1, 1 };
|
||||||
public readonly int SmokePercentage = 25;
|
public readonly int SmokePercentage = 25;
|
||||||
public readonly string SmokeType = "smoke_m";
|
public readonly string SmokeType = "smoke_m";
|
||||||
public object Create(ActorInitializer init) { return new SmudgeLayer(this); }
|
public object Create(ActorInitializer init) { return new SmudgeLayer(this); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SmudgeLayer: IRenderOverlay, IWorldLoaded
|
public class SmudgeLayer : IRenderOverlay, IWorldLoaded, ITickRender
|
||||||
{
|
{
|
||||||
public SmudgeLayerInfo Info;
|
public SmudgeLayerInfo Info;
|
||||||
Dictionary<CPos, TileReference<byte, byte>> tiles;
|
Dictionary<CPos, TileReference<byte, byte>> tiles;
|
||||||
|
Dictionary<CPos, TileReference<byte, byte>> dirty;
|
||||||
Sprite[][] smudgeSprites;
|
Sprite[][] smudgeSprites;
|
||||||
World world;
|
World world;
|
||||||
|
|
||||||
@@ -46,49 +47,66 @@ namespace OpenRA.Mods.RA
|
|||||||
{
|
{
|
||||||
world = w;
|
world = w;
|
||||||
tiles = new Dictionary<CPos, TileReference<byte, byte>>();
|
tiles = new Dictionary<CPos, TileReference<byte, byte>>();
|
||||||
|
dirty = new Dictionary<CPos, TileReference<byte, byte>>();
|
||||||
|
|
||||||
// Add map smudges
|
// Add map smudges
|
||||||
foreach (var s in w.Map.Smudges.Value.Where( s => Info.Types.Contains(s.Type )))
|
foreach (var s in w.Map.Smudges.Value.Where(s => Info.Types.Contains(s.Type)))
|
||||||
tiles.Add((CPos)s.Location, new TileReference<byte, byte>((byte)Array.IndexOf(Info.Types, s.Type), (byte)s.Depth));
|
tiles.Add((CPos)s.Location, new TileReference<byte, byte>((byte)Array.IndexOf(Info.Types, s.Type), (byte)s.Depth));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddSmudge(CPos loc)
|
public void AddSmudge(CPos loc)
|
||||||
{
|
{
|
||||||
if (Game.CosmeticRandom.Next(0,100) <= Info.SmokePercentage)
|
if (Game.CosmeticRandom.Next(0, 100) <= Info.SmokePercentage)
|
||||||
world.AddFrameEndTask(w => w.Add(new Smoke(w, loc.CenterPosition, Info.SmokeType)));
|
world.AddFrameEndTask(w => w.Add(new Smoke(w, loc.CenterPosition, Info.SmokeType)));
|
||||||
|
|
||||||
// No smudge; create a new one
|
if (!dirty.ContainsKey(loc) && !tiles.ContainsKey(loc))
|
||||||
if (!tiles.ContainsKey(loc))
|
|
||||||
{
|
{
|
||||||
byte st = (byte)(1 + world.SharedRandom.Next(Info.Types.Length - 1));
|
// No smudge; create a new one
|
||||||
tiles.Add(loc, new TileReference<byte,byte>(st,(byte)0));
|
var st = (byte)(1 + world.SharedRandom.Next(Info.Types.Length - 1));
|
||||||
return;
|
dirty[loc] = new TileReference<byte, byte>(st, (byte)0);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
var tile = tiles[loc];
|
|
||||||
// Existing smudge; make it deeper
|
|
||||||
int depth = Info.Depths[tile.type-1];
|
|
||||||
if (tile.index < depth - 1)
|
|
||||||
{
|
{
|
||||||
tile.index++;
|
// Existing smudge; make it deeper
|
||||||
tiles[loc] = tile; // struct semantics.
|
var tile = dirty.ContainsKey(loc) ? dirty[loc] : tiles[loc];
|
||||||
|
var depth = Info.Depths[tile.type - 1];
|
||||||
|
if (tile.index < depth - 1)
|
||||||
|
tile.index++;
|
||||||
|
|
||||||
|
dirty[loc] = tile;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Render( WorldRenderer wr )
|
public void TickRender(WorldRenderer wr, Actor self)
|
||||||
|
{
|
||||||
|
var remove = new List<CPos>();
|
||||||
|
foreach (var kv in dirty)
|
||||||
|
{
|
||||||
|
if (!self.World.FogObscures(kv.Key))
|
||||||
|
{
|
||||||
|
tiles[kv.Key] = kv.Value;
|
||||||
|
remove.Add(kv.Key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var r in remove)
|
||||||
|
dirty.Remove(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Render(WorldRenderer wr)
|
||||||
{
|
{
|
||||||
var cliprect = Game.viewport.WorldBounds(world);
|
var cliprect = Game.viewport.WorldBounds(world);
|
||||||
var pal = wr.Palette("terrain");
|
var pal = wr.Palette("terrain");
|
||||||
|
|
||||||
foreach (var kv in tiles)
|
foreach (var kv in tiles)
|
||||||
{
|
{
|
||||||
if (!cliprect.Contains(kv.Key.X,kv.Key.Y))
|
if (!cliprect.Contains(kv.Key.X, kv.Key.Y))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (world.ShroudObscures(kv.Key))
|
if (world.ShroudObscures(kv.Key))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
smudgeSprites[kv.Value.type- 1][kv.Value.index].DrawAt(kv.Key.ToPPos().ToFloat2(), pal);
|
smudgeSprites[kv.Value.type - 1][kv.Value.index].DrawAt(kv.Key.ToPPos().ToFloat2(), pal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -317,12 +317,14 @@
|
|||||||
Guardable:
|
Guardable:
|
||||||
Range: 3
|
Range: 3
|
||||||
BodyOrientation:
|
BodyOrientation:
|
||||||
|
FrozenUnderFog:
|
||||||
|
|
||||||
^CivBuilding:
|
^CivBuilding:
|
||||||
Inherits: ^Building
|
Inherits: ^Building
|
||||||
-DeadBuildingState:
|
-DeadBuildingState:
|
||||||
-Buildable:
|
-Buildable:
|
||||||
-GivesBuildableArea:
|
-GivesBuildableArea:
|
||||||
|
-FrozenUnderFog:
|
||||||
Health:
|
Health:
|
||||||
HP: 400
|
HP: 400
|
||||||
Armor:
|
Armor:
|
||||||
|
|||||||
@@ -273,6 +273,7 @@ World:
|
|||||||
ProductionQueueFromSelection:
|
ProductionQueueFromSelection:
|
||||||
ProductionTabsWidget: PRODUCTION_TABS
|
ProductionTabsWidget: PRODUCTION_TABS
|
||||||
BibLayer:
|
BibLayer:
|
||||||
|
FrozenUnderFog: true
|
||||||
DomainIndex:
|
DomainIndex:
|
||||||
ResourceLayer:
|
ResourceLayer:
|
||||||
ResourceClaimLayer:
|
ResourceClaimLayer:
|
||||||
|
|||||||
@@ -354,6 +354,7 @@ World:
|
|||||||
BibLayer:
|
BibLayer:
|
||||||
BibTypes: bib3x, bib2x
|
BibTypes: bib3x, bib2x
|
||||||
BibWidths: 3, 2
|
BibWidths: 3, 2
|
||||||
|
FrozenUnderFog: true
|
||||||
DomainIndex:
|
DomainIndex:
|
||||||
ResourceLayer:
|
ResourceLayer:
|
||||||
ResourceClaimLayer:
|
ResourceClaimLayer:
|
||||||
|
|||||||
@@ -222,7 +222,6 @@
|
|||||||
ActorTypes: e1,e1,e1,e1,e1,e1,e1,e1,e1,e1,e1,e1,e1,e1,e1,c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,e6,e6,e6,e6,e6
|
ActorTypes: e1,e1,e1,e1,e1,e1,e1,e1,e1,e1,e1,e1,e1,e1,e1,c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,e6,e6,e6,e6,e6
|
||||||
MustBeDestroyed:
|
MustBeDestroyed:
|
||||||
GivesExperience:
|
GivesExperience:
|
||||||
# FrozenUnderFog:
|
|
||||||
CaptureNotification:
|
CaptureNotification:
|
||||||
EditorAppearance:
|
EditorAppearance:
|
||||||
RelativeToTopLeft: yes
|
RelativeToTopLeft: yes
|
||||||
@@ -237,6 +236,7 @@
|
|||||||
Guardable:
|
Guardable:
|
||||||
Range: 3
|
Range: 3
|
||||||
BodyOrientation:
|
BodyOrientation:
|
||||||
|
FrozenUnderFog:
|
||||||
|
|
||||||
^Wall:
|
^Wall:
|
||||||
AppearsOnRadar:
|
AppearsOnRadar:
|
||||||
|
|||||||
@@ -604,6 +604,7 @@ World:
|
|||||||
Name: Soviet
|
Name: Soviet
|
||||||
Race: soviet
|
Race: soviet
|
||||||
BibLayer:
|
BibLayer:
|
||||||
|
FrozenUnderFog: true
|
||||||
DomainIndex:
|
DomainIndex:
|
||||||
ResourceLayer:
|
ResourceLayer:
|
||||||
ResourceClaimLayer:
|
ResourceClaimLayer:
|
||||||
|
|||||||
Reference in New Issue
Block a user