Introduce World.LocalShroud. Breaks targeting stealth tanks. Probably breaks FrozenUnderFog.

This commit is contained in:
Paul Chote
2010-11-26 16:56:33 +13:00
parent 41fd19c766
commit 7c5c989eb2
25 changed files with 88 additions and 161 deletions

View File

@@ -140,7 +140,7 @@ namespace OpenRA.Graphics
foreach (var t in world.Queries.WithTraitMultiple<IRadarSignature>())
{
if (!t.Actor.IsVisible(player))
if (!world.LocalShroud.IsVisible(t.Actor))
continue;
var color = t.Trait.RadarSignatureColor(t.Actor);
@@ -159,7 +159,7 @@ namespace OpenRA.Graphics
var map = world.Map;
var size = Util.NextPowerOf2(Math.Max(map.Bounds.Width, map.Bounds.Height));
Bitmap bitmap = new Bitmap(size, size);
if (world.LocalPlayer == null || world.LocalPlayer.Shroud == null)
if (world.LocalShroud.Disabled)
return bitmap;
var bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
@@ -167,8 +167,6 @@ namespace OpenRA.Graphics
var shroud = Color.Black.ToArgb();
var fog = Color.FromArgb(128, Color.Black).ToArgb();
var playerShroud = world.LocalPlayer.Shroud;
unsafe
{
@@ -179,9 +177,9 @@ namespace OpenRA.Graphics
{
var mapX = x + map.Bounds.Left;
var mapY = y + map.Bounds.Top;
if (!playerShroud.IsExplored(mapX, mapY))
if (!world.LocalShroud.IsExplored(mapX, mapY))
*(c + (y * bitmapData.Stride >> 2) + x) = shroud;
else if (!playerShroud.IsVisible(mapX,mapY))
else if (!world.LocalShroud.IsVisible(mapX,mapY))
*(c + (y * bitmapData.Stride >> 2) + x) = fog;
}
}

View File

@@ -79,9 +79,9 @@ namespace OpenRA.Graphics
if (firstRow < 0) firstRow = 0;
if (lastRow > map.Bounds.Height) lastRow = map.Bounds.Height;
if (world.LocalPlayer != null && !world.LocalPlayer.Shroud.Disabled && world.LocalPlayer.Shroud.Bounds.HasValue)
if (world.LocalPlayer != null && !world.LocalShroud.Disabled && world.LocalShroud.Bounds.HasValue)
{
var r = world.LocalPlayer.Shroud.Bounds.Value;
var r = world.LocalShroud.Bounds.Value;
if (firstRow < r.Top - map.Bounds.Top)
firstRow = r.Top - map.Bounds.Top;

View File

@@ -125,11 +125,9 @@ namespace OpenRA.Graphics
public Rectangle ShroudBounds( World world )
{
var localPlayer = world.LocalPlayer;
if( localPlayer == null ) return world.Map.Bounds;
if( localPlayer.Shroud.Disabled ) return world.Map.Bounds;
if( !localPlayer.Shroud.Bounds.HasValue ) return world.Map.Bounds;
return Rectangle.Intersect( localPlayer.Shroud.Bounds.Value, world.Map.Bounds );
if( world.LocalShroud.Disabled || !world.LocalShroud.Bounds.HasValue )
return world.Map.Bounds;
return Rectangle.Intersect( world.LocalShroud.Bounds.Value, world.Map.Bounds );
}
public Rectangle ViewBounds()

View File

@@ -31,7 +31,7 @@ namespace OpenRA.Graphics
this.world = world;
terrainRenderer = new TerrainRenderer(world, this);
shroudRenderer = new ShroudRenderer(world.WorldActor.Trait<Shroud>(), world.Map);
shroudRenderer = new ShroudRenderer(world);
uiOverlay = new UiOverlay();
palette = new HardwarePalette(world.Map);
@@ -53,9 +53,8 @@ namespace OpenRA.Graphics
Rectangle GetBoundsRect()
{
var r = (world.LocalPlayer != null && !world.LocalPlayer.Shroud.Disabled && world.LocalPlayer.Shroud.Bounds.HasValue)?
world.LocalPlayer.Shroud.Bounds.Value : world.Map.Bounds;
r.Intersect(world.Map.Bounds);
var r = (!world.LocalShroud.Disabled && world.LocalShroud.Bounds.HasValue)?
Rectangle.Intersect(world.LocalShroud.Bounds.Value,world.Map.Bounds) : world.Map.Bounds;
var left = (int)(Game.CellSize * r.Left - Game.viewport.Location.X);
var top = (int)(Game.CellSize * r.Top - Game.viewport.Location.Y);
@@ -135,20 +134,6 @@ namespace OpenRA.Graphics
Game.Renderer.LineRenderer.DrawLine(a, a + c, color, color);
}
void DrawBins(RectangleF bounds)
{
DrawBox(bounds, Color.Red);
if (world.LocalPlayer != null)
DrawBox(world.LocalPlayer.Shroud.Bounds.Value, Color.Blue);
for (var j = 0; j < world.Map.MapSize.Y;
j += world.WorldActor.Info.Traits.Get<SpatialBinsInfo>().BinSize)
{
Game.Renderer.LineRenderer.DrawLine(new float2(0, j * Game.CellSize), new float2(world.Map.MapSize.X * Game.CellSize, j * Game.CellSize), Color.Black, Color.Black);
Game.Renderer.LineRenderer.DrawLine(new float2(j * Game.CellSize, 0), new float2(j * Game.CellSize, world.Map.MapSize.Y * Game.CellSize), Color.Black, Color.Black);
}
}
public void DrawSelectionBox(Actor selectedUnit, Color c)
{
var bounds = selectedUnit.GetBounds(true);

View File

@@ -40,7 +40,7 @@ namespace OpenRA
public readonly PlayerReference PlayerRef;
public bool IsBot;
public Shroud Shroud { get { return World.WorldActor.Trait<Shroud>(); }}
public Shroud Shroud { get { return World.LocalShroud; }}
public World World { get; private set; }
public Player(World world, PlayerReference pr, int index)

View File

@@ -23,26 +23,16 @@ namespace OpenRA
bool dirty = true;
Map map;
public ShroudRenderer(Traits.Shroud shroud, Map map)
public ShroudRenderer(World world)
{
this.shroud = shroud;
this.map = map;
this.shroud = world.LocalShroud;
this.map = world.Map;
sprites = new Sprite[map.MapSize.X, map.MapSize.Y];
fogSprites = new Sprite[map.MapSize.X, map.MapSize.Y];
shroud.Dirty += () => dirty = true;
}
public bool IsExplored(int x, int y)
{
return (shroud == null) ? true : shroud.IsExplored(x,y);
}
public bool IsVisible(int x, int y)
{
return (shroud == null) ? true : shroud.IsVisible(x,y);
}
static readonly byte[][] SpecialShroudTiles =
{
new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
@@ -65,49 +55,49 @@ namespace OpenRA
Sprite ChooseShroud(int i, int j)
{
if( !IsExplored( i, j ) ) return shadowBits[ 0xf ];
if( !shroud.IsExplored( i, j ) ) return shadowBits[ 0xf ];
// bits are for unexploredness: up, right, down, left
var v = 0;
// bits are for unexploredness: TL, TR, BR, BL
var u = 0;
if( !IsExplored( i, j - 1 ) ) { v |= 1; u |= 3; }
if( !IsExplored( i + 1, j ) ) { v |= 2; u |= 6; }
if( !IsExplored( i, j + 1 ) ) { v |= 4; u |= 12; }
if( !IsExplored( i - 1, j ) ) { v |= 8; u |= 9; }
if( !shroud.IsExplored( i, j - 1 ) ) { v |= 1; u |= 3; }
if( !shroud.IsExplored( i + 1, j ) ) { v |= 2; u |= 6; }
if( !shroud.IsExplored( i, j + 1 ) ) { v |= 4; u |= 12; }
if( !shroud.IsExplored( i - 1, j ) ) { v |= 8; u |= 9; }
var uSides = u;
if( !IsExplored( i - 1, j - 1 ) ) u |= 1;
if( !IsExplored( i + 1, j - 1 ) ) u |= 2;
if( !IsExplored( i + 1, j + 1 ) ) u |= 4;
if( !IsExplored( i - 1, j + 1 ) ) u |= 8;
if( !shroud.IsExplored( i - 1, j - 1 ) ) u |= 1;
if( !shroud.IsExplored( i + 1, j - 1 ) ) u |= 2;
if( !shroud.IsExplored( i + 1, j + 1 ) ) u |= 4;
if( !shroud.IsExplored( i - 1, j + 1 ) ) u |= 8;
return shadowBits[ SpecialShroudTiles[ u ^ uSides ][ v ] ];
}
Sprite ChooseFog(int i, int j)
{
if (!IsVisible(i,j)) return shadowBits[0xf];
if (!IsExplored(i, j)) return shadowBits[0xf];
if (!shroud.IsVisible(i,j)) return shadowBits[0xf];
if (!shroud.IsExplored(i, j)) return shadowBits[0xf];
// bits are for unexploredness: up, right, down, left
var v = 0;
// bits are for unexploredness: TL, TR, BR, BL
var u = 0;
if (!IsVisible(i, j - 1)) { v |= 1; u |= 3; }
if (!IsVisible(i + 1, j)) { v |= 2; u |= 6; }
if (!IsVisible(i, j + 1)) { v |= 4; u |= 12; }
if (!IsVisible(i - 1, j)) { v |= 8; u |= 9; }
if (!shroud.IsVisible(i, j - 1)) { v |= 1; u |= 3; }
if (!shroud.IsVisible(i + 1, j)) { v |= 2; u |= 6; }
if (!shroud.IsVisible(i, j + 1)) { v |= 4; u |= 12; }
if (!shroud.IsVisible(i - 1, j)) { v |= 8; u |= 9; }
var uSides = u;
if (!IsVisible(i - 1, j - 1)) u |= 1;
if (!IsVisible(i + 1, j - 1)) u |= 2;
if (!IsVisible(i + 1, j + 1)) u |= 4;
if (!IsVisible(i - 1, j + 1)) u |= 8;
if (!shroud.IsVisible(i - 1, j - 1)) u |= 1;
if (!shroud.IsVisible(i + 1, j - 1)) u |= 2;
if (!shroud.IsVisible(i + 1, j + 1)) u |= 4;
if (!shroud.IsVisible(i - 1, j + 1)) u |= 8;
return shadowBits[SpecialShroudTiles[u ^ uSides][v]];
}

View File

@@ -77,7 +77,7 @@ namespace OpenRA.Traits
{
DisableShroud ^= true;
if (self.World.LocalPlayer == self.Owner)
self.World.LocalPlayer.Shroud.Disabled = DisableShroud;
self.World.LocalShroud.Disabled = DisableShroud;
break;
}
case "DevPathDebug":

View File

@@ -73,7 +73,7 @@ namespace OpenRA.Traits
Color RadarSignatureColor(Actor self);
}
public interface IVisibilityModifier { bool IsVisible(Actor self, Player byPlayer); }
public interface IVisibilityModifier { bool IsVisible(Actor self); }
public interface IRadarColorModifier { Color RadarColorOverride(Actor self); }
public interface IHasLocation
{

View File

@@ -38,15 +38,11 @@ namespace OpenRA.Traits
foreach( var rt in world.WorldActor.TraitsImplementing<ResourceType>() )
rt.info.PaletteIndex = wr.GetPaletteIndex(rt.info.Palette);
Shroud shroud = null;
if( world.LocalPlayer != null )
shroud = world.LocalPlayer.Shroud;
for (int x = minx; x < maxx; x++)
for (int y = miny; y < maxy; y++)
{
if (shroud != null && !shroud.IsExplored(new int2(x, y)))
continue;
if (!world.LocalShroud.IsExplored(new int2(x, y)))
continue;
var c = content[x, y];
if (c.image != null)

View File

@@ -213,6 +213,14 @@ namespace OpenRA.Traits
return visibleCells[x,y] != 0;
}
// Actors are hidden under shroud, but not under fog by default
public bool IsVisible(Actor a)
{
if (a.TraitsImplementing<IVisibilityModifier>().Any(t => !t.IsVisible(a)))
return false;
return disabled || a.Owner == a.World.LocalPlayer || GetVisOrigins(a).Any(o => IsExplored(o));
}
}
}

View File

@@ -149,7 +149,7 @@ namespace OpenRA.Widgets
IEnumerable<Actor> SelectActorsInBox(World world, float2 a, float2 b)
{
return world.FindUnits(a, b)
.Where( x => x.HasTrait<Selectable>() && x.IsVisible(world.LocalPlayer) )
.Where( x => x.HasTrait<Selectable>() && world.LocalShroud.IsVisible(x) )
.GroupBy(x => (x.Owner == world.LocalPlayer) ? x.Info.Traits.Get<SelectableInfo>().Priority : 0)
.OrderByDescending(g => g.Key)
.Select( g => g.AsEnumerable() )

View File

@@ -44,6 +44,7 @@ namespace OpenRA
{
get { return players.ContainsKey(localPlayerIndex) ? players[localPlayerIndex] : null; }
}
public readonly Shroud LocalShroud;
public void SetLocalPlayer(int index)
{
@@ -51,7 +52,6 @@ namespace OpenRA
}
public readonly Actor WorldActor;
public readonly Map Map;
public readonly TileSet TileSet;
@@ -98,6 +98,8 @@ namespace OpenRA
SharedRandom = new XRandom(orderManager.LobbyInfo.GlobalSettings.RandomSeed);
WorldActor = CreateActor( "World", new TypeDictionary() );
LocalShroud = WorldActor.Trait<Shroud>();
Queries = new AllQueries(this);
// Add players

View File

@@ -24,7 +24,7 @@ namespace OpenRA
public static IEnumerable<Actor> FindUnitsAtMouse(this World world, int2 mouseLocation)
{
var loc = mouseLocation + Game.viewport.Location;
return FindUnits(world, loc, loc).Where(a => a.IsVisible(world.LocalPlayer));
return FindUnits(world, loc, loc).Where(a => world.LocalShroud.IsVisible(a));
}
public static IEnumerable<Actor> FindUnits(this World world, float2 a, float2 b)
@@ -72,22 +72,6 @@ namespace OpenRA
return world.TileSet.Terrain[world.GetTerrainType(cell)];
}
public static bool IsVisible(this Actor a, Player byPlayer) /* must never be relied on in synced code! */
{
if (byPlayer == null) return true; // Observer
if (a.World.LocalPlayer != null && a.World.LocalPlayer.Shroud.Disabled)
return true;
var shroud = a.World.WorldActor.Trait<Shroud>();
if (!Shroud.GetVisOrigins(a).Any(o => a.World.Map.IsInMap(o) && shroud.exploredCells[o.X, o.Y])) // covered by shroud
return false;
if (a.TraitsImplementing<IVisibilityModifier>().Any(t => !t.IsVisible(a, byPlayer)))
return false;
return true;
}
public static int2 ClampToWorld( this World world, int2 xy )
{
return xy.Clamp(world.Map.Bounds);

View File

@@ -214,7 +214,6 @@ namespace OpenRA.Mods.RA
return inRange
.Where(a => a.Owner != null && self.Owner.Stances[a.Owner] == Stance.Enemy)
.Where(a => HasAnyValidWeapons(Target.FromActor(a)))
.Where(a => !a.HasTrait<Cloak>() || a.Trait<Cloak>().IsVisible(a, self.Owner))
.OrderBy(a => (a.CenterLocation - self.CenterLocation).LengthSquared)
.FirstOrDefault();
}

View File

@@ -80,7 +80,7 @@ namespace OpenRA.Mods.RA.Buildings
{
if (!cliprect.Contains(kv.Key.X, kv.Key.Y))
continue;
if (world.LocalPlayer != null && !world.LocalPlayer.Shroud.IsExplored(kv.Key))
if (!world.LocalShroud.IsExplored(kv.Key))
continue;
bibSprites[kv.Value.type - 1][kv.Value.image].DrawAt( wr,

View File

@@ -40,12 +40,13 @@ namespace OpenRA.Mods.RA
}
}
// Can't be used in synced code
public virtual bool CanChronoshiftTo(Actor self, int2 targetLocation)
{
// Todo: Allow enemy units to be chronoshifted into bad terrain to kill them
return self.HasTrait<ITeleportable>() &&
self.Trait<ITeleportable>().CanEnterCell(targetLocation) &&
(self.World.LocalPlayer == null || self.World.LocalPlayer.Shroud.IsExplored(targetLocation));
(self.World.LocalShroud.IsExplored(targetLocation));
}
public virtual bool Teleport(Actor self, int2 targetLocation, int duration, bool killCargo, Actor chronosphere)

View File

@@ -76,7 +76,7 @@ namespace OpenRA.Mods.RA
if (remainingTime > 0)
return rs;
if (Cloaked && IsVisible(self, self.World.LocalPlayer))
if (Cloaked && IsVisible(self))
return rs.Select(a => a.WithPalette("shadow"));
else
return new Renderable[] { };
@@ -101,14 +101,6 @@ namespace OpenRA.Mods.RA
public bool Cloaked { get { return remainingTime == 0; } }
public bool IsVisible(Actor self, Player byPlayer)
{
if (!Cloaked || self.Owner.Stances[byPlayer] == Stance.Ally)
return true;
return self.World.Queries.WithTrait<DetectCloaked>().Any(a => a.Actor.Owner == byPlayer && (self.Location - a.Actor.Location).Length < a.Actor.Info.Traits.Get<DetectCloakedInfo>().Range);
}
public bool IsVisible(Actor self)
{
return !Cloaked || self.Owner == self.World.LocalPlayer;

View File

@@ -49,8 +49,8 @@ namespace OpenRA.Mods.RA
foreach (var a in self.World.Queries.OwnedBy[self.Owner])
a.Kill(a);
self.Owner.Shroud.Disabled = true;
if (self.Owner == self.World.LocalPlayer)
self.World.LocalShroud.Disabled = true;
}
public void Win(Actor self)
@@ -59,7 +59,8 @@ namespace OpenRA.Mods.RA
self.Owner.WinState = WinState.Won;
Game.Debug("{0} is victorious.".F(self.Owner.PlayerName));
self.Owner.Shroud.Disabled = true;
if (self.Owner == self.World.LocalPlayer)
self.World.LocalShroud.Disabled = true;
}
}

View File

@@ -73,19 +73,13 @@ namespace OpenRA.Mods.RA
Color trailEnd = Color.FromArgb(trailStart.A - 255 / TrailLength, trailStart.R,
trailStart.G, trailStart.B);
// LocalPlayer is null on shellmap
Shroud shroud = null;
if (self.World.LocalPlayer != null)
shroud = self.World.LocalPlayer.Shroud;
for (int i = positions.Count - 1; i >= 1; --i)
{
var conPos = positions[i];
var nextPos = positions[i - 1];
if (shroud == null ||
shroud.IsVisible(OpenRA.Traits.Util.CellContaining(conPos)) ||
shroud.IsVisible(OpenRA.Traits.Util.CellContaining(nextPos)))
if (self.World.LocalShroud.IsVisible(OpenRA.Traits.Util.CellContaining(conPos)) ||
self.World.LocalShroud.IsVisible(OpenRA.Traits.Util.CellContaining(nextPos)))
{
Game.Renderer.LineRenderer.DrawLine(conPos, nextPos, trailStart, trailEnd);

View File

@@ -209,7 +209,7 @@ namespace OpenRA.Mods.RA
public bool CanTargetLocation(Actor self, int2 location, List<Actor> actorsAtLocation, bool forceAttack, bool forceMove, bool forceQueued, ref string cursor)
{
// Don't leak info about resources under the shroud
if (!self.World.LocalPlayer.Shroud.IsExplored(location)) return false;
if (!self.World.LocalShroud.IsExplored(location)) return false;
var res = self.World.WorldActor.Trait<ResourceLayer>().GetResource( location );
var info = self.Info.Traits.Get<HarvesterInfo>();

View File

@@ -18,9 +18,9 @@ namespace OpenRA.Mods.RA
class InvisibleToOthers : IRenderModifier, IVisibilityModifier, IRadarColorModifier
{
public bool IsVisible(Actor self, Player byPlayer)
public bool IsVisible(Actor self)
{
return self.Owner == byPlayer;
return self.World.LocalPlayer == null || self.Owner == self.World.LocalPlayer;
}
public Color RadarColorOverride(Actor self)

View File

@@ -14,34 +14,15 @@ using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
class FrozenUnderFogInfo : ITraitInfo
class FrozenUnderFogInfo : TraitInfo<FrozenUnderFog> {}
class FrozenUnderFog : IRenderModifier
{
public object Create(ActorInitializer init) { return new FrozenUnderFog(init.self); }
}
class FrozenUnderFog : IRenderModifier, IVisibilityModifier
{
Shroud shroud;
Renderable[] cache = { };
public FrozenUnderFog(Actor self)
{
shroud = self.World.WorldActor.Trait<Shroud>();
}
public bool IsVisible(Actor self, Player byPlayer)
{
return self.World.LocalPlayer == null
|| self.Owner == byPlayer
|| self.World.LocalPlayer.Shroud.Disabled
|| Shroud.GetVisOrigins(self).Any(o => self.World.Map.IsInMap(o) && shroud.visibleCells[o.X, o.Y] != 0);
}
Renderable[] cache = { };
public IEnumerable<Renderable> ModifyRender(Actor self, IEnumerable<Renderable> r)
{
if (IsVisible(self, self.World.LocalPlayer))
if (self.World.LocalShroud.IsVisible(self))
cache = r.ToArray();
return cache;
}
}

View File

@@ -9,36 +9,24 @@
#endregion
using System.Collections.Generic;
using System.Linq;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
class HiddenUnderFogInfo : ITraitInfo
{
public object Create(ActorInitializer init) { return new HiddenUnderFog(init.self); }
}
class HiddenUnderFogInfo : TraitInfo<HiddenUnderFog> {}
class HiddenUnderFog : IRenderModifier, IVisibilityModifier
{
Shroud shroud;
public HiddenUnderFog(Actor self)
public bool IsVisible(Actor self)
{
shroud = self.World.WorldActor.Trait<Shroud>();
}
public bool IsVisible(Actor self, Player byPlayer)
{
return self.World.LocalPlayer == null
|| self.Owner == byPlayer
|| self.World.LocalPlayer.Shroud.Disabled
|| shroud.visibleCells[self.Location.X, self.Location.Y] > 0;
return Shroud.GetVisOrigins(self).Any(o => self.World.LocalShroud.IsVisible(o));
}
static Renderable[] Nothing = { };
public IEnumerable<Renderable> ModifyRender(Actor self, IEnumerable<Renderable> r)
{
return IsVisible(self, self.World.LocalPlayer) ? r : Nothing;
return IsVisible(self) ? r : Nothing;
}
}
}

View File

@@ -7,7 +7,8 @@
* see LICENSE.
*/
#endregion
using System.Linq;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
@@ -32,5 +33,14 @@ namespace OpenRA.Mods.RA
get { return (Cloak.Cloaked) ? info.CloakedTargetTypes
: info.TargetTypes;}
}
// Todo: Finish me
public bool TargetableBy(Actor self, Actor byActor)
{
if (!Cloak.Cloaked || self.Owner == byActor.Owner || self.Owner.Stances[byActor.Owner] == Stance.Ally)
return true;
return self.World.Queries.WithTrait<DetectCloaked>().Any(a => (self.Location - a.Actor.Location).Length < a.Actor.Info.Traits.Get<DetectCloakedInfo>().Range);
}
}
}

View File

@@ -50,7 +50,7 @@ namespace OpenRA.Mods.RA.Widgets
}
var actor = world.FindUnitsAtMouse(Viewport.LastMousePos).FirstOrDefault();
if (actor == null || !actor.IsVisible(world.LocalPlayer))
if (actor == null)
return;
var text = actor.Info.Traits.Contains<TooltipInfo>()